summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: a982dbb6e1d8dfdc3c21afe4b1bf6c97b18bfef1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::error::Error;
use std::fs::read_to_string;
use std::path::Path;

use engine::camera::fly::{
    Extension as FlyCameraExtension,
    Fly as FlyCamera,
    Options as FlyCameraOptions,
};
use engine::camera::{Active as ActiveCamera, Camera};
use engine::color::Color;
use engine::data_types::dimens::Dimens;
use engine::ecs::phase::START as START_PHASE;
use engine::ecs::sole::Single;
use engine::file_format::wavefront::mtl::parse as parse_mtl;
use engine::file_format::wavefront::obj::parse as parse_obj;
use engine::input::Extension as InputExtension;
use engine::lighting::{AttenuationParams, GlobalLight, PointLight};
use engine::material::{Builder as MaterialBuilder, Flags as MaterialFlags};
use engine::renderer::opengl::Extension as OpenglRendererExtension;
use engine::transform::Position;
use engine::vector::Vec3;
use engine::window::{
    Builder as WindowBuilder,
    CursorMode,
    Extension as WindowExtension,
    Window,
};
use engine::Engine;
use tracing::Level;
use tracing_subscriber::FmtSubscriber;

const WINDOW_SIZE: Dimens<u32> = Dimens { width: 1920, height: 1080 };

const YELLOW: Color<f32> = Color {
    red: 0.988235294118,
    green: 0.941176470588,
    blue: 0.0274509803922,
};

const RESOURCE_DIR: &str = "res";

fn main() -> Result<(), Box<dyn Error>>
{
    let subscriber = FmtSubscriber::builder()
        .with_max_level(Level::TRACE)
        .finish();

    tracing::subscriber::set_global_default(subscriber)?;

    let mut engine = Engine::new();

    let teapot_obj =
        parse_obj(&read_to_string(Path::new(RESOURCE_DIR).join("teapot.obj"))?)?;

    let teapot_mat_name = teapot_obj
        .faces
        .first()
        .and_then(|face| face.material_name.as_ref());

    let teapot_mats = teapot_obj.read_and_parse_material_libs(parse_mtl)?;

    let teapot_mat = teapot_mats
        .into_iter()
        .find(|mat| Some(&mat.name) == teapot_mat_name)
        .ok_or("Teapot material was not found")?;

    engine.spawn((
        teapot_obj.to_mesh()?,
        teapot_mat.material,
        Position::from(Vec3 { x: 1.6, y: 0.0, z: 0.0 }),
    ));

    engine.spawn((
        PointLight::builder()
            .position(Vec3 { x: -6.0, y: 3.0, z: 3.0 })
            .diffuse(YELLOW)
            .attenuation_params(AttenuationParams {
                linear: 0.045,
                quadratic: 0.0075,
                ..Default::default()
            })
            .build(),
        Position::from(Vec3 { x: -6.0, y: 3.0, z: 3.0 }),
        parse_obj(&read_to_string(Path::new(RESOURCE_DIR).join("cube.obj"))?)?
            .to_mesh()?,
        MaterialBuilder::new().ambient(YELLOW * 5.0).build(),
        MaterialFlags::builder().use_ambient_color(true).build(),
    ));

    engine.spawn((
        Camera::default(),
        Position {
            position: Vec3 { x: 0.0, y: 0.0, z: 3.0 },
        },
        ActiveCamera,
        FlyCamera::default(),
    ));

    engine.add_sole(GlobalLight::default())?;

    engine.register_system(*START_PHASE, prepare_window);

    engine.add_extension(OpenglRendererExtension::default());

    engine.add_extension(
        WindowExtension::new(WindowBuilder::default().multisampling_sample_count(8))
            .window_title("Game")
            .window_size(WINDOW_SIZE),
    );

    engine.add_extension(FlyCameraExtension(FlyCameraOptions {
        mouse_sensitivity: 0.2,
    }));

    engine.add_extension(InputExtension::default());

    engine.start();

    Ok(())
}

fn prepare_window(window: Single<Window>)
{
    window.set_cursor_mode(CursorMode::Disabled).unwrap();
}