Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Md3AnimModel.cpp 46KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306
  1. /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
  2. /*================================================================
  3. *
  4. * Project : Freyja
  5. * Author : Terry 'Mongoose' Hendrix II
  6. * Website : http://www.westga.edu/~stu7440/
  7. * Email : stu7440@westga.edu
  8. * Object : Md3AnimModel
  9. * License : No use w/o permission (C) 2002 Mongoose
  10. * Comments: Md3 animation model class
  11. *
  12. *
  13. * This file was generated using Mongoose's C++
  14. * template generator script. <stu7440@westga.edu>
  15. *
  16. *-- History -------------------------------------------------
  17. *
  18. * 2002.06.19:
  19. * Mongoose - Created
  20. =================================================================*/
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <ctype.h>
  25. #ifdef USING_OPENGL
  26. #ifdef __APPLE__
  27. #include <OpenGL/gl.h>
  28. #else
  29. #include <GL/gl.h>
  30. #endif
  31. #endif
  32. #include "hel/math.h"
  33. #include "hel/Quaternion.h"
  34. #include "Md3AnimModel.h"
  35. // Update this with renderer's frame interval
  36. extern unsigned int getTicks();
  37. ////////////////////////////////////////////////////////////
  38. // Constructors
  39. ////////////////////////////////////////////////////////////
  40. Md3AnimModel::Md3AnimModel()
  41. {
  42. mFlags = fAnimate;
  43. initMd3(m_lower, 1);
  44. initMd3(m_upper, 2);
  45. initMd3(m_head, 3);
  46. initMd3(m_weapon, 4);
  47. memset(m_anim, 0, sizeof(md3_animation_t)*32);
  48. m_animCount = 0;
  49. m_sex = MD3_SEX_FEMALE;
  50. texNumTest = 0;
  51. setDebug(1);
  52. }
  53. Md3AnimModel::~Md3AnimModel()
  54. {
  55. }
  56. ////////////////////////////////////////////////////////////
  57. // Public Accessors
  58. ////////////////////////////////////////////////////////////
  59. unsigned int Md3AnimModel::getFlags()
  60. {
  61. return mFlags;
  62. }
  63. md3_animation_id_t Md3AnimModel::getAnimUpper()
  64. {
  65. return m_upperAnim;
  66. }
  67. md3_animation_id_t Md3AnimModel::getAnimLower()
  68. {
  69. return m_lowerAnim;
  70. }
  71. ////////////////////////////////////////////////////////////
  72. // Public Mutators
  73. ////////////////////////////////////////////////////////////
  74. void Md3AnimModel::setFlag(Md3AnimModelFlags flag)
  75. {
  76. mFlags |= flag;
  77. }
  78. void Md3AnimModel::toggleFlag(Md3AnimModelFlags flag)
  79. {
  80. mFlags ^= flag;
  81. }
  82. // Mongoose 2002.06.29, FIXME: Add handler here to avoid
  83. // using animations not loaded
  84. void Md3AnimModel::setAnimUpper(md3_animation_id_t anim)
  85. {
  86. switch (anim)
  87. {
  88. case BOTH_DEATH1:
  89. m_upper.currentAnimation = 0;
  90. break;
  91. case BOTH_DEAD1:
  92. m_upper.currentAnimation = 1;
  93. break;
  94. case BOTH_DEATH2:
  95. m_upper.currentAnimation = 2;
  96. break;
  97. case BOTH_DEAD2:
  98. m_upper.currentAnimation = 3;
  99. break;
  100. case BOTH_DEATH3:
  101. m_upper.currentAnimation = 4;
  102. break;
  103. case BOTH_DEAD3:
  104. m_upper.currentAnimation = 5;
  105. break;
  106. case TORSO_GESTURE:
  107. m_upper.currentAnimation = 6;
  108. break;
  109. case TORSO_ATTACK:
  110. m_upper.currentAnimation = 7;
  111. break;
  112. case TORSO_ATTACK2:
  113. m_upper.currentAnimation = 8;
  114. break;
  115. case TORSO_DROP:
  116. m_upper.currentAnimation = 9;
  117. break;
  118. case TORSO_RAISE:
  119. m_upper.currentAnimation = 10;
  120. break;
  121. case TORSO_STAND:
  122. m_upper.currentAnimation = 11;
  123. break;
  124. case TORSO_STAND2:
  125. m_upper.currentAnimation = 12;
  126. break;
  127. default:
  128. m_upper.currentAnimation = 11;
  129. }
  130. m_upper.currentFrame = m_anim[m_upper.currentAnimation].first_frame;
  131. //m_upper.currentAnimation = anim;
  132. m_upperAnim = anim;
  133. if (anim != (int)m_upper.currentAnimation)
  134. {
  135. printf("ERROR upperAnim %i != %i\n", anim, m_upper.currentAnimation);
  136. }
  137. }
  138. // Mongoose 2002.06.29, FIXME: Add handler here to avoid
  139. // using animations not loaded
  140. void Md3AnimModel::setAnimLower(md3_animation_id_t anim)
  141. {
  142. switch (anim)
  143. {
  144. case BOTH_DEATH1:
  145. setAnimUpper(anim);
  146. m_lower.currentAnimation = 0;
  147. break;
  148. case BOTH_DEAD1:
  149. setAnimUpper(anim);
  150. m_lower.currentAnimation = 1;
  151. break;
  152. case BOTH_DEATH2:
  153. setAnimUpper(anim);
  154. m_lower.currentAnimation = 2;
  155. break;
  156. case BOTH_DEAD2:
  157. setAnimUpper(anim);
  158. m_lower.currentAnimation = 3;
  159. break;
  160. case BOTH_DEATH3:
  161. setAnimUpper(anim);
  162. m_lower.currentAnimation = 4;
  163. break;
  164. case BOTH_DEAD3:
  165. setAnimUpper(anim);
  166. m_lower.currentAnimation = 5;
  167. break;
  168. case LEGS_WALKCR:
  169. m_lower.currentAnimation = 13;
  170. break;
  171. case LEGS_WALK:
  172. m_lower.currentAnimation = 14;
  173. break;
  174. case LEGS_RUN:
  175. m_lower.currentAnimation = 15;
  176. break;
  177. case LEGS_BACK:
  178. m_lower.currentAnimation = 16;
  179. break;
  180. case LEGS_SWIM:
  181. m_lower.currentAnimation = 17;
  182. break;
  183. case LEGS_JUMP:
  184. m_lower.currentAnimation = 18;
  185. break;
  186. case LEGS_LAND:
  187. m_lower.currentAnimation = 19;
  188. break;
  189. case LEGS_JUMPB:
  190. m_lower.currentAnimation = 20;
  191. break;
  192. case LEGS_LANDB:
  193. m_lower.currentAnimation = 21;
  194. break;
  195. case LEGS_IDLE:
  196. m_lower.currentAnimation = 22;
  197. break;
  198. case LEGS_IDLECR:
  199. m_lower.currentAnimation = 23;
  200. break;
  201. case LEGS_TURN:
  202. m_lower.currentAnimation = 24;
  203. break;
  204. default:
  205. m_lower.currentAnimation = 14;
  206. }
  207. m_lower.currentFrame = m_anim[m_lower.currentAnimation].first_frame;
  208. //m_lower.currentAnimation = anim;
  209. m_lowerAnim = anim;
  210. if (anim != (int)m_lower.currentAnimation)
  211. {
  212. printf("ERROR lowerAnim %i != %i\n", anim, m_lower.currentAnimation);
  213. }
  214. }
  215. void Md3AnimModel::setDebug(unsigned char level)
  216. {
  217. m_debug = level;
  218. // Mongoose 2002.06.29, Added to allow new warning level
  219. --level;
  220. m_lower.setDebug(level);
  221. m_upper.setDebug(level);
  222. m_head.setDebug(level);
  223. m_weapon.setDebug(level);
  224. }
  225. int Md3AnimModel::load(char *modelPath, char *skin, md3_lod_t modelLoD)
  226. {
  227. int err = 0;
  228. if (!modelPath || !modelPath[0] || !skin || !skin[0] || modelLoD > 2)
  229. {
  230. return -1;
  231. }
  232. err += loadMd3(m_head, "head", modelPath, skin, modelLoD);
  233. if (err)
  234. {
  235. modelLoD = MD3_LOD_MED;
  236. err = 0;
  237. err += loadMd3(m_head, "head", modelPath, skin, modelLoD);
  238. }
  239. if (err)
  240. {
  241. modelLoD = MD3_LOD_LOW;
  242. err = 0;
  243. err += loadMd3(m_head, "head", modelPath, skin, modelLoD);
  244. }
  245. err += loadMd3(m_upper, "upper", modelPath, skin, modelLoD);
  246. err += loadMd3(m_lower, "lower", modelPath, skin, modelLoD);
  247. // Connect upper to lower with torso tag
  248. connectModels("tag_torso", m_upper, m_lower);
  249. // Connect head to upper
  250. connectModels("tag_head", m_head, m_upper);
  251. loadAnimations(modelPath);
  252. setAnimUpper(TORSO_STAND);
  253. setAnimLower(LEGS_WALK);
  254. if (m_animCount < 24)
  255. {
  256. printf("ERROR: Not all animations loaded %i/24\n", m_animCount);
  257. return -2;
  258. }
  259. return err;
  260. }
  261. int Md3AnimModel::loadWeapon(char *modelPath, char *name)
  262. {
  263. int err = 0;
  264. if (!modelPath || !modelPath[0] || !name || !name[0])
  265. {
  266. return -1;
  267. }
  268. err = loadMd3(m_weapon, name, modelPath, "", MD3_LOD_HIGH);
  269. // Connect weapon to upper
  270. connectModels("tag_weapon", m_weapon, m_upper);
  271. // If they loaded a weapon they prob want to see it
  272. setFlag(fDrawWeapon);
  273. return err;
  274. }
  275. int Md3AnimModel::loadAnimations(char *modelPath)
  276. {
  277. unsigned int firstFrame, numFrames, loopingFrames, framesPerSecond;
  278. FILE *f;
  279. int eof;
  280. md3_animation_id_t id;
  281. unsigned int i = 0,j, state, state2, len;
  282. char buffer[256];
  283. char c, lc;
  284. if (!modelPath || !modelPath[0])
  285. {
  286. return -1;
  287. }
  288. len = strlen(modelPath);
  289. snprintf(buffer, 250, "%s%s", modelPath,
  290. (modelPath[len-1] == '/') ? "animation.cfg" : "/animation.cfg");
  291. buffer[250] = 0;
  292. f = fopen(buffer, "r");
  293. if (!f)
  294. {
  295. perror("Md3AnimModel::loadAnimations> ");
  296. return -1;
  297. }
  298. eof = 0;
  299. i = 0;
  300. c = 0;
  301. buffer[0] = 0;
  302. state = 4;
  303. state2 = 0;
  304. printf("\n");
  305. while (eof != EOF)
  306. {
  307. lc = c;
  308. eof = fscanf(f, "%c", &c);
  309. // Treat EOF like end of line
  310. if (eof == EOF)
  311. {
  312. //if (i && isdigit(buffer[i-1])) c = ' '; else
  313. c = '\n';
  314. }
  315. switch (c)
  316. {
  317. case '/': // Comment?
  318. if (lc == '/')
  319. {
  320. if (state == 4)
  321. {
  322. state = 0;
  323. state2 = 0;
  324. }
  325. else
  326. {
  327. state2 = 1;
  328. }
  329. }
  330. break;
  331. case '\t': // Seperator triggers
  332. case ' ':
  333. if (isdigit(buffer[0]))
  334. {
  335. switch (state)
  336. {
  337. case 0:
  338. firstFrame = atoi(buffer);
  339. ++state;
  340. i = 0;
  341. break;
  342. case 1:
  343. numFrames = atoi(buffer);
  344. ++state;
  345. i = 0;
  346. break;
  347. case 2:
  348. loopingFrames = atoi(buffer);
  349. ++state;
  350. i = 0;
  351. break;
  352. case 3:
  353. framesPerSecond = atoi(buffer);
  354. state = 4; // override comment buffer block
  355. i = 0;
  356. break;
  357. }
  358. }
  359. break;
  360. case '\n': // Seperator EOL trigger
  361. case '\r': // Seperator whitespace
  362. case '\0':
  363. state2 = 0;
  364. if (strncmp("BOTH_", buffer, 5) == 0 ||
  365. strncmp("TORSO_", buffer, 6) == 0 ||
  366. strncmp("LEGS_", buffer, 5) == 0)
  367. {
  368. for (j = 0; j < i; ++j)
  369. {
  370. if (!isdigit(buffer[j]) && !isupper(buffer[j]) &&
  371. buffer[j] != '_')
  372. {
  373. printf("WARNING: Stripping '%s'.\n", buffer);
  374. buffer[j] = 0;
  375. j = i;
  376. }
  377. }
  378. i = 0;
  379. }
  380. else
  381. {
  382. i = 0;
  383. }
  384. if (strncmp("BOTH_", buffer, 5) == 0)
  385. {
  386. if (strncmp("BOTH_DEATH1\0", buffer, 12) == 0)
  387. {
  388. id = BOTH_DEATH1;
  389. }
  390. else if (strncmp("BOTH_DEATH2\0", buffer, 12) == 0)
  391. {
  392. id = BOTH_DEATH2;
  393. }
  394. else if (strncmp("BOTH_DEATH3\0", buffer, 12) == 0)
  395. {
  396. id = BOTH_DEATH3;
  397. }
  398. else if (strncmp("BOTH_DEAD1\0", buffer, 11) == 0)
  399. {
  400. id = BOTH_DEAD1;
  401. }
  402. else if (strncmp("BOTH_DEAD2\0", buffer, 11) == 0)
  403. {
  404. id = BOTH_DEAD2;
  405. }
  406. else if (strncmp("BOTH_DEAD3\0", buffer, 11) == 0)
  407. {
  408. id = BOTH_DEAD3;
  409. }
  410. else
  411. {
  412. id = UNSUPPORTED;
  413. }
  414. if (m_debug > 0)
  415. {
  416. printf("<%s> %3i %3i %3i %3i \t'%s' \t(%i)\n",
  417. (id == UNSUPPORTED) ? "Unsupported" : "",
  418. firstFrame, numFrames,
  419. loopingFrames, framesPerSecond, buffer, id);
  420. }
  421. addAnim(buffer, id, firstFrame, numFrames,
  422. loopingFrames, framesPerSecond);
  423. i = 0;
  424. }
  425. else if (strncmp("TORSO_", buffer, 6) == 0)
  426. {
  427. if (strncmp("TORSO_GESTURE\0", buffer, 14) == 0)
  428. {
  429. id = TORSO_GESTURE;
  430. }
  431. else if (strncmp("TORSO_ATTACK2\0", buffer, 14) == 0)
  432. {
  433. id = TORSO_ATTACK2;
  434. }
  435. else if (strncmp("TORSO_ATTACK\0", buffer, 13) == 0)
  436. {
  437. id = TORSO_ATTACK;
  438. }
  439. else if (strncmp("TORSO_DROP\0", buffer, 11) == 0)
  440. {
  441. id = TORSO_DROP;
  442. }
  443. else if (strncmp("TORSO_RAISE\0", buffer, 12) == 0)
  444. {
  445. id = TORSO_RAISE;
  446. }
  447. else if (strncmp("TORSO_STAND2\0", buffer, 13) == 0)
  448. {
  449. id = TORSO_STAND2;
  450. }
  451. else if (strncmp("TORSO_STAND\0", buffer, 12) == 0)
  452. {
  453. id = TORSO_STAND;
  454. }
  455. else
  456. {
  457. id = UNSUPPORTED;
  458. }
  459. if (m_debug > 0)
  460. {
  461. printf("<%s> %3i %3i %3i %3i \t'%s' (%i)\n",
  462. (id == UNSUPPORTED) ? "Unsupported" : "",
  463. firstFrame, numFrames,
  464. loopingFrames, framesPerSecond, buffer, id);
  465. }
  466. if (id != UNSUPPORTED)
  467. {
  468. addAnim(buffer, id, firstFrame, numFrames,
  469. loopingFrames, framesPerSecond);
  470. }
  471. i = 0;
  472. }
  473. else if (strncmp("LEGS_", buffer, 5) == 0)
  474. {
  475. if (strncmp("LEGS_WALKCR\0", buffer, 12) == 0)
  476. {
  477. id = LEGS_WALKCR;
  478. }
  479. else if (strncmp("LEGS_WALK\0", buffer, 10) == 0)
  480. {
  481. id = LEGS_WALK;
  482. }
  483. else if (strncmp("LEGS_RUN\0", buffer, 9) == 0)
  484. {
  485. id = LEGS_RUN;
  486. }
  487. else if (strncmp("LEGS_BACK\0", buffer, 10) == 0)
  488. {
  489. id = LEGS_BACK;
  490. }
  491. else if (strncmp("LEGS_SWIM\0", buffer, 10) == 0)
  492. {
  493. id = LEGS_SWIM;
  494. }
  495. else if (strncmp("LEGS_JUMPB\0", buffer, 11) == 0)
  496. {
  497. id = LEGS_JUMPB;
  498. }
  499. else if (strncmp("LEGS_LANDB\0", buffer, 11) == 0)
  500. {
  501. id = LEGS_LANDB;
  502. }
  503. else if (strncmp("LEGS_IDLECR\0", buffer, 12) == 0)
  504. {
  505. id = LEGS_IDLECR;
  506. }
  507. else if (strncmp("LEGS_JUMP\0", buffer, 10) == 0)
  508. {
  509. id = LEGS_JUMP;
  510. }
  511. else if (strncmp("LEGS_LAND\0", buffer, 10) == 0)
  512. {
  513. id = LEGS_LAND;
  514. }
  515. else if (strncmp("LEGS_IDLE\0", buffer, 10) == 0)
  516. {
  517. id = LEGS_IDLE;
  518. }
  519. else if (strncmp("LEGS_TURN\0", buffer, 10) == 0)
  520. {
  521. id = LEGS_TURN;
  522. }
  523. else
  524. {
  525. id = UNSUPPORTED;
  526. }
  527. if (m_debug > 0)
  528. {
  529. printf("<%s> %3i %3i %3i %3i \t'%s' (%i)\n",
  530. (id == UNSUPPORTED) ? "Unsupported" : "",
  531. firstFrame, numFrames,
  532. loopingFrames, framesPerSecond, buffer, id);
  533. }
  534. if (id != UNSUPPORTED)
  535. {
  536. addAnim(buffer, id, firstFrame, numFrames,
  537. loopingFrames, framesPerSecond);
  538. }
  539. i = 0;
  540. }
  541. else if (strncmp("sexf", buffer, 4) == 0)
  542. {
  543. m_sex = MD3_SEX_FEMALE;
  544. if (m_debug > 0)
  545. {
  546. printf("<> sex = female\n");
  547. }
  548. i = 0;
  549. }
  550. else if (strncmp("sexm", buffer, 4) == 0)
  551. {
  552. if (m_debug > 0)
  553. {
  554. printf("<> sex = male\n");
  555. }
  556. m_sex = MD3_SEX_MALE;
  557. i = 0;
  558. }
  559. else if (strncmp("sexn", buffer, 4) == 0)
  560. {
  561. if (m_debug > 0)
  562. {
  563. printf("<> sex = neuter\n");
  564. }
  565. m_sex = MD3_SEX_NEUTER;
  566. i = 0;
  567. }
  568. else if (strncmp("sex", buffer, 3) == 0)
  569. {
  570. if (m_debug > 0)
  571. {
  572. printf("<> sex = ?\n");
  573. }
  574. m_sex = MD3_SEX_FEMALE;
  575. i = 0;
  576. }
  577. else if (strncmp("footstepsenergy", buffer, 15) == 0)
  578. {
  579. if (m_debug > 0)
  580. {
  581. printf("<> footsteps = energy\n");
  582. }
  583. i = 0;
  584. state = 0;
  585. }
  586. else if (strncmp("footstepsboot", buffer, 13) == 0)
  587. {
  588. if (m_debug > 0)
  589. {
  590. printf("<> footsteps = boot\n");
  591. }
  592. i = 0;
  593. state = 0;
  594. }
  595. else if (strncmp("footsteps", buffer, 9) == 0)
  596. {
  597. if (m_debug > 0)
  598. {
  599. printf("<> footsteps = ?\n");
  600. }
  601. //i = 0;
  602. state = 0;
  603. }
  604. //printf("\"%s\"\n", buffer);
  605. break;
  606. default:
  607. if (!state2)
  608. {
  609. //printf("'%c' %i\n", c, state);
  610. buffer[i++] = c;
  611. buffer[i] = 0;
  612. }
  613. }
  614. if (!i)
  615. {
  616. buffer[i] = 0;
  617. }
  618. }
  619. fclose(f);
  620. int torsoOffset = 0;
  621. for (i = 0; i < m_animCount; ++i)
  622. {
  623. if (!torsoOffset && m_anim[i].id > 12)
  624. {
  625. torsoOffset = m_anim[LEGS_WALKCR].first_frame - m_anim[TORSO_GESTURE].first_frame;
  626. m_anim[i].first_frame -= torsoOffset;
  627. m_anim[i].end_frame -= torsoOffset;
  628. }
  629. }
  630. return 0;
  631. }
  632. ////////////////////////////////////////////////////////////
  633. // Private Mutators
  634. ////////////////////////////////////////////////////////////
  635. void Md3AnimModel::setCurrentTime(Md3 &model)
  636. {
  637. int animationSpeed;
  638. float elapsedTime = 0.0f;
  639. float time, t;
  640. // No animations in this model
  641. if (model.numAnimations == 0)
  642. {
  643. return;
  644. }
  645. // Get time in milliseconds
  646. time = getTicks();
  647. // Find the time that has elapsed since the last time that was stored
  648. elapsedTime = time - model.lastTime;
  649. // Store the animation speed for this animation in a local variable
  650. animationSpeed = m_anim[model.currentAnimation].frames_per_second;
  651. // t value is a value between 0.0 and 1.0
  652. // Tells out far from the current key frame to the next key frame.
  653. t = (elapsedTime / (1000.0f / animationSpeed));
  654. //printf("t = %f, et = %f, lt = %f, fps = %i\n",
  655. // t, elapsedTime, model.lastTime, animationSpeed);
  656. // If our elapsed time goes over the desired time segment, start over
  657. // and go to the next key frame.
  658. if (elapsedTime >= (1000.0f / animationSpeed))
  659. {
  660. // Set our current frame to the next key frame
  661. // (which could be the start of the anim)
  662. model.currentFrame = model.nextFrame;
  663. // Set our last time for the model to the current time
  664. model.lastTime = time;
  665. }
  666. model.time = t;
  667. }
  668. void Md3AnimModel::updateModel(Md3 &model)
  669. {
  670. int startFrame = 0;
  671. int endFrame = 1;
  672. unsigned int anim;
  673. anim = model.currentAnimation;
  674. if (model.numAnimations)
  675. {
  676. startFrame = m_anim[anim].first_frame;
  677. endFrame = m_anim[anim].end_frame;
  678. }
  679. // Compute next frame
  680. model.nextFrame = (model.currentFrame + 1) % endFrame;
  681. // Wrap to first frame if past last
  682. if (model.nextFrame == 0)
  683. {
  684. model.nextFrame = startFrame;
  685. }
  686. // Set interpolating time 0.0 - 1.0 ( start to end of animation)
  687. setCurrentTime(model);
  688. }
  689. void Md3AnimModel::initMd3(Md3 &model, unsigned int id)
  690. {
  691. model.idTest = id;
  692. model.numAnimations = 0;
  693. model.currentAnimation = 0;
  694. model.currentFrame = 0;
  695. model.nextFrame = 0;
  696. model.time = 0.0f;
  697. model.lastTime = 0.0f;
  698. }
  699. int Md3AnimModel::addAnim(char *modelPath, md3_animation_id_t id,
  700. unsigned int firstFrame,
  701. unsigned int numFrames,
  702. unsigned int loopingFrames,
  703. unsigned int framesPerSecond)
  704. {
  705. if (m_animCount == 30)
  706. {
  707. return -1;
  708. }
  709. m_anim[id].id = id;
  710. m_anim[id].first_frame = firstFrame;
  711. m_anim[id].end_frame = firstFrame + numFrames;
  712. m_anim[id].num_frames = numFrames;
  713. m_anim[id].looping_frames = loopingFrames;
  714. m_anim[id].frames_per_second = framesPerSecond;
  715. if (id > 12 || id < 6)
  716. {
  717. m_lower.numAnimations++;
  718. }
  719. if (id < 13)
  720. {
  721. m_upper.numAnimations++;
  722. }
  723. ++m_animCount;
  724. return 0;
  725. }
  726. int Md3AnimModel::loadMd3(Md3 &model, char *base, char *modelPath, char *skin,
  727. md3_lod_t modelLoD)
  728. {
  729. char filename[256];
  730. unsigned int len = 0, l = 250;
  731. if (!modelPath || !modelPath[0] || !base || !base[0] || modelLoD > 2)
  732. {
  733. printf("Md3AnimModel::loadMd3> ERROR: Invalid arguments\n");
  734. return -1;
  735. }
  736. len = strlen(modelPath);
  737. // Load model with requested LoD
  738. snprintf(filename, l, "%s%s%s%s", modelPath,
  739. (modelPath[len-1] == '/') ? "" : "/",
  740. base,
  741. (modelLoD == MD3_LOD_HIGH) ? ".md3" :
  742. (modelLoD == MD3_LOD_MED) ? "_1.md3" : "_2.md3");
  743. model.reset();
  744. if (model.load(filename))
  745. {
  746. printf("Md3AnimModel::loadMd3> ERROR: Loading Model %s\n", filename);
  747. return -2;
  748. }
  749. // Load skin if requested
  750. if (skin && skin[0])
  751. {
  752. snprintf(filename, l, "%s%s%s_%s.skin", modelPath,
  753. (modelPath[len-1] == '/') ? "" : "/", base, skin);
  754. if (loadSkin(model, filename))
  755. {
  756. printf("Md3AnimModel::loadMd3> ERROR: Loading Skin %s\n", filename);
  757. return -3;
  758. }
  759. }
  760. else // Try to load internal skins
  761. {
  762. unsigned int i, j, m;
  763. md3_mesh_t *meshes;
  764. m = model.getNumMeshes();
  765. meshes = model.getMeshes();
  766. for (i = 0; i < m; ++i)
  767. {
  768. strncpy(filename, meshes[i].skin[0].name, 250);
  769. filename[250] = 0;
  770. for (j = 0; filename[j] != 0; ++j)
  771. {
  772. // Replace MSDOS path with unistd ( Should work on NT too iirc )
  773. if (filename[j] == '\\')
  774. {
  775. filename[j] = '/';
  776. }
  777. // Lowercase alphabet MSDOS is case insensitive
  778. // data created with it's skin names are bad
  779. if (filename[j] > 64 && filename[j] < 91)
  780. {
  781. filename[j] += 32;
  782. }
  783. }
  784. model.texTest[i] = cacheTexture(filename);
  785. }
  786. }
  787. return 0;
  788. }
  789. int Md3AnimModel::cacheTexture(char *texture)
  790. {
  791. unsigned int len, i, id;
  792. bool cached = false;
  793. if (!texture || !texture[0])
  794. {
  795. return -1;
  796. }
  797. len = strlen(texture);
  798. for (i = 0; i < texNumTest; ++i)
  799. {
  800. if (strncmp(texture, texTest[i].name, texTest[i].name_len) == 0)
  801. {
  802. cached = true;
  803. id = i;
  804. break;
  805. }
  806. }
  807. if (!cached)
  808. {
  809. texTest[texNumTest].name = new char [len+1];
  810. texTest[texNumTest].name_len = len+1;
  811. strncpy(texTest[texNumTest].name, texture, len+1);
  812. texTest[texNumTest].name[len] = 0;
  813. id = texNumTest;
  814. texNumTest++;
  815. }
  816. return id;
  817. }
  818. int Md3AnimModel::loadSkin(Md3 &model, char *filename)
  819. {
  820. FILE *f;
  821. md3_mesh_t *meshes;
  822. int i, j, m, eof, id = 0;
  823. unsigned int b = 0;
  824. bool ready = false;
  825. char buffer[128];
  826. char mesh[68];
  827. char c;
  828. f = fopen(filename, "r");
  829. if (!f)
  830. {
  831. perror("Md3AnimModel::loadSkin> ");
  832. return -1;
  833. }
  834. eof = 0;
  835. while (eof != EOF)
  836. {
  837. eof = fscanf(f, "%c", &c);
  838. // Treat EOF like end of line
  839. if (eof == EOF)
  840. {
  841. c = '\n';
  842. }
  843. switch (c)
  844. {
  845. case '\t':
  846. case '\r':
  847. case '\0':
  848. break;
  849. case ',':
  850. strncpy(mesh, buffer, b);
  851. mesh[b] = 0;
  852. b = 0;
  853. ready = true;
  854. break;
  855. case '\n':
  856. if (!ready || !b || !buffer[1])
  857. {
  858. b = 0;
  859. ready = false;
  860. continue;
  861. }
  862. id = cacheTexture(buffer);
  863. for (i = 0; i < 4; ++i)
  864. {
  865. switch (i)
  866. {
  867. case 1:
  868. m = m_lower.getNumMeshes();
  869. meshes = m_lower.getMeshes();
  870. break;
  871. case 2:
  872. m = m_upper.getNumMeshes();
  873. meshes = m_upper.getMeshes();
  874. break;
  875. case 3:
  876. m = m_head.getNumMeshes();
  877. meshes = m_head.getMeshes();
  878. break;
  879. default:
  880. continue;
  881. }
  882. for (j = 0; j < m; ++j)
  883. {
  884. if (strncmp(mesh, meshes[j].name, 68) == 0)
  885. {
  886. switch (i)
  887. {
  888. case 1:
  889. m_lower.texTest[j] = id;
  890. break;
  891. case 2:
  892. m_upper.texTest[j] = id;
  893. break;
  894. case 3:
  895. m_head.texTest[j] = id;
  896. break;
  897. default:
  898. continue;
  899. }
  900. if (m_debug > 0)
  901. {
  902. printf("Mapping '%s' -> '%s' (%i)\n", mesh, buffer, id);
  903. }
  904. }
  905. }
  906. }
  907. ready = false;
  908. b = 0;
  909. break;
  910. default:
  911. buffer[b++] = c;
  912. buffer[b] = 0;
  913. }
  914. }
  915. fclose(f);
  916. return 0;
  917. }
  918. // FIXME: should actually parse shaders =)
  919. int Md3AnimModel::loadShader(Md3 &model, char *filename)
  920. {
  921. unsigned int i;
  922. if (model.idTest == 4)
  923. {
  924. m_weapon.texTest[0] = cacheTexture("models/weapons/machinegun/skin2.tga");
  925. for (i = m_weapon.getNumMeshes() - 1; i > 0; --i)
  926. {
  927. m_weapon.texTest[i] = m_weapon.texTest[0];
  928. }
  929. //m_weapon.texTest[0] = cacheTexture("models/weapons/railgun.tga");
  930. //m_weapon.texTest[1] = cacheTexture("models/weapons/railgun2.tga");
  931. //m_weapon.texTest[2] = cacheTexture("models/weapons/railgun3.tga");
  932. //m_weapon.texTest[3] = cacheTexture("models/weapons/railgun4.tga");
  933. }
  934. return 0;
  935. }
  936. void Md3AnimModel::connectModels(char *tagName, Md3 &modelA, Md3 &modelB)
  937. {
  938. unsigned int i, t;
  939. md3_tag_t *tags;
  940. t = modelB.getNumTags();
  941. tags = modelB.getTags();
  942. for (i = 0; i < t; ++i)
  943. {
  944. if (strncmp(tags[i].name, tagName, 63) == 0)
  945. {
  946. modelB.slaveTest[i] = modelA.idTest;
  947. break;
  948. }
  949. }
  950. }
  951. void Md3AnimModel::render()
  952. {
  953. #ifdef USING_OPENGL
  954. if (m_animCount < 1)
  955. {
  956. static unsigned int errors;
  957. if (errors < 8)
  958. {
  959. printf("ERROR: %i. Not all animations loaded %i/24\n",
  960. errors+1, m_animCount);
  961. ++errors;
  962. }
  963. else if (errors == 8)
  964. {
  965. printf("Md3AnimModel::render> Error reporting off after %i errors\n",
  966. errors);
  967. ++errors;
  968. }
  969. return;
  970. }
  971. //glRotatef(-90, 1, 0, 0);
  972. //glScalef(0.01, 0.01, 0.01);
  973. if (mFlags & fAnimate)
  974. {
  975. updateModel(m_upper);
  976. updateModel(m_lower);
  977. }
  978. glPushMatrix();
  979. renderTag(1);
  980. glPopMatrix();
  981. #endif
  982. }
  983. void renderBone(vec3_t min, vec3_t max, vec3_t center, vec_t scale);
  984. void Md3AnimModel::renderModel(Md3 &model)
  985. {
  986. #ifdef USING_OPENGL
  987. unsigned int i, j, k, numBones, numMeshes;
  988. unsigned int index, currentIndex, nextIndex, maxIndex;
  989. md3_mesh_t *meshes, *mesh;
  990. md3_bone_t *bones, *bone;
  991. numMeshes = model.getNumMeshes();
  992. meshes = model.getMeshes();
  993. if (mFlags & fRenderBones)
  994. {
  995. numBones = model.getNumBones();
  996. bones = model.getBones();
  997. for (i = 0; i < numBones; ++i)
  998. {
  999. bone = bones + i;
  1000. glColor4f(1.0, 1.0, 1.0, 1.0);
  1001. renderBone(bone->mins, bone->maxs, bone->center, bone->scale);
  1002. }
  1003. }
  1004. glEnable(GL_TEXTURE_2D);
  1005. for (i = 0; i < numMeshes; ++i)
  1006. {
  1007. glBindTexture(GL_TEXTURE_2D, texTest[model.texTest[i]].gl_texture_id);
  1008. mesh = meshes + i;
  1009. if (mesh->num_triangles <= 0)
  1010. {
  1011. continue;
  1012. }
  1013. currentIndex = mesh->num_vertices * model.currentFrame;
  1014. nextIndex = mesh->num_vertices * model.nextFrame;
  1015. maxIndex = mesh->num_frames * mesh->num_vertices;
  1016. // Try to avoid bad models/loading taking down the subsystem
  1017. // and also handle bad data as well as we can
  1018. if ((int)model.currentFrame >= mesh->num_frames ||
  1019. (int)model.nextFrame >= mesh->num_frames)
  1020. {
  1021. if (mFlags & fRenderingWarnings)
  1022. {
  1023. fprintf(stderr, "renderModel> WARNING: Frame index would be out of bounds\n model[%i].mesh[%i], %i out of %i frames\n",
  1024. model.idTest, i, model.currentFrame, mesh->num_frames);
  1025. }
  1026. model.currentFrame = mesh->num_frames-1;
  1027. model.nextFrame = mesh->num_frames-1;
  1028. currentIndex = (mesh->num_frames-1) * mesh->num_vertices;
  1029. nextIndex = (mesh->num_frames-1) * mesh->num_vertices;
  1030. }
  1031. glBegin(GL_TRIANGLES);
  1032. for (j = 0; (int)j < mesh->num_triangles; ++j)
  1033. {
  1034. for (k = 0; k < 3; ++k)
  1035. {
  1036. index = mesh->tris[j].triangle[k];
  1037. if (index + nextIndex > maxIndex ||
  1038. index + currentIndex > maxIndex)
  1039. {
  1040. currentIndex = 0;
  1041. nextIndex = 0;
  1042. fprintf(stderr, "renderModel> ERROR: Bad frame index\n");
  1043. }
  1044. if (mFlags & fUseNormals)
  1045. {
  1046. glNormal3fv(mesh->vertex[index+currentIndex].norm);
  1047. }
  1048. if (mesh->texel)
  1049. {
  1050. glTexCoord2fv(mesh->texel[index].st);
  1051. }
  1052. if (mFlags & fDisableMeshInterpolate)
  1053. {
  1054. glVertex3f(mesh->vertex[index + currentIndex].pos[0],
  1055. mesh->vertex[index + currentIndex].pos[1],
  1056. mesh->vertex[index + currentIndex].pos[2]);
  1057. }
  1058. else
  1059. {
  1060. glVertex3f(mesh->vertex[index+currentIndex].pos[0] +model.time *
  1061. (mesh->vertex[index+nextIndex].pos[0] -
  1062. mesh->vertex[index+currentIndex].pos[0]),
  1063. mesh->vertex[index+currentIndex].pos[1] +model.time *
  1064. (mesh->vertex[index+nextIndex].pos[1] -
  1065. mesh->vertex[index+currentIndex].pos[1]),
  1066. mesh->vertex[index+currentIndex].pos[2] +model.time *
  1067. (mesh->vertex[index+nextIndex].pos[2] -
  1068. mesh->vertex[index+currentIndex].pos[2]));
  1069. }
  1070. }
  1071. }
  1072. glEnd();
  1073. }
  1074. #endif
  1075. }
  1076. #ifdef USING_OPENGL
  1077. void renderBone(vec3_t min, vec3_t max, vec3_t center, vec_t scale)
  1078. {
  1079. glDisable(GL_TEXTURE_2D);
  1080. //scale *= 0.2f;
  1081. glPushMatrix();
  1082. glTranslatef(center[0], center[1], center[2]);
  1083. //glRotatef(-90.0f, 1, 0, 0);
  1084. glScalef(scale, scale, scale);
  1085. glBegin(GL_LINES);
  1086. // max, top quad
  1087. glVertex3f(max[0], max[1], max[2]);
  1088. glVertex3f(max[0], min[1], max[2]);
  1089. glVertex3f(max[0], max[1], max[2]);
  1090. glVertex3f(min[0], max[1], max[2]);
  1091. glVertex3f(max[0], max[1], max[2]);
  1092. glVertex3f(max[0], max[1], min[2]);
  1093. // max-min, vertical quads
  1094. glVertex3f(min[0], max[1], max[2]);
  1095. glVertex3f(min[0], max[1], min[2]);
  1096. glVertex3f(max[0], min[1], max[2]);
  1097. glVertex3f(max[0], min[1], min[2]);
  1098. glVertex3f(max[0], min[1], max[2]);
  1099. glVertex3f(min[0], min[1], max[2]);
  1100. // min-max, vertical quads
  1101. glVertex3f(max[0], max[1], min[2]);
  1102. glVertex3f(max[0], min[1], min[2]);
  1103. glVertex3f(max[0], max[1], min[2]);
  1104. glVertex3f(min[0], max[1], min[2]);
  1105. glVertex3f(min[0], max[1], max[2]);
  1106. glVertex3f(min[0], min[1], max[2]);
  1107. // min, bottom quad
  1108. glVertex3f(min[0], min[1], min[2]);
  1109. glVertex3f(min[0], max[1], min[2]);
  1110. glVertex3f(min[0], min[1], min[2]);
  1111. glVertex3f(max[0], min[1], min[2]);
  1112. glVertex3f(min[0], min[1], min[2]);
  1113. glVertex3f(min[0], min[1], max[2]);
  1114. glEnd();
  1115. glPopMatrix();
  1116. }
  1117. void renderLaserSight()
  1118. {
  1119. const float lenght = 56.0;
  1120. const float start = 8.0;
  1121. float d = 0.01 + (0.15*rand()/(RAND_MAX+1.0)); // for flicker fx
  1122. glDisable(GL_TEXTURE_2D);
  1123. glPushMatrix();
  1124. glScalef(100, 100, 100);
  1125. // Draw two long quads that skrink and fade the they go further out
  1126. glBegin(GL_QUADS);
  1127. glColor4f(0.9-d, 0.1, 0.1, 0.5);
  1128. glVertex3f(start, 0.0, 0.0);
  1129. glVertex3f(start, 0.2, 0.0);
  1130. glColor4f(0.3-d, 0.1, 0.1, 0.5);
  1131. glVertex3f(lenght, 0.1, 0.0);
  1132. glVertex3f(lenght, 0.0, 0.0);
  1133. glColor4f(0.9-d, 0.1, 0.1, 0.5);
  1134. glVertex3f(start, 0.0, 0.0);
  1135. glVertex3f(start, 0.0, 0.2);
  1136. glColor4f(0.3-d, 0.1, 0.1, 0.5);
  1137. glVertex3f(lenght, 0.0, 0.1);
  1138. glVertex3f(lenght, 0.0, 0.0);
  1139. glEnd();
  1140. glPopMatrix();
  1141. glColor4f(1.0, 1.0, 1.0, 1.0);
  1142. }
  1143. #endif
  1144. void convertQuake3ToHelMatrix(mat3_t q3, matrix_t hel)
  1145. {
  1146. hel[0] = q3[0][0]; hel[1] = q3[0][1]; hel[ 2] = q3[0][2];
  1147. hel[4] = q3[1][0]; hel[5] = q3[1][1]; hel[ 6] = q3[1][2];
  1148. hel[8] = q3[2][0]; hel[9] = q3[2][1]; hel[10] = q3[2][2];
  1149. // yeah, wolf
  1150. hel[3] = hel[7] = hel[11] = hel[12] = hel[13] = hel[14] = 0.0f;
  1151. hel[15] = 1.0f;
  1152. }
  1153. void Md3AnimModel::renderTag(unsigned int id)
  1154. {
  1155. #ifdef USING_OPENGL
  1156. const float scaleHack = 64.0f; // Ah Md3.cpp doesn't scale translate?
  1157. unsigned int i, t, f, nf;
  1158. unsigned int *slaves;
  1159. md3_tag_t *tags;
  1160. float time;
  1161. matrix_t finalMatrix, matrix, nextMatrix;
  1162. vec3_t pos, nextPos;
  1163. Quaternion q, qNext, qInterpolate;
  1164. nf = f = 0;
  1165. switch (id)
  1166. {
  1167. case 1:
  1168. renderModel(m_lower);
  1169. f = m_lower.currentFrame;
  1170. nf = m_lower.nextFrame;
  1171. time = m_lower.time;
  1172. t = m_lower.getNumTags();
  1173. tags = m_lower.getTags();
  1174. slaves = m_lower.slaveTest;
  1175. break;
  1176. case 2:
  1177. renderModel(m_upper);
  1178. f = m_upper.currentFrame;
  1179. nf = m_upper.nextFrame;
  1180. time = m_upper.time;
  1181. t = m_upper.getNumTags();
  1182. tags = m_upper.getTags();
  1183. slaves = m_upper.slaveTest;
  1184. break;
  1185. case 3:
  1186. renderModel(m_head);
  1187. f = m_head.currentFrame;
  1188. nf = m_head.nextFrame;
  1189. time = m_head.time;
  1190. t = m_head.getNumTags();
  1191. tags = m_head.getTags();
  1192. slaves = m_head.slaveTest;
  1193. break;
  1194. case 4:
  1195. if (mFlags & fDrawWeapon)
  1196. {
  1197. renderLaserSight();
  1198. renderModel(m_weapon);
  1199. f = m_weapon.currentFrame;
  1200. nf = m_weapon.nextFrame;
  1201. time = m_weapon.time;
  1202. t = m_weapon.getNumTags();
  1203. tags = m_weapon.getTags();
  1204. slaves = m_weapon.slaveTest;
  1205. }
  1206. return;
  1207. break;
  1208. default:
  1209. return;
  1210. }
  1211. for (i = 0; i < t; ++i)
  1212. {
  1213. if (slaves[i] > 0)
  1214. {
  1215. // Using digiben's tag anim notes
  1216. // To find the current translation position for
  1217. // this frame of animation, we multiply
  1218. // the currentFrame by the number of tags,
  1219. // then add i. This is similar to how
  1220. // the vertex key frames are interpolated.
  1221. pos[0] = tags[f*t+i].center[0];
  1222. pos[1] = tags[f*t+i].center[1];
  1223. pos[2] = tags[f*t+i].center[2];
  1224. // Grab the next key frame translation position
  1225. nextPos[0] = tags[nf*t+i].center[0];
  1226. nextPos[1] = tags[nf*t+i].center[1];
  1227. nextPos[2] = tags[nf*t+i].center[2];
  1228. // By using the equation: p(t) = p0 + t(p1 - p0), with a time t,
  1229. // we create a new translation position that
  1230. // is closer to the next key frame.
  1231. pos[0] = pos[0] + time * (nextPos[0] - pos[0]);
  1232. pos[1] = pos[1] + time * (nextPos[1] - pos[1]);
  1233. pos[2] = pos[2] + time * (nextPos[2] - pos[2]);
  1234. // Now comes the more complex interpolation. Just like
  1235. // the translation, we want to store the current and
  1236. // next key frame rotation matrix, then interpolate
  1237. // between the 2.
  1238. // Get a pointer to the start of the 3x3 rotation matrix
  1239. // for the current frame
  1240. //matrix = &tags[f*t+i].rotation[0][0];
  1241. convertQuake3ToHelMatrix(tags[f*t+i].rotation, matrix);
  1242. // Get a pointer to the start of the 3x3 rotation matrix
  1243. // for the next frame
  1244. //nextMatrix = &tags[nf*t+i].rotation[0][0];
  1245. convertQuake3ToHelMatrix(tags[nf*t+i].rotation, nextMatrix);
  1246. // Convert the current and next key frame matrix into
  1247. // a quaternion
  1248. q.setByMatrix(matrix);
  1249. qNext.setByMatrix(nextMatrix);
  1250. // Using spherical linear interpolation, find the
  1251. // interpolated quaternion
  1252. qInterpolate = Quaternion::slerp(q, qNext, time);
  1253. // Here we convert the interpolated quaternion into a matrix
  1254. qInterpolate.getMatrix(finalMatrix);
  1255. glPushMatrix();
  1256. if (mFlags & fDisableTagInterpolate)
  1257. {
  1258. // Translate w/ scale hack
  1259. //glTranslatef(pos[0]*64, pos[1]*64, pos[2]*64);
  1260. matrix[12] = pos[0]*scaleHack;
  1261. matrix[13] = pos[1]*scaleHack;
  1262. matrix[14] = pos[2]*scaleHack;
  1263. glMultMatrixf(matrix);
  1264. }
  1265. else
  1266. {
  1267. // Translate w/ scale hack
  1268. //glTranslatef(pos[0]*64, pos[1]*64, pos[2]*64);
  1269. finalMatrix[12] = pos[0]*scaleHack;
  1270. finalMatrix[13] = pos[1]*scaleHack;
  1271. finalMatrix[14] = pos[2]*scaleHack;
  1272. glMultMatrixf(finalMatrix);
  1273. }
  1274. renderTag(slaves[i]);
  1275. glPopMatrix();
  1276. }
  1277. }
  1278. #endif
  1279. }
  1280. //////////////////////////////////////////////////////////////////
  1281. // Unit Testing
  1282. //////////////////////////////////////////////////////////////////
  1283. #ifdef UNIT_TEST_MD3ANIMMODEL_SDL
  1284. #include <GL/glu.h>
  1285. #include <GL/gl.h>
  1286. #include <SDL/SDL.h>
  1287. #include "Texture.h"
  1288. void updateTitle();
  1289. void updateWindowTitle(char *title);
  1290. Md3AnimModel gMd3;
  1291. Texture gTexture;
  1292. char gTitle[128];
  1293. char gAnimUpper[32];
  1294. char gAnimLower[32];
  1295. float gYaw = 0.0f;
  1296. bool gYawOn = true;
  1297. float gPitch = -20.0f;
  1298. char gMessage[512];
  1299. unsigned int gWidth = 640;
  1300. unsigned int gHeight = 480;
  1301. void loadMd3(char *model, char *skin, char *weapon)
  1302. {
  1303. char pathname[256];
  1304. unsigned int i;
  1305. snprintf(gTitle, 255, "Md3AnimModel.test: %s ", model);
  1306. updateWindowTitle(gTitle);
  1307. snprintf(pathname, 255, "data/models/players/%s", model);
  1308. pathname[255] = 0;
  1309. if (gMd3.load(pathname, skin, MD3_LOD_HIGH) < 0)
  1310. {
  1311. printf("ERROR: MD3 '%s' not loaded\n", pathname);
  1312. }
  1313. else
  1314. {
  1315. snprintf(pathname, 255, "data/models/weapons2/%s", weapon);
  1316. pathname[255] = 0;
  1317. if (gMd3.loadWeapon(pathname, weapon))
  1318. {
  1319. printf("Couldn't load weapon model '%s'.\n", pathname);
  1320. }
  1321. gMd3.setAnimUpper(TORSO_STAND);
  1322. gMd3.setAnimLower(LEGS_IDLE);
  1323. // Setup textures
  1324. printf("\nLoading textures: ");
  1325. for (i = 0; i < gMd3.texNumTest; ++i)
  1326. {
  1327. snprintf(pathname, 255, "data/%s", gMd3.texTest[i].name);
  1328. pathname[255] = 0;
  1329. gMd3.texTest[i].gl_texture_id = gTexture.loadTGA(pathname);
  1330. if (gMd3.texTest[i].gl_texture_id < 0)
  1331. {
  1332. printf("ERROR: Md3 texture '%s' not loaded\n", pathname);
  1333. }
  1334. }
  1335. }
  1336. }
  1337. void renderScene()
  1338. {
  1339. static float lastTime = 0.0f;
  1340. const float size = 500.0f, step = 50.0f;
  1341. float x, y, time;
  1342. gluLookAt(0.0, 0.0, -256.0,
  1343. 0.0, 8.0, 0.0,
  1344. 0.0, 1.0, 0.0);
  1345. glDisable(GL_TEXTURE_2D);
  1346. time = getTicks() * 0.1f;
  1347. if (time - lastTime > 5.0f)
  1348. {
  1349. lastTime = time;
  1350. if (gYawOn)
  1351. ++gYaw;
  1352. }
  1353. #ifdef DRAW_ACTUAL_ORIGIN_AXIS_WITH_ROTATION
  1354. glPushMatrix();
  1355. glRotatef(yaw, 0, 1, 0);
  1356. glBegin(GL_LINES);
  1357. glColor3f(1.0f, 0.0f, 0.0f);
  1358. glVertex3f(0.0f, 0.0f, 0.0f);
  1359. glVertex3f(10.0f, 0.0f, 0.0f);
  1360. glColor3f(0.0f, 1.0f, 0.0f);
  1361. glVertex3f(0.0f, 0.0f, 0.0f);
  1362. glVertex3f(0.0f, 10.0f, 0.0f);
  1363. glColor3f(0.0f, 0.0f, 1.0f);
  1364. glVertex3f(0.0f, 0.0f, 0.0f);
  1365. glVertex3f(0.0f, 0.0f, 10.0f);
  1366. glEnd();
  1367. glPopMatrix();
  1368. #endif
  1369. glTranslatef(0.0f, -128.0f, 512.0f);
  1370. glRotatef(gPitch, 1, 0, 0);
  1371. glRotatef(gYaw, 0, 1, 0);
  1372. // Draw transformed origin axis
  1373. glBegin(GL_LINES);
  1374. glColor3f(1.0f, 0.0f, 0.0f);
  1375. glVertex3f(-30.0f, 0.0f, 0.0f);
  1376. glVertex3f(30.0f, 0.0f, 0.0f);
  1377. glColor3f(0.0f, 1.0f, 0.0f);
  1378. glVertex3f(0.0f, -30.0f, 0.0f);
  1379. glVertex3f(0.0f, 30.0f, 0.0f);
  1380. glColor3f(0.0f, 0.0f, 1.0f);
  1381. glVertex3f(0.0f, 0.0f, -30.0f);
  1382. glVertex3f(0.0f, 0.0f, 30.0f);
  1383. glEnd();
  1384. // Draw grid
  1385. glPushMatrix();
  1386. glScalef(2.0f, 2.0f, 2.0f);
  1387. glColor3f(0.4f, 0.4f, 0.6f);
  1388. for (x = -size; x < size; x += step)
  1389. {
  1390. glBegin(GL_LINE_LOOP);
  1391. for (y = -size; y < size; y += step)
  1392. {
  1393. glVertex3f(x + step, 0.0f, y);
  1394. glVertex3f(x, 0.0f, y);
  1395. glVertex3f(x, 0.0f, y + step);
  1396. glVertex3f(x + step, 0.0f, y + step);
  1397. }
  1398. glEnd();
  1399. }
  1400. glPopMatrix();
  1401. // Draw model
  1402. glEnable(GL_TEXTURE_2D);
  1403. glColor3f(1.0f, 1.0f, 1.0f);
  1404. glPushMatrix();
  1405. glTranslatef(0.0f, 148.0f, 0.0f);
  1406. glRotatef(-90.0f, 1, 0, 0);
  1407. glScalef(0.1f, 0.1f, 0.1f);
  1408. gMd3.render();
  1409. glPopMatrix();
  1410. #ifdef HAVE_SDL_TTF
  1411. /* Render 2d text */
  1412. glEnterMode2d(gWidth, gHeight);
  1413. glColor3f(1.0, 1.0, 1.0);
  1414. glPrint2d(8, 8, 0.90, gMessage);
  1415. glExitMode2d();
  1416. #endif
  1417. }
  1418. void initScene(int argc, char *argv[])
  1419. {
  1420. glEnable(GL_CULL_FACE);
  1421. glCullFace(GL_FRONT); // Q3A uses front face culling
  1422. glEnable(GL_TEXTURE_2D);
  1423. glEnable(GL_DEPTH_TEST);
  1424. glDepthFunc(GL_LESS);
  1425. glShadeModel(GL_SMOOTH);
  1426. glDisable(GL_LIGHTING);
  1427. if (argc > 3)
  1428. {
  1429. loadMd3(argv[1], argv[2], argv[3]);
  1430. }
  1431. else if (argc > 2)
  1432. {
  1433. loadMd3(argv[1], argv[2], "machinegun");
  1434. }
  1435. else if (argc > 1)
  1436. {
  1437. loadMd3(argv[1], "default", "machinegun");
  1438. }
  1439. else
  1440. {
  1441. printf("Usage:\n");
  1442. printf("%s ModelDir [Skin] [WeaponDir]\n", argv[0]);
  1443. exit(0);
  1444. }
  1445. #ifdef HAVE_SDL_TTF
  1446. gTexture.loadFontTTF("data/test.ttf", 32, 126 - 32);
  1447. bufferedPrintf(gMessage, 256, "Md3AnimModel Unit Test");
  1448. #endif
  1449. printf("\n");
  1450. printf("----------------------------------\n");
  1451. printf("ESC - Exit\n");
  1452. printf("F1 - Take screenshot\n");
  1453. printf("ALT+ENTER - Toogle fullscreen\n");
  1454. printf("UP/DOWN - Adjust scene pitch\n");
  1455. printf("RIGHT/LEFT - Adjust scene yaw\n");
  1456. printf("----------------------------------\n");
  1457. printf("1 - Toggle tag interpolating\n");
  1458. printf("2 - Toggle animation\n");
  1459. printf("3 - Toggle bone rendering\n");
  1460. printf("4 - Toggle weapon rendering\n");
  1461. printf("5 - Toggle mesh interpolating\n");
  1462. printf("6 - Toggle scene rotation\n");
  1463. printf("7 - Toggle rendering warning reporting\n");
  1464. printf("8 - Toggle alpha blending\n");
  1465. printf("w - Toggle wireframe rendering\n");
  1466. printf("[ - Loop through lower animations\n");
  1467. printf("] - Loop through upper animations\n");
  1468. printf("\\ - Loop through both animations\n");
  1469. printf("----------------------------------\n");
  1470. }
  1471. void updateTitle()
  1472. {
  1473. char title[256];
  1474. snprintf(title, 255, "%s %s:%s", gTitle, gAnimUpper, gAnimLower);
  1475. updateWindowTitle(title);
  1476. }
  1477. void handleKey(int key)
  1478. {
  1479. static bool wireframe = false;
  1480. static bool alphaBlend = false;
  1481. static bool lighting = false;
  1482. switch (key)
  1483. {
  1484. case SDLK_RIGHT:
  1485. ++gYaw;
  1486. break;
  1487. case SDLK_LEFT:
  1488. --gYaw;
  1489. break;
  1490. case SDLK_UP:
  1491. ++gPitch;
  1492. break;
  1493. case SDLK_DOWN:
  1494. --gPitch;
  1495. break;
  1496. case '1':
  1497. gMd3.toggleFlag(Md3AnimModel::fDisableTagInterpolate);
  1498. printf("%sabled tag interpolating\n",
  1499. (gMd3.getFlags() & Md3AnimModel::fDisableTagInterpolate) ? "Dis" : "En");
  1500. break;
  1501. case '2':
  1502. gMd3.toggleFlag(Md3AnimModel::fAnimate);
  1503. printf("%sabled animation\n",
  1504. (gMd3.getFlags() & Md3AnimModel::fAnimate) ? "En" : "Dis");
  1505. break;
  1506. case '3':
  1507. gMd3.toggleFlag(Md3AnimModel::fRenderBones);
  1508. printf("%sabled bone rendering\n",
  1509. (gMd3.getFlags() & Md3AnimModel::fRenderBones) ? "En" : "Dis");
  1510. break;
  1511. case '4':
  1512. gMd3.toggleFlag(Md3AnimModel::fDrawWeapon);
  1513. printf("%sabled weapon rendering\n",
  1514. (gMd3.getFlags() & Md3AnimModel::fDrawWeapon) ? "En" : "Dis");
  1515. break;
  1516. case '5':
  1517. gMd3.toggleFlag(Md3AnimModel::fDisableMeshInterpolate);
  1518. printf("%sabled mesh interpolating\n",
  1519. (gMd3.getFlags() & Md3AnimModel::fDisableMeshInterpolate) ? "Dis" : "En");
  1520. break;
  1521. case '6':
  1522. gYawOn = !gYawOn;
  1523. break;
  1524. case '7':
  1525. gMd3.toggleFlag(Md3AnimModel::fRenderingWarnings);
  1526. printf("%sabled rendering warning reporting\n",
  1527. (gMd3.getFlags() & Md3AnimModel::fRenderingWarnings) ? "En" : "Dis");
  1528. break;
  1529. case '8':
  1530. alphaBlend = !alphaBlend;
  1531. if (alphaBlend)
  1532. {
  1533. glEnable(GL_BLEND);
  1534. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1535. glAlphaFunc(GL_GREATER, 0);
  1536. }
  1537. else
  1538. {
  1539. glDisable(GL_BLEND);
  1540. }
  1541. printf("%sabled alpha blending\n", alphaBlend ? "En" : "Dis");
  1542. break;
  1543. case '9':
  1544. lighting = !lighting;
  1545. if (lighting)
  1546. {
  1547. static bool firsttime = true;
  1548. glEnable(GL_LIGHTING);
  1549. if (firsttime)
  1550. {
  1551. float specular[] = { 0.7, 0.7, 0.7, 1.0 };
  1552. float ambient[] = { 0.64, 0.64, 0.96, 1.0 };
  1553. float shine[] = { 50.0 };
  1554. float pos[] = { 0.0, 0.0, 64.0, 0.0 };
  1555. // Caustic fx possible with mod amb?
  1556. glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
  1557. glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
  1558. //glMaterialfv(GL_FRONT, GL_DIFFUSE, ambient);
  1559. glMaterialfv(GL_FRONT, GL_SHININESS, shine);
  1560. glLightfv(GL_LIGHT0, GL_POSITION, pos);
  1561. glEnable(GL_LIGHT0);
  1562. glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
  1563. //glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
  1564. //glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, WHITE);
  1565. //glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, WHITE);
  1566. //glLightModelfv(GL_LIGHT_MODEL_AMBIENT, DIM_WHITE);
  1567. //glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, cutoff);
  1568. //glLightfv(GL_LIGHT0, GL_POSITION, pos);
  1569. //glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);
  1570. //glLightfv(GL_LIGHT0, GL_DIFFUSE, color);
  1571. firsttime = false;
  1572. }
  1573. }
  1574. else
  1575. {
  1576. glDisable(GL_LIGHTING);
  1577. }
  1578. break;
  1579. case '0':
  1580. gMd3.toggleFlag(Md3AnimModel::fUseNormals);
  1581. break;
  1582. case 'w':
  1583. wireframe = !wireframe;
  1584. if (wireframe)
  1585. {
  1586. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  1587. }
  1588. else
  1589. {
  1590. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  1591. }
  1592. printf("%sabled wireframe rendering\n", wireframe ? "En" : "Dis");
  1593. break;
  1594. case '\\':
  1595. switch(gMd3.getAnimLower())
  1596. {
  1597. case BOTH_DEATH1:
  1598. snprintf(gAnimUpper, 32, "BOTH_DEATH1");
  1599. snprintf(gAnimLower, 32, gAnimUpper);
  1600. updateTitle();
  1601. gMd3.setAnimLower(BOTH_DEAD1);
  1602. break;
  1603. case BOTH_DEAD1:
  1604. snprintf(gAnimUpper, 32, "BOTH_DEAD2");
  1605. snprintf(gAnimLower, 32, gAnimUpper);
  1606. updateTitle();
  1607. gMd3.setAnimLower(BOTH_DEATH2);
  1608. break;
  1609. case BOTH_DEATH2:
  1610. snprintf(gAnimUpper, 32, "BOTH_DEATH2");
  1611. snprintf(gAnimLower, 32, gAnimUpper);
  1612. updateTitle();
  1613. gMd3.setAnimLower(BOTH_DEAD2);
  1614. break;
  1615. case BOTH_DEAD2:
  1616. snprintf(gAnimUpper, 32, "BOTH_DEAD2");
  1617. snprintf(gAnimLower, 32, gAnimUpper);
  1618. updateTitle();
  1619. gMd3.setAnimLower(BOTH_DEATH3);
  1620. break;
  1621. case BOTH_DEATH3:
  1622. snprintf(gAnimUpper, 32, "BOTH_DEATH3");
  1623. snprintf(gAnimLower, 32, gAnimUpper);
  1624. gMd3.setAnimLower(BOTH_DEAD3);
  1625. break;
  1626. case BOTH_DEAD3:
  1627. snprintf(gAnimUpper, 32, "BOTH_DEAD3");
  1628. snprintf(gAnimLower, 32, gAnimUpper);
  1629. gMd3.setAnimLower(BOTH_DEATH1);
  1630. break;
  1631. default:
  1632. snprintf(gAnimUpper, 32, "BOTH_DEATH1");
  1633. snprintf(gAnimLower, 32, gAnimUpper);
  1634. gMd3.setAnimLower(BOTH_DEATH1);
  1635. }
  1636. break;
  1637. case ']':
  1638. switch(gMd3.getAnimUpper())
  1639. {
  1640. case TORSO_GESTURE:
  1641. gMd3.setAnimUpper(TORSO_ATTACK);
  1642. break;
  1643. case TORSO_ATTACK:
  1644. gMd3.setAnimUpper(TORSO_ATTACK2);
  1645. break;
  1646. case TORSO_ATTACK2:
  1647. gMd3.setAnimUpper(TORSO_DROP);
  1648. break;
  1649. case TORSO_DROP:
  1650. gMd3.setAnimUpper(TORSO_RAISE);
  1651. break;
  1652. case TORSO_RAISE:
  1653. gMd3.setAnimUpper(TORSO_STAND);
  1654. break;
  1655. case TORSO_STAND:
  1656. gMd3.setAnimUpper(TORSO_STAND2);
  1657. break;
  1658. case TORSO_STAND2:
  1659. gMd3.setAnimUpper(TORSO_GESTURE);
  1660. break;
  1661. default:
  1662. gMd3.setAnimUpper(TORSO_STAND);
  1663. }
  1664. break;
  1665. case '[':
  1666. switch(gMd3.getAnimLower())
  1667. {
  1668. case LEGS_WALKCR:
  1669. gMd3.setAnimLower(LEGS_WALK);
  1670. break;
  1671. case LEGS_WALK:
  1672. gMd3.setAnimLower(LEGS_RUN);
  1673. break;
  1674. case LEGS_RUN:
  1675. gMd3.setAnimLower(LEGS_BACK);
  1676. break;
  1677. case LEGS_BACK:
  1678. gMd3.setAnimLower(LEGS_SWIM);
  1679. break;
  1680. case LEGS_SWIM:
  1681. gMd3.setAnimLower(LEGS_JUMP);
  1682. break;
  1683. case LEGS_JUMP:
  1684. gMd3.setAnimLower(LEGS_LAND);
  1685. break;
  1686. case LEGS_LAND:
  1687. gMd3.setAnimLower(LEGS_JUMPB);
  1688. break;
  1689. case LEGS_JUMPB:
  1690. gMd3.setAnimLower(LEGS_LANDB);
  1691. break;
  1692. case LEGS_LANDB:
  1693. gMd3.setAnimLower(LEGS_IDLE);
  1694. break;
  1695. case LEGS_IDLE:
  1696. gMd3.setAnimLower(LEGS_IDLECR);
  1697. break;
  1698. case LEGS_IDLECR:
  1699. gMd3.setAnimLower(LEGS_TURN);
  1700. break;
  1701. case LEGS_TURN:
  1702. gMd3.setAnimLower(LEGS_WALKCR);
  1703. break;
  1704. default:
  1705. gMd3.setAnimLower(LEGS_IDLE);
  1706. }
  1707. break;
  1708. }
  1709. }
  1710. ///////////////////////////////////////////////////
  1711. SDL_Surface *gSDLWindow = NULL;
  1712. void updateWindowTitle(char *title)
  1713. {
  1714. SDL_WM_SetCaption(title,"Md3AnimModel Test");
  1715. }
  1716. unsigned int getTicks()
  1717. {
  1718. return SDL_GetTicks();
  1719. }
  1720. void swap_buffers()
  1721. {
  1722. SDL_GL_SwapBuffers();
  1723. }
  1724. void event_resize(int width, int height)
  1725. {
  1726. GLfloat aspect;
  1727. aspect = (GLfloat)width/(GLfloat)height;
  1728. gWidth = width;
  1729. gHeight = height;
  1730. glViewport(0, 0, width, height);
  1731. glMatrixMode(GL_PROJECTION);
  1732. glLoadIdentity();
  1733. gluPerspective(45.0f, aspect, 8.0f, 4600.0f);
  1734. glMatrixMode(GL_MODELVIEW);
  1735. glLoadIdentity();
  1736. }
  1737. void event_display(int width, int height)
  1738. {
  1739. glClearColor(0.3, 0.3, 0.5, 1.0);
  1740. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  1741. glLoadIdentity();
  1742. renderScene();
  1743. glFlush();
  1744. swap_buffers();
  1745. }
  1746. void shutdown_gl()
  1747. {
  1748. SDL_Quit();
  1749. }
  1750. void init_gl(unsigned int width, unsigned int height)
  1751. {
  1752. // Print driver support information
  1753. printf("\n\n\t## GL Driver Info 4 ##\n");
  1754. printf("\tVendor : %s\n", glGetString(GL_VENDOR));
  1755. printf("\tRenderer : %s\n", glGetString(GL_RENDERER));
  1756. printf("\tVersion : %s\n", glGetString(GL_VERSION));
  1757. printf("\tExtensions : %s\n\n\n", (char*)glGetString(GL_EXTENSIONS));
  1758. // Setup GL
  1759. glClearColor(0.3, 0.3, 0.5, 1.0);
  1760. event_resize(width, height);
  1761. // Texture setup
  1762. gTexture.reset();
  1763. gTexture.setFlag(Texture::fUseMipmaps);
  1764. gTexture.setMaxTextureCount(64);
  1765. }
  1766. int main_gl(int argc, char *argv[])
  1767. {
  1768. SDL_Event event;
  1769. unsigned int mkeys, mod, key, flags;
  1770. unsigned int width = 640;
  1771. unsigned int height = 460;
  1772. bool fullscreen = false;
  1773. char *driver = 0x0;
  1774. // Setup clean up on exit
  1775. atexit(shutdown_gl);
  1776. // NOTE: Removed fullscreen/driver option parser args
  1777. // Create GL context
  1778. SDL_Init(SDL_INIT_VIDEO);
  1779. printf("\n@Created OpenGL Context...\n");
  1780. if (!driver || !driver[0] || SDL_GL_LoadLibrary(driver) < 0)
  1781. {
  1782. SDL_ClearError();
  1783. // Fallback 1
  1784. if (SDL_GL_LoadLibrary("libGL.so") < 0)
  1785. {
  1786. SDL_ClearError();
  1787. // Fallback 2
  1788. if (SDL_GL_LoadLibrary("libGL.so.1") < 0)
  1789. {
  1790. fprintf(stderr, "main_gl> SDL_GL_LoadLibrary failed!\n");
  1791. fprintf(stderr, "main_gl> Error is [%s].\n", SDL_GetError());
  1792. exit(1);
  1793. }
  1794. }
  1795. }
  1796. flags = SDL_OPENGL;
  1797. if (fullscreen)
  1798. {
  1799. flags |= SDL_FULLSCREEN;
  1800. SDL_ShowCursor(SDL_DISABLE);
  1801. }
  1802. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
  1803. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
  1804. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
  1805. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
  1806. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  1807. gSDLWindow = SDL_SetVideoMode(width, height, 16, flags);
  1808. SDL_WM_SetCaption("Md3AnimModel Test", "Md3AnimModel Test");
  1809. SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
  1810. // Init rendering
  1811. init_gl(width, height);
  1812. initScene(argc, argv);
  1813. printf("\n@Starting event loop...\n");
  1814. for (;;)
  1815. {
  1816. while (SDL_PollEvent(&event))
  1817. {
  1818. switch (event.type)
  1819. {
  1820. case SDL_QUIT:
  1821. exit(0);
  1822. break;
  1823. case SDL_MOUSEMOTION:
  1824. break;
  1825. case SDL_MOUSEBUTTONDOWN:
  1826. case SDL_MOUSEBUTTONUP:
  1827. break;
  1828. case SDL_KEYDOWN:
  1829. mkeys = (unsigned int)SDL_GetModState();
  1830. mod = 0;
  1831. if (mkeys & KMOD_LSHIFT)
  1832. mod |= KMOD_LSHIFT;
  1833. if (mkeys & KMOD_RSHIFT)
  1834. mod |= KMOD_RSHIFT;
  1835. if (mkeys & KMOD_LCTRL)
  1836. mod |= KMOD_LCTRL;
  1837. if (mkeys & KMOD_RCTRL)
  1838. mod |= KMOD_RCTRL;
  1839. if (mkeys & KMOD_LALT)
  1840. mod |= KMOD_LALT;
  1841. if (mkeys & KMOD_RALT)
  1842. mod |= KMOD_RALT;
  1843. key = event.key.keysym.sym;
  1844. switch (key)
  1845. {
  1846. case SDLK_F1:
  1847. gTexture.glScreenShot("Md3AnimModel.Test", width, height);
  1848. break;
  1849. case SDLK_ESCAPE: // 0x1B, 27d, ESC
  1850. exit(0);
  1851. break;
  1852. case SDLK_RETURN:
  1853. if (mod & KMOD_LALT)
  1854. {
  1855. SDL_ShowCursor(SDL_DISABLE);
  1856. SDL_WM_ToggleFullScreen(gSDLWindow);
  1857. }
  1858. }
  1859. handleKey(key);
  1860. break;
  1861. case SDL_KEYUP:
  1862. break;
  1863. case SDL_VIDEORESIZE:
  1864. event_resize(event.resize.w, event.resize.h);
  1865. width = event.resize.w;
  1866. height = event.resize.h;
  1867. event_display(width, height);
  1868. break;
  1869. }
  1870. }
  1871. event_display(width, height);
  1872. }
  1873. return 0;
  1874. }
  1875. int main(int argc, char *argv[])
  1876. {
  1877. main_gl(argc, argv);
  1878. return 0;
  1879. }
  1880. #endif
  1881. #ifdef UNIT_TEST_MD3ANIMMODEL
  1882. int main(int argc, char *argv[])
  1883. {
  1884. Md3AnimModel md3;
  1885. unsigned int i;
  1886. printf("[MD3AnimModel class test]\n");
  1887. if (argc > 3)
  1888. {
  1889. if (!md3.load(argv[2], argv[3], (md3_lod_t)atoi(argv[1])))
  1890. {
  1891. for (i = 0; i < md3.texNumTest; ++i)
  1892. {
  1893. printf("Depends: Texture '%s'\n", md3.texTest[i].name);
  1894. }
  1895. printf("main: load() reports success.\n");
  1896. }
  1897. if (argc > 5)
  1898. {
  1899. if (!md3.loadWeapon(argv[4], argv[6]))
  1900. {
  1901. printf("main: weaponLoad() reports success.\n");
  1902. }
  1903. }
  1904. }
  1905. else
  1906. {
  1907. printf("\n\n%s LoD path skin_name\neg %s 0 /usr/local/games/quake3/qbase3/players/slash/ default [weapon_path weapon_name]\n",
  1908. argv[0], argv[0]);
  1909. }
  1910. }
  1911. #endif