------------------------------------------------------------------------------------------------ Extract animation channel
| 553 | // ------------------------------------------------------------------------------------------------ |
| 554 | // Extract animation channel |
| 555 | void AnimResolver::ExtractAnimChannel(aiNodeAnim **out, unsigned int /*= 0*/) { |
| 556 | *out = nullptr; |
| 557 | |
| 558 | //FIXME: crashes if more than one component is animated at different timings, to be resolved. |
| 559 | |
| 560 | // If we have no envelopes, return nullptr |
| 561 | if (envelopes.empty()) { |
| 562 | return; |
| 563 | } |
| 564 | |
| 565 | // We won't spawn an animation channel if we don't have at least one envelope with more than one keyframe defined. |
| 566 | const bool trans = ((trans_x && trans_x->keys.size() > 1) || (trans_y && trans_y->keys.size() > 1) || (trans_z && trans_z->keys.size() > 1)); |
| 567 | const bool rotat = ((rotat_x && rotat_x->keys.size() > 1) || (rotat_y && rotat_y->keys.size() > 1) || (rotat_z && rotat_z->keys.size() > 1)); |
| 568 | const bool scale = ((scale_x && scale_x->keys.size() > 1) || (scale_y && scale_y->keys.size() > 1) || (scale_z && scale_z->keys.size() > 1)); |
| 569 | if (!trans && !rotat && !scale) |
| 570 | return; |
| 571 | |
| 572 | // Allocate the output animation |
| 573 | aiNodeAnim *anim = *out = new aiNodeAnim(); |
| 574 | |
| 575 | // Setup default animation setup if necessary |
| 576 | if (need_to_setup) { |
| 577 | UpdateAnimRangeSetup(); |
| 578 | need_to_setup = false; |
| 579 | } |
| 580 | |
| 581 | // copy translation keys |
| 582 | if (trans) { |
| 583 | std::vector<aiVectorKey> keys; |
| 584 | GetKeys(keys, trans_x, trans_y, trans_z, flags); |
| 585 | |
| 586 | anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys = static_cast<unsigned int>(keys.size())]; |
| 587 | std::copy(keys.begin(), keys.end(), anim->mPositionKeys); |
| 588 | } |
| 589 | |
| 590 | // copy rotation keys |
| 591 | if (rotat) { |
| 592 | std::vector<aiVectorKey> keys; |
| 593 | GetKeys(keys, rotat_x, rotat_y, rotat_z, flags); |
| 594 | |
| 595 | anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys = static_cast<unsigned int>(keys.size())]; |
| 596 | |
| 597 | // convert heading, pitch, bank to quaternion |
| 598 | // mValue.x=Heading=Rot(Y), mValue.y=Pitch=Rot(X), mValue.z=Bank=Rot(Z) |
| 599 | // Lightwave's rotation order is ZXY |
| 600 | aiVector3D X(1.0, 0.0, 0.0); |
| 601 | aiVector3D Y(0.0, 1.0, 0.0); |
| 602 | aiVector3D Z(0.0, 0.0, 1.0); |
| 603 | for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) { |
| 604 | aiQuatKey &qk = anim->mRotationKeys[i]; |
| 605 | qk.mTime = keys[i].mTime; |
| 606 | qk.mValue = aiQuaternion(Y, keys[i].mValue.x) * aiQuaternion(X, keys[i].mValue.y) * aiQuaternion(Z, keys[i].mValue.z); |
| 607 | } |
| 608 | } |
| 609 | |
| 610 | // copy scaling keys |
| 611 | if (scale) { |
| 612 | std::vector<aiVectorKey> keys; |
no test coverage detected