renderling/primitive/
cpu.rs1use core::ops::Deref;
4use std::sync::{Arc, Mutex};
5
6use craballoc::value::Hybrid;
7use crabslab::{Array, Id};
8
9use crate::{
10 bvol::BoundingSphere,
11 geometry::{Indices, MorphTargetWeights, MorphTargets, Skin, Vertices},
12 material::Material,
13 primitive::shader::PrimitiveDescriptor,
14 stage::Stage,
15 transform::Transform,
16 types::GpuOnlyArray,
17};
18
19pub struct Primitive {
23 pub(crate) descriptor: Hybrid<PrimitiveDescriptor>,
24
25 vertices: Arc<Mutex<Option<Vertices<GpuOnlyArray>>>>,
26 indices: Arc<Mutex<Option<Indices<GpuOnlyArray>>>>,
27
28 pub(crate) transform: Arc<Mutex<Option<Transform>>>,
29 pub(crate) material: Arc<Mutex<Option<Material>>>,
30 skin: Arc<Mutex<Option<Skin>>>,
31 morph_targets: Arc<Mutex<Option<(MorphTargets, MorphTargetWeights)>>>,
32}
33
34impl Primitive {
35 pub fn new(stage: &Stage) -> Self {
41 let descriptor = stage
42 .geometry
43 .slab_allocator()
44 .new_value(PrimitiveDescriptor::default());
45 let primitive = Primitive {
46 descriptor,
47 vertices: Default::default(),
48 indices: Default::default(),
49 transform: Default::default(),
50 material: Default::default(),
51 skin: Default::default(),
52 morph_targets: Default::default(),
53 }
54 .with_vertices(stage.default_vertices());
55 stage.add_primitive(&primitive);
56 primitive
57 }
58}
59
60impl Clone for Primitive {
61 fn clone(&self) -> Self {
62 Self {
63 descriptor: self.descriptor.clone(),
64 vertices: self.vertices.clone(),
65 indices: self.indices.clone(),
66 transform: self.transform.clone(),
67 material: self.material.clone(),
68 skin: self.skin.clone(),
69 morph_targets: self.morph_targets.clone(),
70 }
71 }
72}
73
74impl Primitive {
76 pub fn set_vertices(&self, vertices: impl Into<Vertices<GpuOnlyArray>>) -> &Self {
78 let vertices = vertices.into();
79 let array = vertices.array();
80 self.descriptor.modify(|d| d.vertices_array = array);
81 *self.vertices.lock().unwrap() = Some(vertices.clone());
82 self
83 }
84
85 pub fn with_vertices(self, vertices: impl Into<Vertices<GpuOnlyArray>>) -> Self {
87 self.set_vertices(vertices);
88 self
89 }
90}
91
92impl Primitive {
94 pub fn set_indices(&self, indices: impl Into<Indices<GpuOnlyArray>>) -> &Self {
96 let indices = indices.into();
97 let array = indices.array();
98 self.descriptor.modify(|d| d.indices_array = array);
99 *self.indices.lock().unwrap() = Some(indices.clone());
100 self
101 }
102
103 pub fn with_indices(self, indices: impl Into<Indices<GpuOnlyArray>>) -> Self {
105 self.set_indices(indices);
106 self
107 }
108
109 pub fn remove_indices(&self) -> &Self {
111 *self.indices.lock().unwrap() = None;
112 self.descriptor.modify(|d| d.indices_array = Array::NONE);
113 self
114 }
115}
116
117impl Primitive {
119 pub fn id(&self) -> Id<PrimitiveDescriptor> {
121 self.descriptor.id()
122 }
123
124 pub fn descriptor(&self) -> PrimitiveDescriptor {
126 self.descriptor.get()
127 }
128
129 pub fn set_bounds(&self, bounds: BoundingSphere) -> &Self {
131 self.descriptor.modify(|d| d.bounds = bounds);
132 self
133 }
134
135 pub fn with_bounds(self, bounds: BoundingSphere) -> Self {
137 self.set_bounds(bounds);
138 self
139 }
140
141 pub fn bounds(&self) -> BoundingSphere {
145 self.descriptor.get().bounds
146 }
147
148 pub fn modify_bounds<T: 'static>(&self, f: impl FnOnce(&mut BoundingSphere) -> T) -> T {
155 self.descriptor.modify(|d| f(&mut d.bounds))
156 }
157
158 pub fn set_visible(&self, visible: bool) -> &Self {
160 self.descriptor.modify(|d| d.visible = visible);
161 self
162 }
163
164 pub fn with_visible(self, visible: bool) -> Self {
166 self.set_visible(visible);
167 self
168 }
169
170 pub fn visible(&self) -> bool {
172 self.descriptor.get().visible
173 }
174
175 pub fn modify_visible<T: 'static>(&self, f: impl FnOnce(&mut bool) -> T) -> T {
182 self.descriptor.modify(|d| f(&mut d.visible))
183 }
184}
185
186impl Primitive {
188 pub fn set_transform(&self, transform: impl Into<Transform>) -> &Self {
194 let transform = transform.into();
195 self.descriptor.modify(|d| d.transform_id = transform.id());
196 *self.transform.lock().unwrap() = Some(transform.clone());
197 self
198 }
199
200 pub fn with_transform(self, transform: impl Into<Transform>) -> Self {
206 self.set_transform(transform);
207 self
208 }
209
210 pub fn transform(&self) -> impl Deref<Target = Option<Transform>> + '_ {
214 self.transform.lock().unwrap()
215 }
216
217 pub fn remove_transform(&self) -> &Self {
221 self.descriptor.modify(|d| d.transform_id = Id::NONE);
222 *self.transform.lock().unwrap() = None;
223 self
224 }
225}
226
227impl Primitive {
229 pub fn set_material(&self, material: impl Into<Material>) -> &Self {
231 let material = material.into();
232 self.descriptor.modify(|d| d.material_id = material.id());
233 *self.material.lock().unwrap() = Some(material);
234 self
235 }
236
237 pub fn with_material(self, material: impl Into<Material>) -> Self {
239 self.set_material(material);
240 self
241 }
242
243 pub fn material(&self) -> impl Deref<Target = Option<Material>> + '_ {
247 self.material.lock().unwrap()
248 }
249
250 pub fn remove_material(&self) -> &Self {
252 self.descriptor.modify(|d| d.material_id = Id::NONE);
253 *self.material.lock().unwrap() = None;
254 self
255 }
256}
257
258impl Primitive {
260 pub fn set_skin(&self, skin: impl Into<Skin>) -> &Self {
262 let skin = skin.into();
263 self.descriptor.modify(|d| d.skin_id = skin.id());
264 *self.skin.lock().unwrap() = Some(skin.clone());
265 self
266 }
267
268 pub fn with_skin(self, skin: impl Into<Skin>) -> Self {
270 self.set_skin(skin);
271 self
272 }
273
274 pub fn skin(&self) -> impl Deref<Target = Option<Skin>> + '_ {
278 self.skin.lock().unwrap()
279 }
280
281 pub fn remove_skin(&self) -> &Self {
283 self.descriptor.modify(|d| d.skin_id = Id::NONE);
284 *self.skin.lock().unwrap() = None;
285 self
286 }
287}
288
289impl Primitive {
291 pub fn set_morph_targets(
293 &self,
294 morph_targets: impl Into<MorphTargets>,
295 weights: impl Into<MorphTargetWeights>,
296 ) -> &Self {
297 let morph_targets = morph_targets.into();
298 let weights = weights.into();
299 self.descriptor.modify(|d| {
300 d.morph_targets = morph_targets.array();
301 d.morph_weights = weights.array();
302 });
303 *self.morph_targets.lock().unwrap() = Some((morph_targets.clone(), weights.clone()));
304 self
305 }
306
307 pub fn with_morph_targets(
309 self,
310 morph_targets: impl Into<MorphTargets>,
311 weights: impl Into<MorphTargetWeights>,
312 ) -> Self {
313 self.set_morph_targets(morph_targets, weights);
314 self
315 }
316
317 pub fn morph_targets(
321 &self,
322 ) -> impl Deref<Target = Option<(MorphTargets, MorphTargetWeights)>> + '_ {
323 self.morph_targets.lock().unwrap()
324 }
325
326 pub fn remove_morph_targets(&self) -> &Self {
328 self.descriptor.modify(|d| {
329 d.morph_targets = Array::NONE;
330 d.morph_weights = Array::NONE;
331 });
332 *self.morph_targets.lock().unwrap() = None;
333 self
334 }
335}