grafix_toolbox/kit/opengl/geom/
model.rs1use 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}