Guest User

Untitled

a guest
Jul 7th, 2024
22
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.92 KB | None | 0 0
  1. ozz::unique_ptr<ozz::animation::offline::RawAnimation> GLTFImport::RetargetAnimation(ozz::animation::offline::RawAnimation* anim, const std::vector<ozz::math::Transform>& sourceRestPose, const std::vector<ozz::math::Transform>& targetRestPose, const Animation::OzzSkeleton* skele)
  2. {
  3.     using namespace ozz::math;
  4.  
  5.     const auto NormalizeQuat = [](const Quaternion& q) {
  6.         float magnitude = std::sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
  7.         if (magnitude > 0.0f) {
  8.             float invMagnitude = 1.0f / magnitude;
  9.             return Quaternion(q.x * invMagnitude, q.y * invMagnitude, q.z * invMagnitude, q.w * invMagnitude);
  10.         }
  11.         return q;
  12.     };
  13.  
  14.     const auto InvertQuat = [&NormalizeQuat](const Quaternion& q) {
  15.         Quaternion normalized = NormalizeQuat(q);
  16.         return Quaternion(-normalized.x, -normalized.y, -normalized.z, normalized.w);
  17.     };
  18.  
  19.     const auto RotateVector = [&InvertQuat](const Quaternion& q, const Float3& v) -> Float3 {
  20.         using namespace ozz::math;
  21.         Quaternion qv = { v.x, v.y, v.z, 0.0f };
  22.         Quaternion conjugateQ = InvertQuat(q);
  23.         Quaternion result = conjugateQ * (q * qv);
  24.         return { result.x, result.y, result.z };
  25.     };
  26.  
  27.     const auto GetGlobalTransform = [&RotateVector, &NormalizeQuat](const Transform& localTransform, const Transform& parentGlobalTransform) {
  28.         Transform result;
  29.         result.translation = parentGlobalTransform.translation + RotateVector(parentGlobalTransform.rotation, localTransform.translation);
  30.         result.rotation = NormalizeQuat(parentGlobalTransform.rotation * localTransform.rotation);
  31.         result.scale = { 1.0f, 1.0f, 1.0f };
  32.         return result;
  33.     };
  34.  
  35.     const auto GetLocalTransform = [&RotateVector, &InvertQuat, &NormalizeQuat](const Transform& globalTransform, const Transform& parentGlobalTransform) {
  36.         Quaternion inverseParentRotation = InvertQuat(parentGlobalTransform.rotation);
  37.         Transform result;
  38.         result.translation = RotateVector(inverseParentRotation, globalTransform.translation - parentGlobalTransform.translation);
  39.         result.rotation = NormalizeQuat(inverseParentRotation * globalTransform.rotation);
  40.         result.scale = { 1.0f, 1.0f, 1.0f };
  41.         return result;
  42.     };
  43.  
  44.     const auto L2G = [&GetGlobalTransform](std::span<const Transform> locals, std::span<Transform> globals, std::span<const int16_t> parents, size_t root) {
  45.         std::stack<size_t> stack;
  46.         stack.push(root);
  47.  
  48.         while (!stack.empty()) {
  49.             size_t current = stack.top();
  50.             stack.pop();
  51.  
  52.             if (parents[current] == -1) {
  53.                 globals[current] = locals[current];
  54.             } else {
  55.                 globals[current] = GetGlobalTransform(locals[current], globals[parents[current]]);
  56.             }
  57.  
  58.             for (size_t i = locals.size(); i-- > 0;) {
  59.                 if (parents[i] == current) {
  60.                     stack.push(i);
  61.                 }
  62.             }
  63.         }
  64.     };
  65.  
  66.     const auto InitL2G = [&L2G](std::span<const Transform> locals, std::span<Transform> globals, std::span<const int16_t> parents) {
  67.         for (size_t i = 0; i < parents.size(); i++) {
  68.             if (parents[i] == -1) {
  69.                 L2G(locals, globals, parents, i);
  70.             }
  71.         }
  72.     };
  73.  
  74.     const auto G2L = [&GetLocalTransform](std::span<Transform> locals, std::span<const Transform> globals, std::span<const int16_t> parents, size_t root) {
  75.         std::stack<size_t> stack;
  76.         stack.push(root);
  77.  
  78.         while (!stack.empty()) {
  79.             size_t current = stack.top();
  80.             stack.pop();
  81.  
  82.             if (parents[current] == -1) {
  83.                 locals[current] = globals[current];
  84.             } else {
  85.                 locals[current] = GetLocalTransform(globals[current], globals[parents[current]]);
  86.             }
  87.  
  88.             for (size_t i = locals.size(); i-- > 0;) {
  89.                 if (parents[i] == current) {
  90.                     stack.push(i);
  91.                 }
  92.             }
  93.         }
  94.     };
  95.  
  96.     const auto InitG2L = [&G2L](std::span<Transform> locals, std::span<const Transform> globals, std::span<const int16_t> parents) {
  97.         for (size_t i = 0; i < parents.size(); i++) {
  98.             if (parents[i] == -1) {
  99.                 G2L(locals, globals, parents, i);
  100.             }
  101.         }
  102.     };
  103.  
  104.     const auto RetargetTransform = [&InvertQuat, &NormalizeQuat](const Transform& sourceBase, const Transform& sourceDest, const Transform& targetBase){
  105.         Float3 positionDiff = sourceDest.translation - sourceBase.translation;
  106.         Quaternion rotationDiff = NormalizeQuat(NormalizeQuat(sourceDest.rotation) * InvertQuat(sourceBase.rotation));
  107.  
  108.         Transform result;
  109.         result.translation = targetBase.translation + positionDiff;
  110.         result.rotation = NormalizeQuat(rotationDiff * NormalizeQuat(targetBase.rotation));
  111.         result.scale = { 1.0f, 1.0f, 1.0f };
  112.         return result;
  113.     };
  114.  
  115.     auto parents = skele->data->joint_parents();
  116.  
  117.     if (sourceRestPose.size() != targetRestPose.size() || sourceRestPose.size() != anim->num_tracks())
  118.         return nullptr;
  119.    
  120.     std::vector<Transform> sourceGlobals(anim->num_tracks(), Transform::identity());
  121.     InitL2G(sourceRestPose, sourceGlobals, parents);
  122.  
  123.     std::vector<Transform> targetGlobals(anim->num_tracks(), Transform::identity());
  124.     InitL2G(targetRestPose, targetGlobals, parents);
  125.  
  126.     std::vector<Transform> currentLocals(anim->num_tracks(), Transform::identity());
  127.     std::vector<Transform> currentGlobals(anim->num_tracks(), Transform::identity());
  128.    
  129.     auto result = ozz::make_unique<ozz::animation::offline::RawAnimation>();
  130.     result->tracks.resize(anim->num_tracks());
  131.  
  132.     auto localSpan = ozz::make_span(currentLocals);
  133.  
  134.     const auto DoSample = [&](float time) {
  135.         ozz::animation::offline::SampleAnimation(*anim, time, localSpan);
  136.         InitL2G(currentLocals, currentGlobals, parents);
  137.         for (size_t i = 0; i < currentGlobals.size(); i++) {
  138.             currentGlobals[i] = RetargetTransform(sourceGlobals[i], currentGlobals[i], targetGlobals[i]);
  139.         }
  140.         InitG2L(currentLocals, currentGlobals, parents);
  141.         for (size_t i = 0; i < currentGlobals.size(); i++) {
  142.             auto& rKey = result->tracks[i].rotations.emplace_back();
  143.             auto& tKey = result->tracks[i].translations.emplace_back();
  144.             rKey.time = time;
  145.             tKey.time = time;
  146.             rKey.value = currentLocals[i].rotation;
  147.             tKey.value = currentLocals[i].translation;
  148.         }
  149.     };
  150.  
  151.     for (float i = 0; i < anim->duration; i += 0.0333333333f) {
  152.         DoSample(i);
  153.     }
  154.     DoSample(anim->duration);
  155.  
  156.     return result;
  157. }
Advertisement
Add Comment
Please, Sign In to add comment