1818
1919#include < pxr/base/tf/envSetting.h>
2020#include < pxr/base/gf/colorSpace.h>
21+ #include < pxr/base/gf/vec4f.h>
22+ #include < pxr/base/gf/quatf.h>
23+ #include < pxr/base/gf/vec3f.h>
2124#include < pxr/base/gf/matrix4f.h>
25+ #include < pxr/base/gf/rotation.h>
26+ #include < pxr/base/ts/knot.h>
27+ #include < pxr/base/ts/spline.h>
28+ #include < pxr/base/vt/visitValue.h>
2229#include < pxr/usd/usd/stage.h>
2330#include < pxr/usd/usd/editContext.h>
2431#include < pxr/usd/usdGeom/camera.h>
@@ -112,7 +119,10 @@ namespace detail
112119 }
113120 else if constexpr (std::is_same<T, GfVec2f>() ||
114121 std::is_same<T, GfVec3f>() ||
115- std::is_same<T, GfVec4f>())
122+ std::is_same<T, GfVec4f>() ||
123+ std::is_same<T, GfMatrix2f>() ||
124+ std::is_same<T, GfMatrix3f>() ||
125+ std::is_same<T, GfMatrix4f>())
116126 {
117127 if (!cgltf_accessor_read_float (accessor, i, item.data (), elementSize))
118128 {
@@ -160,6 +170,23 @@ namespace detail
160170 {
161171 array[i] = GfVec4f (floats[i * 4 + 0 ], floats[i * 4 + 1 ], floats[i * 4 + 2 ], floats[i * 4 + 3 ]);
162172 }
173+ else if constexpr (std::is_same<T, GfMatrix2d>())
174+ {
175+ array[i] = GfMatrix2d (floats[i * 4 + 0 ], floats[i * 4 + 1 ], floats[i * 4 + 2 ], floats[i * 4 + 3 ]);
176+ }
177+ else if constexpr (std::is_same<T, GfMatrix3d>())
178+ {
179+ array[i] = GfMatrix3d (floats[i * 9 + 0 ], floats[i * 9 + 1 ], floats[i * 9 + 2 ],
180+ floats[i * 9 + 3 ], floats[i * 9 + 4 ], floats[i * 9 + 5 ],
181+ floats[i * 9 + 6 ], floats[i * 9 + 7 ], floats[i * 9 + 8 ]);
182+ }
183+ else if constexpr (std::is_same<T, GfMatrix4d>())
184+ {
185+ array[i] = GfMatrix4d (floats[i * 16 + 0 ], floats[i * 16 + 1 ], floats[i * 16 + 2 ], floats[i * 16 + 3 ],
186+ floats[i * 16 + 4 ], floats[i * 16 + 5 ], floats[i * 16 + 6 ], floats[i * 16 + 7 ],
187+ floats[i * 16 + 8 ], floats[i * 16 + 9 ], floats[i * 16 + 10 ], floats[i * 16 + 11 ],
188+ floats[i * 16 + 12 ], floats[i * 16 + 13 ], floats[i * 16 + 14 ], floats[i * 16 + 15 ]);
189+ }
163190 else if constexpr (std::is_same<T, int >() || std::is_same<T, float >())
164191 {
165192 array[i] = floats[i];
@@ -186,6 +213,103 @@ namespace detail
186213 return true ;
187214 }
188215
216+ // TODO: reduce length
217+ bool readBoxedVtArrayFromAccessor (const cgltf_accessor* accessor, VtValue& value)
218+ {
219+ switch (accessor->type )
220+ {
221+ case cgltf_type_scalar:
222+ {
223+ if (accessor->component_type == cgltf_component_type_r_32f)
224+ {
225+ VtFloatArray array;
226+ if (readVtArrayFromAccessor (accessor, array))
227+ {
228+ value = VtValue (array);
229+ return true ;
230+ }
231+ }
232+ else
233+ {
234+ VtIntArray array;
235+ if (readVtArrayFromAccessor (accessor, array))
236+ {
237+ value = VtValue (array);
238+ return true ;
239+ }
240+ }
241+ }
242+ case cgltf_type_vec2:
243+ {
244+ VtVec2fArray array;
245+ if (readVtArrayFromAccessor (accessor, array))
246+ {
247+ value = VtValue (array);
248+ return true ;
249+ }
250+ }
251+ case cgltf_type_vec3:
252+ {
253+ VtVec3fArray array;
254+ if (readVtArrayFromAccessor (accessor, array))
255+ {
256+ value = VtValue (array);
257+ return true ;
258+ }
259+ }
260+ case cgltf_type_vec4:
261+ {
262+ VtVec4fArray array;
263+ if (readVtArrayFromAccessor (accessor, array))
264+ {
265+ value = VtValue (array);
266+ return true ;
267+ }
268+ }
269+ case cgltf_type_mat2:
270+ {
271+ VtMatrix2dArray array;
272+ if (readVtArrayFromAccessor (accessor, array))
273+ {
274+ value = VtValue (array);
275+ return true ;
276+ }
277+ }
278+ case cgltf_type_mat3:
279+ {
280+ VtMatrix3dArray array;
281+ if (readVtArrayFromAccessor (accessor, array))
282+ {
283+ value = VtValue (array);
284+ return true ;
285+ }
286+ }
287+ case cgltf_type_mat4:
288+ {
289+ VtMatrix4dArray array;
290+ if (readVtArrayFromAccessor (accessor, array))
291+ {
292+ value = VtValue (array);
293+ return true ;
294+ }
295+ }
296+ default :
297+ break ;
298+ }
299+
300+ return false ;
301+ }
302+
303+ // TODO: all types
304+ VtValue sampleBoxedVtValueFromArray (VtValue array, uint32_t index)
305+ {
306+ TF_STATUS (" %s" , array.GetTypeName ().c_str ());
307+ if (array.IsHolding <VtFloatArray>()) { return VtValue (array.UncheckedGet <VtFloatArray>()[index]); }
308+ if (array.IsHolding <VtVec3fArray>()) { return VtValue (array.UncheckedGet <VtVec3fArray>()[index]); }
309+ if (array.IsHolding <VtVec4fArray>()) { return VtValue (array.UncheckedGet <VtVec4fArray>()[index]); }
310+ return VtValue ();
311+ }
312+
189313 void markAttributeAsGenerated (UsdAttribute attr)
190314 {
191315 VtDictionary customData;
@@ -373,6 +497,17 @@ namespace guc
373497 createNodes (nodeData, nodesPath);
374498 }
375499 }
500+
501+ // Create animation splines retroactively on generated Xforms
502+ for (size_t i = 0 ; i < m_data->animations_count ; i++)
503+ {
504+ const cgltf_animation* anim = &m_data->animations [i];
505+
506+ for (size_t j = 0 ; j < anim->channels_count ; j++)
507+ {
508+ createAnimation (anim->name , &anim->channels [j]);
509+ }
510+ }
376511 }
377512
378513 void Converter::createMaterials (FileExports& fileExports, bool createDefaultMaterial)
@@ -570,6 +705,144 @@ namespace guc
570705 UsdPrim prim = xform.GetPrim ();
571706 detail::setDisplayName (prim, nodeData->name );
572707 }
708+
709+ // Store the nodes for lookup when handling animations
710+ size_t nodeIndex = cgltf_node_index (m_data, nodeData);
711+ if (m_nodeXforms.size () <= nodeIndex)
712+ {
713+ m_nodeXforms.resize (nodeIndex + 1 );
714+ }
715+ m_nodeXforms[nodeIndex] = path;
716+ }
717+
718+ // TODO: are multiple channels on the same node/target allowed?
719+ void Converter::createAnimation (const char * name, const cgltf_animation_channel* channel)
720+ {
721+ if (!channel->target_node )
722+ {
723+ TF_WARN (" skipping animation channel with missing target node" );
724+ return ;
725+ }
726+
727+ size_t nodeIndex = cgltf_node_index (m_data, channel->target_node );
728+ const SdfPath& nodePath = m_nodeXforms[nodeIndex];
729+ UsdPrim prim = m_stage->GetPrimAtPath (nodePath);
730+ UsdGeomXform xform (prim);
731+
732+ UsdGeomXformOp op;
733+ switch (channel->target_path )
734+ {
735+ case cgltf_animation_path_type_translation:
736+ op = xform.AddTranslateOp ();
737+ break ;
738+ case cgltf_animation_path_type_rotation:
739+ op = xform.AddRotateXYZOp ();
740+ break ;
741+ case cgltf_animation_path_type_scale:
742+ op = xform.AddScaleOp ();
743+ break ;
744+ default :
745+ TF_WARN (" unsupported target path; skipping animation channel" );
746+ return ;
747+ }
748+
749+ const cgltf_animation_sampler* sampler = channel->sampler ;
750+
751+ TsInterpMode interpMode;
752+ switch (sampler->interpolation )
753+ {
754+ case cgltf_interpolation_type_linear:
755+ interpMode = TsInterpLinear;
756+ break ;
757+ case cgltf_interpolation_type_step:
758+ interpMode = TsInterpHeld;
759+ break ;
760+ case cgltf_interpolation_type_cubic_spline:
761+ interpMode = TsInterpCurve;
762+ break ;
763+ default :
764+ TF_WARN (" unsupported interpolation type; skipping animation channel" );
765+ break ;
766+ }
767+
768+ VtFloatArray keyframeTimes;
769+ VtValue keyframeValues;
770+ if (!detail::readVtArrayFromAccessor (sampler->input , keyframeTimes) ||
771+ !detail::readBoxedVtArrayFromAccessor (sampler->output , keyframeValues) ||
772+ keyframeTimes.size () != keyframeValues.GetArraySize ())
773+ {
774+ TF_WARN (" invalid input or output values; skipping animation channel" );
775+ return ;
776+ }
777+
778+ if ((channel->target_path == cgltf_animation_path_type_translation && !keyframeValues.IsHolding <VtVec3fArray>()) ||
779+ (channel->target_path == cgltf_animation_path_type_rotation && !keyframeValues.IsHolding <VtVec4fArray>()) ||
780+ (channel->target_path == cgltf_animation_path_type_scale && !keyframeValues.IsHolding <VtVec3fArray>()))
781+ {
782+ TF_WARN (" invalid output values; skipping animation channel" );
783+ return ;
784+ }
785+
786+ if (channel->target_path == cgltf_animation_path_type_rotation)
787+ {
788+ VtVec4fArray array = keyframeValues.UncheckedGet <VtVec4fArray>();
789+ VtVec3fArray newArray (array.size ());
790+
791+ for (size_t i = 0 ; i < array.size (); i++)
792+ {
793+ const GfVec4f& v = array[i];
794+
795+ GfQuatf quat (v[3 ], GfVec3f (v[0 ], v[1 ], v[2 ]));
796+
797+ GfMatrix4f m;
798+ m.SetRotate (quat);
799+
800+ GfRotation rot = m.ExtractRotation ();
801+
802+ GfVec3d newV = rot.Decompose (
803+ GfVec3f (1 .0f , 0 .0f , 0 .0f ),
804+ GfVec3f (0 .0f , 1 .0f , 0 .0f ),
805+ GfVec3f (0 .0f , 0 .0f , 1 .0f )
806+ );
807+
808+ newArray[i] = GfVec3f (newV);
809+ }
810+
811+ keyframeValues = VtValue (newArray);
812+ }
813+
814+ // TODO: put the following in a separate function which we can call for KHR_animation_pointer
815+
816+ size_t keyframeCount = keyframeTimes.size ();
817+
818+ TsKnotMap knotMap;
819+ knotMap.reserve (keyframeCount);
820+
821+ for (size_t i = 0 ; i < keyframeCount; i++)
822+ {
823+ // TODO: spline & knot classes are WIP; only support SCALAR float values right now :(
824+
825+ TsKnot knot (TfType::Find<float >());// keyframeValues.GetType());
826+ knot.SetTime (keyframeTimes[i]);
827+ knot.SetNextInterpolation (interpMode);
828+ knot.SetValue (detail::sampleBoxedVtValueFromArray (keyframeValues, i));
829+ if (interpMode == TsInterpCurve)
830+ {
831+ // TODO: Bezier or Hemite?
832+ knot.SetCurveType (TsCurveTypeHermite); // TODO: function is deprecated; pass in constructor
833+ }
834+ knotMap.insert (knot);
835+ }
836+
837+ // TODO: do we need to call spline.SetInnerLoopParams()?
838+
839+ TsSpline spline;// (keyframeValues.GetType());
840+ spline.SetKnots (knotMap);
841+
842+ auto attr = op.GetAttr ();
843+ attr.SetSpline (spline);
844+
845+ // TODO: author name, for example using user dict
573846 }
574847
575848 void Converter::createOrOverCamera (const cgltf_camera* cameraData, SdfPath path)
0 commit comments