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 Uuid::new_v4(),
209 TextureKind::Volume {
210 width: width * 3,
211 height,
212 depth,
213 },
214 TexturePixelKind::RGB16F,
215 bytes,
216 ResourceKind::Embedded,
217 )
218 .unwrap(),
219 ),
220 }
221 }
222}
223
224#[derive(Debug, Clone, Default, Reflect, TypeUuidProvider)]
228#[type_uuid(id = "8a23a414-e66d-4e12-9628-92c6ab49c2f0")]
229pub struct SurfaceData {
230 pub vertex_buffer: VertexBuffer,
232 pub geometry_buffer: TriangleBuffer,
234 pub blend_shapes_container: Option<BlendShapesContainer>,
236 #[reflect(hidden)]
237 pub(crate) cache_index: Arc<AtomicIndex>,
238}
239
240impl ResourceData for SurfaceData {
241 fn type_uuid(&self) -> Uuid {
242 <SurfaceData as fyrox_core::TypeUuidProvider>::type_uuid()
243 }
244
245 fn save(&mut self, _path: &Path) -> Result<(), Box<dyn Error>> {
246 Ok(())
248 }
249
250 fn can_be_saved(&self) -> bool {
251 true
252 }
253
254 fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
255 Some(Box::new(self.clone()))
256 }
257}
258
259impl SurfaceData {
260 pub fn new(vertex_buffer: VertexBuffer, triangles: TriangleBuffer) -> Self {
262 Self {
263 vertex_buffer,
264 geometry_buffer: triangles,
265 blend_shapes_container: None,
266 cache_index: Arc::new(AtomicIndex::unassigned()),
267 }
268 }
269
270 pub fn transform_geometry(&mut self, transform: &Matrix4<f32>) -> Result<(), VertexFetchError> {
272 let normal_matrix = transform.try_inverse().unwrap_or_default().transpose();
274
275 let mut vertex_buffer_mut = self.vertex_buffer.modify();
276 for mut view in vertex_buffer_mut.iter_mut() {
277 let position = view.read_3_f32(VertexAttributeUsage::Position)?;
278 view.write_3_f32(
279 VertexAttributeUsage::Position,
280 transform.transform_point(&Point3::from(position)).coords,
281 )?;
282 let normal = view.read_3_f32(VertexAttributeUsage::Normal)?;
283 view.write_3_f32(
284 VertexAttributeUsage::Normal,
285 normal_matrix.transform_vector(&normal),
286 )?;
287 let tangent = view.read_4_f32(VertexAttributeUsage::Tangent)?;
288 let new_tangent = normal_matrix.transform_vector(&tangent.xyz());
289 view.write_4_f32(
291 VertexAttributeUsage::Tangent,
292 Vector4::new(new_tangent.x, new_tangent.y, new_tangent.z, tangent.w),
293 )?;
294 }
295
296 Ok(())
297 }
298
299 pub fn from_raw_mesh<T>(raw: RawMesh<T>) -> Self
302 where
303 T: VertexTrait,
304 {
305 Self {
306 vertex_buffer: VertexBuffer::new(raw.vertices.len(), raw.vertices).unwrap(),
307 geometry_buffer: TriangleBuffer::new(raw.triangles),
308 blend_shapes_container: Default::default(),
309 cache_index: Arc::new(AtomicIndex::unassigned()),
310 }
311 }
312
313 pub fn calculate_tangents(&mut self) -> Result<(), VertexFetchError> {
319 let mut tan1 = vec![Vector3::default(); self.vertex_buffer.vertex_count() as usize];
320 let mut tan2 = vec![Vector3::default(); self.vertex_buffer.vertex_count() as usize];
321
322 for triangle in self.geometry_buffer.iter() {
323 let i1 = triangle[0] as usize;
324 let i2 = triangle[1] as usize;
325 let i3 = triangle[2] as usize;
326
327 let view1 = &self.vertex_buffer.get(i1).unwrap();
328 let view2 = &self.vertex_buffer.get(i2).unwrap();
329 let view3 = &self.vertex_buffer.get(i3).unwrap();
330
331 let v1 = view1.read_3_f32(VertexAttributeUsage::Position)?;
332 let v2 = view2.read_3_f32(VertexAttributeUsage::Position)?;
333 let v3 = view3.read_3_f32(VertexAttributeUsage::Position)?;
334
335 if v1 == v2 || v1 == v3 || v2 == v3 {
337 Log::warn(format!(
338 "Degenerated triangle found when calculating tangents. Lighting may be \
339 incorrect! Triangle indices: {triangle:?}. Triangle vertices: {v1:?} {v2:?} {v3:?}",
340 ));
341 }
342
343 let w1 = view1.read_3_f32(VertexAttributeUsage::TexCoord0)?;
344 let w2 = view2.read_3_f32(VertexAttributeUsage::TexCoord0)?;
345 let w3 = view3.read_3_f32(VertexAttributeUsage::TexCoord0)?;
346
347 let x1 = v2.x - v1.x;
348 let x2 = v3.x - v1.x;
349 let y1 = v2.y - v1.y;
350 let y2 = v3.y - v1.y;
351 let z1 = v2.z - v1.z;
352 let z2 = v3.z - v1.z;
353
354 let s1 = w2.x - w1.x;
355 let s2 = w3.x - w1.x;
356 let t1 = w2.y - w1.y;
357 let t2 = w3.y - w1.y;
358
359 let r = 1.0 / (s1 * t2 - s2 * t1);
360
361 let sdir = Vector3::new(
362 (t2 * x1 - t1 * x2) * r,
363 (t2 * y1 - t1 * y2) * r,
364 (t2 * z1 - t1 * z2) * r,
365 );
366
367 tan1[i1] += sdir;
368 tan1[i2] += sdir;
369 tan1[i3] += sdir;
370
371 let tdir = Vector3::new(
372 (s1 * x2 - s2 * x1) * r,
373 (s1 * y2 - s2 * y1) * r,
374 (s1 * z2 - s2 * z1) * r,
375 );
376 tan2[i1] += tdir;
377 tan2[i2] += tdir;
378 tan2[i3] += tdir;
379 }
380
381 let mut vertex_buffer_mut = self.vertex_buffer.modify();
382 for (mut view, (t1, t2)) in vertex_buffer_mut.iter_mut().zip(tan1.into_iter().zip(tan2)) {
383 let normal = view.read_3_f32(VertexAttributeUsage::Normal)?;
384
385 let tangent = (t1 - normal.scale(normal.dot(&t1)))
387 .try_normalize(f32::EPSILON)
388 .unwrap_or_else(|| Vector3::new(0.0, 1.0, 0.0));
389 let handedness = normal.cross(&t1).dot(&t2).signum();
390 view.write_4_f32(
391 VertexAttributeUsage::Tangent,
392 Vector4::new(tangent.x, tangent.y, tangent.z, handedness),
393 )?;
394 }
395
396 Ok(())
397 }
398
399 pub fn make_unit_xy_quad() -> Self {
401 let vertices = vec![
402 StaticVertex {
403 position: Vector3::default(),
404 normal: Vector3::z(),
405 tex_coord: Vector2::y(),
406 tangent: Vector4::default(),
407 },
408 StaticVertex {
409 position: Vector3::x(),
410 normal: Vector3::z(),
411 tex_coord: Vector2::new(1.0, 1.0),
412 tangent: Vector4::default(),
413 },
414 StaticVertex {
415 position: Vector3::new(1.0, 1.0, 0.0),
416 normal: Vector3::z(),
417 tex_coord: Vector2::x(),
418 tangent: Vector4::default(),
419 },
420 StaticVertex {
421 position: Vector3::y(),
422 normal: Vector3::z(),
423 tex_coord: Vector2::default(),
424 tangent: Vector4::default(),
425 },
426 ];
427
428 let triangles = vec![TriangleDefinition([0, 1, 2]), TriangleDefinition([0, 2, 3])];
429
430 Self::new(
431 VertexBuffer::new(vertices.len(), vertices).unwrap(),
432 TriangleBuffer::new(triangles),
433 )
434 }
435
436 pub fn make_collapsed_xy_quad() -> Self {
439 let vertices = vec![
440 StaticVertex {
441 position: Vector3::default(),
442 normal: Vector3::z(),
443 tex_coord: Vector2::default(),
444 tangent: Vector4::default(),
445 },
446 StaticVertex {
447 position: Vector3::default(),
448 normal: Vector3::z(),
449 tex_coord: Vector2::x(),
450 tangent: Vector4::default(),
451 },
452 StaticVertex {
453 position: Vector3::default(),
454 normal: Vector3::z(),
455 tex_coord: Vector2::new(1.0, 1.0),
456 tangent: Vector4::default(),
457 },
458 StaticVertex {
459 position: Vector3::default(),
460 normal: Vector3::z(),
461 tex_coord: Vector2::y(),
462 tangent: Vector4::default(),
463 },
464 ];
465
466 let triangles = vec![TriangleDefinition([0, 1, 2]), TriangleDefinition([0, 2, 3])];
467
468 Self::new(
469 VertexBuffer::new(vertices.len(), vertices).unwrap(),
470 TriangleBuffer::new(triangles),
471 )
472 }
473
474 pub fn make_quad(transform: &Matrix4<f32>) -> Self {
476 let vertices = vec![
477 StaticVertex {
478 position: Vector3::new(-0.5, 0.5, 0.0),
479 normal: -Vector3::z(),
480 tex_coord: Vector2::new(1.0, 1.0),
481 tangent: Vector4::default(),
482 },
483 StaticVertex {
484 position: Vector3::new(0.5, 0.5, 0.0),
485 normal: -Vector3::z(),
486 tex_coord: Vector2::new(0.0, 1.0),
487 tangent: Vector4::default(),
488 },
489 StaticVertex {
490 position: Vector3::new(0.5, -0.5, 0.0),
491 normal: -Vector3::z(),
492 tex_coord: Vector2::new(0.0, 0.0),
493 tangent: Vector4::default(),
494 },
495 StaticVertex {
496 position: Vector3::new(-0.5, -0.5, 0.0),
497 normal: -Vector3::z(),
498 tex_coord: Vector2::new(1.0, 0.0),
499 tangent: Vector4::default(),
500 },
501 ];
502
503 let mut data = Self::new(
504 VertexBuffer::new(vertices.len(), vertices).unwrap(),
505 TriangleBuffer::new(vec![
506 TriangleDefinition([0, 1, 2]),
507 TriangleDefinition([0, 2, 3]),
508 ]),
509 );
510 data.calculate_tangents().unwrap();
511 data.transform_geometry(transform).unwrap();
512 data
513 }
514
515 pub fn calculate_normals(&mut self) -> Result<(), VertexFetchError> {
517 let mut vertex_buffer_mut = self.vertex_buffer.modify();
518 for triangle in self.geometry_buffer.iter() {
519 let ia = triangle[0] as usize;
520 let ib = triangle[1] as usize;
521 let ic = triangle[2] as usize;
522
523 let a = vertex_buffer_mut
524 .get(ia)
525 .unwrap()
526 .read_3_f32(VertexAttributeUsage::Position)?;
527 let b = vertex_buffer_mut
528 .get(ib)
529 .unwrap()
530 .read_3_f32(VertexAttributeUsage::Position)?;
531 let c = vertex_buffer_mut
532 .get(ic)
533 .unwrap()
534 .read_3_f32(VertexAttributeUsage::Position)?;
535
536 let normal = (b - a).cross(&(c - a)).normalize();
537
538 vertex_buffer_mut
539 .get_mut(ia)
540 .unwrap()
541 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
542 vertex_buffer_mut
543 .get_mut(ib)
544 .unwrap()
545 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
546 vertex_buffer_mut
547 .get_mut(ic)
548 .unwrap()
549 .write_3_f32(VertexAttributeUsage::Normal, normal)?;
550 }
551
552 Ok(())
553 }
554
555 pub fn make_sphere(slices: usize, stacks: usize, r: f32, transform: &Matrix4<f32>) -> Self {
559 let mut builder = RawMeshBuilder::<StaticVertex>::new(stacks * slices, stacks * slices * 3);
560
561 let d_theta = std::f32::consts::PI / slices as f32;
562 let d_phi = 2.0 * std::f32::consts::PI / stacks as f32;
563 let d_tc_y = 1.0 / stacks as f32;
564 let d_tc_x = 1.0 / slices as f32;
565
566 for i in 0..stacks {
567 for j in 0..slices {
568 let nj = j + 1;
569 let ni = i + 1;
570
571 let k0 = r * (d_theta * i as f32).sin();
572 let k1 = (d_phi * j as f32).cos();
573 let k2 = (d_phi * j as f32).sin();
574 let k3 = r * (d_theta * i as f32).cos();
575
576 let k4 = r * (d_theta * ni as f32).sin();
577 let k5 = (d_phi * nj as f32).cos();
578 let k6 = (d_phi * nj as f32).sin();
579 let k7 = r * (d_theta * ni as f32).cos();
580
581 if i != (stacks - 1) {
582 let v0 = Vector3::new(k0 * k1, k0 * k2, k3);
583 let t0 = Vector2::new(d_tc_x * j as f32, d_tc_y * i as f32);
584
585 let v1 = Vector3::new(k4 * k1, k4 * k2, k7);
586 let t1 = Vector2::new(d_tc_x * j as f32, d_tc_y * ni as f32);
587
588 let v2 = Vector3::new(k4 * k5, k4 * k6, k7);
589 let t2 = Vector2::new(d_tc_x * nj as f32, d_tc_y * ni as f32);
590
591 builder.insert(StaticVertex::from_pos_uv_normal(v0, t0, v0));
592 builder.insert(StaticVertex::from_pos_uv_normal(v1, t1, v1));
593 builder.insert(StaticVertex::from_pos_uv_normal(v2, t2, v2));
594 }
595
596 if i != 0 {
597 let v0 = Vector3::new(k4 * k5, k4 * k6, k7);
598 let t0 = Vector2::new(d_tc_x * nj as f32, d_tc_y * ni as f32);
599
600 let v1 = Vector3::new(k0 * k5, k0 * k6, k3);
601 let t1 = Vector2::new(d_tc_x * nj as f32, d_tc_y * i as f32);
602
603 let v2 = Vector3::new(k0 * k1, k0 * k2, k3);
604 let t2 = Vector2::new(d_tc_x * j as f32, d_tc_y * i as f32);
605
606 builder.insert(StaticVertex::from_pos_uv_normal(v0, t0, v0));
607 builder.insert(StaticVertex::from_pos_uv_normal(v1, t1, v1));
608 builder.insert(StaticVertex::from_pos_uv_normal(v2, t2, v2));
609 }
610 }
611 }
612
613 let mut data = Self::from_raw_mesh(builder.build());
614 data.calculate_tangents().unwrap();
615 data.transform_geometry(transform).unwrap();
616 data
617 }
618
619 pub fn make_cone(sides: usize, r: f32, h: f32, transform: &Matrix4<f32>) -> Self {
623 let mut builder = RawMeshBuilder::<StaticVertex>::new(3 * sides, 3 * sides);
624
625 let d_phi = 2.0 * std::f32::consts::PI / sides as f32;
626 let d_theta = 1.0 / sides as f32;
627
628 for i in 0..sides {
629 let nx0 = (d_phi * i as f32).cos();
630 let ny0 = (d_phi * i as f32).sin();
631 let nx1 = (d_phi * (i + 1) as f32).cos();
632 let ny1 = (d_phi * (i + 1) as f32).sin();
633
634 let x0 = r * nx0;
635 let z0 = r * ny0;
636 let x1 = r * nx1;
637 let z1 = r * ny1;
638 let tx0 = d_theta * i as f32;
639 let tx1 = d_theta * (i + 1) as f32;
640
641 let (t_cap_y_curr, t_cap_x_curr) = (d_phi * i as f32).sin_cos();
643 let (t_cap_y_next, t_cap_x_next) = (d_phi * (i + 1) as f32).sin_cos();
644
645 let t_cap_x_curr = t_cap_x_curr * 0.5 + 0.5;
646 let t_cap_y_curr = t_cap_y_curr * 0.5 + 0.5;
647
648 let t_cap_x_next = t_cap_x_next * 0.5 + 0.5;
649 let t_cap_y_next = t_cap_y_next * 0.5 + 0.5;
650
651 builder.insert(StaticVertex::from_pos_uv_normal(
652 Vector3::new(0.0, 0.0, 0.0),
653 Vector2::new(0.5, 0.5),
654 Vector3::new(0.0, -1.0, 0.0),
655 ));
656 builder.insert(StaticVertex::from_pos_uv_normal(
657 Vector3::new(x0, 0.0, z0),
658 Vector2::new(t_cap_x_curr, t_cap_y_curr),
659 Vector3::new(0.0, -1.0, 0.0),
660 ));
661 builder.insert(StaticVertex::from_pos_uv_normal(
662 Vector3::new(x1, 0.0, z1),
663 Vector2::new(t_cap_x_next, t_cap_y_next),
664 Vector3::new(0.0, -1.0, 0.0),
665 ));
666
667 let tip = Vector3::new(0.0, h, 0.0);
669 let v_curr = Vector3::new(x0, 0.0, z0);
670 let v_next = Vector3::new(x1, 0.0, z1);
671 let n_next = (tip - v_next).cross(&(v_next - v_curr));
672 let n_curr = (tip - v_curr).cross(&(v_next - v_curr));
673
674 builder.insert(StaticVertex::from_pos_uv_normal(
675 tip,
676 Vector2::new(0.5, 0.0),
677 n_curr,
678 ));
679 builder.insert(StaticVertex::from_pos_uv_normal(
680 v_next,
681 Vector2::new(tx1, 1.0),
682 n_next,
683 ));
684 builder.insert(StaticVertex::from_pos_uv_normal(
685 v_curr,
686 Vector2::new(tx0, 1.0),
687 n_curr,
688 ));
689 }
690
691 let mut data = Self::from_raw_mesh(builder.build());
692 data.calculate_tangents().unwrap();
693 data.transform_geometry(transform).unwrap();
694 data
695 }
696
697 pub fn make_torus(
702 inner_radius: f32,
703 outer_radius: f32,
704 num_rings: usize,
705 num_segments: usize,
706 transform: &Matrix4<f32>,
707 ) -> Self {
708 let mut vertices = Vec::new();
709 for j in 0..=num_rings {
710 for i in 0..=num_segments {
711 let u = i as f32 / num_segments as f32 * std::f32::consts::TAU;
712 let v = j as f32 / num_rings as f32 * std::f32::consts::TAU;
713
714 let center = Vector3::new(inner_radius * u.cos(), inner_radius * u.sin(), 0.0);
715
716 let position = Vector3::new(
717 (inner_radius + outer_radius * v.cos()) * u.cos(),
718 outer_radius * v.sin(),
719 (inner_radius + outer_radius * v.cos()) * u.sin(),
720 );
721
722 let uv = Vector2::new(i as f32 / num_segments as f32, j as f32 / num_rings as f32);
723
724 let normal = (position - center)
725 .try_normalize(f32::EPSILON)
726 .unwrap_or_default();
727
728 vertices.push(StaticVertex::from_pos_uv_normal(position, uv, normal));
729 }
730 }
731
732 let mut triangles = Vec::new();
733 for j in 1..=num_rings {
734 for i in 1..=num_segments {
735 let a = ((num_segments + 1) * j + i - 1) as u32;
736 let b = ((num_segments + 1) * (j - 1) + i - 1) as u32;
737 let c = ((num_segments + 1) * (j - 1) + i) as u32;
738 let d = ((num_segments + 1) * j + i) as u32;
739
740 triangles.push(TriangleDefinition([d, b, a]));
741 triangles.push(TriangleDefinition([d, c, b]));
742 }
743 }
744
745 let mut data = Self::new(
746 VertexBuffer::new(vertices.len(), vertices).unwrap(),
747 TriangleBuffer::new(triangles),
748 );
749 data.calculate_tangents().unwrap();
750 data.transform_geometry(transform).unwrap();
751 data
752 }
753
754 pub fn make_cylinder(
758 sides: usize,
759 r: f32,
760 h: f32,
761 caps: bool,
762 transform: &Matrix4<f32>,
763 ) -> Self {
764 let mut builder = RawMeshBuilder::<StaticVertex>::new(3 * sides, 3 * sides);
765
766 let d_phi = 2.0 * std::f32::consts::PI / sides as f32;
767 let d_theta = 1.0 / sides as f32;
768
769 for i in 0..sides {
770 let nx0 = (d_phi * i as f32).cos();
771 let ny0 = (d_phi * i as f32).sin();
772 let nx1 = (d_phi * (i + 1) as f32).cos();
773 let ny1 = (d_phi * (i + 1) as f32).sin();
774
775 let x0 = r * nx0;
776 let z0 = r * ny0;
777 let x1 = r * nx1;
778 let z1 = r * ny1;
779
780 if caps {
781 let (t_cap_y_curr, t_cap_x_curr) = (d_phi * i as f32).sin_cos();
782 let (t_cap_y_next, t_cap_x_next) = (d_phi * (i + 1) as f32).sin_cos();
783
784 let t_cap_x_curr = t_cap_x_curr * 0.5 + 0.5;
785 let t_cap_y_curr = t_cap_y_curr * 0.5 + 0.5;
786
787 let t_cap_x_next = t_cap_x_next * 0.5 + 0.5;
788 let t_cap_y_next = t_cap_y_next * 0.5 + 0.5;
789
790 builder.insert(StaticVertex::from_pos_uv_normal(
792 Vector3::new(x1, h, z1),
793 Vector2::new(t_cap_x_next, t_cap_y_next),
794 Vector3::new(0.0, 1.0, 0.0),
795 ));
796 builder.insert(StaticVertex::from_pos_uv_normal(
797 Vector3::new(x0, h, z0),
798 Vector2::new(t_cap_x_curr, t_cap_y_curr),
799 Vector3::new(0.0, 1.0, 0.0),
800 ));
801 builder.insert(StaticVertex::from_pos_uv_normal(
802 Vector3::new(0.0, h, 0.0),
803 Vector2::new(0.5, 0.5),
804 Vector3::new(0.0, 1.0, 0.0),
805 ));
806
807 builder.insert(StaticVertex::from_pos_uv_normal(
809 Vector3::new(x0, 0.0, z0),
810 Vector2::new(t_cap_x_curr, t_cap_y_curr),
811 Vector3::new(0.0, -1.0, 0.0),
812 ));
813 builder.insert(StaticVertex::from_pos_uv_normal(
814 Vector3::new(x1, 0.0, z1),
815 Vector2::new(t_cap_x_next, t_cap_y_next),
816 Vector3::new(0.0, -1.0, 0.0),
817 ));
818 builder.insert(StaticVertex::from_pos_uv_normal(
819 Vector3::new(0.0, 0.0, 0.0),
820 Vector2::new(0.5, 0.5),
821 Vector3::new(0.0, -1.0, 0.0),
822 ));
823 }
824
825 let t_side_curr = d_theta * i as f32;
826 let t_side_next = d_theta * (i + 1) as f32;
827
828 builder.insert(StaticVertex::from_pos_uv_normal(
830 Vector3::new(x0, 0.0, z0),
831 Vector2::new(t_side_curr, 0.0),
832 Vector3::new(x0, 0.0, z0),
833 ));
834 builder.insert(StaticVertex::from_pos_uv_normal(
835 Vector3::new(x0, h, z0),
836 Vector2::new(t_side_curr, 1.0),
837 Vector3::new(x0, 0.0, z0),
838 ));
839 builder.insert(StaticVertex::from_pos_uv_normal(
840 Vector3::new(x1, 0.0, z1),
841 Vector2::new(t_side_next, 0.0),
842 Vector3::new(x1, 0.0, z1),
843 ));
844
845 builder.insert(StaticVertex::from_pos_uv_normal(
846 Vector3::new(x1, 0.0, z1),
847 Vector2::new(t_side_next, 0.0),
848 Vector3::new(x1, 0.0, z1),
849 ));
850 builder.insert(StaticVertex::from_pos_uv_normal(
851 Vector3::new(x0, h, z0),
852 Vector2::new(t_side_curr, 1.0),
853 Vector3::new(x0, 0.0, z0),
854 ));
855 builder.insert(StaticVertex::from_pos_uv_normal(
856 Vector3::new(x1, h, z1),
857 Vector2::new(t_side_next, 1.0),
858 Vector3::new(x1, 0.0, z1),
859 ));
860 }
861
862 let mut data = Self::from_raw_mesh(builder.build());
863 data.calculate_tangents().unwrap();
864 data.transform_geometry(transform).unwrap();
865 data
866 }
867
868 pub fn make_cube(transform: Matrix4<f32>) -> Self {
870 let vertices = vec![
871 StaticVertex {
873 position: Vector3::new(-0.5, -0.5, 0.5),
874 normal: Vector3::z(),
875 tex_coord: Vector2::default(),
876 tangent: Vector4::default(),
877 },
878 StaticVertex {
879 position: Vector3::new(-0.5, 0.5, 0.5),
880 normal: Vector3::z(),
881 tex_coord: Vector2::y(),
882 tangent: Vector4::default(),
883 },
884 StaticVertex {
885 position: Vector3::new(0.5, 0.5, 0.5),
886 normal: Vector3::z(),
887 tex_coord: Vector2::new(1.0, 1.0),
888 tangent: Vector4::default(),
889 },
890 StaticVertex {
891 position: Vector3::new(0.5, -0.5, 0.5),
892 normal: Vector3::z(),
893 tex_coord: Vector2::x(),
894 tangent: Vector4::default(),
895 },
896 StaticVertex {
898 position: Vector3::new(-0.5, -0.5, -0.5),
899 normal: -Vector3::z(),
900 tex_coord: Vector2::default(),
901 tangent: Vector4::default(),
902 },
903 StaticVertex {
904 position: Vector3::new(-0.5, 0.5, -0.5),
905 normal: -Vector3::z(),
906 tex_coord: Vector2::y(),
907 tangent: Vector4::default(),
908 },
909 StaticVertex {
910 position: Vector3::new(0.5, 0.5, -0.5),
911 normal: -Vector3::z(),
912 tex_coord: Vector2::new(1.0, 1.0),
913 tangent: Vector4::default(),
914 },
915 StaticVertex {
916 position: Vector3::new(0.5, -0.5, -0.5),
917 normal: -Vector3::z(),
918 tex_coord: Vector2::x(),
919 tangent: Vector4::default(),
920 },
921 StaticVertex {
923 position: Vector3::new(-0.5, -0.5, -0.5),
924 normal: -Vector3::x(),
925 tex_coord: Vector2::default(),
926 tangent: Vector4::default(),
927 },
928 StaticVertex {
929 position: Vector3::new(-0.5, 0.5, -0.5),
930 normal: -Vector3::x(),
931 tex_coord: Vector2::y(),
932 tangent: Vector4::default(),
933 },
934 StaticVertex {
935 position: Vector3::new(-0.5, 0.5, 0.5),
936 normal: -Vector3::x(),
937 tex_coord: Vector2::new(1.0, 1.0),
938 tangent: Vector4::default(),
939 },
940 StaticVertex {
941 position: Vector3::new(-0.5, -0.5, 0.5),
942 normal: -Vector3::x(),
943 tex_coord: Vector2::x(),
944 tangent: Vector4::default(),
945 },
946 StaticVertex {
948 position: Vector3::new(0.5, -0.5, -0.5),
949 normal: Vector3::x(),
950 tex_coord: Vector2::default(),
951 tangent: Vector4::default(),
952 },
953 StaticVertex {
954 position: Vector3::new(0.5, 0.5, -0.5),
955 normal: Vector3::x(),
956 tex_coord: Vector2::y(),
957 tangent: Vector4::default(),
958 },
959 StaticVertex {
960 position: Vector3::new(0.5, 0.5, 0.5),
961 normal: Vector3::x(),
962 tex_coord: Vector2::new(1.0, 1.0),
963 tangent: Vector4::default(),
964 },
965 StaticVertex {
966 position: Vector3::new(0.5, -0.5, 0.5),
967 normal: Vector3::x(),
968 tex_coord: Vector2::x(),
969 tangent: Vector4::default(),
970 },
971 StaticVertex {
973 position: Vector3::new(-0.5, 0.5, 0.5),
974 normal: Vector3::y(),
975 tex_coord: Vector2::default(),
976 tangent: Vector4::default(),
977 },
978 StaticVertex {
979 position: Vector3::new(-0.5, 0.5, -0.5),
980 normal: Vector3::y(),
981 tex_coord: Vector2::y(),
982 tangent: Vector4::default(),
983 },
984 StaticVertex {
985 position: Vector3::new(0.5, 0.5, -0.5),
986 normal: Vector3::y(),
987 tex_coord: Vector2::new(1.0, 1.0),
988 tangent: Vector4::default(),
989 },
990 StaticVertex {
991 position: Vector3::new(0.5, 0.5, 0.5),
992 normal: Vector3::y(),
993 tex_coord: Vector2::x(),
994 tangent: Vector4::default(),
995 },
996 StaticVertex {
998 position: Vector3::new(-0.5, -0.5, 0.5),
999 normal: -Vector3::y(),
1000 tex_coord: Vector2::default(),
1001 tangent: Vector4::default(),
1002 },
1003 StaticVertex {
1004 position: Vector3::new(-0.5, -0.5, -0.5),
1005 normal: -Vector3::y(),
1006 tex_coord: Vector2::y(),
1007 tangent: Vector4::default(),
1008 },
1009 StaticVertex {
1010 position: Vector3::new(0.5, -0.5, -0.5),
1011 normal: -Vector3::y(),
1012 tex_coord: Vector2::new(1.0, 1.0),
1013 tangent: Vector4::default(),
1014 },
1015 StaticVertex {
1016 position: Vector3::new(0.5, -0.5, 0.5),
1017 normal: -Vector3::y(),
1018 tex_coord: Vector2::x(),
1019 tangent: Vector4::default(),
1020 },
1021 ];
1022
1023 let triangles = vec![
1024 TriangleDefinition([2, 1, 0]),
1025 TriangleDefinition([3, 2, 0]),
1026 TriangleDefinition([4, 5, 6]),
1027 TriangleDefinition([4, 6, 7]),
1028 TriangleDefinition([10, 9, 8]),
1029 TriangleDefinition([11, 10, 8]),
1030 TriangleDefinition([12, 13, 14]),
1031 TriangleDefinition([12, 14, 15]),
1032 TriangleDefinition([18, 17, 16]),
1033 TriangleDefinition([19, 18, 16]),
1034 TriangleDefinition([20, 21, 22]),
1035 TriangleDefinition([20, 22, 23]),
1036 ];
1037
1038 let mut data = Self::new(
1039 VertexBuffer::new(vertices.len(), vertices).unwrap(),
1040 TriangleBuffer::new(triangles),
1041 );
1042 data.calculate_tangents().unwrap();
1043 data.transform_geometry(&transform).unwrap();
1044 data
1045 }
1046
1047 pub fn content_hash(&self) -> u64 {
1050 hash_combine(
1051 self.geometry_buffer.content_hash(),
1052 self.vertex_buffer.content_hash(),
1053 )
1054 }
1055
1056 pub fn clear(&mut self) {
1058 self.geometry_buffer.modify().clear();
1059 self.vertex_buffer.modify().clear();
1060 }
1061}
1062
1063impl Visit for SurfaceData {
1064 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1065 let mut region = visitor.enter_region(name)?;
1066
1067 self.vertex_buffer.visit("VertexBuffer", &mut region)?;
1068 self.geometry_buffer.visit("GeometryBuffer", &mut region)?;
1069
1070 Ok(())
1071 }
1072}
1073
1074#[derive(Copy, Clone, PartialEq, Debug)]
1076pub struct VertexWeight {
1077 pub value: f32,
1079 pub effector: ErasedHandle,
1086}
1087
1088impl Default for VertexWeight {
1089 fn default() -> Self {
1090 Self {
1091 value: 0.0,
1092 effector: ErasedHandle::none(),
1093 }
1094 }
1095}
1096
1097#[derive(Copy, Clone, Debug, PartialEq, Default)]
1099pub struct VertexWeightSet {
1100 weights: [VertexWeight; 4],
1101 count: usize,
1102}
1103
1104impl VertexWeightSet {
1105 pub fn push(&mut self, weight: VertexWeight) -> bool {
1108 if self.count < self.weights.len() {
1109 self.weights[self.count] = weight;
1110 self.count += 1;
1111 true
1112 } else {
1113 false
1114 }
1115 }
1116
1117 pub fn len(&self) -> usize {
1119 self.count
1120 }
1121
1122 pub fn is_empty(&self) -> bool {
1124 self.count == 0
1125 }
1126
1127 pub fn iter(&self) -> std::slice::Iter<VertexWeight> {
1129 self.weights[0..self.count].iter()
1130 }
1131
1132 pub fn iter_mut(&mut self) -> std::slice::IterMut<VertexWeight> {
1134 self.weights[0..self.count].iter_mut()
1135 }
1136
1137 pub fn normalize(&mut self) {
1142 let len = self.iter().fold(0.0, |qs, w| qs + w.value * w.value).sqrt();
1143 if len >= f32::EPSILON {
1144 let k = 1.0 / len;
1145 for w in self.iter_mut() {
1146 w.value *= k;
1147 }
1148 }
1149 }
1150}
1151
1152pub type SurfaceResource = Resource<SurfaceData>;
1156
1157pub trait SurfaceResourceExtension {
1159 fn deep_clone(&self) -> Self;
1161}
1162
1163impl SurfaceResourceExtension for SurfaceResource {
1164 fn deep_clone(&self) -> Self {
1165 Self::new_ok(
1166 Uuid::new_v4(),
1167 ResourceKind::Embedded,
1168 self.data_ref().clone(),
1169 )
1170 }
1171}
1172
1173#[derive(Debug, Reflect, PartialEq)]
1254pub struct Surface {
1255 pub(crate) data: InheritableVariable<SurfaceResource>,
1256
1257 pub(crate) material: InheritableVariable<MaterialResource>,
1258
1259 pub bones: InheritableVariable<Vec<Handle<Node>>>,
1261
1262 unique_material: InheritableVariable<bool>,
1266
1267 #[reflect(hidden)]
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 Visit for Surface {
1298 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1299 let mut region = visitor.enter_region(name)?;
1300
1301 if region.is_reading() {
1303 if let Some(material) = material::visit_old_material(&mut region) {
1304 self.material = material.into();
1305 } else {
1306 self.material.visit("Material", &mut region)?;
1307 }
1308 } else {
1309 self.material.visit("Material", &mut region)?;
1310 }
1311
1312 self.data.visit("Data", &mut region)?;
1313 self.bones.visit("Bones", &mut region)?;
1314 let _ = self.unique_material.visit("UniqueMaterial", &mut region); Ok(())
1317 }
1318}
1319
1320impl Default for Surface {
1321 fn default() -> Self {
1322 Self {
1323 data: SurfaceResource::new_ok(
1324 Uuid::new_v4(),
1325 ResourceKind::Embedded,
1326 SurfaceData::make_cube(Matrix4::identity()),
1327 )
1328 .into(),
1329 material: MaterialResource::new_ok(
1330 Uuid::new_v4(),
1331 Default::default(),
1332 Material::standard(),
1333 )
1334 .into(),
1335 vertex_weights: Default::default(),
1336 bones: Default::default(),
1337 unique_material: Default::default(),
1338 }
1339 }
1340}
1341
1342impl Surface {
1343 #[inline]
1345 pub fn new(data: SurfaceResource) -> Self {
1346 Self {
1347 data: data.into(),
1348 ..Default::default()
1349 }
1350 }
1351
1352 pub fn material_id(&self) -> u64 {
1354 self.material.key()
1355 }
1356
1357 pub fn batch_id(&self) -> u64 {
1359 let mut hasher = FxHasher::default();
1360 hasher.write_u64(self.material_id());
1361 hasher.write_u64(self.data.key());
1362 hasher.finish()
1363 }
1364
1365 #[inline]
1367 pub fn data(&self) -> SurfaceResource {
1368 (*self.data).clone()
1369 }
1370
1371 #[inline]
1373 pub fn data_ref(&self) -> &SurfaceResource {
1374 &self.data
1375 }
1376
1377 pub fn material(&self) -> &MaterialResource {
1379 &self.material
1380 }
1381
1382 pub fn set_material(&mut self, material: MaterialResource) {
1384 self.material.set_value_and_mark_modified(material);
1385 }
1386
1387 #[inline]
1389 pub fn bones(&self) -> &[Handle<Node>] {
1390 &self.bones
1391 }
1392
1393 pub fn is_unique_material(&self) -> bool {
1395 *self.unique_material
1396 }
1397
1398 pub fn set_unique_material(&mut self, unique: bool) {
1400 self.unique_material.set_value_and_mark_modified(unique);
1401 }
1402}
1403
1404pub struct SurfaceBuilder {
1406 data: SurfaceResource,
1407 material: Option<MaterialResource>,
1408 bones: Vec<Handle<Node>>,
1409 unique_material: bool,
1410}
1411
1412impl SurfaceBuilder {
1413 pub fn new(data: SurfaceResource) -> Self {
1415 Self {
1416 data,
1417 material: None,
1418 bones: Default::default(),
1419 unique_material: false,
1420 }
1421 }
1422
1423 pub fn with_material(mut self, material: MaterialResource) -> Self {
1425 self.material = Some(material);
1426 self
1427 }
1428
1429 pub fn with_bones(mut self, bones: Vec<Handle<Node>>) -> Self {
1431 self.bones = bones;
1432 self
1433 }
1434
1435 pub fn with_unique_material(mut self, unique: bool) -> Self {
1437 self.unique_material = unique;
1438 self
1439 }
1440
1441 pub fn build(self) -> Surface {
1443 Surface {
1444 data: self.data.into(),
1445 material: self
1446 .material
1447 .unwrap_or_else(|| {
1448 MaterialResource::new_ok(
1449 Uuid::new_v4(),
1450 Default::default(),
1451 Material::standard(),
1452 )
1453 })
1454 .into(),
1455 vertex_weights: Default::default(),
1456 bones: self.bones.into(),
1457 unique_material: self.unique_material.into(),
1458 }
1459 }
1460}
1461
1462pub struct SurfaceDataLoader {}
1464
1465impl ResourceLoader for SurfaceDataLoader {
1466 fn extensions(&self) -> &[&str] {
1467 &["surface"]
1468 }
1469
1470 fn is_native_extension(&self, ext: &str) -> bool {
1471 fyrox_core::cmp_strings_case_insensitive(ext, "surface")
1472 }
1473
1474 fn data_type_uuid(&self) -> Uuid {
1475 <SurfaceData as TypeUuidProvider>::type_uuid()
1476 }
1477
1478 fn load(&self, path: PathBuf, io: Arc<dyn ResourceIo>) -> BoxedLoaderFuture {
1479 Box::pin(async move {
1480 let io = io.as_ref();
1481
1482 let data = io.load_file(&path).await.map_err(LoadError::new)?;
1483 let mut visitor = Visitor::load_from_memory(&data).map_err(LoadError::new)?;
1484 let mut surface_data = SurfaceData::default();
1485 surface_data
1486 .visit("SurfaceData", &mut visitor)
1487 .map_err(LoadError::new)?;
1488 Ok(LoaderPayload::new(surface_data))
1489 })
1490 }
1491}
1492
1493lazy_static! {
1494 pub static ref CUBE: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1496 "__CubeSurface",
1497 SurfaceResource::new_ok(
1498 uuid!("d3a4604a-e1c6-430b-b524-8d3213723952"),
1499 ResourceKind::Embedded,
1500 SurfaceData::make_cube(Matrix4::identity()),
1501 )
1502 );
1503
1504 pub static ref QUAD: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1506 "__QuadSurface",
1507 SurfaceResource::new_ok(
1508 uuid!("a124317f-640b-4c1b-9fdc-af62f745eeba"),
1509 ResourceKind::Embedded,
1510 SurfaceData::make_quad(&Matrix4::identity()),
1511 )
1512 );
1513
1514 pub static ref CYLINDER: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1516 "__CylinderSurface",
1517 SurfaceResource::new_ok(
1518 uuid!("16300ec8-4446-41a7-8ad6-9b45428d0b1b"),
1519 ResourceKind::Embedded,
1520 SurfaceData::make_cylinder(32, 1.0, 1.0, true, &Matrix4::identity()),
1521 )
1522 );
1523
1524 pub static ref SPHERE: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1526 "__SphereSurface",
1527 SurfaceResource::new_ok(
1528 uuid!("ff1811ba-b9ad-4c37-89b8-503f79aaa4bd"),
1529 ResourceKind::Embedded,
1530 SurfaceData::make_sphere(32, 32, 1.0, &Matrix4::identity()),
1531 )
1532 );
1533
1534 pub static ref CONE: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1536 "__ConeSurface",
1537 SurfaceResource::new_ok(
1538 uuid!("e4e79405-39c5-4fe4-ba3e-c961f3d7379e"),
1539 ResourceKind::Embedded,
1540 SurfaceData::make_cone(32, 1.0, 1.0, &Matrix4::identity()),
1541 )
1542 );
1543
1544 pub static ref TORUS: BuiltInResource<SurfaceData> = BuiltInResource::new_no_source(
1546 "__TorusSurface",
1547 SurfaceResource::new_ok(
1548 uuid!("d2bb5455-c72e-475d-90da-e3a7bd5b7d07"),
1549 ResourceKind::Embedded,
1550 SurfaceData::make_torus(1.0, 0.25,32, 32, &Matrix4::identity()),
1551 )
1552 );
1553}