1use crate::{declare_public_tokens, sdf, tf, usd};
5
6declare_public_tokens!(Tokens, TOKENS, [
7 face_vertex_counts: "faceVertexCounts",
8 face_vertex_indices: "faceVertexIndices",
9 normals: "normals",
10 points: "points",
11 purpose: "purpose",
12 visibility: "visibility",
13 xform_op_order: "xformOpOrder"
14]);
15
16#[repr(transparent)]
17pub struct Imageable<'a>(usd::SchemaBase<'a>);
18
19impl Imageable<'_> {
20 pub fn define(stage: &usd::Stage, path: impl Into<sdf::Path>) -> Imageable {
21 Imageable(usd::SchemaBase::new(stage.prim_at_path(path)))
22 }
23
24 pub fn visibility_attr(&self) -> usd::Attribute {
25 self.prim().get_attribute(&TOKENS.visibility)
26 }
27
28 pub fn purpose_attr(&self) -> usd::Attribute {
29 self.prim().get_attribute(&TOKENS.purpose)
30 }
31}
32
33impl<'a> std::ops::Deref for Imageable<'a> {
34 type Target = usd::SchemaBase<'a>;
35 fn deref(&self) -> &Self::Target {
36 unsafe { std::mem::transmute(self) }
37 }
38}
39
40#[repr(transparent)]
41pub struct Xformable<'a>(usd::SchemaBase<'a>);
42
43impl Xformable<'_> {
44 pub fn define(stage: &usd::Stage, path: impl Into<sdf::Path>) -> Xformable {
45 Xformable(usd::SchemaBase::new(stage.prim_at_path(path)))
46 }
47
48 pub fn xform_op_order_attr(&self) -> usd::Attribute {
49 self.prim().get_attribute(&TOKENS.xform_op_order)
50 }
51}
52
53impl<'a> std::ops::Deref for Xformable<'a> {
54 type Target = Imageable<'a>;
55 fn deref(&self) -> &Self::Target {
56 unsafe { std::mem::transmute(self) }
57 }
58}
59
60#[repr(transparent)]
61pub struct Boundable<'a>(usd::SchemaBase<'a>);
62
63impl Boundable<'_> {
64 pub fn define(stage: &usd::Stage, path: impl Into<sdf::Path>) -> Boundable {
65 Boundable(usd::SchemaBase::new(stage.prim_at_path(path)))
66 }
67}
68
69impl<'a> std::ops::Deref for Boundable<'a> {
70 type Target = Xformable<'a>;
71 fn deref(&self) -> &Self::Target {
72 unsafe { std::mem::transmute(self) }
73 }
74}
75
76#[repr(transparent)]
77pub struct Gprim<'a>(usd::SchemaBase<'a>);
78
79impl Gprim<'_> {
80 pub fn define(stage: &usd::Stage, path: impl Into<sdf::Path>) -> Gprim {
81 Gprim(usd::SchemaBase::new(stage.prim_at_path(path)))
82 }
83}
84
85impl<'a> std::ops::Deref for Gprim<'a> {
86 type Target = Boundable<'a>;
87 fn deref(&self) -> &Self::Target {
88 unsafe { std::mem::transmute(self) }
89 }
90}
91
92#[repr(transparent)]
93pub struct PointBased<'a>(usd::SchemaBase<'a>);
94
95impl PointBased<'_> {
96 pub fn define(stage: &usd::Stage, path: impl Into<sdf::Path>) -> PointBased {
97 PointBased(usd::SchemaBase::new(stage.prim_at_path(path)))
98 }
99
100 pub fn points_attr(&self) -> usd::Attribute {
101 self.prim().get_attribute(&TOKENS.points)
102 }
103
104 pub fn normals_attr(&self) -> usd::Attribute {
105 self.prim().get_attribute(&TOKENS.normals)
106 }
107}
108
109impl<'a> std::ops::Deref for PointBased<'a> {
110 type Target = Gprim<'a>;
111 fn deref(&self) -> &Self::Target {
112 unsafe { std::mem::transmute(self) }
113 }
114}
115
116#[repr(transparent)]
117pub struct Mesh<'a>(usd::SchemaBase<'a>);
118
119impl Mesh<'_> {
120 pub fn define(stage: &usd::Stage, path: impl Into<sdf::Path>) -> Mesh {
121 Mesh(usd::SchemaBase::new(stage.prim_at_path(path)))
122 }
123
124 pub fn face_vertex_indices_attr(&self) -> usd::Attribute {
125 self.prim().get_attribute(&TOKENS.face_vertex_indices)
126 }
127
128 pub fn face_vertex_counts_attr(&self) -> usd::Attribute {
129 self.prim().get_attribute(&TOKENS.face_vertex_counts)
130 }
131}
132
133impl<'a> std::ops::Deref for Mesh<'a> {
134 type Target = PointBased<'a>;
135 fn deref(&self) -> &Self::Target {
136 unsafe { std::mem::transmute(self) }
137 }
138}
139
140use super::*;
143use half::f16;
144
145use glam::{DMat4, DQuat, DVec3, dvec3};
146
147pub fn triangulate(mesh: &Mesh) -> Vec<i32> {
148 let face_vertex_counts = mesh.face_vertex_counts_attr().get::<Vec<i32>>();
149 let face_vertex_indices = mesh.face_vertex_indices_attr().get::<Vec<i32>>();
150
151 let mut indices = vec![];
152
153 let mut index = 0;
155 for &count in &face_vertex_counts {
156 for i in 0..(count - 2) as usize {
157 indices.push(face_vertex_indices[index]);
158 indices.push(face_vertex_indices[index + i + 1]);
159 indices.push(face_vertex_indices[index + i + 2]);
160 }
161 index += count as usize;
162 }
163
164 indices
165}
166
167pub enum XformOpType {
168 TranslateX,
170 TranslateY,
171 TranslateZ,
172 Translate,
174
175 ScaleX,
177 ScaleY,
178 ScaleZ,
179 Scale,
181
182 RotateX,
184 RotateY,
185 RotateZ,
186
187 RotateXYZ,
189 RotateXZY,
190 RotateYXZ,
191 RotateYZX,
192 RotateZXY,
193 RotateZYX,
194
195 Orient,
197
198 Transform,
200}
201
202impl TryFrom<&str> for XformOpType {
203 type Error = ();
204 fn try_from(s: &str) -> Result<Self, Self::Error> {
205 Ok(match s {
206 "translateX" => XformOpType::TranslateX,
207 "translateY" => XformOpType::TranslateY,
208 "translateZ" => XformOpType::TranslateZ,
209 "translate" => XformOpType::Translate,
210 "scaleX" => XformOpType::ScaleX,
211 "scaleY" => XformOpType::ScaleY,
212 "scaleZ" => XformOpType::ScaleZ,
213 "scale" => XformOpType::Scale,
214 "rotateX" => XformOpType::RotateX,
215 "rotateY" => XformOpType::RotateY,
216 "rotateZ" => XformOpType::RotateZ,
217 "rotateXYZ" => XformOpType::RotateXYZ,
218 "rotateXZY" => XformOpType::RotateXZY,
219 "rotateYXZ" => XformOpType::RotateYXZ,
220 "rotateYZX" => XformOpType::RotateYZX,
221 "rotateZXY" => XformOpType::RotateZXY,
222 "rotateZYX" => XformOpType::RotateZYX,
223 "orient" => XformOpType::Orient,
224 "transform" => XformOpType::Transform,
225 _ => return Err(()),
226 })
227 }
228}
229
230pub struct XformOp {}
231
232impl XformOp {
233 fn get_op_transform(op_type: XformOpType, value: vt::Value, is_inverse: bool) -> Option<DMat4> {
234 use XformOpType::*;
235
236 let get_scalar = || -> Option<f64> {
237 value
238 .get::<f64>()
239 .or_else(|| value.get::<f32>().map(|v| v.into()))
240 .or_else(|| value.get::<f16>().map(|v| v.into()))
241 };
242
243 let get_vec3 = || -> Option<DVec3> {
244 value
245 .get::<gf::Vec3d>()
246 .or_else(|| value.get::<gf::Vec3f>().map(|v| v.into()))
247 .or_else(|| value.get::<gf::Vec3h>().map(|v| v.into()))
248 .map(|v| DVec3::new(v.x, v.y, v.z))
249 };
250
251 let get_quat = || -> Option<DQuat> {
252 value
253 .get::<gf::Quatd>()
254 .or_else(|| value.get::<gf::Quatf>().map(|v| v.into()))
255 .or_else(|| value.get::<gf::Quath>().map(|v| v.into()))
256 .map(|v| DQuat::from_xyzw(v.i, v.j, v.k, v.w))
257 };
258
259 Some(match op_type {
260 TranslateX if is_inverse => DMat4::from_translation(dvec3(-get_scalar()?, 0.0, 0.0)),
261 TranslateY if is_inverse => DMat4::from_translation(dvec3(0.0, -get_scalar()?, 0.0)),
262 TranslateZ if is_inverse => DMat4::from_translation(dvec3(0.0, 0.0, -get_scalar()?)),
263 Translate if is_inverse => DMat4::from_translation(-get_vec3()?),
264
265 TranslateX => DMat4::from_translation(dvec3(get_scalar()?, 0.0, 0.0)),
266 TranslateY => DMat4::from_translation(dvec3(0.0, get_scalar()?, 0.0)),
267 TranslateZ => DMat4::from_translation(dvec3(0.0, 0.0, get_scalar()?)),
268 Translate => DMat4::from_translation(get_vec3()?),
269
270 ScaleX if is_inverse => DMat4::from_scale(dvec3(1.0 / get_scalar()?, 1.0, 1.0)),
271 ScaleY if is_inverse => DMat4::from_scale(dvec3(1.0, 1.0 / get_scalar()?, 1.0)),
272 ScaleZ if is_inverse => DMat4::from_scale(dvec3(1.0, 1.0, 1.0 / get_scalar()?)),
273 Scale if is_inverse => DMat4::from_scale(1.0 / get_vec3()?),
274
275 ScaleX => DMat4::from_scale(dvec3(get_scalar()?, 1.0, 1.0)),
276 ScaleY => DMat4::from_scale(dvec3(1.0, get_scalar()?, 1.0)),
277 ScaleZ => DMat4::from_scale(dvec3(1.0, 1.0, get_scalar()?)),
278 Scale => DMat4::from_scale(get_vec3()?),
279
280 RotateX if is_inverse => DMat4::from_rotation_x(-get_scalar()?),
281 RotateY if is_inverse => DMat4::from_rotation_y(-get_scalar()?),
282 RotateZ if is_inverse => DMat4::from_rotation_z(-get_scalar()?),
283
284 RotateX => DMat4::from_rotation_x(get_scalar()?),
285 RotateY => DMat4::from_rotation_y(get_scalar()?),
286 RotateZ => DMat4::from_rotation_z(get_scalar()?),
287
288 RotateXYZ | RotateXZY | RotateYXZ | RotateYZX | RotateZXY | RotateZYX => {
289 let vec = if is_inverse {
290 -get_vec3()?
291 } else {
292 get_vec3()?
293 };
294
295 let rot_x = DQuat::from_axis_angle(DVec3::X, vec.x);
296 let rot_y = DQuat::from_axis_angle(DVec3::Y, vec.y);
297 let rot_z = DQuat::from_axis_angle(DVec3::Z, vec.z);
298
299 let rot = match op_type {
300 RotateXYZ if is_inverse => rot_z * rot_y * rot_x,
301 RotateXZY if is_inverse => rot_y * rot_z * rot_x,
302 RotateYXZ if is_inverse => rot_z * rot_x * rot_y,
303 RotateYZX if is_inverse => rot_x * rot_z * rot_y,
304 RotateZXY if is_inverse => rot_y * rot_x * rot_z,
305 RotateZYX if is_inverse => rot_x * rot_y * rot_z,
306
307 RotateXYZ => rot_x * rot_y * rot_z,
308 RotateXZY => rot_x * rot_z * rot_y,
309 RotateYXZ => rot_y * rot_x * rot_z,
310 RotateYZX => rot_y * rot_z * rot_x,
311 RotateZXY => rot_z * rot_x * rot_y,
312 RotateZYX => rot_z * rot_y * rot_x,
313 _ => unreachable!(),
314 };
315
316 DMat4::from_quat(rot)
317 }
318 Orient => DMat4::from_quat(if is_inverse {
319 get_quat()?.inverse()
320 } else {
321 get_quat()?
322 }),
323 Transform => {
324 let mat = value.get::<gf::Matrix4d>()?;
325 let mat = DMat4::from_cols_array_2d(&mat.data).transpose();
327 if is_inverse { mat.inverse() } else { mat }
328 }
329 })
330 }
331
332 pub fn get_local_transform(prim: &usd::Prim) -> Option<gf::Transform3d> {
333 let mut matrix = DMat4::IDENTITY;
334
335 if !prim.has_attribute(&TOKENS.xform_op_order) {
336 return None;
337 }
338
339 let op_order = prim
340 .get_attribute(&TOKENS.xform_op_order)
341 .get::<Vec<tf::Token>>();
342
343 for op in op_order.iter().rev() {
344 let op_type =
345 XformOpType::try_from(op.as_str().trim_start_matches("xformOp:")).unwrap();
346 if let Some(op_value) = prim.get_attribute(&op).get_value() {
347 if let Some(mat) = Self::get_op_transform(op_type, op_value, false) {
348 matrix *= mat;
349 }
350 }
351 }
352
353 let transform = matrix.to_scale_rotation_translation();
354 Some(gf::Transform3d {
355 translation: gf::Vec3d {
356 x: transform.2.x,
357 y: transform.2.y,
358 z: transform.2.z,
359 },
360 rotation: gf::Quatd {
361 i: transform.1.x,
362 j: transform.1.y,
363 k: transform.1.z,
364 w: transform.1.w,
365 },
366 scale: gf::Vec3d {
367 x: transform.0.x,
368 y: transform.0.y,
369 z: transform.0.z,
370 },
371 })
372 }
373}