| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* $Header: /Commando/Code/ww3d2/motchan.cpp 3 5/05/01 7:10p Jani_p $ */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando / G 3D Library *
- * *
- * $Archive:: /Commando/Code/ww3d2/motchan.cpp $*
- * *
- * Author:: Greg_h *
- * *
- * $Modtime:: 5/05/01 6:28p $*
- * *
- * $Revision:: 3 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * MotionChannelClass::MotionChannelClass -- constructor *
- * MotionChannelClass::~MotionChannelClass -- destructor *
- * MotionChannelClass::Free -- de-allocates all memory in use *
- * MotionChannelClass::Load -- loads a motion channel from a file *
- * BitChannelClass::BitChannelClass -- Constructor for BitChannelClass *
- * BitChannelClass::~BitChannelClass -- Destructor for BitChannelClass *
- * BitChannelClass::Free -- Free all "external" memory in use *
- * BitChannelClass::Load -- Read a bit channel from a w3d chunk *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "motchan.h"
- #include "w3d_file.h"
- #include "chunkio.h"
- #include "vector.h"
- #include "wwmath.h"
- #include "quat.h"
- // Static Table, for Adaptive Delta Decompressor
- #define FILTER_TABLE_SIZE (256)
- #define FILTER_TABLE_GEN_START (16)
- #define FILTER_TABLE_GEN_SIZE (FILTER_TABLE_SIZE - FILTER_TABLE_GEN_START)
- static float filtertable[FILTER_TABLE_SIZE] = {
- 0.00000001f,
- 0.0000001f,
- 0.000001f,
- 0.00001f,
- 0.0001f,
- 0.001f,
- 0.01f,
- 0.1f,
- 1.0f,
- 10.0f,
- 100.0f,
- 1000.0f,
- 10000.0f,
- 100000.0f,
- 1000000.0f,
- 10000000.0f,
- };
- static bool table_valid = false;
- /***********************************************************************************************
- * MotionChannelClass::MotionChannelClass -- constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/11/1997 GH : Created. *
- *=============================================================================================*/
- MotionChannelClass::MotionChannelClass(void) :
- PivotIdx(0),
- Type(0),
- VectorLen(0),
- Data(NULL),
- FirstFrame(-1),
- LastFrame(-1)
- {
- }
- /***********************************************************************************************
- * MotionChannelClass::~MotionChannelClass -- destructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/11/1997 GH : Created. *
- *=============================================================================================*/
- MotionChannelClass::~MotionChannelClass(void)
- {
- Free();
- }
- /***********************************************************************************************
- * MotionChannelClass::Free -- de-allocates all memory in use *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/11/1997 GH : Created. *
- *=============================================================================================*/
- void MotionChannelClass::Free(void)
- {
- if (Data) {
- delete[] Data;
- Data = NULL;
- }
- }
- /***********************************************************************************************
- * MotionChannelClass::Load -- loads a motion channel from a file *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/11/1997 GH : Created. *
- *=============================================================================================*/
- bool MotionChannelClass::Load_W3D(ChunkLoadClass & cload)
- {
- int size = cload.Cur_Chunk_Length();
- unsigned int datasize = (size - sizeof(W3dAnimChannelStruct));
- unsigned int num_floats = (datasize / sizeof(float32)) + 1;
-
- W3dAnimChannelStruct chan;
- if (cload.Read(&chan,sizeof(W3dAnimChannelStruct)) != sizeof(W3dAnimChannelStruct)) {
- return false;
- }
- FirstFrame = chan.FirstFrame;
- LastFrame = chan.LastFrame;
- VectorLen = chan.VectorLen;
- Type = chan.Flags;
- PivotIdx = chan.Pivot;
- Data = MSGW3DNEWARRAY("MotionChannelClass::Data") float32[num_floats];
- Data[0] = chan.Data[0];
-
- if (cload.Read(&(Data[1]),datasize) != datasize) {
- Free();
- return false;
- }
- return true;
- }
- /***********************************************************************************************
- * BitChannelClass::BitChannelClass -- Constructor for BitChannelClass *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- *=============================================================================================*/
- BitChannelClass::BitChannelClass(void) :
- PivotIdx(0),
- Type(0),
- DefaultVal(0),
- FirstFrame(-1),
- LastFrame(-1),
- Bits(NULL)
- {
- }
- /***********************************************************************************************
- * BitChannelClass::~BitChannelClass -- Destructor for BitChannelClass *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/21/98 GTH : Created. *
- *=============================================================================================*/
- BitChannelClass::~BitChannelClass(void)
- {
- Free();
- }
- /***********************************************************************************************
- * BitChannelClass::Free -- Free all "external" memory in use *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/21/98 GTH : Created. *
- *=============================================================================================*/
- void BitChannelClass::Free(void)
- {
- if (Bits != NULL) {
- delete[] Bits;
- Bits = NULL;
- }
- }
- /***********************************************************************************************
- * BitChannelClass::Load -- Read a bit channel from a w3d chunk *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/21/98 GTH : Created. *
- *=============================================================================================*/
- bool BitChannelClass::Load_W3D(ChunkLoadClass & cload)
- {
- Free();
-
- int chunk_size = cload.Cur_Chunk_Length();
- W3dBitChannelStruct chan;
- if (cload.Read(&chan,sizeof(W3dBitChannelStruct)) != sizeof(W3dBitChannelStruct)) {
- return false;
- }
- FirstFrame = chan.FirstFrame;
- LastFrame = chan.LastFrame;
- Type = chan.Flags;
- PivotIdx = chan.Pivot;
- DefaultVal = chan.DefaultVal;
- uint32 numbits = LastFrame - FirstFrame + 1;
- uint32 numbytes = (numbits + 7) / 8;
- uint32 bytesleft = numbytes - 1;
- assert((sizeof(W3dBitChannelStruct) + bytesleft) == (unsigned)chunk_size);
- Bits = MSGW3DNEWARRAY("BitChannelClass::Bits") uint8[numbytes];
- assert(Bits);
- Bits[0] = chan.Data[0];
-
- if (bytesleft > 0) {
- if (cload.Read(&(Bits[1]),bytesleft) != bytesleft) {
- Free();
- return false;
- }
- }
- return true;
- }
- /***********************************************************************************************
- * TimeCodedMotionChannelClass::TimeCodedMotionChannelClass -- constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/11/1997 GH : Created. *
- *=============================================================================================*/
- TimeCodedMotionChannelClass::TimeCodedMotionChannelClass(void) :
- PivotIdx(0),
- Type(0),
- VectorLen(0),
- PacketSize(0),
- Data(NULL),
- NumTimeCodes(0),
- LastTimeCodeIdx(0), // absolute index to last time code
- CachedIdx(0) // Last Index Used
- {
- }
- /***********************************************************************************************
- * MotionChannelClass::~MotionChannelClass -- destructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/11/1997 GH : Created. *
- *=============================================================================================*/
- TimeCodedMotionChannelClass::~TimeCodedMotionChannelClass(void)
- {
- Free();
- }
- /***********************************************************************************************
- * TimeCodedMotionChannelClass::Free -- de-allocates all memory in use *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/11/1997 GH : Created. *
- *=============================================================================================*/
- void TimeCodedMotionChannelClass::Free(void)
- {
- if (Data) {
- delete[] Data;
- Data = NULL;
- }
- }
- /***********************************************************************************************
- * TimeCodedMotionChannelClass::Load -- loads a motion channel from a file *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/11/1997 GH : Created. *
- *=============================================================================================*/
- bool TimeCodedMotionChannelClass::Load_W3D(ChunkLoadClass & cload)
- {
- int size = cload.Cur_Chunk_Length();
- unsigned int datasize = size - sizeof(W3dTimeCodedAnimChannelStruct);
- unsigned int numInts = (datasize / sizeof(uint32)) + 1;
- W3dTimeCodedAnimChannelStruct chan;
- if (cload.Read(&chan,sizeof(W3dTimeCodedAnimChannelStruct)) != sizeof(W3dTimeCodedAnimChannelStruct)) {
- return false;
- }
-
- NumTimeCodes = chan.NumTimeCodes;
- VectorLen = chan.VectorLen;
- Type = chan.Flags;
- PivotIdx = chan.Pivot;
- PacketSize = VectorLen+1;
- CachedIdx = 0;
- LastTimeCodeIdx = (NumTimeCodes-1) * PacketSize;
- Data = MSGW3DNEWARRAY("TimeCodedMotionChannelClass::Data") uint32[numInts];
- Data[0] = chan.Data[0];
-
- if (cload.Read(&(Data[1]), datasize) != datasize) {
- Free();
- return false;
- }
- return true;
- }
- /***********************************************************************************************
- * TimeCodedMotionChannelClass::Get_Vector -- returns the vector for the specified frame # *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/11/1997 GH : Created. *
- *=============================================================================================*/
- void TimeCodedMotionChannelClass::Get_Vector(float32 frame,float * setvec)
- {
-
- uint32 tc0;
-
- tc0 = frame;
-
- uint32 pidx = get_index( tc0 );
- uint32 p2idx;
-
- if (pidx == ((NumTimeCodes - 1) * PacketSize)) {
-
- float32 *frm = (float32 *) &Data[pidx+1];
-
- for (int i=0; i < VectorLen; i++) {
-
- setvec[i] = frm[i];
-
- }
-
- return;
-
- }
- else {
- p2idx = pidx + PacketSize;
- }
-
- uint32 time = Data[p2idx];
- if (time & W3D_TIMECODED_BINARY_MOVEMENT_FLAG) {
- float32 *frm = (float32 *) &Data[pidx+1];
- for (int i=0; i < VectorLen; i++) {
- setvec[i] = frm[i];
- }
- return;
- }
- float32 time1 = (Data[pidx] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
- float32 time2 = (time & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
-
- float32 ratio = (frame - time1) / (time2 - time1);
-
- float32 *frame1 = (float32 *) &Data[pidx+1];
- float32 *frame2 = (float32 *) &Data[p2idx+1];
-
- for (int i=0; i < VectorLen; i++) {
-
- setvec[i] = WWMath::Lerp(frame1[i],frame2[i],ratio);
-
- }
- } // Get_Vector
- Quaternion TimeCodedMotionChannelClass::Get_QuatVector(float32 frame)
- {
- assert(VectorLen == 4);
- Quaternion q(1);
- uint32 tc0;
-
- tc0 = frame;
-
- uint32 pidx = get_index( tc0 );
- uint32 p2idx;
-
- if (pidx == ((NumTimeCodes - 1) * PacketSize)) {
-
- float32 *vec = (float32 *) &Data[pidx+1];
-
- q.Set(vec[0], vec[1], vec[2], vec[3]);
- return( q );
-
- }
- else {
- p2idx = pidx + PacketSize;
- }
-
- uint32 time = Data[p2idx];
- if (time & W3D_TIMECODED_BINARY_MOVEMENT_FLAG) {
- // its a binary movement!
- float32 *vec = (float32 *) &Data[pidx+1];
- q.Set(vec[0], vec[1], vec[2], vec[3]);
-
- return( q );
- }
-
- float32 time1 = (Data[pidx] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
- float32 time2 = (time & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
- float32 ratio = (frame - time1) / (time2 - time1);
-
- float32 *frame1 = (float32 *) &Data[pidx+1];
- float32 *frame2 = (float32 *) &Data[p2idx+1];
-
- Quaternion q1(1);
- Quaternion q2(1);
- q1.Set(frame1[0], frame1[1], frame1[2], frame1[3]);
- q2.Set(frame2[0], frame2[1], frame2[2], frame2[3]);
- Fast_Slerp(q, q1, q2, ratio);
- return( q );
- } // Get_QuatVector
- /***********************************************************************************************
- * TimeCodedMotionChannelClass::binary_search_index / returns packet index *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 01/27/2000 JGA : Created. *
- *=============================================================================================*/
- // New version that uses a binary search, and no cache
- uint32 TimeCodedMotionChannelClass::binary_search_index(uint32 timecode)
- {
- int leftIdx = 0;
- int rightIdx = NumTimeCodes - 2;
- int dx;
- uint32 time;
- int idx = LastTimeCodeIdx; //((rightIdx+1) * PacketSize;)
- //int32 LastTimeCodeIdx; // absolute index to last time code
- //int32 CachedIdx; // Last Index Used
- // special case last packet
- time = Data[idx] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
- if (timecode >= time) return(idx);
- for (;;) {
-
- dx = rightIdx - leftIdx;
- dx>>=1; // divide by 2
- dx += leftIdx;
- idx = dx * PacketSize;
- time = Data[idx] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
- if (timecode < time) {
- rightIdx = dx;
- continue;
- }
- time = Data[idx + PacketSize] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
- if (timecode < time) return(idx);
- if (leftIdx ^ dx) {
- leftIdx = dx;
- continue;
- }
- //
- // if leftIdx == dx prior to assignment, then leftIdx is stuck.
- //
- leftIdx++;
- }
- assert(0);
- return(0);
- } // binary_search_index
-
- /***********************************************************************************************
- * TimeCodedMotionChannelClass::get_index / returns packet index *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 01/27/2000 JGA : Created. *
- *=============================================================================================*/
- uint32 TimeCodedMotionChannelClass::get_index(uint32 timecode)
- {
- assert(CachedIdx <= LastTimeCodeIdx);
- uint32 time;
- time = Data[CachedIdx] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
- if (timecode >= time) {
- // possibly in the current packet
- // special case for end packets
- if (CachedIdx == LastTimeCodeIdx) return(CachedIdx);
- time = Data[CachedIdx + PacketSize] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
- if (timecode < time) return(CachedIdx);
- // Do one time look-ahead before reverting to a search
- CachedIdx+=PacketSize;
- if (CachedIdx == LastTimeCodeIdx) return(CachedIdx);
- time = Data[CachedIdx + PacketSize] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
- if (timecode < time) return(CachedIdx);
- }
- CachedIdx = binary_search_index( timecode );
- return(CachedIdx);
- } // get_index
-
- /***********************************************************************************************
- * TimeCodedMotionChannelClass::set_identity -- returns an "identity" vector (not really...hmm...) *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/11/1997 GH : Created. *
- *=============================================================================================*/
- void TimeCodedMotionChannelClass::set_identity(float * setvec)
- {
- if (Type == ANIM_CHANNEL_Q) {
- setvec[0] = 0.0f;
- setvec[1] = 0.0f;
- setvec[2] = 0.0f;
- setvec[3] = 1.0f;
- } else {
- setvec[0] = 0.0f;
- }
- } // set_identity
- /***********************************************************************************************
- * TimeCodedBitChannelClass::TimeCodedBitChannelClass -- Constructor for BitChannelClass *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- *=============================================================================================*/
- TimeCodedBitChannelClass::TimeCodedBitChannelClass(void) :
- PivotIdx(0),
- Type(0),
- DefaultVal(0),
- Bits(NULL),
- CachedIdx(0)
- {
- }
- /***********************************************************************************************
- * TimeCodedBitChannelClass::~TimeCodedBitChannelClass -- Destructor for BitChannelClass *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/21/98 GTH : Created. *
- *=============================================================================================*/
- TimeCodedBitChannelClass::~TimeCodedBitChannelClass(void)
- {
- Free();
- }
- /***********************************************************************************************
- * TimeCodedBitChannelClass::Free -- Free all "external" memory in use *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/21/98 GTH : Created. *
- *=============================================================================================*/
- void TimeCodedBitChannelClass::Free(void)
- {
- if (Bits != NULL) {
- delete[] Bits;
- Bits = NULL;
- }
- }
- /***********************************************************************************************
- * TimeCodedBitChannelClass::Load -- Read a bit channel from a w3d chunk *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/21/98 GTH : Created. *
- *=============================================================================================*/
- bool TimeCodedBitChannelClass::Load_W3D(ChunkLoadClass & cload)
- {
- Free();
-
- int chunk_size = cload.Cur_Chunk_Length();
- W3dTimeCodedBitChannelStruct chan;
- if (cload.Read(&chan,sizeof(W3dTimeCodedBitChannelStruct)) != sizeof(W3dTimeCodedBitChannelStruct)) {
- return false;
- }
-
- NumTimeCodes = chan.NumTimeCodes;
- Type = chan.Flags;
- PivotIdx = chan.Pivot;
- DefaultVal = chan.DefaultVal;
- CachedIdx = 0;
- uint32 bytesleft = (NumTimeCodes - 1) * sizeof(uint32);
- assert((sizeof(W3dTimeCodedBitChannelStruct) + bytesleft) == (unsigned)chunk_size);
- Bits = MSGW3DNEWARRAY("TimeCodedBitChannelClass::Bits") uint32[NumTimeCodes];
- assert(Bits);
- Bits[0] = chan.Data[0];
-
- if (bytesleft > 0) {
- if (cload.Read(&(Bits[1]),bytesleft) != bytesleft) {
- Free();
- return false;
- }
- }
- return true;
- } // Load_W3D
- /***********************************************************************************************
- * TimeCodedBitChannelClass::Get_Bit -- Lookup a bit in the bit channel *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/21/98 GTH : Created. *
- *=============================================================================================*/
- int TimeCodedBitChannelClass::Get_Bit(int frame)
- {
- assert(frame >= 0);
- assert(CachedIdx < NumTimeCodes);
- int time;
- int idx=0;
- time = Bits[CachedIdx] & ~W3D_TIMECODED_BIT_MASK;
-
- if (frame >= time) {
-
- // start from here
- idx = CachedIdx+1;
- }
- for (;idx < (int) NumTimeCodes ; idx++) {
-
- time = Bits[idx] &~W3D_TIMECODED_BIT_MASK;
-
- if (frame < time) break;
-
- }
-
- idx--;
-
- if (idx < 0) idx = 0;
-
- CachedIdx = idx;
- return (((Bits[idx] & W3D_TIMECODED_BIT_MASK) == W3D_TIMECODED_BIT_MASK));
-
- } // Get_Bit
- // Begin Adaptive Delta
- /***********************************************************************************************
- * AdaptiveDeltaMotionChannelClass::AdaptiveDeltaMotionChannelClass -- constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 02/18/2000 JGA : Created. *
- *=============================================================================================*/
- AdaptiveDeltaMotionChannelClass::AdaptiveDeltaMotionChannelClass(void) :
- PivotIdx(0),
- Type(0),
- VectorLen(0),
- Data(NULL),
- NumFrames(0),
- CacheData(NULL),
- Scale(0.0f)
- {
- if (false == table_valid) {
- // Create Filter Table, used in delta compression
- for (int i=0; i<FILTER_TABLE_GEN_SIZE; i++)
- {
- float ratio = i;
- //ratio = ((ratio + 1.0f) / 128.0f);
- ratio/=((float) FILTER_TABLE_GEN_SIZE);
- filtertable[i + FILTER_TABLE_GEN_START] = 1.0f - WWMath::Sin( DEG_TO_RAD(90.0f * ratio));
- }
- table_valid = true;
- }
- }
- /***********************************************************************************************
- * MotionChannelClass::~MotionChannelClass -- destructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 02/18/1000 JGA : Created. *
- *=============================================================================================*/
- AdaptiveDeltaMotionChannelClass::~AdaptiveDeltaMotionChannelClass(void)
- {
- Free();
- }
- /***********************************************************************************************
- * AdaptiveDeltaMotionChannelClass::Free -- de-allocates all memory in use *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 02/18/2000 JGA : Created. *
- *=============================================================================================*/
- void AdaptiveDeltaMotionChannelClass::Free(void)
- {
- if (Data) {
- delete[] Data;
- Data = NULL;
- }
- if (CacheData) {
- delete CacheData;
- CacheData = NULL;
- }
- } // Free
- /***********************************************************************************************
- * AdaptiveDeltaMotionChannelClass::Load -- loads a motion channel from a file *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 02/18/2000 JGA : Created. *
- *=============================================================================================*/
- bool AdaptiveDeltaMotionChannelClass::Load_W3D(ChunkLoadClass & cload)
- {
- int size = cload.Cur_Chunk_Length();
- unsigned int datasize = size - sizeof(W3dAdaptiveDeltaAnimChannelStruct);
- unsigned int numInts = (datasize / sizeof(uint32)) + 1;
- W3dAdaptiveDeltaAnimChannelStruct chan;
- if (cload.Read(&chan,sizeof(W3dAdaptiveDeltaAnimChannelStruct)) != sizeof(W3dAdaptiveDeltaAnimChannelStruct)) {
- return false;
- }
-
- VectorLen = chan.VectorLen;
- Type = chan.Flags;
- PivotIdx = chan.Pivot;
- NumFrames = chan.NumFrames;
- Scale = chan.Scale;
- CacheFrame = 0x7FFFFFFF; // a big number, so we know its not valid
- CacheData = MSGW3DNEWARRAY("AdaptiveDeltaMotionChannelClass::CacheData") float[VectorLen * 2]; // cacheframe & cachedframe+1 by VectorLen
- Data = MSGW3DNEWARRAY("AdaptiveDeltaMotionChannelClass::Data") uint32[numInts];
- Data[0] = chan.Data[0];
-
- if (cload.Read(&(Data[1]), datasize) != datasize) {
- Free();
- return false;
- }
- return true;
- } // Load_W3D
- /***********************************************************************************************
- * AdaptiveDeltaMotionChannelClass::decompress *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 02/23/2000 JGA : Created. *
- *=============================================================================================*/
- #define PACKET_SIZE (9)
- void AdaptiveDeltaMotionChannelClass::decompress(uint32 frame_idx, float *outdata)
- {
- // Start Over from the beginning
- float *base = (float *) &Data[0]; // pointer to our true know beginning values
- bool done = false;
- for(int vi=0; vi<VectorLen; vi++) {
- // Decompress all the vector indices, since they will probably all be needed
- unsigned char *pPacket = (unsigned char *) Data; // pointer to current packet
- pPacket+= (sizeof(float) * VectorLen); // skip non-compressed header information
- pPacket+= PACKET_SIZE * vi; // skip to the appropriate packet start
- float last_value = base[vi];
- for (uint32 frame=1; frame<=frame_idx;) {
- // Frame Loop
- uint32 filter_index = *pPacket; // packet header
- pPacket++; // skip to nybble compressed data
- float filter = filtertable[filter_index] * Scale; // decompression filter
- // data is grouped in sets of 16 nybbles
- for (int fi=0; fi < 16; fi++) {
- int pi = fi>>1; // create packet index
-
- int factor; // factor, contains extracted nybble -8 to +7
- if (fi & 1) {
- factor = pPacket[pi];
- factor>>=4;
- }
- else {
- factor = pPacket[pi];
- }
- // Sign Extend
- factor &=0xF;
- if (factor & 0x8) {
- factor |= 0xFFFFFFF0;
- }
- // Convert to Floating Point
-
- float ffactor = factor;
- float delta = ffactor * filter;
- last_value+=delta;
- if (frame == frame_idx) {
- done = true;
- break;
- }
- frame++;
- } // for fi < 16
- if (done) break; // we're at the desired frame
- pPacket+= ((PACKET_SIZE * VectorLen) - 1); // skip to next packet
- } // for frame_idx
-
- outdata[vi] = last_value;
- } // for vi=0; vi < 4
- } // decompress, from beginning
-
- void AdaptiveDeltaMotionChannelClass::decompress(uint32 src_idx, float *srcdata, uint32 frame_idx, float *outdata)
- {
- // Contine decompressing from src_idx, up to frame_idx
-
- assert(src_idx < frame_idx);
- src_idx++;
-
- float *base = (float *) &Data[0]; // pointer to our true know beginning values
- base += VectorLen; // skip header information
- bool done = false;
- for(int vi=0; vi<VectorLen; vi++) {
- // Decompress all the vector indices, since they will probably all be needed
- unsigned char *pPacket = (unsigned char *) base; // pointer to current packet
- pPacket+= PACKET_SIZE * vi; // skip to the appropriate packet start
- pPacket+= (PACKET_SIZE * VectorLen) * ((src_idx-1)>>4); // skip out to current packet
-
- // initial filter index
- int fi = (src_idx-1) & 0xF;
-
- float last_value = srcdata[vi];
- for (uint32 frame=src_idx; frame<=frame_idx;) {
- // Frame Loop
- uint32 filter_index = *pPacket; // packet header
- pPacket++; // skip to nybble compressed data
- float filter = filtertable[filter_index] * Scale; // decompression filter
- // data is grouped in sets of 16 nybbles
- for (fi; fi < 16; fi++) {
- int pi = fi>>1; // create packet index
-
- int factor; // factor, contains extracted nybble -8 to +7
- if (fi & 1) {
- factor = pPacket[pi];
- factor>>=4;
- }
- else {
- factor = pPacket[pi];
- }
- // Sign Extend
- factor &=0xF;
- if (factor & 0x8) {
- factor |= 0xFFFFFFF0;
- }
- // Convert to Floating Point
-
- float ffactor = factor;
- float delta = ffactor * filter;
- last_value+=delta;
- if (frame == frame_idx) {
- done = true;
- break;
- }
- frame++;
- } // for fi < 16
- fi = 0;
- if (done) break; // we're at the desired frame
- pPacket+= ((PACKET_SIZE * VectorLen) - 1); // skip to next packet
- } // for frame_idx
-
- outdata[vi] = last_value;
- } // for vi=0; vi < 4
-
- } // decompress, from continuation
-
- /***********************************************************************************************
- * AdaptiveDeltaMotionChannelClass::getframe returns decompressed data for frame/vectorindex *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 02/18/2000 JGA : Created. *
- *=============================================================================================*/
- float AdaptiveDeltaMotionChannelClass::getframe(uint32 frame_idx, uint32 vector_idx)
- {
- // Make sure frame_idx is valid
- if (frame_idx >= NumFrames) frame_idx = NumFrames - 1;
- // Check to see if the data is already in cache?
- if (CacheFrame == frame_idx) {
- return(CacheData[vector_idx]);
- }
- if ((CacheFrame+1) == frame_idx) {
- return(CacheData[vector_idx + VectorLen]);
- }
-
- if (frame_idx < CacheFrame) {
- // Requested Frame isn't cached, so cache it, and frame_idx+1, and return the decompressed data
- // from frame_idx
-
- decompress(frame_idx, &CacheData[0]);
-
- if (frame_idx != (NumFrames - 1)) {
- decompress(frame_idx, &CacheData[0], frame_idx+1, &CacheData[VectorLen]);
- }
-
- CacheFrame = frame_idx;
-
- return(CacheData[vector_idx]);
- }
-
- // Copy last known Cached data down
-
- if (frame_idx == (CacheFrame + 2)) {
-
- // Sliding window
- memcpy(&CacheData[0], &CacheData[VectorLen], VectorLen * sizeof(float));
-
- CacheFrame++;
-
- decompress(CacheFrame, &CacheData[0], frame_idx, &CacheData[VectorLen]);
-
- return(CacheData[VectorLen + vector_idx]);
- }
-
- // Else just use last known frame to decompress forwards
-
- assert(VectorLen <= 4);
-
- float temp[4];
-
- memcpy(&temp[0], &CacheData[VectorLen], VectorLen * sizeof(float));
-
- decompress(CacheFrame, &temp[0], frame_idx, &CacheData[0]);
- CacheFrame = frame_idx;
-
- if (frame_idx != (NumFrames - 1)) {
- decompress(CacheFrame, &CacheData[0], frame_idx+1, &CacheData[VectorLen]);
- }
-
- return(CacheData[vector_idx]);
- } // getframe
- /***********************************************************************************************
- * AdaptiveDeltaMotionChannelClass::Get_Vector -- returns the vector for the specified frame # *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 02/18/2000 JGA : Created. *
- *=============================================================================================*/
- void AdaptiveDeltaMotionChannelClass::Get_Vector(float32 frame,float * setvec)
- {
- uint32 frame1 = frame;
-
- float ratio = frame - frame1;
- float value1 = getframe(frame1);
- float value2 = getframe(frame1 + 1);
- *setvec = WWMath::Lerp(value1,value2,ratio);
- } // Get_Vector
- //
- // Special Case Quats, so we can use Slerp
- //
- Quaternion AdaptiveDeltaMotionChannelClass::Get_QuatVector(float32 frame)
- {
- uint32 frame1 = frame;
- uint32 frame2 = frame1+1;
- float ratio = frame - frame1;
- Quaternion q1(1);
- q1.Set( getframe(frame1, 0),
- getframe(frame1, 1),
- getframe(frame1, 2),
- getframe(frame1, 3) );
- Quaternion q2(1);
- q2.Set( getframe(frame2, 0),
- getframe(frame2, 1),
- getframe(frame2, 2),
- getframe(frame2, 3) );
- Quaternion q(1);
- Fast_Slerp(q, q1, q2, ratio);
- return( q );
- } // Get_QuatVector
- // EOF - motchan.cpp
|