appcore_render/
asset_data.rs1use crate::{RenderError, Transform};
12use std::sync::{
13 atomic::{AtomicU64, Ordering},
14 Arc,
15};
16pub(crate) struct AssetLease {
17 pub(crate) counter: Arc<AtomicU64>,
18 pub(crate) bytes: u64,
19}
20impl Drop for AssetLease {
21 fn drop(&mut self) {
22 self.counter.fetch_sub(self.bytes, Ordering::AcqRel);
23 }
24}
25#[derive(Debug, Clone, Copy)]
27pub struct MeshVertex {
28 position: [f32; 3],
29 normal: [f32; 3],
30}
31impl MeshVertex {
32 pub fn new(position: [f32; 3], normal: [f32; 3]) -> Result<Self, RenderError> {
34 if !position
35 .iter()
36 .all(|v| v.is_finite() && v.abs() <= 1_000_000.0)
37 || !normal.iter().all(|v| v.is_finite())
38 || (normal.iter().map(|v| v * v).sum::<f32>() - 1.0).abs() > 0.0001
39 {
40 return Err(RenderError::InvalidLimits);
41 }
42 Ok(Self { position, normal })
43 }
44 pub fn position(self) -> [f32; 3] {
46 self.position
47 }
48 pub fn normal(self) -> [f32; 3] {
50 self.normal
51 }
52}
53#[derive(Debug, Clone, Copy)]
55pub struct BoundingSphere {
56 pub center: [f32; 3],
58 pub radius: f32,
60}
61pub struct MeshAsset {
63 pub(crate) vertices: Vec<MeshVertex>,
64 pub(crate) indices: Vec<u32>,
65 pub(crate) bounds: BoundingSphere,
66 pub(crate) _lease: AssetLease,
67}
68impl MeshAsset {
69 pub fn vertices(&self) -> &[MeshVertex] {
71 &self.vertices
72 }
73 pub fn indices(&self) -> &[u32] {
75 &self.indices
76 }
77 pub fn bounds(&self) -> BoundingSphere {
79 self.bounds
80 }
81}
82pub(crate) struct Material {
83 pub(crate) color: [f32; 4],
84 pub(crate) _lease: AssetLease,
85}
86pub(crate) fn bounds(vertices: &[MeshVertex]) -> BoundingSphere {
87 let mut low = [f32::INFINITY; 3];
88 let mut high = [f32::NEG_INFINITY; 3];
89 for vertex in vertices {
90 for i in 0..3 {
91 low[i] = low[i].min(vertex.position[i]);
92 high[i] = high[i].max(vertex.position[i]);
93 }
94 }
95 let center = std::array::from_fn(|i| (low[i] + high[i]) * 0.5);
96 let radius = vertices
97 .iter()
98 .map(|v| {
99 (0..3)
100 .map(|i| (v.position[i] - center[i]).powi(2))
101 .sum::<f32>()
102 .sqrt()
103 })
104 .fold(0.0, f32::max);
105 BoundingSphere {
106 center,
107 radius: radius * (1.0 + 0.0001),
108 }
109}
110pub(crate) fn world_bounds(local: BoundingSphere, transform: Transform) -> BoundingSphere {
111 let scaled: [f32; 3] = std::array::from_fn(|i| local.center[i] * transform.scale()[i]);
112 let q = transform.rotation();
113 let cross = |a: [f32; 3], b: [f32; 3]| {
114 [
115 a[1] * b[2] - a[2] * b[1],
116 a[2] * b[0] - a[0] * b[2],
117 a[0] * b[1] - a[1] * b[0],
118 ]
119 };
120 let u = [q[0], q[1], q[2]];
121 let v = cross(u, scaled);
122 let w = cross(u, v);
123 let center =
124 std::array::from_fn(|i| scaled[i] + 2.0 * (q[3] * v[i] + w[i]) + transform.position()[i]);
125 let radius = local.radius * transform.scale().into_iter().fold(0.0, f32::max) * (1.0 + 0.0002);
126 BoundingSphere { center, radius }
127}