Skip to content

Commit

Permalink
[Tydra] AnimationChannel refactoring(W.I.P.)
Browse files Browse the repository at this point in the history
  • Loading branch information
syoyo committed Apr 19, 2024
1 parent 1101bd8 commit f2d70ed
Show file tree
Hide file tree
Showing 3 changed files with 301 additions and 88 deletions.
103 changes: 70 additions & 33 deletions src/tydra/render-data.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5125,15 +5125,6 @@ bool RenderSceneConverter::ConvertSkelAnimation(const RenderSceneConverterEnv &e
// An animation source is only valid if its translation, rotation, and scale components are all authored, storing arrays size to the same size as the authored joints array.
// """

// NOTE: fortunately USD SkelAnimation uses quaternions for rotations
// anim_out->channels.rotations

(void)anim_out;

AnimationChannel channel_txs; channel_txs.type = AnimationChannel::ChannelType::Translation;
AnimationChannel channel_rots; channel_rots.type = AnimationChannel::ChannelType::Rotation;
AnimationChannel channel_scales; channel_scales.type = AnimationChannel::ChannelType::Scale;

if (!skelAnim.joints.authored()) {
PUSH_ERROR_AND_RETURN(fmt::format("`joints` is not authored for SkelAnimation Prim : {}", abs_path));
}
Expand All @@ -5153,6 +5144,18 @@ bool RenderSceneConverter::ConvertSkelAnimation(const RenderSceneConverterEnv &e
skelAnim.scales.authored() ? "yes" : "no"));
}

//
// Reorder values[channels][timeCode][jointId] into values[jointId][channels][timeCode]
//

std::map<std::string, std::map<AnimationChannel::ChannelType, AnimationChannel>> channelMap;
StringAndIdMap jointIdMap;

for (const auto &joint : joints) {
uint64_t id = jointIdMap.size();
jointIdMap.add(joint.str(), id);
}


Animatable<std::vector<value::float3>> translations;
if (!skelAnim.translations.get_value(&translations)) {
Expand All @@ -5169,6 +5172,9 @@ bool RenderSceneConverter::ConvertSkelAnimation(const RenderSceneConverterEnv &e
PUSH_ERROR_AND_RETURN(fmt::format("Failed to get `scales` attribute of SkelAnimation. Maybe ValueBlock or connection? : {}", abs_path));
}

//
// NOTE: both timeSamples and default value are authored, timeSamples wins.
//
bool is_translations_timesamples = false;
bool is_rotations_timesamples = false;
bool is_scales_timesamples = false;
Expand All @@ -5181,16 +5187,25 @@ bool RenderSceneConverter::ConvertSkelAnimation(const RenderSceneConverterEnv &e
}

for (const auto &sample : ts_txs.get_samples()) {
AnimationSample<std::vector<value::float3>> dst;
if (!sample.blocked) {
// length check
if (sample.value.size() != joints.size()) {
PUSH_ERROR_AND_RETURN(fmt::format("Array length mismatch in SkelAnimation. timeCode {} translations.size {} must be equal to joints.size {} : {}", sample.t, sample.value.size(), joints.size(), abs_path));
}

dst.t = float(sample.t);
dst.value = sample.value;
channel_txs.translations.samples.push_back(dst);
for (size_t j = 0; j < sample.value.size(); j++) {
AnimationSample<value::float3> s;
s.t = float(sample.t);
s.value = sample.value[j];

std::string jointName = jointIdMap.at(j);
auto &it = channelMap.at(jointName).at(AnimationChannel::ChannelType::Translation);
if (it.translations.samples.empty()) {
it.type = AnimationChannel::ChannelType::Translation;
}
it.translations.samples.push_back(s);
}

}
}
is_translations_timesamples = true;
Expand All @@ -5214,6 +5229,7 @@ bool RenderSceneConverter::ConvertSkelAnimation(const RenderSceneConverterEnv &e
}
}

// value at 'default' time.
std::vector<value::float3> translation;
std::vector<value::float4> rotation;
std::vector<value::float3> scale;
Expand Down Expand Up @@ -5268,33 +5284,54 @@ bool RenderSceneConverter::ConvertSkelAnimation(const RenderSceneConverterEnv &e
is_scales_timesamples = false;
}

// Use USD TimeCode::Default for static sample.
if (is_translations_timesamples) {
} else {
AnimationSample<std::vector<value::float3>> sample;
sample.t = std::numeric_limits<float>::quiet_NaN();
sample.value = translation;
channel_txs.translations.samples.push_back(sample);
if (!is_translations_timesamples) {
// Create a channel value with single-entry
// Use USD TimeCode::Default for static sample.
for (const auto &joint : joints) {
channelMap[joint.str()][AnimationChannel::ChannelType::Translation].type = AnimationChannel::ChannelType::Translation;

AnimationSample<value::float3> s;
s.t = std::numeric_limits<float>::quiet_NaN();
uint64_t joint_id = jointIdMap.at(joint.str());
s.value = translation[joint_id];
channelMap[joint.str()][AnimationChannel::ChannelType::Translation].translations.samples.clear();
channelMap[joint.str()][AnimationChannel::ChannelType::Translation].translations.samples.push_back(s);
}
}

if (is_rotations_timesamples) {
} else {
AnimationSample<std::vector<value::float4>> sample;
sample.t = std::numeric_limits<float>::quiet_NaN();
sample.value = rotation;
channel_rots.rotations.samples.push_back(sample);
if (!is_rotations_timesamples) {
for (const auto &joint : joints) {
channelMap[joint.str()][AnimationChannel::ChannelType::Rotation].type = AnimationChannel::ChannelType::Rotation;

AnimationSample<value::float4> s;
s.t = std::numeric_limits<float>::quiet_NaN();
uint64_t joint_id = jointIdMap.at(joint.str());
s.value = rotation[joint_id];
channelMap[joint.str()][AnimationChannel::ChannelType::Rotation].rotations.samples.clear();
channelMap[joint.str()][AnimationChannel::ChannelType::Rotation].rotations.samples.push_back(s);
}
}

if (is_scales_timesamples) {
} else {
AnimationSample<std::vector<value::float3>> sample;
sample.t = std::numeric_limits<float>::quiet_NaN();
sample.value = scale;
channel_scales.scales.samples.push_back(sample);
if (!is_scales_timesamples) {
for (const auto &joint : joints) {
channelMap[joint.str()][AnimationChannel::ChannelType::Scale].type = AnimationChannel::ChannelType::Scale;

AnimationSample<value::float3> s;
s.t = std::numeric_limits<float>::quiet_NaN();
uint64_t joint_id = jointIdMap.at(joint.str());
s.value = scale[joint_id];
channelMap[joint.str()][AnimationChannel::ChannelType::Scale].scales.samples.clear();
channelMap[joint.str()][AnimationChannel::ChannelType::Scale].scales.samples.push_back(s);
}
}

PUSH_ERROR_AND_RETURN("TODO");
anim_out->abs_path = abs_path.full_path_name();
anim_out->prim_name = skelAnim.name;
anim_out->display_name = skelAnim.metas().displayName.value_or("");

anim_out->channels_map = std::move(channelMap);

return true;
}

bool RenderSceneConverter::BuildNodeHierarchyImpl(
Expand Down
19 changes: 12 additions & 7 deletions src/tydra/render-data.hh
Original file line number Diff line number Diff line change
Expand Up @@ -665,19 +665,24 @@ struct AnimationSampler {
struct AnimationChannel {
enum class ChannelType { Transform, Translation, Rotation, Scale, Weight };

AnimationChannel() = default;

AnimationChannel(ChannelType ty) : type(ty) {
}

ChannelType type;
// The following AnimationSampler is filled depending on ChannelType.
// Example: Rotation => Only `rotations` are filled.

// Matrix precision is reduced to float-precision
// NOTE: transform is not supported in glTF(you need to decompose transform
// matrix into TRS)
AnimationSampler<std::vector<mat4>> transforms;
AnimationSampler<mat4> transforms;

AnimationSampler<std::vector<vec3>> translations;
AnimationSampler<std::vector<quat>> rotations; // Rotation is represented as quaternions
AnimationSampler<std::vector<vec3>> scales; // half-types are upcasted to float precision
AnimationSampler<std::vector<float>> weights;
AnimationSampler<vec3> translations;
AnimationSampler<quat> rotations; // Rotation is represented as quaternions
AnimationSampler<vec3> scales; // half-types are upcasted to float precision
AnimationSampler<float> weights;

//std::string joint_name; // joint name(UsdSkel::joints)
//int64_t joint_id{-1}; // joint index in SkelHierarchy
Expand All @@ -689,8 +694,8 @@ struct Animation {
std::string abs_path; // Target USD Prim path
std::string display_name; // `displayName` prim meta

// key = joint, value = channels(Usually 3(trans, rots and scales))
std::map<std::string, std::vector<AnimationChannel>> channels_map;
// key = joint, value = (key: channel_type, value: channel_value)
std::map<std::string, std::map<AnimationChannel::ChannelType, AnimationChannel>> channels_map;
};

struct Node {
Expand Down
Loading

0 comments on commit f2d70ed

Please sign in to comment.