dynamis_world/world/
shape.rs1use super::World;
2use crate::world::shape_pool::{ShapePool, height_field_triangles};
3use dynamis_layout::{SHAPE_HEIGHTFIELD, SHAPE_HULL, SHAPE_MESH};
4use dynamis_mesh::convex_hull_mesh;
5use dynamis_model::{MAX_COLLIDERS_PER_BODY, Shape, ShapeSourceHandle};
6
7pub(crate) struct Shapes {
8 pub(crate) pool: ShapePool,
9 pub(crate) dirty: bool,
10}
11
12impl Shapes {
13 pub(crate) fn new() -> Self {
14 Self {
15 pool: ShapePool::new(),
16 dirty: false,
17 }
18 }
19}
20
21impl World {
22 pub fn add_hull(&mut self, vertices: &[[f32; 3]], triangles: &[[u32; 3]]) -> ShapeSourceHandle {
23 self.allocate_shape(SHAPE_HULL, vertices, triangles.to_vec())
24 }
25
26 pub fn add_mesh(&mut self, vertices: &[[f32; 3]], triangles: &[[u32; 3]]) -> ShapeSourceHandle {
27 self.allocate_shape(SHAPE_MESH, vertices, triangles.to_vec())
28 }
29
30 pub fn add_decomposed_mesh(
31 &mut self,
32 vertices: &[[f32; 3]],
33 triangles: &[[u32; 3]],
34 settings: dynamis_mesh::HullDecomposeSettings,
35 ) -> Vec<ShapeSourceHandle> {
36 assert!(
37 settings.max_parts as usize <= MAX_COLLIDERS_PER_BODY,
38 "decomposition part limit must fit within one body"
39 );
40 let parts = dynamis_mesh::decompose_mesh(vertices, triangles, &settings);
41 parts
42 .iter()
43 .map(|part| self.add_hull(&part.vertices, &part.triangles))
44 .collect()
45 }
46
47 pub fn add_hull_from_mesh(
48 &mut self,
49 vertices: &[[f32; 3]],
50 triangles: &[[u32; 3]],
51 ) -> ShapeSourceHandle {
52 let (hull_vertices, hull_triangles) = convex_hull_mesh(vertices, triangles);
53 self.allocate_shape(SHAPE_HULL, &hull_vertices, hull_triangles)
54 }
55
56 pub fn add_height_field(
57 &mut self,
58 rows: u32,
59 cols: u32,
60 heights: &[f32],
61 cell_size: [f32; 2],
62 ) -> ShapeSourceHandle {
63 let (vertices, triangles) = height_field_triangles(rows, cols, heights, cell_size);
64 self.allocate_shape(SHAPE_HEIGHTFIELD, &vertices, triangles)
65 }
66
67 pub fn remove_shape(&mut self, handle: ShapeSourceHandle) {
68 self.shapes.pool.remove(handle);
69 self.shapes.dirty = true;
70 }
71
72 pub fn update_mesh(
73 &mut self,
74 handle: ShapeSourceHandle,
75 vertices: &[[f32; 3]],
76 triangles: &[[u32; 3]],
77 ) {
78 self.shapes.pool.update_mesh(handle, vertices, triangles);
79 self.shapes.pool.upload_update(
80 self.backend.gpu.queue(),
81 &self.backend.buffers.shapes.sources,
82 &self.backend.buffers.shapes.vertices,
83 &self.backend.buffers.shapes.triangles,
84 &self.backend.buffers.shapes.nodes,
85 handle,
86 );
87 }
88
89 pub fn update_height_field(
90 &mut self,
91 handle: ShapeSourceHandle,
92 rows: u32,
93 cols: u32,
94 heights: &[f32],
95 cell_size: [f32; 2],
96 ) {
97 let (vertices, triangles) = height_field_triangles(rows, cols, heights, cell_size);
98 self.update_mesh(handle, &vertices, &triangles);
99 }
100
101 fn allocate_shape(
102 &mut self,
103 kind: u32,
104 vertices: &[[f32; 3]],
105 triangles: Vec<[u32; 3]>,
106 ) -> ShapeSourceHandle {
107 let handle = self.shapes.pool.allocate(kind, vertices, &triangles);
108 self.shapes.dirty = true;
109 handle
110 }
111
112 pub(super) fn shape_bounds(&self, shape: &Shape) -> Option<([f32; 3], [f32; 3])> {
113 match shape {
114 Shape::Hull(handle) | Shape::Mesh(handle) | Shape::HeightField(handle) => {
115 Some(self.shapes.pool.record(*handle).bounds)
116 }
117 _ => None,
118 }
119 }
120}