vrshoot

annotate libs/assimp/TargetAnimation.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
rev   line source
nuclear@0 1 /*
nuclear@0 2 Open Asset Import Library (assimp)
nuclear@0 3 ----------------------------------------------------------------------
nuclear@0 4
nuclear@0 5 Copyright (c) 2006-2012, assimp team
nuclear@0 6 All rights reserved.
nuclear@0 7
nuclear@0 8 Redistribution and use of this software in source and binary forms,
nuclear@0 9 with or without modification, are permitted provided that the
nuclear@0 10 following conditions are met:
nuclear@0 11
nuclear@0 12 * Redistributions of source code must retain the above
nuclear@0 13 copyright notice, this list of conditions and the
nuclear@0 14 following disclaimer.
nuclear@0 15
nuclear@0 16 * Redistributions in binary form must reproduce the above
nuclear@0 17 copyright notice, this list of conditions and the
nuclear@0 18 following disclaimer in the documentation and/or other
nuclear@0 19 materials provided with the distribution.
nuclear@0 20
nuclear@0 21 * Neither the name of the assimp team, nor the names of its
nuclear@0 22 contributors may be used to endorse or promote products
nuclear@0 23 derived from this software without specific prior
nuclear@0 24 written permission of the assimp team.
nuclear@0 25
nuclear@0 26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
nuclear@0 27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
nuclear@0 28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0 29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
nuclear@0 30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0 31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
nuclear@0 32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0 33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
nuclear@0 34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
nuclear@0 35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nuclear@0 36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0 37
nuclear@0 38 ----------------------------------------------------------------------
nuclear@0 39 */
nuclear@0 40
nuclear@0 41 #include "AssimpPCH.h"
nuclear@0 42 #include "TargetAnimation.h"
nuclear@0 43 #include <algorithm>
nuclear@0 44
nuclear@0 45 using namespace Assimp;
nuclear@0 46
nuclear@0 47
nuclear@0 48 // ------------------------------------------------------------------------------------------------
nuclear@0 49 KeyIterator::KeyIterator(const std::vector<aiVectorKey>* _objPos,
nuclear@0 50 const std::vector<aiVectorKey>* _targetObjPos,
nuclear@0 51 const aiVector3D* defaultObjectPos /*= NULL*/,
nuclear@0 52 const aiVector3D* defaultTargetPos /*= NULL*/)
nuclear@0 53
nuclear@0 54 : reachedEnd (false)
nuclear@0 55 , curTime (-1.)
nuclear@0 56 , objPos (_objPos)
nuclear@0 57 , targetObjPos (_targetObjPos)
nuclear@0 58 , nextObjPos (0)
nuclear@0 59 , nextTargetObjPos(0)
nuclear@0 60 {
nuclear@0 61 // Generate default transformation tracks if necessary
nuclear@0 62 if (!objPos || objPos->empty())
nuclear@0 63 {
nuclear@0 64 defaultObjPos.resize(1);
nuclear@0 65 defaultObjPos.front().mTime = 10e10;
nuclear@0 66
nuclear@0 67 if (defaultObjectPos)
nuclear@0 68 defaultObjPos.front().mValue = *defaultObjectPos;
nuclear@0 69
nuclear@0 70 objPos = & defaultObjPos;
nuclear@0 71 }
nuclear@0 72 if (!targetObjPos || targetObjPos->empty())
nuclear@0 73 {
nuclear@0 74 defaultTargetObjPos.resize(1);
nuclear@0 75 defaultTargetObjPos.front().mTime = 10e10;
nuclear@0 76
nuclear@0 77 if (defaultTargetPos)
nuclear@0 78 defaultTargetObjPos.front().mValue = *defaultTargetPos;
nuclear@0 79
nuclear@0 80 targetObjPos = & defaultTargetObjPos;
nuclear@0 81 }
nuclear@0 82 }
nuclear@0 83
nuclear@0 84 // ------------------------------------------------------------------------------------------------
nuclear@0 85 template <class T>
nuclear@0 86 inline T Interpolate(const T& one, const T& two, float val)
nuclear@0 87 {
nuclear@0 88 return one + (two-one)*val;
nuclear@0 89 }
nuclear@0 90
nuclear@0 91 // ------------------------------------------------------------------------------------------------
nuclear@0 92 void KeyIterator::operator ++()
nuclear@0 93 {
nuclear@0 94 // If we are already at the end of all keyframes, return
nuclear@0 95 if (reachedEnd) {
nuclear@0 96 return;
nuclear@0 97 }
nuclear@0 98
nuclear@0 99 // Now search in all arrays for the time value closest
nuclear@0 100 // to our current position on the time line
nuclear@0 101 double d0,d1;
nuclear@0 102
nuclear@0 103 d0 = objPos->at ( std::min<unsigned int> ( nextObjPos, objPos->size()-1) ).mTime;
nuclear@0 104 d1 = targetObjPos->at( std::min<unsigned int> ( nextTargetObjPos, targetObjPos->size()-1) ).mTime;
nuclear@0 105
nuclear@0 106 // Easiest case - all are identical. In this
nuclear@0 107 // case we don't need to interpolate so we can
nuclear@0 108 // return earlier
nuclear@0 109 if ( d0 == d1 )
nuclear@0 110 {
nuclear@0 111 curTime = d0;
nuclear@0 112 curPosition = objPos->at(nextObjPos).mValue;
nuclear@0 113 curTargetPosition = targetObjPos->at(nextTargetObjPos).mValue;
nuclear@0 114
nuclear@0 115 // increment counters
nuclear@0 116 if (objPos->size() != nextObjPos-1)
nuclear@0 117 ++nextObjPos;
nuclear@0 118
nuclear@0 119 if (targetObjPos->size() != nextTargetObjPos-1)
nuclear@0 120 ++nextTargetObjPos;
nuclear@0 121 }
nuclear@0 122
nuclear@0 123 // An object position key is closest to us
nuclear@0 124 else if (d0 < d1)
nuclear@0 125 {
nuclear@0 126 curTime = d0;
nuclear@0 127
nuclear@0 128 // interpolate the other
nuclear@0 129 if (1 == targetObjPos->size() || !nextTargetObjPos) {
nuclear@0 130 curTargetPosition = targetObjPos->at(0).mValue;
nuclear@0 131 }
nuclear@0 132 else
nuclear@0 133 {
nuclear@0 134 const aiVectorKey& last = targetObjPos->at(nextTargetObjPos);
nuclear@0 135 const aiVectorKey& first = targetObjPos->at(nextTargetObjPos-1);
nuclear@0 136
nuclear@0 137 curTargetPosition = Interpolate(first.mValue, last.mValue, (float) (
nuclear@0 138 (curTime-first.mTime) / (last.mTime-first.mTime) ));
nuclear@0 139 }
nuclear@0 140
nuclear@0 141 if (objPos->size() != nextObjPos-1)
nuclear@0 142 ++nextObjPos;
nuclear@0 143 }
nuclear@0 144 // A target position key is closest to us
nuclear@0 145 else
nuclear@0 146 {
nuclear@0 147 curTime = d1;
nuclear@0 148
nuclear@0 149 // interpolate the other
nuclear@0 150 if (1 == objPos->size() || !nextObjPos) {
nuclear@0 151 curPosition = objPos->at(0).mValue;
nuclear@0 152 }
nuclear@0 153 else
nuclear@0 154 {
nuclear@0 155 const aiVectorKey& last = objPos->at(nextObjPos);
nuclear@0 156 const aiVectorKey& first = objPos->at(nextObjPos-1);
nuclear@0 157
nuclear@0 158 curPosition = Interpolate(first.mValue, last.mValue, (float) (
nuclear@0 159 (curTime-first.mTime) / (last.mTime-first.mTime)));
nuclear@0 160 }
nuclear@0 161
nuclear@0 162 if (targetObjPos->size() != nextTargetObjPos-1)
nuclear@0 163 ++nextTargetObjPos;
nuclear@0 164 }
nuclear@0 165
nuclear@0 166 if (nextObjPos >= objPos->size()-1 &&
nuclear@0 167 nextTargetObjPos >= targetObjPos->size()-1)
nuclear@0 168 {
nuclear@0 169 // We reached the very last keyframe
nuclear@0 170 reachedEnd = true;
nuclear@0 171 }
nuclear@0 172 }
nuclear@0 173
nuclear@0 174 // ------------------------------------------------------------------------------------------------
nuclear@0 175 void TargetAnimationHelper::SetTargetAnimationChannel (
nuclear@0 176 const std::vector<aiVectorKey>* _targetPositions)
nuclear@0 177 {
nuclear@0 178 ai_assert(NULL != _targetPositions);
nuclear@0 179 targetPositions = _targetPositions;
nuclear@0 180 }
nuclear@0 181
nuclear@0 182 // ------------------------------------------------------------------------------------------------
nuclear@0 183 void TargetAnimationHelper::SetMainAnimationChannel (
nuclear@0 184 const std::vector<aiVectorKey>* _objectPositions)
nuclear@0 185 {
nuclear@0 186 ai_assert(NULL != _objectPositions);
nuclear@0 187 objectPositions = _objectPositions;
nuclear@0 188 }
nuclear@0 189
nuclear@0 190 // ------------------------------------------------------------------------------------------------
nuclear@0 191 void TargetAnimationHelper::SetFixedMainAnimationChannel(
nuclear@0 192 const aiVector3D& fixed)
nuclear@0 193 {
nuclear@0 194 objectPositions = NULL; // just to avoid confusion
nuclear@0 195 fixedMain = fixed;
nuclear@0 196 }
nuclear@0 197
nuclear@0 198 // ------------------------------------------------------------------------------------------------
nuclear@0 199 void TargetAnimationHelper::Process(std::vector<aiVectorKey>* distanceTrack)
nuclear@0 200 {
nuclear@0 201 ai_assert(NULL != targetPositions && NULL != distanceTrack);
nuclear@0 202
nuclear@0 203 // TODO: in most cases we won't need the extra array
nuclear@0 204 std::vector<aiVectorKey> real;
nuclear@0 205
nuclear@0 206 std::vector<aiVectorKey>* fill = (distanceTrack == objectPositions ? &real : distanceTrack);
nuclear@0 207 fill->reserve(std::max( objectPositions->size(), targetPositions->size() ));
nuclear@0 208
nuclear@0 209 // Iterate through all object keys and interpolate their values if necessary.
nuclear@0 210 // Then get the corresponding target position, compute the difference
nuclear@0 211 // vector between object and target position. Then compute a rotation matrix
nuclear@0 212 // that rotates the base vector of the object coordinate system at that time
nuclear@0 213 // to match the diff vector.
nuclear@0 214
nuclear@0 215 KeyIterator iter(objectPositions,targetPositions,&fixedMain);
nuclear@0 216 for (;!iter.Finished();++iter)
nuclear@0 217 {
nuclear@0 218 const aiVector3D& position = iter.GetCurPosition();
nuclear@0 219 const aiVector3D& tposition = iter.GetCurTargetPosition();
nuclear@0 220
nuclear@0 221 // diff vector
nuclear@0 222 aiVector3D diff = tposition - position;
nuclear@0 223 float f = diff.Length();
nuclear@0 224
nuclear@0 225 // output distance vector
nuclear@0 226 if (f)
nuclear@0 227 {
nuclear@0 228 fill->push_back(aiVectorKey());
nuclear@0 229 aiVectorKey& v = fill->back();
nuclear@0 230 v.mTime = iter.GetCurTime();
nuclear@0 231 v.mValue = diff;
nuclear@0 232
nuclear@0 233 diff /= f;
nuclear@0 234 }
nuclear@0 235 else
nuclear@0 236 {
nuclear@0 237 // FIXME: handle this
nuclear@0 238 }
nuclear@0 239
nuclear@0 240 // diff is now the vector in which our camera is pointing
nuclear@0 241 }
nuclear@0 242
nuclear@0 243 if (real.size()) {
nuclear@0 244 *distanceTrack = real;
nuclear@0 245 }
nuclear@0 246 }