USD Keyframe Animations (#5856)

USD Keyframe Animations

Signed-off-by: AMZN-Gene <genewalt@amazon.com>
Signed-off-by: Gene Walters <genewalt@amazon.com>
Co-authored-by: Kazuki Y <6259214+kazu0617@users.noreply.github.com>
Co-authored-by: kazu0617 <kazu0617@protonmail.com>
Co-authored-by: Kim Kulling <kim.kulling@googlemail.com>
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
This commit is contained in:
Gene Walters
2024-11-28 12:29:58 -08:00
committed by GitHub
parent 12f3309996
commit 2493deff37
8 changed files with 400 additions and 23 deletions

View File

@@ -213,6 +213,7 @@ void USDImporterImplTinyusdz::InternReadFile(
}
// sanityCheckNodesRecursive(pScene->mRootNode);
animations(render_scene, pScene);
meshes(render_scene, pScene, nameWExt);
materials(render_scene, pScene, nameWExt);
textures(render_scene, pScene, nameWExt);
@@ -223,6 +224,128 @@ void USDImporterImplTinyusdz::InternReadFile(
setupBlendShapes(render_scene, pScene, nameWExt);
}
void USDImporterImplTinyusdz::animations(
const tinyusdz::tydra::RenderScene& render_scene,
aiScene* pScene) {
if (render_scene.animations.empty()) {
return;
}
pScene->mNumAnimations = render_scene.animations.size();
pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations];
for (int animationIndex = 0; animationIndex < pScene->mNumAnimations; ++animationIndex) {
const auto &animation = render_scene.animations[animationIndex];
auto newAiAnimation = new aiAnimation();
pScene->mAnimations[animationIndex] = newAiAnimation;
newAiAnimation->mName = animation.abs_path;
if (animation.channels_map.empty()) {
newAiAnimation->mNumChannels = 0;
continue;
}
// each channel affects a node (joint)
newAiAnimation->mNumChannels = animation.channels_map.size();
newAiAnimation->mChannels = new aiNodeAnim *[newAiAnimation->mNumChannels];
int channelIndex = 0;
for (const auto &[jointName, animationChannelMap] : animation.channels_map) {
auto newAiNodeAnim = new aiNodeAnim();
newAiAnimation->mChannels[channelIndex] = newAiNodeAnim;
newAiNodeAnim->mNodeName = jointName;
newAiAnimation->mDuration = 0;
std::vector<aiVectorKey> positionKeys;
std::vector<aiQuatKey> rotationKeys;
std::vector<aiVectorKey> scalingKeys;
for (const auto &[channelType, animChannel] : animationChannelMap) {
switch (channelType) {
case tinyusdz::tydra::AnimationChannel::ChannelType::Rotation:
if (animChannel.rotations.static_value.has_value()) {
rotationKeys.emplace_back(0, tinyUsdzQuatToAiQuat(animChannel.rotations.static_value.value()));
}
for (const auto &rotationAnimSampler : animChannel.rotations.samples) {
if (rotationAnimSampler.t > newAiAnimation->mDuration) {
newAiAnimation->mDuration = rotationAnimSampler.t;
}
rotationKeys.emplace_back(rotationAnimSampler.t, tinyUsdzQuatToAiQuat(rotationAnimSampler.value));
}
break;
case tinyusdz::tydra::AnimationChannel::ChannelType::Scale:
if (animChannel.scales.static_value.has_value()) {
scalingKeys.emplace_back(0, tinyUsdzScaleOrPosToAssimp(animChannel.scales.static_value.value()));
}
for (const auto &scaleAnimSampler : animChannel.scales.samples) {
if (scaleAnimSampler.t > newAiAnimation->mDuration) {
newAiAnimation->mDuration = scaleAnimSampler.t;
}
scalingKeys.emplace_back(scaleAnimSampler.t, tinyUsdzScaleOrPosToAssimp(scaleAnimSampler.value));
}
break;
case tinyusdz::tydra::AnimationChannel::ChannelType::Transform:
if (animChannel.transforms.static_value.has_value()) {
aiVector3D position;
aiVector3D scale;
aiQuaternion rotation;
tinyUsdzMat4ToAiMat4(animChannel.transforms.static_value.value().m).Decompose(scale, rotation, position);
positionKeys.emplace_back(0, position);
scalingKeys.emplace_back(0, scale);
rotationKeys.emplace_back(0, rotation);
}
for (const auto &transformAnimSampler : animChannel.transforms.samples) {
if (transformAnimSampler.t > newAiAnimation->mDuration) {
newAiAnimation->mDuration = transformAnimSampler.t;
}
aiVector3D position;
aiVector3D scale;
aiQuaternion rotation;
tinyUsdzMat4ToAiMat4(transformAnimSampler.value.m).Decompose(scale, rotation, position);
positionKeys.emplace_back(transformAnimSampler.t, position);
scalingKeys.emplace_back(transformAnimSampler.t, scale);
rotationKeys.emplace_back(transformAnimSampler.t, rotation);
}
break;
case tinyusdz::tydra::AnimationChannel::ChannelType::Translation:
if (animChannel.translations.static_value.has_value()) {
positionKeys.emplace_back(0, tinyUsdzScaleOrPosToAssimp(animChannel.translations.static_value.value()));
}
for (const auto &translationAnimSampler : animChannel.translations.samples) {
if (translationAnimSampler.t > newAiAnimation->mDuration) {
newAiAnimation->mDuration = translationAnimSampler.t;
}
positionKeys.emplace_back(translationAnimSampler.t, tinyUsdzScaleOrPosToAssimp(translationAnimSampler.value));
}
break;
default:
TINYUSDZLOGW(TAG, "Unsupported animation channel type (%s). Please update the USD importer to support this animation channel.", tinyusdzAnimChannelTypeFor(channelType).c_str());
}
}
newAiNodeAnim->mNumPositionKeys = positionKeys.size();
newAiNodeAnim->mPositionKeys = new aiVectorKey[newAiNodeAnim->mNumPositionKeys];
std::move(positionKeys.begin(), positionKeys.end(), newAiNodeAnim->mPositionKeys);
newAiNodeAnim->mNumRotationKeys = rotationKeys.size();
newAiNodeAnim->mRotationKeys = new aiQuatKey[newAiNodeAnim->mNumRotationKeys];
std::move(rotationKeys.begin(), rotationKeys.end(), newAiNodeAnim->mRotationKeys);
newAiNodeAnim->mNumScalingKeys = scalingKeys.size();
newAiNodeAnim->mScalingKeys = new aiVectorKey[newAiNodeAnim->mNumScalingKeys];
std::move(scalingKeys.begin(), scalingKeys.end(), newAiNodeAnim->mScalingKeys);
++channelIndex;
}
}
}
void USDImporterImplTinyusdz::meshes(
const tinyusdz::tydra::RenderScene &render_scene,

View File

@@ -65,6 +65,10 @@ public:
aiScene *pScene,
IOSystem *pIOHandler);
void animations(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene);
void meshes(
const tinyusdz::tydra::RenderScene &render_scene,
aiScene *pScene,

View File

@@ -100,27 +100,6 @@ std::string Assimp::tinyusdzNodeTypeFor(NodeType type) {
}
}
aiMatrix4x4 Assimp::tinyUsdzMat4ToAiMat4(const double matIn[4][4]) {
aiMatrix4x4 matOut;
matOut.a1 = matIn[0][0];
matOut.a2 = matIn[1][0];
matOut.a3 = matIn[2][0];
matOut.a4 = matIn[3][0];
matOut.b1 = matIn[0][1];
matOut.b2 = matIn[1][1];
matOut.b3 = matIn[2][1];
matOut.b4 = matIn[3][1];
matOut.c1 = matIn[0][2];
matOut.c2 = matIn[1][2];
matOut.c3 = matIn[2][2];
matOut.c4 = matIn[3][2];
matOut.d1 = matIn[0][3];
matOut.d2 = matIn[1][3];
matOut.d3 = matIn[2][3];
matOut.d4 = matIn[3][3];
return matOut;
}
aiVector3D Assimp::tinyUsdzScaleOrPosToAssimp(const std::array<float, 3> &scaleOrPosIn) {
return aiVector3D(scaleOrPosIn[0], scaleOrPosIn[1], scaleOrPosIn[2]);
}

View File

@@ -48,14 +48,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/types.h>
#include "tinyusdz.hh"
#include "tydra/render-data.hh"
#include <type_traits>
namespace Assimp {
std::string tinyusdzAnimChannelTypeFor(
tinyusdz::tydra::AnimationChannel::ChannelType animChannel);
std::string tinyusdzNodeTypeFor(tinyusdz::tydra::NodeType type);
aiMatrix4x4 tinyUsdzMat4ToAiMat4(const double matIn[4][4]);
template <typename T>
aiMatrix4x4 tinyUsdzMat4ToAiMat4(const T matIn[4][4]) {
static_assert(std::is_floating_point_v<T>, "Only floating-point types are allowed.");
aiMatrix4x4 matOut;
matOut.a1 = matIn[0][0];
matOut.a2 = matIn[1][0];
matOut.a3 = matIn[2][0];
matOut.a4 = matIn[3][0];
matOut.b1 = matIn[0][1];
matOut.b2 = matIn[1][1];
matOut.b3 = matIn[2][1];
matOut.b4 = matIn[3][1];
matOut.c1 = matIn[0][2];
matOut.c2 = matIn[1][2];
matOut.c3 = matIn[2][2];
matOut.c4 = matIn[3][2];
matOut.d1 = matIn[0][3];
matOut.d2 = matIn[1][3];
matOut.d3 = matIn[2][3];
matOut.d4 = matIn[3][3];
return matOut;
}
aiVector3D tinyUsdzScaleOrPosToAssimp(const std::array<float, 3> &scaleOrPosIn);
/**

View File

@@ -447,7 +447,7 @@ void ValidateDSProcess::Validate(const aiMesh *pMesh, const aiBone *pBone, float
if (pBone->mWeights[i].mVertexId >= pMesh->mNumVertices) {
ReportError("aiBone::mWeights[%i].mVertexId is out of range", i);
} else if (!pBone->mWeights[i].mWeight || pBone->mWeights[i].mWeight > 1.0f) {
ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value", i);
ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value %i. Value must be greater than zero and less than 1.", i, pBone->mWeights[i].mWeight);
}
afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight;
}

View File

@@ -2,3 +2,4 @@
[texturedcube.usda](texturedcube.usda) copied from tinyusdz/models (No attribution/license cited in that project)
[translated-cube.usda](translated-cube.usda) copied from tinyusdz/models (No attribution/license cited in that project)
[simple-skin-test.usda](simple-skin-test.usda) copied from tinyusdz/models (No attribution/license cited in that project)
[simple-skin-animation-test.usda](simple-skin-animation-test.usda) modified tinyusdz/models (No attribution/license cited in that project)

View File

@@ -0,0 +1,237 @@
#usda 1.0
(
defaultPrim = "root"
doc = "Blender v4.2.3 LTS"
endTimeCode = 40
metersPerUnit = 1
startTimeCode = 0
timeCodesPerSecond = 24
upAxis = "Z"
)
def Xform "root" (
customData = {
dictionary Blender = {
bool generated = 1
}
}
)
{
def SkelRoot "Armature_001"
{
custom string userProperties:blender:object_name = "Armature.001"
float3 xformOp:rotateXYZ = (-89.99999, 0, 0)
float3 xformOp:scale = (1, 1, 1)
double3 xformOp:translate = (0, -1.7017418146133423, 0)
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"]
def Xform "Grid"
{
custom string userProperties:blender:object_name = "Grid"
float3 xformOp:rotateXYZ = (89.99999, -0, 0)
float3 xformOp:scale = (1, 1, 1)
double3 xformOp:translate = (0, -7.438549687321938e-8, 1.7017418146133423)
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"]
def Mesh "Grid" (
active = true
prepend apiSchemas = ["SkelBindingAPI"]
)
{
float3[] extent = [(-1, -1, 0), (1, 1, 0)]
int[] faceVertexCounts = [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
int[] faceVertexIndices = [0, 1, 6, 5, 1, 2, 7, 6, 2, 3, 8, 7, 3, 4, 9, 8, 5, 6, 11, 10, 6, 7, 12, 11, 7, 8, 13, 12, 8, 9, 14, 13, 10, 11, 16, 15, 11, 12, 17, 16, 12, 13, 18, 17, 13, 14, 19, 18, 15, 16, 21, 20, 16, 17, 22, 21, 17, 18, 23, 22, 18, 19, 24, 23]
normal3f[] normals = [(0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)] (
interpolation = "faceVarying"
)
point3f[] points = [(-1, -1, 0), (-0.5, -1, 0), (0, -1, 0), (0.5, -1, 0), (1, -1, 0), (-1, -0.5, 0), (-0.5, -0.5, 0), (0, -0.5, 0), (0.5, -0.5, 0), (1, -0.5, 0), (-1, 0, 0), (-0.5, 0, 0), (0, 0, 0), (0.5, 0, 0), (1, 0, 0), (-1, 0.5, 0), (-0.5, 0.5, 0), (0, 0.5, 0), (0.5, 0.5, 0), (1, 0.5, 0), (-1, 1, 0), (-0.5, 1, 0), (0, 1, 0), (0.5, 1, 0), (1, 1, 0)]
bool[] primvars:sharp_face = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] (
interpolation = "uniform"
)
matrix4d primvars:skel:geomBindTransform = ( (1, 0, 0, 0), (0, 1.331580543606492e-7, 0.9999999999999911, 0), (0, -0.9999999999999911, 1.331580543606492e-7, 0), (0, -7.438549687321943e-8, 1.701741814613342, 1) )
int[] primvars:skel:jointIndices = [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1] (
elementSize = 2
interpolation = "vertex"
)
float[] primvars:skel:jointWeights = [0.43767902, 0.56232095, 0.605441, 0.39455906, 1, 0, 0.605441, 0.39455906, 0.43767902, 0.562321, 0.23470172, 0.7652983, 0.18096954, 0.81903046, 1, 0, 0.18096954, 0.81903046, 0.23470171, 0.7652983, 0.114853, 0.88514704, 0.06506716, 0.9349329, 1, 0, 0.06506715, 0.9349329, 0.11485299, 0.88514704, 0.059175473, 0.94082457, 0.009479873, 0.9905201, 1, 0, 0.009479865, 0.9905201, 0.059175465, 0.94082457, 0.031181445, 0.96881855, 1, 0, 1, 0, 1, 0, 0.031181442, 0.9688186] (
elementSize = 2
interpolation = "vertex"
)
texCoord2f[] primvars:st = [(0, 0), (0.25, 0), (0.25, 0.25), (0, 0.25), (0.25, 0), (0.5, 0), (0.5, 0.25), (0.25, 0.25), (0.5, 0), (0.75, 0), (0.75, 0.25), (0.5, 0.25), (0.75, 0), (1, 0), (1, 0.25), (0.75, 0.25), (0, 0.25), (0.25, 0.25), (0.25, 0.5), (0, 0.5), (0.25, 0.25), (0.5, 0.25), (0.5, 0.5), (0.25, 0.5), (0.5, 0.25), (0.75, 0.25), (0.75, 0.5), (0.5, 0.5), (0.75, 0.25), (1, 0.25), (1, 0.5), (0.75, 0.5), (0, 0.5), (0.25, 0.5), (0.25, 0.75), (0, 0.75), (0.25, 0.5), (0.5, 0.5), (0.5, 0.75), (0.25, 0.75), (0.5, 0.5), (0.75, 0.5), (0.75, 0.75), (0.5, 0.75), (0.75, 0.5), (1, 0.5), (1, 0.75), (0.75, 0.75), (0, 0.75), (0.25, 0.75), (0.25, 1), (0, 1), (0.25, 0.75), (0.5, 0.75), (0.5, 1), (0.25, 1), (0.5, 0.75), (0.75, 0.75), (0.75, 1), (0.5, 1), (0.75, 0.75), (1, 0.75), (1, 1), (0.75, 1)] (
interpolation = "faceVarying"
)
rel skel:skeleton = </root/Armature_001/Armature/Armature>
uniform token subdivisionScheme = "none"
custom string userProperties:blender:data_name = "Grid"
}
}
def Xform "Armature"
{
custom string userProperties:blender:object_name = "Armature"
float3 xformOp:rotateXYZ.timeSamples = {
0: (0, -0, 0),
}
float3 xformOp:scale.timeSamples = {
0: (1, 1, 1),
}
double3 xformOp:translate.timeSamples = {
0: (0, 0, 0),
}
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"]
def Skeleton "Armature" (
prepend apiSchemas = ["SkelBindingAPI"]
)
{
uniform matrix4d[] bindTransforms = [( (1, 0, 0, 0), (0, 0, 1, 0), (0, -1, 0, 0), (0, 0, 0, 1) ), ( (1, 0, 0, 0), (0, 0, 1, 0), (0, -1, 0, 0), (0, 0, 1, 1) )]
uniform token[] joints = ["Bone", "Bone/Bone_001"]
uniform matrix4d[] restTransforms = [( (1, 0, 0, 0), (0, 0, 1, 0), (0, -1, 0, 0), (0, 0, 0, 1) ), ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1, 0, 1) )]
rel skel:animationSource = </root/Armature_001/Armature/Armature/Anim>
def SkelAnimation "Anim"
{
uniform token[] joints = ["Bone", "Bone/Bone_001"]
quatf[] rotations.timeSamples = {
0: [(0.70710677, 0.70710677, 0, 0), (1, 0, 0, 0)],
1: [(0.70710677, 0.70710677, 0, 0), (0.9996082, 0, 0, 0.027989032)],
2: [(0.70710677, 0.70710677, 0, 0), (0.99463546, 0, 0, 0.10344209)],
3: [(0.70710677, 0.70710677, 0, 0), (0.9774578, 0, 0, 0.21113087)],
4: [(0.70710677, 0.70710677, 0, 0), (0.9432686, 0, 0, 0.3320306)],
5: [(0.70710677, 0.70710677, 0, 0), (0.89442724, 0, 0, 0.4472135)],
6: [(0.70710677, 0.70710677, 0, 0), (0.83920974, 0, 0, 0.5438079)],
7: [(0.70710677, 0.70710677, 0, 0), (0.7869733, 0, 0, 0.61698705)],
8: [(0.70710677, 0.70710677, 0, 0), (0.7447736, 0, 0, 0.6673172)],
9: [(0.70710677, 0.70710677, 0, 0), (0.7170745, 0, 0, 0.6969965)],
10: [(0.70710677, 0.70710677, 0, 0), (0.70710677, 0, 0, 0.70710677)],
11: [(0.70710677, 0.70710677, 0, 0), (0.7122517, 0, 0, 0.70192415)],
12: [(0.70710677, 0.70710677, 0, 0), (0.7271744, 0, 0, 0.68645275)],
13: [(0.70710677, 0.70710677, 0, 0), (0.75127214, 0, 0, 0.6599926)],
14: [(0.70710677, 0.70710677, 0, 0), (0.7839187, 0, 0, 0.62086356)],
15: [(0.70710677, 0.70710677, 0, 0), (0.82404196, 0, 0, 0.5665288)],
16: [(0.70710677, 0.70710677, 0, 0), (0.8695245, 0, 0, 0.49388987)],
17: [(0.70710677, 0.70710677, 0, 0), (0.91649354, 0, 0, 0.4000495)],
18: [(0.70710677, 0.70710677, 0, 0), (0.9588755, 0, 0, 0.28382713)],
19: [(0.70710677, 0.70710677, 0, 0), (0.9890088, 0, 0, 0.14785683)],
20: [(0.70710677, 0.70710677, 0, 0), (1, 0, 0, 0)],
21: [(0.70710677, 0.70710677, 0, 0), (0.9890088, 0, 0, -0.14785682)],
22: [(0.70710677, 0.70710677, 0, 0), (0.9588755, 0, 0, -0.28382716)],
23: [(0.70710677, 0.70710677, 0, 0), (0.91649354, 0, 0, -0.40004945)],
24: [(0.70710677, 0.70710677, 0, 0), (0.86952454, 0, 0, -0.49388978)],
25: [(0.70710677, 0.70710677, 0, 0), (0.82404196, 0, 0, -0.5665288)],
26: [(0.70710677, 0.70710677, 0, 0), (0.7839186, 0, 0, -0.6208636)],
27: [(0.70710677, 0.70710677, 0, 0), (0.7512721, 0, 0, -0.65999264)],
28: [(0.70710677, 0.70710677, 0, 0), (0.7271744, 0, 0, -0.68645275)],
29: [(0.70710677, 0.70710677, 0, 0), (0.7122517, 0, 0, -0.70192415)],
30: [(0.70710677, 0.70710677, 0, 0), (0.70710677, 0, 0, -0.70710677)],
31: [(0.70710677, 0.70710677, 0, 0), (0.7170746, 0, 0, -0.69699645)],
32: [(0.70710677, 0.70710677, 0, 0), (0.7447736, 0, 0, -0.6673172)],
33: [(0.70710677, 0.70710677, 0, 0), (0.7869733, 0, 0, -0.61698705)],
34: [(0.70710677, 0.70710677, 0, 0), (0.83920974, 0, 0, -0.5438079)],
35: [(0.70710677, 0.70710677, 0, 0), (0.8944272, 0, 0, -0.44721356)],
36: [(0.70710677, 0.70710677, 0, 0), (0.9432686, 0, 0, -0.3320306)],
37: [(0.70710677, 0.70710677, 0, 0), (0.97745776, 0, 0, -0.21113095)],
38: [(0.70710677, 0.70710677, 0, 0), (0.99463546, 0, 0, -0.10344207)],
39: [(0.70710677, 0.70710677, 0, 0), (0.9996082, 0, 0, -0.027989028)],
40: [(0.70710677, 0.70710677, 0, 0), (1, 0, 0, 0)],
}
half3[] scales.timeSamples = {
0: [(1, 1, 1), (1, 1, 1)],
1: [(1, 1, 1), (1, 1, 1)],
2: [(1, 1, 1), (1, 1, 1)],
3: [(1, 1, 1), (1, 1, 1)],
4: [(1, 1, 1), (1, 1, 1)],
5: [(1, 1, 1), (1, 1, 1)],
6: [(1, 1, 1), (1, 1, 1)],
7: [(1, 1, 1), (1, 1, 1)],
8: [(1, 1, 1), (1, 1, 1)],
9: [(1, 1, 1), (1, 1, 1)],
10: [(1, 1, 1), (1, 1, 1)],
11: [(1, 1, 1), (1, 1, 1)],
12: [(1, 1, 1), (1, 1, 1)],
13: [(1, 1, 1), (1, 1, 1)],
14: [(1, 1, 1), (1, 1, 1)],
15: [(1, 1, 1), (1, 1, 1)],
16: [(1, 1, 1), (1, 1, 1)],
17: [(1, 1, 1), (1, 1, 1)],
18: [(1, 1, 1), (1, 1, 1)],
19: [(1, 1, 1), (1, 1, 1)],
20: [(1, 1, 1), (1, 1, 1)],
21: [(1, 1, 1), (1, 1, 1)],
22: [(1, 1, 1), (1, 1, 1)],
23: [(1, 1, 1), (1, 1, 1)],
24: [(1, 1, 1), (1, 1, 1)],
25: [(1, 1, 1), (1, 1, 1)],
26: [(1, 1, 1), (1, 1, 1)],
27: [(1, 1, 1), (1, 1, 1)],
28: [(1, 1, 1), (1, 1, 1)],
29: [(1, 1, 1), (1, 1, 1)],
30: [(1, 1, 1), (1, 1, 1)],
31: [(1, 1, 1), (1, 1, 1)],
32: [(1, 1, 1), (1, 1, 1)],
33: [(1, 1, 1), (1, 1, 1)],
34: [(1, 1, 1), (1, 1, 1)],
35: [(1, 1, 1), (1, 1, 1)],
36: [(1, 1, 1), (1, 1, 1)],
37: [(1, 1, 1), (1, 1, 1)],
38: [(1, 1, 1), (1, 1, 1)],
39: [(1, 1, 1), (1, 1, 1)],
40: [(1, 1, 1), (1, 1, 1)],
}
float3[] translations.timeSamples = {
0: [(0, 0, 0), (0, 1, 0)],
1: [(0, 0, 0), (0, 1, 0)],
2: [(0, 0, 0), (0, 1, 0)],
3: [(0, 0, 0), (0, 1, 0)],
4: [(0, 0, 0), (0, 1, 0)],
5: [(0, 0, 0), (0, 1, 0)],
6: [(0, 0, 0), (0, 1, 0)],
7: [(0, 0, 0), (0, 1, 0)],
8: [(0, 0, 0), (0, 1, 0)],
9: [(0, 0, 0), (0, 1, 0)],
10: [(0, 0, 0), (0, 1, 0)],
11: [(0, 0, 0), (0, 1, 0)],
12: [(0, 0, 0), (0, 1, 0)],
13: [(0, 0, 0), (0, 1, 0)],
14: [(0, 0, 0), (0, 1, 0)],
15: [(0, 0, 0), (0, 1, 0)],
16: [(0, 0, 0), (0, 1, 0)],
17: [(0, 0, 0), (0, 1, 0)],
18: [(0, 0, 0), (0, 1, 0)],
19: [(0, 0, 0), (0, 1, 0)],
20: [(0, 0, 0), (0, 1, 0)],
21: [(0, 0, 0), (0, 1, 0)],
22: [(0, 0, 0), (0, 1, 0)],
23: [(0, 0, 0), (0, 1, 0)],
24: [(0, 0, 0), (0, 1, 0)],
25: [(0, 0, 0), (0, 1, 0)],
26: [(0, 0, 0), (0, 1, 0)],
27: [(0, 0, 0), (0, 1, 0)],
28: [(0, 0, 0), (0, 1, 0)],
29: [(0, 0, 0), (0, 1, 0)],
30: [(0, 0, 0), (0, 1, 0)],
31: [(0, 0, 0), (0, 1, 0)],
32: [(0, 0, 0), (0, 1, 0)],
33: [(0, 0, 0), (0, 1, 0)],
34: [(0, 0, 0), (0, 1, 0)],
35: [(0, 0, 0), (0, 1, 0)],
36: [(0, 0, 0), (0, 1, 0)],
37: [(0, 0, 0), (0, 1, 0)],
38: [(0, 0, 0), (0, 1, 0)],
39: [(0, 0, 0), (0, 1, 0)],
40: [(0, 0, 0), (0, 1, 0)],
}
}
}
}
}
def DomeLight "env_light"
{
float inputs:intensity = 1
asset inputs:texture:file = @.\textures\color_121212.hdr@
float3 xformOp:rotateXYZ = (90, 1.2722219e-14, 90)
uniform token[] xformOpOrder = ["xformOp:rotateXYZ"]
}
}

View File

@@ -77,3 +77,14 @@ TEST_F(utUSDImport, skinnedMeshTest) {
EXPECT_NE(nullptr, scene->mRootNode->FindNode("Bone"));
EXPECT_NE(nullptr, scene->mRootNode->FindNode("Bone/Bone_001"));
}
TEST_F(utUSDImport, singleAnimationTest) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/../models-nonbsd/USD/usda/simple-skin-animation-test.usda", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
EXPECT_TRUE(scene->HasAnimations());
EXPECT_EQ(2, scene->mAnimations[0]->mNumChannels); // 2 bones. 1 channel for each bone
}
// Note: Add multi-animation test once supported by USD
// See https://github.com/lighttransport/tinyusdz/issues/122 for details.