diff --git a/bevy_rmesh/examples/view.rs b/bevy_rmesh/examples/view.rs index 1cc769c..3252126 100644 --- a/bevy_rmesh/examples/view.rs +++ b/bevy_rmesh/examples/view.rs @@ -16,7 +16,10 @@ fn setup( // cube commands.spawn(PbrBundle { mesh: asset_server.load("cube.rmesh#Mesh0"), - material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()), + material: materials.add(StandardMaterial { + base_color: Color::rgb(0.8, 0.7, 0.6), + ..default() + }), transform: Transform::from_xyz(0.0, 0.5, 0.0), ..default() }); diff --git a/rmesh/src/lib.rs b/rmesh/src/lib.rs index 882d3f7..9e4b68f 100644 --- a/rmesh/src/lib.rs +++ b/rmesh/src/lib.rs @@ -131,6 +131,180 @@ pub struct TriggerBox { pub name: FixedLengthString, } +impl ExtMesh for SimpleMesh { + fn bounding_box(&self) -> Bounds { + let mut min_x = f32::INFINITY; + let mut min_y = f32::INFINITY; + let mut min_z = f32::INFINITY; + let mut max_x = f32::NEG_INFINITY; + let mut max_y = f32::NEG_INFINITY; + let mut max_z = f32::NEG_INFINITY; + + for vertex in &self.vertices { + let [x, y, z] = *vertex; + + // Update min values + min_x = min_x.min(x); + min_y = min_y.min(y); + min_z = min_z.min(z); + + // Update max values + max_x = max_x.max(x); + max_y = max_y.max(y); + max_z = max_z.max(z); + } + + let min_point = [min_x, min_y, min_z]; + let max_point = [max_x, max_y, max_z]; + Bounds::new(min_point, max_point) + } + + fn calculate_normals(&self) -> Vec<[f32; 3]> { + // Initialize vertex normals with zero vectors + let mut vertex_normals = vec![[0.0, 0.0, 0.0]; self.vertices.len()]; + + // Calculate face normals and accumulate them to vertex normals + for triangle in &self.triangles { + let vertex0 = self.vertices[triangle[0] as usize]; + let vertex1 = self.vertices[triangle[1] as usize]; + let vertex2 = self.vertices[triangle[2] as usize]; + + let edge1 = [ + vertex1[0] - vertex0[0], + vertex1[1] - vertex0[1], + vertex1[2] - vertex0[2], + ]; + let edge2 = [ + vertex2[0] - vertex0[0], + vertex2[1] - vertex0[1], + vertex2[2] - vertex0[2], + ]; + + let normal = [ + edge1[1] * edge2[2] - edge1[2] * edge2[1], + edge1[2] * edge2[0] - edge1[0] * edge2[2], + edge1[0] * edge2[1] - edge1[1] * edge2[0], + ]; + + // Accumulate face normal to the vertices of the triangle + for i in 0..3 { + let vertex_index = triangle[i] as usize; + vertex_normals[vertex_index][0] += normal[0]; + vertex_normals[vertex_index][1] += normal[1]; + vertex_normals[vertex_index][2] += normal[2]; + } + } + + // Normalize vertex normals + for normal in &mut vertex_normals { + let length = (normal[0].powi(2) + normal[1].powi(2) + normal[2].powi(2)).sqrt(); + if length != 0.0 { + normal[0] /= length; + normal[1] /= length; + normal[2] /= length; + } + } + + vertex_normals + } +} + +impl ExtMesh for ComplexMesh { + fn bounding_box(&self) -> Bounds { + let mut min_x = f32::INFINITY; + let mut min_y = f32::INFINITY; + let mut min_z = f32::INFINITY; + let mut max_x = f32::NEG_INFINITY; + let mut max_y = f32::NEG_INFINITY; + let mut max_z = f32::NEG_INFINITY; + + for vertex in &self.vertices { + let [x, y, z] = vertex.position; + + // Update min values + min_x = min_x.min(x); + min_y = min_y.min(y); + min_z = min_z.min(z); + + // Update max values + max_x = max_x.max(x); + max_y = max_y.max(y); + max_z = max_z.max(z); + } + + let min_point = [min_x, min_y, min_z]; + let max_point = [max_x, max_y, max_z]; + Bounds::new(min_point, max_point) + } + + fn calculate_normals(&self) -> Vec<[f32; 3]> { + // Initialize vertex normals with zero vectors + let mut vertex_normals = vec![[0.0, 0.0, 0.0]; self.vertices.len()]; + + // Calculate face normals and accumulate them to vertex normals + for triangle in &self.triangles { + let vertex0 = self.vertices[triangle[0] as usize].position; + let vertex1 = self.vertices[triangle[1] as usize].position; + let vertex2 = self.vertices[triangle[2] as usize].position; + + let edge1 = [ + vertex1[0] - vertex0[0], + vertex1[1] - vertex0[1], + vertex1[2] - vertex0[2], + ]; + let edge2 = [ + vertex2[0] - vertex0[0], + vertex2[1] - vertex0[1], + vertex2[2] - vertex0[2], + ]; + + let normal = [ + edge1[1] * edge2[2] - edge1[2] * edge2[1], + edge1[2] * edge2[0] - edge1[0] * edge2[2], + edge1[0] * edge2[1] - edge1[1] * edge2[0], + ]; + + // Accumulate face normal to the vertices of the triangle + for i in 0..3 { + let vertex_index = triangle[i] as usize; + vertex_normals[vertex_index][0] += normal[0]; + vertex_normals[vertex_index][1] += normal[1]; + vertex_normals[vertex_index][2] += normal[2]; + } + } + + // Normalize vertex normals + for normal in &mut vertex_normals { + let length = (normal[0].powi(2) + normal[1].powi(2) + normal[2].powi(2)).sqrt(); + if length != 0.0 { + normal[0] /= length; + normal[1] /= length; + normal[2] /= length; + } + } + + vertex_normals + } +} + +pub trait ExtMesh { + /// Used for aabb calc + fn bounding_box(&self) -> Bounds; + /// Calculate normals for the vertices based on the triangle faces. + fn calculate_normals(&self) -> Vec<[f32; 3]>; +} + +pub struct Bounds { + pub min: [f32; 3], + pub max: [f32; 3], +} + +impl Bounds { + pub fn new(min: [f32; 3], max: [f32; 3]) -> Self { + Self { min, max } + } +} + #[binrw] #[derive(Debug)] pub struct EntityData { @@ -173,35 +347,3 @@ pub fn write_rmesh(header: &Header) -> Result, RMeshError> { Ok(bytes) } - -/// Used for aabb calc -pub fn calculate_bounds(vertices: &Vec) -> Option<([f32; 3], [f32; 3])> { - if vertices.is_empty() { - return None; - } - - let mut min_x = f32::INFINITY; - let mut min_y = f32::INFINITY; - let mut min_z = f32::INFINITY; - let mut max_x = f32::NEG_INFINITY; - let mut max_y = f32::NEG_INFINITY; - let mut max_z = f32::NEG_INFINITY; - - for vertex in vertices { - let [x, y, z] = vertex.position; - - // Update min values - min_x = min_x.min(x); - min_y = min_y.min(y); - min_z = min_z.min(z); - - // Update max values - max_x = max_x.max(x); - max_y = max_y.max(y); - max_z = max_z.max(z); - } - - let min_point = [min_x, min_y, min_z]; - let max_point = [max_x, max_y, max_z]; - Some((min_point, max_point)) -}