bevy_mesh/primitives/dim3/
triangle3d.rs1use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology};
2use bevy_asset::RenderAssetUsages;
3use bevy_math::{primitives::Triangle3d, Vec3};
4use bevy_reflect::prelude::*;
5
6#[derive(Clone, Copy, Debug, Default, Reflect)]
8#[reflect(Default, Debug, Clone)]
9pub struct Triangle3dMeshBuilder {
10 triangle: Triangle3d,
11}
12
13impl MeshBuilder for Triangle3dMeshBuilder {
14 fn build(&self) -> Mesh {
15 let positions: Vec<_> = self.triangle.vertices.into();
16 let uvs: Vec<_> = uv_coords(&self.triangle).into();
17
18 let normal: Vec3 = normal_vec(&self.triangle);
20 let normals = vec![normal; 3];
21
22 let indices = Indices::U32(vec![0, 1, 2]);
23
24 Mesh::new(
25 PrimitiveTopology::TriangleList,
26 RenderAssetUsages::default(),
27 )
28 .with_inserted_indices(indices)
29 .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
30 .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
31 .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
32 }
33}
34
35impl Meshable for Triangle3d {
36 type Output = Triangle3dMeshBuilder;
37
38 fn mesh(&self) -> Self::Output {
39 Triangle3dMeshBuilder { triangle: *self }
40 }
41}
42
43#[inline]
45pub(crate) fn normal_vec(triangle: &Triangle3d) -> Vec3 {
46 triangle.normal().map_or(Vec3::ZERO, Into::into)
47}
48
49#[inline]
51pub(crate) fn uv_coords(triangle: &Triangle3d) -> [[f32; 2]; 3] {
52 let [a, b, c] = triangle.vertices;
53
54 let main_length = a.distance(b);
55 let Some(x) = (b - a).try_normalize() else {
56 return [[0., 0.], [1., 0.], [0., 1.]];
57 };
58 let y = c - a;
59
60 let y_proj = y.project_onto_normalized(x);
65
66 let offset = y_proj.dot(x) / main_length;
69
70 if offset < 0. {
72 let total_length = 1. - offset;
73 let a_uv = [offset.abs() / total_length, 0.];
74 let b_uv = [1., 0.];
75 let c_uv = [0., 1.];
76
77 [a_uv, b_uv, c_uv]
78 }
79 else if offset > 1. {
81 let a_uv = [0., 0.];
82 let b_uv = [1. / offset, 0.];
83 let c_uv = [1., 1.];
84
85 [a_uv, b_uv, c_uv]
86 }
87 else {
89 let a_uv = [0., 0.];
90 let b_uv = [1., 0.];
91 let c_uv = [offset, 1.];
92
93 [a_uv, b_uv, c_uv]
94 }
95}
96
97impl From<Triangle3d> for Mesh {
98 fn from(triangle: Triangle3d) -> Self {
99 triangle.mesh().build()
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::uv_coords;
106 use bevy_math::primitives::Triangle3d;
107
108 #[test]
109 fn uv_test() {
110 use bevy_math::vec3;
111 let mut triangle = Triangle3d::new(vec3(0., 0., 0.), vec3(2., 0., 0.), vec3(-1., 1., 0.));
112
113 let [a_uv, b_uv, c_uv] = uv_coords(&triangle);
114 assert_eq!(a_uv, [1. / 3., 0.]);
115 assert_eq!(b_uv, [1., 0.]);
116 assert_eq!(c_uv, [0., 1.]);
117
118 triangle.vertices[2] = vec3(3., 1., 0.);
119 let [a_uv, b_uv, c_uv] = uv_coords(&triangle);
120 assert_eq!(a_uv, [0., 0.]);
121 assert_eq!(b_uv, [2. / 3., 0.]);
122 assert_eq!(c_uv, [1., 1.]);
123
124 triangle.vertices[2] = vec3(2., 1., 0.);
125 let [a_uv, b_uv, c_uv] = uv_coords(&triangle);
126 assert_eq!(a_uv, [0., 0.]);
127 assert_eq!(b_uv, [1., 0.]);
128 assert_eq!(c_uv, [1., 1.]);
129 }
130}