grafix_toolbox/kit/opengl/geom/
model.rs

1use super::*;
2use crate::math::*;
3
4#[derive(Default, Debug, Clone)]
5pub struct Model {
6	idxs: Box<[u32]>,
7	xyz: Box<[f32]>,
8	uv: Box<[f16]>,
9	norm: Box<[f16]>,
10}
11#[cfg(feature = "obj")]
12impl Model {
13	pub fn load_models(file: &str, scale: f32) -> Res<Vec<Self>> {
14		let file = &format!("res/{file}.obj");
15		let (models, _) = tobj::load_obj(
16			file,
17			&tobj::LoadOptions {
18				single_index: true,
19				triangulate: true,
20				ignore_points: true,
21				ignore_lines: true,
22			},
23		)
24		.explain_err(|| format!("Cannot load models from {file:?}"))?;
25		let models = models
26			.into_iter()
27			.map(|m| {
28				let m = m.mesh;
29				let (idxs, xyz, uv, mut norm) = (
30					m.indices.into(),
31					m.positions,
32					m.texcoords.into_iter().map(f16).collect(),
33					m.normals.iter().map(|&v| f16(v)).collect_vec(),
34				);
35				let (mut min, mut max) = ((0., 0., 0.), (0., 0., 0.));
36				for i in (0..xyz.len()).step_by(3) {
37					let v = Vec3(&xyz[i..]);
38					min = min.fmin(v);
39					max = max.fmax(v);
40					if m.normals.is_empty() && i % 9 == 0 && i + 8 < xyz.len() {
41						let xyz = &xyz[i..];
42						let (v1, v2, v3) = vec3::<Vec3>::to((xyz, &xyz[3..], &xyz[6..]));
43						let ndir = v1.sum(v2).sum(v3).div(3).sgn();
44						let (v1, v2, v3) = vec3::<la::V3>::to((v1, v2, v3));
45						let n = <[_; 3]>::to(hVec3(Vec3(la::normal(v1, v2, v3)).mul(ndir)));
46						(0..9).for_each(|i| norm.push(n[i % 3]));
47					}
48				}
49				let d: Vec3 = max.sub(min);
50				let (center, scale) = (max.sum(min).div(2), (1., 1., 1.).div(d.x().max(d.y()).max(d.z())).mul(scale));
51				let xyz = xyz.chunks(3).flat_map(|s| <[_; 3]>::to((Vec3(s)).sub(center).mul(scale)).to_vec()).collect();
52				Self { idxs, xyz, uv, norm: norm.into() }
53			})
54			.collect();
55		Ok(models)
56	}
57	#[cfg(feature = "adv_fs")]
58	pub fn new_cached(name: &str) -> Res<Self> {
59		let cache = format!("{name}.obj.z");
60		if let Ok(d) = FS::Load::Archive(&cache) {
61			if let Ok(model) = ser::SERDE::FromVec(&d) {
62				return Ok(model);
63			}
64		}
65
66		let model: Res<Self> = (|| {
67			let m = Self::load_models(name, 1.)?.into_iter().next().ok_or("Empty models file")?;
68			let _ = ser::SERDE::ToVec(&m).map(|v| FS::Save::Archive((cache, v, 22)));
69			Ok(m)
70		})();
71		model
72	}
73}
74impl<T: Borrow<Model>> From<T> for Mesh<u32, f32, f16, f16> {
75	fn from(m: T) -> Self {
76		let m = m.borrow();
77		let (i, c, n) = (&m.idxs, &m.xyz, &m.norm);
78		if m.uv.is_empty() {
79			Self::new((i, c, n, gl::TRIANGLES))
80		} else {
81			Self::new((i, c, &m.uv, n, gl::TRIANGLES))
82		}
83	}
84}
85
86impl Mesh<u16, f32, f16, f32> {
87	pub fn make_sphere(scale: f32, segs: u32) -> Self {
88		let (xyz, uv) = {
89			let (mut xyz, mut uv) = (vec![], vec![]);
90			iter2d(0..1 + segs).for_each(|(x, y)| {
91				let (sx, sy) = Vec2((x, y)).div(segs);
92				let (rx, ry) = (sx.to_radians(), sy.to_radians());
93				let (x, y, z) = ((rx * 360.).cos() * (ry * 180.).sin(), (ry * 180.).cos(), (rx * 360.).sin() * (ry * 180.).sin()).mul(scale);
94				let (sx, sy) = hVec2((sx, sy).norm());
95				xyz.extend(&[x, y, z]);
96				uv.extend(&[sx, sy]);
97			});
98			(xyz, uv)
99		};
100
101		let idx = (0..segs)
102			.flat_map(|y| {
103				let s = segs + 1;
104				let row = (0..s).flat_map(|x| vec![y * s + x, (y + 1) * s + x]);
105				if y % 2 == y {
106					row.collect_vec()
107				} else {
108					row.rev().collect_vec()
109				}
110			})
111			.map(u16)
112			.collect_vec();
113
114		let draw = (u32(idx.len()), gl::TRIANGLE_STRIP);
115		let idx = IdxArr::new(&idx[..]);
116		let xyz = AttrArr::new(&xyz[..]);
117		let uv = AttrArr::new(&uv[..]);
118
119		let mut vao = Vao::new();
120		vao.BindIdxs(&idx);
121		vao.AttribFmt(&xyz, (0, 3));
122		vao.AttribFmt(&uv, (1, 2));
123		vao.AttribFmt(&xyz, (2, 3));
124		let buff = (idx, xyz, Some(uv), Def());
125
126		Self { vao, buff, draw }
127	}
128}
129
130#[cfg(feature = "adv_fs")]
131mod serde {
132	use super::{ser::*, *};
133	impl Serialize for Model {
134		fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
135			self.to_bytes().serialize(s)
136		}
137	}
138	impl<'de> Deserialize<'de> for Model {
139		fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
140			Ok(Self::from_bytes(<&[u8]>::deserialize(d)?))
141		}
142	}
143}
144
145impl Model {
146	pub fn to_bytes(&self) -> Box<[u8]> {
147		let Self { idxs, xyz, uv, norm } = self;
148		let il: [_; 8] = (idxs.len() * type_size::<u32>()).to_le_bytes();
149		let cl: [_; 8] = (xyz.len() * type_size::<f32>()).to_le_bytes();
150		let tl: [_; 8] = (uv.len() * type_size::<f16>()).to_le_bytes();
151		let (_, i, _) = unsafe { idxs.align_to() };
152		let (_, c, _) = unsafe { xyz.align_to() };
153		let (_, t, _) = unsafe { uv.align_to() };
154		let (_, n, _) = unsafe { norm.align_to() };
155		[&il, &cl, &tl, i, c, t, n].concat().into()
156	}
157	pub fn from_bytes(v: &[u8]) -> Self {
158		let il = 24 + usize::from_le_bytes(v[0..8].try_into().valid());
159		let cl = il + usize::from_le_bytes(v[8..16].try_into().valid());
160		let tl = cl + usize::from_le_bytes(v[16..24].try_into().valid());
161		let idxs = unsafe { v[24..il].align_to() }.1.into();
162		let xyz = unsafe { v[il..cl].align_to() }.1.into();
163		let uv = unsafe { v[cl..tl].align_to() }.1.into();
164		let norm = unsafe { v[tl..].align_to() }.1.into();
165		Self { idxs, xyz, uv, norm }
166	}
167}