summaryrefslogtreecommitdiff
path: root/libs/assimp/code/Common/TargetAnimation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/assimp/code/Common/TargetAnimation.cpp')
-rw-r--r--libs/assimp/code/Common/TargetAnimation.cpp226
1 files changed, 226 insertions, 0 deletions
diff --git a/libs/assimp/code/Common/TargetAnimation.cpp b/libs/assimp/code/Common/TargetAnimation.cpp
new file mode 100644
index 0000000..5f6d9ba
--- /dev/null
+++ b/libs/assimp/code/Common/TargetAnimation.cpp
@@ -0,0 +1,226 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2022, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#include "TargetAnimation.h"
+#include <assimp/ai_assert.h>
+#include <algorithm>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+KeyIterator::KeyIterator(const std::vector<aiVectorKey> *_objPos,
+ const std::vector<aiVectorKey> *_targetObjPos,
+ const aiVector3D *defaultObjectPos /*= nullptr*/,
+ const aiVector3D *defaultTargetPos /*= nullptr*/) :
+ reachedEnd(false),
+ curTime(-1.),
+ objPos(_objPos),
+ targetObjPos(_targetObjPos),
+ nextObjPos(0),
+ nextTargetObjPos(0) {
+ // Generate default transformation tracks if necessary
+ if (!objPos || objPos->empty()) {
+ defaultObjPos.resize(1);
+ defaultObjPos.front().mTime = 10e10;
+
+ if (defaultObjectPos)
+ defaultObjPos.front().mValue = *defaultObjectPos;
+
+ objPos = &defaultObjPos;
+ }
+ if (!targetObjPos || targetObjPos->empty()) {
+ defaultTargetObjPos.resize(1);
+ defaultTargetObjPos.front().mTime = 10e10;
+
+ if (defaultTargetPos)
+ defaultTargetObjPos.front().mValue = *defaultTargetPos;
+
+ targetObjPos = &defaultTargetObjPos;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+template <class T>
+inline T Interpolate(const T &one, const T &two, ai_real val) {
+ return one + (two - one) * val;
+}
+
+// ------------------------------------------------------------------------------------------------
+void KeyIterator::operator++() {
+ // If we are already at the end of all keyframes, return
+ if (reachedEnd) {
+ return;
+ }
+
+ // Now search in all arrays for the time value closest
+ // to our current position on the time line
+ double d0, d1;
+
+ d0 = objPos->at(std::min(nextObjPos, static_cast<unsigned int>(objPos->size() - 1))).mTime;
+ d1 = targetObjPos->at(std::min(nextTargetObjPos, static_cast<unsigned int>(targetObjPos->size() - 1))).mTime;
+
+ // Easiest case - all are identical. In this
+ // case we don't need to interpolate so we can
+ // return earlier
+ if (d0 == d1) {
+ curTime = d0;
+ curPosition = objPos->at(nextObjPos).mValue;
+ curTargetPosition = targetObjPos->at(nextTargetObjPos).mValue;
+
+ // increment counters
+ if (objPos->size() != nextObjPos - 1)
+ ++nextObjPos;
+
+ if (targetObjPos->size() != nextTargetObjPos - 1)
+ ++nextTargetObjPos;
+ }
+
+ // An object position key is closest to us
+ else if (d0 < d1) {
+ curTime = d0;
+
+ // interpolate the other
+ if (1 == targetObjPos->size() || !nextTargetObjPos) {
+ curTargetPosition = targetObjPos->at(0).mValue;
+ } else {
+ const aiVectorKey &last = targetObjPos->at(nextTargetObjPos);
+ const aiVectorKey &first = targetObjPos->at(nextTargetObjPos - 1);
+
+ curTargetPosition = Interpolate(first.mValue, last.mValue, (ai_real)((curTime - first.mTime) / (last.mTime - first.mTime)));
+ }
+
+ if (objPos->size() != nextObjPos - 1)
+ ++nextObjPos;
+ }
+ // A target position key is closest to us
+ else {
+ curTime = d1;
+
+ // interpolate the other
+ if (1 == objPos->size() || !nextObjPos) {
+ curPosition = objPos->at(0).mValue;
+ } else {
+ const aiVectorKey &last = objPos->at(nextObjPos);
+ const aiVectorKey &first = objPos->at(nextObjPos - 1);
+
+ curPosition = Interpolate(first.mValue, last.mValue, (ai_real)((curTime - first.mTime) / (last.mTime - first.mTime)));
+ }
+
+ if (targetObjPos->size() != nextTargetObjPos - 1)
+ ++nextTargetObjPos;
+ }
+
+ if (nextObjPos >= objPos->size() - 1 &&
+ nextTargetObjPos >= targetObjPos->size() - 1) {
+ // We reached the very last keyframe
+ reachedEnd = true;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void TargetAnimationHelper::SetTargetAnimationChannel(
+ const std::vector<aiVectorKey> *_targetPositions) {
+ ai_assert(nullptr != _targetPositions);
+
+ targetPositions = _targetPositions;
+}
+
+// ------------------------------------------------------------------------------------------------
+void TargetAnimationHelper::SetMainAnimationChannel(
+ const std::vector<aiVectorKey> *_objectPositions) {
+ ai_assert(nullptr != _objectPositions);
+
+ objectPositions = _objectPositions;
+}
+
+// ------------------------------------------------------------------------------------------------
+void TargetAnimationHelper::SetFixedMainAnimationChannel(
+ const aiVector3D &fixed) {
+ objectPositions = nullptr; // just to avoid confusion
+ fixedMain = fixed;
+}
+
+// ------------------------------------------------------------------------------------------------
+void TargetAnimationHelper::Process(std::vector<aiVectorKey> *distanceTrack) {
+ ai_assert(nullptr != targetPositions);
+ ai_assert(nullptr != distanceTrack);
+
+ // TODO: in most cases we won't need the extra array
+ std::vector<aiVectorKey> real;
+
+ std::vector<aiVectorKey> *fill = (distanceTrack == objectPositions ? &real : distanceTrack);
+ fill->reserve(std::max(objectPositions->size(), targetPositions->size()));
+
+ // Iterate through all object keys and interpolate their values if necessary.
+ // Then get the corresponding target position, compute the difference
+ // vector between object and target position. Then compute a rotation matrix
+ // that rotates the base vector of the object coordinate system at that time
+ // to match the diff vector.
+
+ KeyIterator iter(objectPositions, targetPositions, &fixedMain);
+ for (; !iter.Finished(); ++iter) {
+ const aiVector3D &position = iter.GetCurPosition();
+ const aiVector3D &tposition = iter.GetCurTargetPosition();
+
+ // diff vector
+ aiVector3D diff = tposition - position;
+ ai_real f = diff.Length();
+
+ // output distance vector
+ if (f) {
+ fill->push_back(aiVectorKey());
+ aiVectorKey &v = fill->back();
+ v.mTime = iter.GetCurTime();
+ v.mValue = diff;
+
+ diff /= f;
+ } else {
+ // FIXME: handle this
+ }
+
+ // diff is now the vector in which our camera is pointing
+ }
+
+ if (real.size()) {
+ *distanceTrack = real;
+ }
+}