Skip to content

Commit 798a59c

Browse files
committed
WIP
1 parent e96687e commit 798a59c

3 files changed

Lines changed: 277 additions & 2 deletions

File tree

src/libguc/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ set(LIBGUC_DEFINES
4141
if(TARGET usd_ms)
4242
set(LIBGUC_USD_LIBS usd_ms)
4343
else()
44-
set(LIBGUC_USD_LIBS usd usdGeom usdLux usdShade usdUtils usdMtlx usdUI)
44+
set(LIBGUC_USD_LIBS usd usdGeom usdLux usdShade usdUtils usdMtlx usdUI ts)
4545
endif()
4646

4747
set(LIBGUC_SHARED_LIBRARIES

src/libguc/src/converter.cpp

Lines changed: 274 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@
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)

src/libguc/src/converter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ namespace guc
6565
private:
6666
void createMaterials(FileExports& fileExports, bool createDefaultMaterial);
6767
void createNodesRecursively(const cgltf_node* nodeData, SdfPath path);
68+
void createAnimation(const char* name, const cgltf_animation_channel* channel);
6869
void createOrOverCamera(const cgltf_camera* cameraData, SdfPath path);
6970
void createOrOverLight(const cgltf_light* lightData, SdfPath path);
7071
void createOrOverMesh(const cgltf_mesh* meshData, SdfPath path);
@@ -87,5 +88,6 @@ namespace guc
8788
UsdPreviewSurfaceMaterialConverter m_usdPreviewSurfaceConverter;
8889
std::unordered_map<void*, SdfPath> m_uniquePaths;
8990
std::vector<std::string> m_materialNames;
91+
std::vector<SdfPath> m_nodeXforms;
9092
};
9193
}

0 commit comments

Comments
 (0)