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(
90 slab: &SlabAllocator<WgpuRuntime>,
91 vertices: impl IntoIterator<Item = Vertex>,
92 ) -> Self {
93 Vertices {
94 inner: slab.new_array(vertices),
95 }
96 }
97
98 pub fn into_gpu_only(self) -> Vertices<GpuOnlyArray> {
103 Vertices {
104 inner: self.inner.into_gpu_only(),
105 }
106 }
107
108 pub fn get_vertex(&self, index: usize) -> Option<Vertex> {
110 self.inner.get(index)
111 }
112
113 pub fn get_vec(&self) -> Vec<Vertex> {
115 self.inner.get_vec()
116 }
117
118 pub fn modify_vertex<T: 'static>(
120 &self,
121 index: usize,
122 f: impl FnOnce(&mut Vertex) -> T,
123 ) -> Option<T> {
124 self.inner.modify(index, f)
125 }
126}
127
128impl<T> Vertices<T>
129where
130 T: IsContainer<Pointer<Vertex> = Array<Vertex>>,
131{
132 pub fn array(&self) -> Array<Vertex> {
134 T::get_pointer(&self.inner)
135 }
136}
137
138impl Vertices<GpuOnlyArray> {
139 pub fn set_vertex(&self, index: usize, value: &Vertex) {
142 self.inner.set_item(index, value)
143 }
144}
145
146pub struct Indices<Ct: IsContainer = GpuCpuArray> {
150 inner: Ct::Container<u32>,
151}
152
153impl<Ct> std::fmt::Debug for Indices<Ct>
154where
155 Ct: IsContainer<Pointer<u32> = Array<u32>>,
156{
157 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
158 f.debug_struct("Indices")
159 .field("array", &Ct::get_pointer(&self.inner))
160 .finish()
161 }
162}
163
164impl<Ct> Clone for Indices<Ct>
165where
166 Ct: IsContainer,
167 Ct::Container<u32>: Clone,
168{
169 fn clone(&self) -> Self {
170 Self {
171 inner: self.inner.clone(),
172 }
173 }
174}
175
176impl From<Indices> for Indices<GpuOnlyArray> {
177 fn from(value: Indices) -> Self {
178 value.into_gpu_only()
179 }
180}
181
182impl From<&Indices> for Indices<GpuOnlyArray> {
183 fn from(value: &Indices) -> Self {
184 value.clone().into_gpu_only()
185 }
186}
187
188impl From<&Indices<GpuOnlyArray>> for Indices<GpuOnlyArray> {
189 fn from(value: &Indices<GpuOnlyArray>) -> Self {
190 value.clone()
191 }
192}
193
194impl<T> Indices<T>
195where
196 T: IsContainer<Pointer<u32> = Array<u32>>,
197{
198 pub fn array(&self) -> Array<u32> {
200 T::get_pointer(&self.inner)
201 }
202}
203
204impl Indices {
205 pub fn new(geometry: &Geometry, indices: impl IntoIterator<Item = u32>) -> Self {
211 Indices {
212 inner: geometry.slab.new_array(indices),
213 }
214 }
215
216 pub fn into_gpu_only(self) -> Indices<GpuOnlyArray> {
218 Indices {
219 inner: self.inner.into_gpu_only(),
220 }
221 }
222}
223
224#[derive(Clone)]
226pub struct MorphTargets {
227 _targets: Arc<Vec<GpuArray<MorphTarget>>>,
229 arrays: HybridArray<Array<MorphTarget>>,
230}
231
232impl From<&MorphTargets> for MorphTargets {
233 fn from(value: &MorphTargets) -> Self {
234 value.clone()
235 }
236}
237
238impl std::fmt::Debug for MorphTargets {
239 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
240 f.debug_struct("MorphTargets")
241 .field("arrays", &self.arrays)
242 .field("targets", &"...")
243 .finish()
244 }
245}
246
247impl MorphTargets {
248 pub(crate) fn new(
249 slab: &SlabAllocator<impl IsRuntime>,
250 morph_targets: impl IntoIterator<Item = impl IntoIterator<Item = MorphTarget>>,
251 ) -> Self {
252 let targets = morph_targets
253 .into_iter()
254 .map(|verts| slab.new_array(verts).into_gpu_only())
255 .collect::<Vec<_>>();
256 let arrays = slab.new_array(targets.iter().map(|ts| ts.array()));
257 Self {
258 _targets: targets.into(),
259 arrays,
260 }
261 }
262 pub fn array(&self) -> Array<Array<MorphTarget>> {
264 self.arrays.array()
265 }
266}
267
268#[derive(Clone, Debug)]
270pub struct MorphTargetWeights {
271 inner: HybridArray<f32>,
272}
273
274impl From<&MorphTargetWeights> for MorphTargetWeights {
275 fn from(value: &MorphTargetWeights) -> Self {
276 value.clone()
277 }
278}
279
280impl MorphTargetWeights {
281 pub(crate) fn new(
282 slab: &SlabAllocator<impl IsRuntime>,
283 data: impl IntoIterator<Item = f32>,
284 ) -> Self {
285 Self {
286 inner: slab.new_array(data),
287 }
288 }
289
290 pub fn array(&self) -> Array<f32> {
293 self.inner.array()
294 }
295
296 pub fn get_item(&self, index: usize) -> Option<f32> {
298 self.inner.get(index)
299 }
300
301 pub fn set_item(&self, index: usize, weight: f32) {
303 self.inner.set_item(index, weight);
304 }
305}
306
307#[derive(Clone)]
309pub struct Geometry {
310 slab: SlabAllocator<WgpuRuntime>,
311 descriptor: Hybrid<GeometryDescriptor>,
312 default_vertices: Vertices,
314 camera: Arc<Mutex<Option<Camera>>>,
319}
320
321impl AsRef<WgpuRuntime> for Geometry {
322 fn as_ref(&self) -> &WgpuRuntime {
323 self.slab.runtime()
324 }
325}
326
327impl AsRef<SlabAllocator<WgpuRuntime>> for Geometry {
328 fn as_ref(&self) -> &SlabAllocator<WgpuRuntime> {
329 &self.slab
330 }
331}
332
333impl Geometry {
334 pub fn new(runtime: impl AsRef<WgpuRuntime>, resolution: UVec2, atlas_size: UVec2) -> Self {
335 let runtime = runtime.as_ref();
336 let slab = SlabAllocator::new(runtime, "geometry", wgpu::BufferUsages::empty());
337 let descriptor = slab.new_value(GeometryDescriptor {
338 atlas_size,
339 resolution,
340 ..Default::default()
341 });
342 let default_vertices = Vertices::new(
343 &slab,
344 crate::math::unit_cube().into_iter().map(|(p, n)| {
345 Vertex::default()
346 .with_position(p)
347 .with_normal(n)
348 .with_color(Vec4::ONE)
349 }),
350 );
351 Self {
352 slab,
353 descriptor,
354 default_vertices,
355 camera: Default::default(),
356 }
357 }
358
359 pub fn runtime(&self) -> &WgpuRuntime {
360 self.as_ref()
361 }
362
363 pub fn slab_allocator(&self) -> &SlabAllocator<WgpuRuntime> {
364 self.as_ref()
365 }
366
367 pub fn descriptor(&self) -> &Hybrid<GeometryDescriptor> {
368 &self.descriptor
369 }
370
371 pub fn default_vertices(&self) -> &Vertices {
373 &self.default_vertices
374 }
375
376 #[must_use]
377 pub fn commit(&self) -> SlabBuffer<wgpu::Buffer> {
378 self.slab.commit()
379 }
380
381 pub fn new_camera(&self) -> Camera {
385 let c = Camera::new(&self.slab);
386 if self.descriptor.get().camera_id.is_none() {
387 self.use_camera(&c);
388 }
389 c
390 }
391
392 pub fn use_camera(&self, camera: &Camera) {
394 let id = camera.id();
395 log::info!("using camera: {id:?}");
396 self.descriptor.modify(|cfg| cfg.camera_id = id);
399 *self.camera.lock().expect("geometry camera lock") = Some(camera.clone());
400 }
401
402 pub fn new_transform(&self) -> Transform {
404 Transform::new(&self.slab)
405 }
406
407 pub fn new_vertices(&self, vertices: impl IntoIterator<Item = Vertex>) -> Vertices {
409 Vertices::new(self.slab_allocator(), vertices)
410 }
411
412 pub fn new_indices(&self, indices: impl IntoIterator<Item = u32>) -> Indices {
414 Indices::new(self, indices)
415 }
416
417 pub fn new_morph_targets(
419 &self,
420 data: impl IntoIterator<Item = impl IntoIterator<Item = MorphTarget>>,
421 ) -> MorphTargets {
422 MorphTargets::new(&self.slab, data)
423 }
424
425 pub fn new_morph_target_weights(
427 &self,
428 data: impl IntoIterator<Item = f32>,
429 ) -> MorphTargetWeights {
430 MorphTargetWeights::new(&self.slab, data)
431 }
432
433 pub fn new_matrices(&self, data: impl IntoIterator<Item = Mat4>) -> HybridArray<Mat4> {
435 self.slab.new_array(data)
436 }
437
438 pub fn new_skin(
439 &self,
440 joints: impl IntoIterator<Item = impl Into<SkinJoint>>,
441 inverse_bind_matrices: impl IntoIterator<Item = impl Into<Mat4>>,
442 ) -> Skin {
443 Skin::new(self.slab_allocator(), joints, inverse_bind_matrices)
444 }
445}
446
447#[derive(Clone)]
452pub struct Skin {
453 descriptor: Hybrid<SkinDescriptor>,
454 joints: HybridArray<Id<TransformDescriptor>>,
455 _skin_joints: Arc<Mutex<Vec<SkinJoint>>>,
457 _inverse_bind_matrices: Arc<Mutex<Option<GpuArray<Mat4>>>>,
462}
463
464impl From<&Skin> for Skin {
465 fn from(value: &Skin) -> Self {
466 value.clone()
467 }
468}
469
470impl core::fmt::Debug for Skin {
471 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
472 f.debug_struct("Skin")
473 .field("descriptor", &self.descriptor)
474 .field("joints", &self.joints)
475 .field("joint_transforms", &"...")
476 .field("inverse_bind_matrices", &"...")
477 .finish()
478 }
479}
480
481impl Skin {
482 pub fn new(
484 slab: &SlabAllocator<impl IsRuntime>,
485 joints: impl IntoIterator<Item = impl Into<SkinJoint>>,
486 inverse_bind_matrices: impl IntoIterator<Item = impl Into<Mat4>>,
487 ) -> Self {
488 let descriptor = slab.new_value(SkinDescriptor::default());
489 let skin_joints = joints.into_iter().map(|t| t.into()).collect::<Vec<_>>();
490 let joints = skin_joints.iter().map(|sj| sj.0.id()).collect::<Vec<_>>();
491 let inverse_bind_matrices = inverse_bind_matrices
492 .into_iter()
493 .map(|m| m.into())
494 .collect::<Vec<_>>();
495 let inverse_bind_matrices = if inverse_bind_matrices.is_empty() {
496 None
497 } else {
498 Some(slab.new_array(inverse_bind_matrices).into_gpu_only())
499 };
500
501 Skin {
502 descriptor,
503 joints: slab.new_array(joints),
504 _skin_joints: Arc::new(Mutex::new(skin_joints)),
506 _inverse_bind_matrices: Arc::new(Mutex::new(inverse_bind_matrices)),
507 }
508 }
509
510 pub fn id(&self) -> Id<SkinDescriptor> {
512 self.descriptor.id()
513 }
514
515 pub fn descriptor(&self) -> SkinDescriptor {
517 self.descriptor.get()
518 }
519}
520
521pub struct SkinJoint(pub(crate) Transform);
530
531impl From<Transform> for SkinJoint {
532 fn from(transform: Transform) -> Self {
533 SkinJoint(transform)
534 }
535}
536
537impl From<&Transform> for SkinJoint {
538 fn from(transform: &Transform) -> Self {
539 transform.clone().into()
540 }
541}
542
543impl From<NestedTransform> for SkinJoint {
544 fn from(value: NestedTransform) -> Self {
545 SkinJoint(value.global_transform)
546 }
547}
548
549impl From<&NestedTransform> for SkinJoint {
550 fn from(value: &NestedTransform) -> Self {
551 value.clone().into()
552 }
553}