Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

934 lines
20 KiB

  1. //========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. //
  9. // studiomdl.c: generates a studio .mdl file from a .qc script
  10. // models/<scriptname>.mdl.
  11. //
  12. #pragma warning( disable : 4244 )
  13. #pragma warning( disable : 4237 )
  14. #pragma warning( disable : 4305 )
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <sys/stat.h>
  18. #include <math.h>
  19. #include "cmdlib.h"
  20. #include "scriplib.h"
  21. #include "mathlib/mathlib.h"
  22. #include "studio.h"
  23. #include "studiomdl.h"
  24. //#include "..\..\dlls\activity.h"
  25. bool IsEnd( char const* pLine )
  26. {
  27. if (strncmp( "end", pLine, 3 ) != 0)
  28. return false;
  29. return (pLine[3] == '\0') || (pLine[3] == '\n');
  30. }
  31. int SortAndBalanceBones( int iCount, int iMaxCount, int bones[], float weights[] )
  32. {
  33. int i;
  34. // collapse duplicate bone weights
  35. for (i = 0; i < iCount-1; i++)
  36. {
  37. int j;
  38. for (j = i + 1; j < iCount; j++)
  39. {
  40. if (bones[i] == bones[j])
  41. {
  42. weights[i] += weights[j];
  43. weights[j] = 0.0;
  44. }
  45. }
  46. }
  47. // do sleazy bubble sort
  48. int bShouldSort;
  49. do {
  50. bShouldSort = false;
  51. for (i = 0; i < iCount-1; i++)
  52. {
  53. if (weights[i+1] > weights[i])
  54. {
  55. int j = bones[i+1]; bones[i+1] = bones[i]; bones[i] = j;
  56. float w = weights[i+1]; weights[i+1] = weights[i]; weights[i] = w;
  57. bShouldSort = true;
  58. }
  59. }
  60. } while (bShouldSort);
  61. #ifdef MDLCOMPILE
  62. // throw away all weights less than 1/10,000th
  63. while (iCount > 1 && weights[iCount-1] < 0.0001)
  64. {
  65. iCount--;
  66. }
  67. #else // #ifdef MDLCOMPILE
  68. // throw away all weights less than 1/20th
  69. while (iCount > 1 && weights[iCount-1] < 0.05)
  70. {
  71. iCount--;
  72. }
  73. #endif // #ifdef MDLCOMPILE
  74. // clip to the top iMaxCount bones
  75. if (iCount > iMaxCount)
  76. {
  77. iCount = iMaxCount;
  78. }
  79. float t = 0;
  80. for (i = 0; i < iCount; i++)
  81. {
  82. t += weights[i];
  83. }
  84. if (t <= 0.0)
  85. {
  86. // missing weights?, go ahead and evenly share?
  87. // FIXME: shouldn't this error out?
  88. t = 1.0 / iCount;
  89. for (i = 0; i < iCount; i++)
  90. {
  91. weights[i] = t;
  92. }
  93. }
  94. else
  95. {
  96. // scale to sum to 1.0
  97. t = 1.0 / t;
  98. for (i = 0; i < iCount; i++)
  99. {
  100. weights[i] = weights[i] * t;
  101. }
  102. }
  103. return iCount;
  104. }
  105. void Grab_Vertexlist( s_source_t *psource )
  106. {
  107. while (1)
  108. {
  109. if (fgets( g_szLine, sizeof( g_szLine ), g_fpInput ) != NULL)
  110. {
  111. int j;
  112. int bone;
  113. Vector p;
  114. int iCount, bones[4];
  115. float weights[4];
  116. g_iLinecount++;
  117. // check for end
  118. if (IsEnd(g_szLine))
  119. return;
  120. int i = sscanf( g_szLine, "%d %d %f %f %f %d %d %f %d %f %d %f %d %f",
  121. &j,
  122. &bone,
  123. &p[0], &p[1], &p[2],
  124. &iCount,
  125. &bones[0], &weights[0], &bones[1], &weights[1], &bones[2], &weights[2], &bones[3], &weights[3] );
  126. if (i == 5)
  127. {
  128. if (bone < 0 || bone >= psource->numbones)
  129. {
  130. MdlWarning( "bogus bone index\n" );
  131. MdlWarning( "%d %s :\n%s", g_iLinecount, g_szFilename, g_szLine );
  132. MdlError( "Exiting due to errors\n" );
  133. }
  134. VectorCopy( p, g_vertex[j] );
  135. g_bone[j].numbones = 1;
  136. g_bone[j].bone[0] = bone;
  137. g_bone[j].weight[0] = 1.0;
  138. }
  139. else if (i > 5)
  140. {
  141. iCount = SortAndBalanceBones( iCount, MAXSTUDIOBONEWEIGHTS, bones, weights );
  142. VectorCopy( p, g_vertex[j] );
  143. g_bone[j].numbones = iCount;
  144. for (i = 0; i < iCount; i++)
  145. {
  146. g_bone[j].bone[i] = bones[i];
  147. g_bone[j].weight[i] = weights[i];
  148. }
  149. }
  150. else
  151. {
  152. MdlError("%s: error on line %d: %s", g_szFilename, g_iLinecount, g_szLine );
  153. }
  154. }
  155. }
  156. }
  157. void Grab_Facelist( s_source_t *psource )
  158. {
  159. while (1)
  160. {
  161. if (fgets( g_szLine, sizeof( g_szLine ), g_fpInput ) != NULL)
  162. {
  163. int j;
  164. s_tmpface_t f;
  165. g_iLinecount++;
  166. // check for end
  167. if (IsEnd(g_szLine))
  168. return;
  169. if (sscanf( g_szLine, "%d %d %d %d",
  170. &j,
  171. &f.a, &f.b, &f.c) == 4)
  172. {
  173. g_face[j] = f;
  174. }
  175. else
  176. {
  177. MdlError("%s: error on line %d: %s", g_szFilename, g_iLinecount, g_szLine );
  178. }
  179. }
  180. }
  181. }
  182. void Grab_Materiallist( s_source_t *psource )
  183. {
  184. while (1)
  185. {
  186. if (fgets( g_szLine, sizeof( g_szLine ), g_fpInput ) != NULL)
  187. {
  188. // char name[256];
  189. char path[MAX_PATH];
  190. rgb2_t a, d, s;
  191. float g;
  192. int j;
  193. g_iLinecount++;
  194. // check for end
  195. if (IsEnd(g_szLine))
  196. return;
  197. if (sscanf( g_szLine, "%d %f %f %f %f %f %f %f %f %f %f %f %f %f \"%[^\"]s",
  198. &j,
  199. &a.r, &a.g, &a.b, &a.a,
  200. &d.r, &d.g, &d.b, &d.a,
  201. &s.r, &s.g, &s.b, &s.a,
  202. &g,
  203. path ) == 15)
  204. {
  205. if (path[0] == '\0')
  206. {
  207. psource->texmap[j] = -1;
  208. }
  209. else if (j < sizeof(psource->texmap))
  210. {
  211. psource->texmap[j] = LookupTexture( path );
  212. }
  213. else
  214. {
  215. MdlError( "Too many materials, max %d\n", sizeof(psource->texmap) );
  216. }
  217. }
  218. }
  219. }
  220. }
  221. void Grab_Texcoordlist( s_source_t *psource )
  222. {
  223. while (1)
  224. {
  225. if (fgets( g_szLine, sizeof( g_szLine ), g_fpInput ) != NULL)
  226. {
  227. int j;
  228. Vector2D t;
  229. g_iLinecount++;
  230. // check for end
  231. if (IsEnd(g_szLine))
  232. return;
  233. if (sscanf( g_szLine, "%d %f %f",
  234. &j,
  235. &t[0], &t[1]) == 3)
  236. {
  237. t[1] = 1.0 - t[1];
  238. g_texcoord[0][j][0] = t[0];
  239. g_texcoord[0][j][1] = t[1];
  240. }
  241. else
  242. {
  243. MdlError("%s: error on line %d: %s", g_szFilename, g_iLinecount, g_szLine );
  244. }
  245. }
  246. }
  247. }
  248. void Grab_Normallist( s_source_t *psource )
  249. {
  250. while (1)
  251. {
  252. if (fgets( g_szLine, sizeof( g_szLine ), g_fpInput ) != NULL)
  253. {
  254. int j;
  255. int bone;
  256. Vector n;
  257. g_iLinecount++;
  258. // check for end
  259. if (IsEnd(g_szLine))
  260. return;
  261. if (sscanf( g_szLine, "%d %d %f %f %f",
  262. &j,
  263. &bone,
  264. &n[0], &n[1], &n[2]) == 5)
  265. {
  266. if (bone < 0 || bone >= psource->numbones)
  267. {
  268. MdlWarning( "bogus bone index\n" );
  269. MdlWarning( "%d %s :\n%s", g_iLinecount, g_szFilename, g_szLine );
  270. MdlError( "Exiting due to errors\n" );
  271. }
  272. VectorCopy( n, g_normal[j] );
  273. }
  274. else
  275. {
  276. MdlError("%s: error on line %d: %s", g_szFilename, g_iLinecount, g_szLine );
  277. }
  278. }
  279. }
  280. }
  281. void Grab_Faceattriblist( s_source_t *psource )
  282. {
  283. while (1)
  284. {
  285. if (fgets( g_szLine, sizeof( g_szLine ), g_fpInput ) != NULL)
  286. {
  287. int j;
  288. int smooth;
  289. int material;
  290. s_tmpface_t f;
  291. unsigned short s;
  292. g_iLinecount++;
  293. // check for end
  294. if (IsEnd(g_szLine))
  295. return;
  296. if (sscanf( g_szLine, "%d %d %d %d %d %d %d %d %d",
  297. &j,
  298. &material,
  299. &smooth,
  300. &f.ta[0], &f.tb[0], &f.tc[0],
  301. &f.na, &f.nb, &f.nc) == 9)
  302. {
  303. f.a = g_face[j].a;
  304. f.b = g_face[j].b;
  305. f.c = g_face[j].c;
  306. f.material = UseTextureAsMaterial( psource->texmap[material] );
  307. if (f.material < 0)
  308. {
  309. MdlError( "face %d references NULL texture %d\n", j, material );
  310. }
  311. if (1)
  312. {
  313. s = f.b; f.b = f.c; f.c = s;
  314. s = f.tb[0]; f.tb[0] = f.tc[0]; f.tc[0] = s;
  315. s = f.nb; f.nb = f.nc; f.nc = s;
  316. }
  317. g_face[j] = f;
  318. }
  319. else
  320. {
  321. MdlError("%s: error on line %d: %s", g_szFilename, g_iLinecount, g_szLine );
  322. }
  323. }
  324. }
  325. }
  326. int closestNormal( int v, int n )
  327. {
  328. float maxdot = -1.0;
  329. float dot;
  330. int r = n;
  331. v_unify_t *cur = v_list[v];
  332. while (cur)
  333. {
  334. dot = DotProduct( g_normal[cur->n], g_normal[n] );
  335. if (dot > maxdot)
  336. {
  337. r = cur->n;
  338. maxdot = dot;
  339. }
  340. cur = cur->next;
  341. }
  342. return r;
  343. }
  344. int AddToVlist(int v, int m, int n, int* t, int firstref)
  345. {
  346. v_unify_t *prev = NULL;
  347. v_unify_t *cur = v_list[v];
  348. while (cur)
  349. {
  350. if (cur->m == m && cur->n == n)
  351. {
  352. bool bMatch = true;
  353. for (int i = 0; (i < MAXSTUDIOTEXCOORDS) && bMatch; ++i)
  354. {
  355. if (cur->t[i] != t[i])
  356. {
  357. bMatch = false;
  358. }
  359. }
  360. if (bMatch)
  361. {
  362. cur->refcount++;
  363. return cur - v_listdata;
  364. }
  365. }
  366. prev = cur;
  367. cur = cur->next;
  368. }
  369. if (g_numvlist >= MAXSTUDIOSRCVERTS)
  370. {
  371. MdlError( "Too many unified vertices\n");
  372. }
  373. cur = &v_listdata[g_numvlist++];
  374. cur->lastref = -1;
  375. cur->refcount = 1;
  376. cur->v = v;
  377. cur->m = m;
  378. cur->n = n;
  379. for (int i = 0; i < MAXSTUDIOTEXCOORDS; ++i)
  380. {
  381. cur->t[i] = t[i];
  382. }
  383. if (prev)
  384. {
  385. prev->next = cur;
  386. }
  387. else
  388. {
  389. v_list[v] = cur;
  390. }
  391. return g_numvlist - 1;
  392. }
  393. void DecrementReferenceVlist( int uv, int numverts )
  394. {
  395. if (uv < 0 || uv > MAXSTUDIOSRCVERTS)
  396. MdlError( "decrement outside of range\n");
  397. v_listdata[uv].refcount--;
  398. if (v_listdata[uv].refcount == 0)
  399. {
  400. v_listdata[uv].lastref = numverts;
  401. }
  402. else if (v_listdata[uv].refcount < 0)
  403. {
  404. MdlError("<0 ref\n");
  405. }
  406. }
  407. void UnifyIndices( s_source_t *psource )
  408. {
  409. int i;
  410. s_face_t uface;
  411. // clear v_list
  412. g_numvlist = 0;
  413. memset( v_list, 0, sizeof( v_list ) );
  414. memset( v_listdata, 0, sizeof( v_listdata ) );
  415. // create an list of all the
  416. for (i = 0; i < g_numfaces; i++)
  417. {
  418. uface.a = AddToVlist(g_face[i].a, g_face[i].material, g_face[i].na, (int*)g_face[i].ta, g_numverts);
  419. uface.b = AddToVlist(g_face[i].b, g_face[i].material, g_face[i].nb, (int*)g_face[i].tb, g_numverts);
  420. uface.c = AddToVlist(g_face[i].c, g_face[i].material, g_face[i].nc, (int*)g_face[i].tc, g_numverts);
  421. uface.d = 0xFFFFFFFF;
  422. if ( g_face[i].d != 0xFFFFFFFF )
  423. {
  424. uface.d = AddToVlist(g_face[i].d, g_face[i].material, g_face[i].nd, (int*)g_face[i].td, g_numverts);
  425. }
  426. // keep an original copy
  427. g_src_uface[i] = uface;
  428. }
  429. // printf("%d : %d %d %d\n", numvlist, g_numverts, g_numnormals, g_numtexcoords );
  430. }
  431. void CalcModelTangentSpaces( s_source_t *pSrc );
  432. //-----------------------------------------------------------------------------
  433. // Builds a list of unique vertices in a source
  434. //-----------------------------------------------------------------------------
  435. static void BuildUniqueVertexList( s_source_t *pSource, const int *pDesiredToVList )
  436. {
  437. // allocate memory
  438. pSource->vertex = (s_vertexinfo_t *)calloc( pSource->numvertices, sizeof( s_vertexinfo_t ) );
  439. int numValidTexcoords = 1;
  440. for (int i = 1; i < MAXSTUDIOTEXCOORDS; ++i)
  441. {
  442. if (g_numtexcoords[i])
  443. {
  444. numValidTexcoords++;
  445. }
  446. else
  447. {
  448. break;
  449. }
  450. }
  451. // create arrays of unique vertexes, normals, texcoords.
  452. for (int i = 0; i < pSource->numvertices; i++)
  453. {
  454. int j = pDesiredToVList[i];
  455. s_vertexinfo_t &vertex = pSource->vertex[i];
  456. VectorCopy( g_vertex[ v_listdata[j].v ], vertex.position );
  457. VectorCopy( g_normal[ v_listdata[j].n ], vertex.normal );
  458. vertex.boneweight.numbones = g_bone[ v_listdata[j].v ].numbones;
  459. int k;
  460. for( k = 0; k < MAXSTUDIOBONEWEIGHTS; k++ )
  461. {
  462. vertex.boneweight.bone[k] = g_bone[ v_listdata[j].v ].bone[k];
  463. vertex.boneweight.weight[k] = g_bone[ v_listdata[j].v ].weight[k];
  464. }
  465. for (k = 0; k < numValidTexcoords; ++k)
  466. {
  467. Vector2Copy(g_texcoord[k][v_listdata[j].t[k]], vertex.texcoord[k]);
  468. }
  469. vertex.numTexcoord = numValidTexcoords;
  470. // store a bunch of other info
  471. vertex.material = v_listdata[j].m;
  472. #if 0
  473. pSource->vertexInfo[i].firstref = v_listdata[j].firstref;
  474. pSource->vertexInfo[i].lastref = v_listdata[j].lastref;
  475. #endif
  476. // printf("%4d : %2d : %6.2f %6.2f %6.2f\n", i, psource->boneweight[i].bone[0], psource->vertex[i][0], psource->vertex[i][1], psource->vertex[i][2] );
  477. }
  478. }
  479. //-----------------------------------------------------------------------------
  480. // sort new vertices by materials, last used
  481. //-----------------------------------------------------------------------------
  482. static int vlistCompare( const void *elem1, const void *elem2 )
  483. {
  484. v_unify_t *u1 = &v_listdata[*(int *)elem1];
  485. v_unify_t *u2 = &v_listdata[*(int *)elem2];
  486. // sort by material
  487. if (u1->m < u2->m)
  488. return -1;
  489. if (u1->m > u2->m)
  490. return 1;
  491. // sort by last used
  492. if (u1->lastref < u2->lastref)
  493. return -1;
  494. if (u1->lastref > u2->lastref)
  495. return 1;
  496. return 0;
  497. }
  498. static void SortVerticesByMaterial( int *pDesiredToVList, int *pVListToDesired )
  499. {
  500. for ( int i = 0; i < g_numvlist; i++ )
  501. {
  502. pDesiredToVList[i] = i;
  503. }
  504. qsort( pDesiredToVList, g_numvlist, sizeof( int ), vlistCompare );
  505. for ( int i = 0; i < g_numvlist; i++ )
  506. {
  507. pVListToDesired[ pDesiredToVList[i] ] = i;
  508. }
  509. }
  510. //-----------------------------------------------------------------------------
  511. // sort new faces by materials, last used
  512. //-----------------------------------------------------------------------------
  513. static int faceCompare( const void *elem1, const void *elem2 )
  514. {
  515. int i1 = *(int *)elem1;
  516. int i2 = *(int *)elem2;
  517. // sort by material
  518. if (g_face[i1].material < g_face[i2].material)
  519. return -1;
  520. if (g_face[i1].material > g_face[i2].material)
  521. return 1;
  522. // sort by original usage
  523. if (i1 < i2)
  524. return -1;
  525. if (i1 > i2)
  526. return 1;
  527. return 0;
  528. }
  529. static void SortFacesByMaterial( int *pDesiredToSrcFace )
  530. {
  531. // NOTE: Unlike SortVerticesByMaterial, srcFaceToDesired isn't needed, so we're not computing it
  532. for ( int i = 0; i < g_numfaces; i++ )
  533. {
  534. pDesiredToSrcFace[i] = i;
  535. }
  536. qsort( pDesiredToSrcFace, g_numfaces, sizeof( int ), faceCompare );
  537. }
  538. //-----------------------------------------------------------------------------
  539. // Builds mesh structures in the source
  540. //-----------------------------------------------------------------------------
  541. static void PointMeshesToVertexAndFaceData( s_source_t *pSource, int *pDesiredToSrcFace )
  542. {
  543. // First, assign all meshes to be empty
  544. // A mesh is a set of faces + vertices that all use 1 material
  545. for ( int m = 0; m < MAXSTUDIOSKINS; m++ )
  546. {
  547. pSource->mesh[m].numvertices = 0;
  548. pSource->mesh[m].vertexoffset = pSource->numvertices;
  549. pSource->mesh[m].numfaces = 0;
  550. pSource->mesh[m].faceoffset = pSource->numfaces;
  551. }
  552. // find first and count of vertices per material
  553. for ( int i = 0; i < pSource->numvertices; i++ )
  554. {
  555. int m = pSource->vertex[i].material;
  556. pSource->mesh[m].numvertices++;
  557. if (pSource->mesh[m].vertexoffset > i)
  558. {
  559. pSource->mesh[m].vertexoffset = i;
  560. }
  561. }
  562. // find first and count of faces per material
  563. for ( int i = 0; i < pSource->numfaces; i++ )
  564. {
  565. int m = g_face[ pDesiredToSrcFace[i] ].material;
  566. pSource->mesh[m].numfaces++;
  567. if (pSource->mesh[m].faceoffset > i)
  568. {
  569. pSource->mesh[m].faceoffset = i;
  570. }
  571. }
  572. /*
  573. for (k = 0; k < MAXSTUDIOSKINS; k++)
  574. {
  575. printf("%d : %d:%d %d:%d\n", k, psource->mesh[k].numvertices, psource->mesh[k].vertexoffset, psource->mesh[k].numfaces, psource->mesh[k].faceoffset );
  576. }
  577. */
  578. }
  579. //-----------------------------------------------------------------------------
  580. // Builds the face list in the mesh
  581. //-----------------------------------------------------------------------------
  582. static void BuildFaceList( s_source_t *pSource, int *pVListToDesired, int *pDesiredToSrcFace )
  583. {
  584. pSource->face = (s_face_t *)calloc( pSource->numfaces, sizeof( s_face_t ));
  585. for ( int m = 0; m < MAXSTUDIOSKINS; m++)
  586. {
  587. if ( !pSource->mesh[m].numfaces )
  588. continue;
  589. pSource->meshindex[ pSource->nummeshes++ ] = m;
  590. for ( int i = pSource->mesh[m].faceoffset; i < pSource->mesh[m].numfaces + pSource->mesh[m].faceoffset; i++)
  591. {
  592. int j = pDesiredToSrcFace[i];
  593. // NOTE: per-face vertex indices a,b,c,d are mesh relative (hence the subtraction), while g_src_uface are model relative
  594. pSource->face[i].a = pVListToDesired[ g_src_uface[j].a ] - pSource->mesh[m].vertexoffset;
  595. pSource->face[i].b = pVListToDesired[ g_src_uface[j].b ] - pSource->mesh[m].vertexoffset;
  596. pSource->face[i].c = pVListToDesired[ g_src_uface[j].c ] - pSource->mesh[m].vertexoffset;
  597. if ( g_src_uface[j].d != 0xFFFFFFFF )
  598. {
  599. pSource->face[i].d = pVListToDesired[ g_src_uface[j].d ] - pSource->mesh[m].vertexoffset;
  600. }
  601. Assert( ((pSource->face[i].a & 0xF0000000) == 0) && ((pSource->face[i].b & 0xF0000000) == 0) &&
  602. ((pSource->face[i].c & 0xF0000000) == 0) && (((pSource->face[i].d & 0xF0000000) == 0) || (pSource->face[i].d == 0xFFFFFFFF)) );
  603. // printf("%3d : %4d %4d %4d %4d\n", i, pSource->face[i].a, pSource->face[i].b, pSource->face[i].c, pSource->face[i].d );
  604. }
  605. }
  606. }
  607. //-----------------------------------------------------------------------------
  608. // Remaps the vertex animations based on the new vertex ordering
  609. //-----------------------------------------------------------------------------
  610. static void RemapVertexAnimations( s_source_t *pSource, int *pVListToDesired )
  611. {
  612. CUtlVectorAuto< int > temp;
  613. int nAnimationCount = pSource->m_Animations.Count();
  614. for ( int i = 0; i < nAnimationCount; ++i )
  615. {
  616. s_sourceanim_t &anim = pSource->m_Animations[i];
  617. if ( !anim.newStyleVertexAnimations )
  618. continue;
  619. for ( int j = 0; j < MAXSTUDIOANIMFRAMES; ++j )
  620. {
  621. int nVAnimCount = anim.numvanims[j];
  622. if ( nVAnimCount == 0 )
  623. continue;
  624. // Copy off the initial vertex data
  625. // Have to do it in 2 loops because it'll overwrite itself if we do it in 1
  626. for ( int k = 0; k < nVAnimCount; ++k )
  627. {
  628. temp[k] = anim.vanim[j][k].vertex;
  629. }
  630. for ( int k = 0; k < nVAnimCount; ++k )
  631. {
  632. // NOTE: vertex animations are model relative, not mesh relative
  633. anim.vanim[j][k].vertex = pVListToDesired[ temp[k] ];
  634. }
  635. }
  636. }
  637. }
  638. //-----------------------------------------------------------------------------
  639. // Sorts vertices by material type, re-maps data structures that refer to those vertices
  640. // to use the new indices
  641. //-----------------------------------------------------------------------------
  642. void BuildIndividualMeshes( s_source_t *pSource )
  643. {
  644. int *v_listsort = (int *)malloc( g_numvlist * sizeof( int ) ); // map desired order to vlist entry
  645. int *v_ilistsort = (int *)malloc( g_numvlist * sizeof( int ) ); // map vlist entry to desired order
  646. int *facesort = (int *)malloc( g_numfaces * sizeof( int ) ); // map desired order to src_face entry
  647. SortVerticesByMaterial( v_listsort, v_ilistsort );
  648. SortFacesByMaterial( facesort );
  649. pSource->numvertices = g_numvlist;
  650. pSource->numfaces = g_numfaces;
  651. BuildUniqueVertexList( pSource, v_listsort );
  652. PointMeshesToVertexAndFaceData( pSource, facesort );
  653. BuildFaceList( pSource, v_ilistsort, facesort );
  654. RemapVertexAnimations( pSource, v_ilistsort );
  655. CalcModelTangentSpaces( pSource );
  656. free( facesort );
  657. free( v_ilistsort );
  658. free( v_listsort );
  659. }
  660. void Grab_MRMFaceupdates( s_source_t *psource )
  661. {
  662. while (1)
  663. {
  664. if (fgets( g_szLine, sizeof( g_szLine ), g_fpInput ) != NULL)
  665. {
  666. g_iLinecount++;
  667. // check for end
  668. if (IsEnd(g_szLine))
  669. return;
  670. }
  671. }
  672. }
  673. int Load_VRM ( s_source_t *psource )
  674. {
  675. char cmd[1024];
  676. int option;
  677. if (!OpenGlobalFile( psource->filename ))
  678. {
  679. return 0;
  680. }
  681. if( !g_quiet )
  682. {
  683. printf ("grabbing %s\n", psource->filename);
  684. }
  685. g_iLinecount = 0;
  686. while (fgets( g_szLine, sizeof( g_szLine ), g_fpInput ) != NULL)
  687. {
  688. g_iLinecount++;
  689. sscanf( g_szLine, "%1023s %d", cmd, &option );
  690. if (stricmp( cmd, "version" ) == 0)
  691. {
  692. if (option != 2)
  693. {
  694. MdlError("bad version\n");
  695. }
  696. }
  697. else if (stricmp( cmd, "name" ) == 0)
  698. {
  699. }
  700. else if (stricmp( cmd, "vertices" ) == 0)
  701. {
  702. g_numverts = option;
  703. }
  704. else if (stricmp( cmd, "faces" ) == 0)
  705. {
  706. g_numfaces = option;
  707. }
  708. else if (stricmp( cmd, "materials" ) == 0)
  709. {
  710. // doesn't matter;
  711. }
  712. else if (stricmp( cmd, "texcoords" ) == 0)
  713. {
  714. g_numtexcoords[0] = option;
  715. if (option == 0)
  716. MdlError( "model has no texture coordinates\n");
  717. }
  718. else if (stricmp( cmd, "normals" ) == 0)
  719. {
  720. g_numnormals = option;
  721. }
  722. else if (stricmp( cmd, "tristrips" ) == 0)
  723. {
  724. // should be 0;
  725. }
  726. else if (stricmp( cmd, "vertexlist" ) == 0)
  727. {
  728. Grab_Vertexlist( psource );
  729. }
  730. else if (stricmp( cmd, "facelist" ) == 0)
  731. {
  732. Grab_Facelist( psource );
  733. }
  734. else if (stricmp( cmd, "materiallist" ) == 0)
  735. {
  736. Grab_Materiallist( psource );
  737. }
  738. else if (stricmp( cmd, "texcoordlist" ) == 0)
  739. {
  740. Grab_Texcoordlist( psource );
  741. }
  742. else if (stricmp( cmd, "normallist" ) == 0)
  743. {
  744. Grab_Normallist( psource );
  745. }
  746. else if (stricmp( cmd, "faceattriblist" ) == 0)
  747. {
  748. Grab_Faceattriblist( psource );
  749. }
  750. else if (stricmp( cmd, "MRM" ) == 0)
  751. {
  752. }
  753. else if (stricmp( cmd, "MRMvertices" ) == 0)
  754. {
  755. }
  756. else if (stricmp( cmd, "MRMfaces" ) == 0)
  757. {
  758. }
  759. else if (stricmp( cmd, "MRMfaceupdates" ) == 0)
  760. {
  761. Grab_MRMFaceupdates( psource );
  762. }
  763. else if (stricmp( cmd, "nodes" ) == 0)
  764. {
  765. psource->numbones = Grab_Nodes( psource->localBone );
  766. }
  767. else if (stricmp( cmd, "skeleton" ) == 0)
  768. {
  769. Grab_Animation( psource, "BindPose" );
  770. }
  771. /*
  772. else if (stricmp( cmd, "triangles" ) == 0) {
  773. Grab_Triangles( psource );
  774. }
  775. */
  776. else
  777. {
  778. MdlError("unknown VRM command : %s \n", cmd );
  779. }
  780. }
  781. UnifyIndices( psource );
  782. BuildIndividualMeshes( psource );
  783. fclose( g_fpInput );
  784. return 1;
  785. }