From c3b3e3bd98a4cd1855629c3d789a4ba5441d0eee Mon Sep 17 00:00:00 2001 From: fredrikr79 Date: Wed, 1 Oct 2025 11:27:35 +0200 Subject: [PATCH] wip pls force push this --- gloom-rs/src/draw.rs | 241 +++++++++++++++++++++++++++++++++++++++++++ gloom-rs/src/main.rs | 224 +--------------------------------------- 2 files changed, 243 insertions(+), 222 deletions(-) create mode 100644 gloom-rs/src/draw.rs diff --git a/gloom-rs/src/draw.rs b/gloom-rs/src/draw.rs new file mode 100644 index 0000000..2037541 --- /dev/null +++ b/gloom-rs/src/draw.rs @@ -0,0 +1,241 @@ +use crate::shader::Shader; +use crate::scene_graph::SceneNode; + +use std::collections::HashMap; +use std::{ mem, ptr, os::raw::c_void }; +use std::thread; +use std::sync::{Mutex, Arc, RwLock}; + +use crate::mesh::{ Mesh, Terrain, Helicopter }; + +// Get the size of an arbitrary array of numbers measured in bytes +// Example usage: byte_size_of_array(my_array) +fn byte_size_of_array(val: &[T]) -> isize { + std::mem::size_of_val(&val[..]) as isize +} + +// Get the OpenGL-compatible pointer to an arbitrary array of numbers +// Example usage: pointer_to_array(my_array) +fn pointer_to_array(val: &[T]) -> *const c_void { + &val[0] as *const T as *const c_void +} + +// Get the size of the given type in bytes +// Example usage: size_of::() +fn size_of() -> i32 { + mem::size_of::() as i32 +} + +// Get an offset in bytes for n units of type T, represented as a relative pointer +// Example usage: offset::(4) +// Get an offset in bytes for n units of type T, represented as a relative pointer +// Example usage: offset::(4) +fn offset(n: u32) -> *const c_void { + (n * mem::size_of::() as u32) as *const c_void +} +// ptr::null() + +pub unsafe fn draw_scene(node: &SceneNode, + view_projection_matrix: &glm::Mat4, + mut transformation_so_far: glm::Mat4, + shader: &Shader, + elapsed: f32 +) { + + let mut model_matrix = glm::identity(); + // then apply node’s actual translation + model_matrix = glm::translate(&model_matrix, &node.position); + + // translate to pivot, rotate, translate back + model_matrix = glm::translate(&model_matrix, &node.reference_point); + model_matrix = glm::rotate_z(&model_matrix, node.rotation.z); + model_matrix = glm::rotate_y(&model_matrix, node.rotation.y); + model_matrix = glm::rotate_x(&model_matrix, node.rotation.x); + model_matrix = glm::translate(&model_matrix, &-node.reference_point); + + // combine with parent + transformation_so_far = transformation_so_far * model_matrix; + + let loc = shader.get_uniform_location("transform"); + gl::UniformMatrix4fv(loc, 1, gl::FALSE, (view_projection_matrix * transformation_so_far).as_ptr()); + + if node.index_count >= 0 { + gl::BindVertexArray(node.vao_id); + gl::DrawElements(gl::TRIANGLES, node.index_count, gl::UNSIGNED_INT, ptr::null()); + } + + for &child in &node.children { + draw_scene(&*child, view_projection_matrix, transformation_so_far, shader, elapsed); + } +} + +// == // Generate your VAO here +unsafe fn create_vao(vertices: &Vec, indices: &Vec, colors: &Vec, normals: &Vec, id:u32) -> u32 { + // generate a VAO and bind it + let mut vao_id: u32 = id; + gl::GenVertexArrays(1, &mut vao_id); + gl::BindVertexArray(vao_id); + + // -- vertex buffer -- + + // generate a VBO and bind it + let mut vertices_vbo_id: u32 = 0; + gl::GenBuffers(1, &mut vertices_vbo_id); + gl::BindBuffer(gl::ARRAY_BUFFER, vertices_vbo_id); + + // fill it with data + gl::BufferData( + gl::ARRAY_BUFFER, + byte_size_of_array(vertices), + pointer_to_array(vertices), + gl::STATIC_DRAW + ); + + // configure a VAP for the data and enable it + let vertices_index = 0; + gl::VertexAttribPointer(vertices_index, 3, gl::FLOAT, gl::FALSE, size_of::()*3, ptr::null()); + gl::EnableVertexAttribArray(vertices_index); + + // -- color buffer -- + + // generate a VBO and bind it + let mut colors_vbo_id: u32 = 1; + gl::GenBuffers(1, &mut colors_vbo_id); + gl::BindBuffer(gl::ARRAY_BUFFER, colors_vbo_id); + + // fill it with data + gl::BufferData( + gl::ARRAY_BUFFER, + byte_size_of_array(colors), + pointer_to_array(colors), + gl::STATIC_DRAW + ); + + // configure a VAP for the data and enable it + let colors_index = 1; + gl::VertexAttribPointer(colors_index, 4, gl::FLOAT, gl::FALSE, size_of::()*4, ptr::null()); + gl::EnableVertexAttribArray(colors_index); + + // -- normal buffer -- + + // generate a VBO and bind it + let mut normals_vbo_id: u32 = 2; + gl::GenBuffers(1, &mut normals_vbo_id); + gl::BindBuffer(gl::ARRAY_BUFFER, normals_vbo_id); + + // fill it with data + gl::BufferData( + gl::ARRAY_BUFFER, + byte_size_of_array(normals), + pointer_to_array(normals), + gl::STATIC_DRAW + ); + + // configure a VAP for the normal data and enable it + let normals_index = 2; + gl::VertexAttribPointer(normals_index, 3, gl::FLOAT, gl::FALSE, size_of::()*3, ptr::null()); + gl::EnableVertexAttribArray(normals_index); + + // -- index buffer -- + + // generate a IBO and bind it + let mut ibo_id: u32 = 0; + gl::GenBuffers(1, &mut ibo_id); + gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ibo_id); + + // fill it with data + gl::BufferData( + gl::ELEMENT_ARRAY_BUFFER, + byte_size_of_array(indices), + pointer_to_array(indices), + gl::STATIC_DRAW + ); + + return vao_id; +} + +type MeshMap = HashMap; + +struct World { + lunar: +} + +pub fn load_models() -> World { + let lunarsurface = Terrain::load(&"resources/lunarsurface.obj"); + let helicopter = Helicopter::load(&"resources/helicopter.obj"); + let heli_body = helicopter.body; + let heli_door = helicopter.door; + let heli_main_rotor = helicopter.main_rotor; + let heli_tail_rotor = helicopter.tail_rotor; + + return HashMap::from([ + (unsafe { + create_vao(&lunarsurface.vertices, &lunarsurface.indices, &lunarsurface.colors, &lunarsurface.normals, 1) + }, lunarsurface), + (unsafe { + create_vao(&heli_body.vertices, &heli_body.indices, &heli_body.colors, &heli_body.normals, 2) + }, heli_body), + (unsafe { + create_vao(&heli_door.vertices, &heli_door.indices, &heli_door.colors, &heli_door.normals, 2) + }, heli_door), + (unsafe { + create_vao(&heli_main_rotor.vertices, &heli_main_rotor.indices, &heli_main_rotor.colors, &heli_main_rotor.normals, 2) + }, heli_main_rotor), + (unsafe { + create_vao(&heli_tail_rotor.vertices, &heli_tail_rotor.indices, &heli_tail_rotor.colors, &heli_tail_rotor.normals, 2) + }, heli_tail_rotor), + ]); +} + +pub fn setup_scene_graph(world: World) { + // Define scene nodes + let mut scene_node = SceneNode::new(); + let mut lunar_node = SceneNode::from_vao(world.lunar_vao_id, world.lunarsurface.index_count); + let mut heli_root_node = SceneNode::new(); + let mut heli_body_node = SceneNode::from_vao(world.heli_body_vao_id, world.heli_body.index_count); + let mut heli_door_node = SceneNode::from_vao(world.heli_door_vao_id, world.heli_door.index_count); + let mut heli_main_rotor_node = SceneNode::from_vao(world.heli_main_rotor_vao_id, world.heli_main_rotor.index_count); + let mut heli_tail_rotor_node = SceneNode::from_vao(world.heli_tail_rotor_vao_id, world.heli_tail_rotor.index_count); + + // Set scene graph hierarchy + heli_root_node.add_child(&heli_body_node); + heli_root_node.add_child(&heli_door_node); + heli_root_node.add_child(&heli_main_rotor_node); + heli_root_node.add_child(&heli_tail_rotor_node); + lunar_node.add_child(&heli_root_node); + scene_node.add_child(&lunar_node); + + // Set model reference points + scene_node.reference_point = glm::vec3(0.0f32,0.0f32, 0.0f32); + lunar_node.reference_point = glm::vec3(0.0f32,0.0f32, 0.0f32); + heli_root_node.reference_point = glm::vec3(0.0f32, 0.0f32, 0.0f32); + heli_body_node.reference_point = glm::vec3(0.0f32,0.0f32, 0.0f32); + heli_door_node.reference_point = glm::vec3(0.0f32, 0.0f32, 0.0f32); + heli_main_rotor_node.reference_point = glm::vec3(0.0f32, 2.0f32, 0.0f32); + heli_tail_rotor_node.reference_point = glm::vec3(0.35f32, 2.3f32, 10.4f32); + + lunar_node.position.y = -10.0f32; + heli_main_rotor_node.rotation = glm::vec3(0.0f32, 2.0f32, 0.0f32); + heli_tail_rotor_node.rotation = glm::vec3(1.0f32, 0.0f32, 0.0f32); +} + + +pub fn update(elapsed: f32, world: World, perspective: glm::Mat4, transformation: glm::Mat4 ) { + // Apply perspective transformation last + let transform_thus_far = perspective * transformation; + + let rotor_speed = 60.0f32; + + // let iter_heli_heading = toolbox::simple_heading_animation(elapsed); + // heli_root_node.position.x = iter_heli_heading.x; + // heli_root_node.position.z = iter_heli_heading.z; + // heli_root_node.rotation.z = iter_heli_heading.roll; + // heli_root_node.rotation.y = iter_heli_heading.yaw; + // heli_root_node.rotation.x = iter_heli_heading.pitch; + world.heli_root_node.rotation.y = elapsed; + + world.heli_main_rotor_node.rotation.y = elapsed * rotor_speed; + world.heli_tail_rotor_node.rotation.x = elapsed * rotor_speed; + + draw::draw_scene(&scene_node, &transform_thus_far, glm::identity(), &simple_shader, elapsed); +} diff --git a/gloom-rs/src/main.rs b/gloom-rs/src/main.rs index f99a70b..5183675 100644 --- a/gloom-rs/src/main.rs +++ b/gloom-rs/src/main.rs @@ -8,7 +8,7 @@ #![allow(unused_variables)] */ extern crate nalgebra_glm as glm; -use std::{ mem, ptr, os::raw::c_void }; +use std::ptr; use std::thread; use std::sync::{Mutex, Arc, RwLock}; @@ -17,13 +17,10 @@ mod util; mod mesh; mod scene_graph; mod toolbox; +mod draw; -use glm::{identity, rotation}; use glutin::event::{Event, WindowEvent, DeviceEvent, KeyboardInput, ElementState::{Pressed, Released}, VirtualKeyCode::{self, *}}; use glutin::event_loop::ControlFlow; -use scene_graph::SceneNode; - -use crate::mesh::{Helicopter, Terrain}; // initial window size const INITIAL_SCREEN_W: u32 = 800; @@ -31,118 +28,7 @@ const INITIAL_SCREEN_H: u32 = 600; // == // Helper functions to make interacting with OpenGL a little bit prettier. You *WILL* need these! // == // -// Get the size of an arbitrary array of numbers measured in bytes -// Example usage: byte_size_of_array(my_array) -fn byte_size_of_array(val: &[T]) -> isize { - std::mem::size_of_val(&val[..]) as isize -} -// Get the OpenGL-compatible pointer to an arbitrary array of numbers -// Example usage: pointer_to_array(my_array) -fn pointer_to_array(val: &[T]) -> *const c_void { - &val[0] as *const T as *const c_void -} - -// Get the size of the given type in bytes -// Example usage: size_of::() -fn size_of() -> i32 { - mem::size_of::() as i32 -} - -// Get an offset in bytes for n units of type T, represented as a relative pointer -// Example usage: offset::(4) -// Get an offset in bytes for n units of type T, represented as a relative pointer -// Example usage: offset::(4) -fn offset(n: u32) -> *const c_void { - (n * mem::size_of::() as u32) as *const c_void -} -// ptr::null() - - -// == // Generate your VAO here -unsafe fn create_vao(vertices: &Vec, indices: &Vec, colors: &Vec, normals: &Vec, id:u32) -> u32 { - // generate a VAO and bind it - let mut vao_id: u32 = id; - gl::GenVertexArrays(1, &mut vao_id); - gl::BindVertexArray(vao_id); - - // -- vertex buffer -- - - // generate a VBO and bind it - let mut vertices_vbo_id: u32 = 0; - gl::GenBuffers(1, &mut vertices_vbo_id); - gl::BindBuffer(gl::ARRAY_BUFFER, vertices_vbo_id); - - // fill it with data - gl::BufferData( - gl::ARRAY_BUFFER, - byte_size_of_array(vertices), - pointer_to_array(vertices), - gl::STATIC_DRAW - ); - - // configure a VAP for the data and enable it - let vertices_index = 0; - gl::VertexAttribPointer(vertices_index, 3, gl::FLOAT, gl::FALSE, size_of::()*3, ptr::null()); - gl::EnableVertexAttribArray(vertices_index); - - // -- color buffer -- - - // generate a VBO and bind it - let mut colors_vbo_id: u32 = 1; - gl::GenBuffers(1, &mut colors_vbo_id); - gl::BindBuffer(gl::ARRAY_BUFFER, colors_vbo_id); - - // fill it with data - gl::BufferData( - gl::ARRAY_BUFFER, - byte_size_of_array(colors), - pointer_to_array(colors), - gl::STATIC_DRAW - ); - - // configure a VAP for the data and enable it - let colors_index = 1; - gl::VertexAttribPointer(colors_index, 4, gl::FLOAT, gl::FALSE, size_of::()*4, ptr::null()); - gl::EnableVertexAttribArray(colors_index); - - // -- normal buffer -- - - // generate a VBO and bind it - let mut normals_vbo_id: u32 = 2; - gl::GenBuffers(1, &mut normals_vbo_id); - gl::BindBuffer(gl::ARRAY_BUFFER, normals_vbo_id); - - // fill it with data - gl::BufferData( - gl::ARRAY_BUFFER, - byte_size_of_array(normals), - pointer_to_array(normals), - gl::STATIC_DRAW - ); - - // configure a VAP for the normal data and enable it - let normals_index = 2; - gl::VertexAttribPointer(normals_index, 3, gl::FLOAT, gl::FALSE, size_of::()*3, ptr::null()); - gl::EnableVertexAttribArray(normals_index); - - // -- index buffer -- - - // generate a IBO and bind it - let mut ibo_id: u32 = 0; - gl::GenBuffers(1, &mut ibo_id); - gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ibo_id); - - // fill it with data - gl::BufferData( - gl::ELEMENT_ARRAY_BUFFER, - byte_size_of_array(indices), - pointer_to_array(indices), - gl::STATIC_DRAW - ); - - return vao_id; -} fn main() { @@ -205,61 +91,6 @@ fn main() { println!("GLSL\t: {}", util::get_gl_string(gl::SHADING_LANGUAGE_VERSION)); } - // == // Set up your VAO around here - - let lunarsurface = Terrain::load(&"resources/lunarsurface.obj"); - let helicopter = Helicopter::load(&"resources/helicopter.obj"); - let heli_body = helicopter.body; - let heli_door = helicopter.door; - let heli_main_rotor = helicopter.main_rotor; - let heli_tail_rotor = helicopter.tail_rotor; - - // - let lunar_vao_id = unsafe { - create_vao(&lunarsurface.vertices, &lunarsurface.indices, &lunarsurface.colors, &lunarsurface.normals, 1) - }; - let heli_body_vao_id = unsafe { - create_vao(&heli_body.vertices, &heli_body.indices, &heli_body.colors, &heli_body.normals, 2) - }; - let heli_door_vao_id = unsafe { - create_vao(&heli_door.vertices, &heli_door.indices, &heli_door.colors, &heli_door.normals, 2) - }; - let heli_main_rotor_vao_id = unsafe { - create_vao(&heli_main_rotor.vertices, &heli_main_rotor.indices, &heli_main_rotor.colors, &heli_main_rotor.normals, 2) - }; - let heli_tail_rotor_vao_id = unsafe { - create_vao(&heli_tail_rotor.vertices, &heli_tail_rotor.indices, &heli_tail_rotor.colors, &heli_tail_rotor.normals, 2) - }; - - // Define scene nodes - let mut scene_node = SceneNode::new(); - let mut lunar_node = SceneNode::from_vao(lunar_vao_id, lunarsurface.index_count); - let mut heli_root_node = SceneNode::new(); - let mut heli_body_node = SceneNode::from_vao(heli_body_vao_id, heli_body.index_count); - let mut heli_door_node = SceneNode::from_vao(heli_door_vao_id, heli_door.index_count); - let mut heli_main_rotor_node = SceneNode::from_vao(heli_main_rotor_vao_id, heli_main_rotor.index_count); - let mut heli_tail_rotor_node = SceneNode::from_vao(heli_tail_rotor_vao_id, heli_tail_rotor.index_count); - - // Set scene graph hierarchy - heli_root_node.add_child(&heli_body_node); - heli_root_node.add_child(&heli_door_node); - heli_root_node.add_child(&heli_main_rotor_node); - heli_root_node.add_child(&heli_tail_rotor_node); - lunar_node.add_child(&heli_root_node); - scene_node.add_child(&lunar_node); - - // Set model reference points - scene_node.reference_point = glm::vec3(0.0f32,0.0f32, 0.0f32); - lunar_node.reference_point = glm::vec3(0.0f32,0.0f32, 0.0f32); - heli_root_node.reference_point = glm::vec3(0.0f32, 0.0f32, 0.0f32); - heli_body_node.reference_point = glm::vec3(0.0f32,0.0f32, 0.0f32); - heli_door_node.reference_point = glm::vec3(0.0f32, 0.0f32, 0.0f32); - heli_main_rotor_node.reference_point = glm::vec3(0.0f32, 2.0f32, 0.0f32); - heli_tail_rotor_node.reference_point = glm::vec3(0.35f32, 2.3f32, 10.4f32); - - lunar_node.position.y = -10.0f32; - heli_main_rotor_node.rotation = glm::vec3(0.0f32, 2.0f32, 0.0f32); - heli_tail_rotor_node.rotation = glm::vec3(1.0f32, 0.0f32, 0.0f32); let mut transformation: glm::Mat4; let perspective: glm::Mat4 = glm::perspective( @@ -395,57 +226,6 @@ fn main() { gl::ClearColor(0.40, 0.55, 1.0, 1.0); // night sky gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT); - // Apply perspective transformation last - let transform_thus_far = perspective * transformation; - - let rotor_speed = 60.0f32; - - // let iter_heli_heading = toolbox::simple_heading_animation(elapsed); - // heli_root_node.position.x = iter_heli_heading.x; - // heli_root_node.position.z = iter_heli_heading.z; - // heli_root_node.rotation.z = iter_heli_heading.roll; - // heli_root_node.rotation.y = iter_heli_heading.yaw; - // heli_root_node.rotation.x = iter_heli_heading.pitch; - heli_root_node.rotation.y = elapsed; - - heli_main_rotor_node.rotation.y = elapsed * rotor_speed; - heli_tail_rotor_node.rotation.x = elapsed * rotor_speed; - - unsafe fn draw_scene(node: &scene_graph::SceneNode, - view_projection_matrix: &glm::Mat4, - mut transformation_so_far: glm::Mat4, - shader: &shader::Shader, - elapsed: f32 - ) { - - let mut model_matrix = identity(); - // then apply node’s actual translation - model_matrix = glm::translate(&model_matrix, &node.position); - - // translate to pivot, rotate, translate back - model_matrix = glm::translate(&model_matrix, &node.reference_point); - model_matrix = glm::rotate_z(&model_matrix, node.rotation.z); - model_matrix = glm::rotate_y(&model_matrix, node.rotation.y); - model_matrix = glm::rotate_x(&model_matrix, node.rotation.x); - model_matrix = glm::translate(&model_matrix, &-node.reference_point); - - // combine with parent - transformation_so_far = transformation_so_far * model_matrix; - - let loc = shader.get_uniform_location("transform"); - gl::UniformMatrix4fv(loc, 1, gl::FALSE, (view_projection_matrix * transformation_so_far).as_ptr()); - - if node.index_count >= 0 { - gl::BindVertexArray(node.vao_id); - gl::DrawElements(gl::TRIANGLES, node.index_count, gl::UNSIGNED_INT, ptr::null()); - } - - for &child in &node.children { - draw_scene(&*child, view_projection_matrix, transformation_so_far, shader, elapsed); - } - } - - draw_scene(&scene_node, &transform_thus_far, identity(), &simple_shader, elapsed); // Display the new color buffer on the display context.swap_buffers().unwrap(); // we use "double buffering" to avoid artifacts }