motchan.cpp 55 KB

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