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 let mut visitor = Visitor::new();
246 self.visit("SurfaceData", &mut visitor)?;
247 visitor.save_ascii_to_file(path)?;
248 Ok(())
249 }
250
251 fn can_be_saved(&self) -> bool {
252 true
253 }
254
255 fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
256 Some(Box::new(self.clone()))
257 }
258}
259
260impl SurfaceData {
261 pub fn new(vertex_buffer: VertexBuffer, triangles: TriangleBuffer) -> Self {
263 Self {
264 vertex_buffer,
265 geometry_buffer: triangles,
266 blend_shapes_container: None,
267 cache_index: Arc::new(AtomicIndex::unassigned()),
268 }
269 }
270
271 pub fn transform_geometry(&mut self, transform: &Matrix4<f32>) -> Result<(), VertexFetchError> {
273 let normal_matrix = transform.try_inverse().unwrap_or_default().transpose();
275
276 let mut vertex_buffer_mut = self.vertex_buffer.modify();
277 for mut view in vertex_buffer_mut.iter_mut() {
278 let position = view.read_3_f32(VertexAttributeUsage::Position)?;
279 view.write_3_f32(
280 VertexAttributeUsage::Position,
281 transform.transform_point(&Point3::from(position)).coords,
282 )?;
283 let normal = view.read_3_f32(VertexAttributeUsage::Normal)?;
284 view.write_3_f32(
285 VertexAttributeUsage::Normal,
286 normal_matrix.transform_vector(&normal),
287 )?;
288 let tangent = view.read_4_f32(VertexAttributeUsage::Tangent)?;
289 let new_tangent = normal_matrix.transform_vector(&tangent.xyz());
290 view.write_4_f32(
292 VertexAttributeUsage::Tangent,
293 Vector4::new(new_tangent.x, new_tangent.y, new_tangent.z, tangent.w),
294 )?;
295 }
296
297 Ok(())
298 }
299
300 pub fn from_raw_mesh<T>(raw: RawMesh<T>) -> Self
303 where
304 T: VertexTrait,
305 {
306 Self {
307 vertex_buffer: VertexBuffer::new(raw.vertices.len(), raw.vertices).unwrap(),
308 geometry_buffer: TriangleBuffer::new(raw.triangles),
309 blend_shapes_container: Default::default(),
310 cache_index: Arc::new(AtomicIndex::unassigned()),
311 }
312 }
313
314 pub fn calculate_tangents(&mut self) -> Result<(), VertexFetchError> {
320 let mut tan1 = vec![Vector3::default(); self.vertex_buffer.vertex_count() as usize];
321 let mut tan2 = vec![Vector3::default(); self.vertex_buffer.vertex_count() as usize];
322
323 for triangle in self.geometry_buffer.iter() {
324 let i1 = triangle[0] as usize;
325 let i2 = triangle[1] as usize;
326 let i3 = triangle[2] as usize;
327
328 let view1 = &self.vertex_buffer.get(i1).unwrap();
329 let view2 = &self.vertex_buffer.get(i2).unwrap();
330 let view3 = &self.vertex_buffer.get(i3).unwrap();
331
332 let v1 = view1.read_3_f32(VertexAttributeUsage::Position)?;
333 let v2 = view2.read_3_f32(VertexAttributeUsage::Position)?;
334 let v3 = view3.read_3_f32(VertexAttributeUsage::Position)?;
335
336 if v1 == v2 || v1 == v3 || v2 == v3 {
338 Log::warn(format!(
339 "Degenerated triangle found when calculating tangents. Lighting may be \
340 incorrect! Triangle indices: {triangle:?}. Triangle vertices: {v1:?} {v2:?} {v3:?}",
341 ));
342 }
343
344 let w1 = view1.read_3_f32(VertexAttributeUsage::TexCoord0)?;
345 let w2 = view2.read_3_f32(VertexAttributeUsage::TexCoord0)?;
346 let w3 = view3.read_3_f32(VertexAttributeUsage::TexCoord0)?;
347
348 let x1 = v2.x - v1.x;
349 let x2 = v3.x - v1.x;
350 let y1 = v2.y - v1.y;
351 let y2 = v3.y - v1.y;
352 let z1 = v2.z - v1.z;
353 let z2 = v3.z - v1.z;
354
355 let s1 = w2.x - w1.x;
356 let s2 = w3.x - w1.x;
357 let t1 = w2.y - w1.y;
358 let t2 = w3.y - w1.y;
359
360 let r = 1.0 / (s1 * t2 - s2 * t1);
361
362 let sdir = Vector3::new(
363 (t2 * x1 - t1 * x2) * r,
364 (t2 * y1 - t1 * y2) * r,
365 (t2 * z1 - t1 * z2) * r,
366 );
367
368 tan1[i1] += sdir;
369 tan1[i2] += sdir;
370 tan1[i3] += sdir;
371
372 let tdir = Vector3::new(
373 (s1 * x2 - s2 * x1) * r,
374 (s1 * y2 - s2 * y1) * r,
375 (s1 * z2 - s2 * z1) * r,
376 );
377 tan2[i1] += tdir;
378 tan2[i2] += tdir;
379 tan2[i3] += tdir;
380 }
381
382 let mut vertex_buffer_mut = self.vertex_buffer.modify();
383 for (mut view, (t1, t2)) in vertex_buffer_mut.iter_mut().zip(tan1.into_iter().zip(tan2)) {
384 let normal = view.read_3_f32(VertexAttributeUsage::Normal)?;
385
386 let tangent = (t1 - normal.scale(normal.dot(&t1)))
388 .try_normalize(f32::EPSILON)
389 .unwrap_or_else(|| Vector3::new(0.0, 1.0, 0.0));
390 let handedness = normal.cross(&t1).dot(&t2).signum();
391 view.write_4_f32(
392 VertexAttributeUsage::Tangent,
393 Vector4::new(tangent.x, tangent.y, tangent.z, handedness),
394 )?;
395 }
396
397 Ok(())
398 }
399
400 pub fn make_unit_xy_quad() -> Self {
402 let vertices = vec![
403 StaticVertex {
404 position: Vector3::default(),
405 normal: Vector3::z(),
406 tex_coord: Vector2::y(),
407 tangent: Vector4::default(),
408 },
409 StaticVertex {
410 position: Vector3::x(),
411 normal: Vector3::z(),
412 tex_coord: Vector2::new(1.0, 1.0),
413 tangent: Vector4::default(),
414 },
415 StaticVertex {
416 position: Vector3::new(1.0, 1.0, 0.0),
417 normal: Vector3::z(),
418 tex_coord: Vector2::x(),
419 tangent: Vector4::default(),
420 },
421 StaticVertex {
422 position: Vector3::y(),
423 normal: Vector3::z(),
424 tex_coord: Vector2::default(),
425 tangent: Vector4::default(),
426 },
427 ];
428
429 let triangles = vec![TriangleDefinition([0, 1, 2]), TriangleDefinition([0, 2, 3])];
430
431 Self::new(
432 VertexBuffer::new(vertices.len(), vertices).unwrap(),
433 TriangleBuffer::new(triangles),
434 )
435 }
436
437 pub fn make_collapsed_xy_quad() -> Self {
440 let vertices = vec![
441 StaticVertex {
442 position: Vector3::default(),
443 normal: Vector3::z(),
444 tex_coord: Vector2::default(),
445 tangent: Vector4::default(),
446 },
447 StaticVertex {
448 position: Vector3::default(),
449 normal: Vector3::z(),
450 tex_coord: Vector2::x(),
451 tangent: Vector4::default(),
452 },
453 StaticVertex {
454 position: Vector3::default(),
455 normal: Vector3::z(),
456 tex_coord: Vector2::new(1.0, 1.0),
457 tangent: Vector4::default(),
458 },
459 StaticVertex {
460 position: Vector3::default(),
461 normal: Vector3::z(),
462 tex_coord: Vector2::y(),
463 tangent: Vector4::default(),
464 },
465 ];
466
467 let triangles = vec![TriangleDefinition([0, 1, 2]), TriangleDefinition([0, 2, 3])];
468
469 Self::new(
470 VertexBuffer::new(vertices.len(), vertices).unwrap(),
471 TriangleBuffer::new(triangles),
472 )
473 }
474
475 pub fn make_quad(transform: &Matrix4<f32>) -> Self {
477 let vertices = vec![
478 StaticVertex {
479 position: Vector3::new(-0.5, 0.5, 0.0),
480 normal: -Vector3::z(),
481 tex_coord: Vector2::new(1.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, 1.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(0.0, 0.0),
494 tangent: Vector4::default(),
495 },
496 StaticVertex {
497 position: Vector3::new(-0.5, -0.5, 0.0),
498 normal: -Vector3::z(),
499 tex_coord: Vector2::new(1.0, 0.0),
500 tangent: Vector4::default(),
501 },
502 ];
503
504 let mut data = Self::new(
505 VertexBuffer::new(vertices.len(), vertices).unwrap(),
506 TriangleBuffer::new(vec![
507 TriangleDefinition([0, 1, 2]),
508 TriangleDefinition([0, 2, 3]),
509 ]),
510 );
511 data.calculate_tangents().unwrap();
512 data.transform_geometry(transform).unwrap();
513 data
514 }
515
516 pub fn calculate_normals(&mut self) -> Result<(), VertexFetchError> {
518 let mut vertex_buffer_mut = self.vertex_buffer.modify();
519 for triangle in self.geometry_buffer.iter() {
520 let ia = triangle[0] as usize;
521 let ib = triangle[1] as usize;
522 let ic = triangle[2] as usize;
523
524 let a = vertex_buffer_mut
525 .get(ia)
526 .unwrap()
527 .read_3_f32(VertexAttributeUsage::Position)?;
528 let b = vertex_buffer_mut
529 .get(ib)
530 .unwrap()
531 .read_3_f32(VertexAttributeUsage::Position)?;
532 let c = vertex_buffer_mut
533 .get(ic)
534 .unwrap()
535 .read_3_f32(VertexAttributeUsage::Position)?;
536
537 let normal = (b - a).cross(&(c - a)).normalize();
538
539 vertex_buffer_mut
540 .get_mut(ia)
541 .unwrap()
542 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
543 vertex_buffer_mut
544 .get_mut(ib)
545 .unwrap()
546 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
547 vertex_buffer_mut
548 .get_mut(ic)
549 .unwrap()
550 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
551 }
552
553 Ok(())
554 }
555
556 pub fn make_sphere(slices: usize, stacks: usize, r: f32, transform: &Matrix4<f32>) -> Self {
560 let mut builder = RawMeshBuilder::<StaticVertex>::new(stacks * slices, stacks * slices * 3);
561
562 let d_theta = std::f32::consts::PI / slices as f32;
563 let d_phi = 2.0 * std::f32::consts::PI / stacks as f32;
564 let d_tc_y = 1.0 / stacks as f32;
565 let d_tc_x = 1.0 / slices as f32;
566
567 for i in 0..stacks {
568 for j in 0..slices {
569 let nj = j + 1;
570 let ni = i + 1;
571
572 let k0 = r * (d_theta * i as f32).sin();
573 let k1 = (d_phi * j as f32).cos();
574 let k2 = (d_phi * j as f32).sin();
575 let k3 = r * (d_theta * i as f32).cos();
576
577 let k4 = r * (d_theta * ni as f32).sin();
578 let k5 = (d_phi * nj as f32).cos();
579 let k6 = (d_phi * nj as f32).sin();
580 let k7 = r * (d_theta * ni as f32).cos();
581
582 if i != (stacks - 1) {
583 let v0 = Vector3::new(k0 * k1, k0 * k2, k3);
584 let t0 = Vector2::new(d_tc_x * j as f32, d_tc_y * i as f32);
585
586 let v1 = Vector3::new(k4 * k1, k4 * k2, k7);
587 let t1 = Vector2::new(d_tc_x * j as f32, d_tc_y * ni as f32);
588
589 let v2 = Vector3::new(k4 * k5, k4 * k6, k7);
590 let t2 = Vector2::new(d_tc_x * nj as f32, d_tc_y * ni as f32);
591
592 builder.insert(StaticVertex::from_pos_uv_normal(v0, t0, v0));
593 builder.insert(StaticVertex::from_pos_uv_normal(v1, t1, v1));
594 builder.insert(StaticVertex::from_pos_uv_normal(v2, t2, v2));
595 }
596
597 if i != 0 {
598 let v0 = Vector3::new(k4 * k5, k4 * k6, k7);
599 let t0 = Vector2::new(d_tc_x * nj as f32, d_tc_y * ni as f32);
600
601 let v1 = Vector3::new(k0 * k5, k0 * k6, k3);
602 let t1 = Vector2::new(d_tc_x * nj as f32, d_tc_y * i as f32);
603
604 let v2 = Vector3::new(k0 * k1, k0 * k2, k3);
605 let t2 = Vector2::new(d_tc_x * j as f32, d_tc_y * i as f32);
606
607 builder.insert(StaticVertex::from_pos_uv_normal(v0, t0, v0));
608 builder.insert(StaticVertex::from_pos_uv_normal(v1, t1, v1));
609 builder.insert(StaticVertex::from_pos_uv_normal(v2, t2, v2));
610 }
611 }
612 }
613
614 let mut data = Self::from_raw_mesh(builder.build());
615 data.calculate_tangents().unwrap();
616 data.transform_geometry(transform).unwrap();
617 data
618 }
619
620 pub fn make_cone(sides: usize, r: f32, h: f32, transform: &Matrix4<f32>) -> Self {
624 let mut builder = RawMeshBuilder::<StaticVertex>::new(3 * sides, 3 * sides);
625
626 let d_phi = 2.0 * std::f32::consts::PI / sides as f32;
627 let d_theta = 1.0 / sides as f32;
628
629 for i in 0..sides {
630 let nx0 = (d_phi * i as f32).cos();
631 let ny0 = (d_phi * i as f32).sin();
632 let nx1 = (d_phi * (i + 1) as f32).cos();
633 let ny1 = (d_phi * (i + 1) as f32).sin();
634
635 let x0 = r * nx0;
636 let z0 = r * ny0;
637 let x1 = r * nx1;
638 let z1 = r * ny1;
639 let tx0 = d_theta * i as f32;
640 let tx1 = d_theta * (i + 1) as f32;
641
642 let (t_cap_y_curr, t_cap_x_curr) = (d_phi * i as f32).sin_cos();
644 let (t_cap_y_next, t_cap_x_next) = (d_phi * (i + 1) as f32).sin_cos();
645
646 let t_cap_x_curr = t_cap_x_curr * 0.5 + 0.5;
647 let t_cap_y_curr = t_cap_y_curr * 0.5 + 0.5;
648
649 let t_cap_x_next = t_cap_x_next * 0.5 + 0.5;
650 let t_cap_y_next = t_cap_y_next * 0.5 + 0.5;
651
652 builder.insert(StaticVertex::from_pos_uv_normal(
653 Vector3::new(0.0, 0.0, 0.0),
654 Vector2::new(0.5, 0.5),
655 Vector3::new(0.0, -1.0, 0.0),
656 ));
657 builder.insert(StaticVertex::from_pos_uv_normal(
658 Vector3::new(x0, 0.0, z0),
659 Vector2::new(t_cap_x_curr, t_cap_y_curr),
660 Vector3::new(0.0, -1.0, 0.0),
661 ));
662 builder.insert(StaticVertex::from_pos_uv_normal(
663 Vector3::new(x1, 0.0, z1),
664 Vector2::new(t_cap_x_next, t_cap_y_next),
665 Vector3::new(0.0, -1.0, 0.0),
666 ));
667
668 let tip = Vector3::new(0.0, h, 0.0);
670 let v_curr = Vector3::new(x0, 0.0, z0);
671 let v_next = Vector3::new(x1, 0.0, z1);
672 let n_next = (tip - v_next).cross(&(v_next - v_curr));
673 let n_curr = (tip - v_curr).cross(&(v_next - v_curr));
674
675 builder.insert(StaticVertex::from_pos_uv_normal(
676 tip,
677 Vector2::new(0.5, 0.0),
678 n_curr,
679 ));
680 builder.insert(StaticVertex::from_pos_uv_normal(
681 v_next,
682 Vector2::new(tx1, 1.0),
683 n_next,
684 ));
685 builder.insert(StaticVertex::from_pos_uv_normal(
686 v_curr,
687 Vector2::new(tx0, 1.0),
688 n_curr,
689 ));
690 }
691
692 let mut data = Self::from_raw_mesh(builder.build());
693 data.calculate_tangents().unwrap();
694 data.transform_geometry(transform).unwrap();
695 data
696 }
697
698 pub fn make_torus(
703 inner_radius: f32,
704 outer_radius: f32,
705 num_rings: usize,
706 num_segments: usize,
707 transform: &Matrix4<f32>,
708 ) -> Self {
709 let mut vertices = Vec::new();
710 for j in 0..=num_rings {
711 for i in 0..=num_segments {
712 let u = i as f32 / num_segments as f32 * std::f32::consts::TAU;
713 let v = j as f32 / num_rings as f32 * std::f32::consts::TAU;
714
715 let center = Vector3::new(inner_radius * u.cos(), inner_radius * u.sin(), 0.0);
716
717 let position = Vector3::new(
718 (inner_radius + outer_radius * v.cos()) * u.cos(),
719 outer_radius * v.sin(),
720 (inner_radius + outer_radius * v.cos()) * u.sin(),
721 );
722
723 let uv = Vector2::new(i as f32 / num_segments as f32, j as f32 / num_rings as f32);
724
725 let normal = (position - center)
726 .try_normalize(f32::EPSILON)
727 .unwrap_or_default();
728
729 vertices.push(StaticVertex::from_pos_uv_normal(position, uv, normal));
730 }
731 }
732
733 let mut triangles = Vec::new();
734 for j in 1..=num_rings {
735 for i in 1..=num_segments {
736 let a = ((num_segments + 1) * j + i - 1) as u32;
737 let b = ((num_segments + 1) * (j - 1) + i - 1) as u32;
738 let c = ((num_segments + 1) * (j - 1) + i) as u32;
739 let d = ((num_segments + 1) * j + i) as u32;
740
741 triangles.push(TriangleDefinition([d, b, a]));
742 triangles.push(TriangleDefinition([d, c, b]));
743 }
744 }
745
746 let mut data = Self::new(
747 VertexBuffer::new(vertices.len(), vertices).unwrap(),
748 TriangleBuffer::new(triangles),
749 );
750 data.calculate_tangents().unwrap();
751 data.transform_geometry(transform).unwrap();
752 data
753 }
754
755 pub fn make_cylinder(
759 sides: usize,
760 r: f32,
761 h: f32,
762 caps: bool,
763 transform: &Matrix4<f32>,
764 ) -> Self {
765 let mut builder = RawMeshBuilder::<StaticVertex>::new(3 * sides, 3 * sides);
766
767 let d_phi = 2.0 * std::f32::consts::PI / sides as f32;
768 let d_theta = 1.0 / sides as f32;
769
770 for i in 0..sides {
771 let nx0 = (d_phi * i as f32).cos();
772 let ny0 = (d_phi * i as f32).sin();
773 let nx1 = (d_phi * (i + 1) as f32).cos();
774 let ny1 = (d_phi * (i + 1) as f32).sin();
775
776 let x0 = r * nx0;
777 let z0 = r * ny0;
778 let x1 = r * nx1;
779 let z1 = r * ny1;
780
781 if caps {
782 let (t_cap_y_curr, t_cap_x_curr) = (d_phi * i as f32).sin_cos();
783 let (t_cap_y_next, t_cap_x_next) = (d_phi * (i + 1) as f32).sin_cos();
784
785 let t_cap_x_curr = t_cap_x_curr * 0.5 + 0.5;
786 let t_cap_y_curr = t_cap_y_curr * 0.5 + 0.5;
787
788 let t_cap_x_next = t_cap_x_next * 0.5 + 0.5;
789 let t_cap_y_next = t_cap_y_next * 0.5 + 0.5;
790
791 builder.insert(StaticVertex::from_pos_uv_normal(
793 Vector3::new(x1, h, z1),
794 Vector2::new(t_cap_x_next, t_cap_y_next),
795 Vector3::new(0.0, 1.0, 0.0),
796 ));
797 builder.insert(StaticVertex::from_pos_uv_normal(
798 Vector3::new(x0, h, z0),
799 Vector2::new(t_cap_x_curr, t_cap_y_curr),
800 Vector3::new(0.0, 1.0, 0.0),
801 ));
802 builder.insert(StaticVertex::from_pos_uv_normal(
803 Vector3::new(0.0, h, 0.0),
804 Vector2::new(0.5, 0.5),
805 Vector3::new(0.0, 1.0, 0.0),
806 ));
807
808 builder.insert(StaticVertex::from_pos_uv_normal(
810 Vector3::new(x0, 0.0, z0),
811 Vector2::new(t_cap_x_curr, t_cap_y_curr),
812 Vector3::new(0.0, -1.0, 0.0),
813 ));
814 builder.insert(StaticVertex::from_pos_uv_normal(
815 Vector3::new(x1, 0.0, z1),
816 Vector2::new(t_cap_x_next, t_cap_y_next),
817 Vector3::new(0.0, -1.0, 0.0),
818 ));
819 builder.insert(StaticVertex::from_pos_uv_normal(
820 Vector3::new(0.0, 0.0, 0.0),
821 Vector2::new(0.5, 0.5),
822 Vector3::new(0.0, -1.0, 0.0),
823 ));
824 }
825
826 let t_side_curr = d_theta * i as f32;
827 let t_side_next = d_theta * (i + 1) as f32;
828
829 builder.insert(StaticVertex::from_pos_uv_normal(
831 Vector3::new(x0, 0.0, z0),
832 Vector2::new(t_side_curr, 0.0),
833 Vector3::new(x0, 0.0, z0),
834 ));
835 builder.insert(StaticVertex::from_pos_uv_normal(
836 Vector3::new(x0, h, z0),
837 Vector2::new(t_side_curr, 1.0),
838 Vector3::new(x0, 0.0, z0),
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
846 builder.insert(StaticVertex::from_pos_uv_normal(
847 Vector3::new(x1, 0.0, z1),
848 Vector2::new(t_side_next, 0.0),
849 Vector3::new(x1, 0.0, z1),
850 ));
851 builder.insert(StaticVertex::from_pos_uv_normal(
852 Vector3::new(x0, h, z0),
853 Vector2::new(t_side_curr, 1.0),
854 Vector3::new(x0, 0.0, z0),
855 ));
856 builder.insert(StaticVertex::from_pos_uv_normal(
857 Vector3::new(x1, h, z1),
858 Vector2::new(t_side_next, 1.0),
859 Vector3::new(x1, 0.0, z1),
860 ));
861 }
862
863 let mut data = Self::from_raw_mesh(builder.build());
864 data.calculate_tangents().unwrap();
865 data.transform_geometry(transform).unwrap();
866 data
867 }
868
869 pub fn make_cube(transform: Matrix4<f32>) -> Self {
871 let vertices = vec![
872 StaticVertex {
874 position: Vector3::new(-0.5, -0.5, 0.5),
875 normal: Vector3::z(),
876 tex_coord: Vector2::default(),
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::y(),
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::new(1.0, 1.0),
889 tangent: Vector4::default(),
890 },
891 StaticVertex {
892 position: Vector3::new(0.5, -0.5, 0.5),
893 normal: Vector3::z(),
894 tex_coord: Vector2::x(),
895 tangent: Vector4::default(),
896 },
897 StaticVertex {
899 position: Vector3::new(-0.5, -0.5, -0.5),
900 normal: -Vector3::z(),
901 tex_coord: Vector2::default(),
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::y(),
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::new(1.0, 1.0),
914 tangent: Vector4::default(),
915 },
916 StaticVertex {
917 position: Vector3::new(0.5, -0.5, -0.5),
918 normal: -Vector3::z(),
919 tex_coord: Vector2::x(),
920 tangent: Vector4::default(),
921 },
922 StaticVertex {
924 position: Vector3::new(-0.5, -0.5, -0.5),
925 normal: -Vector3::x(),
926 tex_coord: Vector2::default(),
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::y(),
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::new(1.0, 1.0),
939 tangent: Vector4::default(),
940 },
941 StaticVertex {
942 position: Vector3::new(-0.5, -0.5, 0.5),
943 normal: -Vector3::x(),
944 tex_coord: Vector2::x(),
945 tangent: Vector4::default(),
946 },
947 StaticVertex {
949 position: Vector3::new(0.5, -0.5, -0.5),
950 normal: Vector3::x(),
951 tex_coord: Vector2::default(),
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::y(),
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::new(1.0, 1.0),
964 tangent: Vector4::default(),
965 },
966 StaticVertex {
967 position: Vector3::new(0.5, -0.5, 0.5),
968 normal: Vector3::x(),
969 tex_coord: Vector2::x(),
970 tangent: Vector4::default(),
971 },
972 StaticVertex {
974 position: Vector3::new(-0.5, 0.5, 0.5),
975 normal: Vector3::y(),
976 tex_coord: Vector2::default(),
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::y(),
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::new(1.0, 1.0),
989 tangent: Vector4::default(),
990 },
991 StaticVertex {
992 position: Vector3::new(0.5, 0.5, 0.5),
993 normal: Vector3::y(),
994 tex_coord: Vector2::x(),
995 tangent: Vector4::default(),
996 },
997 StaticVertex {
999 position: Vector3::new(-0.5, -0.5, 0.5),
1000 normal: -Vector3::y(),
1001 tex_coord: Vector2::default(),
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::y(),
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::new(1.0, 1.0),
1014 tangent: Vector4::default(),
1015 },
1016 StaticVertex {
1017 position: Vector3::new(0.5, -0.5, 0.5),
1018 normal: -Vector3::y(),
1019 tex_coord: Vector2::x(),
1020 tangent: Vector4::default(),
1021 },
1022 ];
1023
1024 let triangles = vec![
1025 TriangleDefinition([2, 1, 0]),
1026 TriangleDefinition([3, 2, 0]),
1027 TriangleDefinition([4, 5, 6]),
1028 TriangleDefinition([4, 6, 7]),
1029 TriangleDefinition([10, 9, 8]),
1030 TriangleDefinition([11, 10, 8]),
1031 TriangleDefinition([12, 13, 14]),
1032 TriangleDefinition([12, 14, 15]),
1033 TriangleDefinition([18, 17, 16]),
1034 TriangleDefinition([19, 18, 16]),
1035 TriangleDefinition([20, 21, 22]),
1036 TriangleDefinition([20, 22, 23]),
1037 ];
1038
1039 let mut data = Self::new(
1040 VertexBuffer::new(vertices.len(), vertices).unwrap(),
1041 TriangleBuffer::new(triangles),
1042 );
1043 data.calculate_tangents().unwrap();
1044 data.transform_geometry(&transform).unwrap();
1045 data
1046 }
1047
1048 pub fn content_hash(&self) -> u64 {
1051 hash_combine(
1052 self.geometry_buffer.content_hash(),
1053 self.vertex_buffer.content_hash(),
1054 )
1055 }
1056
1057 pub fn clear(&mut self) {
1059 self.geometry_buffer.modify().clear();
1060 self.vertex_buffer.modify().clear();
1061 }
1062}
1063
1064impl Visit for SurfaceData {
1065 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1066 let mut region = visitor.enter_region(name)?;
1067
1068 self.vertex_buffer.visit("VertexBuffer", &mut region)?;
1069 self.geometry_buffer.visit("GeometryBuffer", &mut region)?;
1070
1071 Ok(())
1072 }
1073}
1074
1075#[derive(Copy, Clone, PartialEq, Debug)]
1077pub struct VertexWeight {
1078 pub value: f32,
1080 pub effector: ErasedHandle,
1087}
1088
1089impl Default for VertexWeight {
1090 fn default() -> Self {
1091 Self {
1092 value: 0.0,
1093 effector: ErasedHandle::none(),
1094 }
1095 }
1096}
1097
1098#[derive(Copy, Clone, Debug, PartialEq, Default)]
1100pub struct VertexWeightSet {
1101 weights: [VertexWeight; 4],
1102 count: usize,
1103}
1104
1105impl VertexWeightSet {
1106 pub fn push(&mut self, weight: VertexWeight) -> bool {
1109 if self.count < self.weights.len() {
1110 self.weights[self.count] = weight;
1111 self.count += 1;
1112 true
1113 } else {
1114 false
1115 }
1116 }
1117
1118 pub fn len(&self) -> usize {
1120 self.count
1121 }
1122
1123 pub fn is_empty(&self) -> bool {
1125 self.count == 0
1126 }
1127
1128 pub fn iter(&self) -> std::slice::Iter<VertexWeight> {
1130 self.weights[0..self.count].iter()
1131 }
1132
1133 pub fn iter_mut(&mut self) -> std::slice::IterMut<VertexWeight> {
1135 self.weights[0..self.count].iter_mut()
1136 }
1137
1138 pub fn normalize(&mut self) {
1143 let len = self.iter().fold(0.0, |qs, w| qs + w.value * w.value).sqrt();
1144 if len >= f32::EPSILON {
1145 let k = 1.0 / len;
1146 for w in self.iter_mut() {
1147 w.value *= k;
1148 }
1149 }
1150 }
1151}
1152
1153pub type SurfaceResource = Resource<SurfaceData>;
1157
1158pub trait SurfaceResourceExtension {
1160 fn deep_clone(&self) -> Self;
1162}
1163
1164impl SurfaceResourceExtension for SurfaceResource {
1165 fn deep_clone(&self) -> Self {
1166 Self::new_ok(
1167 Uuid::new_v4(),
1168 ResourceKind::Embedded,
1169 self.data_ref().clone(),
1170 )
1171 }
1172}
1173
1174#[derive(Debug, Reflect, Visit, PartialEq)]
1255pub struct Surface {
1256 pub(crate) data: InheritableVariable<SurfaceResource>,
1257
1258 pub(crate) material: InheritableVariable<MaterialResource>,
1259
1260 pub bones: InheritableVariable<Vec<Handle<Node>>>,
1262
1263 unique_material: InheritableVariable<bool>,
1267
1268 #[reflect(hidden)]
1275 #[visit(skip)]
1276 pub(crate) vertex_weights: Vec<VertexWeightSet>,
1277}
1278
1279uuid_provider!(Surface = "485caf12-4e7d-4b1a-b6bd-0681fd92f789");
1280
1281impl Clone for Surface {
1282 fn clone(&self) -> Self {
1283 Self {
1284 data: self.data.clone(),
1285 material: if *self.unique_material {
1286 self.material.deep_copy_as_embedded().into()
1288 } else {
1289 self.material.clone()
1291 },
1292 bones: self.bones.clone(),
1293 unique_material: self.unique_material.clone(),
1294 vertex_weights: self.vertex_weights.clone(),
1295 }
1296 }
1297}
1298
1299impl Default for Surface {
1300 fn default() -> Self {
1301 Self {
1302 data: SurfaceResource::new_ok(
1303 Uuid::new_v4(),
1304 ResourceKind::Embedded,
1305 SurfaceData::make_cube(Matrix4::identity()),
1306 )
1307 .into(),
1308 material: MaterialResource::new_ok(
1309 Uuid::new_v4(),
1310 Default::default(),
1311 Material::standard(),
1312 )
1313 .into(),
1314 vertex_weights: Default::default(),
1315 bones: Default::default(),
1316 unique_material: Default::default(),
1317 }
1318 }
1319}
1320
1321impl Surface {
1322 #[inline]
1324 pub fn new(data: SurfaceResource) -> Self {
1325 Self {
1326 data: data.into(),
1327 ..Default::default()
1328 }
1329 }
1330
1331 pub fn material_id(&self) -> u64 {
1333 self.material.key()
1334 }
1335
1336 pub fn batch_id(&self) -> u64 {
1338 let mut hasher = FxHasher::default();
1339 hasher.write_u64(self.material_id());
1340 hasher.write_u64(self.data.key());
1341 hasher.finish()
1342 }
1343
1344 #[inline]
1346 pub fn data(&self) -> SurfaceResource {
1347 (*self.data).clone()
1348 }
1349
1350 #[inline]
1352 pub fn data_ref(&self) -> &SurfaceResource {
1353 &self.data
1354 }
1355
1356 pub fn material(&self) -> &MaterialResource {
1358 &self.material
1359 }
1360
1361 pub fn set_material(&mut self, material: MaterialResource) {
1363 self.material.set_value_and_mark_modified(material);
1364 }
1365
1366 #[inline]
1368 pub fn bones(&self) -> &[Handle<Node>] {
1369 &self.bones
1370 }
1371
1372 pub fn is_unique_material(&self) -> bool {
1374 *self.unique_material
1375 }
1376
1377 pub fn set_unique_material(&mut self, unique: bool) {
1379 self.unique_material.set_value_and_mark_modified(unique);
1380 }
1381}
1382
1383pub struct SurfaceBuilder {
1385 data: SurfaceResource,
1386 material: Option<MaterialResource>,
1387 bones: Vec<Handle<Node>>,
1388 unique_material: bool,
1389}
1390
1391impl SurfaceBuilder {
1392 pub fn new(data: SurfaceResource) -> Self {
1394 Self {
1395 data,
1396 material: None,
1397 bones: Default::default(),
1398 unique_material: false,
1399 }
1400 }
1401
1402 pub fn with_material(mut self, material: MaterialResource) -> Self {
1404 self.material = Some(material);
1405 self
1406 }
1407
1408 pub fn with_bones(mut self, bones: Vec<Handle<Node>>) -> Self {
1410 self.bones = bones;
1411 self
1412 }
1413
1414 pub fn with_unique_material(mut self, unique: bool) -> Self {
1416 self.unique_material = unique;
1417 self
1418 }
1419
1420 pub fn build(self) -> Surface {
1422 Surface {
1423 data: self.data.into(),
1424 material: self
1425 .material
1426 .unwrap_or_else(|| {
1427 MaterialResource::new_ok(
1428 Uuid::new_v4(),
1429 Default::default(),
1430 Material::standard(),
1431 )
1432 })
1433 .into(),
1434 vertex_weights: Default::default(),
1435 bones: self.bones.into(),
1436 unique_material: self.unique_material.into(),
1437 }
1438 }
1439}
1440
1441pub struct SurfaceDataLoader {}
1443
1444impl ResourceLoader for SurfaceDataLoader {
1445 fn extensions(&self) -> &[&str] {
1446 &["surface"]
1447 }
1448
1449 fn is_native_extension(&self, ext: &str) -> bool {
1450 fyrox_core::cmp_strings_case_insensitive(ext, "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
1472pub static CUBE: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1474 BuiltInResource::new_no_source(
1475 "Cube Surface",
1476 SurfaceResource::new_ok(
1477 uuid!("d3a4604a-e1c6-430b-b524-8d3213723952"),
1478 ResourceKind::External,
1479 SurfaceData::make_cube(Matrix4::identity()),
1480 ),
1481 )
1482});
1483
1484pub static QUAD: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1486 BuiltInResource::new_no_source(
1487 "Quad Surface",
1488 SurfaceResource::new_ok(
1489 uuid!("a124317f-640b-4c1b-9fdc-af62f745eeba"),
1490 ResourceKind::External,
1491 SurfaceData::make_quad(&Matrix4::identity()),
1492 ),
1493 )
1494});
1495
1496pub static CYLINDER: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1498 BuiltInResource::new_no_source(
1499 "Cylinder Surface",
1500 SurfaceResource::new_ok(
1501 uuid!("16300ec8-4446-41a7-8ad6-9b45428d0b1b"),
1502 ResourceKind::External,
1503 SurfaceData::make_cylinder(32, 1.0, 1.0, true, &Matrix4::identity()),
1504 ),
1505 )
1506});
1507
1508pub static SPHERE: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1510 BuiltInResource::new_no_source(
1511 "Sphere Surface",
1512 SurfaceResource::new_ok(
1513 uuid!("ff1811ba-b9ad-4c37-89b8-503f79aaa4bd"),
1514 ResourceKind::External,
1515 SurfaceData::make_sphere(32, 32, 1.0, &Matrix4::identity()),
1516 ),
1517 )
1518});
1519
1520pub static CONE: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1522 BuiltInResource::new_no_source(
1523 "Cone Surface",
1524 SurfaceResource::new_ok(
1525 uuid!("e4e79405-39c5-4fe4-ba3e-c961f3d7379e"),
1526 ResourceKind::External,
1527 SurfaceData::make_cone(32, 1.0, 1.0, &Matrix4::identity()),
1528 ),
1529 )
1530});
1531
1532pub static TORUS: LazyLock<BuiltInResource<SurfaceData>> = LazyLock::new(|| {
1534 BuiltInResource::new_no_source(
1535 "Torus Surface",
1536 SurfaceResource::new_ok(
1537 uuid!("d2bb5455-c72e-475d-90da-e3a7bd5b7d07"),
1538 ResourceKind::External,
1539 SurfaceData::make_torus(1.0, 0.25, 32, 32, &Matrix4::identity()),
1540 ),
1541 )
1542});