mod3d_base/example_objects/
tetrahedron.rs

1//a Documentation
2/*!
3
4This provides a function to create [ExampleVertices] object that is a triangle of a specified size at z=0
5
6 */
7
8//a Imports
9use super::ExampleVertices;
10use crate::{
11    BufferElementType, Mesh, Primitive, PrimitiveType, Renderable, ShortIndex, VertexAttr,
12    VertexDesc,
13};
14
15/// Add new position, normal and indices views to an [ExampleVertices]
16/// for a tetrahedron with base at z=0 and tip at (0, 0, size)
17///
18/// The bottom plane is reflectionallty symmetric about the X axis
19///
20/// This has four vertices with a normal at each that is directed away
21/// from the centroid
22///
23/// The height is sqrt(2)/sqrt(3) * side length
24/// The centroid is 1/4 of the way up = 1/sqrt(24)
25/// sqrt(1-centroid^2) = sqrt(23/24)
26///
27/// Each equilateral triangle face has three sides of length size
28///
29/// The height of the triangles is size * sqrt(3)/2
30/// The centroid of these triangles is at 1/3 of the height
31///
32/// The X tip (Y=0, Z=0) is then at 2/3 * sqrt(3)/2 * size = size / sqrt(3)
33/// The other tips at Z=0 are then at
34///  X = -1/3 * sqrt(3)/2 * size = -size / (2*sqrt(3))
35///  Y = +- size/2
36pub fn new<R: Renderable>(eg: &mut ExampleVertices<R>, size: f32)
37where
38    <R as Renderable>::Descriptor: Unpin,
39{
40    let height = (2.0_f32 / 3.0).sqrt();
41    let centroid = height / 4.0;
42    let r3_2 = (3.0_f32).sqrt() * 0.5;
43    let s = 1.0 / (3.0_f32).sqrt();
44    let x = (23.0_f32 / 24.0).sqrt();
45    let vertex_data = [
46        size * 2.0 * s,
47        0.,
48        0.,
49        x,
50        0.,
51        -centroid,
52        -size * s,
53        size * 0.5,
54        0.,
55        -x * 0.5,
56        x * r3_2,
57        -centroid,
58        -size * s,
59        -size * 0.5,
60        0.,
61        -x * 0.5,
62        -x * r3_2,
63        -centroid,
64        0.,
65        0.,
66        size * height,
67        0.,
68        0.,
69        1.,
70    ];
71    let index_data = [0u8, 1, 2, 3, 0, 1];
72
73    let data_indices = eg.push_byte_buffer(Box::new(index_data));
74    let data_vertices = eg.push_byte_buffer(Box::new(vertex_data));
75
76    let indices = eg.push_index_accessor(data_indices, 6, BufferElementType::UInt8, 0);
77    let desc = eg.push_descriptor(data_vertices, 0, 0, 0); // Use all the buffer, and stride used to be 6*4
78    let normals = eg.push_data_accessor(
79        desc,
80        VertexDesc::vec(VertexAttr::Normal, BufferElementType::Float32, 3, 3 * 4),
81    );
82    let vertices = eg.push_data_accessor(
83        desc,
84        VertexDesc::vec(VertexAttr::Position, BufferElementType::Float32, 3, 0),
85    );
86
87    // Create set of data (indices, vertex data) to by subset into by the meshes and their primitives
88    eg.push_vertices(Some(indices), vertices, &[normals]);
89}
90
91/// Create a mesh for the tetrahedron given the vertices index and
92/// material index within a parent model3d::Object
93///
94/// The object should have had the vertices for the tetrahedron (created
95/// with new() above) added to it (using a parent [ExampleVertices])
96pub fn mesh(v_id: ShortIndex, m_id: ShortIndex) -> Mesh {
97    let mut mesh = Mesh::default();
98    mesh.add_primitive(Primitive::new(
99        PrimitiveType::TriangleStrip,
100        v_id,
101        0,
102        6,
103        m_id,
104    ));
105    mesh
106}