1use crate::{
25 asset::{
26 io::ResourceIo,
27 loader::{BoxedLoaderFuture, LoaderPayload, ResourceLoader},
28 state::LoadError,
29 untyped::ResourceKind,
30 Resource, ResourceData,
31 },
32 core::{
33 algebra::{Matrix4, Point3, Vector2, Vector3, Vector4},
34 hash_combine,
35 log::Log,
36 math::TriangleDefinition,
37 pool::{ErasedHandle, Handle},
38 reflect::prelude::*,
39 sparse::AtomicIndex,
40 type_traits::prelude::*,
41 uuid_provider,
42 variable::InheritableVariable,
43 visitor::{Visit, VisitResult, Visitor},
44 Uuid,
45 },
46 material::{self, Material, MaterialResource, MaterialResourceExtension},
47 resource::texture::{TextureKind, TexturePixelKind, TextureResource, TextureResourceExtension},
48 scene::{
49 mesh::{
50 buffer::{
51 TriangleBuffer, VertexAttributeUsage, VertexBuffer, VertexFetchError,
52 VertexReadTrait, VertexTrait, VertexWriteTrait,
53 },
54 vertex::StaticVertex,
55 },
56 node::Node,
57 },
58 utils::raw_mesh::{RawMesh, RawMeshBuilder},
59};
60use bytemuck::{Pod, Zeroable};
61use fxhash::{FxHashMap, FxHasher};
62use fyrox_resource::manager::BuiltInResource;
63use half::f16;
64use lazy_static::lazy_static;
65use std::{
66 error::Error,
67 hash::Hasher,
68 path::{Path, PathBuf},
69 sync::Arc,
70};
71
72#[derive(Debug, Clone, Visit, Reflect, PartialEq)]
74pub struct BlendShape {
75 #[reflect(min_value = 0.0, max_value = 100.0, step = 1.0)]
77 pub weight: f32,
78 #[reflect(read_only)]
80 pub name: String,
81}
82
83uuid_provider!(BlendShape = "fea08418-58fe-4fde-991b-36be235432bd");
84
85impl Default for BlendShape {
86 fn default() -> Self {
87 Self {
88 weight: 100.0,
89 name: Default::default(),
90 }
91 }
92}
93
94#[derive(Reflect, Debug, Clone, Default)]
96pub struct BlendShapesContainer {
97 pub blend_shapes: Vec<BlendShape>,
99 pub blend_shape_storage: Option<TextureResource>,
101}
102
103#[derive(Clone)]
105pub struct InputBlendShapeData {
106 pub default_weight: f32,
108 pub name: String,
110 pub positions: FxHashMap<u32, Vector3<f16>>,
112 pub normals: FxHashMap<u32, Vector3<f16>>,
114 pub tangents: FxHashMap<u32, Vector3<f16>>,
116}
117
118impl BlendShapesContainer {
119 pub fn from_lists(
121 base_shape: &VertexBuffer,
122 input_blend_shapes: &[InputBlendShapeData],
123 ) -> Self {
124 #[repr(C)]
125 #[derive(Default, Clone, Copy, Pod, Zeroable)]
126 struct VertexData {
127 position: Vector3<f16>,
128 normal: Vector3<f16>,
129 tangent: Vector3<f16>,
130 }
131
132 #[inline]
133 fn coord_to_index(x: usize, y: usize, z: usize, width: usize, height: usize) -> usize {
134 z * width * height + y * width + x
135 }
136
137 #[inline]
138 fn index_to_2d_coord(index: usize, width: usize) -> Vector2<usize> {
139 let y = index / width;
140 let x = index - width * y; Vector2::new(x, y)
142 }
143
144 #[inline]
145 fn fetch(
146 vertices: &mut [VertexData],
147 vertex_index: usize,
148 width: u32,
149 height: u32,
150 layer: usize,
151 ) -> Option<&mut VertexData> {
152 let coord = index_to_2d_coord(vertex_index, width as usize);
153 vertices.get_mut(coord_to_index(
154 coord.x,
155 coord.y,
156 layer,
157 width as usize,
158 height as usize,
159 ))
160 }
161
162 let width = base_shape.vertex_count().min(512);
163 let height = (base_shape.vertex_count() as f32 / width as f32).ceil() as u32;
164 let depth = input_blend_shapes.len() as u32;
165
166 let mut vertex_data = vec![VertexData::default(); (width * height * depth) as usize];
167
168 for (layer, blend_shape) in input_blend_shapes.iter().enumerate() {
169 for (index, position) in blend_shape.positions.iter() {
170 if let Some(vertex) = fetch(&mut vertex_data, *index as usize, width, height, layer)
171 {
172 vertex.position = *position;
173 }
174 }
175
176 for (index, normal) in blend_shape.normals.iter() {
177 if let Some(vertex) = fetch(&mut vertex_data, *index as usize, width, height, layer)
178 {
179 vertex.normal = *normal;
180 }
181 }
182
183 for (index, tangent) in blend_shape.tangents.iter() {
184 if let Some(vertex) = fetch(&mut vertex_data, *index as usize, width, height, layer)
185 {
186 vertex.tangent = *tangent;
187 }
188 }
189 }
190
191 let bytes = crate::core::transmute_vec_as_bytes::<VertexData>(vertex_data);
192
193 assert_eq!(
194 bytes.len(),
195 (width * height * depth) as usize * std::mem::size_of::<VertexData>()
196 );
197
198 Self {
199 blend_shapes: input_blend_shapes
200 .iter()
201 .map(|bs| BlendShape {
202 weight: bs.default_weight,
203 name: bs.name.clone(),
204 })
205 .collect(),
206 blend_shape_storage: Some(
207 TextureResource::from_bytes(
208 TextureKind::Volume {
209 width: width * 3,
210 height,
211 depth,
212 },
213 TexturePixelKind::RGB16F,
214 bytes,
215 ResourceKind::Embedded,
216 )
217 .unwrap(),
218 ),
219 }
220 }
221}
222
223#[derive(Debug, Clone, Default, Reflect, TypeUuidProvider)]
227#[type_uuid(id = "8a23a414-e66d-4e12-9628-92c6ab49c2f0")]
228pub struct SurfaceData {
229 pub vertex_buffer: VertexBuffer,
231 pub geometry_buffer: TriangleBuffer,
233 pub blend_shapes_container: Option<BlendShapesContainer>,
235 #[reflect(hidden)]
236 pub(crate) cache_index: Arc<AtomicIndex>,
237}
238
239impl ResourceData for SurfaceData {
240 fn type_uuid(&self) -> Uuid {
241 <SurfaceData as fyrox_core::TypeUuidProvider>::type_uuid()
242 }
243
244 fn save(&mut self, _path: &Path) -> Result<(), Box<dyn Error>> {
245 Ok(())
247 }
248
249 fn can_be_saved(&self) -> bool {
250 true
251 }
252}
253
254impl SurfaceData {
255 pub fn new(vertex_buffer: VertexBuffer, triangles: TriangleBuffer) -> Self {
257 Self {
258 vertex_buffer,
259 geometry_buffer: triangles,
260 blend_shapes_container: None,
261 cache_index: Arc::new(AtomicIndex::unassigned()),
262 }
263 }
264
265 pub fn transform_geometry(&mut self, transform: &Matrix4<f32>) -> Result<(), VertexFetchError> {
267 let normal_matrix = transform.try_inverse().unwrap_or_default().transpose();
269
270 let mut vertex_buffer_mut = self.vertex_buffer.modify();
271 for mut view in vertex_buffer_mut.iter_mut() {
272 let position = view.read_3_f32(VertexAttributeUsage::Position)?;
273 view.write_3_f32(
274 VertexAttributeUsage::Position,
275 transform.transform_point(&Point3::from(position)).coords,
276 )?;
277 let normal = view.read_3_f32(VertexAttributeUsage::Normal)?;
278 view.write_3_f32(
279 VertexAttributeUsage::Normal,
280 normal_matrix.transform_vector(&normal),
281 )?;
282 let tangent = view.read_4_f32(VertexAttributeUsage::Tangent)?;
283 let new_tangent = normal_matrix.transform_vector(&tangent.xyz());
284 view.write_4_f32(
286 VertexAttributeUsage::Tangent,
287 Vector4::new(new_tangent.x, new_tangent.y, new_tangent.z, tangent.w),
288 )?;
289 }
290
291 Ok(())
292 }
293
294 pub fn from_raw_mesh<T>(raw: RawMesh<T>) -> Self
297 where
298 T: VertexTrait,
299 {
300 Self {
301 vertex_buffer: VertexBuffer::new(raw.vertices.len(), raw.vertices).unwrap(),
302 geometry_buffer: TriangleBuffer::new(raw.triangles),
303 blend_shapes_container: Default::default(),
304 cache_index: Arc::new(AtomicIndex::unassigned()),
305 }
306 }
307
308 pub fn calculate_tangents(&mut self) -> Result<(), VertexFetchError> {
314 let mut tan1 = vec![Vector3::default(); self.vertex_buffer.vertex_count() as usize];
315 let mut tan2 = vec![Vector3::default(); self.vertex_buffer.vertex_count() as usize];
316
317 for triangle in self.geometry_buffer.iter() {
318 let i1 = triangle[0] as usize;
319 let i2 = triangle[1] as usize;
320 let i3 = triangle[2] as usize;
321
322 let view1 = &self.vertex_buffer.get(i1).unwrap();
323 let view2 = &self.vertex_buffer.get(i2).unwrap();
324 let view3 = &self.vertex_buffer.get(i3).unwrap();
325
326 let v1 = view1.read_3_f32(VertexAttributeUsage::Position)?;
327 let v2 = view2.read_3_f32(VertexAttributeUsage::Position)?;
328 let v3 = view3.read_3_f32(VertexAttributeUsage::Position)?;
329
330 if v1 == v2 || v1 == v3 || v2 == v3 {
332 Log::warn(format!(
333 "Degenerated triangle found when calculating tangents. Lighting may be \
334 incorrect! Triangle indices: {triangle:?}. Triangle vertices: {v1} {v2} {v3}",
335 ));
336 }
337
338 let w1 = view1.read_3_f32(VertexAttributeUsage::TexCoord0)?;
339 let w2 = view2.read_3_f32(VertexAttributeUsage::TexCoord0)?;
340 let w3 = view3.read_3_f32(VertexAttributeUsage::TexCoord0)?;
341
342 let x1 = v2.x - v1.x;
343 let x2 = v3.x - v1.x;
344 let y1 = v2.y - v1.y;
345 let y2 = v3.y - v1.y;
346 let z1 = v2.z - v1.z;
347 let z2 = v3.z - v1.z;
348
349 let s1 = w2.x - w1.x;
350 let s2 = w3.x - w1.x;
351 let t1 = w2.y - w1.y;
352 let t2 = w3.y - w1.y;
353
354 let r = 1.0 / (s1 * t2 - s2 * t1);
355
356 let sdir = Vector3::new(
357 (t2 * x1 - t1 * x2) * r,
358 (t2 * y1 - t1 * y2) * r,
359 (t2 * z1 - t1 * z2) * r,
360 );
361
362 tan1[i1] += sdir;
363 tan1[i2] += sdir;
364 tan1[i3] += sdir;
365
366 let tdir = Vector3::new(
367 (s1 * x2 - s2 * x1) * r,
368 (s1 * y2 - s2 * y1) * r,
369 (s1 * z2 - s2 * z1) * r,
370 );
371 tan2[i1] += tdir;
372 tan2[i2] += tdir;
373 tan2[i3] += tdir;
374 }
375
376 let mut vertex_buffer_mut = self.vertex_buffer.modify();
377 for (mut view, (t1, t2)) in vertex_buffer_mut.iter_mut().zip(tan1.into_iter().zip(tan2)) {
378 let normal = view.read_3_f32(VertexAttributeUsage::Normal)?;
379
380 let tangent = (t1 - normal.scale(normal.dot(&t1)))
382 .try_normalize(f32::EPSILON)
383 .unwrap_or_else(|| Vector3::new(0.0, 1.0, 0.0));
384 let handedness = normal.cross(&t1).dot(&t2).signum();
385 view.write_4_f32(
386 VertexAttributeUsage::Tangent,
387 Vector4::new(tangent.x, tangent.y, tangent.z, handedness),
388 )?;
389 }
390
391 Ok(())
392 }
393
394 pub fn make_unit_xy_quad() -> Self {
396 let vertices = vec![
397 StaticVertex {
398 position: Vector3::default(),
399 normal: Vector3::z(),
400 tex_coord: Vector2::y(),
401 tangent: Vector4::default(),
402 },
403 StaticVertex {
404 position: Vector3::x(),
405 normal: Vector3::z(),
406 tex_coord: Vector2::new(1.0, 1.0),
407 tangent: Vector4::default(),
408 },
409 StaticVertex {
410 position: Vector3::new(1.0, 1.0, 0.0),
411 normal: Vector3::z(),
412 tex_coord: Vector2::x(),
413 tangent: Vector4::default(),
414 },
415 StaticVertex {
416 position: Vector3::y(),
417 normal: Vector3::z(),
418 tex_coord: Vector2::default(),
419 tangent: Vector4::default(),
420 },
421 ];
422
423 let triangles = vec![TriangleDefinition([0, 1, 2]), TriangleDefinition([0, 2, 3])];
424
425 Self::new(
426 VertexBuffer::new(vertices.len(), vertices).unwrap(),
427 TriangleBuffer::new(triangles),
428 )
429 }
430
431 pub fn make_collapsed_xy_quad() -> Self {
434 let vertices = vec![
435 StaticVertex {
436 position: Vector3::default(),
437 normal: Vector3::z(),
438 tex_coord: Vector2::default(),
439 tangent: Vector4::default(),
440 },
441 StaticVertex {
442 position: Vector3::default(),
443 normal: Vector3::z(),
444 tex_coord: Vector2::x(),
445 tangent: Vector4::default(),
446 },
447 StaticVertex {
448 position: Vector3::default(),
449 normal: Vector3::z(),
450 tex_coord: Vector2::new(1.0, 1.0),
451 tangent: Vector4::default(),
452 },
453 StaticVertex {
454 position: Vector3::default(),
455 normal: Vector3::z(),
456 tex_coord: Vector2::y(),
457 tangent: Vector4::default(),
458 },
459 ];
460
461 let triangles = vec![TriangleDefinition([0, 1, 2]), TriangleDefinition([0, 2, 3])];
462
463 Self::new(
464 VertexBuffer::new(vertices.len(), vertices).unwrap(),
465 TriangleBuffer::new(triangles),
466 )
467 }
468
469 pub fn make_quad(transform: &Matrix4<f32>) -> Self {
471 let vertices = vec![
472 StaticVertex {
473 position: Vector3::new(-0.5, 0.5, 0.0),
474 normal: -Vector3::z(),
475 tex_coord: Vector2::new(1.0, 1.0),
476 tangent: Vector4::default(),
477 },
478 StaticVertex {
479 position: Vector3::new(0.5, 0.5, 0.0),
480 normal: -Vector3::z(),
481 tex_coord: Vector2::new(0.0, 1.0),
482 tangent: Vector4::default(),
483 },
484 StaticVertex {
485 position: Vector3::new(0.5, -0.5, 0.0),
486 normal: -Vector3::z(),
487 tex_coord: Vector2::new(0.0, 0.0),
488 tangent: Vector4::default(),
489 },
490 StaticVertex {
491 position: Vector3::new(-0.5, -0.5, 0.0),
492 normal: -Vector3::z(),
493 tex_coord: Vector2::new(1.0, 0.0),
494 tangent: Vector4::default(),
495 },
496 ];
497
498 let mut data = Self::new(
499 VertexBuffer::new(vertices.len(), vertices).unwrap(),
500 TriangleBuffer::new(vec![
501 TriangleDefinition([0, 1, 2]),
502 TriangleDefinition([0, 2, 3]),
503 ]),
504 );
505 data.calculate_tangents().unwrap();
506 data.transform_geometry(transform).unwrap();
507 data
508 }
509
510 pub fn calculate_normals(&mut self) -> Result<(), VertexFetchError> {
512 let mut vertex_buffer_mut = self.vertex_buffer.modify();
513 for triangle in self.geometry_buffer.iter() {
514 let ia = triangle[0] as usize;
515 let ib = triangle[1] as usize;
516 let ic = triangle[2] as usize;
517
518 let a = vertex_buffer_mut
519 .get(ia)
520 .unwrap()
521 .read_3_f32(VertexAttributeUsage::Position)?;
522 let b = vertex_buffer_mut
523 .get(ib)
524 .unwrap()
525 .read_3_f32(VertexAttributeUsage::Position)?;
526 let c = vertex_buffer_mut
527 .get(ic)
528 .unwrap()
529 .read_3_f32(VertexAttributeUsage::Position)?;
530
531 let normal = (b - a).cross(&(c - a)).normalize();
532
533 vertex_buffer_mut
534 .get_mut(ia)
535 .unwrap()
536 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
537 vertex_buffer_mut
538 .get_mut(ib)
539 .unwrap()
540 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
541 vertex_buffer_mut
542 .get_mut(ic)
543 .unwrap()
544 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
545 }
546
547 Ok(())
548 }
549
550 pub fn make_sphere(slices: usize, stacks: usize, r: f32, transform: &Matrix4<f32>) -> Self {
554 let mut builder = RawMeshBuilder::<StaticVertex>::new(stacks * slices, stacks * slices * 3);
555
556 let d_theta = std::f32::consts::PI / slices as f32;
557 let d_phi = 2.0 * std::f32::consts::PI / stacks as f32;
558 let d_tc_y = 1.0 / stacks as f32;
559 let d_tc_x = 1.0 / slices as f32;
560
561 for i in 0..stacks {
562 for j in 0..slices {
563 let nj = j + 1;
564 let ni = i + 1;
565
566 let k0 = r * (d_theta * i as f32).sin();
567 let k1 = (d_phi * j as f32).cos();
568 let k2 = (d_phi * j as f32).sin();
569 let k3 = r * (d_theta * i as f32).cos();
570
571 let k4 = r * (d_theta * ni as f32).sin();
572 let k5 = (d_phi * nj as f32).cos();
573 let k6 = (d_phi * nj as f32).sin();
574 let k7 = r * (d_theta * ni as f32).cos();
575
576 if i != (stacks - 1) {
577 let v0 = Vector3::new(k0 * k1, k0 * k2, k3);
578 let t0 = Vector2::new(d_tc_x * j as f32, d_tc_y * i as f32);
579
580 let v1 = Vector3::new(k4 * k1, k4 * k2, k7);
581 let t1 = Vector2::new(d_tc_x * j as f32, d_tc_y * ni as f32);
582
583 let v2 = Vector3::new(k4 * k5, k4 * k6, k7);
584 let t2 = Vector2::new(d_tc_x * nj as f32, d_tc_y * ni as f32);
585
586 builder.insert(StaticVertex::from_pos_uv_normal(v0, t0, v0));
587 builder.insert(StaticVertex::from_pos_uv_normal(v1, t1, v1));
588 builder.insert(StaticVertex::from_pos_uv_normal(v2, t2, v2));
589 }
590
591 if i != 0 {
592 let v0 = Vector3::new(k4 * k5, k4 * k6, k7);
593 let t0 = Vector2::new(d_tc_x * nj as f32, d_tc_y * ni as f32);
594
595 let v1 = Vector3::new(k0 * k5, k0 * k6, k3);
596 let t1 = Vector2::new(d_tc_x * nj as f32, d_tc_y * i as f32);
597
598 let v2 = Vector3::new(k0 * k1, k0 * k2, k3);
599 let t2 = Vector2::new(d_tc_x * j as f32, d_tc_y * i as f32);
600
601 builder.insert(StaticVertex::from_pos_uv_normal(v0, t0, v0));
602 builder.insert(StaticVertex::from_pos_uv_normal(v1, t1, v1));
603 builder.insert(StaticVertex::from_pos_uv_normal(v2, t2, v2));
604 }
605 }
606 }
607
608 let mut data = Self::from_raw_mesh(builder.build());
609 data.calculate_tangents().unwrap();
610 data.transform_geometry(transform).unwrap();
611 data
612 }
613
614 pub fn make_cone(sides: usize, r: f32, h: f32, transform: &Matrix4<f32>) -> Self {
618 let mut builder = RawMeshBuilder::<StaticVertex>::new(3 * sides, 3 * sides);
619
620 let d_phi = 2.0 * std::f32::consts::PI / sides as f32;
621 let d_theta = 1.0 / sides as f32;
622
623 for i in 0..sides {
624 let nx0 = (d_phi * i as f32).cos();
625 let ny0 = (d_phi * i as f32).sin();
626 let nx1 = (d_phi * (i + 1) as f32).cos();
627 let ny1 = (d_phi * (i + 1) as f32).sin();
628
629 let x0 = r * nx0;
630 let z0 = r * ny0;
631 let x1 = r * nx1;
632 let z1 = r * ny1;
633 let tx0 = d_theta * i as f32;
634 let tx1 = d_theta * (i + 1) as f32;
635
636 let (t_cap_y_curr, t_cap_x_curr) = (d_phi * i as f32).sin_cos();
638 let (t_cap_y_next, t_cap_x_next) = (d_phi * (i + 1) as f32).sin_cos();
639
640 let t_cap_x_curr = t_cap_x_curr * 0.5 + 0.5;
641 let t_cap_y_curr = t_cap_y_curr * 0.5 + 0.5;
642
643 let t_cap_x_next = t_cap_x_next * 0.5 + 0.5;
644 let t_cap_y_next = t_cap_y_next * 0.5 + 0.5;
645
646 builder.insert(StaticVertex::from_pos_uv_normal(
647 Vector3::new(0.0, 0.0, 0.0),
648 Vector2::new(0.5, 0.5),
649 Vector3::new(0.0, -1.0, 0.0),
650 ));
651 builder.insert(StaticVertex::from_pos_uv_normal(
652 Vector3::new(x0, 0.0, z0),
653 Vector2::new(t_cap_x_curr, t_cap_y_curr),
654 Vector3::new(0.0, -1.0, 0.0),
655 ));
656 builder.insert(StaticVertex::from_pos_uv_normal(
657 Vector3::new(x1, 0.0, z1),
658 Vector2::new(t_cap_x_next, t_cap_y_next),
659 Vector3::new(0.0, -1.0, 0.0),
660 ));
661
662 let tip = Vector3::new(0.0, h, 0.0);
664 let v_curr = Vector3::new(x0, 0.0, z0);
665 let v_next = Vector3::new(x1, 0.0, z1);
666 let n_next = (tip - v_next).cross(&(v_next - v_curr));
667 let n_curr = (tip - v_curr).cross(&(v_next - v_curr));
668
669 builder.insert(StaticVertex::from_pos_uv_normal(
670 tip,
671 Vector2::new(0.5, 0.0),
672 n_curr,
673 ));
674 builder.insert(StaticVertex::from_pos_uv_normal(
675 v_next,
676 Vector2::new(tx1, 1.0),
677 n_next,
678 ));
679 builder.insert(StaticVertex::from_pos_uv_normal(
680 v_curr,
681 Vector2::new(tx0, 1.0),
682 n_curr,
683 ));
684 }
685
686 let mut data = Self::from_raw_mesh(builder.build());
687 data.calculate_tangents().unwrap();
688 data.transform_geometry(transform).unwrap();
689 data
690 }
691
692 pub fn make_torus(
697 inner_radius: f32,
698 outer_radius: f32,
699 num_rings: usize,
700 num_segments: usize,
701 transform: &Matrix4<f32>,
702 ) -> Self {
703 let mut vertices = Vec::new();
704 for j in 0..=num_rings {
705 for i in 0..=num_segments {
706 let u = i as f32 / num_segments as f32 * std::f32::consts::TAU;
707 let v = j as f32 / num_rings as f32 * std::f32::consts::TAU;
708
709 let center = Vector3::new(inner_radius * u.cos(), inner_radius * u.sin(), 0.0);
710
711 let position = Vector3::new(
712 (inner_radius + outer_radius * v.cos()) * u.cos(),
713 outer_radius * v.sin(),
714 (inner_radius + outer_radius * v.cos()) * u.sin(),
715 );
716
717 let uv = Vector2::new(i as f32 / num_segments as f32, j as f32 / num_rings as f32);
718
719 let normal = (position - center)
720 .try_normalize(f32::EPSILON)
721 .unwrap_or_default();
722
723 vertices.push(StaticVertex::from_pos_uv_normal(position, uv, normal));
724 }
725 }
726
727 let mut triangles = Vec::new();
728 for j in 1..=num_rings {
729 for i in 1..=num_segments {
730 let a = ((num_segments + 1) * j + i - 1) as u32;
731 let b = ((num_segments + 1) * (j - 1) + i - 1) as u32;
732 let c = ((num_segments + 1) * (j - 1) + i) as u32;
733 let d = ((num_segments + 1) * j + i) as u32;
734
735 triangles.push(TriangleDefinition([a, b, d]));
736 triangles.push(TriangleDefinition([b, c, d]));
737 }
738 }
739
740 let mut data = Self::new(
741 VertexBuffer::new(vertices.len(), vertices).unwrap(),
742 TriangleBuffer::new(triangles),
743 );
744 data.calculate_tangents().unwrap();
745 data.transform_geometry(transform).unwrap();
746 data
747 }
748
749 pub fn make_cylinder(
753 sides: usize,
754 r: f32,
755 h: f32,
756 caps: bool,
757 transform: &Matrix4<f32>,
758 ) -> Self {
759 let mut builder = RawMeshBuilder::<StaticVertex>::new(3 * sides, 3 * sides);
760
761 let d_phi = 2.0 * std::f32::consts::PI / sides as f32;
762 let d_theta = 1.0 / sides as f32;
763
764 for i in 0..sides {
765 let nx0 = (d_phi * i as f32).cos();
766 let ny0 = (d_phi * i as f32).sin();
767 let nx1 = (d_phi * (i + 1) as f32).cos();
768 let ny1 = (d_phi * (i + 1) as f32).sin();
769
770 let x0 = r * nx0;
771 let z0 = r * ny0;
772 let x1 = r * nx1;
773 let z1 = r * ny1;
774
775 if caps {
776 let (t_cap_y_curr, t_cap_x_curr) = (d_phi * i as f32).sin_cos();
777 let (t_cap_y_next, t_cap_x_next) = (d_phi * (i + 1) as f32).sin_cos();
778
779 let t_cap_x_curr = t_cap_x_curr * 0.5 + 0.5;
780 let t_cap_y_curr = t_cap_y_curr * 0.5 + 0.5;
781
782 let t_cap_x_next = t_cap_x_next * 0.5 + 0.5;
783 let t_cap_y_next = t_cap_y_next * 0.5 + 0.5;
784
785 builder.insert(StaticVertex::from_pos_uv_normal(
787 Vector3::new(x1, h, z1),
788 Vector2::new(t_cap_x_next, t_cap_y_next),
789 Vector3::new(0.0, 1.0, 0.0),
790 ));
791 builder.insert(StaticVertex::from_pos_uv_normal(
792 Vector3::new(x0, h, z0),
793 Vector2::new(t_cap_x_curr, t_cap_y_curr),
794 Vector3::new(0.0, 1.0, 0.0),
795 ));
796 builder.insert(StaticVertex::from_pos_uv_normal(
797 Vector3::new(0.0, h, 0.0),
798 Vector2::new(0.5, 0.5),
799 Vector3::new(0.0, 1.0, 0.0),
800 ));
801
802 builder.insert(StaticVertex::from_pos_uv_normal(
804 Vector3::new(x0, 0.0, z0),
805 Vector2::new(t_cap_x_curr, t_cap_y_curr),
806 Vector3::new(0.0, -1.0, 0.0),
807 ));
808 builder.insert(StaticVertex::from_pos_uv_normal(
809 Vector3::new(x1, 0.0, z1),
810 Vector2::new(t_cap_x_next, t_cap_y_next),
811 Vector3::new(0.0, -1.0, 0.0),
812 ));
813 builder.insert(StaticVertex::from_pos_uv_normal(
814 Vector3::new(0.0, 0.0, 0.0),
815 Vector2::new(0.5, 0.5),
816 Vector3::new(0.0, -1.0, 0.0),
817 ));
818 }
819
820 let t_side_curr = d_theta * i as f32;
821 let t_side_next = d_theta * (i + 1) as f32;
822
823 builder.insert(StaticVertex::from_pos_uv_normal(
825 Vector3::new(x0, 0.0, z0),
826 Vector2::new(t_side_curr, 0.0),
827 Vector3::new(x0, 0.0, z0),
828 ));
829 builder.insert(StaticVertex::from_pos_uv_normal(
830 Vector3::new(x0, h, z0),
831 Vector2::new(t_side_curr, 1.0),
832 Vector3::new(x0, 0.0, z0),
833 ));
834 builder.insert(StaticVertex::from_pos_uv_normal(
835 Vector3::new(x1, 0.0, z1),
836 Vector2::new(t_side_next, 0.0),
837 Vector3::new(x1, 0.0, z1),
838 ));
839
840 builder.insert(StaticVertex::from_pos_uv_normal(
841 Vector3::new(x1, 0.0, z1),
842 Vector2::new(t_side_next, 0.0),
843 Vector3::new(x1, 0.0, z1),
844 ));
845 builder.insert(StaticVertex::from_pos_uv_normal(
846 Vector3::new(x0, h, z0),
847 Vector2::new(t_side_curr, 1.0),
848 Vector3::new(x0, 0.0, z0),
849 ));
850 builder.insert(StaticVertex::from_pos_uv_normal(
851 Vector3::new(x1, h, z1),
852 Vector2::new(t_side_next, 1.0),
853 Vector3::new(x1, 0.0, z1),
854 ));
855 }
856
857 let mut data = Self::from_raw_mesh(builder.build());
858 data.calculate_tangents().unwrap();
859 data.transform_geometry(transform).unwrap();
860 data
861 }
862
863 pub fn make_cube(transform: Matrix4<f32>) -> Self {
865 let vertices = vec![
866 StaticVertex {
868 position: Vector3::new(-0.5, -0.5, 0.5),
869 normal: Vector3::z(),
870 tex_coord: Vector2::default(),
871 tangent: Vector4::default(),
872 },
873 StaticVertex {
874 position: Vector3::new(-0.5, 0.5, 0.5),
875 normal: Vector3::z(),
876 tex_coord: Vector2::y(),
877 tangent: Vector4::default(),
878 },
879 StaticVertex {
880 position: Vector3::new(0.5, 0.5, 0.5),
881 normal: Vector3::z(),
882 tex_coord: Vector2::new(1.0, 1.0),
883 tangent: Vector4::default(),
884 },
885 StaticVertex {
886 position: Vector3::new(0.5, -0.5, 0.5),
887 normal: Vector3::z(),
888 tex_coord: Vector2::x(),
889 tangent: Vector4::default(),
890 },
891 StaticVertex {
893 position: Vector3::new(-0.5, -0.5, -0.5),
894 normal: -Vector3::z(),
895 tex_coord: Vector2::default(),
896 tangent: Vector4::default(),
897 },
898 StaticVertex {
899 position: Vector3::new(-0.5, 0.5, -0.5),
900 normal: -Vector3::z(),
901 tex_coord: Vector2::y(),
902 tangent: Vector4::default(),
903 },
904 StaticVertex {
905 position: Vector3::new(0.5, 0.5, -0.5),
906 normal: -Vector3::z(),
907 tex_coord: Vector2::new(1.0, 1.0),
908 tangent: Vector4::default(),
909 },
910 StaticVertex {
911 position: Vector3::new(0.5, -0.5, -0.5),
912 normal: -Vector3::z(),
913 tex_coord: Vector2::x(),
914 tangent: Vector4::default(),
915 },
916 StaticVertex {
918 position: Vector3::new(-0.5, -0.5, -0.5),
919 normal: -Vector3::x(),
920 tex_coord: Vector2::default(),
921 tangent: Vector4::default(),
922 },
923 StaticVertex {
924 position: Vector3::new(-0.5, 0.5, -0.5),
925 normal: -Vector3::x(),
926 tex_coord: Vector2::y(),
927 tangent: Vector4::default(),
928 },
929 StaticVertex {
930 position: Vector3::new(-0.5, 0.5, 0.5),
931 normal: -Vector3::x(),
932 tex_coord: Vector2::new(1.0, 1.0),
933 tangent: Vector4::default(),
934 },
935 StaticVertex {
936 position: Vector3::new(-0.5, -0.5, 0.5),
937 normal: -Vector3::x(),
938 tex_coord: Vector2::x(),
939 tangent: Vector4::default(),
940 },
941 StaticVertex {
943 position: Vector3::new(0.5, -0.5, -0.5),
944 normal: Vector3::x(),
945 tex_coord: Vector2::default(),
946 tangent: Vector4::default(),
947 },
948 StaticVertex {
949 position: Vector3::new(0.5, 0.5, -0.5),
950 normal: Vector3::x(),
951 tex_coord: Vector2::y(),
952 tangent: Vector4::default(),
953 },
954 StaticVertex {
955 position: Vector3::new(0.5, 0.5, 0.5),
956 normal: Vector3::x(),
957 tex_coord: Vector2::new(1.0, 1.0),
958 tangent: Vector4::default(),
959 },
960 StaticVertex {
961 position: Vector3::new(0.5, -0.5, 0.5),
962 normal: Vector3::x(),
963 tex_coord: Vector2::x(),
964 tangent: Vector4::default(),
965 },
966 StaticVertex {
968 position: Vector3::new(-0.5, 0.5, 0.5),
969 normal: Vector3::y(),
970 tex_coord: Vector2::default(),
971 tangent: Vector4::default(),
972 },
973 StaticVertex {
974 position: Vector3::new(-0.5, 0.5, -0.5),
975 normal: Vector3::y(),
976 tex_coord: Vector2::y(),
977 tangent: Vector4::default(),
978 },
979 StaticVertex {
980 position: Vector3::new(0.5, 0.5, -0.5),
981 normal: Vector3::y(),
982 tex_coord: Vector2::new(1.0, 1.0),
983 tangent: Vector4::default(),
984 },
985 StaticVertex {
986 position: Vector3::new(0.5, 0.5, 0.5),
987 normal: Vector3::y(),
988 tex_coord: Vector2::x(),
989 tangent: Vector4::default(),
990 },
991 StaticVertex {
993 position: Vector3::new(-0.5, -0.5, 0.5),
994 normal: -Vector3::y(),
995 tex_coord: Vector2::default(),
996 tangent: Vector4::default(),
997 },
998 StaticVertex {
999 position: Vector3::new(-0.5, -0.5, -0.5),
1000 normal: -Vector3::y(),
1001 tex_coord: Vector2::y(),
1002 tangent: Vector4::default(),
1003 },
1004 StaticVertex {
1005 position: Vector3::new(0.5, -0.5, -0.5),
1006 normal: -Vector3::y(),
1007 tex_coord: Vector2::new(1.0, 1.0),
1008 tangent: Vector4::default(),
1009 },
1010 StaticVertex {
1011 position: Vector3::new(0.5, -0.5, 0.5),
1012 normal: -Vector3::y(),
1013 tex_coord: Vector2::x(),
1014 tangent: Vector4::default(),
1015 },
1016 ];
1017
1018 let triangles = vec![
1019 TriangleDefinition([2, 1, 0]),
1020 TriangleDefinition([3, 2, 0]),
1021 TriangleDefinition([4, 5, 6]),
1022 TriangleDefinition([4, 6, 7]),
1023 TriangleDefinition([10, 9, 8]),
1024 TriangleDefinition([11, 10, 8]),
1025 TriangleDefinition([12, 13, 14]),
1026 TriangleDefinition([12, 14, 15]),
1027 TriangleDefinition([18, 17, 16]),
1028 TriangleDefinition([19, 18, 16]),
1029 TriangleDefinition([20, 21, 22]),
1030 TriangleDefinition([20, 22, 23]),
1031 ];
1032
1033 let mut data = Self::new(
1034 VertexBuffer::new(vertices.len(), vertices).unwrap(),
1035 TriangleBuffer::new(triangles),
1036 );
1037 data.calculate_tangents().unwrap();
1038 data.transform_geometry(&transform).unwrap();
1039 data
1040 }
1041
1042 pub fn content_hash(&self) -> u64 {
1045 hash_combine(
1046 self.geometry_buffer.content_hash(),
1047 self.vertex_buffer.content_hash(),
1048 )
1049 }
1050
1051 pub fn clear(&mut self) {
1053 self.geometry_buffer.modify().clear();
1054 self.vertex_buffer.modify().clear();
1055 }
1056}
1057
1058impl Visit for SurfaceData {
1059 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1060 let mut region = visitor.enter_region(name)?;
1061
1062 self.vertex_buffer.visit("VertexBuffer", &mut region)?;
1063 self.geometry_buffer.visit("GeometryBuffer", &mut region)?;
1064
1065 Ok(())
1066 }
1067}
1068
1069#[derive(Copy, Clone, PartialEq, Debug)]
1071pub struct VertexWeight {
1072 pub value: f32,
1074 pub effector: ErasedHandle,
1081}
1082
1083impl Default for VertexWeight {
1084 fn default() -> Self {
1085 Self {
1086 value: 0.0,
1087 effector: ErasedHandle::none(),
1088 }
1089 }
1090}
1091
1092#[derive(Copy, Clone, Debug, PartialEq, Default)]
1094pub struct VertexWeightSet {
1095 weights: [VertexWeight; 4],
1096 count: usize,
1097}
1098
1099impl VertexWeightSet {
1100 pub fn push(&mut self, weight: VertexWeight) -> bool {
1103 if self.count < self.weights.len() {
1104 self.weights[self.count] = weight;
1105 self.count += 1;
1106 true
1107 } else {
1108 false
1109 }
1110 }
1111
1112 pub fn len(&self) -> usize {
1114 self.count
1115 }
1116
1117 pub fn is_empty(&self) -> bool {
1119 self.count == 0
1120 }
1121
1122 pub fn iter(&self) -> std::slice::Iter<VertexWeight> {
1124 self.weights[0..self.count].iter()
1125 }
1126
1127 pub fn iter_mut(&mut self) -> std::slice::IterMut<VertexWeight> {
1129 self.weights[0..self.count].iter_mut()
1130 }
1131
1132 pub fn normalize(&mut self) {
1137 let len = self.iter().fold(0.0, |qs, w| qs + w.value * w.value).sqrt();
1138 if len >= f32::EPSILON {
1139 let k = 1.0 / len;
1140 for w in self.iter_mut() {
1141 w.value *= k;
1142 }
1143 }
1144 }
1145}
1146
1147pub type SurfaceResource = Resource<SurfaceData>;
1151
1152pub trait SurfaceResourceExtension {
1154 fn deep_clone(&self) -> Self;
1156}
1157
1158impl SurfaceResourceExtension for SurfaceResource {
1159 fn deep_clone(&self) -> Self {
1160 Self::new_ok(self.kind(), self.data_ref().clone())
1161 }
1162}
1163
1164#[derive(Debug, Reflect, PartialEq)]
1245pub struct Surface {
1246 pub(crate) data: InheritableVariable<SurfaceResource>,
1247
1248 pub(crate) material: InheritableVariable<MaterialResource>,
1249
1250 pub bones: InheritableVariable<Vec<Handle<Node>>>,
1252
1253 #[reflect(
1254 description = "If true, then the current material will become a unique instance when cloning the surface.\
1255 Could be useful if you need to have unique materials per on every instance. Keep in mind that this option \
1256 might affect performance!"
1257 )]
1258 unique_material: InheritableVariable<bool>,
1259
1260 #[reflect(hidden)]
1267 pub(crate) vertex_weights: Vec<VertexWeightSet>,
1268}
1269
1270uuid_provider!(Surface = "485caf12-4e7d-4b1a-b6bd-0681fd92f789");
1271
1272impl Clone for Surface {
1273 fn clone(&self) -> Self {
1274 Self {
1275 data: self.data.clone(),
1276 material: if *self.unique_material {
1277 self.material.deep_copy_as_embedded().into()
1279 } else {
1280 self.material.clone()
1282 },
1283 bones: self.bones.clone(),
1284 unique_material: self.unique_material.clone(),
1285 vertex_weights: self.vertex_weights.clone(),
1286 }
1287 }
1288}
1289
1290impl Visit for Surface {
1291 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1292 let mut region = visitor.enter_region(name)?;
1293
1294 if region.is_reading() {
1296 if let Some(material) = material::visit_old_material(&mut region) {
1297 self.material = material.into();
1298 } else {
1299 self.material.visit("Material", &mut region)?;
1300 }
1301 } else {
1302 self.material.visit("Material", &mut region)?;
1303 }
1304
1305 self.data.visit("Data", &mut region)?;
1306 self.bones.visit("Bones", &mut region)?;
1307 let _ = self.unique_material.visit("UniqueMaterial", &mut region); Ok(())
1310 }
1311}
1312
1313impl Default for Surface {
1314 fn default() -> Self {
1315 Self {
1316 data: SurfaceResource::new_ok(
1317 ResourceKind::Embedded,
1318 SurfaceData::make_cube(Matrix4::identity()),
1319 )
1320 .into(),
1321 material: MaterialResource::new_ok(Default::default(), Material::standard()).into(),
1322 vertex_weights: Default::default(),
1323 bones: Default::default(),
1324 unique_material: Default::default(),
1325 }
1326 }
1327}
1328
1329impl Surface {
1330 #[inline]
1332 pub fn new(data: SurfaceResource) -> Self {
1333 Self {
1334 data: data.into(),
1335 ..Default::default()
1336 }
1337 }
1338
1339 pub fn material_id(&self) -> u64 {
1341 self.material.key()
1342 }
1343
1344 pub fn batch_id(&self) -> u64 {
1346 let mut hasher = FxHasher::default();
1347 hasher.write_u64(self.material_id());
1348 hasher.write_u64(self.data.key());
1349 hasher.finish()
1350 }
1351
1352 #[inline]
1354 pub fn data(&self) -> SurfaceResource {
1355 (*self.data).clone()
1356 }
1357
1358 #[inline]
1360 pub fn data_ref(&self) -> &SurfaceResource {
1361 &self.data
1362 }
1363
1364 pub fn material(&self) -> &MaterialResource {
1366 &self.material
1367 }
1368
1369 pub fn set_material(&mut self, material: MaterialResource) {
1371 self.material.set_value_and_mark_modified(material);
1372 }
1373
1374 #[inline]
1376 pub fn bones(&self) -> &[Handle<Node>] {
1377 &self.bones
1378 }
1379
1380 pub fn is_unique_material(&self) -> bool {
1382 *self.unique_material
1383 }
1384
1385 pub fn set_unique_material(&mut self, unique: bool) {
1387 self.unique_material.set_value_and_mark_modified(unique);
1388 }
1389}
1390
1391pub struct SurfaceBuilder {
1393 data: SurfaceResource,
1394 material: Option<MaterialResource>,
1395 bones: Vec<Handle<Node>>,
1396 unique_material: bool,
1397}
1398
1399impl SurfaceBuilder {
1400 pub fn new(data: SurfaceResource) -> Self {
1402 Self {
1403 data,
1404 material: None,
1405 bones: Default::default(),
1406 unique_material: false,
1407 }
1408 }
1409
1410 pub fn with_material(mut self, material: MaterialResource) -> Self {
1412 self.material = Some(material);
1413 self
1414 }
1415
1416 pub fn with_bones(mut self, bones: Vec<Handle<Node>>) -> Self {
1418 self.bones = bones;
1419 self
1420 }
1421
1422 pub fn with_unique_material(mut self, unique: bool) -> Self {
1424 self.unique_material = unique;
1425 self
1426 }
1427
1428 pub fn build(self) -> Surface {
1430 Surface {
1431 data: self.data.into(),
1432 material: self
1433 .material
1434 .unwrap_or_else(|| {
1435 MaterialResource::new_ok(Default::default(), Material::standard())
1436 })
1437 .into(),
1438 vertex_weights: Default::default(),
1439 bones: self.bones.into(),
1440 unique_material: self.unique_material.into(),
1441 }
1442 }
1443}
1444
1445pub struct SurfaceDataLoader {}
1447
1448impl ResourceLoader for SurfaceDataLoader {
1449 fn extensions(&self) -> &[&str] {
1450 &["surface"]
1451 }
1452
1453 fn data_type_uuid(&self) -> Uuid {
1454 <SurfaceData as TypeUuidProvider>::type_uuid()
1455 }
1456
1457 fn load(&self, path: PathBuf, io: Arc<dyn ResourceIo>) -> BoxedLoaderFuture {
1458 Box::pin(async move {
1459 let io = io.as_ref();
1460
1461 let data = io.load_file(&path).await.map_err(LoadError::new)?;
1462 let mut visitor = Visitor::load_from_memory(&data).map_err(LoadError::new)?;
1463 let mut surface_data = SurfaceData::default();
1464 surface_data
1465 .visit("SurfaceData", &mut visitor)
1466 .map_err(LoadError::new)?;
1467 Ok(LoaderPayload::new(surface_data))
1468 })
1469 }
1470}
1471
1472lazy_static! {
1473 pub static ref CUBE: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1475 SurfaceResource::new_ok(
1476 "__CubeSurface".into(),
1477 SurfaceData::make_cube(Matrix4::identity()),
1478 )
1479 );
1480
1481 pub static ref QUAD: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1483 SurfaceResource::new_ok(
1484 "__QuadSurface".into(),
1485 SurfaceData::make_quad(&Matrix4::identity()),
1486 )
1487 );
1488
1489 pub static ref CYLINDER: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1491 SurfaceResource::new_ok(
1492 "__CylinderSurface".into(),
1493 SurfaceData::make_cylinder(32, 1.0, 1.0, true, &Matrix4::identity()),
1494 )
1495 );
1496
1497 pub static ref SPHERE: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1499 SurfaceResource::new_ok(
1500 "__SphereSurface".into(),
1501 SurfaceData::make_sphere(32, 32, 1.0, &Matrix4::identity()),
1502 )
1503 );
1504
1505 pub static ref CONE: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1507 SurfaceResource::new_ok(
1508 "__ConeSurface".into(),
1509 SurfaceData::make_cone(32, 1.0, 1.0, &Matrix4::identity()),
1510 )
1511 );
1512
1513 pub static ref TORUS: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1515 SurfaceResource::new_ok(
1516 "__TorusSurface".into(),
1517 SurfaceData::make_torus(1.0, 0.25,32, 32, &Matrix4::identity()),
1518 )
1519 );
1520}