motchan.cpp 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: /Commando/Code/ww3d2/motchan.cpp 3 5/05/01 7:10p Jani_p $ */
  19. /***********************************************************************************************
  20. *** Confidential - Westwood Studios ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Commando / G 3D Library *
  24. * *
  25. * $Archive:: /Commando/Code/ww3d2/motchan.cpp $*
  26. * *
  27. * Author:: Greg_h *
  28. * *
  29. * $Modtime:: 5/05/01 6:28p $*
  30. * *
  31. * $Revision:: 3 $*
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * MotionChannelClass::MotionChannelClass -- constructor *
  36. * MotionChannelClass::~MotionChannelClass -- destructor *
  37. * MotionChannelClass::Free -- de-allocates all memory in use *
  38. * MotionChannelClass::Load -- loads a motion channel from a file *
  39. * BitChannelClass::BitChannelClass -- Constructor for BitChannelClass *
  40. * BitChannelClass::~BitChannelClass -- Destructor for BitChannelClass *
  41. * BitChannelClass::Free -- Free all "external" memory in use *
  42. * BitChannelClass::Load -- Read a bit channel from a w3d chunk *
  43. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  44. #include "motchan.h"
  45. #include "w3d_file.h"
  46. #include "chunkio.h"
  47. #include "vector.h"
  48. #include "wwmath.h"
  49. #include "quat.h"
  50. // Static Table, for Adaptive Delta Decompressor
  51. #define FILTER_TABLE_SIZE (256)
  52. #define FILTER_TABLE_GEN_START (16)
  53. #define FILTER_TABLE_GEN_SIZE (FILTER_TABLE_SIZE - FILTER_TABLE_GEN_START)
  54. static float filtertable[FILTER_TABLE_SIZE] = {
  55. 0.00000001f,
  56. 0.0000001f,
  57. 0.000001f,
  58. 0.00001f,
  59. 0.0001f,
  60. 0.001f,
  61. 0.01f,
  62. 0.1f,
  63. 1.0f,
  64. 10.0f,
  65. 100.0f,
  66. 1000.0f,
  67. 10000.0f,
  68. 100000.0f,
  69. 1000000.0f,
  70. 10000000.0f,
  71. };
  72. static bool table_valid = false;
  73. /***********************************************************************************************
  74. * MotionChannelClass::MotionChannelClass -- constructor *
  75. * *
  76. * INPUT: *
  77. * *
  78. * OUTPUT: *
  79. * *
  80. * WARNINGS: *
  81. * *
  82. * HISTORY: *
  83. * 08/11/1997 GH : Created. *
  84. *=============================================================================================*/
  85. MotionChannelClass::MotionChannelClass(void) :
  86. PivotIdx(0),
  87. Type(0),
  88. VectorLen(0),
  89. Data(NULL),
  90. FirstFrame(-1),
  91. LastFrame(-1)
  92. {
  93. }
  94. /***********************************************************************************************
  95. * MotionChannelClass::~MotionChannelClass -- destructor *
  96. * *
  97. * INPUT: *
  98. * *
  99. * OUTPUT: *
  100. * *
  101. * WARNINGS: *
  102. * *
  103. * HISTORY: *
  104. * 08/11/1997 GH : Created. *
  105. *=============================================================================================*/
  106. MotionChannelClass::~MotionChannelClass(void)
  107. {
  108. Free();
  109. }
  110. /***********************************************************************************************
  111. * MotionChannelClass::Free -- de-allocates all memory in use *
  112. * *
  113. * INPUT: *
  114. * *
  115. * OUTPUT: *
  116. * *
  117. * WARNINGS: *
  118. * *
  119. * HISTORY: *
  120. * 08/11/1997 GH : Created. *
  121. *=============================================================================================*/
  122. void MotionChannelClass::Free(void)
  123. {
  124. if (Data) {
  125. delete[] Data;
  126. Data = NULL;
  127. }
  128. }
  129. /***********************************************************************************************
  130. * MotionChannelClass::Load -- loads a motion channel from a file *
  131. * *
  132. * INPUT: *
  133. * *
  134. * OUTPUT: *
  135. * *
  136. * WARNINGS: *
  137. * *
  138. * HISTORY: *
  139. * 08/11/1997 GH : Created. *
  140. *=============================================================================================*/
  141. bool MotionChannelClass::Load_W3D(ChunkLoadClass & cload)
  142. {
  143. int size = cload.Cur_Chunk_Length();
  144. unsigned int datasize = (size - sizeof(W3dAnimChannelStruct));
  145. unsigned int num_floats = (datasize / sizeof(float32)) + 1;
  146. W3dAnimChannelStruct chan;
  147. if (cload.Read(&chan,sizeof(W3dAnimChannelStruct)) != sizeof(W3dAnimChannelStruct)) {
  148. return false;
  149. }
  150. FirstFrame = chan.FirstFrame;
  151. LastFrame = chan.LastFrame;
  152. VectorLen = chan.VectorLen;
  153. Type = chan.Flags;
  154. PivotIdx = chan.Pivot;
  155. Data = MSGW3DNEWARRAY("MotionChannelClass::Data") float32[num_floats];
  156. Data[0] = chan.Data[0];
  157. if (cload.Read(&(Data[1]),datasize) != datasize) {
  158. Free();
  159. return false;
  160. }
  161. return true;
  162. }
  163. /***********************************************************************************************
  164. * BitChannelClass::BitChannelClass -- Constructor for BitChannelClass *
  165. * *
  166. * INPUT: *
  167. * *
  168. * OUTPUT: *
  169. * *
  170. * WARNINGS: *
  171. * *
  172. * HISTORY: *
  173. *=============================================================================================*/
  174. BitChannelClass::BitChannelClass(void) :
  175. PivotIdx(0),
  176. Type(0),
  177. DefaultVal(0),
  178. FirstFrame(-1),
  179. LastFrame(-1),
  180. Bits(NULL)
  181. {
  182. }
  183. /***********************************************************************************************
  184. * BitChannelClass::~BitChannelClass -- Destructor for BitChannelClass *
  185. * *
  186. * INPUT: *
  187. * *
  188. * OUTPUT: *
  189. * *
  190. * WARNINGS: *
  191. * *
  192. * HISTORY: *
  193. * 1/21/98 GTH : Created. *
  194. *=============================================================================================*/
  195. BitChannelClass::~BitChannelClass(void)
  196. {
  197. Free();
  198. }
  199. /***********************************************************************************************
  200. * BitChannelClass::Free -- Free all "external" memory in use *
  201. * *
  202. * INPUT: *
  203. * *
  204. * OUTPUT: *
  205. * *
  206. * WARNINGS: *
  207. * *
  208. * HISTORY: *
  209. * 1/21/98 GTH : Created. *
  210. *=============================================================================================*/
  211. void BitChannelClass::Free(void)
  212. {
  213. if (Bits != NULL) {
  214. delete[] Bits;
  215. Bits = NULL;
  216. }
  217. }
  218. /***********************************************************************************************
  219. * BitChannelClass::Load -- Read a bit channel from a w3d chunk *
  220. * *
  221. * INPUT: *
  222. * *
  223. * OUTPUT: *
  224. * *
  225. * WARNINGS: *
  226. * *
  227. * HISTORY: *
  228. * 1/21/98 GTH : Created. *
  229. *=============================================================================================*/
  230. bool BitChannelClass::Load_W3D(ChunkLoadClass & cload)
  231. {
  232. Free();
  233. int chunk_size = cload.Cur_Chunk_Length();
  234. W3dBitChannelStruct chan;
  235. if (cload.Read(&chan,sizeof(W3dBitChannelStruct)) != sizeof(W3dBitChannelStruct)) {
  236. return false;
  237. }
  238. FirstFrame = chan.FirstFrame;
  239. LastFrame = chan.LastFrame;
  240. Type = chan.Flags;
  241. PivotIdx = chan.Pivot;
  242. DefaultVal = chan.DefaultVal;
  243. uint32 numbits = LastFrame - FirstFrame + 1;
  244. uint32 numbytes = (numbits + 7) / 8;
  245. uint32 bytesleft = numbytes - 1;
  246. assert((sizeof(W3dBitChannelStruct) + bytesleft) == (unsigned)chunk_size);
  247. Bits = MSGW3DNEWARRAY("BitChannelClass::Bits") uint8[numbytes];
  248. assert(Bits);
  249. Bits[0] = chan.Data[0];
  250. if (bytesleft > 0) {
  251. if (cload.Read(&(Bits[1]),bytesleft) != bytesleft) {
  252. Free();
  253. return false;
  254. }
  255. }
  256. return true;
  257. }
  258. /***********************************************************************************************
  259. * TimeCodedMotionChannelClass::TimeCodedMotionChannelClass -- constructor *
  260. * *
  261. * INPUT: *
  262. * *
  263. * OUTPUT: *
  264. * *
  265. * WARNINGS: *
  266. * *
  267. * HISTORY: *
  268. * 08/11/1997 GH : Created. *
  269. *=============================================================================================*/
  270. TimeCodedMotionChannelClass::TimeCodedMotionChannelClass(void) :
  271. PivotIdx(0),
  272. Type(0),
  273. VectorLen(0),
  274. PacketSize(0),
  275. Data(NULL),
  276. NumTimeCodes(0),
  277. LastTimeCodeIdx(0), // absolute index to last time code
  278. CachedIdx(0) // Last Index Used
  279. {
  280. }
  281. /***********************************************************************************************
  282. * MotionChannelClass::~MotionChannelClass -- destructor *
  283. * *
  284. * INPUT: *
  285. * *
  286. * OUTPUT: *
  287. * *
  288. * WARNINGS: *
  289. * *
  290. * HISTORY: *
  291. * 08/11/1997 GH : Created. *
  292. *=============================================================================================*/
  293. TimeCodedMotionChannelClass::~TimeCodedMotionChannelClass(void)
  294. {
  295. Free();
  296. }
  297. /***********************************************************************************************
  298. * TimeCodedMotionChannelClass::Free -- de-allocates all memory in use *
  299. * *
  300. * INPUT: *
  301. * *
  302. * OUTPUT: *
  303. * *
  304. * WARNINGS: *
  305. * *
  306. * HISTORY: *
  307. * 08/11/1997 GH : Created. *
  308. *=============================================================================================*/
  309. void TimeCodedMotionChannelClass::Free(void)
  310. {
  311. if (Data) {
  312. delete[] Data;
  313. Data = NULL;
  314. }
  315. }
  316. /***********************************************************************************************
  317. * TimeCodedMotionChannelClass::Load -- loads a motion channel from a file *
  318. * *
  319. * INPUT: *
  320. * *
  321. * OUTPUT: *
  322. * *
  323. * WARNINGS: *
  324. * *
  325. * HISTORY: *
  326. * 08/11/1997 GH : Created. *
  327. *=============================================================================================*/
  328. bool TimeCodedMotionChannelClass::Load_W3D(ChunkLoadClass & cload)
  329. {
  330. int size = cload.Cur_Chunk_Length();
  331. unsigned int datasize = size - sizeof(W3dTimeCodedAnimChannelStruct);
  332. unsigned int numInts = (datasize / sizeof(uint32)) + 1;
  333. W3dTimeCodedAnimChannelStruct chan;
  334. if (cload.Read(&chan,sizeof(W3dTimeCodedAnimChannelStruct)) != sizeof(W3dTimeCodedAnimChannelStruct)) {
  335. return false;
  336. }
  337. NumTimeCodes = chan.NumTimeCodes;
  338. VectorLen = chan.VectorLen;
  339. Type = chan.Flags;
  340. PivotIdx = chan.Pivot;
  341. PacketSize = VectorLen+1;
  342. CachedIdx = 0;
  343. LastTimeCodeIdx = (NumTimeCodes-1) * PacketSize;
  344. Data = MSGW3DNEWARRAY("TimeCodedMotionChannelClass::Data") uint32[numInts];
  345. Data[0] = chan.Data[0];
  346. if (cload.Read(&(Data[1]), datasize) != datasize) {
  347. Free();
  348. return false;
  349. }
  350. return true;
  351. }
  352. /***********************************************************************************************
  353. * TimeCodedMotionChannelClass::Get_Vector -- returns the vector for the specified frame # *
  354. * *
  355. * INPUT: *
  356. * *
  357. * OUTPUT: *
  358. * *
  359. * WARNINGS: *
  360. * *
  361. * HISTORY: *
  362. * 08/11/1997 GH : Created. *
  363. *=============================================================================================*/
  364. void TimeCodedMotionChannelClass::Get_Vector(float32 frame,float * setvec)
  365. {
  366. uint32 tc0;
  367. tc0 = frame;
  368. uint32 pidx = get_index( tc0 );
  369. uint32 p2idx;
  370. if (pidx == ((NumTimeCodes - 1) * PacketSize)) {
  371. float32 *frm = (float32 *) &Data[pidx+1];
  372. for (int i=0; i < VectorLen; i++) {
  373. setvec[i] = frm[i];
  374. }
  375. return;
  376. }
  377. else {
  378. p2idx = pidx + PacketSize;
  379. }
  380. uint32 time = Data[p2idx];
  381. if (time & W3D_TIMECODED_BINARY_MOVEMENT_FLAG) {
  382. float32 *frm = (float32 *) &Data[pidx+1];
  383. for (int i=0; i < VectorLen; i++) {
  384. setvec[i] = frm[i];
  385. }
  386. return;
  387. }
  388. float32 time1 = (Data[pidx] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
  389. float32 time2 = (time & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
  390. float32 ratio = (frame - time1) / (time2 - time1);
  391. float32 *frame1 = (float32 *) &Data[pidx+1];
  392. float32 *frame2 = (float32 *) &Data[p2idx+1];
  393. for (int i=0; i < VectorLen; i++) {
  394. setvec[i] = WWMath::Lerp(frame1[i],frame2[i],ratio);
  395. }
  396. } // Get_Vector
  397. Quaternion TimeCodedMotionChannelClass::Get_QuatVector(float32 frame)
  398. {
  399. assert(VectorLen == 4);
  400. Quaternion q(1);
  401. uint32 tc0;
  402. tc0 = frame;
  403. uint32 pidx = get_index( tc0 );
  404. uint32 p2idx;
  405. if (pidx == ((NumTimeCodes - 1) * PacketSize)) {
  406. float32 *vec = (float32 *) &Data[pidx+1];
  407. q.Set(vec[0], vec[1], vec[2], vec[3]);
  408. return( q );
  409. }
  410. else {
  411. p2idx = pidx + PacketSize;
  412. }
  413. uint32 time = Data[p2idx];
  414. if (time & W3D_TIMECODED_BINARY_MOVEMENT_FLAG) {
  415. // its a binary movement!
  416. float32 *vec = (float32 *) &Data[pidx+1];
  417. q.Set(vec[0], vec[1], vec[2], vec[3]);
  418. return( q );
  419. }
  420. float32 time1 = (Data[pidx] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
  421. float32 time2 = (time & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
  422. float32 ratio = (frame - time1) / (time2 - time1);
  423. float32 *frame1 = (float32 *) &Data[pidx+1];
  424. float32 *frame2 = (float32 *) &Data[p2idx+1];
  425. Quaternion q1(1);
  426. Quaternion q2(1);
  427. q1.Set(frame1[0], frame1[1], frame1[2], frame1[3]);
  428. q2.Set(frame2[0], frame2[1], frame2[2], frame2[3]);
  429. Fast_Slerp(q, q1, q2, ratio);
  430. return( q );
  431. } // Get_QuatVector
  432. /***********************************************************************************************
  433. * TimeCodedMotionChannelClass::binary_search_index / returns packet index *
  434. * *
  435. * INPUT: *
  436. * *
  437. * OUTPUT: *
  438. * *
  439. * WARNINGS: *
  440. * *
  441. * HISTORY: *
  442. * 01/27/2000 JGA : Created. *
  443. *=============================================================================================*/
  444. // New version that uses a binary search, and no cache
  445. uint32 TimeCodedMotionChannelClass::binary_search_index(uint32 timecode)
  446. {
  447. int leftIdx = 0;
  448. int rightIdx = NumTimeCodes - 2;
  449. int dx;
  450. uint32 time;
  451. int idx = LastTimeCodeIdx; //((rightIdx+1) * PacketSize;)
  452. //int32 LastTimeCodeIdx; // absolute index to last time code
  453. //int32 CachedIdx; // Last Index Used
  454. // special case last packet
  455. time = Data[idx] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
  456. if (timecode >= time) return(idx);
  457. for (;;) {
  458. dx = rightIdx - leftIdx;
  459. dx>>=1; // divide by 2
  460. dx += leftIdx;
  461. idx = dx * PacketSize;
  462. time = Data[idx] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
  463. if (timecode < time) {
  464. rightIdx = dx;
  465. continue;
  466. }
  467. time = Data[idx + PacketSize] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
  468. if (timecode < time) return(idx);
  469. if (leftIdx ^ dx) {
  470. leftIdx = dx;
  471. continue;
  472. }
  473. //
  474. // if leftIdx == dx prior to assignment, then leftIdx is stuck.
  475. //
  476. leftIdx++;
  477. }
  478. assert(0);
  479. return(0);
  480. } // binary_search_index
  481. /***********************************************************************************************
  482. * TimeCodedMotionChannelClass::get_index / returns packet index *
  483. * *
  484. * INPUT: *
  485. * *
  486. * OUTPUT: *
  487. * *
  488. * WARNINGS: *
  489. * *
  490. * HISTORY: *
  491. * 01/27/2000 JGA : Created. *
  492. *=============================================================================================*/
  493. uint32 TimeCodedMotionChannelClass::get_index(uint32 timecode)
  494. {
  495. assert(CachedIdx <= LastTimeCodeIdx);
  496. uint32 time;
  497. time = Data[CachedIdx] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
  498. if (timecode >= time) {
  499. // possibly in the current packet
  500. // special case for end packets
  501. if (CachedIdx == LastTimeCodeIdx) return(CachedIdx);
  502. time = Data[CachedIdx + PacketSize] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
  503. if (timecode < time) return(CachedIdx);
  504. // Do one time look-ahead before reverting to a search
  505. CachedIdx+=PacketSize;
  506. if (CachedIdx == LastTimeCodeIdx) return(CachedIdx);
  507. time = Data[CachedIdx + PacketSize] & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG;
  508. if (timecode < time) return(CachedIdx);
  509. }
  510. CachedIdx = binary_search_index( timecode );
  511. return(CachedIdx);
  512. } // get_index
  513. /***********************************************************************************************
  514. * TimeCodedMotionChannelClass::set_identity -- returns an "identity" vector (not really...hmm...) *
  515. * *
  516. * INPUT: *
  517. * *
  518. * OUTPUT: *
  519. * *
  520. * WARNINGS: *
  521. * *
  522. * HISTORY: *
  523. * 08/11/1997 GH : Created. *
  524. *=============================================================================================*/
  525. void TimeCodedMotionChannelClass::set_identity(float * setvec)
  526. {
  527. if (Type == ANIM_CHANNEL_Q) {
  528. setvec[0] = 0.0f;
  529. setvec[1] = 0.0f;
  530. setvec[2] = 0.0f;
  531. setvec[3] = 1.0f;
  532. } else {
  533. setvec[0] = 0.0f;
  534. }
  535. } // set_identity
  536. /***********************************************************************************************
  537. * TimeCodedBitChannelClass::TimeCodedBitChannelClass -- Constructor for BitChannelClass *
  538. * *
  539. * INPUT: *
  540. * *
  541. * OUTPUT: *
  542. * *
  543. * WARNINGS: *
  544. * *
  545. * HISTORY: *
  546. *=============================================================================================*/
  547. TimeCodedBitChannelClass::TimeCodedBitChannelClass(void) :
  548. PivotIdx(0),
  549. Type(0),
  550. DefaultVal(0),
  551. Bits(NULL),
  552. CachedIdx(0)
  553. {
  554. }
  555. /***********************************************************************************************
  556. * TimeCodedBitChannelClass::~TimeCodedBitChannelClass -- Destructor for BitChannelClass *
  557. * *
  558. * INPUT: *
  559. * *
  560. * OUTPUT: *
  561. * *
  562. * WARNINGS: *
  563. * *
  564. * HISTORY: *
  565. * 1/21/98 GTH : Created. *
  566. *=============================================================================================*/
  567. TimeCodedBitChannelClass::~TimeCodedBitChannelClass(void)
  568. {
  569. Free();
  570. }
  571. /***********************************************************************************************
  572. * TimeCodedBitChannelClass::Free -- Free all "external" memory in use *
  573. * *
  574. * INPUT: *
  575. * *
  576. * OUTPUT: *
  577. * *
  578. * WARNINGS: *
  579. * *
  580. * HISTORY: *
  581. * 1/21/98 GTH : Created. *
  582. *=============================================================================================*/
  583. void TimeCodedBitChannelClass::Free(void)
  584. {
  585. if (Bits != NULL) {
  586. delete[] Bits;
  587. Bits = NULL;
  588. }
  589. }
  590. /***********************************************************************************************
  591. * TimeCodedBitChannelClass::Load -- Read a bit channel from a w3d chunk *
  592. * *
  593. * INPUT: *
  594. * *
  595. * OUTPUT: *
  596. * *
  597. * WARNINGS: *
  598. * *
  599. * HISTORY: *
  600. * 1/21/98 GTH : Created. *
  601. *=============================================================================================*/
  602. bool TimeCodedBitChannelClass::Load_W3D(ChunkLoadClass & cload)
  603. {
  604. Free();
  605. int chunk_size = cload.Cur_Chunk_Length();
  606. W3dTimeCodedBitChannelStruct chan;
  607. if (cload.Read(&chan,sizeof(W3dTimeCodedBitChannelStruct)) != sizeof(W3dTimeCodedBitChannelStruct)) {
  608. return false;
  609. }
  610. NumTimeCodes = chan.NumTimeCodes;
  611. Type = chan.Flags;
  612. PivotIdx = chan.Pivot;
  613. DefaultVal = chan.DefaultVal;
  614. CachedIdx = 0;
  615. uint32 bytesleft = (NumTimeCodes - 1) * sizeof(uint32);
  616. assert((sizeof(W3dTimeCodedBitChannelStruct) + bytesleft) == (unsigned)chunk_size);
  617. Bits = MSGW3DNEWARRAY("TimeCodedBitChannelClass::Bits") uint32[NumTimeCodes];
  618. assert(Bits);
  619. Bits[0] = chan.Data[0];
  620. if (bytesleft > 0) {
  621. if (cload.Read(&(Bits[1]),bytesleft) != bytesleft) {
  622. Free();
  623. return false;
  624. }
  625. }
  626. return true;
  627. } // Load_W3D
  628. /***********************************************************************************************
  629. * TimeCodedBitChannelClass::Get_Bit -- Lookup a bit in the bit channel *
  630. * *
  631. * INPUT: *
  632. * *
  633. * OUTPUT: *
  634. * *
  635. * WARNINGS: *
  636. * *
  637. * HISTORY: *
  638. * 1/21/98 GTH : Created. *
  639. *=============================================================================================*/
  640. int TimeCodedBitChannelClass::Get_Bit(int frame)
  641. {
  642. assert(frame >= 0);
  643. assert(CachedIdx < NumTimeCodes);
  644. int time;
  645. int idx=0;
  646. time = Bits[CachedIdx] & ~W3D_TIMECODED_BIT_MASK;
  647. if (frame >= time) {
  648. // start from here
  649. idx = CachedIdx+1;
  650. }
  651. for (;idx < (int) NumTimeCodes ; idx++) {
  652. time = Bits[idx] &~W3D_TIMECODED_BIT_MASK;
  653. if (frame < time) break;
  654. }
  655. idx--;
  656. if (idx < 0) idx = 0;
  657. CachedIdx = idx;
  658. return (((Bits[idx] & W3D_TIMECODED_BIT_MASK) == W3D_TIMECODED_BIT_MASK));
  659. } // Get_Bit
  660. // Begin Adaptive Delta
  661. /***********************************************************************************************
  662. * AdaptiveDeltaMotionChannelClass::AdaptiveDeltaMotionChannelClass -- constructor *
  663. * *
  664. * INPUT: *
  665. * *
  666. * OUTPUT: *
  667. * *
  668. * WARNINGS: *
  669. * *
  670. * HISTORY: *
  671. * 02/18/2000 JGA : Created. *
  672. *=============================================================================================*/
  673. AdaptiveDeltaMotionChannelClass::AdaptiveDeltaMotionChannelClass(void) :
  674. PivotIdx(0),
  675. Type(0),
  676. VectorLen(0),
  677. Data(NULL),
  678. NumFrames(0),
  679. CacheData(NULL),
  680. Scale(0.0f)
  681. {
  682. if (false == table_valid) {
  683. // Create Filter Table, used in delta compression
  684. for (int i=0; i<FILTER_TABLE_GEN_SIZE; i++)
  685. {
  686. float ratio = i;
  687. //ratio = ((ratio + 1.0f) / 128.0f);
  688. ratio/=((float) FILTER_TABLE_GEN_SIZE);
  689. filtertable[i + FILTER_TABLE_GEN_START] = 1.0f - WWMath::Sin( DEG_TO_RAD(90.0f * ratio));
  690. }
  691. table_valid = true;
  692. }
  693. }
  694. /***********************************************************************************************
  695. * MotionChannelClass::~MotionChannelClass -- destructor *
  696. * *
  697. * INPUT: *
  698. * *
  699. * OUTPUT: *
  700. * *
  701. * WARNINGS: *
  702. * *
  703. * HISTORY: *
  704. * 02/18/1000 JGA : Created. *
  705. *=============================================================================================*/
  706. AdaptiveDeltaMotionChannelClass::~AdaptiveDeltaMotionChannelClass(void)
  707. {
  708. Free();
  709. }
  710. /***********************************************************************************************
  711. * AdaptiveDeltaMotionChannelClass::Free -- de-allocates all memory in use *
  712. * *
  713. * INPUT: *
  714. * *
  715. * OUTPUT: *
  716. * *
  717. * WARNINGS: *
  718. * *
  719. * HISTORY: *
  720. * 02/18/2000 JGA : Created. *
  721. *=============================================================================================*/
  722. void AdaptiveDeltaMotionChannelClass::Free(void)
  723. {
  724. if (Data) {
  725. delete[] Data;
  726. Data = NULL;
  727. }
  728. if (CacheData) {
  729. delete CacheData;
  730. CacheData = NULL;
  731. }
  732. } // Free
  733. /***********************************************************************************************
  734. * AdaptiveDeltaMotionChannelClass::Load -- loads a motion channel from a file *
  735. * *
  736. * INPUT: *
  737. * *
  738. * OUTPUT: *
  739. * *
  740. * WARNINGS: *
  741. * *
  742. * HISTORY: *
  743. * 02/18/2000 JGA : Created. *
  744. *=============================================================================================*/
  745. bool AdaptiveDeltaMotionChannelClass::Load_W3D(ChunkLoadClass & cload)
  746. {
  747. int size = cload.Cur_Chunk_Length();
  748. unsigned int datasize = size - sizeof(W3dAdaptiveDeltaAnimChannelStruct);
  749. unsigned int numInts = (datasize / sizeof(uint32)) + 1;
  750. W3dAdaptiveDeltaAnimChannelStruct chan;
  751. if (cload.Read(&chan,sizeof(W3dAdaptiveDeltaAnimChannelStruct)) != sizeof(W3dAdaptiveDeltaAnimChannelStruct)) {
  752. return false;
  753. }
  754. VectorLen = chan.VectorLen;
  755. Type = chan.Flags;
  756. PivotIdx = chan.Pivot;
  757. NumFrames = chan.NumFrames;
  758. Scale = chan.Scale;
  759. CacheFrame = 0x7FFFFFFF; // a big number, so we know its not valid
  760. CacheData = MSGW3DNEWARRAY("AdaptiveDeltaMotionChannelClass::CacheData") float[VectorLen * 2]; // cacheframe & cachedframe+1 by VectorLen
  761. Data = MSGW3DNEWARRAY("AdaptiveDeltaMotionChannelClass::Data") uint32[numInts];
  762. Data[0] = chan.Data[0];
  763. if (cload.Read(&(Data[1]), datasize) != datasize) {
  764. Free();
  765. return false;
  766. }
  767. return true;
  768. } // Load_W3D
  769. /***********************************************************************************************
  770. * AdaptiveDeltaMotionChannelClass::decompress *
  771. * *
  772. * INPUT: *
  773. * *
  774. * OUTPUT: *
  775. * *
  776. * WARNINGS: *
  777. * *
  778. * HISTORY: *
  779. * 02/23/2000 JGA : Created. *
  780. *=============================================================================================*/
  781. #define PACKET_SIZE (9)
  782. void AdaptiveDeltaMotionChannelClass::decompress(uint32 frame_idx, float *outdata)
  783. {
  784. // Start Over from the beginning
  785. float *base = (float *) &Data[0]; // pointer to our true know beginning values
  786. bool done = false;
  787. for(int vi=0; vi<VectorLen; vi++) {
  788. // Decompress all the vector indices, since they will probably all be needed
  789. unsigned char *pPacket = (unsigned char *) Data; // pointer to current packet
  790. pPacket+= (sizeof(float) * VectorLen); // skip non-compressed header information
  791. pPacket+= PACKET_SIZE * vi; // skip to the appropriate packet start
  792. float last_value = base[vi];
  793. for (uint32 frame=1; frame<=frame_idx;) {
  794. // Frame Loop
  795. uint32 filter_index = *pPacket; // packet header
  796. pPacket++; // skip to nybble compressed data
  797. float filter = filtertable[filter_index] * Scale; // decompression filter
  798. // data is grouped in sets of 16 nybbles
  799. for (int fi=0; fi < 16; fi++) {
  800. int pi = fi>>1; // create packet index
  801. int factor; // factor, contains extracted nybble -8 to +7
  802. if (fi & 1) {
  803. factor = pPacket[pi];
  804. factor>>=4;
  805. }
  806. else {
  807. factor = pPacket[pi];
  808. }
  809. // Sign Extend
  810. factor &=0xF;
  811. if (factor & 0x8) {
  812. factor |= 0xFFFFFFF0;
  813. }
  814. // Convert to Floating Point
  815. float ffactor = factor;
  816. float delta = ffactor * filter;
  817. last_value+=delta;
  818. if (frame == frame_idx) {
  819. done = true;
  820. break;
  821. }
  822. frame++;
  823. } // for fi < 16
  824. if (done) break; // we're at the desired frame
  825. pPacket+= ((PACKET_SIZE * VectorLen) - 1); // skip to next packet
  826. } // for frame_idx
  827. outdata[vi] = last_value;
  828. } // for vi=0; vi < 4
  829. } // decompress, from beginning
  830. void AdaptiveDeltaMotionChannelClass::decompress(uint32 src_idx, float *srcdata, uint32 frame_idx, float *outdata)
  831. {
  832. // Contine decompressing from src_idx, up to frame_idx
  833. assert(src_idx < frame_idx);
  834. src_idx++;
  835. float *base = (float *) &Data[0]; // pointer to our true know beginning values
  836. base += VectorLen; // skip header information
  837. bool done = false;
  838. for(int vi=0; vi<VectorLen; vi++) {
  839. // Decompress all the vector indices, since they will probably all be needed
  840. unsigned char *pPacket = (unsigned char *) base; // pointer to current packet
  841. pPacket+= PACKET_SIZE * vi; // skip to the appropriate packet start
  842. pPacket+= (PACKET_SIZE * VectorLen) * ((src_idx-1)>>4); // skip out to current packet
  843. // initial filter index
  844. int fi = (src_idx-1) & 0xF;
  845. float last_value = srcdata[vi];
  846. for (uint32 frame=src_idx; frame<=frame_idx;) {
  847. // Frame Loop
  848. uint32 filter_index = *pPacket; // packet header
  849. pPacket++; // skip to nybble compressed data
  850. float filter = filtertable[filter_index] * Scale; // decompression filter
  851. // data is grouped in sets of 16 nybbles
  852. for (fi; fi < 16; fi++) {
  853. int pi = fi>>1; // create packet index
  854. int factor; // factor, contains extracted nybble -8 to +7
  855. if (fi & 1) {
  856. factor = pPacket[pi];
  857. factor>>=4;
  858. }
  859. else {
  860. factor = pPacket[pi];
  861. }
  862. // Sign Extend
  863. factor &=0xF;
  864. if (factor & 0x8) {
  865. factor |= 0xFFFFFFF0;
  866. }
  867. // Convert to Floating Point
  868. float ffactor = factor;
  869. float delta = ffactor * filter;
  870. last_value+=delta;
  871. if (frame == frame_idx) {
  872. done = true;
  873. break;
  874. }
  875. frame++;
  876. } // for fi < 16
  877. fi = 0;
  878. if (done) break; // we're at the desired frame
  879. pPacket+= ((PACKET_SIZE * VectorLen) - 1); // skip to next packet
  880. } // for frame_idx
  881. outdata[vi] = last_value;
  882. } // for vi=0; vi < 4
  883. } // decompress, from continuation
  884. /***********************************************************************************************
  885. * AdaptiveDeltaMotionChannelClass::getframe returns decompressed data for frame/vectorindex *
  886. * *
  887. * INPUT: *
  888. * *
  889. * OUTPUT: *
  890. * *
  891. * WARNINGS: *
  892. * *
  893. * HISTORY: *
  894. * 02/18/2000 JGA : Created. *
  895. *=============================================================================================*/
  896. float AdaptiveDeltaMotionChannelClass::getframe(uint32 frame_idx, uint32 vector_idx)
  897. {
  898. // Make sure frame_idx is valid
  899. if (frame_idx >= NumFrames) frame_idx = NumFrames - 1;
  900. // Check to see if the data is already in cache?
  901. if (CacheFrame == frame_idx) {
  902. return(CacheData[vector_idx]);
  903. }
  904. if ((CacheFrame+1) == frame_idx) {
  905. return(CacheData[vector_idx + VectorLen]);
  906. }
  907. if (frame_idx < CacheFrame) {
  908. // Requested Frame isn't cached, so cache it, and frame_idx+1, and return the decompressed data
  909. // from frame_idx
  910. decompress(frame_idx, &CacheData[0]);
  911. if (frame_idx != (NumFrames - 1)) {
  912. decompress(frame_idx, &CacheData[0], frame_idx+1, &CacheData[VectorLen]);
  913. }
  914. CacheFrame = frame_idx;
  915. return(CacheData[vector_idx]);
  916. }
  917. // Copy last known Cached data down
  918. if (frame_idx == (CacheFrame + 2)) {
  919. // Sliding window
  920. memcpy(&CacheData[0], &CacheData[VectorLen], VectorLen * sizeof(float));
  921. CacheFrame++;
  922. decompress(CacheFrame, &CacheData[0], frame_idx, &CacheData[VectorLen]);
  923. return(CacheData[VectorLen + vector_idx]);
  924. }
  925. // Else just use last known frame to decompress forwards
  926. assert(VectorLen <= 4);
  927. float temp[4];
  928. memcpy(&temp[0], &CacheData[VectorLen], VectorLen * sizeof(float));
  929. decompress(CacheFrame, &temp[0], frame_idx, &CacheData[0]);
  930. CacheFrame = frame_idx;
  931. if (frame_idx != (NumFrames - 1)) {
  932. decompress(CacheFrame, &CacheData[0], frame_idx+1, &CacheData[VectorLen]);
  933. }
  934. return(CacheData[vector_idx]);
  935. } // getframe
  936. /***********************************************************************************************
  937. * AdaptiveDeltaMotionChannelClass::Get_Vector -- returns the vector for the specified frame # *
  938. * *
  939. * INPUT: *
  940. * *
  941. * OUTPUT: *
  942. * *
  943. * WARNINGS: *
  944. * *
  945. * HISTORY: *
  946. * 02/18/2000 JGA : Created. *
  947. *=============================================================================================*/
  948. void AdaptiveDeltaMotionChannelClass::Get_Vector(float32 frame,float * setvec)
  949. {
  950. uint32 frame1 = frame;
  951. float ratio = frame - frame1;
  952. float value1 = getframe(frame1);
  953. float value2 = getframe(frame1 + 1);
  954. *setvec = WWMath::Lerp(value1,value2,ratio);
  955. } // Get_Vector
  956. //
  957. // Special Case Quats, so we can use Slerp
  958. //
  959. Quaternion AdaptiveDeltaMotionChannelClass::Get_QuatVector(float32 frame)
  960. {
  961. uint32 frame1 = frame;
  962. uint32 frame2 = frame1+1;
  963. float ratio = frame - frame1;
  964. Quaternion q1(1);
  965. q1.Set( getframe(frame1, 0),
  966. getframe(frame1, 1),
  967. getframe(frame1, 2),
  968. getframe(frame1, 3) );
  969. Quaternion q2(1);
  970. q2.Set( getframe(frame2, 0),
  971. getframe(frame2, 1),
  972. getframe(frame2, 2),
  973. getframe(frame2, 3) );
  974. Quaternion q(1);
  975. Fast_Slerp(q, q1, q2, ratio);
  976. return( q );
  977. } // Get_QuatVector
  978. // EOF - motchan.cpp