From 139f7d92cc0ff68525011811b67ca0ed3bc82d90 Mon Sep 17 00:00:00 2001 From: hodasemi Date: Tue, 9 May 2023 16:39:53 +0200 Subject: [PATCH] Base objects --- src/board.rs | 468 +++++++++++++++++++++++++++++++++++++++---------- src/game.rs | 190 ++++++++++++++++++-- src/main.rs | 4 + src/objects.rs | 235 +++++++++++++++++++++++++ 4 files changed, 795 insertions(+), 102 deletions(-) create mode 100644 src/objects.rs diff --git a/src/board.rs b/src/board.rs index 3aa4698..edb2b25 100644 --- a/src/board.rs +++ b/src/board.rs @@ -2,16 +2,114 @@ use std::sync::Arc; use anyhow::Result; use engine::prelude::{ - cgmath::{vec3, Vector3}, + cgmath::{vec2, vec3, Vector2, Vector3}, *, }; +use crate::{game::MillGame, objects::Objects}; + +#[derive(Debug, PartialEq, Clone, Copy)] +pub struct BoardSlot { + pub state: BoardSlotState, + pub position: Vector2, + pub slot_marker: Option, +} + +impl BoardSlot { + pub const SLOT_MARKER_SIZE: f32 = 1.5; + + pub fn new(position: Vector2, scene: &mut Scene) -> Result { + let mut marker = scene.engine().assets().empty_entity(); + + let meshes = vec![Self::create_mesh(&scene.engine(), Color::Black)?]; + + let draw = Draw::new(meshes); + marker.insert_component(draw); + + let mut location = Location::from_entity(&mut marker); + location.set_position(position.extend(MillGame::OFFSET_TO_BOARD)); + marker.insert_component(location); + + Ok(Self { + state: BoardSlotState::default(), + position, + slot_marker: Some(scene.add_entity(marker)?), + }) + } + + pub fn invalid() -> Self { + Self { + state: BoardSlotState::Invalid, + position: vec2(0.0, 0.0), + slot_marker: None, + } + } + + fn create_mesh(engine: &Arc, color: Color) -> Result { + let mut mesh = AssetMesh::new( + engine.device(), + engine.settings().graphics_info()?.render_type, + )?; + + let vertex_buffer = Buffer::builder() + .set_data(&Objects::create_flat_quad([ + vec2(-Self::SLOT_MARKER_SIZE * 0.5, -Self::SLOT_MARKER_SIZE * 0.5), + vec2(Self::SLOT_MARKER_SIZE * 0.5, -Self::SLOT_MARKER_SIZE * 0.5), + vec2(Self::SLOT_MARKER_SIZE * 0.5, Self::SLOT_MARKER_SIZE * 0.5), + vec2(-Self::SLOT_MARKER_SIZE * 0.5, Self::SLOT_MARKER_SIZE * 0.5), + ])) + .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) + .set_memory_usage(MemoryUsage::CpuOnly) + .build(engine.device().clone())?; + + let a: [f32; 3] = color.into(); + + mesh.add_primitive( + vertex_buffer, + None, + None, + PrimitiveMaterial { + color: [a[0], a[1], a[2], 1.0], + metallic_factor: 0.2, + emissive_factor: [0.2, 0.2, 0.2], + roughness_factor: 0.8, + alpha_mode: AlphaMode::Opaque, + alpha_cut_off: 0.5, + }, + true, + )?; + + Ok(mesh) + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum BoardSlotState { + Invalid, + Empty, + Black(Entity), + White(Entity), +} + +impl Default for BoardSlotState { + fn default() -> Self { + Self::Empty + } +} + pub struct Board { board: Entity, + center: Vector3, + + connection_lines: Vec, + + slots: [[[BoardSlot; 3]; 3]; 3], + white_start_slots: [Vector2; 9], + black_start_slots: [Vector2; 9], } impl Board { - pub fn new(engine: Arc, scene: &mut SceneHandle) -> Result> { + pub fn new(engine: &Arc, scene: &mut SceneHandle) -> Result> { let mut board_entity = engine.assets().empty_entity(); let meshes = vec![Self::create_board_base(&engine)?]; @@ -23,17 +121,138 @@ impl Board { board_entity.insert_component(location); let mut board = None; + let mut slots = None; + scene.on_scene(|scene| { board = Some(scene.add_entity(board_entity)?); + slots = Some([ + [ + [ + BoardSlot::new(vec2(-15.0, -15.0), scene)?, // 0 0 0 + BoardSlot::new(vec2(-10.0, -10.0), scene)?, // 0 0 1 + BoardSlot::new(vec2(-5.0, -5.0), scene)?, // 0 0 2 + ], + [ + BoardSlot::new(vec2(-15.0, 0.0), scene)?, // 0 1 0 + BoardSlot::new(vec2(-10.0, 0.0), scene)?, // 0 1 1 + BoardSlot::new(vec2(-5.0, 0.0), scene)?, // 0 1 2 + ], + [ + BoardSlot::new(vec2(-15.0, 15.0), scene)?, // 0 2 0 + BoardSlot::new(vec2(-10.0, 10.0), scene)?, // 0 2 1 + BoardSlot::new(vec2(-5.0, 5.0), scene)?, // 0 2 2 + ], + ], + [ + [ + BoardSlot::new(vec2(0.0, -15.0), scene)?, // 1 0 0 + BoardSlot::new(vec2(0.0, -10.0), scene)?, // 1 0 1 + BoardSlot::new(vec2(0.0, -5.0), scene)?, // 1 0 2 + ], + [ + BoardSlot::invalid(), // 1 1 0 + BoardSlot::invalid(), // 1 1 1 + BoardSlot::invalid(), // 1 1 2 + ], + [ + BoardSlot::new(vec2(0.0, 15.0), scene)?, // 1 2 0 + BoardSlot::new(vec2(0.0, 10.0), scene)?, // 1 2 1 + BoardSlot::new(vec2(0.0, 5.0), scene)?, // 1 2 2 + ], + ], + [ + [ + BoardSlot::new(vec2(15.0, -15.0), scene)?, // 2 0 0 + BoardSlot::new(vec2(10.0, -10.0), scene)?, // 2 0 1 + BoardSlot::new(vec2(5.0, -5.0), scene)?, // 2 0 2 + ], + [ + BoardSlot::new(vec2(15.0, 0.0), scene)?, // 2 1 0 + BoardSlot::new(vec2(10.0, 0.0), scene)?, // 2 1 1 + BoardSlot::new(vec2(5.0, 0.0), scene)?, // 2 1 2 + ], + [ + BoardSlot::new(vec2(15.0, 15.0), scene)?, // 2 2 0 + BoardSlot::new(vec2(10.0, 10.0), scene)?, // 2 2 1 + BoardSlot::new(vec2(5.0, 5.0), scene)?, // 2 2 2 + ], + ], + ]); + Ok(()) })?; + let distance = 20.0; + + let white_start_slots = [ + vec2(-16.0, distance), + vec2(-12.0, distance), + vec2(-8.0, distance), + vec2(-4.0, distance), + vec2(0.0, distance), + vec2(4.0, distance), + vec2(8.0, distance), + vec2(12.0, distance), + vec2(16.0, distance), + ]; + + let black_start_slots = [ + vec2(-16.0, -distance), + vec2(-12.0, -distance), + vec2(-8.0, -distance), + vec2(-4.0, -distance), + vec2(0.0, -distance), + vec2(4.0, -distance), + vec2(8.0, -distance), + vec2(12.0, -distance), + vec2(16.0, -distance), + ]; + Ok(Arc::new(Self { board: board.unwrap(), + center: vec3(0.0, 0.0, 0.0), + + connection_lines: Self::create_connection_lines(scene, Color::Black)?, + + slots: slots.unwrap(), + white_start_slots, + black_start_slots, })) } + pub fn center(&self) -> Vector3 { + self.center + } + + pub fn white_start_slots(&self) -> &[Vector2; 9] { + &self.white_start_slots + } + + pub fn black_start_slots(&self) -> &[Vector2; 9] { + &self.black_start_slots + } + + pub fn close_to_marker(&self, position: Vector2) -> bool { + const DISTANCE: f32 = 1.25; + + for outer in self.slots.iter() { + for inner in outer.iter() { + for slot in inner.iter() { + if slot.state != BoardSlotState::Invalid { + if (slot.position - position).magnitude() <= DISTANCE { + return true; + } + } + } + } + } + + false + } +} + +impl Board { fn create_board_base(engine: &Arc) -> Result { let mut board_base = AssetMesh::new( engine.device(), @@ -41,9 +260,9 @@ impl Board { )?; let vertex_buffer = Buffer::builder() - .set_data(&Self::create_cuboid( - vec3(-17.5, -20.0, -2.0), - vec3(35.0, 40.0, 2.0), + .set_data(&Objects::create_cuboid( + vec3(-22.5, -25.0, -2.0), + vec3(45.0, 50.0, 2.0), )) .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) .set_memory_usage(MemoryUsage::CpuOnly) @@ -59,7 +278,7 @@ impl Board { PrimitiveMaterial { color: [a[0], a[1], a[2], 1.0], metallic_factor: 0.2, - emissive_factor: [0.2, 0.2, 0.2], + emissive_factor: [0.5, 0.5, 0.5], roughness_factor: 0.8, alpha_mode: AlphaMode::Opaque, alpha_cut_off: 0.5, @@ -70,90 +289,155 @@ impl Board { Ok(board_base) } - fn create_cuboid(offset: Vector3, extent: Vector3) -> Vec { - vec![ - // near - PositionNormal::new( - vec3(offset.x, offset.y + extent.y, offset.z + extent.z), - vec3(0.0, -1.0, 0.0), - ), - PositionNormal::new( - vec3( - offset.x + extent.x, - offset.y + extent.y, - offset.z + extent.z, - ), - vec3(0.0, -1.0, 0.0), - ), - PositionNormal::new( - vec3(offset.x, offset.y + extent.y, offset.z), - vec3(0.0, -1.0, 0.0), - ), - PositionNormal::new( - vec3(offset.x, offset.y + extent.y, offset.z), - vec3(0.0, -1.0, 0.0), - ), - PositionNormal::new( - vec3(offset.x, offset.y + extent.y, offset.z), - vec3(0.0, -1.0, 0.0), - ), - PositionNormal::new( - vec3(offset.x, offset.y + extent.y, offset.z + extent.z), - vec3(0.0, -1.0, 0.0), - ), - // right - PositionNormal::new( - vec3( - offset.x + extent.x, - offset.y + extent.y, - offset.z + extent.z, - ), - vec3(1.0, 0.0, 0.0), - ), - PositionNormal::new( - vec3(offset.x + extent.x, offset.y, offset.z + extent.z), - vec3(1.0, 0.0, 0.0), - ), - PositionNormal::new( - vec3(offset.x + extent.x, offset.y, offset.z), - vec3(1.0, 0.0, 0.0), - ), - PositionNormal::new( - vec3(offset.x + extent.x, offset.y, offset.z), - vec3(1.0, 0.0, 0.0), - ), - PositionNormal::new( - vec3(offset.x + extent.x, offset.y + extent.y, offset.z), - vec3(1.0, 0.0, 0.0), - ), - PositionNormal::new( - vec3( - offset.x + extent.x, - offset.y + extent.y, - offset.z + extent.z, - ), - vec3(1.0, 0.0, 0.0), - ), - // far - PositionNormal::new( - vec3(offset.x + extent.x, offset.y, offset.z + extent.z), - vec3(0.0, 1.0, 0.0), - ), - PositionNormal::new( - vec3(offset.x, offset.y, offset.z + extent.z), - vec3(0.0, 1.0, 0.0), - ), - PositionNormal::new(vec3(offset.x, offset.y, offset.z), vec3(0.0, 1.0, 0.0)), - PositionNormal::new(vec3(offset.x, offset.y, offset.z), vec3(0.0, 1.0, 0.0)), - PositionNormal::new( - vec3(offset.x + extent.x, offset.y, offset.z), - vec3(0.0, 1.0, 0.0), - ), - PositionNormal::new( - vec3(offset.x + extent.x, offset.y, offset.z + extent.z), - vec3(0.0, 1.0, 0.0), - ), - ] + fn create_connection_lines(scene: &mut SceneHandle, color: Color) -> Result> { + let mut entities = Vec::new(); + + scene.on_scene(|scene| { + let mut lines = scene.engine().assets().empty_entity(); + + let draw = Draw::new(vec![{ + let mut mesh = AssetMesh::new( + scene.engine().device(), + scene.engine().settings().graphics_info()?.render_type, + )?; + + let vertex_buffer = Buffer::builder() + .set_data( + &[ + Objects::create_flat_quad([ + vec2(-15.25, -15.25), + vec2(15.25, -15.25), + vec2(15.25, -14.75), + vec2(-15.25, -14.75), + ]), + Objects::create_flat_quad([ + vec2(-10.25, -10.25), + vec2(10.25, -10.25), + vec2(10.25, -9.75), + vec2(-10.25, -9.75), + ]), + Objects::create_flat_quad([ + vec2(-5.25, -5.25), + vec2(5.25, -5.25), + vec2(5.25, -4.75), + vec2(-5.25, -4.75), + ]), + Objects::create_flat_quad([ + vec2(-15.25, 14.75), + vec2(15.25, 14.75), + vec2(15.25, 15.25), + vec2(-15.25, 15.25), + ]), + Objects::create_flat_quad([ + vec2(-10.25, 9.75), + vec2(10.25, 9.75), + vec2(10.25, 10.25), + vec2(-10.25, 10.25), + ]), + Objects::create_flat_quad([ + vec2(-5.25, 4.75), + vec2(5.25, 4.75), + vec2(5.25, 5.25), + vec2(-5.25, 5.25), + ]), + Objects::create_flat_quad([ + vec2(-14.75, -15.25), + vec2(-14.75, 15.25), + vec2(-15.25, 15.25), + vec2(-15.25, -15.25), + ]), + Objects::create_flat_quad([ + vec2(-9.75, -10.25), + vec2(-9.75, 10.25), + vec2(-10.25, 10.25), + vec2(-10.25, -10.25), + ]), + Objects::create_flat_quad([ + vec2(-4.75, -5.25), + vec2(-4.75, 5.25), + vec2(-5.25, 5.25), + vec2(-5.25, -5.25), + ]), + Objects::create_flat_quad([ + vec2(15.25, -15.25), + vec2(15.25, 15.25), + vec2(14.75, 15.25), + vec2(14.75, -15.25), + ]), + Objects::create_flat_quad([ + vec2(10.25, -10.25), + vec2(10.25, 10.25), + vec2(9.75, 10.25), + vec2(9.75, -10.25), + ]), + Objects::create_flat_quad([ + vec2(5.25, -5.25), + vec2(5.25, 5.25), + vec2(4.75, 5.25), + vec2(4.75, -5.25), + ]), + Objects::create_flat_quad([ + vec2(0.25, -15.25), + vec2(0.25, -4.75), + vec2(-0.25, -4.75), + vec2(-0.25, -15.25), + ]), + Objects::create_flat_quad([ + vec2(-0.25, 15.25), + vec2(-0.25, 4.75), + vec2(0.25, 4.75), + vec2(0.25, 15.25), + ]), + Objects::create_flat_quad([ + vec2(-15.25, -0.25), + vec2(-4.75, -0.25), + vec2(-4.75, 0.25), + vec2(-15.25, 0.25), + ]), + Objects::create_flat_quad([ + vec2(15.25, 0.25), + vec2(4.75, 0.25), + vec2(4.75, -0.25), + vec2(15.25, -0.25), + ]), + ] + .concat(), + ) + .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) + .set_memory_usage(MemoryUsage::CpuOnly) + .build(scene.engine().device().clone())?; + + let a: [f32; 3] = color.into(); + + mesh.add_primitive( + vertex_buffer, + None, + None, + PrimitiveMaterial { + color: [a[0], a[1], a[2], 1.0], + metallic_factor: 0.2, + emissive_factor: [0.2, 0.2, 0.2], + roughness_factor: 0.8, + alpha_mode: AlphaMode::Opaque, + alpha_cut_off: 0.5, + }, + true, + )?; + + mesh + }]); + lines.insert_component(draw); + + let mut location = Location::from_entity(&mut lines); + location.set_offset(vec3(0.0, 0.0, MillGame::OFFSET_TO_BOARD)); + lines.insert_component(location); + + entities.push(scene.add_entity(lines)?); + + Ok(()) + })?; + + Ok(entities) } } @@ -183,7 +467,7 @@ impl Map for Board { Ok(vec![]) } - fn disable(&self, scene: &mut Scene) -> Result<()> { - todo!() + fn disable(&self, _scene: &mut Scene) -> Result<()> { + unreachable!() } } diff --git a/src/game.rs b/src/game.rs index 461075b..ea74713 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,26 +1,155 @@ -use std::sync::Arc; +use std::sync::{ + atomic::{AtomicU32, Ordering::SeqCst}, + Arc, Mutex, +}; use anyhow::Result; -use engine::prelude::*; +use engine::prelude::{cgmath::vec3, *}; -use crate::board::Board; +use crate::{board::Board, objects::Objects}; pub struct MillGame { board: Arc, - scene: SceneHandle, + white_stones: [Entity; 9], + black_stones: [Entity; 9], + + scene: Mutex, + camera_controls: Mutex, + + mouse_x: AtomicU32, + mouse_y: AtomicU32, } impl MillGame { + pub const OFFSET_TO_BOARD: f32 = 0.01; + pub fn new(engine: Arc) -> Result> { let mut scene = SceneHandle::new(&engine)?; + let board = Board::new(&engine, &mut scene)?; + + let mut white_stones = None; + let mut black_stones = None; + + scene.on_scene(|scene| { + let view = scene.view_mut(); + + view.camera_mut().set_center(board.center()); + view.update_buffer()?; + + // add light + let mut sun_light = engine.new_directional_light()?; + sun_light.set_direction(vec3(10.0, -4.0, -20.0))?; + sun_light.set_color(vec3(1.0, 1.0, 1.0))?; + sun_light.set_position(vec3(0.0, 0.0, 100.0))?; + sun_light.set_power(10000000000.0)?; + + scene.add_light(sun_light)?; + + white_stones = Some( + Self::init_nine_stones(&engine, Color::White)? + .into_iter() + .enumerate() + .map(|(index, mut e)| { + let location = e.get_component_mut::()?; + location.set_position(board.white_start_slots()[index].extend(0.0)); + + scene.add_entity(e) + }) + .collect::>>()? + .try_into() + .unwrap_or_else(|_: Vec| { + unreachable!("create array from vec from an array") + }), + ); + + black_stones = Some( + Self::init_nine_stones(&engine, Color::Black)? + .into_iter() + .enumerate() + .map(|(index, mut e)| { + let location = e.get_component_mut::()?; + location.set_position(board.black_start_slots()[index].extend(0.0)); + + scene.add_entity(e) + }) + .collect::>>()? + .try_into() + .unwrap_or_else(|_: Vec| { + unreachable!("create array from vec from an array") + }), + ); + + Ok(()) + })?; + + let camera_control = CameraControl::new(&mut scene)?; scene.activate()?; Ok(Arc::new(Self { - board: Board::new(engine, &mut scene)?, - scene, + board, + white_stones: white_stones.unwrap(), + black_stones: black_stones.unwrap(), + + scene: Mutex::new(scene), + camera_controls: Mutex::new(camera_control), + + mouse_x: AtomicU32::new(0), + mouse_y: AtomicU32::new(0), })) } + + fn init_nine_stones(engine: &Arc, color: Color) -> Result<[EntityObject; 9]> { + Ok((0..9) + .map(|_| Self::init_stone(engine, color)) + .collect::>>()? + .try_into() + .unwrap_or_else(|_: Vec| { + unreachable!("create array from vec from an array") + })) + } + + fn init_stone(engine: &Arc, color: Color) -> Result { + let mut marker = engine.assets().empty_entity(); + + let draw = Draw::new(vec![{ + let mut mesh = AssetMesh::new( + engine.device(), + engine.settings().graphics_info()?.render_type, + )?; + + let vertex_buffer = Buffer::builder() + .set_data(&Objects::create_cylinder(1.0, 0.25, 12)) + .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) + .set_memory_usage(MemoryUsage::CpuOnly) + .build(engine.device().clone())?; + + let a: [f32; 3] = color.into(); + + mesh.add_primitive( + vertex_buffer, + None, + None, + PrimitiveMaterial { + color: [a[0], a[1], a[2], 1.0], + metallic_factor: 0.2, + emissive_factor: [0.2, 0.2, 0.2], + roughness_factor: 0.8, + alpha_mode: AlphaMode::Opaque, + alpha_cut_off: 0.5, + }, + true, + )?; + + mesh + }]); + marker.insert_component(draw); + + let location = Location::from_entity(&mut marker); + marker.insert_component(location); + + Ok(marker) + } } impl EngineObject for MillGame { @@ -34,10 +163,51 @@ impl EngineObject for MillGame { fn event(&self, event: EngineEvent) -> Result<()> { match event { - EngineEvent::MouseMotion(_, _) => (), - EngineEvent::MouseButtonDown(_) => (), - EngineEvent::MouseButtonUp(_) => (), - EngineEvent::MouseWheel(_, _, _) => (), + EngineEvent::MouseMotion(x, y) => { + self.mouse_x.store(x, SeqCst); + self.mouse_y.store(y, SeqCst); + + self.camera_controls.lock().unwrap().mouse_move( + x, + y, + &mut *self.scene.lock().unwrap(), + )?; + } + EngineEvent::MouseButtonDown(button) => match button { + MouseButton::Left => { + self.scene.lock().unwrap().on_scene(|scene| { + if let Some(world_space) = scene.screen_space_to_world( + self.mouse_x.load(SeqCst), + self.mouse_y.load(SeqCst), + )? { + if self.board.close_to_marker(world_space.truncate()) { + println!("close to marker"); + } else { + println!("not close to a marker"); + } + } + + Ok(()) + })?; + } + MouseButton::Middle => self.camera_controls.lock().unwrap().hold(), + MouseButton::Right => (), + MouseButton::Forward => (), + MouseButton::Backward => (), + }, + EngineEvent::MouseButtonUp(button) => match button { + MouseButton::Left => (), + MouseButton::Middle => self.camera_controls.lock().unwrap().release(), + MouseButton::Right => (), + MouseButton::Forward => (), + MouseButton::Backward => (), + }, + EngineEvent::MouseWheel(_x, y, direction) => self + .camera_controls + .lock() + .unwrap() + .scroll_wheel(y, direction, &mut *self.scene.lock().unwrap())?, + EngineEvent::KeyDown(_) => (), EngineEvent::KeyUp(_) => (), EngineEvent::ButtonDown(_) => (), diff --git a/src/main.rs b/src/main.rs index 39d72a4..bb28530 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod board; mod game; +mod objects; use anyhow::Result; use assetpath::AssetPath; @@ -22,6 +23,9 @@ fn main() -> Result<()> { create_info.window_info.height = 600; create_info.window_info.width = 800; + create_info.enable_keyboard = true; + create_info.enable_mouse = true; + let engine = Engine::new(create_info)?; engine.set_game_object(Some(MillGame::new(engine.clone())?))?; diff --git a/src/objects.rs b/src/objects.rs new file mode 100644 index 0000000..beaf183 --- /dev/null +++ b/src/objects.rs @@ -0,0 +1,235 @@ +use cgmath::{vec3, Matrix3, Vector3}; +use engine::prelude::{ + cgmath::{Deg, Vector2}, + *, +}; + +pub struct Objects; + +impl Objects { + pub fn create_cuboid(offset: Vector3, extent: Vector3) -> [PositionNormal; 36] { + [ + // near + PositionNormal::new( + vec3(offset.x, offset.y + extent.y, offset.z + extent.z), + vec3(0.0, -1.0, 0.0), + ), + PositionNormal::new( + vec3( + offset.x + extent.x, + offset.y + extent.y, + offset.z + extent.z, + ), + vec3(0.0, -1.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y + extent.y, offset.z), + vec3(0.0, -1.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y + extent.y, offset.z), + vec3(0.0, -1.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y + extent.y, offset.z), + vec3(0.0, -1.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y + extent.y, offset.z + extent.z), + vec3(0.0, -1.0, 0.0), + ), + // right + PositionNormal::new( + vec3( + offset.x + extent.x, + offset.y + extent.y, + offset.z + extent.z, + ), + vec3(1.0, 0.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x + extent.x, offset.y, offset.z + extent.z), + vec3(1.0, 0.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x + extent.x, offset.y, offset.z), + vec3(1.0, 0.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x + extent.x, offset.y, offset.z), + vec3(1.0, 0.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x + extent.x, offset.y + extent.y, offset.z), + vec3(1.0, 0.0, 0.0), + ), + PositionNormal::new( + vec3( + offset.x + extent.x, + offset.y + extent.y, + offset.z + extent.z, + ), + vec3(1.0, 0.0, 0.0), + ), + // far + PositionNormal::new( + vec3(offset.x + extent.x, offset.y, offset.z + extent.z), + vec3(0.0, 1.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y, offset.z + extent.z), + vec3(0.0, 1.0, 0.0), + ), + PositionNormal::new(vec3(offset.x, offset.y, offset.z), vec3(0.0, 1.0, 0.0)), + PositionNormal::new(vec3(offset.x, offset.y, offset.z), vec3(0.0, 1.0, 0.0)), + PositionNormal::new( + vec3(offset.x + extent.x, offset.y, offset.z), + vec3(0.0, 1.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x + extent.x, offset.y, offset.z + extent.z), + vec3(0.0, 1.0, 0.0), + ), + // left + PositionNormal::new( + vec3(offset.x, offset.y, offset.z + extent.z), + vec3(-1.0, 0.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y + extent.y, offset.z + extent.z), + vec3(-1.0, 0.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y + extent.y, offset.z), + vec3(-1.0, 0.0, 0.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y + extent.y, offset.z), + vec3(-1.0, 0.0, 0.0), + ), + PositionNormal::new(vec3(offset.x, offset.y, offset.z), vec3(-1.0, 0.0, 0.0)), + PositionNormal::new( + vec3(offset.x, offset.y, offset.z + extent.z), + vec3(-1.0, 0.0, 0.0), + ), + // top + PositionNormal::new( + vec3(offset.x, offset.y, offset.z + extent.z), + vec3(0.0, 0.0, 1.0), + ), + PositionNormal::new( + vec3(offset.x + extent.x, offset.y, offset.z + extent.z), + vec3(0.0, 0.0, 1.0), + ), + PositionNormal::new( + vec3( + offset.x + extent.x, + offset.y + extent.y, + offset.z + extent.z, + ), + vec3(0.0, 0.0, 1.0), + ), + PositionNormal::new( + vec3( + offset.x + extent.x, + offset.y + extent.y, + offset.z + extent.z, + ), + vec3(0.0, 0.0, 1.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y + extent.y, offset.z + extent.z), + vec3(0.0, 0.0, 1.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y, offset.z + extent.z), + vec3(0.0, 0.0, 1.0), + ), + // bottom + PositionNormal::new( + vec3(offset.x + extent.x, offset.y + extent.y, offset.z), + vec3(0.0, 0.0, -1.0), + ), + PositionNormal::new( + vec3(offset.x, offset.y + extent.y, offset.z), + vec3(0.0, 0.0, -1.0), + ), + PositionNormal::new(vec3(offset.x, offset.y, offset.z), vec3(0.0, 0.0, -1.0)), + PositionNormal::new(vec3(offset.x, offset.y, offset.z), vec3(0.0, 0.0, -1.0)), + PositionNormal::new( + vec3(offset.x + extent.x, offset.y, offset.z), + vec3(0.0, 0.0, -1.0), + ), + PositionNormal::new( + vec3(offset.x + extent.x, offset.y + extent.y, offset.z), + vec3(0.0, 0.0, -1.0), + ), + ] + } + + pub fn create_flat_quad(corners: [Vector2; 4]) -> [PositionNormal; 6] { + let up = vec3(0.0, 0.0, 1.0); + + [ + PositionNormal::new(corners[0].extend(0.0), up), + PositionNormal::new(corners[1].extend(0.0), up), + PositionNormal::new(corners[2].extend(0.0), up), + PositionNormal::new(corners[2].extend(0.0), up), + PositionNormal::new(corners[3].extend(0.0), up), + PositionNormal::new(corners[0].extend(0.0), up), + ] + } + + pub fn create_cylinder(radius: f32, height: f32, detail: u8) -> Vec { + let center = vec3(0.0, 0.0, 0.0); + let reference_point = vec3(radius, 0.0, 0.0); + + let split_degree = Deg(360.0 / detail as f32); + + let mut vertices = Vec::with_capacity(detail as usize * 12); + + for i in 0..detail { + let first_outer = Matrix3::from_angle_z(split_degree * i as f32) * reference_point; + let second_outer = + Matrix3::from_angle_z(split_degree * (i + 1) as f32) * reference_point; + + // bottom triangle + vertices.push(PositionNormal::new(center, vec3(0.0, 0.0, -1.0))); + vertices.push(PositionNormal::new(first_outer, vec3(0.0, 0.0, -1.0))); + vertices.push(PositionNormal::new(second_outer, vec3(0.0, 0.0, -1.0))); + + // top triangle + vertices.push(PositionNormal::new( + center + vec3(0.0, 0.0, height), + vec3(0.0, 0.0, 1.0), + )); + vertices.push(PositionNormal::new( + first_outer + vec3(0.0, 0.0, height), + vec3(0.0, 0.0, 1.0), + )); + vertices.push(PositionNormal::new( + second_outer + vec3(0.0, 0.0, height), + vec3(0.0, 0.0, 1.0), + )); + + // outside face + vertices.push(PositionNormal::new( + first_outer + vec3(0.0, 0.0, height), + first_outer.normalize(), + )); + vertices.push(PositionNormal::new(first_outer, first_outer.normalize())); + vertices.push(PositionNormal::new(second_outer, second_outer.normalize())); + vertices.push(PositionNormal::new(second_outer, second_outer.normalize())); + vertices.push(PositionNormal::new( + second_outer + vec3(0.0, 0.0, height), + second_outer.normalize(), + )); + vertices.push(PositionNormal::new( + first_outer + vec3(0.0, 0.0, height), + first_outer.normalize(), + )); + } + + vertices + } +}