00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "LampBasic.h"
00026 #include "Animation/RotationInterpolator/QuaternionLinearInterpolator.h"
00027
00028 namespace Lamp{
00029
00030
00031
00032 QuaternionLinearInterpolator::QuaternionLinearInterpolator() :
00033 keys_(NULL), keyCount_(0), lastestUseKeyIndex_(0){
00034 }
00035
00036
00037 QuaternionLinearInterpolator::~QuaternionLinearInterpolator(){
00038 SafeArrayDelete(keys_);
00039 }
00040
00041
00042 QuaternionLinearInterpolator::QuaternionLinearInterpolator(
00043 const QuaternionLinearInterpolator& copy){
00044 keyCount_ = copy.keyCount_;
00045 lastestUseKeyIndex_ = 0;
00046
00047 keys_ = NULL;
00048 if(keyCount_ == 0){ return; }
00049 keys_ = new Key[keyCount_];
00050 std::memcpy(keys_, copy.keys_, sizeof(Key) * keyCount_);
00051 }
00052
00053
00054 QuaternionLinearInterpolator& QuaternionLinearInterpolator::operator =(
00055 const QuaternionLinearInterpolator& copy){
00056
00057 if(this == ©){ return *this; }
00058 keyCount_ = copy.keyCount_;
00059 lastestUseKeyIndex_ = 0;
00060
00061 SafeArrayDelete(keys_);
00062 if(keyCount_ == 0){ return *this; }
00063 keys_ = new Key[keyCount_];
00064 std::memcpy(keys_, copy.keys_, sizeof(Key) * keyCount_);
00065 return *this;
00066 }
00067
00068
00069
00070
00071 float QuaternionLinearInterpolator::getLength() const{
00072 Assert((keyCount_ > 0) && (keys_ != NULL));
00073 return keys_[keyCount_ - 1].time_;
00074 }
00075
00076
00077
00078
00079 Vector3 QuaternionLinearInterpolator::eulerInterpolate(float time){
00080
00081 Quaternion resultQuaternion = quaternionInterpolate(time);
00082 Vector3 result;
00083 resultQuaternion.getRotationXYZ(&result);
00084 #ifdef _DEBUG
00085 if((!Math::classCheck(result.x)) ||
00086 (!Math::classCheck(result.y)) ||
00087 (!Math::classCheck(result.z))){
00088 _asm{ int 3 }
00089 }
00090 #endif
00091 return result;
00092 }
00093
00094
00095 Quaternion QuaternionLinearInterpolator::quaternionInterpolate(float time){
00096 Assert(keys_ != NULL);
00097
00098 if(time <= 0.f){ return keys_[0].value_; }
00099
00100 float length = getLength();
00101 int maxKeyIndex = keyCount_ - 1;
00102 if(time >= length){ return keys_[maxKeyIndex].value_; }
00103
00104
00105 int keyIndex = lastestUseKeyIndex_;
00106 Assert((keyIndex >= 0) && (keyIndex < maxKeyIndex));
00107 for(int i = 0; i < maxKeyIndex; i++){
00108 const Key& preKey = keys_[keyIndex];
00109 const Key& postKey = keys_[keyIndex + 1];
00110 Assert(preKey.time_ < postKey.time_);
00111 if((time >= preKey.time_) && (time < postKey.time_)){ break; }
00112 keyIndex++;
00113 if(keyIndex == maxKeyIndex){ keyIndex = 0; }
00114 Assert((keyIndex >= 0) && (keyIndex < maxKeyIndex));
00115 }
00116 Assert((keyIndex >= 0) && (keyIndex < maxKeyIndex));
00117 lastestUseKeyIndex_ = keyIndex;
00118
00119
00120 const Key& key = keys_[keyIndex];
00121 float keyTime = key.time_;
00122 const Key& nextKey = keys_[keyIndex + 1];
00123 Assert(keyTime < nextKey.time_);
00124 Assert((time >= keyTime) && (time < nextKey.time_));
00125 float rate = (time - keyTime) / (nextKey.time_ - keyTime);
00126 Assert(key.value_.dotProduct(nextKey.value_) >= 0.f);
00127 Assert(key.value_.isUnit() && nextKey.value_.isUnit());
00128 Quaternion result = Quaternion::slerp(key.value_, nextKey.value_, rate);
00129 #ifdef _DEBUG
00130 if((!Math::classCheck(result.x)) ||
00131 (!Math::classCheck(result.y)) ||
00132 (!Math::classCheck(result.z)) ||
00133 (!Math::classCheck(result.w))){
00134 _asm{ int 3 }
00135 }
00136 #endif
00137 return result;
00138 }
00139
00140
00141
00142
00143 void QuaternionLinearInterpolator::setKeyCount(int keyCount){
00144
00145 Assert(keyCount > 1);
00146 keyCount_ = keyCount;
00147 SafeArrayDelete(keys_);
00148 keys_ = new Key[keyCount_];
00149 lastestUseKeyIndex_ = 0;
00150 }
00151
00152 }
00153