diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cube.rs | 522 | ||||
-rw-r--r-- | src/main.rs | 170 |
2 files changed, 638 insertions, 54 deletions
diff --git a/src/cube.rs b/src/cube.rs new file mode 100644 index 0000000..d81eb76 --- /dev/null +++ b/src/cube.rs @@ -0,0 +1,522 @@ +use engine::math::calc_triangle_surface_normal; +use engine::object::Builder as ObjectBuilder; +use engine::vector::Vec3; +use engine::vertex::{Builder as VertexBuilder, Vertex}; + +pub enum Side +{ + Front, + Back, + Left, + Right, + Top, + Bottom, +} + +pub enum Corner +{ + TopRight, + TopLeft, + BottomRight, + BottomLeft, +} + +pub fn create_cube( + vertex_builder_cb: impl Fn(VertexBuilder, Side, Corner) -> VertexBuilder, +) -> ObjectBuilder +{ + let mut vertices: [Option<Vertex>; VertexIndex::VARIANT_CNT] = + [(); VertexIndex::VARIANT_CNT].map(|()| None); + + let front_top_right_pos = Vec3 { x: 0.5, y: 0.5, z: -0.5 }; + let front_bottom_right_pos = Vec3 { x: 0.5, y: -0.5, z: -0.5 }; + let front_bottom_left_pos = Vec3 { x: -0.5, y: -0.5, z: -0.5 }; + let front_top_left_pos = Vec3 { x: -0.5, y: 0.5, z: -0.5 }; + + let front_normal = calc_triangle_surface_normal( + &front_top_right_pos, + &front_bottom_right_pos, + &front_top_left_pos, + ); + + vertices[VertexIndex::FrontTopRight as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(front_top_right_pos) + .normal(front_normal.clone()), + Side::Front, + Corner::TopRight, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::FrontBottomRight as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(front_bottom_right_pos) + .normal(front_normal.clone()), + Side::Front, + Corner::BottomRight, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::FrontBottomLeft as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(front_bottom_left_pos) + .normal(front_normal.clone()), + Side::Front, + Corner::BottomLeft, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::FrontTopLeft as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(front_top_left_pos) + .normal(front_normal.clone()), + Side::Front, + Corner::TopLeft, + ) + .build() + .unwrap(), + ); + + let back_top_right_pos = Vec3 { x: 0.5, y: 0.5, z: 0.5 }; + let back_bottom_right_pos = Vec3 { x: 0.5, y: -0.5, z: 0.5 }; + let back_bottom_left_pos = Vec3 { x: -0.5, y: -0.5, z: 0.5 }; + let back_top_left_pos = Vec3 { x: -0.5, y: 0.5, z: 0.5 }; + + let back_normal = -calc_triangle_surface_normal( + &back_top_right_pos, + &back_bottom_right_pos, + &back_top_left_pos, + ); + + vertices[VertexIndex::BackTopRight as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(back_top_right_pos) + .normal(back_normal.clone()), + Side::Back, + Corner::TopRight, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::BackBottomRight as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(back_bottom_right_pos) + .normal(back_normal.clone()), + Side::Back, + Corner::BottomRight, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::BackBottomLeft as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(back_bottom_left_pos) + .normal(back_normal.clone()), + Side::Back, + Corner::BottomLeft, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::BackTopLeft as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(back_top_left_pos) + .normal(back_normal), + Side::Back, + Corner::TopLeft, + ) + .build() + .unwrap(), + ); + + let right_back_top_pos = Vec3 { x: 0.5, y: 0.5, z: 0.5 }; + let right_back_bottom_pos = Vec3 { x: 0.5, y: -0.5, z: 0.5 }; + let right_front_top_pos = Vec3 { x: 0.5, y: 0.5, z: -0.5 }; + let right_front_bottom_pos = Vec3 { x: 0.5, y: -0.5, z: -0.5 }; + + let right_normal = calc_triangle_surface_normal( + &right_back_top_pos, + &right_back_bottom_pos, + &right_front_top_pos, + ); + + vertices[VertexIndex::RightBackTop as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(right_back_top_pos) + .normal(right_normal.clone()), + Side::Right, + Corner::TopLeft, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::RightBackBottom as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(right_back_bottom_pos) + .normal(right_normal.clone()), + Side::Right, + Corner::BottomLeft, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::RightFrontTop as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(right_front_top_pos) + .normal(right_normal.clone()), + Side::Right, + Corner::TopRight, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::RightFrontBottom as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(right_front_bottom_pos) + .normal(right_normal), + Side::Right, + Corner::BottomRight, + ) + .build() + .unwrap(), + ); + + let left_back_top_pos = Vec3 { x: -0.5, y: 0.5, z: 0.5 }; + let left_back_bottom_pos = Vec3 { x: -0.5, y: -0.5, z: 0.5 }; + let left_front_top_pos = Vec3 { x: -0.5, y: 0.5, z: -0.5 }; + let left_front_bottom_pos = Vec3 { x: -0.5, y: -0.5, z: -0.5 }; + + let left_normal = -calc_triangle_surface_normal( + &left_back_top_pos, + &left_back_bottom_pos, + &left_front_top_pos, + ); + + vertices[VertexIndex::LeftBackTop as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(left_back_top_pos) + .normal(left_normal.clone()), + Side::Left, + Corner::TopRight, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::LeftBackBottom as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(left_back_bottom_pos) + .normal(left_normal.clone()), + Side::Left, + Corner::BottomRight, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::LeftFrontTop as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(left_front_top_pos) + .normal(left_normal.clone()), + Side::Left, + Corner::TopLeft, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::LeftFrontBottom as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(left_front_bottom_pos) + .normal(left_normal), + Side::Left, + Corner::BottomLeft, + ) + .build() + .unwrap(), + ); + + let top_back_right_pos = Vec3 { x: 0.5, y: 0.5, z: 0.5 }; + let top_back_left_pos = Vec3 { x: -0.5, y: 0.5, z: 0.5 }; + let top_front_left_pos = Vec3 { x: -0.5, y: 0.5, z: -0.5 }; + let top_front_right_pos = Vec3 { x: 0.5, y: 0.5, z: -0.5 }; + + let top_normal = -calc_triangle_surface_normal( + &top_back_right_pos, + &top_back_left_pos, + &top_front_right_pos, + ); + + vertices[VertexIndex::TopBackRight as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(top_back_right_pos) + .normal(top_normal.clone()), + Side::Top, + Corner::TopRight, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::TopBackLeft as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(top_back_left_pos) + .normal(top_normal.clone()), + Side::Top, + Corner::TopLeft, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::TopFrontLeft as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(top_front_left_pos) + .normal(top_normal.clone()), + Side::Top, + Corner::BottomLeft, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::TopFrontRight as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(top_front_right_pos) + .normal(top_normal), + Side::Top, + Corner::BottomRight, + ) + .build() + .unwrap(), + ); + + let bottom_back_right_pos = Vec3 { x: 0.5, y: -0.5, z: 0.5 }; + let bottom_back_left_pos = Vec3 { x: -0.5, y: -0.5, z: 0.5 }; + let bottom_front_right_pos = Vec3 { x: 0.5, y: -0.5, z: -0.5 }; + let bottom_front_left_pos = Vec3 { x: -0.5, y: -0.5, z: -0.5 }; + + let bottom_normal = calc_triangle_surface_normal( + &bottom_back_right_pos, + &bottom_back_left_pos, + &bottom_front_right_pos, + ); + + vertices[VertexIndex::BottomBackRight as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(bottom_back_right_pos) + .normal(bottom_normal.clone()), + Side::Bottom, + Corner::BottomRight, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::BottomBackLeft as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(bottom_back_left_pos) + .normal(bottom_normal.clone()), + Side::Bottom, + Corner::BottomLeft, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::BottomFrontRight as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(bottom_front_right_pos) + .normal(bottom_normal.clone()), + Side::Bottom, + Corner::TopRight, + ) + .build() + .unwrap(), + ); + + vertices[VertexIndex::BottomFrontLeft as usize] = Some( + vertex_builder_cb( + VertexBuilder::new() + .pos(bottom_front_left_pos) + .normal(bottom_normal), + Side::Bottom, + Corner::TopLeft, + ) + .build() + .unwrap(), + ); + + let front = [ + // 🮝 + VertexIndex::FrontTopRight, + VertexIndex::FrontBottomRight, + VertexIndex::FrontTopLeft, + // + // 🮟 + VertexIndex::FrontBottomRight, + VertexIndex::FrontBottomLeft, + VertexIndex::FrontTopLeft, + ]; + + let back = [ + // 🮝 + VertexIndex::BackTopRight, + VertexIndex::BackBottomRight, + VertexIndex::BackTopLeft, + // + // 🮟 + VertexIndex::BackBottomRight, + VertexIndex::BackBottomLeft, + VertexIndex::BackTopLeft, + ]; + + let right = [ + // 🮝 + VertexIndex::RightBackTop, + VertexIndex::RightBackBottom, + VertexIndex::RightFrontTop, + // + // 🮟 + VertexIndex::RightBackBottom, + VertexIndex::RightFrontBottom, + VertexIndex::RightFrontTop, + ]; + + let left = [ + // 🮝 + VertexIndex::LeftBackTop, + VertexIndex::LeftBackBottom, + VertexIndex::LeftFrontTop, + // + // 🮟 + VertexIndex::LeftBackBottom, + VertexIndex::LeftFrontBottom, + VertexIndex::LeftFrontTop, + ]; + + let top = [ + // 🮝 + VertexIndex::TopBackRight, + VertexIndex::TopBackLeft, + VertexIndex::TopFrontRight, + // + // 🮟 + VertexIndex::TopBackLeft, + VertexIndex::TopFrontLeft, + VertexIndex::TopFrontRight, + ]; + + let bottom = [ + // 🮝 + VertexIndex::BottomBackRight, + VertexIndex::BottomBackLeft, + VertexIndex::BottomFrontRight, + // + // 🮟 + VertexIndex::BottomBackLeft, + VertexIndex::BottomFrontLeft, + VertexIndex::BottomFrontRight, + ]; + + let indices = [front, back, right, left, top, bottom]; + + ObjectBuilder::new() + .vertices(vertices.map(Option::unwrap)) + .indices(indices.into_iter().flatten().map(|index| index as u32)) +} + +macro_rules! one { + ($tt: tt) => { + 1 + }; +} + +macro_rules! enum_with_variant_cnt { + ( + $(#[$attr: meta])* + enum $name: ident { + $($variant: ident,)* + } + ) => { + $(#[$attr])* + enum $name { + $($variant,)* + } + + impl $name { + const VARIANT_CNT: usize = 0 $(+ one!($variant))*; + } + }; +} + +enum_with_variant_cnt! { +#[repr(u32)] +enum VertexIndex +{ + FrontTopRight, + FrontBottomRight, + FrontBottomLeft, + FrontTopLeft, + + BackTopRight, + BackBottomRight, + BackBottomLeft, + BackTopLeft, + + RightBackTop, + RightBackBottom, + RightFrontTop, + RightFrontBottom, + + LeftBackTop, + LeftBackBottom, + LeftFrontTop, + LeftFrontBottom, + + TopBackRight, + TopBackLeft, + TopFrontRight, + TopFrontLeft, + + BottomBackRight, + BottomBackLeft, + BottomFrontRight, + BottomFrontLeft, +} +} diff --git a/src/main.rs b/src/main.rs index f594c7c..9171b35 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,27 @@ use std::error::Error; +use std::path::Path; use engine::color::Color; -use engine::object::{Builder as ObjectBuilder, Id as ObjectId}; -use engine::vector::Vec3; -use engine::vertex::Builder as VertexBuilder; +use engine::lighting::{LightSettings, LightSourceBuilder}; +use engine::object::Id as ObjectId; +use engine::texture::Texture; +use engine::vector::{Vec2, Vec3}; use engine::{Engine, Key, WindowSize}; use tracing::Level; use tracing_subscriber::FmtSubscriber; +use crate::cube::{create_cube, Corner as CubeCorner, Side as CubeSide}; + +mod cube; + const WINDOW_SIZE: WindowSize = WindowSize { width: 500, height: 600 }; const BLUE: Color<f32> = Color { red: 0.0, blue: 1.0, green: 0.0 }; +const RED: Color<f32> = Color { red: 1.0, green: 0.0, blue: 0.0 }; +const GREEN: Color<f32> = Color { red: 0.0, green: 1.0, blue: 0.0 }; +const ORANGE: Color<f32> = Color { red: 1.0, green: 0.5, blue: 0.0 }; +const PURPLE: Color<f32> = Color { red: 0.5, green: 0.0, blue: 1.0 }; +const CYAN: Color<f32> = Color { red: 0.0, green: 1.0, blue: 1.0 }; fn main() -> Result<(), Box<dyn Error>> { @@ -22,60 +33,53 @@ fn main() -> Result<(), Box<dyn Error>> let mut engine = Engine::new(&WINDOW_SIZE, "Yaaay lmao")?; - let mut triangle = ObjectBuilder::new() - .vertices([ - VertexBuilder::new() - .pos(Vec3 { x: -0.5, y: -0.5, z: 0.0 }) - .color(Color { red: 1.0, green: 0.0, blue: 0.0 }) - .build() - .unwrap(), - VertexBuilder::new() - .pos(Vec3 { x: 0.5, y: -0.5, z: 0.0 }) - .color(Color { red: 0.0, green: 1.0, blue: 0.0 }) - .build() - .unwrap(), - VertexBuilder::new() - .pos(Vec3 { x: 0.0, y: 0.5, z: 0.0 }) - .color(Color { red: 0.0, green: 0.0, blue: 1.0 }) - .build() - .unwrap(), - ]) - .build(ObjectId::new(1))?; - - triangle.translate(Vec3 { x: 0.0, y: 0.4, z: 0.0 }); - - engine.add_object(triangle); - - let square = ObjectBuilder::new() - .vertices([ - VertexBuilder::new() - .pos(Vec3 { x: 0.5, y: 0.5, z: 0.0 }) - .color(BLUE) - .build() - .unwrap(), - VertexBuilder::new() - .pos(Vec3 { x: 0.5, y: -0.5, z: 0.0 }) - .color(BLUE) - .build() - .unwrap(), - VertexBuilder::new() - .pos(Vec3 { x: -0.5, y: -0.5, z: 0.0 }) - .color(BLUE) - .build() - .unwrap(), - VertexBuilder::new() - .pos(Vec3 { x: -0.5, y: 0.5, z: 0.0 }) - .color(BLUE) - .build() - .unwrap(), - ]) - .indices([0, 1, 3, 1, 2, 3]) - .build(ObjectId::new(2))?; - - engine.add_object(square); + engine.set_light_settings(LightSettings { + ambient_light_strength: 0.1, + specular_light_strength: 0.5, + specular_shininess: 32, + }); + + let cube = create_cube(|vertex_builder, side, _| { + vertex_builder.color(match side { + CubeSide::Top => BLUE, + CubeSide::Back => RED, + CubeSide::Left => PURPLE, + CubeSide::Front => ORANGE, + CubeSide::Right => GREEN, + CubeSide::Bottom => CYAN, + }) + }) + .build(ObjectId::new(3))?; + + engine.add_object(cube); + + let texture = Texture::open(Path::new("vent.png"))?; + + let mut textured_cube = create_cube(|vertex_builder, _, corner| { + vertex_builder.texture_coords(match corner { + CubeCorner::TopRight => Vec2 { x: 1.0, y: 1.0 }, + CubeCorner::TopLeft => Vec2 { x: 0.0, y: 1.0 }, + CubeCorner::BottomRight => Vec2 { x: 1.0, y: 0.0 }, + CubeCorner::BottomLeft => Vec2 { x: 0.0, y: 0.0 }, + }) + }) + .texture(texture) + .build(ObjectId::new(4))?; + + textured_cube.translate(Vec3 { x: 1.6, y: 0.0, z: 0.0 }); + + engine.add_object(textured_cube); + + let light_source = LightSourceBuilder::new() + .position(Vec3 { x: 1.2, y: 1.0, z: 1.5 }) + .build(); + + engine.set_light_source(light_source); let cam_speed = 3.0; + let light_source_speed = 1.2; + engine.start(|engine| { let delta_time = *engine.delta_time(); @@ -113,6 +117,64 @@ fn main() -> Result<(), Box<dyn Error>> *engine.camera_mut().position_mut() += cam_right * cam_speed_dist_adj * delta_time.as_secs_f32(); } + if engine.is_key_pressed(Key::K).unwrap() { + let cam_up = engine.camera().up().clone(); + + // Camera speed adjusted to be same no matter how far the distance is to the + // camera target + let cam_speed_dist_adj = cam_speed + * (engine.camera().position() - engine.camera().target()).length(); + + *engine.camera_mut().position_mut() += + cam_up * cam_speed_dist_adj * delta_time.as_secs_f32(); + } + if engine.is_key_pressed(Key::J).unwrap() { + let cam_up = engine.camera().down().clone(); + + // Camera speed adjusted to be same no matter how far the distance is to the + // camera target + let cam_speed_dist_adj = cam_speed + * (engine.camera().position() - engine.camera().target()).length(); + + *engine.camera_mut().position_mut() += + cam_up * cam_speed_dist_adj * delta_time.as_secs_f32(); + } + + if engine.is_key_pressed(Key::O).unwrap() { + let light_source = engine.light_source_mut().unwrap(); + + let front_right = Vec3 { x: 1.0, y: 0.0, z: 1.0 }; + + light_source + .translate(front_right * light_source_speed * delta_time.as_secs_f32()); + } + + if engine.is_key_pressed(Key::L).unwrap() { + let light_source = engine.light_source_mut().unwrap(); + + let back_left = Vec3 { x: -1.0, y: 0.0, z: -1.0 }; + + light_source + .translate(back_left * light_source_speed * delta_time.as_secs_f32()); + } + + if engine.is_key_pressed(Key::KpAdd).unwrap() { + let light_settings = engine.light_settings().unwrap().clone(); + + engine.set_light_settings(LightSettings { + ambient_light_strength: light_settings.ambient_light_strength + 0.2, + ..light_settings + }) + } + + if engine.is_key_pressed(Key::KpSubtract).unwrap() { + let light_settings = engine.light_settings().unwrap().clone(); + + engine.set_light_settings(LightSettings { + ambient_light_strength: light_settings.ambient_light_strength - 0.2, + ..light_settings + }) + } })?; Ok(()) |