Model_md5.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code 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. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "tr_local.h"
  23. #include "Model_local.h"
  24. #ifdef ID_WIN_X86_SSE2_INTRIN
  25. static const __m128 vector_float_posInfinity = { idMath::INFINITY, idMath::INFINITY, idMath::INFINITY, idMath::INFINITY };
  26. static const __m128 vector_float_negInfinity = { -idMath::INFINITY, -idMath::INFINITY, -idMath::INFINITY, -idMath::INFINITY };
  27. #endif
  28. static const char *MD5_SnapshotName = "_MD5_Snapshot_";
  29. static const byte MD5B_VERSION = 106;
  30. static const unsigned int MD5B_MAGIC = ( '5' << 24 ) | ( 'D' << 16 ) | ( 'M' << 8 ) | MD5B_VERSION;
  31. idCVar r_useGPUSkinning( "r_useGPUSkinning", "1", CVAR_INTEGER, "animate normals and tangents instead of deriving" );
  32. /***********************************************************************
  33. idMD5Mesh
  34. ***********************************************************************/
  35. static int c_numVerts = 0;
  36. static int c_numWeights = 0;
  37. static int c_numWeightJoints = 0;
  38. struct vertexWeight_t {
  39. int joint;
  40. idVec3 offset;
  41. float jointWeight;
  42. };
  43. /*
  44. ====================
  45. idMD5Mesh::idMD5Mesh
  46. ====================
  47. */
  48. idMD5Mesh::idMD5Mesh() {
  49. shader = NULL;
  50. numVerts = 0;
  51. numTris = 0;
  52. meshJoints = NULL;
  53. numMeshJoints = 0;
  54. maxJointVertDist = 0.0f;
  55. deformInfo = NULL;
  56. surfaceNum = 0;
  57. }
  58. /*
  59. ====================
  60. idMD5Mesh::~idMD5Mesh
  61. ====================
  62. */
  63. idMD5Mesh::~idMD5Mesh() {
  64. if ( meshJoints != NULL ) {
  65. Mem_Free( meshJoints );
  66. meshJoints = NULL;
  67. }
  68. if ( deformInfo != NULL ) {
  69. R_FreeDeformInfo( deformInfo );
  70. deformInfo = NULL;
  71. }
  72. }
  73. /*
  74. ====================
  75. idMD5Mesh::ParseMesh
  76. ====================
  77. */
  78. void idMD5Mesh::ParseMesh( idLexer &parser, int numJoints, const idJointMat *joints ) {
  79. idToken token;
  80. idToken name;
  81. parser.ExpectTokenString( "{" );
  82. //
  83. // parse name
  84. //
  85. if ( parser.CheckTokenString( "name" ) ) {
  86. parser.ReadToken( &name );
  87. }
  88. //
  89. // parse shader
  90. //
  91. parser.ExpectTokenString( "shader" );
  92. parser.ReadToken( &token );
  93. idStr shaderName = token;
  94. shader = declManager->FindMaterial( shaderName );
  95. //
  96. // parse texture coordinates
  97. //
  98. parser.ExpectTokenString( "numverts" );
  99. int count = parser.ParseInt();
  100. if ( count < 0 ) {
  101. parser.Error( "Invalid size: %s", token.c_str() );
  102. }
  103. this->numVerts = count;
  104. idList<idVec2> texCoords;
  105. idList<int> firstWeightForVertex;
  106. idList<int> numWeightsForVertex;
  107. texCoords.SetNum( count );
  108. firstWeightForVertex.SetNum( count );
  109. numWeightsForVertex.SetNum( count );
  110. int numWeights = 0;
  111. int maxweight = 0;
  112. for ( int i = 0; i < texCoords.Num(); i++ ) {
  113. parser.ExpectTokenString( "vert" );
  114. parser.ParseInt();
  115. parser.Parse1DMatrix( 2, texCoords[ i ].ToFloatPtr() );
  116. firstWeightForVertex[ i ] = parser.ParseInt();
  117. numWeightsForVertex[ i ] = parser.ParseInt();
  118. if ( !numWeightsForVertex[ i ] ) {
  119. parser.Error( "Vertex without any joint weights." );
  120. }
  121. numWeights += numWeightsForVertex[ i ];
  122. if ( numWeightsForVertex[ i ] + firstWeightForVertex[ i ] > maxweight ) {
  123. maxweight = numWeightsForVertex[ i ] + firstWeightForVertex[ i ];
  124. }
  125. }
  126. //
  127. // parse tris
  128. //
  129. parser.ExpectTokenString( "numtris" );
  130. count = parser.ParseInt();
  131. if ( count < 0 ) {
  132. parser.Error( "Invalid size: %d", count );
  133. }
  134. idList<int> tris;
  135. tris.SetNum( count * 3 );
  136. numTris = count;
  137. for ( int i = 0; i < count; i++ ) {
  138. parser.ExpectTokenString( "tri" );
  139. parser.ParseInt();
  140. tris[ i * 3 + 0 ] = parser.ParseInt();
  141. tris[ i * 3 + 1 ] = parser.ParseInt();
  142. tris[ i * 3 + 2 ] = parser.ParseInt();
  143. }
  144. //
  145. // parse weights
  146. //
  147. parser.ExpectTokenString( "numweights" );
  148. count = parser.ParseInt();
  149. if ( count < 0 ) {
  150. parser.Error( "Invalid size: %d", count );
  151. }
  152. if ( maxweight > count ) {
  153. parser.Warning( "Vertices reference out of range weights in model (%d of %d weights).", maxweight, count );
  154. }
  155. idList<vertexWeight_t> tempWeights;
  156. tempWeights.SetNum( count );
  157. assert( numJoints < 256 ); // so we can pack into bytes
  158. for ( int i = 0; i < count; i++ ) {
  159. parser.ExpectTokenString( "weight" );
  160. parser.ParseInt();
  161. int jointnum = parser.ParseInt();
  162. if ( ( jointnum < 0 ) || ( jointnum >= numJoints ) ) {
  163. parser.Error( "Joint Index out of range(%d): %d", numJoints, jointnum );
  164. }
  165. tempWeights[ i ].joint = jointnum;
  166. tempWeights[ i ].jointWeight = parser.ParseFloat();
  167. parser.Parse1DMatrix( 3, tempWeights[ i ].offset.ToFloatPtr() );
  168. }
  169. // create pre-scaled weights and an index for the vertex/joint lookup
  170. idVec4 * scaledWeights = (idVec4 *) Mem_Alloc16( numWeights * sizeof( scaledWeights[0] ), TAG_MD5_WEIGHT );
  171. int * weightIndex = (int *) Mem_Alloc16( numWeights * 2 * sizeof( weightIndex[0] ), TAG_MD5_INDEX );
  172. memset( weightIndex, 0, numWeights * 2 * sizeof( weightIndex[0] ) );
  173. count = 0;
  174. for ( int i = 0; i < texCoords.Num(); i++ ) {
  175. int num = firstWeightForVertex[i];
  176. for( int j = 0; j < numWeightsForVertex[i]; j++, num++, count++ ) {
  177. scaledWeights[count].ToVec3() = tempWeights[num].offset * tempWeights[num].jointWeight;
  178. scaledWeights[count].w = tempWeights[num].jointWeight;
  179. weightIndex[count * 2 + 0] = tempWeights[num].joint * sizeof( idJointMat );
  180. }
  181. weightIndex[count * 2 - 1] = 1;
  182. }
  183. parser.ExpectTokenString( "}" );
  184. // update counters
  185. c_numVerts += texCoords.Num();
  186. c_numWeights += numWeights;
  187. c_numWeightJoints++;
  188. for ( int i = 0; i < numWeights; i++ ) {
  189. c_numWeightJoints += weightIndex[i*2+1];
  190. }
  191. //
  192. // build a base pose that can be used for skinning
  193. //
  194. idDrawVert * basePose = (idDrawVert *)Mem_ClearedAlloc( texCoords.Num() * sizeof( *basePose ), TAG_MD5_BASE );
  195. for( int j = 0, i = 0; i < texCoords.Num(); i++ ) {
  196. idVec3 v = ( *(idJointMat *) ( (byte *)joints + weightIndex[j*2+0] ) ) * scaledWeights[j];
  197. while( weightIndex[j*2+1] == 0 ) {
  198. j++;
  199. v += ( *(idJointMat *) ( (byte *)joints + weightIndex[j*2+0] ) ) * scaledWeights[j];
  200. }
  201. j++;
  202. basePose[i].Clear();
  203. basePose[i].xyz = v;
  204. basePose[i].SetTexCoord( texCoords[i] );
  205. }
  206. // build the weights and bone indexes into the verts, so they will be duplicated
  207. // as necessary at mirror seems
  208. static int maxWeightsPerVert;
  209. static float maxResidualWeight;
  210. const int MAX_VERTEX_WEIGHTS = 4;
  211. idList< bool > jointIsUsed;
  212. jointIsUsed.SetNum( numJoints );
  213. for ( int i = 0; i < jointIsUsed.Num(); i++ ) {
  214. jointIsUsed[i] = false;
  215. }
  216. numMeshJoints = 0;
  217. maxJointVertDist = 0.0f;
  218. //-----------------------------------------
  219. // new-style setup for fixed four weights and normal / tangent deformation
  220. //
  221. // Several important models have >25% residual weight in joints after the
  222. // first four, which is worrisome for using a fixed four joint deformation.
  223. //-----------------------------------------
  224. for ( int i = 0; i < texCoords.Num(); i++ ) {
  225. idDrawVert & dv = basePose[i];
  226. // some models do have >4 joint weights, so it is necessary to sort and renormalize
  227. // sort the weights and take the four largest
  228. int weights[256];
  229. const int numWeights = numWeightsForVertex[ i ];
  230. for ( int j = 0; j < numWeights; j++ ) {
  231. weights[j] = firstWeightForVertex[i] + j;
  232. }
  233. // bubble sort
  234. for ( int j = 0; j < numWeights; j++ ) {
  235. for ( int k = 0; k < numWeights - 1 - j; k++ ) {
  236. if ( tempWeights[weights[k]].jointWeight < tempWeights[weights[k+1]].jointWeight ) {
  237. SwapValues( weights[k], weights[k+1] );
  238. }
  239. }
  240. }
  241. if ( numWeights > maxWeightsPerVert ) {
  242. maxWeightsPerVert = numWeights;
  243. }
  244. const int usedWeights = Min( MAX_VERTEX_WEIGHTS, numWeights );
  245. float totalWeight = 0;
  246. for ( int j = 0; j < numWeights; j++ ) {
  247. totalWeight += tempWeights[weights[j]].jointWeight;
  248. }
  249. assert( totalWeight > 0.999f && totalWeight < 1.001f );
  250. float usedWeight = 0;
  251. for ( int j = 0; j < usedWeights; j++ ) {
  252. usedWeight += tempWeights[weights[j]].jointWeight;
  253. }
  254. const float residualWeight = totalWeight - usedWeight;
  255. if ( residualWeight > maxResidualWeight ) {
  256. maxResidualWeight = residualWeight;
  257. }
  258. byte finalWeights[MAX_VERTEX_WEIGHTS] = { 0 };
  259. byte finalJointIndecies[MAX_VERTEX_WEIGHTS] = { 0 };
  260. for ( int j = 0; j < usedWeights; j++ ) {
  261. const vertexWeight_t & weight = tempWeights[weights[j]];
  262. const int jointIndex = weight.joint;
  263. const float fw = weight.jointWeight;
  264. assert( fw >= 0.0f && fw <= 1.0f );
  265. const float normalizedWeight = fw / usedWeight;
  266. finalWeights[j] = idMath::Ftob( normalizedWeight * 255.0f);
  267. finalJointIndecies[j] = jointIndex;
  268. }
  269. // Sort the weights and indices for hardware skinning
  270. for ( int k = 0; k < 3; ++k ) {
  271. for ( int l = k + 1; l < 4; ++l ) {
  272. if ( finalWeights[l] > finalWeights[k] ) {
  273. SwapValues( finalWeights[k], finalWeights[l] );
  274. SwapValues( finalJointIndecies[k], finalJointIndecies[l] );
  275. }
  276. }
  277. }
  278. // Give any left over to the biggest weight
  279. finalWeights[0] += Max( 255 - finalWeights[0] - finalWeights[1] - finalWeights[2] - finalWeights[3], 0 );
  280. dv.color[0] = finalJointIndecies[0];
  281. dv.color[1] = finalJointIndecies[1];
  282. dv.color[2] = finalJointIndecies[2];
  283. dv.color[3] = finalJointIndecies[3];
  284. dv.color2[0] = finalWeights[0];
  285. dv.color2[1] = finalWeights[1];
  286. dv.color2[2] = finalWeights[2];
  287. dv.color2[3] = finalWeights[3];
  288. for ( int j = usedWeights; j < 4; j++ ) {
  289. assert( dv.color2[j] == 0 );
  290. }
  291. for ( int j = 0; j < usedWeights; j++ ) {
  292. if ( !jointIsUsed[finalJointIndecies[j]] ) {
  293. jointIsUsed[finalJointIndecies[j]] = true;
  294. numMeshJoints++;
  295. }
  296. const idJointMat & joint = joints[finalJointIndecies[j]];
  297. float dist = ( dv.xyz - joint.GetTranslation() ).Length();
  298. if ( dist > maxJointVertDist ) {
  299. maxJointVertDist = dist;
  300. }
  301. }
  302. }
  303. meshJoints = (byte *) Mem_Alloc( numMeshJoints * sizeof( meshJoints[0] ), TAG_MODEL );
  304. numMeshJoints = 0;
  305. for ( int i = 0; i < numJoints; i++ ) {
  306. if ( jointIsUsed[i] ) {
  307. meshJoints[numMeshJoints++] = i;
  308. }
  309. }
  310. // build the deformInfo and collect a final base pose with the mirror
  311. // seam verts properly including the bone weights
  312. deformInfo = R_BuildDeformInfo( texCoords.Num(), basePose, tris.Num(), tris.Ptr(),
  313. shader->UseUnsmoothedTangents() );
  314. for ( int i = 0; i < deformInfo->numOutputVerts; i++ ) {
  315. for ( int j = 0; j < 4; j++ ) {
  316. if ( deformInfo->verts[i].color[j] >= numJoints ) {
  317. idLib::FatalError( "Bad joint index" );
  318. }
  319. }
  320. }
  321. Mem_Free( basePose );
  322. }
  323. /*
  324. ============
  325. TransformVertsAndTangents
  326. ============
  327. */
  328. void TransformVertsAndTangents( idDrawVert * targetVerts, const int numVerts, const idDrawVert *baseVerts, const idJointMat *joints ) {
  329. for( int i = 0; i < numVerts; i++ ) {
  330. const idDrawVert & base = baseVerts[i];
  331. const idJointMat & j0 = joints[base.color[0]];
  332. const idJointMat & j1 = joints[base.color[1]];
  333. const idJointMat & j2 = joints[base.color[2]];
  334. const idJointMat & j3 = joints[base.color[3]];
  335. const float w0 = base.color2[0] * ( 1.0f / 255.0f );
  336. const float w1 = base.color2[1] * ( 1.0f / 255.0f );
  337. const float w2 = base.color2[2] * ( 1.0f / 255.0f );
  338. const float w3 = base.color2[3] * ( 1.0f / 255.0f );
  339. idJointMat accum;
  340. idJointMat::Mul( accum, j0, w0 );
  341. idJointMat::Mad( accum, j1, w1 );
  342. idJointMat::Mad( accum, j2, w2 );
  343. idJointMat::Mad( accum, j3, w3 );
  344. targetVerts[i].xyz = accum * idVec4( base.xyz.x, base.xyz.y, base.xyz.z, 1.0f );
  345. targetVerts[i].SetNormal( accum * base.GetNormal() );
  346. targetVerts[i].SetTangent( accum * base.GetTangent() );
  347. targetVerts[i].tangent[3] = base.tangent[3];
  348. }
  349. }
  350. /*
  351. ====================
  352. idMD5Mesh::UpdateSurface
  353. ====================
  354. */
  355. void idMD5Mesh::UpdateSurface( const struct renderEntity_s *ent, const idJointMat *entJoints,
  356. const idJointMat *entJointsInverted, modelSurface_t *surf ) {
  357. tr.pc.c_deformedSurfaces++;
  358. tr.pc.c_deformedVerts += deformInfo->numOutputVerts;
  359. tr.pc.c_deformedIndexes += deformInfo->numIndexes;
  360. surf->shader = shader;
  361. if ( surf->geometry != NULL ) {
  362. // if the number of verts and indexes are the same we can re-use the triangle surface
  363. if ( surf->geometry->numVerts == deformInfo->numOutputVerts && surf->geometry->numIndexes == deformInfo->numIndexes ) {
  364. R_FreeStaticTriSurfVertexCaches( surf->geometry );
  365. } else {
  366. R_FreeStaticTriSurf( surf->geometry );
  367. surf->geometry = R_AllocStaticTriSurf();
  368. }
  369. } else {
  370. surf->geometry = R_AllocStaticTriSurf();
  371. }
  372. srfTriangles_t * tri = surf->geometry;
  373. // note that some of the data is referenced, and should not be freed
  374. tri->referencedIndexes = true;
  375. tri->numIndexes = deformInfo->numIndexes;
  376. tri->indexes = deformInfo->indexes;
  377. tri->silIndexes = deformInfo->silIndexes;
  378. tri->numMirroredVerts = deformInfo->numMirroredVerts;
  379. tri->mirroredVerts = deformInfo->mirroredVerts;
  380. tri->numDupVerts = deformInfo->numDupVerts;
  381. tri->dupVerts = deformInfo->dupVerts;
  382. tri->numSilEdges = deformInfo->numSilEdges;
  383. tri->silEdges = deformInfo->silEdges;
  384. tri->indexCache = deformInfo->staticIndexCache;
  385. tri->numVerts = deformInfo->numOutputVerts;
  386. if ( r_useGPUSkinning.GetBool() ) {
  387. if ( tri->verts != NULL && tri->verts != deformInfo->verts ) {
  388. R_FreeStaticTriSurfVerts( tri );
  389. }
  390. tri->verts = deformInfo->verts;
  391. tri->ambientCache = deformInfo->staticAmbientCache;
  392. tri->shadowCache = deformInfo->staticShadowCache;
  393. tri->referencedVerts = true;
  394. } else {
  395. if ( tri->verts == NULL || tri->verts == deformInfo->verts ) {
  396. tri->verts = NULL;
  397. R_AllocStaticTriSurfVerts( tri, deformInfo->numOutputVerts );
  398. assert( tri->verts != NULL ); // quiet analyze warning
  399. memcpy( tri->verts, deformInfo->verts, deformInfo->numOutputVerts * sizeof( deformInfo->verts[0] ) ); // copy over the texture coordinates
  400. }
  401. TransformVertsAndTangents( tri->verts, deformInfo->numOutputVerts, deformInfo->verts, entJointsInverted );
  402. tri->referencedVerts = false;
  403. }
  404. tri->tangentsCalculated = true;
  405. CalculateBounds( entJoints, tri->bounds );
  406. }
  407. /*
  408. ====================
  409. idMD5Mesh::CalculateBounds
  410. ====================
  411. */
  412. void idMD5Mesh::CalculateBounds( const idJointMat * entJoints, idBounds & bounds ) const {
  413. #ifdef ID_WIN_X86_SSE2_INTRIN
  414. __m128 minX = vector_float_posInfinity;
  415. __m128 minY = vector_float_posInfinity;
  416. __m128 minZ = vector_float_posInfinity;
  417. __m128 maxX = vector_float_negInfinity;
  418. __m128 maxY = vector_float_negInfinity;
  419. __m128 maxZ = vector_float_negInfinity;
  420. for ( int i = 0; i < numMeshJoints; i++ ) {
  421. const idJointMat & joint = entJoints[meshJoints[i]];
  422. __m128 x = _mm_load_ps( joint.ToFloatPtr() + 0 * 4 );
  423. __m128 y = _mm_load_ps( joint.ToFloatPtr() + 1 * 4 );
  424. __m128 z = _mm_load_ps( joint.ToFloatPtr() + 2 * 4 );
  425. minX = _mm_min_ps( minX, x );
  426. minY = _mm_min_ps( minY, y );
  427. minZ = _mm_min_ps( minZ, z );
  428. maxX = _mm_max_ps( maxX, x );
  429. maxY = _mm_max_ps( maxY, y );
  430. maxZ = _mm_max_ps( maxZ, z );
  431. }
  432. __m128 expand = _mm_splat_ps( _mm_load_ss( & maxJointVertDist ), 0 );
  433. minX = _mm_sub_ps( minX, expand );
  434. minY = _mm_sub_ps( minY, expand );
  435. minZ = _mm_sub_ps( minZ, expand );
  436. maxX = _mm_add_ps( maxX, expand );
  437. maxY = _mm_add_ps( maxY, expand );
  438. maxZ = _mm_add_ps( maxZ, expand );
  439. _mm_store_ss( bounds.ToFloatPtr() + 0, _mm_splat_ps( minX, 3 ) );
  440. _mm_store_ss( bounds.ToFloatPtr() + 1, _mm_splat_ps( minY, 3 ) );
  441. _mm_store_ss( bounds.ToFloatPtr() + 2, _mm_splat_ps( minZ, 3 ) );
  442. _mm_store_ss( bounds.ToFloatPtr() + 3, _mm_splat_ps( maxX, 3 ) );
  443. _mm_store_ss( bounds.ToFloatPtr() + 4, _mm_splat_ps( maxY, 3 ) );
  444. _mm_store_ss( bounds.ToFloatPtr() + 5, _mm_splat_ps( maxZ, 3 ) );
  445. #else
  446. bounds.Clear();
  447. for ( int i = 0; i < numMeshJoints; i++ ) {
  448. const idJointMat & joint = entJoints[meshJoints[i]];
  449. bounds.AddPoint( joint.GetTranslation() );
  450. }
  451. bounds.ExpandSelf( maxJointVertDist );
  452. #endif
  453. }
  454. /*
  455. ====================
  456. idMD5Mesh::NearestJoint
  457. ====================
  458. */
  459. int idMD5Mesh::NearestJoint( int a, int b, int c ) const {
  460. // duplicated vertices might not have weights
  461. int vertNum;
  462. if ( a >= 0 && a < numVerts ) {
  463. vertNum = a;
  464. } else if ( b >= 0 && b < numVerts ) {
  465. vertNum = b;
  466. } else if ( c >= 0 && c < numVerts ) {
  467. vertNum = c;
  468. } else {
  469. // all vertices are duplicates which shouldn't happen
  470. return 0;
  471. }
  472. const idDrawVert & v = deformInfo->verts[vertNum];
  473. int bestWeight = 0;
  474. int bestJoint = 0;
  475. for ( int i = 0; i < 4; i++ ) {
  476. if ( v.color2[i] > bestWeight ) {
  477. bestWeight = v.color2[i];
  478. bestJoint = v.color[i];
  479. }
  480. }
  481. return bestJoint;
  482. }
  483. /***********************************************************************
  484. idRenderModelMD5
  485. ***********************************************************************/
  486. /*
  487. ====================
  488. idRenderModelMD5::ParseJoint
  489. ====================
  490. */
  491. void idRenderModelMD5::ParseJoint( idLexer &parser, idMD5Joint *joint, idJointQuat *defaultPose ) {
  492. //
  493. // parse name
  494. //
  495. idToken token;
  496. parser.ReadToken( &token );
  497. joint->name = token;
  498. //
  499. // parse parent
  500. //
  501. int num = parser.ParseInt();
  502. if ( num < 0 ) {
  503. joint->parent = NULL;
  504. } else {
  505. if ( num >= joints.Num() - 1 ) {
  506. parser.Error( "Invalid parent for joint '%s'", joint->name.c_str() );
  507. }
  508. joint->parent = &joints[ num ];
  509. }
  510. //
  511. // parse default pose
  512. //
  513. parser.Parse1DMatrix( 3, defaultPose->t.ToFloatPtr() );
  514. parser.Parse1DMatrix( 3, defaultPose->q.ToFloatPtr() );
  515. defaultPose->q.w = defaultPose->q.CalcW();
  516. }
  517. /*
  518. ====================
  519. idRenderModelMD5::InitFromFile
  520. ====================
  521. */
  522. void idRenderModelMD5::InitFromFile( const char *fileName ) {
  523. name = fileName;
  524. LoadModel();
  525. }
  526. /*
  527. ========================
  528. idRenderModelMD5::LoadBinaryModel
  529. ========================
  530. */
  531. bool idRenderModelMD5::LoadBinaryModel( idFile * file, const ID_TIME_T sourceTimeStamp ) {
  532. if ( !idRenderModelStatic::LoadBinaryModel( file, sourceTimeStamp ) ) {
  533. return false;
  534. }
  535. unsigned int magic = 0;
  536. file->ReadBig( magic );
  537. if ( magic != MD5B_MAGIC ) {
  538. return false;
  539. }
  540. int tempNum;
  541. file->ReadBig( tempNum );
  542. joints.SetNum( tempNum );
  543. for ( int i = 0; i < joints.Num(); i++ ) {
  544. file->ReadString( joints[i].name );
  545. int offset;
  546. file->ReadBig( offset );
  547. if ( offset >= 0 ) {
  548. joints[i].parent = joints.Ptr() + offset;
  549. } else {
  550. joints[i].parent = NULL;
  551. }
  552. }
  553. file->ReadBig( tempNum );
  554. defaultPose.SetNum( tempNum );
  555. for ( int i = 0; i < defaultPose.Num(); i++ ) {
  556. file->ReadBig( defaultPose[i].q.x );
  557. file->ReadBig( defaultPose[i].q.y );
  558. file->ReadBig( defaultPose[i].q.z );
  559. file->ReadBig( defaultPose[i].q.w );
  560. file->ReadVec3( defaultPose[i].t );
  561. }
  562. file->ReadBig( tempNum );
  563. invertedDefaultPose.SetNum( tempNum );
  564. for ( int i = 0; i < invertedDefaultPose.Num(); i++ ) {
  565. file->ReadBigArray( invertedDefaultPose[ i ].ToFloatPtr(), JOINTMAT_TYPESIZE );
  566. }
  567. SIMD_INIT_LAST_JOINT( invertedDefaultPose.Ptr(), joints.Num() );
  568. file->ReadBig( tempNum );
  569. meshes.SetNum( tempNum );
  570. for ( int i = 0; i < meshes.Num(); i++ ) {
  571. idStr materialName;
  572. file->ReadString( materialName );
  573. if ( materialName.IsEmpty() ) {
  574. meshes[i].shader = NULL;
  575. } else {
  576. meshes[i].shader = declManager->FindMaterial( materialName );
  577. }
  578. file->ReadBig( meshes[i].numVerts );
  579. file->ReadBig( meshes[i].numTris );
  580. file->ReadBig( meshes[i].numMeshJoints );
  581. meshes[i].meshJoints = (byte *) Mem_Alloc( meshes[i].numMeshJoints * sizeof( meshes[i].meshJoints[0] ), TAG_MODEL );
  582. file->ReadBigArray( meshes[i].meshJoints, meshes[i].numMeshJoints );
  583. file->ReadBig( meshes[i].maxJointVertDist );
  584. meshes[i].deformInfo = (deformInfo_t *)R_ClearedStaticAlloc( sizeof( deformInfo_t ) );
  585. deformInfo_t & deform = *meshes[i].deformInfo;
  586. file->ReadBig( deform.numSourceVerts );
  587. file->ReadBig( deform.numOutputVerts );
  588. file->ReadBig( deform.numIndexes );
  589. file->ReadBig( deform.numMirroredVerts );
  590. file->ReadBig( deform.numDupVerts );
  591. file->ReadBig( deform.numSilEdges );
  592. srfTriangles_t tri;
  593. memset( &tri, 0, sizeof( srfTriangles_t ) );
  594. if ( deform.numOutputVerts > 0 ) {
  595. R_AllocStaticTriSurfVerts( &tri, deform.numOutputVerts );
  596. deform.verts = tri.verts;
  597. file->ReadBigArray( deform.verts, deform.numOutputVerts );
  598. }
  599. if ( deform.numIndexes > 0 ) {
  600. R_AllocStaticTriSurfIndexes( &tri, deform.numIndexes );
  601. R_AllocStaticTriSurfSilIndexes( &tri, deform.numIndexes );
  602. deform.indexes = tri.indexes;
  603. deform.silIndexes = tri.silIndexes;
  604. file->ReadBigArray( deform.indexes, deform.numIndexes );
  605. file->ReadBigArray( deform.silIndexes, deform.numIndexes );
  606. }
  607. if ( deform.numMirroredVerts > 0 ) {
  608. R_AllocStaticTriSurfMirroredVerts( &tri, deform.numMirroredVerts );
  609. deform.mirroredVerts = tri.mirroredVerts;
  610. file->ReadBigArray( deform.mirroredVerts, deform.numMirroredVerts );
  611. }
  612. if ( deform.numDupVerts > 0 ) {
  613. R_AllocStaticTriSurfDupVerts( &tri, deform.numDupVerts );
  614. deform.dupVerts = tri.dupVerts;
  615. file->ReadBigArray( deform.dupVerts, deform.numDupVerts * 2 );
  616. }
  617. if ( deform.numSilEdges > 0 ) {
  618. R_AllocStaticTriSurfSilEdges( &tri, deform.numSilEdges );
  619. deform.silEdges = tri.silEdges;
  620. assert( deform.silEdges != NULL );
  621. for ( int j = 0; j < deform.numSilEdges; j++ ) {
  622. file->ReadBig( deform.silEdges[j].p1 );
  623. file->ReadBig( deform.silEdges[j].p2 );
  624. file->ReadBig( deform.silEdges[j].v1 );
  625. file->ReadBig( deform.silEdges[j].v2 );
  626. }
  627. }
  628. idShadowVertSkinned * shadowVerts = (idShadowVertSkinned *) Mem_Alloc( ALIGN( deform.numOutputVerts * 2 * sizeof( idShadowVertSkinned ), 16 ), TAG_MODEL );
  629. idShadowVertSkinned::CreateShadowCache( shadowVerts, deform.verts, deform.numOutputVerts );
  630. deform.staticAmbientCache = vertexCache.AllocStaticVertex( deform.verts, ALIGN( deform.numOutputVerts * sizeof( idDrawVert ), VERTEX_CACHE_ALIGN ) );
  631. deform.staticIndexCache = vertexCache.AllocStaticIndex( deform.indexes, ALIGN( deform.numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
  632. deform.staticShadowCache = vertexCache.AllocStaticVertex( shadowVerts, ALIGN( deform.numOutputVerts * 2 * sizeof( idShadowVertSkinned ), VERTEX_CACHE_ALIGN ) );
  633. Mem_Free( shadowVerts );
  634. file->ReadBig( meshes[i].surfaceNum );
  635. }
  636. return true;
  637. }
  638. /*
  639. ========================
  640. idRenderModelMD5::WriteBinaryModel
  641. ========================
  642. */
  643. void idRenderModelMD5::WriteBinaryModel( idFile * file, ID_TIME_T *_timeStamp ) const {
  644. idRenderModelStatic::WriteBinaryModel( file );
  645. if ( file == NULL ) {
  646. return;
  647. }
  648. file->WriteBig( MD5B_MAGIC );
  649. file->WriteBig( joints.Num() );
  650. for ( int i = 0; i < joints.Num(); i++ ) {
  651. file->WriteString( joints[i].name );
  652. int offset = -1;
  653. if ( joints[i].parent != NULL ) {
  654. offset = joints[i].parent - joints.Ptr();
  655. }
  656. file->WriteBig( offset );
  657. }
  658. file->WriteBig( defaultPose.Num() );
  659. for ( int i = 0; i < defaultPose.Num(); i++ ) {
  660. file->WriteBig( defaultPose[i].q.x );
  661. file->WriteBig( defaultPose[i].q.y );
  662. file->WriteBig( defaultPose[i].q.z );
  663. file->WriteBig( defaultPose[i].q.w );
  664. file->WriteVec3( defaultPose[i].t );
  665. }
  666. file->WriteBig( invertedDefaultPose.Num() );
  667. for ( int i = 0; i < invertedDefaultPose.Num(); i++ ) {
  668. file->WriteBigArray( invertedDefaultPose[ i ].ToFloatPtr(), JOINTMAT_TYPESIZE );
  669. }
  670. file->WriteBig( meshes.Num() );
  671. for ( int i = 0; i < meshes.Num(); i++ ) {
  672. if ( meshes[i].shader != NULL && meshes[i].shader->GetName() != NULL ) {
  673. file->WriteString( meshes[i].shader->GetName() );
  674. } else {
  675. file->WriteString( "" );
  676. }
  677. file->WriteBig( meshes[i].numVerts );
  678. file->WriteBig( meshes[i].numTris );
  679. file->WriteBig( meshes[i].numMeshJoints );
  680. file->WriteBigArray( meshes[i].meshJoints, meshes[i].numMeshJoints );
  681. file->WriteBig( meshes[i].maxJointVertDist );
  682. deformInfo_t & deform = *meshes[i].deformInfo;
  683. file->WriteBig( deform.numSourceVerts );
  684. file->WriteBig( deform.numOutputVerts );
  685. file->WriteBig( deform.numIndexes );
  686. file->WriteBig( deform.numMirroredVerts );
  687. file->WriteBig( deform.numDupVerts );
  688. file->WriteBig( deform.numSilEdges );
  689. if ( deform.numOutputVerts > 0 ) {
  690. file->WriteBigArray( deform.verts, deform.numOutputVerts );
  691. }
  692. if ( deform.numIndexes > 0 ) {
  693. file->WriteBigArray( deform.indexes, deform.numIndexes );
  694. file->WriteBigArray( deform.silIndexes, deform.numIndexes );
  695. }
  696. if ( deform.numMirroredVerts > 0 ) {
  697. file->WriteBigArray( deform.mirroredVerts, deform.numMirroredVerts );
  698. }
  699. if ( deform.numDupVerts > 0 ) {
  700. file->WriteBigArray( deform.dupVerts, deform.numDupVerts * 2 );
  701. }
  702. if ( deform.numSilEdges > 0 ) {
  703. for ( int j = 0; j < deform.numSilEdges; j++ ) {
  704. file->WriteBig( deform.silEdges[j].p1 );
  705. file->WriteBig( deform.silEdges[j].p2 );
  706. file->WriteBig( deform.silEdges[j].v1 );
  707. file->WriteBig( deform.silEdges[j].v2 );
  708. }
  709. }
  710. file->WriteBig( meshes[i].surfaceNum );
  711. }
  712. }
  713. /*
  714. ====================
  715. idRenderModelMD5::LoadModel
  716. used for initial loads, reloadModel, and reloading the data of purged models
  717. Upon exit, the model will absolutely be valid, but possibly as a default model
  718. ====================
  719. */
  720. void idRenderModelMD5::LoadModel() {
  721. int version;
  722. int num;
  723. int parentNum;
  724. idToken token;
  725. idLexer parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
  726. if ( !purged ) {
  727. PurgeModel();
  728. }
  729. purged = false;
  730. if ( !parser.LoadFile( name ) ) {
  731. MakeDefaultModel();
  732. return;
  733. }
  734. parser.ExpectTokenString( MD5_VERSION_STRING );
  735. version = parser.ParseInt();
  736. if ( version != MD5_VERSION ) {
  737. parser.Error( "Invalid version %d. Should be version %d\n", version, MD5_VERSION );
  738. }
  739. //
  740. // skip commandline
  741. //
  742. parser.ExpectTokenString( "commandline" );
  743. parser.ReadToken( &token );
  744. // parse num joints
  745. parser.ExpectTokenString( "numJoints" );
  746. num = parser.ParseInt();
  747. joints.SetGranularity( 1 );
  748. joints.SetNum( num );
  749. defaultPose.SetGranularity( 1 );
  750. defaultPose.SetNum( num );
  751. // parse num meshes
  752. parser.ExpectTokenString( "numMeshes" );
  753. num = parser.ParseInt();
  754. if ( num < 0 ) {
  755. parser.Error( "Invalid size: %d", num );
  756. }
  757. meshes.SetGranularity( 1 );
  758. meshes.SetNum( num );
  759. //
  760. // parse joints
  761. //
  762. parser.ExpectTokenString( "joints" );
  763. parser.ExpectTokenString( "{" );
  764. idJointMat *poseMat = ( idJointMat * )_alloca16( joints.Num() * sizeof( poseMat[0] ) );
  765. for( int i = 0; i < joints.Num(); i++ ) {
  766. idMD5Joint * joint = &joints[i];
  767. idJointQuat * pose = &defaultPose[i];
  768. ParseJoint( parser, joint, pose );
  769. poseMat[ i ].SetRotation( pose->q.ToMat3() );
  770. poseMat[ i ].SetTranslation( pose->t );
  771. if ( joint->parent ) {
  772. parentNum = joint->parent - joints.Ptr();
  773. pose->q = ( poseMat[ i ].ToMat3() * poseMat[ parentNum ].ToMat3().Transpose() ).ToQuat();
  774. pose->t = ( poseMat[ i ].ToVec3() - poseMat[ parentNum ].ToVec3() ) * poseMat[ parentNum ].ToMat3().Transpose();
  775. }
  776. }
  777. parser.ExpectTokenString( "}" );
  778. //-----------------------------------------
  779. // create the inverse of the base pose joints to support tech6 style deformation
  780. // of base pose vertexes, normals, and tangents.
  781. //
  782. // vertex * joints * inverseJoints == vertex when joints is the base pose
  783. // When the joints are in another pose, it gives the animated vertex position
  784. //-----------------------------------------
  785. invertedDefaultPose.SetNum( SIMD_ROUND_JOINTS( joints.Num() ) );
  786. for ( int i = 0; i < joints.Num(); i++ ) {
  787. invertedDefaultPose[i] = poseMat[i];
  788. invertedDefaultPose[i].Invert();
  789. }
  790. SIMD_INIT_LAST_JOINT( invertedDefaultPose.Ptr(), joints.Num() );
  791. for ( int i = 0; i < meshes.Num(); i++ ) {
  792. parser.ExpectTokenString( "mesh" );
  793. meshes[i].ParseMesh( parser, defaultPose.Num(), poseMat );
  794. }
  795. // calculate the bounds of the model
  796. bounds.Clear();
  797. for ( int i = 0; i < meshes.Num(); i++ ) {
  798. idBounds meshBounds;
  799. meshes[i].CalculateBounds( poseMat, meshBounds );
  800. bounds.AddBounds( meshBounds );
  801. }
  802. // set the timestamp for reloadmodels
  803. fileSystem->ReadFile( name, NULL, &timeStamp );
  804. common->UpdateLevelLoadPacifier();
  805. }
  806. /*
  807. ==============
  808. idRenderModelMD5::Print
  809. ==============
  810. */
  811. void idRenderModelMD5::Print() const {
  812. common->Printf( "%s\n", name.c_str() );
  813. common->Printf( "Dynamic model.\n" );
  814. common->Printf( "Generated smooth normals.\n" );
  815. common->Printf( " verts tris weights material\n" );
  816. int totalVerts = 0;
  817. int totalTris = 0;
  818. const idMD5Mesh * mesh = meshes.Ptr();
  819. for ( int i = 0; i < meshes.Num(); i++, mesh++ ) {
  820. totalVerts += mesh->NumVerts();
  821. totalTris += mesh->NumTris();
  822. common->Printf( "%2i: %5i %5i %s\n", i, mesh->NumVerts(), mesh->NumTris(), mesh->shader->GetName() );
  823. }
  824. common->Printf( "-----\n" );
  825. common->Printf( "%4i verts.\n", totalVerts );
  826. common->Printf( "%4i tris.\n", totalTris );
  827. common->Printf( "%4i joints.\n", joints.Num() );
  828. }
  829. /*
  830. ==============
  831. idRenderModelMD5::List
  832. ==============
  833. */
  834. void idRenderModelMD5::List() const {
  835. int i;
  836. const idMD5Mesh *mesh;
  837. int totalTris = 0;
  838. int totalVerts = 0;
  839. for( mesh = meshes.Ptr(), i = 0; i < meshes.Num(); i++, mesh++ ) {
  840. totalTris += mesh->numTris;
  841. totalVerts += mesh->NumVerts();
  842. }
  843. common->Printf( " %4ik %3i %4i %4i %s(MD5)", Memory()/1024, meshes.Num(), totalVerts, totalTris, Name() );
  844. if ( defaulted ) {
  845. common->Printf( " (DEFAULTED)" );
  846. }
  847. common->Printf( "\n" );
  848. }
  849. /*
  850. ====================
  851. idRenderModelMD5::Bounds
  852. This calculates a rough bounds by using the joint radii without
  853. transforming all the points
  854. ====================
  855. */
  856. idBounds idRenderModelMD5::Bounds( const renderEntity_t *ent ) const {
  857. if ( ent == NULL ) {
  858. // this is the bounds for the reference pose
  859. return bounds;
  860. }
  861. return ent->bounds;
  862. }
  863. /*
  864. ====================
  865. idRenderModelMD5::DrawJoints
  866. ====================
  867. */
  868. void idRenderModelMD5::DrawJoints( const renderEntity_t *ent, const viewDef_t *view ) const {
  869. int i;
  870. int num;
  871. idVec3 pos;
  872. const idJointMat *joint;
  873. const idMD5Joint *md5Joint;
  874. int parentNum;
  875. num = ent->numJoints;
  876. joint = ent->joints;
  877. md5Joint = joints.Ptr();
  878. for( i = 0; i < num; i++, joint++, md5Joint++ ) {
  879. pos = ent->origin + joint->ToVec3() * ent->axis;
  880. if ( md5Joint->parent ) {
  881. parentNum = md5Joint->parent - joints.Ptr();
  882. common->RW()->DebugLine( colorWhite, ent->origin + ent->joints[ parentNum ].ToVec3() * ent->axis, pos );
  883. }
  884. common->RW()->DebugLine( colorRed, pos, pos + joint->ToMat3()[ 0 ] * 2.0f * ent->axis );
  885. common->RW()->DebugLine( colorGreen,pos, pos + joint->ToMat3()[ 1 ] * 2.0f * ent->axis );
  886. common->RW()->DebugLine( colorBlue, pos, pos + joint->ToMat3()[ 2 ] * 2.0f * ent->axis );
  887. }
  888. idBounds bounds;
  889. bounds.FromTransformedBounds( ent->bounds, vec3_zero, ent->axis );
  890. common->RW()->DebugBounds( colorMagenta, bounds, ent->origin );
  891. if ( ( r_jointNameScale.GetFloat() != 0.0f ) && ( bounds.Expand( 128.0f ).ContainsPoint( view->renderView.vieworg - ent->origin ) ) ) {
  892. idVec3 offset( 0, 0, r_jointNameOffset.GetFloat() );
  893. float scale;
  894. scale = r_jointNameScale.GetFloat();
  895. joint = ent->joints;
  896. num = ent->numJoints;
  897. for( i = 0; i < num; i++, joint++ ) {
  898. pos = ent->origin + joint->ToVec3() * ent->axis;
  899. common->RW()->DrawText( joints[ i ].name, pos + offset, scale, colorWhite, view->renderView.viewaxis, 1 );
  900. }
  901. }
  902. }
  903. /*
  904. ====================
  905. TransformJoints
  906. ====================
  907. */
  908. static void TransformJoints( idJointMat *__restrict outJoints, const int numJoints, const idJointMat *__restrict inJoints1, const idJointMat *__restrict inJoints2 ) {
  909. float * outFloats = outJoints->ToFloatPtr();
  910. const float * inFloats1 = inJoints1->ToFloatPtr();
  911. const float * inFloats2 = inJoints2->ToFloatPtr();
  912. assert_16_byte_aligned( outFloats );
  913. assert_16_byte_aligned( inFloats1 );
  914. assert_16_byte_aligned( inFloats2 );
  915. #ifdef ID_WIN_X86_SSE2_INTRIN
  916. const __m128 mask_keep_last = __m128c( _mm_set_epi32( 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 ) );
  917. for ( int i = 0; i < numJoints; i += 2, inFloats1 += 2 * 12, inFloats2 += 2 * 12, outFloats += 2 * 12 ) {
  918. __m128 m1a0 = _mm_load_ps( inFloats1 + 0 * 12 + 0 );
  919. __m128 m1b0 = _mm_load_ps( inFloats1 + 0 * 12 + 4 );
  920. __m128 m1c0 = _mm_load_ps( inFloats1 + 0 * 12 + 8 );
  921. __m128 m1a1 = _mm_load_ps( inFloats1 + 1 * 12 + 0 );
  922. __m128 m1b1 = _mm_load_ps( inFloats1 + 1 * 12 + 4 );
  923. __m128 m1c1 = _mm_load_ps( inFloats1 + 1 * 12 + 8 );
  924. __m128 m2a0 = _mm_load_ps( inFloats2 + 0 * 12 + 0 );
  925. __m128 m2b0 = _mm_load_ps( inFloats2 + 0 * 12 + 4 );
  926. __m128 m2c0 = _mm_load_ps( inFloats2 + 0 * 12 + 8 );
  927. __m128 m2a1 = _mm_load_ps( inFloats2 + 1 * 12 + 0 );
  928. __m128 m2b1 = _mm_load_ps( inFloats2 + 1 * 12 + 4 );
  929. __m128 m2c1 = _mm_load_ps( inFloats2 + 1 * 12 + 8 );
  930. __m128 tj0 = _mm_and_ps( m1a0, mask_keep_last );
  931. __m128 tk0 = _mm_and_ps( m1b0, mask_keep_last );
  932. __m128 tl0 = _mm_and_ps( m1c0, mask_keep_last );
  933. __m128 tj1 = _mm_and_ps( m1a1, mask_keep_last );
  934. __m128 tk1 = _mm_and_ps( m1b1, mask_keep_last );
  935. __m128 tl1 = _mm_and_ps( m1c1, mask_keep_last );
  936. __m128 ta0 = _mm_splat_ps( m1a0, 0 );
  937. __m128 td0 = _mm_splat_ps( m1b0, 0 );
  938. __m128 tg0 = _mm_splat_ps( m1c0, 0 );
  939. __m128 ta1 = _mm_splat_ps( m1a1, 0 );
  940. __m128 td1 = _mm_splat_ps( m1b1, 0 );
  941. __m128 tg1 = _mm_splat_ps( m1c1, 0 );
  942. __m128 ra0 = _mm_add_ps( tj0, _mm_mul_ps( ta0, m2a0 ) );
  943. __m128 rd0 = _mm_add_ps( tk0, _mm_mul_ps( td0, m2a0 ) );
  944. __m128 rg0 = _mm_add_ps( tl0, _mm_mul_ps( tg0, m2a0 ) );
  945. __m128 ra1 = _mm_add_ps( tj1, _mm_mul_ps( ta1, m2a1 ) );
  946. __m128 rd1 = _mm_add_ps( tk1, _mm_mul_ps( td1, m2a1 ) );
  947. __m128 rg1 = _mm_add_ps( tl1, _mm_mul_ps( tg1, m2a1 ) );
  948. __m128 tb0 = _mm_splat_ps( m1a0, 1 );
  949. __m128 te0 = _mm_splat_ps( m1b0, 1 );
  950. __m128 th0 = _mm_splat_ps( m1c0, 1 );
  951. __m128 tb1 = _mm_splat_ps( m1a1, 1 );
  952. __m128 te1 = _mm_splat_ps( m1b1, 1 );
  953. __m128 th1 = _mm_splat_ps( m1c1, 1 );
  954. __m128 rb0 = _mm_add_ps( ra0, _mm_mul_ps( tb0, m2b0 ) );
  955. __m128 re0 = _mm_add_ps( rd0, _mm_mul_ps( te0, m2b0 ) );
  956. __m128 rh0 = _mm_add_ps( rg0, _mm_mul_ps( th0, m2b0 ) );
  957. __m128 rb1 = _mm_add_ps( ra1, _mm_mul_ps( tb1, m2b1 ) );
  958. __m128 re1 = _mm_add_ps( rd1, _mm_mul_ps( te1, m2b1 ) );
  959. __m128 rh1 = _mm_add_ps( rg1, _mm_mul_ps( th1, m2b1 ) );
  960. __m128 tc0 = _mm_splat_ps( m1a0, 2 );
  961. __m128 tf0 = _mm_splat_ps( m1b0, 2 );
  962. __m128 ti0 = _mm_splat_ps( m1c0, 2 );
  963. __m128 tf1 = _mm_splat_ps( m1b1, 2 );
  964. __m128 ti1 = _mm_splat_ps( m1c1, 2 );
  965. __m128 tc1 = _mm_splat_ps( m1a1, 2 );
  966. __m128 rc0 = _mm_add_ps( rb0, _mm_mul_ps( tc0, m2c0 ) );
  967. __m128 rf0 = _mm_add_ps( re0, _mm_mul_ps( tf0, m2c0 ) );
  968. __m128 ri0 = _mm_add_ps( rh0, _mm_mul_ps( ti0, m2c0 ) );
  969. __m128 rc1 = _mm_add_ps( rb1, _mm_mul_ps( tc1, m2c1 ) );
  970. __m128 rf1 = _mm_add_ps( re1, _mm_mul_ps( tf1, m2c1 ) );
  971. __m128 ri1 = _mm_add_ps( rh1, _mm_mul_ps( ti1, m2c1 ) );
  972. _mm_store_ps( outFloats + 0 * 12 + 0, rc0 );
  973. _mm_store_ps( outFloats + 0 * 12 + 4, rf0 );
  974. _mm_store_ps( outFloats + 0 * 12 + 8, ri0 );
  975. _mm_store_ps( outFloats + 1 * 12 + 0, rc1 );
  976. _mm_store_ps( outFloats + 1 * 12 + 4, rf1 );
  977. _mm_store_ps( outFloats + 1 * 12 + 8, ri1 );
  978. }
  979. #else
  980. for ( int i = 0; i < numJoints; i++ ) {
  981. idJointMat::Multiply( outJoints[i], inJoints1[i], inJoints2[i] );
  982. }
  983. #endif
  984. }
  985. /*
  986. ====================
  987. idRenderModelMD5::InstantiateDynamicModel
  988. ====================
  989. */
  990. idRenderModel *idRenderModelMD5::InstantiateDynamicModel( const struct renderEntity_s *ent, const viewDef_t *view, idRenderModel *cachedModel ) {
  991. if ( cachedModel != NULL && !r_useCachedDynamicModels.GetBool() ) {
  992. delete cachedModel;
  993. cachedModel = NULL;
  994. }
  995. if ( purged ) {
  996. common->DWarning( "model %s instantiated while purged", Name() );
  997. LoadModel();
  998. }
  999. if ( !ent->joints ) {
  1000. common->Printf( "idRenderModelMD5::InstantiateDynamicModel: NULL joints on renderEntity for '%s'\n", Name() );
  1001. delete cachedModel;
  1002. return NULL;
  1003. } else if ( ent->numJoints != joints.Num() ) {
  1004. common->Printf( "idRenderModelMD5::InstantiateDynamicModel: renderEntity has different number of joints than model for '%s'\n", Name() );
  1005. delete cachedModel;
  1006. return NULL;
  1007. }
  1008. tr.pc.c_generateMd5++;
  1009. idRenderModelStatic * staticModel;
  1010. if ( cachedModel != NULL ) {
  1011. assert( dynamic_cast<idRenderModelStatic *>(cachedModel) != NULL );
  1012. assert( idStr::Icmp( cachedModel->Name(), MD5_SnapshotName ) == 0 );
  1013. staticModel = static_cast<idRenderModelStatic *>(cachedModel);
  1014. } else {
  1015. staticModel = new (TAG_MODEL) idRenderModelStatic;
  1016. staticModel->InitEmpty( MD5_SnapshotName );
  1017. }
  1018. staticModel->bounds.Clear();
  1019. if ( r_showSkel.GetInteger() ) {
  1020. if ( ( view != NULL ) && ( !r_skipSuppress.GetBool() || !ent->suppressSurfaceInViewID || ( ent->suppressSurfaceInViewID != view->renderView.viewID ) ) ) {
  1021. // only draw the skeleton
  1022. DrawJoints( ent, view );
  1023. }
  1024. if ( r_showSkel.GetInteger() > 1 ) {
  1025. // turn off the model when showing the skeleton
  1026. staticModel->InitEmpty( MD5_SnapshotName );
  1027. return staticModel;
  1028. }
  1029. }
  1030. // update the GPU joints array
  1031. const int numInvertedJoints = SIMD_ROUND_JOINTS( joints.Num() );
  1032. if ( staticModel->jointsInverted == NULL ) {
  1033. staticModel->numInvertedJoints = numInvertedJoints;
  1034. const int alignment = glConfig.uniformBufferOffsetAlignment;
  1035. staticModel->jointsInverted = (idJointMat *)Mem_ClearedAlloc( ALIGN( numInvertedJoints * sizeof( idJointMat ), alignment ), TAG_JOINTMAT );
  1036. staticModel->jointsInvertedBuffer = 0;
  1037. } else {
  1038. assert( staticModel->numInvertedJoints == numInvertedJoints );
  1039. }
  1040. TransformJoints( staticModel->jointsInverted, joints.Num(), ent->joints, invertedDefaultPose.Ptr() );
  1041. // create all the surfaces
  1042. idMD5Mesh * mesh = meshes.Ptr();
  1043. for ( int i = 0; i < meshes.Num(); i++, mesh++ ) {
  1044. // avoid deforming the surface if it will be a nodraw due to a skin remapping
  1045. const idMaterial *shader = mesh->shader;
  1046. shader = R_RemapShaderBySkin( shader, ent->customSkin, ent->customShader );
  1047. if ( !shader || ( !shader->IsDrawn() && !shader->SurfaceCastsShadow() ) ) {
  1048. staticModel->DeleteSurfaceWithId( i );
  1049. mesh->surfaceNum = -1;
  1050. continue;
  1051. }
  1052. modelSurface_t *surf;
  1053. int surfaceNum = 0;
  1054. if ( staticModel->FindSurfaceWithId( i, surfaceNum ) ) {
  1055. mesh->surfaceNum = surfaceNum;
  1056. surf = &staticModel->surfaces[surfaceNum];
  1057. } else {
  1058. mesh->surfaceNum = staticModel->NumSurfaces();
  1059. surf = &staticModel->surfaces.Alloc();
  1060. surf->geometry = NULL;
  1061. surf->shader = NULL;
  1062. surf->id = i;
  1063. }
  1064. mesh->UpdateSurface( ent, ent->joints, staticModel->jointsInverted, surf );
  1065. assert( surf->geometry != NULL ); // to get around compiler warning
  1066. // the deformation of the tangents can be deferred until each surface is added to the view
  1067. surf->geometry->staticModelWithJoints = staticModel;
  1068. staticModel->bounds.AddBounds( surf->geometry->bounds );
  1069. }
  1070. return staticModel;
  1071. }
  1072. /*
  1073. ====================
  1074. idRenderModelMD5::IsDynamicModel
  1075. ====================
  1076. */
  1077. dynamicModel_t idRenderModelMD5::IsDynamicModel() const {
  1078. return DM_CACHED;
  1079. }
  1080. /*
  1081. ====================
  1082. idRenderModelMD5::NumJoints
  1083. ====================
  1084. */
  1085. int idRenderModelMD5::NumJoints() const {
  1086. return joints.Num();
  1087. }
  1088. /*
  1089. ====================
  1090. idRenderModelMD5::GetJoints
  1091. ====================
  1092. */
  1093. const idMD5Joint *idRenderModelMD5::GetJoints() const {
  1094. return joints.Ptr();
  1095. }
  1096. /*
  1097. ====================
  1098. idRenderModelMD5::GetDefaultPose
  1099. ====================
  1100. */
  1101. const idJointQuat *idRenderModelMD5::GetDefaultPose() const {
  1102. return defaultPose.Ptr();
  1103. }
  1104. /*
  1105. ====================
  1106. idRenderModelMD5::GetJointHandle
  1107. ====================
  1108. */
  1109. jointHandle_t idRenderModelMD5::GetJointHandle( const char *name ) const {
  1110. const idMD5Joint *joint = joints.Ptr();
  1111. for ( int i = 0; i < joints.Num(); i++, joint++ ) {
  1112. if ( idStr::Icmp( joint->name.c_str(), name ) == 0 ) {
  1113. return ( jointHandle_t )i;
  1114. }
  1115. }
  1116. return INVALID_JOINT;
  1117. }
  1118. /*
  1119. =====================
  1120. idRenderModelMD5::GetJointName
  1121. =====================
  1122. */
  1123. const char *idRenderModelMD5::GetJointName( jointHandle_t handle ) const {
  1124. if ( ( handle < 0 ) || ( handle >= joints.Num() ) ) {
  1125. return "<invalid joint>";
  1126. }
  1127. return joints[ handle ].name;
  1128. }
  1129. /*
  1130. ====================
  1131. idRenderModelMD5::NearestJoint
  1132. ====================
  1133. */
  1134. int idRenderModelMD5::NearestJoint( int surfaceNum, int a, int b, int c ) const {
  1135. if ( surfaceNum > meshes.Num() ) {
  1136. common->Error( "idRenderModelMD5::NearestJoint: surfaceNum > meshes.Num()" );
  1137. }
  1138. const idMD5Mesh *mesh = meshes.Ptr();
  1139. for ( int i = 0; i < meshes.Num(); i++, mesh++ ) {
  1140. if ( mesh->surfaceNum == surfaceNum ) {
  1141. return mesh->NearestJoint( a, b, c );
  1142. }
  1143. }
  1144. return 0;
  1145. }
  1146. /*
  1147. ====================
  1148. idRenderModelMD5::TouchData
  1149. models that are already loaded at level start time
  1150. will still touch their materials to make sure they
  1151. are kept loaded
  1152. ====================
  1153. */
  1154. void idRenderModelMD5::TouchData() {
  1155. for ( int i = 0; i < meshes.Num(); i++ ) {
  1156. declManager->FindMaterial( meshes[i].shader->GetName() );
  1157. }
  1158. }
  1159. /*
  1160. ===================
  1161. idRenderModelMD5::PurgeModel
  1162. frees all the data, but leaves the class around for dangling references,
  1163. which can regenerate the data with LoadModel()
  1164. ===================
  1165. */
  1166. void idRenderModelMD5::PurgeModel() {
  1167. purged = true;
  1168. joints.Clear();
  1169. defaultPose.Clear();
  1170. meshes.Clear();
  1171. }
  1172. /*
  1173. ===================
  1174. idRenderModelMD5::Memory
  1175. ===================
  1176. */
  1177. int idRenderModelMD5::Memory() const {
  1178. int total = sizeof( *this );
  1179. total += joints.MemoryUsed() + defaultPose.MemoryUsed() + meshes.MemoryUsed();
  1180. // count up strings
  1181. for ( int i = 0; i < joints.Num(); i++ ) {
  1182. total += joints[i].name.DynamicMemoryUsed();
  1183. }
  1184. // count up meshes
  1185. for ( int i = 0; i < meshes.Num(); i++ ) {
  1186. const idMD5Mesh *mesh = &meshes[i];
  1187. total += mesh->numMeshJoints * sizeof( mesh->meshJoints[0] );
  1188. // sum up deform info
  1189. total += sizeof( mesh->deformInfo );
  1190. total += R_DeformInfoMemoryUsed( mesh->deformInfo );
  1191. }
  1192. return total;
  1193. }