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::{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 std::{
65 error::Error,
66 hash::Hasher,
67 path::{Path, PathBuf},
68 sync::{Arc, LazyLock},
69};
70
71#[derive(Debug, Clone, Visit, Reflect, PartialEq)]
73pub struct BlendShape {
74 #[reflect(min_value = 0.0, max_value = 100.0, step = 1.0)]
76 pub weight: f32,
77 #[reflect(read_only)]
79 pub name: String,
80}
81
82uuid_provider!(BlendShape = "fea08418-58fe-4fde-991b-36be235432bd");
83
84impl Default for BlendShape {
85 fn default() -> Self {
86 Self {
87 weight: 100.0,
88 name: Default::default(),
89 }
90 }
91}
92
93#[derive(Reflect, Debug, Clone, Default)]
95pub struct BlendShapesContainer {
96 pub blend_shapes: Vec<BlendShape>,
98 pub blend_shape_storage: Option<TextureResource>,
100}
101
102#[derive(Clone)]
104pub struct InputBlendShapeData {
105 pub default_weight: f32,
107 pub name: String,
109 pub positions: FxHashMap<u32, Vector3<f16>>,
111 pub normals: FxHashMap<u32, Vector3<f16>>,
113 pub tangents: FxHashMap<u32, Vector3<f16>>,
115}
116
117impl BlendShapesContainer {
118 pub fn from_lists(
120 base_shape: &VertexBuffer,
121 input_blend_shapes: &[InputBlendShapeData],
122 ) -> Self {
123 #[repr(C)]
124 #[derive(Default, Clone, Copy, Pod, Zeroable)]
125 struct VertexData {
126 position: Vector3<f16>,
127 normal: Vector3<f16>,
128 tangent: Vector3<f16>,
129 }
130
131 #[inline]
132 fn coord_to_index(x: usize, y: usize, z: usize, width: usize, height: usize) -> usize {
133 z * width * height + y * width + x
134 }
135
136 #[inline]
137 fn index_to_2d_coord(index: usize, width: usize) -> Vector2<usize> {
138 let y = index / width;
139 let x = index - width * y; Vector2::new(x, y)
141 }
142
143 #[inline]
144 fn fetch(
145 vertices: &mut [VertexData],
146 vertex_index: usize,
147 width: u32,
148 height: u32,
149 layer: usize,
150 ) -> Option<&mut VertexData> {
151 let coord = index_to_2d_coord(vertex_index, width as usize);
152 vertices.get_mut(coord_to_index(
153 coord.x,
154 coord.y,
155 layer,
156 width as usize,
157 height as usize,
158 ))
159 }
160
161 let width = base_shape.vertex_count().min(512);
162 let height = (base_shape.vertex_count() as f32 / width as f32).ceil() as u32;
163 let depth = input_blend_shapes.len() as u32;
164
165 let mut vertex_data = vec![VertexData::default(); (width * height * depth) as usize];
166
167 for (layer, blend_shape) in input_blend_shapes.iter().enumerate() {
168 for (index, position) in blend_shape.positions.iter() {
169 if let Some(vertex) = fetch(&mut vertex_data, *index as usize, width, height, layer)
170 {
171 vertex.position = *position;
172 }
173 }
174
175 for (index, normal) in blend_shape.normals.iter() {
176 if let Some(vertex) = fetch(&mut vertex_data, *index as usize, width, height, layer)
177 {
178 vertex.normal = *normal;
179 }
180 }
181
182 for (index, tangent) in blend_shape.tangents.iter() {
183 if let Some(vertex) = fetch(&mut vertex_data, *index as usize, width, height, layer)
184 {
185 vertex.tangent = *tangent;
186 }
187 }
188 }
189
190 let bytes = crate::core::transmute_vec_as_bytes::<VertexData>(vertex_data);
191
192 assert_eq!(
193 bytes.len(),
194 (width * height * depth) as usize * std::mem::size_of::<VertexData>()
195 );
196
197 Self {
198 blend_shapes: input_blend_shapes
199 .iter()
200 .map(|bs| BlendShape {
201 weight: bs.default_weight,
202 name: bs.name.clone(),
203 })
204 .collect(),
205 blend_shape_storage: Some(
206 TextureResource::from_bytes(
207 Uuid::new_v4(),
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 fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
254 Some(Box::new(self.clone()))
255 }
256}
257
258impl SurfaceData {
259 pub fn new(vertex_buffer: VertexBuffer, triangles: TriangleBuffer) -> Self {
261 Self {
262 vertex_buffer,
263 geometry_buffer: triangles,
264 blend_shapes_container: None,
265 cache_index: Arc::new(AtomicIndex::unassigned()),
266 }
267 }
268
269 pub fn transform_geometry(&mut self, transform: &Matrix4<f32>) -> Result<(), VertexFetchError> {
271 let normal_matrix = transform.try_inverse().unwrap_or_default().transpose();
273
274 let mut vertex_buffer_mut = self.vertex_buffer.modify();
275 for mut view in vertex_buffer_mut.iter_mut() {
276 let position = view.read_3_f32(VertexAttributeUsage::Position)?;
277 view.write_3_f32(
278 VertexAttributeUsage::Position,
279 transform.transform_point(&Point3::from(position)).coords,
280 )?;
281 let normal = view.read_3_f32(VertexAttributeUsage::Normal)?;
282 view.write_3_f32(
283 VertexAttributeUsage::Normal,
284 normal_matrix.transform_vector(&normal),
285 )?;
286 let tangent = view.read_4_f32(VertexAttributeUsage::Tangent)?;
287 let new_tangent = normal_matrix.transform_vector(&tangent.xyz());
288 view.write_4_f32(
290 VertexAttributeUsage::Tangent,
291 Vector4::new(new_tangent.x, new_tangent.y, new_tangent.z, tangent.w),
292 )?;
293 }
294
295 Ok(())
296 }
297
298 pub fn from_raw_mesh<T>(raw: RawMesh<T>) -> Self
301 where
302 T: VertexTrait,
303 {
304 Self {
305 vertex_buffer: VertexBuffer::new(raw.vertices.len(), raw.vertices).unwrap(),
306 geometry_buffer: TriangleBuffer::new(raw.triangles),
307 blend_shapes_container: Default::default(),
308 cache_index: Arc::new(AtomicIndex::unassigned()),
309 }
310 }
311
312 pub fn calculate_tangents(&mut self) -> Result<(), VertexFetchError> {
318 let mut tan1 = vec![Vector3::default(); self.vertex_buffer.vertex_count() as usize];
319 let mut tan2 = vec![Vector3::default(); self.vertex_buffer.vertex_count() as usize];
320
321 for triangle in self.geometry_buffer.iter() {
322 let i1 = triangle[0] as usize;
323 let i2 = triangle[1] as usize;
324 let i3 = triangle[2] as usize;
325
326 let view1 = &self.vertex_buffer.get(i1).unwrap();
327 let view2 = &self.vertex_buffer.get(i2).unwrap();
328 let view3 = &self.vertex_buffer.get(i3).unwrap();
329
330 let v1 = view1.read_3_f32(VertexAttributeUsage::Position)?;
331 let v2 = view2.read_3_f32(VertexAttributeUsage::Position)?;
332 let v3 = view3.read_3_f32(VertexAttributeUsage::Position)?;
333
334 if v1 == v2 || v1 == v3 || v2 == v3 {
336 Log::warn(format!(
337 "Degenerated triangle found when calculating tangents. Lighting may be \
338 incorrect! Triangle indices: {triangle:?}. Triangle vertices: {v1:?} {v2:?} {v3:?}",
339 ));
340 }
341
342 let w1 = view1.read_3_f32(VertexAttributeUsage::TexCoord0)?;
343 let w2 = view2.read_3_f32(VertexAttributeUsage::TexCoord0)?;
344 let w3 = view3.read_3_f32(VertexAttributeUsage::TexCoord0)?;
345
346 let x1 = v2.x - v1.x;
347 let x2 = v3.x - v1.x;
348 let y1 = v2.y - v1.y;
349 let y2 = v3.y - v1.y;
350 let z1 = v2.z - v1.z;
351 let z2 = v3.z - v1.z;
352
353 let s1 = w2.x - w1.x;
354 let s2 = w3.x - w1.x;
355 let t1 = w2.y - w1.y;
356 let t2 = w3.y - w1.y;
357
358 let r = 1.0 / (s1 * t2 - s2 * t1);
359
360 let sdir = Vector3::new(
361 (t2 * x1 - t1 * x2) * r,
362 (t2 * y1 - t1 * y2) * r,
363 (t2 * z1 - t1 * z2) * r,
364 );
365
366 tan1[i1] += sdir;
367 tan1[i2] += sdir;
368 tan1[i3] += sdir;
369
370 let tdir = Vector3::new(
371 (s1 * x2 - s2 * x1) * r,
372 (s1 * y2 - s2 * y1) * r,
373 (s1 * z2 - s2 * z1) * r,
374 );
375 tan2[i1] += tdir;
376 tan2[i2] += tdir;
377 tan2[i3] += tdir;
378 }
379
380 let mut vertex_buffer_mut = self.vertex_buffer.modify();
381 for (mut view, (t1, t2)) in vertex_buffer_mut.iter_mut().zip(tan1.into_iter().zip(tan2)) {
382 let normal = view.read_3_f32(VertexAttributeUsage::Normal)?;
383
384 let tangent = (t1 - normal.scale(normal.dot(&t1)))
386 .try_normalize(f32::EPSILON)
387 .unwrap_or_else(|| Vector3::new(0.0, 1.0, 0.0));
388 let handedness = normal.cross(&t1).dot(&t2).signum();
389 view.write_4_f32(
390 VertexAttributeUsage::Tangent,
391 Vector4::new(tangent.x, tangent.y, tangent.z, handedness),
392 )?;
393 }
394
395 Ok(())
396 }
397
398 pub fn make_unit_xy_quad() -> Self {
400 let vertices = vec![
401 StaticVertex {
402 position: Vector3::default(),
403 normal: Vector3::z(),
404 tex_coord: Vector2::y(),
405 tangent: Vector4::default(),
406 },
407 StaticVertex {
408 position: Vector3::x(),
409 normal: Vector3::z(),
410 tex_coord: Vector2::new(1.0, 1.0),
411 tangent: Vector4::default(),
412 },
413 StaticVertex {
414 position: Vector3::new(1.0, 1.0, 0.0),
415 normal: Vector3::z(),
416 tex_coord: Vector2::x(),
417 tangent: Vector4::default(),
418 },
419 StaticVertex {
420 position: Vector3::y(),
421 normal: Vector3::z(),
422 tex_coord: Vector2::default(),
423 tangent: Vector4::default(),
424 },
425 ];
426
427 let triangles = vec![TriangleDefinition([0, 1, 2]), TriangleDefinition([0, 2, 3])];
428
429 Self::new(
430 VertexBuffer::new(vertices.len(), vertices).unwrap(),
431 TriangleBuffer::new(triangles),
432 )
433 }
434
435 pub fn make_collapsed_xy_quad() -> Self {
438 let vertices = vec![
439 StaticVertex {
440 position: Vector3::default(),
441 normal: Vector3::z(),
442 tex_coord: Vector2::default(),
443 tangent: Vector4::default(),
444 },
445 StaticVertex {
446 position: Vector3::default(),
447 normal: Vector3::z(),
448 tex_coord: Vector2::x(),
449 tangent: Vector4::default(),
450 },
451 StaticVertex {
452 position: Vector3::default(),
453 normal: Vector3::z(),
454 tex_coord: Vector2::new(1.0, 1.0),
455 tangent: Vector4::default(),
456 },
457 StaticVertex {
458 position: Vector3::default(),
459 normal: Vector3::z(),
460 tex_coord: Vector2::y(),
461 tangent: Vector4::default(),
462 },
463 ];
464
465 let triangles = vec![TriangleDefinition([0, 1, 2]), TriangleDefinition([0, 2, 3])];
466
467 Self::new(
468 VertexBuffer::new(vertices.len(), vertices).unwrap(),
469 TriangleBuffer::new(triangles),
470 )
471 }
472
473 pub fn make_quad(transform: &Matrix4<f32>) -> Self {
475 let vertices = vec![
476 StaticVertex {
477 position: Vector3::new(-0.5, 0.5, 0.0),
478 normal: -Vector3::z(),
479 tex_coord: Vector2::new(1.0, 1.0),
480 tangent: Vector4::default(),
481 },
482 StaticVertex {
483 position: Vector3::new(0.5, 0.5, 0.0),
484 normal: -Vector3::z(),
485 tex_coord: Vector2::new(0.0, 1.0),
486 tangent: Vector4::default(),
487 },
488 StaticVertex {
489 position: Vector3::new(0.5, -0.5, 0.0),
490 normal: -Vector3::z(),
491 tex_coord: Vector2::new(0.0, 0.0),
492 tangent: Vector4::default(),
493 },
494 StaticVertex {
495 position: Vector3::new(-0.5, -0.5, 0.0),
496 normal: -Vector3::z(),
497 tex_coord: Vector2::new(1.0, 0.0),
498 tangent: Vector4::default(),
499 },
500 ];
501
502 let mut data = Self::new(
503 VertexBuffer::new(vertices.len(), vertices).unwrap(),
504 TriangleBuffer::new(vec![
505 TriangleDefinition([0, 1, 2]),
506 TriangleDefinition([0, 2, 3]),
507 ]),
508 );
509 data.calculate_tangents().unwrap();
510 data.transform_geometry(transform).unwrap();
511 data
512 }
513
514 pub fn calculate_normals(&mut self) -> Result<(), VertexFetchError> {
516 let mut vertex_buffer_mut = self.vertex_buffer.modify();
517 for triangle in self.geometry_buffer.iter() {
518 let ia = triangle[0] as usize;
519 let ib = triangle[1] as usize;
520 let ic = triangle[2] as usize;
521
522 let a = vertex_buffer_mut
523 .get(ia)
524 .unwrap()
525 .read_3_f32(VertexAttributeUsage::Position)?;
526 let b = vertex_buffer_mut
527 .get(ib)
528 .unwrap()
529 .read_3_f32(VertexAttributeUsage::Position)?;
530 let c = vertex_buffer_mut
531 .get(ic)
532 .unwrap()
533 .read_3_f32(VertexAttributeUsage::Position)?;
534
535 let normal = (b - a).cross(&(c - a)).normalize();
536
537 vertex_buffer_mut
538 .get_mut(ia)
539 .unwrap()
540 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
541 vertex_buffer_mut
542 .get_mut(ib)
543 .unwrap()
544 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
545 vertex_buffer_mut
546 .get_mut(ic)
547 .unwrap()
548 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
549 }
550
551 Ok(())
552 }
553
554 pub fn make_sphere(slices: usize, stacks: usize, r: f32, transform: &Matrix4<f32>) -> Self {
558 let mut builder = RawMeshBuilder::<StaticVertex>::new(stacks * slices, stacks * slices * 3);
559
560 let d_theta = std::f32::consts::PI / slices as f32;
561 let d_phi = 2.0 * std::f32::consts::PI / stacks as f32;
562 let d_tc_y = 1.0 / stacks as f32;
563 let d_tc_x = 1.0 / slices as f32;
564
565 for i in 0..stacks {
566 for j in 0..slices {
567 let nj = j + 1;
568 let ni = i + 1;
569
570 let k0 = r * (d_theta * i as f32).sin();
571 let k1 = (d_phi * j as f32).cos();
572 let k2 = (d_phi * j as f32).sin();
573 let k3 = r * (d_theta * i as f32).cos();
574
575 let k4 = r * (d_theta * ni as f32).sin();
576 let k5 = (d_phi * nj as f32).cos();
577 let k6 = (d_phi * nj as f32).sin();
578 let k7 = r * (d_theta * ni as f32).cos();
579
580 if i != (stacks - 1) {
581 let v0 = Vector3::new(k0 * k1, k0 * k2, k3);
582 let t0 = Vector2::new(d_tc_x * j as f32, d_tc_y * i as f32);
583
584 let v1 = Vector3::new(k4 * k1, k4 * k2, k7);
585 let t1 = Vector2::new(d_tc_x * j as f32, d_tc_y * ni as f32);
586
587 let v2 = Vector3::new(k4 * k5, k4 * k6, k7);
588 let t2 = Vector2::new(d_tc_x * nj as f32, d_tc_y * ni as f32);
589
590 builder.insert(StaticVertex::from_pos_uv_normal(v0, t0, v0));
591 builder.insert(StaticVertex::from_pos_uv_normal(v1, t1, v1));
592 builder.insert(StaticVertex::from_pos_uv_normal(v2, t2, v2));
593 }
594
595 if i != 0 {
596 let v0 = Vector3::new(k4 * k5, k4 * k6, k7);
597 let t0 = Vector2::new(d_tc_x * nj as f32, d_tc_y * ni as f32);
598
599 let v1 = Vector3::new(k0 * k5, k0 * k6, k3);
600 let t1 = Vector2::new(d_tc_x * nj as f32, d_tc_y * i as f32);
601
602 let v2 = Vector3::new(k0 * k1, k0 * k2, k3);
603 let t2 = Vector2::new(d_tc_x * j as f32, d_tc_y * i as f32);
604
605 builder.insert(StaticVertex::from_pos_uv_normal(v0, t0, v0));
606 builder.insert(StaticVertex::from_pos_uv_normal(v1, t1, v1));
607 builder.insert(StaticVertex::from_pos_uv_normal(v2, t2, v2));
608 }
609 }
610 }
611
612 let mut data = Self::from_raw_mesh(builder.build());
613 data.calculate_tangents().unwrap();
614 data.transform_geometry(transform).unwrap();
615 data
616 }
617
618 pub fn make_cone(sides: usize, r: f32, h: f32, transform: &Matrix4<f32>) -> Self {
622 let mut builder = RawMeshBuilder::<StaticVertex>::new(3 * sides, 3 * sides);
623
624 let d_phi = 2.0 * std::f32::consts::PI / sides as f32;
625 let d_theta = 1.0 / sides as f32;
626
627 for i in 0..sides {
628 let nx0 = (d_phi * i as f32).cos();
629 let ny0 = (d_phi * i as f32).sin();
630 let nx1 = (d_phi * (i + 1) as f32).cos();
631 let ny1 = (d_phi * (i + 1) as f32).sin();
632
633 let x0 = r * nx0;
634 let z0 = r * ny0;
635 let x1 = r * nx1;
636 let z1 = r * ny1;
637 let tx0 = d_theta * i as f32;
638 let tx1 = d_theta * (i + 1) as f32;
639
640 let (t_cap_y_curr, t_cap_x_curr) = (d_phi * i as f32).sin_cos();
642 let (t_cap_y_next, t_cap_x_next) = (d_phi * (i + 1) as f32).sin_cos();
643
644 let t_cap_x_curr = t_cap_x_curr * 0.5 + 0.5;
645 let t_cap_y_curr = t_cap_y_curr * 0.5 + 0.5;
646
647 let t_cap_x_next = t_cap_x_next * 0.5 + 0.5;
648 let t_cap_y_next = t_cap_y_next * 0.5 + 0.5;
649
650 builder.insert(StaticVertex::from_pos_uv_normal(
651 Vector3::new(0.0, 0.0, 0.0),
652 Vector2::new(0.5, 0.5),
653 Vector3::new(0.0, -1.0, 0.0),
654 ));
655 builder.insert(StaticVertex::from_pos_uv_normal(
656 Vector3::new(x0, 0.0, z0),
657 Vector2::new(t_cap_x_curr, t_cap_y_curr),
658 Vector3::new(0.0, -1.0, 0.0),
659 ));
660 builder.insert(StaticVertex::from_pos_uv_normal(
661 Vector3::new(x1, 0.0, z1),
662 Vector2::new(t_cap_x_next, t_cap_y_next),
663 Vector3::new(0.0, -1.0, 0.0),
664 ));
665
666 let tip = Vector3::new(0.0, h, 0.0);
668 let v_curr = Vector3::new(x0, 0.0, z0);
669 let v_next = Vector3::new(x1, 0.0, z1);
670 let n_next = (tip - v_next).cross(&(v_next - v_curr));
671 let n_curr = (tip - v_curr).cross(&(v_next - v_curr));
672
673 builder.insert(StaticVertex::from_pos_uv_normal(
674 tip,
675 Vector2::new(0.5, 0.0),
676 n_curr,
677 ));
678 builder.insert(StaticVertex::from_pos_uv_normal(
679 v_next,
680 Vector2::new(tx1, 1.0),
681 n_next,
682 ));
683 builder.insert(StaticVertex::from_pos_uv_normal(
684 v_curr,
685 Vector2::new(tx0, 1.0),
686 n_curr,
687 ));
688 }
689
690 let mut data = Self::from_raw_mesh(builder.build());
691 data.calculate_tangents().unwrap();
692 data.transform_geometry(transform).unwrap();
693 data
694 }
695
696 pub fn make_torus(
701 inner_radius: f32,
702 outer_radius: f32,
703 num_rings: usize,
704 num_segments: usize,
705 transform: &Matrix4<f32>,
706 ) -> Self {
707 let mut vertices = Vec::new();
708 for j in 0..=num_rings {
709 for i in 0..=num_segments {
710 let u = i as f32 / num_segments as f32 * std::f32::consts::TAU;
711 let v = j as f32 / num_rings as f32 * std::f32::consts::TAU;
712
713 let center = Vector3::new(inner_radius * u.cos(), inner_radius * u.sin(), 0.0);
714
715 let position = Vector3::new(
716 (inner_radius + outer_radius * v.cos()) * u.cos(),
717 outer_radius * v.sin(),
718 (inner_radius + outer_radius * v.cos()) * u.sin(),
719 );
720
721 let uv = Vector2::new(i as f32 / num_segments as f32, j as f32 / num_rings as f32);
722
723 let normal = (position - center)
724 .try_normalize(f32::EPSILON)
725 .unwrap_or_default();
726
727 vertices.push(StaticVertex::from_pos_uv_normal(position, uv, normal));
728 }
729 }
730
731 let mut triangles = Vec::new();
732 for j in 1..=num_rings {
733 for i in 1..=num_segments {
734 let a = ((num_segments + 1) * j + i - 1) as u32;
735 let b = ((num_segments + 1) * (j - 1) + i - 1) as u32;
736 let c = ((num_segments + 1) * (j - 1) + i) as u32;
737 let d = ((num_segments + 1) * j + i) as u32;
738
739 triangles.push(TriangleDefinition([d, b, a]));
740 triangles.push(TriangleDefinition([d, c, b]));
741 }
742 }
743
744 let mut data = Self::new(
745 VertexBuffer::new(vertices.len(), vertices).unwrap(),
746 TriangleBuffer::new(triangles),
747 );
748 data.calculate_tangents().unwrap();
749 data.transform_geometry(transform).unwrap();
750 data
751 }
752
753 pub fn make_cylinder(
757 sides: usize,
758 r: f32,
759 h: f32,
760 caps: bool,
761 transform: &Matrix4<f32>,
762 ) -> Self {
763 let mut builder = RawMeshBuilder::<StaticVertex>::new(3 * sides, 3 * sides);
764
765 let d_phi = 2.0 * std::f32::consts::PI / sides as f32;
766 let d_theta = 1.0 / sides as f32;
767
768 for i in 0..sides {
769 let nx0 = (d_phi * i as f32).cos();
770 let ny0 = (d_phi * i as f32).sin();
771 let nx1 = (d_phi * (i + 1) as f32).cos();
772 let ny1 = (d_phi * (i + 1) as f32).sin();
773
774 let x0 = r * nx0;
775 let z0 = r * ny0;
776 let x1 = r * nx1;
777 let z1 = r * ny1;
778
779 if caps {
780 let (t_cap_y_curr, t_cap_x_curr) = (d_phi * i as f32).sin_cos();
781 let (t_cap_y_next, t_cap_x_next) = (d_phi * (i + 1) as f32).sin_cos();
782
783 let t_cap_x_curr = t_cap_x_curr * 0.5 + 0.5;
784 let t_cap_y_curr = t_cap_y_curr * 0.5 + 0.5;
785
786 let t_cap_x_next = t_cap_x_next * 0.5 + 0.5;
787 let t_cap_y_next = t_cap_y_next * 0.5 + 0.5;
788
789 builder.insert(StaticVertex::from_pos_uv_normal(
791 Vector3::new(x1, h, z1),
792 Vector2::new(t_cap_x_next, t_cap_y_next),
793 Vector3::new(0.0, 1.0, 0.0),
794 ));
795 builder.insert(StaticVertex::from_pos_uv_normal(
796 Vector3::new(x0, h, z0),
797 Vector2::new(t_cap_x_curr, t_cap_y_curr),
798 Vector3::new(0.0, 1.0, 0.0),
799 ));
800 builder.insert(StaticVertex::from_pos_uv_normal(
801 Vector3::new(0.0, h, 0.0),
802 Vector2::new(0.5, 0.5),
803 Vector3::new(0.0, 1.0, 0.0),
804 ));
805
806 builder.insert(StaticVertex::from_pos_uv_normal(
808 Vector3::new(x0, 0.0, z0),
809 Vector2::new(t_cap_x_curr, t_cap_y_curr),
810 Vector3::new(0.0, -1.0, 0.0),
811 ));
812 builder.insert(StaticVertex::from_pos_uv_normal(
813 Vector3::new(x1, 0.0, z1),
814 Vector2::new(t_cap_x_next, t_cap_y_next),
815 Vector3::new(0.0, -1.0, 0.0),
816 ));
817 builder.insert(StaticVertex::from_pos_uv_normal(
818 Vector3::new(0.0, 0.0, 0.0),
819 Vector2::new(0.5, 0.5),
820 Vector3::new(0.0, -1.0, 0.0),
821 ));
822 }
823
824 let t_side_curr = d_theta * i as f32;
825 let t_side_next = d_theta * (i + 1) as f32;
826
827 builder.insert(StaticVertex::from_pos_uv_normal(
829 Vector3::new(x0, 0.0, z0),
830 Vector2::new(t_side_curr, 0.0),
831 Vector3::new(x0, 0.0, z0),
832 ));
833 builder.insert(StaticVertex::from_pos_uv_normal(
834 Vector3::new(x0, h, z0),
835 Vector2::new(t_side_curr, 1.0),
836 Vector3::new(x0, 0.0, z0),
837 ));
838 builder.insert(StaticVertex::from_pos_uv_normal(
839 Vector3::new(x1, 0.0, z1),
840 Vector2::new(t_side_next, 0.0),
841 Vector3::new(x1, 0.0, z1),
842 ));
843
844 builder.insert(StaticVertex::from_pos_uv_normal(
845 Vector3::new(x1, 0.0, z1),
846 Vector2::new(t_side_next, 0.0),
847 Vector3::new(x1, 0.0, z1),
848 ));
849 builder.insert(StaticVertex::from_pos_uv_normal(
850 Vector3::new(x0, h, z0),
851 Vector2::new(t_side_curr, 1.0),
852 Vector3::new(x0, 0.0, z0),
853 ));
854 builder.insert(StaticVertex::from_pos_uv_normal(
855 Vector3::new(x1, h, z1),
856 Vector2::new(t_side_next, 1.0),
857 Vector3::new(x1, 0.0, z1),
858 ));
859 }
860
861 let mut data = Self::from_raw_mesh(builder.build());
862 data.calculate_tangents().unwrap();
863 data.transform_geometry(transform).unwrap();
864 data
865 }
866
867 pub fn make_cube(transform: Matrix4<f32>) -> Self {
869 let vertices = vec![
870 StaticVertex {
872 position: Vector3::new(-0.5, -0.5, 0.5),
873 normal: Vector3::z(),
874 tex_coord: Vector2::default(),
875 tangent: Vector4::default(),
876 },
877 StaticVertex {
878 position: Vector3::new(-0.5, 0.5, 0.5),
879 normal: Vector3::z(),
880 tex_coord: Vector2::y(),
881 tangent: Vector4::default(),
882 },
883 StaticVertex {
884 position: Vector3::new(0.5, 0.5, 0.5),
885 normal: Vector3::z(),
886 tex_coord: Vector2::new(1.0, 1.0),
887 tangent: Vector4::default(),
888 },
889 StaticVertex {
890 position: Vector3::new(0.5, -0.5, 0.5),
891 normal: Vector3::z(),
892 tex_coord: Vector2::x(),
893 tangent: Vector4::default(),
894 },
895 StaticVertex {
897 position: Vector3::new(-0.5, -0.5, -0.5),
898 normal: -Vector3::z(),
899 tex_coord: Vector2::default(),
900 tangent: Vector4::default(),
901 },
902 StaticVertex {
903 position: Vector3::new(-0.5, 0.5, -0.5),
904 normal: -Vector3::z(),
905 tex_coord: Vector2::y(),
906 tangent: Vector4::default(),
907 },
908 StaticVertex {
909 position: Vector3::new(0.5, 0.5, -0.5),
910 normal: -Vector3::z(),
911 tex_coord: Vector2::new(1.0, 1.0),
912 tangent: Vector4::default(),
913 },
914 StaticVertex {
915 position: Vector3::new(0.5, -0.5, -0.5),
916 normal: -Vector3::z(),
917 tex_coord: Vector2::x(),
918 tangent: Vector4::default(),
919 },
920 StaticVertex {
922 position: Vector3::new(-0.5, -0.5, -0.5),
923 normal: -Vector3::x(),
924 tex_coord: Vector2::default(),
925 tangent: Vector4::default(),
926 },
927 StaticVertex {
928 position: Vector3::new(-0.5, 0.5, -0.5),
929 normal: -Vector3::x(),
930 tex_coord: Vector2::y(),
931 tangent: Vector4::default(),
932 },
933 StaticVertex {
934 position: Vector3::new(-0.5, 0.5, 0.5),
935 normal: -Vector3::x(),
936 tex_coord: Vector2::new(1.0, 1.0),
937 tangent: Vector4::default(),
938 },
939 StaticVertex {
940 position: Vector3::new(-0.5, -0.5, 0.5),
941 normal: -Vector3::x(),
942 tex_coord: Vector2::x(),
943 tangent: Vector4::default(),
944 },
945 StaticVertex {
947 position: Vector3::new(0.5, -0.5, -0.5),
948 normal: Vector3::x(),
949 tex_coord: Vector2::default(),
950 tangent: Vector4::default(),
951 },
952 StaticVertex {
953 position: Vector3::new(0.5, 0.5, -0.5),
954 normal: Vector3::x(),
955 tex_coord: Vector2::y(),
956 tangent: Vector4::default(),
957 },
958 StaticVertex {
959 position: Vector3::new(0.5, 0.5, 0.5),
960 normal: Vector3::x(),
961 tex_coord: Vector2::new(1.0, 1.0),
962 tangent: Vector4::default(),
963 },
964 StaticVertex {
965 position: Vector3::new(0.5, -0.5, 0.5),
966 normal: Vector3::x(),
967 tex_coord: Vector2::x(),
968 tangent: Vector4::default(),
969 },
970 StaticVertex {
972 position: Vector3::new(-0.5, 0.5, 0.5),
973 normal: Vector3::y(),
974 tex_coord: Vector2::default(),
975 tangent: Vector4::default(),
976 },
977 StaticVertex {
978 position: Vector3::new(-0.5, 0.5, -0.5),
979 normal: Vector3::y(),
980 tex_coord: Vector2::y(),
981 tangent: Vector4::default(),
982 },
983 StaticVertex {
984 position: Vector3::new(0.5, 0.5, -0.5),
985 normal: Vector3::y(),
986 tex_coord: Vector2::new(1.0, 1.0),
987 tangent: Vector4::default(),
988 },
989 StaticVertex {
990 position: Vector3::new(0.5, 0.5, 0.5),
991 normal: Vector3::y(),
992 tex_coord: Vector2::x(),
993 tangent: Vector4::default(),
994 },
995 StaticVertex {
997 position: Vector3::new(-0.5, -0.5, 0.5),
998 normal: -Vector3::y(),
999 tex_coord: Vector2::default(),
1000 tangent: Vector4::default(),
1001 },
1002 StaticVertex {
1003 position: Vector3::new(-0.5, -0.5, -0.5),
1004 normal: -Vector3::y(),
1005 tex_coord: Vector2::y(),
1006 tangent: Vector4::default(),
1007 },
1008 StaticVertex {
1009 position: Vector3::new(0.5, -0.5, -0.5),
1010 normal: -Vector3::y(),
1011 tex_coord: Vector2::new(1.0, 1.0),
1012 tangent: Vector4::default(),
1013 },
1014 StaticVertex {
1015 position: Vector3::new(0.5, -0.5, 0.5),
1016 normal: -Vector3::y(),
1017 tex_coord: Vector2::x(),
1018 tangent: Vector4::default(),
1019 },
1020 ];
1021
1022 let triangles = vec![
1023 TriangleDefinition([2, 1, 0]),
1024 TriangleDefinition([3, 2, 0]),
1025 TriangleDefinition([4, 5, 6]),
1026 TriangleDefinition([4, 6, 7]),
1027 TriangleDefinition([10, 9, 8]),
1028 TriangleDefinition([11, 10, 8]),
1029 TriangleDefinition([12, 13, 14]),
1030 TriangleDefinition([12, 14, 15]),
1031 TriangleDefinition([18, 17, 16]),
1032 TriangleDefinition([19, 18, 16]),
1033 TriangleDefinition([20, 21, 22]),
1034 TriangleDefinition([20, 22, 23]),
1035 ];
1036
1037 let mut data = Self::new(
1038 VertexBuffer::new(vertices.len(), vertices).unwrap(),
1039 TriangleBuffer::new(triangles),
1040 );
1041 data.calculate_tangents().unwrap();
1042 data.transform_geometry(&transform).unwrap();
1043 data
1044 }
1045
1046 pub fn content_hash(&self) -> u64 {
1049 hash_combine(
1050 self.geometry_buffer.content_hash(),
1051 self.vertex_buffer.content_hash(),
1052 )
1053 }
1054
1055 pub fn clear(&mut self) {
1057 self.geometry_buffer.modify().clear();
1058 self.vertex_buffer.modify().clear();
1059 }
1060}
1061
1062impl Visit for SurfaceData {
1063 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1064 let mut region = visitor.enter_region(name)?;
1065
1066 self.vertex_buffer.visit("VertexBuffer", &mut region)?;
1067 self.geometry_buffer.visit("GeometryBuffer", &mut region)?;
1068
1069 Ok(())
1070 }
1071}
1072
1073#[derive(Copy, Clone, PartialEq, Debug)]
1075pub struct VertexWeight {
1076 pub value: f32,
1078 pub effector: ErasedHandle,
1085}
1086
1087impl Default for VertexWeight {
1088 fn default() -> Self {
1089 Self {
1090 value: 0.0,
1091 effector: ErasedHandle::none(),
1092 }
1093 }
1094}
1095
1096#[derive(Copy, Clone, Debug, PartialEq, Default)]
1098pub struct VertexWeightSet {
1099 weights: [VertexWeight; 4],
1100 count: usize,
1101}
1102
1103impl VertexWeightSet {
1104 pub fn push(&mut self, weight: VertexWeight) -> bool {
1107 if self.count < self.weights.len() {
1108 self.weights[self.count] = weight;
1109 self.count += 1;
1110 true
1111 } else {
1112 false
1113 }
1114 }
1115
1116 pub fn len(&self) -> usize {
1118 self.count
1119 }
1120
1121 pub fn is_empty(&self) -> bool {
1123 self.count == 0
1124 }
1125
1126 pub fn iter(&self) -> std::slice::Iter<VertexWeight> {
1128 self.weights[0..self.count].iter()
1129 }
1130
1131 pub fn iter_mut(&mut self) -> std::slice::IterMut<VertexWeight> {
1133 self.weights[0..self.count].iter_mut()
1134 }
1135
1136 pub fn normalize(&mut self) {
1141 let len = self.iter().fold(0.0, |qs, w| qs + w.value * w.value).sqrt();
1142 if len >= f32::EPSILON {
1143 let k = 1.0 / len;
1144 for w in self.iter_mut() {
1145 w.value *= k;
1146 }
1147 }
1148 }
1149}
1150
1151pub type SurfaceResource = Resource<SurfaceData>;
1155
1156pub trait SurfaceResourceExtension {
1158 fn deep_clone(&self) -> Self;
1160}
1161
1162impl SurfaceResourceExtension for SurfaceResource {
1163 fn deep_clone(&self) -> Self {
1164 Self::new_ok(
1165 Uuid::new_v4(),
1166 ResourceKind::Embedded,
1167 self.data_ref().clone(),
1168 )
1169 }
1170}
1171
1172#[derive(Debug, Reflect, Visit, PartialEq)]
1253pub struct Surface {
1254 pub(crate) data: InheritableVariable<SurfaceResource>,
1255
1256 pub(crate) material: InheritableVariable<MaterialResource>,
1257
1258 pub bones: InheritableVariable<Vec<Handle<Node>>>,
1260
1261 unique_material: InheritableVariable<bool>,
1265
1266 #[reflect(hidden)]
1273 #[visit(skip)]
1274 pub(crate) vertex_weights: Vec<VertexWeightSet>,
1275}
1276
1277uuid_provider!(Surface = "485caf12-4e7d-4b1a-b6bd-0681fd92f789");
1278
1279impl Clone for Surface {
1280 fn clone(&self) -> Self {
1281 Self {
1282 data: self.data.clone(),
1283 material: if *self.unique_material {
1284 self.material.deep_copy_as_embedded().into()
1286 } else {
1287 self.material.clone()
1289 },
1290 bones: self.bones.clone(),
1291 unique_material: self.unique_material.clone(),
1292 vertex_weights: self.vertex_weights.clone(),
1293 }
1294 }
1295}
1296
1297impl Default for Surface {
1298 fn default() -> Self {
1299 Self {
1300 data: SurfaceResource::new_ok(
1301 Uuid::new_v4(),
1302 ResourceKind::Embedded,
1303 SurfaceData::make_cube(Matrix4::identity()),
1304 )
1305 .into(),
1306 material: MaterialResource::new_ok(
1307 Uuid::new_v4(),
1308 Default::default(),
1309 Material::standard(),
1310 )
1311 .into(),
1312 vertex_weights: Default::default(),
1313 bones: Default::default(),
1314 unique_material: Default::default(),
1315 }
1316 }
1317}
1318
1319impl Surface {
1320 #[inline]
1322 pub fn new(data: SurfaceResource) -> Self {
1323 Self {
1324 data: data.into(),
1325 ..Default::default()
1326 }
1327 }
1328
1329 pub fn material_id(&self) -> u64 {
1331 self.material.key()
1332 }
1333
1334 pub fn batch_id(&self) -> u64 {
1336 let mut hasher = FxHasher::default();
1337 hasher.write_u64(self.material_id());
1338 hasher.write_u64(self.data.key());
1339 hasher.finish()
1340 }
1341
1342 #[inline]
1344 pub fn data(&self) -> SurfaceResource {
1345 (*self.data).clone()
1346 }
1347
1348 #[inline]
1350 pub fn data_ref(&self) -> &SurfaceResource {
1351 &self.data
1352 }
1353
1354 pub fn material(&self) -> &MaterialResource {
1356 &self.material
1357 }
1358
1359 pub fn set_material(&mut self, material: MaterialResource) {
1361 self.material.set_value_and_mark_modified(material);
1362 }
1363
1364 #[inline]
1366 pub fn bones(&self) -> &[Handle<Node>] {
1367 &self.bones
1368 }
1369
1370 pub fn is_unique_material(&self) -> bool {
1372 *self.unique_material
1373 }
1374
1375 pub fn set_unique_material(&mut self, unique: bool) {
1377 self.unique_material.set_value_and_mark_modified(unique);
1378 }
1379}
1380
1381pub struct SurfaceBuilder {
1383 data: SurfaceResource,
1384 material: Option<MaterialResource>,
1385 bones: Vec<Handle<Node>>,
1386 unique_material: bool,
1387}
1388
1389impl SurfaceBuilder {
1390 pub fn new(data: SurfaceResource) -> Self {
1392 Self {
1393 data,
1394 material: None,
1395 bones: Default::default(),
1396 unique_material: false,
1397 }
1398 }
1399
1400 pub fn with_material(mut self, material: MaterialResource) -> Self {
1402 self.material = Some(material);
1403 self
1404 }
1405
1406 pub fn with_bones(mut self, bones: Vec<Handle<Node>>) -> Self {
1408 self.bones = bones;
1409 self
1410 }
1411
1412 pub fn with_unique_material(mut self, unique: bool) -> Self {
1414 self.unique_material = unique;
1415 self
1416 }
1417
1418 pub fn build(self) -> Surface {
1420 Surface {
1421 data: self.data.into(),
1422 material: self
1423 .material
1424 .unwrap_or_else(|| {
1425 MaterialResource::new_ok(
1426 Uuid::new_v4(),
1427 Default::default(),
1428 Material::standard(),
1429 )
1430 })
1431 .into(),
1432 vertex_weights: Default::default(),
1433 bones: self.bones.into(),
1434 unique_material: self.unique_material.into(),
1435 }
1436 }
1437}
1438
1439pub struct SurfaceDataLoader {}
1441
1442impl ResourceLoader for SurfaceDataLoader {
1443 fn extensions(&self) -> &[&str] {
1444 &["surface"]
1445 }
1446
1447 fn is_native_extension(&self, ext: &str) -> bool {
1448 fyrox_core::cmp_strings_case_insensitive(ext, "surface")
1449 }
1450
1451 fn data_type_uuid(&self) -> Uuid {
1452 <SurfaceData as TypeUuidProvider>::type_uuid()
1453 }
1454
1455 fn load(&self, path: PathBuf, io: Arc<dyn ResourceIo>) -> BoxedLoaderFuture {
1456 Box::pin(async move {
1457 let io = io.as_ref();
1458
1459 let data = io.load_file(&path).await.map_err(LoadError::new)?;
1460 let mut visitor = Visitor::load_from_memory(&data).map_err(LoadError::new)?;
1461 let mut surface_data = SurfaceData::default();
1462 surface_data
1463 .visit("SurfaceData", &mut visitor)
1464 .map_err(LoadError::new)?;
1465 Ok(LoaderPayload::new(surface_data))
1466 })
1467 }
1468}
1469
1470pub static CUBE: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1472 BuiltInResource::new_no_source(
1473 "__CubeSurface",
1474 SurfaceResource::new_ok(
1475 uuid!("d3a4604a-e1c6-430b-b524-8d3213723952"),
1476 ResourceKind::External,
1477 SurfaceData::make_cube(Matrix4::identity()),
1478 ),
1479 )
1480});
1481
1482pub static QUAD: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1484 BuiltInResource::new_no_source(
1485 "__QuadSurface",
1486 SurfaceResource::new_ok(
1487 uuid!("a124317f-640b-4c1b-9fdc-af62f745eeba"),
1488 ResourceKind::External,
1489 SurfaceData::make_quad(&Matrix4::identity()),
1490 ),
1491 )
1492});
1493
1494pub static CYLINDER: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1496 BuiltInResource::new_no_source(
1497 "__CylinderSurface",
1498 SurfaceResource::new_ok(
1499 uuid!("16300ec8-4446-41a7-8ad6-9b45428d0b1b"),
1500 ResourceKind::External,
1501 SurfaceData::make_cylinder(32, 1.0, 1.0, true, &Matrix4::identity()),
1502 ),
1503 )
1504});
1505
1506pub static SPHERE: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1508 BuiltInResource::new_no_source(
1509 "__SphereSurface",
1510 SurfaceResource::new_ok(
1511 uuid!("ff1811ba-b9ad-4c37-89b8-503f79aaa4bd"),
1512 ResourceKind::External,
1513 SurfaceData::make_sphere(32, 32, 1.0, &Matrix4::identity()),
1514 ),
1515 )
1516});
1517
1518pub static CONE: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1520 BuiltInResource::new_no_source(
1521 "__ConeSurface",
1522 SurfaceResource::new_ok(
1523 uuid!("e4e79405-39c5-4fe4-ba3e-c961f3d7379e"),
1524 ResourceKind::External,
1525 SurfaceData::make_cone(32, 1.0, 1.0, &Matrix4::identity()),
1526 ),
1527 )
1528});
1529
1530pub static TORUS: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1532 BuiltInResource::new_no_source(
1533 "__TorusSurface",
1534 SurfaceResource::new_ok(
1535 uuid!("d2bb5455-c72e-475d-90da-e3a7bd5b7d07"),
1536 ResourceKind::External,
1537 SurfaceData::make_torus(1.0, 0.25, 32, 32, &Matrix4::identity()),
1538 ),
1539 )
1540});