# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

bone.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 #include "3d/bone.h"
00029 
00030 
00031 namespace NL3D
00032 {
00033 
00034 
00035 // ***************************************************************************
00036 // ***************************************************************************
00037 // CBoneBase
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         // Default: never disable.
00049         LodDisableDistance= 0.f;
00050 }
00051 
00052 
00053 // ***************************************************************************
00054 void                    CBoneBase::serial(NLMISC::IStream &f)
00055 {
00056         /*
00057         Version 1:
00058                 - LodDisableDistance
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                 // Default: never disable.
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 // CBone
00086 // ***************************************************************************
00087 // ***************************************************************************
00088 
00089 
00090 // ***************************************************************************
00091 CBone::CBone(CBoneBase *boneBase)
00092 {
00093         nlassert(boneBase);
00094         _BoneBase= boneBase;
00095 
00096         // IAnimatable.
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         // By default, the bone is not binded to a channelMixer.
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         // what value ?
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         // No, only ITrnasformable values!
00129         nlstop;
00130         // Deriver note: else call BaseClass::getDefaultTrack(valueId);
00131 
00132         return NULL;
00133 }
00134 
00135 // ***************************************************************************
00136 void    CBone::registerToChannelMixer(CChannelMixer *chanMixer, const std::string &prefix)
00137 {
00138         // For CBone, channels are detailled.
00139         // Bkup each channelId (for disable).
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         // Deriver note: if necessary, call     BaseClass::registerToChannelMixer(chanMixer, prefix);
00147 }
00148 
00149 // ***************************************************************************
00150 void    CBone::compute(CBone *parent, const CMatrix &rootMatrix)
00151 {
00152         nlassert(_BoneBase);
00153 
00154         // Compute LocalSkeletonMatrix.
00155         // Root case?
00156         if(!parent)
00157         {
00158                 _LocalSkeletonMatrix= getMatrix();
00159         }
00160         // Else, son case, take world matrix from parent.
00161         else
00162         {
00163                 // UnheritScale case.
00164                 if(_BoneBase->UnheritScale)
00165                 {
00166                         CMatrix         invScaleComp;
00167                         CVector         fatherScale;
00168                         CVector         trans;
00169 
00170                         // retrieve our translation
00171                         if( getTransformMode()==ITransformable::DirectMatrix )
00172                                 getMatrix().getPos(trans);
00173                         else
00174                                 getPos(trans);
00175                         // retrieve scale from our father.
00176                         parent->getScale(fatherScale);
00177                         // inverse this scale.
00178                         fatherScale.x= 1.0f / fatherScale.x;
00179                         fatherScale.y= 1.0f / fatherScale.y;
00180                         fatherScale.z= 1.0f / fatherScale.z;
00181 
00182 
00183                         // Compute InverseScale compensation:
00184                         // with UnheritScale, formula per bone should be  T*Sf-1*P*R*S*P-1.
00185                         // But getMatrix() return T*P*R*S*P-1.
00186                         // So we must compute T*Sf-1*T-1, in order to get wanted result.
00187                         invScaleComp.scale(fatherScale);
00188                         // Faster compute of the translation part: just "trans + fatherScale MUL -trans" where MUL is comp mul
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                         // And finally, we got ParentWM * T*Sf-1*P*R*S*P-1.
00196                         // Do: _LocalSkeletonMatrix= parent->_LocalSkeletonMatrix * invScaleComp * getMatrix()
00197                         static  CMatrix tmp;
00198                         tmp.setMulMatrixNoProj( parent->_LocalSkeletonMatrix, invScaleComp );
00199                         _LocalSkeletonMatrix.setMulMatrixNoProj( tmp, getMatrix() );
00200                 }
00201                 // Normal case.
00202                 else
00203                 {
00204                         // Do: _LocalSkeletonMatrix= parent->_LocalSkeletonMatrix * getMatrix()
00205                         _LocalSkeletonMatrix.setMulMatrixNoProj( parent->_LocalSkeletonMatrix, getMatrix() );
00206                 }
00207         }
00208 
00209         // Compute WorldMatrix. Do: _WorldMatrix= rootMatrix * _LocalSkeletonMatrix
00210         _WorldMatrix.setMulMatrixNoProj( rootMatrix, _LocalSkeletonMatrix );
00211 
00212         // Compute BoneSkinMatrix. Do: _BoneSkinMatrix= _LocalSkeletonMatrix * _BoneBase->InvBindPos
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         // interpolate rot/scale. Just interpolate basis vectors
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         // replace rotation
00233         curMatrix.setRot(curI, curJ, curK);
00234 
00235         // interpolate pos
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         // Lod Enable channels if they are correclty registered to the channelMixer.
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 } // NL3D