00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/bone.h"
00029
00030
00031 namespace NL3D
00032 {
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 CBoneBase::CBoneBase() : DefaultPos(CVector(0,0,0)), DefaultRotEuler(CVector(0,0,0)),
00044 DefaultScale(CVector(1,1,1)), DefaultPivot(CVector(0,0,0))
00045 {
00046 FatherId= -1;
00047 UnheritScale= true;
00048
00049 LodDisableDistance= 0.f;
00050 }
00051
00052
00053
00054 void CBoneBase::serial(NLMISC::IStream &f)
00055 {
00056
00057
00058
00059
00060 sint ver= f.serialVersion(1);
00061
00062 f.serial(Name);
00063 f.serial(InvBindPos);
00064 f.serial(FatherId);
00065 f.serial(UnheritScale);
00066
00067 if(ver>=1)
00068 f.serial(LodDisableDistance);
00069 else
00070 {
00071
00072 LodDisableDistance= 0.f;
00073 }
00074
00075 f.serial(DefaultPos);
00076 f.serial(DefaultRotEuler);
00077 f.serial(DefaultRotQuat);
00078 f.serial(DefaultScale);
00079 f.serial(DefaultPivot);
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 CBone::CBone(CBoneBase *boneBase)
00092 {
00093 nlassert(boneBase);
00094 _BoneBase= boneBase;
00095
00096
00097 IAnimatable::resize(AnimValueLast);
00098
00099 ITransformable::setTransformMode(ITransformable::RotQuat);
00100 ITransformable::setPos( ((CAnimatedValueVector&)_BoneBase->DefaultPos.getValue()).Value );
00101 ITransformable::setRotQuat( ((CAnimatedValueQuat&)_BoneBase->DefaultRotQuat.getValue()).Value );
00102 ITransformable::setScale( ((CAnimatedValueVector&)_BoneBase->DefaultScale.getValue()).Value );
00103 ITransformable::setPivot( ((CAnimatedValueVector&)_BoneBase->DefaultPivot.getValue()).Value );
00104
00105
00106 _PosChannelId= -1;
00107 _RotEulerChannelId= -1;
00108 _RotQuatChannelId= -1;
00109 _ScaleChannelId= -1;
00110 _PivotChannelId= -1;
00111 }
00112
00113
00114 ITrack* CBone::getDefaultTrack (uint valueId)
00115 {
00116 nlassert(_BoneBase);
00117
00118
00119 switch (valueId)
00120 {
00121 case PosValue: return &_BoneBase->DefaultPos;
00122 case RotEulerValue: return &_BoneBase->DefaultRotEuler;
00123 case RotQuatValue: return &_BoneBase->DefaultRotQuat;
00124 case ScaleValue: return &_BoneBase->DefaultScale;
00125 case PivotValue: return &_BoneBase->DefaultPivot;
00126 }
00127
00128
00129 nlstop;
00130
00131
00132 return NULL;
00133 }
00134
00135
00136 void CBone::registerToChannelMixer(CChannelMixer *chanMixer, const std::string &prefix)
00137 {
00138
00139
00140 _PosChannelId= addValue(chanMixer, PosValue, OwnerBit, prefix, true);
00141 _RotEulerChannelId= addValue(chanMixer, RotEulerValue, OwnerBit, prefix, true);
00142 _RotQuatChannelId= addValue(chanMixer, RotQuatValue, OwnerBit, prefix, true);
00143 _ScaleChannelId= addValue(chanMixer, ScaleValue, OwnerBit, prefix, true);
00144 _PivotChannelId= addValue(chanMixer, PivotValue, OwnerBit, prefix, true);
00145
00146
00147 }
00148
00149
00150 void CBone::compute(CBone *parent, const CMatrix &rootMatrix)
00151 {
00152 nlassert(_BoneBase);
00153
00154
00155
00156 if(!parent)
00157 {
00158 _LocalSkeletonMatrix= getMatrix();
00159 }
00160
00161 else
00162 {
00163
00164 if(_BoneBase->UnheritScale)
00165 {
00166 CMatrix invScaleComp;
00167 CVector fatherScale;
00168 CVector trans;
00169
00170
00171 if( getTransformMode()==ITransformable::DirectMatrix )
00172 getMatrix().getPos(trans);
00173 else
00174 getPos(trans);
00175
00176 parent->getScale(fatherScale);
00177
00178 fatherScale.x= 1.0f / fatherScale.x;
00179 fatherScale.y= 1.0f / fatherScale.y;
00180 fatherScale.z= 1.0f / fatherScale.z;
00181
00182
00183
00184
00185
00186
00187 invScaleComp.scale(fatherScale);
00188
00189 trans.x-= fatherScale.x * trans.x;
00190 trans.y-= fatherScale.y * trans.y;
00191 trans.z-= fatherScale.z * trans.z;
00192 invScaleComp.setPos(trans);
00193
00194
00195
00196
00197 static CMatrix tmp;
00198 tmp.setMulMatrixNoProj( parent->_LocalSkeletonMatrix, invScaleComp );
00199 _LocalSkeletonMatrix.setMulMatrixNoProj( tmp, getMatrix() );
00200 }
00201
00202 else
00203 {
00204
00205 _LocalSkeletonMatrix.setMulMatrixNoProj( parent->_LocalSkeletonMatrix, getMatrix() );
00206 }
00207 }
00208
00209
00210 _WorldMatrix.setMulMatrixNoProj( rootMatrix, _LocalSkeletonMatrix );
00211
00212
00213 _BoneSkinMatrix.setMulMatrixNoProj( _LocalSkeletonMatrix, _BoneBase->InvBindPos );
00214 }
00215
00216
00217
00218 void CBone::interpolateBoneSkinMatrix(const CMatrix &otherMatrix, float interp)
00219 {
00220 CMatrix &curMatrix= _BoneSkinMatrix;
00221
00222
00223 CVector fatherI= otherMatrix.getI();
00224 CVector curI= curMatrix.getI();
00225 curI= fatherI*(1-interp) + curI*interp;
00226 CVector fatherJ= otherMatrix.getJ();
00227 CVector curJ= curMatrix.getJ();
00228 curJ= fatherJ*(1-interp) + curJ*interp;
00229 CVector fatherK= otherMatrix.getK();
00230 CVector curK= curMatrix.getK();
00231 curK= fatherK*(1-interp) + curK*interp;
00232
00233 curMatrix.setRot(curI, curJ, curK);
00234
00235
00236 CVector fatherPos= otherMatrix.getPos();
00237 CVector curPos= curMatrix.getPos();
00238 curPos= fatherPos*(1-interp) + curPos*interp;
00239 curMatrix.setPos(curPos);
00240 }
00241
00242
00243
00244 void CBone::lodEnableChannels(CChannelMixer *chanMixer, bool enable)
00245 {
00246 nlassert(chanMixer);
00247
00248
00249 if( _PosChannelId>=0 )
00250 chanMixer->lodEnableChannel(_PosChannelId, enable);
00251 if( _RotEulerChannelId>=0 )
00252 chanMixer->lodEnableChannel(_RotEulerChannelId, enable);
00253 if( _RotQuatChannelId>=0 )
00254 chanMixer->lodEnableChannel(_RotQuatChannelId, enable);
00255 if( _ScaleChannelId>=0 )
00256 chanMixer->lodEnableChannel(_ScaleChannelId, enable);
00257 if( _PivotChannelId>=0 )
00258 chanMixer->lodEnableChannel(_PivotChannelId, enable);
00259
00260 }
00261
00262
00263 }