Skip to content

Commit

Permalink
Normals fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
DotWith committed Apr 3, 2024
1 parent 43e2b37 commit e3a59f3
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 17 deletions.
2 changes: 1 addition & 1 deletion bevy_rmesh/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bevy_rmesh"
version = "0.3.1"
version = "0.3.2"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "A Bevy extension for RMesh loading"
Expand Down
28 changes: 16 additions & 12 deletions bevy_rmesh/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use bevy::render::{
mesh::{Indices, Mesh},
render_resource::PrimitiveTopology,
};
use rmesh::{read_rmesh, CalcBoundBox, ROOM_SCALE};
use rmesh::{read_rmesh, ExtMesh, ROOM_SCALE};

pub struct RMeshLoader {
pub(crate) supported_compressed_formats: CompressedImageFormats,
Expand Down Expand Up @@ -53,7 +53,10 @@ async fn load_rmesh<'a, 'b>(
// let mut entity_meshes = vec![];

for (i, complex_mesh) in header.meshes.iter().enumerate() {
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default());
let mut mesh = Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetUsages::default(),
);

let positions: Vec<_> = complex_mesh
.vertices
Expand All @@ -69,24 +72,25 @@ async fn load_rmesh<'a, 'b>(
let tex_coords: Vec<_> = complex_mesh
.vertices
.iter()
.flat_map(|v| {
[
[v.tex_coords[0][0], 1.0 - v.tex_coords[0][1]], // First UV channel
[v.tex_coords[1][0], 1.0 - v.tex_coords[1][1]], // Second UV channel
]
})
// .flat_map(|v| {
// [
// [v.tex_coords[0][0], 1.0 - v.tex_coords[0][1]], // First UV channel
// [v.tex_coords[1][0], 1.0 - v.tex_coords[1][1]], // Second UV channel
// ]
// })
.map(|v| v.tex_coords[0])
.collect();
let indices = complex_mesh
let indices: Vec<u32> = complex_mesh
.triangles
.iter()
.flat_map(|strip| strip.iter().rev().copied())
.collect();
let normals = complex_mesh.calculate_normals();

mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, positions);
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, tex_coords);
mesh.insert_indices(Indices::U32(indices));
mesh.duplicate_vertices();
mesh.compute_flat_normals();
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
mesh.insert_indices(Indices::U32(indices)); // TODO: Colliders need this second call for indices

let mesh = load_context.add_labeled_asset(format!("Mesh{0}", i), mesh);

Expand Down
2 changes: 1 addition & 1 deletion rmesh/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rmesh"
version = "0.3.4"
version = "0.3.5"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "A parser for the rmesh extension"
Expand Down
106 changes: 103 additions & 3 deletions rmesh/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ pub struct TriggerBox {
pub name: FixedLengthString,
}

impl CalcBoundBox for SimpleMesh {
impl ExtMesh for SimpleMesh {
fn bounding_box(&self) -> Bounds {
let mut min_x = f32::INFINITY;
let mut min_y = f32::INFINITY;
Expand All @@ -158,9 +158,58 @@ impl CalcBoundBox for SimpleMesh {
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 CalcBoundBox for ComplexMesh {
impl ExtMesh for ComplexMesh {
fn bounding_box(&self) -> Bounds {
let mut min_x = f32::INFINITY;
let mut min_y = f32::INFINITY;
Expand All @@ -187,11 +236,62 @@ impl CalcBoundBox for ComplexMesh {
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 CalcBoundBox {
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 {
Expand Down

0 comments on commit e3a59f3

Please sign in to comment.