Skip to content

Commit e3a59f3

Browse files
committed
Normals fixed
1 parent 43e2b37 commit e3a59f3

File tree

4 files changed

+121
-17
lines changed

4 files changed

+121
-17
lines changed

bevy_rmesh/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bevy_rmesh"
3-
version = "0.3.1"
3+
version = "0.3.2"
44
edition = "2021"
55
license = "MIT OR Apache-2.0"
66
description = "A Bevy extension for RMesh loading"

bevy_rmesh/src/loader.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use bevy::render::{
1313
mesh::{Indices, Mesh},
1414
render_resource::PrimitiveTopology,
1515
};
16-
use rmesh::{read_rmesh, CalcBoundBox, ROOM_SCALE};
16+
use rmesh::{read_rmesh, ExtMesh, ROOM_SCALE};
1717

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

5555
for (i, complex_mesh) in header.meshes.iter().enumerate() {
56-
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default());
56+
let mut mesh = Mesh::new(
57+
PrimitiveTopology::TriangleList,
58+
RenderAssetUsages::default(),
59+
);
5760

5861
let positions: Vec<_> = complex_mesh
5962
.vertices
@@ -69,24 +72,25 @@ async fn load_rmesh<'a, 'b>(
6972
let tex_coords: Vec<_> = complex_mesh
7073
.vertices
7174
.iter()
72-
.flat_map(|v| {
73-
[
74-
[v.tex_coords[0][0], 1.0 - v.tex_coords[0][1]], // First UV channel
75-
[v.tex_coords[1][0], 1.0 - v.tex_coords[1][1]], // Second UV channel
76-
]
77-
})
75+
// .flat_map(|v| {
76+
// [
77+
// [v.tex_coords[0][0], 1.0 - v.tex_coords[0][1]], // First UV channel
78+
// [v.tex_coords[1][0], 1.0 - v.tex_coords[1][1]], // Second UV channel
79+
// ]
80+
// })
81+
.map(|v| v.tex_coords[0])
7882
.collect();
79-
let indices = complex_mesh
83+
let indices: Vec<u32> = complex_mesh
8084
.triangles
8185
.iter()
8286
.flat_map(|strip| strip.iter().rev().copied())
8387
.collect();
88+
let normals = complex_mesh.calculate_normals();
8489

8590
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, positions);
8691
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, tex_coords);
87-
mesh.insert_indices(Indices::U32(indices));
88-
mesh.duplicate_vertices();
89-
mesh.compute_flat_normals();
92+
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals);
93+
mesh.insert_indices(Indices::U32(indices)); // TODO: Colliders need this second call for indices
9094

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

rmesh/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rmesh"
3-
version = "0.3.4"
3+
version = "0.3.5"
44
edition = "2021"
55
license = "MIT OR Apache-2.0"
66
description = "A parser for the rmesh extension"

rmesh/src/lib.rs

+103-3
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ pub struct TriggerBox {
131131
pub name: FixedLengthString,
132132
}
133133

134-
impl CalcBoundBox for SimpleMesh {
134+
impl ExtMesh for SimpleMesh {
135135
fn bounding_box(&self) -> Bounds {
136136
let mut min_x = f32::INFINITY;
137137
let mut min_y = f32::INFINITY;
@@ -158,9 +158,58 @@ impl CalcBoundBox for SimpleMesh {
158158
let max_point = [max_x, max_y, max_z];
159159
Bounds::new(min_point, max_point)
160160
}
161+
162+
fn calculate_normals(&self) -> Vec<[f32; 3]> {
163+
// Initialize vertex normals with zero vectors
164+
let mut vertex_normals = vec![[0.0, 0.0, 0.0]; self.vertices.len()];
165+
166+
// Calculate face normals and accumulate them to vertex normals
167+
for triangle in &self.triangles {
168+
let vertex0 = self.vertices[triangle[0] as usize];
169+
let vertex1 = self.vertices[triangle[1] as usize];
170+
let vertex2 = self.vertices[triangle[2] as usize];
171+
172+
let edge1 = [
173+
vertex1[0] - vertex0[0],
174+
vertex1[1] - vertex0[1],
175+
vertex1[2] - vertex0[2],
176+
];
177+
let edge2 = [
178+
vertex2[0] - vertex0[0],
179+
vertex2[1] - vertex0[1],
180+
vertex2[2] - vertex0[2],
181+
];
182+
183+
let normal = [
184+
edge1[1] * edge2[2] - edge1[2] * edge2[1],
185+
edge1[2] * edge2[0] - edge1[0] * edge2[2],
186+
edge1[0] * edge2[1] - edge1[1] * edge2[0],
187+
];
188+
189+
// Accumulate face normal to the vertices of the triangle
190+
for i in 0..3 {
191+
let vertex_index = triangle[i] as usize;
192+
vertex_normals[vertex_index][0] += normal[0];
193+
vertex_normals[vertex_index][1] += normal[1];
194+
vertex_normals[vertex_index][2] += normal[2];
195+
}
196+
}
197+
198+
// Normalize vertex normals
199+
for normal in &mut vertex_normals {
200+
let length = (normal[0].powi(2) + normal[1].powi(2) + normal[2].powi(2)).sqrt();
201+
if length != 0.0 {
202+
normal[0] /= length;
203+
normal[1] /= length;
204+
normal[2] /= length;
205+
}
206+
}
207+
208+
vertex_normals
209+
}
161210
}
162211

163-
impl CalcBoundBox for ComplexMesh {
212+
impl ExtMesh for ComplexMesh {
164213
fn bounding_box(&self) -> Bounds {
165214
let mut min_x = f32::INFINITY;
166215
let mut min_y = f32::INFINITY;
@@ -187,11 +236,62 @@ impl CalcBoundBox for ComplexMesh {
187236
let max_point = [max_x, max_y, max_z];
188237
Bounds::new(min_point, max_point)
189238
}
239+
240+
fn calculate_normals(&self) -> Vec<[f32; 3]> {
241+
// Initialize vertex normals with zero vectors
242+
let mut vertex_normals = vec![[0.0, 0.0, 0.0]; self.vertices.len()];
243+
244+
// Calculate face normals and accumulate them to vertex normals
245+
for triangle in &self.triangles {
246+
let vertex0 = self.vertices[triangle[0] as usize].position;
247+
let vertex1 = self.vertices[triangle[1] as usize].position;
248+
let vertex2 = self.vertices[triangle[2] as usize].position;
249+
250+
let edge1 = [
251+
vertex1[0] - vertex0[0],
252+
vertex1[1] - vertex0[1],
253+
vertex1[2] - vertex0[2],
254+
];
255+
let edge2 = [
256+
vertex2[0] - vertex0[0],
257+
vertex2[1] - vertex0[1],
258+
vertex2[2] - vertex0[2],
259+
];
260+
261+
let normal = [
262+
edge1[1] * edge2[2] - edge1[2] * edge2[1],
263+
edge1[2] * edge2[0] - edge1[0] * edge2[2],
264+
edge1[0] * edge2[1] - edge1[1] * edge2[0],
265+
];
266+
267+
// Accumulate face normal to the vertices of the triangle
268+
for i in 0..3 {
269+
let vertex_index = triangle[i] as usize;
270+
vertex_normals[vertex_index][0] += normal[0];
271+
vertex_normals[vertex_index][1] += normal[1];
272+
vertex_normals[vertex_index][2] += normal[2];
273+
}
274+
}
275+
276+
// Normalize vertex normals
277+
for normal in &mut vertex_normals {
278+
let length = (normal[0].powi(2) + normal[1].powi(2) + normal[2].powi(2)).sqrt();
279+
if length != 0.0 {
280+
normal[0] /= length;
281+
normal[1] /= length;
282+
normal[2] /= length;
283+
}
284+
}
285+
286+
vertex_normals
287+
}
190288
}
191289

192-
pub trait CalcBoundBox {
290+
pub trait ExtMesh {
193291
/// Used for aabb calc
194292
fn bounding_box(&self) -> Bounds;
293+
/// Calculate normals for the vertices based on the triangle faces.
294+
fn calculate_normals(&self) -> Vec<[f32; 3]>;
195295
}
196296

197297
pub struct Bounds {

0 commit comments

Comments
 (0)