Skip to content

Commit 9e7355d

Browse files
authored
Calculate UVs and Normals in ConvexPolygonMeshBuilder (#23540)
# Objective Fixes #23526 ## Solution - Added UVs to `ConvexPolygonMeshBuilder` - Whilst testing I noticed that normals were also not generated for the mesh so i've added these as well. ## Testing - Added `test_convex_polygon` to bevy_mesh which imitates a different test but for regular polygons. - Added `Extrusion<ConvexPolygon>` to the 3d_shapes example - you can use this example to validate UVs and Normals are working as expected.
1 parent 35ee4bf commit 9e7355d

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

crates/bevy_mesh/src/primitives/dim2.rs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,9 +431,24 @@ impl MeshBuilder for ConvexPolygonMeshBuilder {
431431
let len = self.vertices.len();
432432
let mut indices = Vec::with_capacity((len - 2) * 3);
433433
let mut positions = Vec::with_capacity(len);
434+
let normals = vec![[0.0, 0.0, 1.0]; len];
435+
let mut uvs = Vec::with_capacity(len);
436+
437+
let mut min = Vec2::splat(f32::INFINITY);
438+
let mut max = Vec2::splat(f32::NEG_INFINITY);
439+
440+
for vertex in &self.vertices {
441+
min = min.min(*vertex);
442+
max = max.max(*vertex);
443+
}
444+
445+
let size = (max - min).max(Vec2::splat(f32::EPSILON));
434446

435447
for vertex in &self.vertices {
436448
positions.push([vertex.x, vertex.y, 0.0]);
449+
let uv = (*vertex - min) / size;
450+
// Map each axis independently into [0, 1] over the polygon's AABB.
451+
uvs.push([uv.x, uv.y]);
437452
}
438453
for i in 2..len as u32 {
439454
indices.extend_from_slice(&[0, i - 1, i]);
@@ -443,6 +458,8 @@ impl MeshBuilder for ConvexPolygonMeshBuilder {
443458
RenderAssetUsages::default(),
444459
)
445460
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
461+
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
462+
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
446463
.with_inserted_indices(Indices::U32(indices))
447464
}
448465
}
@@ -1526,7 +1543,11 @@ where
15261543

15271544
#[cfg(test)]
15281545
mod tests {
1529-
use bevy_math::{prelude::Annulus, primitives::RegularPolygon, FloatOrd};
1546+
use bevy_math::{
1547+
prelude::Annulus,
1548+
primitives::{ConvexPolygon, RegularPolygon},
1549+
FloatOrd, Vec2,
1550+
};
15301551
use bevy_platform::collections::HashSet;
15311552

15321553
use crate::{Mesh, MeshBuilder, Meshable, VertexAttributeValues};
@@ -1605,4 +1626,53 @@ mod tests {
16051626

16061627
assert_eq!(&[[0.0, 0.0, 1.0]; 4], &normals[..]);
16071628
}
1629+
1630+
#[test]
1631+
fn test_convex_polygon() {
1632+
let polygon = ConvexPolygon::new(vec![
1633+
Vec2::new(-2.0, -1.0),
1634+
Vec2::new(2.0, -1.0),
1635+
Vec2::new(1.0, 3.0),
1636+
Vec2::new(-1.0, 2.0),
1637+
])
1638+
.unwrap();
1639+
1640+
let mut mesh = Mesh::from(polygon);
1641+
1642+
let Some(VertexAttributeValues::Float32x3(mut positions)) =
1643+
mesh.remove_attribute(Mesh::ATTRIBUTE_POSITION)
1644+
else {
1645+
panic!("Expected positions f32x3");
1646+
};
1647+
let Some(VertexAttributeValues::Float32x2(mut uvs)) =
1648+
mesh.remove_attribute(Mesh::ATTRIBUTE_UV_0)
1649+
else {
1650+
panic!("Expected uvs f32x2");
1651+
};
1652+
let Some(VertexAttributeValues::Float32x3(normals)) =
1653+
mesh.remove_attribute(Mesh::ATTRIBUTE_NORMAL)
1654+
else {
1655+
panic!("Expected normals f32x3");
1656+
};
1657+
1658+
fix_floats(&mut positions);
1659+
fix_floats(&mut uvs);
1660+
1661+
assert_eq!(
1662+
[
1663+
[-2.0, -1.0, 0.0],
1664+
[2.0, -1.0, 0.0],
1665+
[1.0, 3.0, 0.0],
1666+
[-1.0, 2.0, 0.0],
1667+
],
1668+
&positions[..]
1669+
);
1670+
1671+
assert_eq!(
1672+
[[0.0, 0.0], [1.0, 0.0], [0.75, 1.0], [0.25, 0.75]],
1673+
&uvs[..]
1674+
);
1675+
1676+
assert_eq!(&[[0.0, 0.0, 1.0]; 4], &normals[..]);
1677+
}
16081678
}

examples/3d/3d_shapes.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,17 @@ fn setup(
9191
meshes.add(Extrusion::new(Ellipse::default(), 1.)),
9292
meshes.add(Extrusion::new(RegularPolygon::default(), 1.)),
9393
meshes.add(Extrusion::new(Triangle2d::default(), 1.)),
94+
meshes.add(Extrusion::new(
95+
ConvexPolygon::new(vec![
96+
Vec2::new(0.0, 0.8),
97+
Vec2::new(-0.47, 0.25),
98+
Vec2::new(-0.47, -0.65),
99+
Vec2::new(0.47, -0.65),
100+
Vec2::new(0.47, 0.25),
101+
])
102+
.unwrap(),
103+
1.0,
104+
)),
94105
];
95106

96107
let ring_extrusions = [

0 commit comments

Comments
 (0)