1use std::sync::{Arc, Mutex};
3
4use craballoc::{
5 runtime::{IsRuntime, WgpuRuntime},
6 slab::{SlabAllocator, SlabBuffer},
7 value::{GpuArray, Hybrid, HybridArray, IsContainer},
8};
9use crabslab::{Array, Id};
10use glam::{Mat4, UVec2, Vec4};
11
12use crate::{
13 camera::Camera,
14 geometry::{
15 shader::{GeometryDescriptor, SkinDescriptor},
16 MorphTarget, Vertex,
17 },
18 transform::{shader::TransformDescriptor, NestedTransform, Transform},
19 types::{GpuCpuArray, GpuOnlyArray},
20};
21
22pub struct Vertices<Ct: IsContainer = GpuCpuArray> {
39 inner: Ct::Container<Vertex>,
40}
41
42impl<Ct> Clone for Vertices<Ct>
43where
44 Ct: IsContainer,
45 Ct::Container<Vertex>: Clone,
46{
47 fn clone(&self) -> Self {
48 Self {
49 inner: self.inner.clone(),
50 }
51 }
52}
53
54impl<Ct> std::fmt::Debug for Vertices<Ct>
55where
56 Ct: IsContainer<Pointer<Vertex> = Array<Vertex>>,
57{
58 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
59 f.debug_struct("Vertices")
60 .field("array", &Ct::get_pointer(&self.inner))
61 .finish()
62 }
63}
64
65impl From<Vertices> for Vertices<GpuOnlyArray> {
66 fn from(value: Vertices) -> Self {
67 value.into_gpu_only()
68 }
69}
70
71impl From<&Vertices> for Vertices<GpuOnlyArray> {
72 fn from(value: &Vertices) -> Self {
73 value.clone().into_gpu_only()
74 }
75}
76
77impl From<&Vertices<GpuOnlyArray>> for Vertices<GpuOnlyArray> {
78 fn from(value: &Vertices<GpuOnlyArray>) -> Self {
79 value.clone()
80 }
81}
82
83impl Vertices {
84 pub(crate) fn new(
89 slab: &SlabAllocator<WgpuRuntime>,
90 vertices: impl IntoIterator<Item = Vertex>,
91 ) -> Self {
92 Vertices {
93 inner: slab.new_array(vertices),
94 }
95 }
96
97 pub fn into_gpu_only(self) -> Vertices<GpuOnlyArray> {
102 Vertices {
103 inner: self.inner.into_gpu_only(),
104 }
105 }
106
107 pub fn get_vertex(&self, index: usize) -> Option<Vertex> {
109 self.inner.get(index)
110 }
111
112 pub fn get_vec(&self) -> Vec<Vertex> {
114 self.inner.get_vec()
115 }
116
117 pub fn modify_vertex<T: 'static>(
119 &self,
120 index: usize,
121 f: impl FnOnce(&mut Vertex) -> T,
122 ) -> Option<T> {
123 self.inner.modify(index, f)
124 }
125}
126
127impl<T> Vertices<T>
128where
129 T: IsContainer<Pointer<Vertex> = Array<Vertex>>,
130{
131 pub fn array(&self) -> Array<Vertex> {
133 T::get_pointer(&self.inner)
134 }
135}
136
137impl Vertices<GpuOnlyArray> {
138 pub fn set_vertex(&self, index: usize, value: &Vertex) {
141 self.inner.set_item(index, value)
142 }
143}
144
145pub struct Indices<Ct: IsContainer = GpuCpuArray> {
149 inner: Ct::Container<u32>,
150}
151
152impl<Ct> std::fmt::Debug for Indices<Ct>
153where
154 Ct: IsContainer<Pointer<u32> = Array<u32>>,
155{
156 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
157 f.debug_struct("Indices")
158 .field("array", &Ct::get_pointer(&self.inner))
159 .finish()
160 }
161}
162
163impl<Ct> Clone for Indices<Ct>
164where
165 Ct: IsContainer,
166 Ct::Container<u32>: Clone,
167{
168 fn clone(&self) -> Self {
169 Self {
170 inner: self.inner.clone(),
171 }
172 }
173}
174
175impl From<Indices> for Indices<GpuOnlyArray> {
176 fn from(value: Indices) -> Self {
177 value.into_gpu_only()
178 }
179}
180
181impl From<&Indices> for Indices<GpuOnlyArray> {
182 fn from(value: &Indices) -> Self {
183 value.clone().into_gpu_only()
184 }
185}
186
187impl From<&Indices<GpuOnlyArray>> for Indices<GpuOnlyArray> {
188 fn from(value: &Indices<GpuOnlyArray>) -> Self {
189 value.clone()
190 }
191}
192
193impl<T> Indices<T>
194where
195 T: IsContainer<Pointer<u32> = Array<u32>>,
196{
197 pub fn array(&self) -> Array<u32> {
199 T::get_pointer(&self.inner)
200 }
201}
202
203impl Indices {
204 pub fn new(geometry: &Geometry, indices: impl IntoIterator<Item = u32>) -> Self {
209 Indices {
210 inner: geometry.slab.new_array(indices),
211 }
212 }
213
214 pub fn into_gpu_only(self) -> Indices<GpuOnlyArray> {
216 Indices {
217 inner: self.inner.into_gpu_only(),
218 }
219 }
220}
221
222#[derive(Clone)]
224pub struct MorphTargets {
225 _targets: Arc<Vec<GpuArray<MorphTarget>>>,
227 arrays: HybridArray<Array<MorphTarget>>,
228}
229
230impl From<&MorphTargets> for MorphTargets {
231 fn from(value: &MorphTargets) -> Self {
232 value.clone()
233 }
234}
235
236impl std::fmt::Debug for MorphTargets {
237 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
238 f.debug_struct("MorphTargets")
239 .field("arrays", &self.arrays)
240 .field("targets", &"...")
241 .finish()
242 }
243}
244
245impl MorphTargets {
246 pub(crate) fn new(
247 slab: &SlabAllocator<impl IsRuntime>,
248 morph_targets: impl IntoIterator<Item = impl IntoIterator<Item = MorphTarget>>,
249 ) -> Self {
250 let targets = morph_targets
251 .into_iter()
252 .map(|verts| slab.new_array(verts).into_gpu_only())
253 .collect::<Vec<_>>();
254 let arrays = slab.new_array(targets.iter().map(|ts| ts.array()));
255 Self {
256 _targets: targets.into(),
257 arrays,
258 }
259 }
260 pub fn array(&self) -> Array<Array<MorphTarget>> {
262 self.arrays.array()
263 }
264}
265
266#[derive(Clone, Debug)]
268pub struct MorphTargetWeights {
269 inner: HybridArray<f32>,
270}
271
272impl From<&MorphTargetWeights> for MorphTargetWeights {
273 fn from(value: &MorphTargetWeights) -> Self {
274 value.clone()
275 }
276}
277
278impl MorphTargetWeights {
279 pub(crate) fn new(
280 slab: &SlabAllocator<impl IsRuntime>,
281 data: impl IntoIterator<Item = f32>,
282 ) -> Self {
283 Self {
284 inner: slab.new_array(data),
285 }
286 }
287
288 pub fn array(&self) -> Array<f32> {
290 self.inner.array()
291 }
292
293 pub fn get_item(&self, index: usize) -> Option<f32> {
295 self.inner.get(index)
296 }
297
298 pub fn set_item(&self, index: usize, weight: f32) {
300 self.inner.set_item(index, weight);
301 }
302}
303
304#[derive(Clone)]
306pub struct Geometry {
307 slab: SlabAllocator<WgpuRuntime>,
308 descriptor: Hybrid<GeometryDescriptor>,
309 default_vertices: Vertices,
311 camera: Arc<Mutex<Option<Camera>>>,
316}
317
318impl AsRef<WgpuRuntime> for Geometry {
319 fn as_ref(&self) -> &WgpuRuntime {
320 self.slab.runtime()
321 }
322}
323
324impl AsRef<SlabAllocator<WgpuRuntime>> for Geometry {
325 fn as_ref(&self) -> &SlabAllocator<WgpuRuntime> {
326 &self.slab
327 }
328}
329
330impl Geometry {
331 pub fn new(runtime: impl AsRef<WgpuRuntime>, resolution: UVec2, atlas_size: UVec2) -> Self {
332 let runtime = runtime.as_ref();
333 let slab = SlabAllocator::new(runtime, "geometry", wgpu::BufferUsages::empty());
334 let descriptor = slab.new_value(GeometryDescriptor {
335 atlas_size,
336 resolution,
337 ..Default::default()
338 });
339 let default_vertices = Vertices::new(
340 &slab,
341 crate::math::unit_cube().into_iter().map(|(p, n)| {
342 Vertex::default()
343 .with_position(p)
344 .with_normal(n)
345 .with_color(Vec4::ONE)
346 }),
347 );
348 Self {
349 slab,
350 descriptor,
351 default_vertices,
352 camera: Default::default(),
353 }
354 }
355
356 pub fn runtime(&self) -> &WgpuRuntime {
357 self.as_ref()
358 }
359
360 pub fn slab_allocator(&self) -> &SlabAllocator<WgpuRuntime> {
361 self.as_ref()
362 }
363
364 pub fn descriptor(&self) -> &Hybrid<GeometryDescriptor> {
365 &self.descriptor
366 }
367
368 pub fn default_vertices(&self) -> &Vertices {
370 &self.default_vertices
371 }
372
373 #[must_use]
374 pub fn commit(&self) -> SlabBuffer<wgpu::Buffer> {
375 self.slab.commit()
376 }
377
378 pub fn new_camera(&self) -> Camera {
382 let c = Camera::new(&self.slab);
383 if self.descriptor.get().camera_id.is_none() {
384 self.use_camera(&c);
385 }
386 c
387 }
388
389 pub fn use_camera(&self, camera: &Camera) {
391 let id = camera.id();
392 log::info!("using camera: {id:?}");
393 self.descriptor.modify(|cfg| cfg.camera_id = id);
395 *self.camera.lock().unwrap() = Some(camera.clone());
396 }
397
398 pub fn new_transform(&self) -> Transform {
400 Transform::new(&self.slab)
401 }
402
403 pub fn new_vertices(&self, vertices: impl IntoIterator<Item = Vertex>) -> Vertices {
405 Vertices::new(self.slab_allocator(), vertices)
406 }
407
408 pub fn new_indices(&self, indices: impl IntoIterator<Item = u32>) -> Indices {
410 Indices::new(self, indices)
411 }
412
413 pub fn new_morph_targets(
415 &self,
416 data: impl IntoIterator<Item = impl IntoIterator<Item = MorphTarget>>,
417 ) -> MorphTargets {
418 MorphTargets::new(&self.slab, data)
419 }
420
421 pub fn new_morph_target_weights(
423 &self,
424 data: impl IntoIterator<Item = f32>,
425 ) -> MorphTargetWeights {
426 MorphTargetWeights::new(&self.slab, data)
427 }
428
429 pub fn new_matrices(&self, data: impl IntoIterator<Item = Mat4>) -> HybridArray<Mat4> {
431 self.slab.new_array(data)
432 }
433
434 pub fn new_skin(
435 &self,
436 joints: impl IntoIterator<Item = impl Into<SkinJoint>>,
437 inverse_bind_matrices: impl IntoIterator<Item = impl Into<Mat4>>,
438 ) -> Skin {
439 Skin::new(self.slab_allocator(), joints, inverse_bind_matrices)
440 }
441}
442
443#[derive(Clone)]
448pub struct Skin {
449 descriptor: Hybrid<SkinDescriptor>,
450 joints: HybridArray<Id<TransformDescriptor>>,
451 _skin_joints: Arc<Mutex<Vec<SkinJoint>>>,
453 _inverse_bind_matrices: Arc<Mutex<Option<GpuArray<Mat4>>>>,
458}
459
460impl From<&Skin> for Skin {
461 fn from(value: &Skin) -> Self {
462 value.clone()
463 }
464}
465
466impl core::fmt::Debug for Skin {
467 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
468 f.debug_struct("Skin")
469 .field("descriptor", &self.descriptor)
470 .field("joints", &self.joints)
471 .field("joint_transforms", &"...")
472 .field("inverse_bind_matrices", &"...")
473 .finish()
474 }
475}
476
477impl Skin {
478 pub fn new(
480 slab: &SlabAllocator<impl IsRuntime>,
481 joints: impl IntoIterator<Item = impl Into<SkinJoint>>,
482 inverse_bind_matrices: impl IntoIterator<Item = impl Into<Mat4>>,
483 ) -> Self {
484 let descriptor = slab.new_value(SkinDescriptor::default());
485 let skin_joints = joints.into_iter().map(|t| t.into()).collect::<Vec<_>>();
486 let joints = skin_joints.iter().map(|sj| sj.0.id()).collect::<Vec<_>>();
487 let inverse_bind_matrices = inverse_bind_matrices
488 .into_iter()
489 .map(|m| m.into())
490 .collect::<Vec<_>>();
491 let inverse_bind_matrices = if inverse_bind_matrices.is_empty() {
492 None
493 } else {
494 Some(slab.new_array(inverse_bind_matrices).into_gpu_only())
495 };
496
497 Skin {
498 descriptor,
499 joints: slab.new_array(joints),
500 _skin_joints: Arc::new(Mutex::new(skin_joints)),
502 _inverse_bind_matrices: Arc::new(Mutex::new(inverse_bind_matrices)),
503 }
504 }
505
506 pub fn id(&self) -> Id<SkinDescriptor> {
508 self.descriptor.id()
509 }
510
511 pub fn descriptor(&self) -> SkinDescriptor {
513 self.descriptor.get()
514 }
515}
516
517pub struct SkinJoint(pub(crate) Transform);
526
527impl From<Transform> for SkinJoint {
528 fn from(transform: Transform) -> Self {
529 SkinJoint(transform)
530 }
531}
532
533impl From<&Transform> for SkinJoint {
534 fn from(transform: &Transform) -> Self {
535 transform.clone().into()
536 }
537}
538
539impl From<NestedTransform> for SkinJoint {
540 fn from(value: NestedTransform) -> Self {
541 SkinJoint(value.global_transform)
542 }
543}
544
545impl From<&NestedTransform> for SkinJoint {
546 fn from(value: &NestedTransform) -> Self {
547 value.clone().into()
548 }
549}