# 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  

track_sampled_quat.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000-2002 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 "nel/misc/quat.h"
00029 #include "nel/misc/common.h"
00030 #include "3d/track_sampled_quat.h"
00031 
00032 using namespace NLMISC;
00033 using namespace std;
00034 
00035 
00036 namespace NL3D 
00037 {
00038 
00039 // ***************************************************************************
00040 // ***************************************************************************
00041 // Quaternion compression
00042 // ***************************************************************************
00043 // ***************************************************************************
00044 
00045 const   double  NL3D_OO32767= 1.0f/32767;
00046 const   double  NL3D_OO65535= 1.0f/65535;
00047 
00048 #ifdef NL3D_TSQ_ALLOW_QUAT_COMPRESS
00049 // ***************************************************************************
00050 void            CTrackSampledQuat::CQuatPack::pack(const CQuat &quat)
00051 {
00052         /*
00053                 This is the most precise/faster compression we can have. Some other tries have been made.
00054 
00055                 - deducing w from x,y,z is possible with w= 1-sqrt(x²+y²+z²) (with tradeoff of the W sign) 
00056                         but very not precise.
00057                 - Transform the quaternion to an AxisAngle is possible, but slower (some cos/sin or LUT).
00058                         Axis is encoded with sint16, and angle is encoded with uint16.
00059                 - The same than above, but encode the axis as X/Y only, and deduce Z from
00060                         them, is possible but precision problems arise. 
00061                         
00062                 You can see that the operation "deduce a 3/4 member from unit lenght rule" is definetly not precise.
00063 
00064                 Hence this simpler but workable way.
00065         */
00066 
00067         // normalize the quaterion.
00068         CQuatD nquat= quat;
00069         nquat.normalize();
00070 
00071         sint    ax= (sint)floor(nquat.x * 32767 + 0.5);
00072         sint    ay= (sint)floor(nquat.y * 32767 + 0.5);
00073         sint    az= (sint)floor(nquat.z * 32767 + 0.5);
00074         sint    aw= (sint)floor(nquat.w * 32767 + 0.5);
00075         clamp(ax, -32767, 32767);
00076         clamp(ay, -32767, 32767);
00077         clamp(az, -32767, 32767);
00078         clamp(aw, -32767, 32767);
00079         x= ax;
00080         y= ay;
00081         z= az;
00082         w= aw;
00083 }
00084 
00085 // ***************************************************************************
00086 void            CTrackSampledQuat::CQuatPack::unpack(CQuat &quat)
00087 {
00088         // unpack x/y/z.
00089         CQuatD  quatD;
00090         quatD.x= x * NL3D_OO32767;
00091         quatD.y= y * NL3D_OO32767;
00092         quatD.z= z * NL3D_OO32767;
00093         quatD.w= w * NL3D_OO32767;
00094         quatD.normalize();
00095 
00096         quat= quatD;
00097 }
00098 #endif
00099 
00100 
00101 // ***************************************************************************
00102 // ***************************************************************************
00103 // CTrackSampledQuat
00104 // ***************************************************************************
00105 // ***************************************************************************
00106 
00107 
00108 // ***************************************************************************
00109 CTrackSampledQuat::CTrackSampledQuat()
00110 {
00111 }
00112 
00113 // ***************************************************************************
00114 CTrackSampledQuat::~CTrackSampledQuat()
00115 {
00116 }
00117 
00118 // ***************************************************************************
00119 const IAnimatedValue&   CTrackSampledQuat::getValue () const
00120 {
00121         return _Value;
00122 }
00123 
00124 // ***************************************************************************
00125 void                                    CTrackSampledQuat::serial(NLMISC::IStream &f)
00126 {
00127         /*
00128         Version 1:
00129                 - split class with base CTrackSampledCommon (must add a version in it).
00130         Version 0:
00131                 - base version.
00132         */
00133         sint    ver= f.serialVersion(1);
00134 
00135         if( ver<=0 )
00136         {
00137                 // serial Time infos, directly in CTrackSampledCommon
00138                 f.serial(_LoopMode);
00139                 f.serial(_BeginTime);
00140                 f.serial(_EndTime) ;
00141                 f.serial(_TotalRange);
00142                 f.serial(_OOTotalRange);
00143                 f.serial(_DeltaTime);
00144                 f.serial(_OODeltaTime);
00145                 f.serial(_TimeBlocks);
00146         }
00147         else
00148         {
00149                 // serial Time infos.
00150                 CTrackSampledCommon::serialCommon(f);
00151         }
00152 
00153         // serial Keys.
00154         f.serial(_Keys);
00155 
00156 }
00157 
00158 // ***************************************************************************
00159 void    CTrackSampledQuat::build(const std::vector<uint16> &timeList, const std::vector<CQuat> &keyList, 
00160         float beginTime, float endTime)
00161 {
00162         nlassert( endTime>beginTime || (beginTime==endTime && keyList.size()<=1) );
00163         nlassert( keyList.size()==timeList.size() );
00164         uint i;
00165 
00166         // reset.
00167         uint    numKeys= keyList.size();
00168         _Keys.clear();
00169         _TimeBlocks.clear();
00170 
00171         // Build Common time information
00172         CTrackSampledCommon::buildCommon(timeList, beginTime, endTime);
00173 
00174 
00175         // Compute All Key values.
00176         //===================
00177         _Keys.resize(numKeys);
00178         for(i=0; i<numKeys;i++)
00179         {
00180                 _Keys[i].pack(keyList[i]);
00181         }
00182 
00183 }
00184 
00185 // ***************************************************************************
00186 void    CTrackSampledQuat::eval (const TAnimationTime& date)
00187 {
00188         // Eval time, and get key interpolation info
00189         uint    keyId0;
00190         uint    keyId1;
00191         float   interpValue;
00192         TEvalType       evalType= evalTime(date, _Keys.size(), keyId0, keyId1, interpValue);
00193 
00194         // Discard? 
00195         if( evalType==EvalDiscard )
00196                 return;
00197         // One Key? easy, and quit.
00198         else if( evalType==EvalKey0 )
00199         {
00200                 _Keys[keyId0].unpack(_Value.Value);
00201         }
00202         // interpolate
00203         else if( evalType==EvalInterpolate )
00204         {
00205                 CQuatPack       valueKey0= _Keys[keyId0];
00206                 CQuatPack       valueKey1= _Keys[keyId1];
00207 
00208                 // If the 2 keys have same value, just unpack.
00209                 if(valueKey0 == valueKey1)
00210                 {
00211                         valueKey0.unpack(_Value.Value);
00212                 }
00213                 // else interpolate
00214                 else
00215                 {
00216                         // unpack key value.
00217                         CQuat   quat0, quat1;
00218                         valueKey0.unpack(quat0);
00219                         valueKey1.unpack(quat1);
00220 
00221                         // interpolate
00222                         _Value.Value= CQuat::slerp(quat0, quat1, interpValue);
00223                 }
00224         }
00225         else
00226         {
00227                 nlstop;
00228         }
00229 
00230 }
00231 
00232 
00233 } // NL3D