Model.cpp 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483
  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. #include "Model_ase.h"
  25. #include "Model_lwo.h"
  26. #include "Model_ma.h"
  27. idCVar idRenderModelStatic::r_mergeModelSurfaces( "r_mergeModelSurfaces", "1", CVAR_BOOL|CVAR_RENDERER, "combine model surfaces with the same material" );
  28. idCVar idRenderModelStatic::r_slopVertex( "r_slopVertex", "0.01", CVAR_RENDERER, "merge xyz coordinates this far apart" );
  29. idCVar idRenderModelStatic::r_slopTexCoord( "r_slopTexCoord", "0.001", CVAR_RENDERER, "merge texture coordinates this far apart" );
  30. idCVar idRenderModelStatic::r_slopNormal( "r_slopNormal", "0.02", CVAR_RENDERER, "merge normals that dot less than this" );
  31. static const byte BRM_VERSION = 108;
  32. static const unsigned int BRM_MAGIC = ( 'B' << 24 ) | ( 'R' << 16 ) | ( 'M' << 8 ) | BRM_VERSION;
  33. /*
  34. ================
  35. idRenderModelStatic::idRenderModelStatic
  36. ================
  37. */
  38. idRenderModelStatic::idRenderModelStatic() {
  39. name = "<undefined>";
  40. bounds.Clear();
  41. lastModifiedFrame = 0;
  42. lastArchivedFrame = 0;
  43. overlaysAdded = 0;
  44. isStaticWorldModel = false;
  45. defaulted = false;
  46. purged = false;
  47. fastLoad = false;
  48. reloadable = true;
  49. levelLoadReferenced = false;
  50. hasDrawingSurfaces = true;
  51. hasInteractingSurfaces = true;
  52. hasShadowCastingSurfaces = true;
  53. timeStamp = 0;
  54. numInvertedJoints = 0;
  55. jointsInverted = NULL;
  56. jointsInvertedBuffer = 0;
  57. }
  58. /*
  59. ================
  60. idRenderModelStatic::~idRenderModelStatic
  61. ================
  62. */
  63. idRenderModelStatic::~idRenderModelStatic() {
  64. PurgeModel();
  65. }
  66. /*
  67. ==============
  68. idRenderModelStatic::Print
  69. ==============
  70. */
  71. void idRenderModelStatic::Print() const {
  72. common->Printf( "%s\n", name.c_str() );
  73. common->Printf( "Static model.\n" );
  74. common->Printf( "bounds: (%f %f %f) to (%f %f %f)\n",
  75. bounds[0][0], bounds[0][1], bounds[0][2],
  76. bounds[1][0], bounds[1][1], bounds[1][2] );
  77. common->Printf( " verts tris material\n" );
  78. for ( int i = 0; i < NumSurfaces(); i++ ) {
  79. const modelSurface_t *surf = Surface( i );
  80. srfTriangles_t *tri = surf->geometry;
  81. const idMaterial *material = surf->shader;
  82. if ( !tri ) {
  83. common->Printf( "%2i: %s, NULL surface geometry\n", i, material->GetName() );
  84. continue;
  85. }
  86. common->Printf( "%2i: %5i %5i %s", i, tri->numVerts, tri->numIndexes / 3, material->GetName() );
  87. if ( tri->generateNormals ) {
  88. common->Printf( " (smoothed)\n" );
  89. } else {
  90. common->Printf( "\n" );
  91. }
  92. }
  93. }
  94. /*
  95. ==============
  96. idRenderModelStatic::Memory
  97. ==============
  98. */
  99. int idRenderModelStatic::Memory() const {
  100. int totalBytes = 0;
  101. totalBytes += sizeof( *this );
  102. totalBytes += name.DynamicMemoryUsed();
  103. totalBytes += surfaces.MemoryUsed();
  104. for ( int j = 0; j < NumSurfaces(); j++ ) {
  105. const modelSurface_t *surf = Surface( j );
  106. if ( !surf->geometry ) {
  107. continue;
  108. }
  109. totalBytes += R_TriSurfMemory( surf->geometry );
  110. }
  111. return totalBytes;
  112. }
  113. /*
  114. ==============
  115. idRenderModelStatic::List
  116. ==============
  117. */
  118. void idRenderModelStatic::List() const {
  119. int totalTris = 0;
  120. int totalVerts = 0;
  121. int totalBytes = 0;
  122. totalBytes = Memory();
  123. char closed = 'C';
  124. for ( int j = 0; j < NumSurfaces(); j++ ) {
  125. const modelSurface_t *surf = Surface( j );
  126. if ( !surf->geometry ) {
  127. continue;
  128. }
  129. if ( !surf->geometry->perfectHull ) {
  130. closed = ' ';
  131. }
  132. totalTris += surf->geometry->numIndexes / 3;
  133. totalVerts += surf->geometry->numVerts;
  134. }
  135. common->Printf( "%c%4ik %3i %4i %4i %s", closed, totalBytes/1024, NumSurfaces(), totalVerts, totalTris, Name() );
  136. if ( IsDynamicModel() == DM_CACHED ) {
  137. common->Printf( " (DM_CACHED)" );
  138. }
  139. if ( IsDynamicModel() == DM_CONTINUOUS ) {
  140. common->Printf( " (DM_CONTINUOUS)" );
  141. }
  142. if ( defaulted ) {
  143. common->Printf( " (DEFAULTED)" );
  144. }
  145. if ( bounds[0][0] >= bounds[1][0] ) {
  146. common->Printf( " (EMPTY BOUNDS)" );
  147. }
  148. if ( bounds[1][0] - bounds[0][0] > 100000 ) {
  149. common->Printf( " (HUGE BOUNDS)" );
  150. }
  151. common->Printf( "\n" );
  152. }
  153. /*
  154. ================
  155. idRenderModelStatic::IsDefaultModel
  156. ================
  157. */
  158. bool idRenderModelStatic::IsDefaultModel() const {
  159. return defaulted;
  160. }
  161. /*
  162. ================
  163. AddCubeFace
  164. ================
  165. */
  166. static void AddCubeFace( srfTriangles_t *tri, idVec3 v1, idVec3 v2, idVec3 v3, idVec3 v4 ) {
  167. tri->verts[tri->numVerts+0].Clear();
  168. tri->verts[tri->numVerts+0].xyz = v1 * 8;
  169. tri->verts[tri->numVerts+0].SetTexCoord( 0, 0 );
  170. tri->verts[tri->numVerts+1].Clear();
  171. tri->verts[tri->numVerts+1].xyz = v2 * 8;
  172. tri->verts[tri->numVerts+1].SetTexCoord( 1, 0 );
  173. tri->verts[tri->numVerts+2].Clear();
  174. tri->verts[tri->numVerts+2].xyz = v3 * 8;
  175. tri->verts[tri->numVerts+2].SetTexCoord( 1, 1 );
  176. tri->verts[tri->numVerts+3].Clear();
  177. tri->verts[tri->numVerts+3].xyz = v4 * 8;
  178. tri->verts[tri->numVerts+3].SetTexCoord( 0, 1 );
  179. tri->indexes[tri->numIndexes+0] = tri->numVerts + 0;
  180. tri->indexes[tri->numIndexes+1] = tri->numVerts + 1;
  181. tri->indexes[tri->numIndexes+2] = tri->numVerts + 2;
  182. tri->indexes[tri->numIndexes+3] = tri->numVerts + 0;
  183. tri->indexes[tri->numIndexes+4] = tri->numVerts + 2;
  184. tri->indexes[tri->numIndexes+5] = tri->numVerts + 3;
  185. tri->numVerts += 4;
  186. tri->numIndexes += 6;
  187. }
  188. /*
  189. ================
  190. idRenderModelStatic::MakeDefaultModel
  191. ================
  192. */
  193. void idRenderModelStatic::MakeDefaultModel() {
  194. defaulted = true;
  195. // throw out any surfaces we already have
  196. PurgeModel();
  197. // create one new surface
  198. modelSurface_t surf;
  199. srfTriangles_t *tri = R_AllocStaticTriSurf();
  200. surf.shader = tr.defaultMaterial;
  201. surf.geometry = tri;
  202. R_AllocStaticTriSurfVerts( tri, 24 );
  203. R_AllocStaticTriSurfIndexes( tri, 36 );
  204. AddCubeFace( tri, idVec3(-1, 1, 1), idVec3(1, 1, 1), idVec3(1, -1, 1), idVec3(-1, -1, 1) );
  205. AddCubeFace( tri, idVec3(-1, 1, -1), idVec3(-1, -1, -1), idVec3(1, -1, -1), idVec3(1, 1, -1) );
  206. AddCubeFace( tri, idVec3(1, -1, 1), idVec3(1, 1, 1), idVec3(1, 1, -1), idVec3(1, -1, -1) );
  207. AddCubeFace( tri, idVec3(-1, -1, 1), idVec3(-1, -1, -1), idVec3(-1, 1, -1), idVec3(-1, 1, 1) );
  208. AddCubeFace( tri, idVec3(-1, -1, 1), idVec3(1, -1, 1), idVec3(1, -1, -1), idVec3(-1, -1, -1) );
  209. AddCubeFace( tri, idVec3(-1, 1, 1), idVec3(-1, 1, -1), idVec3(1, 1, -1), idVec3(1, 1, 1) );
  210. tri->generateNormals = true;
  211. AddSurface( surf );
  212. FinishSurfaces();
  213. }
  214. /*
  215. ================
  216. idRenderModelStatic::PartialInitFromFile
  217. ================
  218. */
  219. void idRenderModelStatic::PartialInitFromFile( const char *fileName ) {
  220. fastLoad = true;
  221. InitFromFile( fileName );
  222. }
  223. /*
  224. ================
  225. idRenderModelStatic::InitFromFile
  226. ================
  227. */
  228. void idRenderModelStatic::InitFromFile( const char *fileName ) {
  229. bool loaded;
  230. idStr extension;
  231. InitEmpty( fileName );
  232. // FIXME: load new .proc map format
  233. name.ExtractFileExtension( extension );
  234. if ( extension.Icmp( "ase" ) == 0 ) {
  235. loaded = LoadASE( name );
  236. reloadable = true;
  237. } else if ( extension.Icmp( "lwo" ) == 0 ) {
  238. loaded = LoadLWO( name );
  239. reloadable = true;
  240. } else if ( extension.Icmp( "ma" ) == 0 ) {
  241. loaded = LoadMA( name );
  242. reloadable = true;
  243. } else {
  244. common->Warning( "idRenderModelStatic::InitFromFile: unknown type for model: \'%s\'", name.c_str() );
  245. loaded = false;
  246. }
  247. if ( !loaded ) {
  248. common->Warning( "Couldn't load model: '%s'", name.c_str() );
  249. MakeDefaultModel();
  250. return;
  251. }
  252. // it is now available for use
  253. purged = false;
  254. // create the bounds for culling and dynamic surface creation
  255. FinishSurfaces();
  256. }
  257. /*
  258. ========================
  259. idRenderModelStatic::LoadBinaryModel
  260. ========================
  261. */
  262. bool idRenderModelStatic::LoadBinaryModel( idFile * file, const ID_TIME_T sourceTimeStamp ) {
  263. if ( file == NULL ) {
  264. return false;
  265. }
  266. unsigned int magic = 0;
  267. file->ReadBig( magic );
  268. if ( magic != BRM_MAGIC ) {
  269. return false;
  270. }
  271. file->ReadBig( timeStamp );
  272. if ( !fileSystem->InProductionMode() && sourceTimeStamp != timeStamp ) {
  273. return false;
  274. }
  275. common->UpdateLevelLoadPacifier();
  276. int numSurfaces;
  277. file->ReadBig( numSurfaces );
  278. surfaces.SetNum( numSurfaces );
  279. for ( int i = 0; i < surfaces.Num(); i++ ) {
  280. file->ReadBig( surfaces[i].id );
  281. idStr materialName;
  282. file->ReadString( materialName );
  283. if ( materialName.IsEmpty() ) {
  284. surfaces[i].shader = NULL;
  285. } else {
  286. surfaces[i].shader = declManager->FindMaterial( materialName );
  287. }
  288. bool isGeometry;
  289. file->ReadBig( isGeometry );
  290. surfaces[i].geometry = NULL;
  291. if ( isGeometry ) {
  292. bool temp;
  293. surfaces[i].geometry = R_AllocStaticTriSurf();
  294. // Read the contents of srfTriangles_t
  295. srfTriangles_t & tri = *surfaces[i].geometry;
  296. file->ReadVec3( tri.bounds[0] );
  297. file->ReadVec3( tri.bounds[1] );
  298. int ambientViewCount = 0; // FIXME: remove
  299. file->ReadBig( ambientViewCount );
  300. file->ReadBig( tri.generateNormals );
  301. file->ReadBig( tri.tangentsCalculated );
  302. file->ReadBig( tri.perfectHull );
  303. file->ReadBig( tri.referencedIndexes );
  304. file->ReadBig( tri.numVerts );
  305. tri.verts = NULL;
  306. int numInFile = 0;
  307. file->ReadBig( numInFile );
  308. if ( numInFile > 0 ) {
  309. R_AllocStaticTriSurfVerts( &tri, tri.numVerts );
  310. assert( tri.verts != NULL );
  311. for ( int j = 0; j < tri.numVerts; j++ ) {
  312. file->ReadVec3( tri.verts[j].xyz );
  313. file->ReadBigArray( tri.verts[j].st, 2 );
  314. file->ReadBigArray( tri.verts[j].normal, 4 );
  315. file->ReadBigArray( tri.verts[j].tangent, 4 );
  316. file->ReadBigArray( tri.verts[j].color, sizeof( tri.verts[j].color ) / sizeof( tri.verts[j].color[0] ) );
  317. file->ReadBigArray( tri.verts[j].color2, sizeof( tri.verts[j].color2 ) / sizeof( tri.verts[j].color2[0] ) );
  318. }
  319. }
  320. file->ReadBig( numInFile );
  321. if ( numInFile == 0 ) {
  322. tri.preLightShadowVertexes = NULL;
  323. } else {
  324. R_AllocStaticTriSurfPreLightShadowVerts( &tri, numInFile );
  325. for ( int j = 0; j < numInFile; j++ ) {
  326. file->ReadVec4( tri.preLightShadowVertexes[ j ].xyzw );
  327. }
  328. }
  329. file->ReadBig( tri.numIndexes );
  330. tri.indexes = NULL;
  331. tri.silIndexes = NULL;
  332. if ( tri.numIndexes > 0 ) {
  333. R_AllocStaticTriSurfIndexes( &tri, tri.numIndexes );
  334. file->ReadBigArray( tri.indexes, tri.numIndexes );
  335. }
  336. file->ReadBig( numInFile );
  337. if ( numInFile > 0 ) {
  338. R_AllocStaticTriSurfSilIndexes( &tri, tri.numIndexes );
  339. file->ReadBigArray( tri.silIndexes, tri.numIndexes );
  340. }
  341. file->ReadBig( tri.numMirroredVerts );
  342. tri.mirroredVerts = NULL;
  343. if ( tri.numMirroredVerts > 0 ) {
  344. R_AllocStaticTriSurfMirroredVerts( &tri, tri.numMirroredVerts );
  345. file->ReadBigArray( tri.mirroredVerts, tri.numMirroredVerts );
  346. }
  347. file->ReadBig( tri.numDupVerts );
  348. tri.dupVerts = NULL;
  349. if ( tri.numDupVerts > 0 ) {
  350. R_AllocStaticTriSurfDupVerts( &tri, tri.numDupVerts );
  351. file->ReadBigArray( tri.dupVerts, tri.numDupVerts * 2 );
  352. }
  353. file->ReadBig( tri.numSilEdges );
  354. tri.silEdges = NULL;
  355. if ( tri.numSilEdges > 0 ) {
  356. R_AllocStaticTriSurfSilEdges( &tri, tri.numSilEdges );
  357. assert( tri.silEdges != NULL );
  358. for ( int j = 0; j < tri.numSilEdges; j++ ) {
  359. file->ReadBig( tri.silEdges[j].p1 );
  360. file->ReadBig( tri.silEdges[j].p2 );
  361. file->ReadBig( tri.silEdges[j].v1 );
  362. file->ReadBig( tri.silEdges[j].v2 );
  363. }
  364. }
  365. file->ReadBig( temp );
  366. tri.dominantTris = NULL;
  367. if ( temp ) {
  368. R_AllocStaticTriSurfDominantTris( &tri, tri.numVerts );
  369. assert( tri.dominantTris != NULL );
  370. for ( int j = 0; j < tri.numVerts; j++ ) {
  371. file->ReadBig( tri.dominantTris[j].v2 );
  372. file->ReadBig( tri.dominantTris[j].v3 );
  373. file->ReadFloat( tri.dominantTris[j].normalizationScale[0] );
  374. file->ReadFloat( tri.dominantTris[j].normalizationScale[1] );
  375. file->ReadFloat( tri.dominantTris[j].normalizationScale[2] );
  376. }
  377. }
  378. file->ReadBig( tri.numShadowIndexesNoFrontCaps );
  379. file->ReadBig( tri.numShadowIndexesNoCaps );
  380. file->ReadBig( tri.shadowCapPlaneBits );
  381. tri.ambientSurface = NULL;
  382. tri.nextDeferredFree = NULL;
  383. tri.indexCache = 0;
  384. tri.ambientCache = 0;
  385. tri.shadowCache = 0;
  386. }
  387. }
  388. file->ReadVec3( bounds[0] );
  389. file->ReadVec3( bounds[1] );
  390. file->ReadBig( overlaysAdded );
  391. file->ReadBig( lastModifiedFrame );
  392. file->ReadBig( lastArchivedFrame );
  393. file->ReadString( name );
  394. file->ReadBig( isStaticWorldModel );
  395. file->ReadBig( defaulted );
  396. file->ReadBig( purged );
  397. file->ReadBig( fastLoad );
  398. file->ReadBig( reloadable );
  399. file->ReadBig( levelLoadReferenced ); // should this actually be saved/loaded?
  400. file->ReadBig( hasDrawingSurfaces );
  401. file->ReadBig( hasInteractingSurfaces );
  402. file->ReadBig( hasShadowCastingSurfaces );
  403. return true;
  404. }
  405. /*
  406. ========================
  407. idRenderModelStatic::WriteBinaryModel
  408. ========================
  409. */
  410. void idRenderModelStatic::WriteBinaryModel( idFile * file, ID_TIME_T *_timeStamp ) const {
  411. if ( file == NULL ) {
  412. common->Printf( "Failed to WriteBinaryModel\n" );
  413. return;
  414. }
  415. file->WriteBig( BRM_MAGIC );
  416. if ( _timeStamp != NULL ) {
  417. file->WriteBig( *_timeStamp );
  418. } else {
  419. file->WriteBig( timeStamp );
  420. }
  421. file->WriteBig( surfaces.Num() );
  422. for ( int i = 0; i < surfaces.Num(); i++ ) {
  423. file->WriteBig( surfaces[i].id );
  424. if ( surfaces[i].shader != NULL && surfaces[i].shader->GetName() != NULL ) {
  425. file->WriteString( surfaces[i].shader->GetName() );
  426. } else {
  427. file->WriteString( "" );
  428. }
  429. file->WriteBig( surfaces[i].geometry != NULL );
  430. if ( surfaces[i].geometry != NULL ) {
  431. srfTriangles_t & tri = *surfaces[i].geometry;
  432. file->WriteVec3( tri.bounds[0] );
  433. file->WriteVec3( tri.bounds[1] );
  434. int ambientViewCount = 0; // FIXME: remove
  435. file->WriteBig( ambientViewCount );
  436. file->WriteBig( tri.generateNormals );
  437. file->WriteBig( tri.tangentsCalculated );
  438. file->WriteBig( tri.perfectHull );
  439. file->WriteBig( tri.referencedIndexes );
  440. // shadow models use numVerts but have no verts
  441. file->WriteBig( tri.numVerts );
  442. if ( tri.verts != NULL ) {
  443. file->WriteBig( tri.numVerts );
  444. } else {
  445. file->WriteBig( ( int ) 0 );
  446. }
  447. if ( tri.numVerts > 0 && tri.verts != NULL ) {
  448. for ( int j = 0; j < tri.numVerts; j++ ) {
  449. file->WriteVec3( tri.verts[j].xyz );
  450. file->WriteBigArray( tri.verts[j].st, 2 );
  451. file->WriteBigArray( tri.verts[j].normal, 4 );
  452. file->WriteBigArray( tri.verts[j].tangent, 4 );
  453. file->WriteBigArray( tri.verts[j].color, sizeof( tri.verts[j].color ) / sizeof( tri.verts[j].color[0] ) );
  454. file->WriteBigArray( tri.verts[j].color2, sizeof( tri.verts[j].color2 ) / sizeof( tri.verts[j].color2[0] ) );
  455. }
  456. }
  457. if ( tri.preLightShadowVertexes != NULL ) {
  458. file->WriteBig( tri.numVerts * 2 );
  459. for ( int j = 0; j < tri.numVerts * 2; j++ ) {
  460. file->WriteVec4( tri.preLightShadowVertexes[ j ].xyzw );
  461. }
  462. } else {
  463. file->WriteBig( ( int ) 0 );
  464. }
  465. file->WriteBig( tri.numIndexes );
  466. if ( tri.numIndexes > 0 ) {
  467. file->WriteBigArray( tri.indexes, tri.numIndexes );
  468. }
  469. if ( tri.silIndexes != NULL ) {
  470. file->WriteBig( tri.numIndexes );
  471. } else {
  472. file->WriteBig( ( int ) 0 );
  473. }
  474. if ( tri.numIndexes > 0 && tri.silIndexes != NULL ) {
  475. file->WriteBigArray( tri.silIndexes, tri.numIndexes );
  476. }
  477. file->WriteBig( tri.numMirroredVerts );
  478. if ( tri.numMirroredVerts > 0 ) {
  479. file->WriteBigArray( tri.mirroredVerts, tri.numMirroredVerts );
  480. }
  481. file->WriteBig( tri.numDupVerts );
  482. if ( tri.numDupVerts > 0 ) {
  483. file->WriteBigArray( tri.dupVerts, tri.numDupVerts * 2 );
  484. }
  485. file->WriteBig( tri.numSilEdges );
  486. if ( tri.numSilEdges > 0 ) {
  487. for ( int j = 0; j < tri.numSilEdges; j++ ) {
  488. file->WriteBig( tri.silEdges[j].p1 );
  489. file->WriteBig( tri.silEdges[j].p2 );
  490. file->WriteBig( tri.silEdges[j].v1 );
  491. file->WriteBig( tri.silEdges[j].v2 );
  492. }
  493. }
  494. file->WriteBig( tri.dominantTris != NULL );
  495. if ( tri.dominantTris != NULL ) {
  496. for ( int j = 0; j < tri.numVerts; j++ ) {
  497. file->WriteBig( tri.dominantTris[j].v2 );
  498. file->WriteBig( tri.dominantTris[j].v3 );
  499. file->WriteFloat( tri.dominantTris[j].normalizationScale[0] );
  500. file->WriteFloat( tri.dominantTris[j].normalizationScale[1] );
  501. file->WriteFloat( tri.dominantTris[j].normalizationScale[2] );
  502. }
  503. }
  504. file->WriteBig( tri.numShadowIndexesNoFrontCaps );
  505. file->WriteBig( tri.numShadowIndexesNoCaps );
  506. file->WriteBig( tri.shadowCapPlaneBits );
  507. }
  508. }
  509. file->WriteVec3( bounds[0] );
  510. file->WriteVec3( bounds[1] );
  511. file->WriteBig( overlaysAdded );
  512. file->WriteBig( lastModifiedFrame );
  513. file->WriteBig( lastArchivedFrame );
  514. file->WriteString( name );
  515. // shadowHull
  516. file->WriteBig( isStaticWorldModel );
  517. file->WriteBig( defaulted );
  518. file->WriteBig( purged );
  519. file->WriteBig( fastLoad );
  520. file->WriteBig( reloadable );
  521. file->WriteBig( levelLoadReferenced );
  522. file->WriteBig( hasDrawingSurfaces );
  523. file->WriteBig( hasInteractingSurfaces );
  524. file->WriteBig( hasShadowCastingSurfaces );
  525. }
  526. /*
  527. ================
  528. idRenderModelStatic::LoadModel
  529. ================
  530. */
  531. void idRenderModelStatic::LoadModel() {
  532. PurgeModel();
  533. InitFromFile( name );
  534. }
  535. /*
  536. ================
  537. idRenderModelStatic::InitEmpty
  538. ================
  539. */
  540. void idRenderModelStatic::InitEmpty( const char *fileName ) {
  541. // model names of the form _area* are static parts of the
  542. // world, and have already been considered for optimized shadows
  543. // other model names are inline entity models, and need to be
  544. // shadowed normally
  545. if ( !idStr::Cmpn( fileName, "_area", 5 ) ) {
  546. isStaticWorldModel = true;
  547. } else {
  548. isStaticWorldModel = false;
  549. }
  550. name = fileName;
  551. reloadable = false; // if it didn't come from a file, we can't reload it
  552. PurgeModel();
  553. purged = false;
  554. bounds.Zero();
  555. }
  556. /*
  557. ================
  558. idRenderModelStatic::AddSurface
  559. ================
  560. */
  561. void idRenderModelStatic::AddSurface( modelSurface_t surface ) {
  562. surfaces.Append( surface );
  563. if ( surface.geometry ) {
  564. bounds += surface.geometry->bounds;
  565. }
  566. }
  567. /*
  568. ================
  569. idRenderModelStatic::Name
  570. ================
  571. */
  572. const char *idRenderModelStatic::Name() const {
  573. return name;
  574. }
  575. /*
  576. ================
  577. idRenderModelStatic::Timestamp
  578. ================
  579. */
  580. ID_TIME_T idRenderModelStatic::Timestamp() const {
  581. return timeStamp;
  582. }
  583. /*
  584. ================
  585. idRenderModelStatic::NumSurfaces
  586. ================
  587. */
  588. int idRenderModelStatic::NumSurfaces() const {
  589. return surfaces.Num();
  590. }
  591. /*
  592. ================
  593. idRenderModelStatic::NumBaseSurfaces
  594. ================
  595. */
  596. int idRenderModelStatic::NumBaseSurfaces() const {
  597. return surfaces.Num() - overlaysAdded;
  598. }
  599. /*
  600. ================
  601. idRenderModelStatic::Surface
  602. ================
  603. */
  604. const modelSurface_t *idRenderModelStatic::Surface( int surfaceNum ) const {
  605. return &surfaces[surfaceNum];
  606. }
  607. /*
  608. ================
  609. idRenderModelStatic::AllocSurfaceTriangles
  610. ================
  611. */
  612. srfTriangles_t *idRenderModelStatic::AllocSurfaceTriangles( int numVerts, int numIndexes ) const {
  613. srfTriangles_t *tri = R_AllocStaticTriSurf();
  614. R_AllocStaticTriSurfVerts( tri, numVerts );
  615. R_AllocStaticTriSurfIndexes( tri, numIndexes );
  616. return tri;
  617. }
  618. /*
  619. ================
  620. idRenderModelStatic::FreeSurfaceTriangles
  621. ================
  622. */
  623. void idRenderModelStatic::FreeSurfaceTriangles( srfTriangles_t *tris ) const {
  624. R_FreeStaticTriSurf( tris );
  625. }
  626. /*
  627. ================
  628. idRenderModelStatic::IsStaticWorldModel
  629. ================
  630. */
  631. bool idRenderModelStatic::IsStaticWorldModel() const {
  632. return isStaticWorldModel;
  633. }
  634. /*
  635. ================
  636. idRenderModelStatic::IsDynamicModel
  637. ================
  638. */
  639. dynamicModel_t idRenderModelStatic::IsDynamicModel() const {
  640. // dynamic subclasses will override this
  641. return DM_STATIC;
  642. }
  643. /*
  644. ================
  645. idRenderModelStatic::IsReloadable
  646. ================
  647. */
  648. bool idRenderModelStatic::IsReloadable() const {
  649. return reloadable;
  650. }
  651. /*
  652. ================
  653. idRenderModelStatic::Bounds
  654. ================
  655. */
  656. idBounds idRenderModelStatic::Bounds( const struct renderEntity_s *mdef ) const {
  657. return bounds;
  658. }
  659. /*
  660. ================
  661. idRenderModelStatic::DepthHack
  662. ================
  663. */
  664. float idRenderModelStatic::DepthHack() const {
  665. return 0.0f;
  666. }
  667. /*
  668. ================
  669. idRenderModelStatic::InstantiateDynamicModel
  670. ================
  671. */
  672. idRenderModel *idRenderModelStatic::InstantiateDynamicModel( const struct renderEntity_s *ent, const viewDef_t *view, idRenderModel *cachedModel ) {
  673. if ( cachedModel ) {
  674. delete cachedModel;
  675. cachedModel = NULL;
  676. }
  677. common->Error( "InstantiateDynamicModel called on static model '%s'", name.c_str() );
  678. return NULL;
  679. }
  680. /*
  681. ================
  682. idRenderModelStatic::NumJoints
  683. ================
  684. */
  685. int idRenderModelStatic::NumJoints() const {
  686. return 0;
  687. }
  688. /*
  689. ================
  690. idRenderModelStatic::GetJoints
  691. ================
  692. */
  693. const idMD5Joint *idRenderModelStatic::GetJoints() const {
  694. return NULL;
  695. }
  696. /*
  697. ================
  698. idRenderModelStatic::GetJointHandle
  699. ================
  700. */
  701. jointHandle_t idRenderModelStatic::GetJointHandle( const char *name ) const {
  702. return INVALID_JOINT;
  703. }
  704. /*
  705. ================
  706. idRenderModelStatic::GetJointName
  707. ================
  708. */
  709. const char * idRenderModelStatic::GetJointName( jointHandle_t handle ) const {
  710. return "";
  711. }
  712. /*
  713. ================
  714. idRenderModelStatic::GetDefaultPose
  715. ================
  716. */
  717. const idJointQuat *idRenderModelStatic::GetDefaultPose() const {
  718. return NULL;
  719. }
  720. /*
  721. ================
  722. idRenderModelStatic::NearestJoint
  723. ================
  724. */
  725. int idRenderModelStatic::NearestJoint( int surfaceNum, int a, int b, int c ) const {
  726. return INVALID_JOINT;
  727. }
  728. //=====================================================================
  729. /*
  730. ================
  731. idRenderModelStatic::FinishSurfaces
  732. The mergeShadows option allows surfaces with different textures to share
  733. silhouette edges for shadow calculation, instead of leaving shared edges
  734. hanging.
  735. If any of the original shaders have the noSelfShadow flag set, the surfaces
  736. can't be merged, because they will need to be drawn in different order.
  737. If there is only one surface, a separate merged surface won't be generated.
  738. A model with multiple surfaces can't later have a skinned shader change the
  739. state of the noSelfShadow flag.
  740. -----------------
  741. Creates mirrored copies of two sided surfaces with normal maps, which would
  742. otherwise light funny.
  743. Extends the bounds of deformed surfaces so they don't cull incorrectly at screen edges.
  744. ================
  745. */
  746. void idRenderModelStatic::FinishSurfaces() {
  747. int i;
  748. int totalVerts, totalIndexes;
  749. hasDrawingSurfaces = false;
  750. hasInteractingSurfaces = false;
  751. hasShadowCastingSurfaces = false;
  752. purged = false;
  753. // make sure we don't have a huge bounds even if we don't finish everything
  754. bounds.Zero();
  755. if ( surfaces.Num() == 0 ) {
  756. return;
  757. }
  758. // renderBump doesn't care about most of this
  759. if ( fastLoad ) {
  760. bounds.Zero();
  761. for ( i = 0; i < surfaces.Num(); i++ ) {
  762. const modelSurface_t *surf = &surfaces[i];
  763. R_BoundTriSurf( surf->geometry );
  764. bounds.AddBounds( surf->geometry->bounds );
  765. }
  766. return;
  767. }
  768. // cleanup all the final surfaces, but don't create sil edges
  769. totalVerts = 0;
  770. totalIndexes = 0;
  771. // decide if we are going to merge all the surfaces into one shadower
  772. int numOriginalSurfaces = surfaces.Num();
  773. // make sure there aren't any NULL shaders or geometry
  774. for ( i = 0; i < numOriginalSurfaces; i++ ) {
  775. const modelSurface_t *surf = &surfaces[i];
  776. if ( surf->geometry == NULL || surf->shader == NULL ) {
  777. MakeDefaultModel();
  778. common->Error( "Model %s, surface %i had NULL geometry", name.c_str(), i );
  779. }
  780. if ( surf->shader == NULL ) {
  781. MakeDefaultModel();
  782. common->Error( "Model %s, surface %i had NULL shader", name.c_str(), i );
  783. }
  784. }
  785. // duplicate and reverse triangles for two sided bump mapped surfaces
  786. // note that this won't catch surfaces that have their shaders dynamically
  787. // changed, and won't work with animated models.
  788. // It is better to create completely separate surfaces, rather than
  789. // add vertexes and indexes to the existing surface, because the
  790. // tangent generation wouldn't like the acute shared edges
  791. for ( i = 0; i < numOriginalSurfaces; i++ ) {
  792. const modelSurface_t *surf = &surfaces[i];
  793. if ( surf->shader->ShouldCreateBackSides() ) {
  794. srfTriangles_t *newTri;
  795. newTri = R_CopyStaticTriSurf( surf->geometry );
  796. R_ReverseTriangles( newTri );
  797. modelSurface_t newSurf;
  798. newSurf.shader = surf->shader;
  799. newSurf.geometry = newTri;
  800. AddSurface( newSurf );
  801. }
  802. }
  803. // clean the surfaces
  804. for ( i = 0; i < surfaces.Num(); i++ ) {
  805. const modelSurface_t *surf = &surfaces[i];
  806. R_CleanupTriangles( surf->geometry, surf->geometry->generateNormals, true, surf->shader->UseUnsmoothedTangents() );
  807. if ( surf->shader->SurfaceCastsShadow() ) {
  808. totalVerts += surf->geometry->numVerts;
  809. totalIndexes += surf->geometry->numIndexes;
  810. }
  811. }
  812. // add up the total surface area for development information
  813. for ( i = 0; i < surfaces.Num(); i++ ) {
  814. const modelSurface_t *surf = &surfaces[i];
  815. srfTriangles_t *tri = surf->geometry;
  816. for ( int j = 0; j < tri->numIndexes; j += 3 ) {
  817. float area = idWinding::TriangleArea( tri->verts[tri->indexes[j]].xyz,
  818. tri->verts[tri->indexes[j+1]].xyz, tri->verts[tri->indexes[j+2]].xyz );
  819. const_cast<idMaterial *>(surf->shader)->AddToSurfaceArea( area );
  820. }
  821. }
  822. // set flags for whole-model rejection
  823. for ( i = 0; i < surfaces.Num(); i++ ) {
  824. const modelSurface_t *surf = &surfaces[i];
  825. if ( surf->shader->IsDrawn() ) {
  826. hasDrawingSurfaces = true;
  827. }
  828. if ( surf->shader->SurfaceCastsShadow() ) {
  829. hasShadowCastingSurfaces = true;
  830. }
  831. if ( surf->shader->ReceivesLighting() ) {
  832. hasInteractingSurfaces = true;
  833. }
  834. if ( strstr( surf->shader->GetName(), "trigger" ) ) {
  835. static int breakHere;
  836. breakHere++;
  837. }
  838. }
  839. // calculate the bounds
  840. if ( surfaces.Num() == 0 ) {
  841. bounds.Zero();
  842. } else {
  843. bounds.Clear();
  844. for ( i = 0; i < surfaces.Num(); i++ ) {
  845. modelSurface_t *surf = &surfaces[i];
  846. // if the surface has a deformation, increase the bounds
  847. // the amount here is somewhat arbitrary, designed to handle
  848. // autosprites and flares, but could be done better with exact
  849. // deformation information.
  850. // Note that this doesn't handle deformations that are skinned in
  851. // at run time...
  852. if ( surf->shader->Deform() != DFRM_NONE ) {
  853. srfTriangles_t *tri = surf->geometry;
  854. idVec3 mid = ( tri->bounds[1] + tri->bounds[0] ) * 0.5f;
  855. float radius = ( tri->bounds[0] - mid ).Length();
  856. radius += 20.0f;
  857. tri->bounds[0][0] = mid[0] - radius;
  858. tri->bounds[0][1] = mid[1] - radius;
  859. tri->bounds[0][2] = mid[2] - radius;
  860. tri->bounds[1][0] = mid[0] + radius;
  861. tri->bounds[1][1] = mid[1] + radius;
  862. tri->bounds[1][2] = mid[2] + radius;
  863. }
  864. // add to the model bounds
  865. bounds.AddBounds( surf->geometry->bounds );
  866. }
  867. }
  868. }
  869. /*
  870. =================
  871. idRenderModelStatic::ConvertASEToModelSurfaces
  872. =================
  873. */
  874. typedef struct matchVert_s {
  875. struct matchVert_s *next;
  876. int v, tv;
  877. byte color[4];
  878. idVec3 normal;
  879. } matchVert_t;
  880. bool idRenderModelStatic::ConvertASEToModelSurfaces( const struct aseModel_s *ase ) {
  881. aseObject_t * object;
  882. aseMesh_t * mesh;
  883. aseMaterial_t * material;
  884. const idMaterial *im1, *im2;
  885. srfTriangles_t *tri;
  886. int objectNum;
  887. int i, j, k;
  888. int v, tv;
  889. int * vRemap;
  890. int * tvRemap;
  891. matchVert_t * mvTable; // all of the match verts
  892. matchVert_t ** mvHash; // points inside mvTable for each xyz index
  893. matchVert_t * lastmv;
  894. matchVert_t * mv;
  895. idVec3 normal;
  896. float uOffset, vOffset, textureSin, textureCos;
  897. float uTiling, vTiling;
  898. int * mergeTo;
  899. byte * color;
  900. static byte identityColor[4] = { 255, 255, 255, 255 };
  901. modelSurface_t surf, *modelSurf;
  902. if ( !ase ) {
  903. return false;
  904. }
  905. if ( ase->objects.Num() < 1 ) {
  906. return false;
  907. }
  908. timeStamp = ase->timeStamp;
  909. // the modeling programs can save out multiple surfaces with a common
  910. // material, but we would like to mege them together where possible
  911. // meaning that this->NumSurfaces() <= ase->objects.currentElements
  912. mergeTo = (int *)_alloca( ase->objects.Num() * sizeof( *mergeTo ) );
  913. surf.geometry = NULL;
  914. if ( ase->materials.Num() == 0 ) {
  915. // if we don't have any materials, dump everything into a single surface
  916. surf.shader = tr.defaultMaterial;
  917. surf.id = 0;
  918. this->AddSurface( surf );
  919. for ( i = 0; i < ase->objects.Num(); i++ ) {
  920. mergeTo[i] = 0;
  921. }
  922. } else if ( !r_mergeModelSurfaces.GetBool() ) {
  923. // don't merge any
  924. for ( i = 0; i < ase->objects.Num(); i++ ) {
  925. mergeTo[i] = i;
  926. object = ase->objects[i];
  927. material = ase->materials[object->materialRef];
  928. surf.shader = declManager->FindMaterial( material->name );
  929. surf.id = this->NumSurfaces();
  930. this->AddSurface( surf );
  931. }
  932. } else {
  933. // search for material matches
  934. for ( i = 0; i < ase->objects.Num(); i++ ) {
  935. object = ase->objects[i];
  936. material = ase->materials[object->materialRef];
  937. im1 = declManager->FindMaterial( material->name );
  938. if ( im1->IsDiscrete() ) {
  939. // flares, autosprites, etc
  940. j = this->NumSurfaces();
  941. } else {
  942. for ( j = 0; j < this->NumSurfaces(); j++ ) {
  943. modelSurf = &this->surfaces[j];
  944. im2 = modelSurf->shader;
  945. if ( im1 == im2 ) {
  946. // merge this
  947. mergeTo[i] = j;
  948. break;
  949. }
  950. }
  951. }
  952. if ( j == this->NumSurfaces() ) {
  953. // didn't merge
  954. mergeTo[i] = j;
  955. surf.shader = im1;
  956. surf.id = this->NumSurfaces();
  957. this->AddSurface( surf );
  958. }
  959. }
  960. }
  961. idVectorSubset<idVec3, 3> vertexSubset;
  962. idVectorSubset<idVec2, 2> texCoordSubset;
  963. // build the surfaces
  964. for ( objectNum = 0; objectNum < ase->objects.Num(); objectNum++ ) {
  965. object = ase->objects[objectNum];
  966. mesh = &object->mesh;
  967. material = ase->materials[object->materialRef];
  968. im1 = declManager->FindMaterial( material->name );
  969. bool normalsParsed = mesh->normalsParsed;
  970. // completely ignore any explict normals on surfaces with a renderbump command
  971. // which will guarantee the best contours and least vertexes.
  972. const char *rb = im1->GetRenderBump();
  973. if ( rb != NULL && rb[0] != NULL ) {
  974. normalsParsed = false;
  975. }
  976. // It seems like the tools our artists are using often generate
  977. // verts and texcoords slightly separated that should be merged
  978. // note that we really should combine the surfaces with common materials
  979. // before doing this operation, because we can miss a slop combination
  980. // if they are in different surfaces
  981. vRemap = (int *)R_StaticAlloc( mesh->numVertexes * sizeof( vRemap[0] ), TAG_MODEL );
  982. if ( fastLoad ) {
  983. // renderbump doesn't care about vertex count
  984. for ( j = 0; j < mesh->numVertexes; j++ ) {
  985. vRemap[j] = j;
  986. }
  987. } else {
  988. float vertexEpsilon = r_slopVertex.GetFloat();
  989. float expand = 2 * 32 * vertexEpsilon;
  990. idVec3 mins, maxs;
  991. SIMDProcessor->MinMax( mins, maxs, mesh->vertexes, mesh->numVertexes );
  992. mins -= idVec3( expand, expand, expand );
  993. maxs += idVec3( expand, expand, expand );
  994. vertexSubset.Init( mins, maxs, 32, 1024 );
  995. for ( j = 0; j < mesh->numVertexes; j++ ) {
  996. vRemap[j] = vertexSubset.FindVector( mesh->vertexes, j, vertexEpsilon );
  997. }
  998. }
  999. tvRemap = (int *)R_StaticAlloc( mesh->numTVertexes * sizeof( tvRemap[0] ), TAG_MODEL );
  1000. if ( fastLoad ) {
  1001. // renderbump doesn't care about vertex count
  1002. for ( j = 0; j < mesh->numTVertexes; j++ ) {
  1003. tvRemap[j] = j;
  1004. }
  1005. } else {
  1006. float texCoordEpsilon = r_slopTexCoord.GetFloat();
  1007. float expand = 2 * 32 * texCoordEpsilon;
  1008. idVec2 mins, maxs;
  1009. SIMDProcessor->MinMax( mins, maxs, mesh->tvertexes, mesh->numTVertexes );
  1010. mins -= idVec2( expand, expand );
  1011. maxs += idVec2( expand, expand );
  1012. texCoordSubset.Init( mins, maxs, 32, 1024 );
  1013. for ( j = 0; j < mesh->numTVertexes; j++ ) {
  1014. tvRemap[j] = texCoordSubset.FindVector( mesh->tvertexes, j, texCoordEpsilon );
  1015. }
  1016. }
  1017. // we need to find out how many unique vertex / texcoord combinations
  1018. // there are, because ASE tracks them separately but we need them unified
  1019. // the maximum possible number of combined vertexes is the number of indexes
  1020. mvTable = (matchVert_t *)R_ClearedStaticAlloc( mesh->numFaces * 3 * sizeof( mvTable[0] ) );
  1021. // we will have a hash chain based on the xyz values
  1022. mvHash = (matchVert_t **)R_ClearedStaticAlloc( mesh->numVertexes * sizeof( mvHash[0] ) );
  1023. // allocate triangle surface
  1024. tri = R_AllocStaticTriSurf();
  1025. tri->numVerts = 0;
  1026. tri->numIndexes = 0;
  1027. R_AllocStaticTriSurfIndexes( tri, mesh->numFaces * 3 );
  1028. tri->generateNormals = !normalsParsed;
  1029. // init default normal, color and tex coord index
  1030. normal.Zero();
  1031. color = identityColor;
  1032. tv = 0;
  1033. // find all the unique combinations
  1034. float normalEpsilon = 1.0f - r_slopNormal.GetFloat();
  1035. for ( j = 0; j < mesh->numFaces; j++ ) {
  1036. for ( k = 0; k < 3; k++ ) {
  1037. v = mesh->faces[j].vertexNum[k];
  1038. if ( v < 0 || v >= mesh->numVertexes ) {
  1039. common->Error( "ConvertASEToModelSurfaces: bad vertex index in ASE file %s", name.c_str() );
  1040. }
  1041. // collapse the position if it was slightly offset
  1042. v = vRemap[v];
  1043. // we may or may not have texcoords to compare
  1044. if ( mesh->numTVFaces == mesh->numFaces && mesh->numTVertexes != 0 ) {
  1045. tv = mesh->faces[j].tVertexNum[k];
  1046. if ( tv < 0 || tv >= mesh->numTVertexes ) {
  1047. common->Error( "ConvertASEToModelSurfaces: bad tex coord index in ASE file %s", name.c_str() );
  1048. }
  1049. // collapse the tex coord if it was slightly offset
  1050. tv = tvRemap[tv];
  1051. }
  1052. // we may or may not have normals to compare
  1053. if ( normalsParsed ) {
  1054. normal = mesh->faces[j].vertexNormals[k];
  1055. }
  1056. // we may or may not have colors to compare
  1057. if ( mesh->colorsParsed ) {
  1058. color = mesh->faces[j].vertexColors[k];
  1059. }
  1060. // find a matching vert
  1061. for ( lastmv = NULL, mv = mvHash[v]; mv != NULL; lastmv = mv, mv = mv->next ) {
  1062. if ( mv->tv != tv ) {
  1063. continue;
  1064. }
  1065. if ( *(unsigned *)mv->color != *(unsigned *)color ) {
  1066. continue;
  1067. }
  1068. if ( !normalsParsed ) {
  1069. // if we are going to create the normals, just
  1070. // matching texcoords is enough
  1071. break;
  1072. }
  1073. if ( mv->normal * normal > normalEpsilon ) {
  1074. break; // we already have this one
  1075. }
  1076. }
  1077. if ( !mv ) {
  1078. // allocate a new match vert and link to hash chain
  1079. mv = &mvTable[ tri->numVerts ];
  1080. mv->v = v;
  1081. mv->tv = tv;
  1082. mv->normal = normal;
  1083. *(unsigned *)mv->color = *(unsigned *)color;
  1084. mv->next = NULL;
  1085. if ( lastmv ) {
  1086. lastmv->next = mv;
  1087. } else {
  1088. mvHash[v] = mv;
  1089. }
  1090. tri->numVerts++;
  1091. }
  1092. tri->indexes[tri->numIndexes] = mv - mvTable;
  1093. tri->numIndexes++;
  1094. }
  1095. }
  1096. // allocate space for the indexes and copy them
  1097. if ( tri->numIndexes > mesh->numFaces * 3 ) {
  1098. common->FatalError( "ConvertASEToModelSurfaces: index miscount in ASE file %s", name.c_str() );
  1099. }
  1100. if ( tri->numVerts > mesh->numFaces * 3 ) {
  1101. common->FatalError( "ConvertASEToModelSurfaces: vertex miscount in ASE file %s", name.c_str() );
  1102. }
  1103. // an ASE allows the texture coordinates to be scaled, translated, and rotated
  1104. if ( ase->materials.Num() == 0 ) {
  1105. uOffset = vOffset = 0.0f;
  1106. uTiling = vTiling = 1.0f;
  1107. textureSin = 0.0f;
  1108. textureCos = 1.0f;
  1109. } else {
  1110. material = ase->materials[object->materialRef];
  1111. uOffset = -material->uOffset;
  1112. vOffset = material->vOffset;
  1113. uTiling = material->uTiling;
  1114. vTiling = material->vTiling;
  1115. textureSin = idMath::Sin( material->angle );
  1116. textureCos = idMath::Cos( material->angle );
  1117. }
  1118. // now allocate and generate the combined vertexes
  1119. R_AllocStaticTriSurfVerts( tri, tri->numVerts );
  1120. for ( j = 0; j < tri->numVerts; j++ ) {
  1121. mv = &mvTable[j];
  1122. tri->verts[ j ].Clear();
  1123. tri->verts[ j ].xyz = mesh->vertexes[ mv->v ];
  1124. tri->verts[ j ].SetNormal( mv->normal );
  1125. *(unsigned *)tri->verts[j].color = *(unsigned *)mv->color;
  1126. if ( mesh->numTVFaces == mesh->numFaces && mesh->numTVertexes != 0 ) {
  1127. const idVec2 &tv = mesh->tvertexes[ mv->tv ];
  1128. float u = tv.x * uTiling + uOffset;
  1129. float v = tv.y * vTiling + vOffset;
  1130. tri->verts[j].SetTexCoord( u * textureCos + v * textureSin, u * -textureSin + v * textureCos );
  1131. }
  1132. }
  1133. R_StaticFree( mvTable );
  1134. R_StaticFree( mvHash );
  1135. R_StaticFree( tvRemap );
  1136. R_StaticFree( vRemap );
  1137. // see if we need to merge with a previous surface of the same material
  1138. modelSurf = &this->surfaces[mergeTo[ objectNum ]];
  1139. srfTriangles_t *mergeTri = modelSurf->geometry;
  1140. if ( !mergeTri ) {
  1141. modelSurf->geometry = tri;
  1142. } else {
  1143. modelSurf->geometry = R_MergeTriangles( mergeTri, tri );
  1144. R_FreeStaticTriSurf( tri );
  1145. R_FreeStaticTriSurf( mergeTri );
  1146. }
  1147. }
  1148. return true;
  1149. }
  1150. /*
  1151. =================
  1152. idRenderModelStatic::ConvertLWOToModelSurfaces
  1153. =================
  1154. */
  1155. bool idRenderModelStatic::ConvertLWOToModelSurfaces( const struct st_lwObject *lwo ) {
  1156. const idMaterial *im1, *im2;
  1157. srfTriangles_t *tri;
  1158. lwSurface * lwoSurf;
  1159. int numTVertexes;
  1160. int i, j, k;
  1161. int v, tv;
  1162. idVec3 * vList;
  1163. int * vRemap;
  1164. idVec2 * tvList;
  1165. int * tvRemap;
  1166. matchVert_t * mvTable; // all of the match verts
  1167. matchVert_t ** mvHash; // points inside mvTable for each xyz index
  1168. matchVert_t * lastmv;
  1169. matchVert_t * mv;
  1170. idVec3 normal;
  1171. int * mergeTo;
  1172. byte color[4];
  1173. modelSurface_t surf, *modelSurf;
  1174. if ( !lwo ) {
  1175. return false;
  1176. }
  1177. if ( lwo->surf == NULL ) {
  1178. return false;
  1179. }
  1180. timeStamp = lwo->timeStamp;
  1181. // count the number of surfaces
  1182. i = 0;
  1183. for ( lwoSurf = lwo->surf; lwoSurf; lwoSurf = lwoSurf->next ) {
  1184. i++;
  1185. }
  1186. // the modeling programs can save out multiple surfaces with a common
  1187. // material, but we would like to merge them together where possible
  1188. mergeTo = (int *)_alloca( i * sizeof( mergeTo[0] ) );
  1189. memset( &surf, 0, sizeof( surf ) );
  1190. if ( !r_mergeModelSurfaces.GetBool() ) {
  1191. // don't merge any
  1192. for ( lwoSurf = lwo->surf, i = 0; lwoSurf; lwoSurf = lwoSurf->next, i++ ) {
  1193. mergeTo[i] = i;
  1194. surf.shader = declManager->FindMaterial( lwoSurf->name );
  1195. surf.id = this->NumSurfaces();
  1196. this->AddSurface( surf );
  1197. }
  1198. } else {
  1199. // search for material matches
  1200. for ( lwoSurf = lwo->surf, i = 0; lwoSurf; lwoSurf = lwoSurf->next, i++ ) {
  1201. im1 = declManager->FindMaterial( lwoSurf->name );
  1202. if ( im1->IsDiscrete() ) {
  1203. // flares, autosprites, etc
  1204. j = this->NumSurfaces();
  1205. } else {
  1206. for ( j = 0; j < this->NumSurfaces(); j++ ) {
  1207. modelSurf = &this->surfaces[j];
  1208. im2 = modelSurf->shader;
  1209. if ( im1 == im2 ) {
  1210. // merge this
  1211. mergeTo[i] = j;
  1212. break;
  1213. }
  1214. }
  1215. }
  1216. if ( j == this->NumSurfaces() ) {
  1217. // didn't merge
  1218. mergeTo[i] = j;
  1219. surf.shader = im1;
  1220. surf.id = this->NumSurfaces();
  1221. this->AddSurface( surf );
  1222. }
  1223. }
  1224. }
  1225. idVectorSubset<idVec3, 3> vertexSubset;
  1226. idVectorSubset<idVec2, 2> texCoordSubset;
  1227. // we only ever use the first layer
  1228. lwLayer *layer = lwo->layer;
  1229. // vertex positions
  1230. if ( layer->point.count <= 0 ) {
  1231. common->Warning( "ConvertLWOToModelSurfaces: model \'%s\' has bad or missing vertex data", name.c_str() );
  1232. return false;
  1233. }
  1234. vList = (idVec3 *)R_StaticAlloc( layer->point.count * sizeof( vList[0] ), TAG_MODEL );
  1235. for ( j = 0; j < layer->point.count; j++ ) {
  1236. vList[j].x = layer->point.pt[j].pos[0];
  1237. vList[j].y = layer->point.pt[j].pos[2];
  1238. vList[j].z = layer->point.pt[j].pos[1];
  1239. }
  1240. // vertex texture coords
  1241. numTVertexes = 0;
  1242. if ( layer->nvmaps ) {
  1243. for( lwVMap *vm = layer->vmap; vm; vm = vm->next ) {
  1244. if ( vm->type == LWID_('T','X','U','V') ) {
  1245. numTVertexes += vm->nverts;
  1246. }
  1247. }
  1248. }
  1249. if ( numTVertexes ) {
  1250. tvList = (idVec2 *)Mem_Alloc( numTVertexes * sizeof( tvList[0] ), TAG_MODEL );
  1251. int offset = 0;
  1252. for( lwVMap *vm = layer->vmap; vm; vm = vm->next ) {
  1253. if ( vm->type == LWID_('T','X','U','V') ) {
  1254. vm->offset = offset;
  1255. for ( k = 0; k < vm->nverts; k++ ) {
  1256. tvList[k + offset].x = vm->val[k][0];
  1257. tvList[k + offset].y = 1.0f - vm->val[k][1]; // invert the t
  1258. }
  1259. offset += vm->nverts;
  1260. }
  1261. }
  1262. } else {
  1263. common->Warning( "ConvertLWOToModelSurfaces: model \'%s\' has bad or missing uv data", name.c_str() );
  1264. numTVertexes = 1;
  1265. tvList = (idVec2 *)Mem_ClearedAlloc( numTVertexes * sizeof( tvList[0] ), TAG_MODEL );
  1266. }
  1267. // It seems like the tools our artists are using often generate
  1268. // verts and texcoords slightly separated that should be merged
  1269. // note that we really should combine the surfaces with common materials
  1270. // before doing this operation, because we can miss a slop combination
  1271. // if they are in different surfaces
  1272. vRemap = (int *)R_StaticAlloc( layer->point.count * sizeof( vRemap[0] ), TAG_MODEL );
  1273. if ( fastLoad ) {
  1274. // renderbump doesn't care about vertex count
  1275. for ( j = 0; j < layer->point.count; j++ ) {
  1276. vRemap[j] = j;
  1277. }
  1278. } else {
  1279. float vertexEpsilon = r_slopVertex.GetFloat();
  1280. float expand = 2 * 32 * vertexEpsilon;
  1281. idVec3 mins, maxs;
  1282. SIMDProcessor->MinMax( mins, maxs, vList, layer->point.count );
  1283. mins -= idVec3( expand, expand, expand );
  1284. maxs += idVec3( expand, expand, expand );
  1285. vertexSubset.Init( mins, maxs, 32, 1024 );
  1286. for ( j = 0; j < layer->point.count; j++ ) {
  1287. vRemap[j] = vertexSubset.FindVector( vList, j, vertexEpsilon );
  1288. }
  1289. }
  1290. tvRemap = (int *)R_StaticAlloc( numTVertexes * sizeof( tvRemap[0] ), TAG_MODEL );
  1291. if ( fastLoad ) {
  1292. // renderbump doesn't care about vertex count
  1293. for ( j = 0; j < numTVertexes; j++ ) {
  1294. tvRemap[j] = j;
  1295. }
  1296. } else {
  1297. float texCoordEpsilon = r_slopTexCoord.GetFloat();
  1298. float expand = 2 * 32 * texCoordEpsilon;
  1299. idVec2 mins, maxs;
  1300. SIMDProcessor->MinMax( mins, maxs, tvList, numTVertexes );
  1301. mins -= idVec2( expand, expand );
  1302. maxs += idVec2( expand, expand );
  1303. texCoordSubset.Init( mins, maxs, 32, 1024 );
  1304. for ( j = 0; j < numTVertexes; j++ ) {
  1305. tvRemap[j] = texCoordSubset.FindVector( tvList, j, texCoordEpsilon );
  1306. }
  1307. }
  1308. // build the surfaces
  1309. for ( lwoSurf = lwo->surf, i = 0; lwoSurf; lwoSurf = lwoSurf->next, i++ ) {
  1310. im1 = declManager->FindMaterial( lwoSurf->name );
  1311. bool normalsParsed = true;
  1312. // completely ignore any explict normals on surfaces with a renderbump command
  1313. // which will guarantee the best contours and least vertexes.
  1314. const char *rb = im1->GetRenderBump();
  1315. if ( rb && rb[0] ) {
  1316. normalsParsed = false;
  1317. }
  1318. // we need to find out how many unique vertex / texcoord combinations there are
  1319. // the maximum possible number of combined vertexes is the number of indexes
  1320. mvTable = (matchVert_t *)R_ClearedStaticAlloc( layer->polygon.count * 3 * sizeof( mvTable[0] ) );
  1321. // we will have a hash chain based on the xyz values
  1322. mvHash = (matchVert_t **)R_ClearedStaticAlloc( layer->point.count * sizeof( mvHash[0] ) );
  1323. // allocate triangle surface
  1324. tri = R_AllocStaticTriSurf();
  1325. tri->numVerts = 0;
  1326. tri->numIndexes = 0;
  1327. R_AllocStaticTriSurfIndexes( tri, layer->polygon.count * 3 );
  1328. tri->generateNormals = !normalsParsed;
  1329. // find all the unique combinations
  1330. float normalEpsilon;
  1331. if ( fastLoad ) {
  1332. normalEpsilon = 1.0f; // don't merge unless completely exact
  1333. } else {
  1334. normalEpsilon = 1.0f - r_slopNormal.GetFloat();
  1335. }
  1336. for ( j = 0; j < layer->polygon.count; j++ ) {
  1337. lwPolygon *poly = &layer->polygon.pol[j];
  1338. if ( poly->surf != lwoSurf ) {
  1339. continue;
  1340. }
  1341. if ( poly->nverts != 3 ) {
  1342. common->Warning( "ConvertLWOToModelSurfaces: model %s has too many verts for a poly! Make sure you triplet it down", name.c_str() );
  1343. continue;
  1344. }
  1345. for ( k = 0; k < 3; k++ ) {
  1346. v = vRemap[poly->v[k].index];
  1347. normal.x = poly->v[k].norm[0];
  1348. normal.y = poly->v[k].norm[2];
  1349. normal.z = poly->v[k].norm[1];
  1350. // LWO models aren't all that pretty when it comes down to the floating point values they store
  1351. normal.FixDegenerateNormal();
  1352. tv = 0;
  1353. color[0] = lwoSurf->color.rgb[0] * 255;
  1354. color[1] = lwoSurf->color.rgb[1] * 255;
  1355. color[2] = lwoSurf->color.rgb[2] * 255;
  1356. color[3] = 255;
  1357. // first set attributes from the vertex
  1358. lwPoint *pt = &layer->point.pt[poly->v[k].index];
  1359. int nvm;
  1360. for ( nvm = 0; nvm < pt->nvmaps; nvm++ ) {
  1361. lwVMapPt *vm = &pt->vm[nvm];
  1362. if ( vm->vmap->type == LWID_('T','X','U','V') ) {
  1363. tv = tvRemap[vm->index + vm->vmap->offset];
  1364. }
  1365. if ( vm->vmap->type == LWID_('R','G','B','A') ) {
  1366. for ( int chan = 0; chan < 4; chan++ ) {
  1367. color[chan] = 255 * vm->vmap->val[vm->index][chan];
  1368. }
  1369. }
  1370. }
  1371. // then override with polygon attributes
  1372. for ( nvm = 0; nvm < poly->v[k].nvmaps; nvm++ ) {
  1373. lwVMapPt *vm = &poly->v[k].vm[nvm];
  1374. if ( vm->vmap->type == LWID_('T','X','U','V') ) {
  1375. tv = tvRemap[vm->index + vm->vmap->offset];
  1376. }
  1377. if ( vm->vmap->type == LWID_('R','G','B','A') ) {
  1378. for ( int chan = 0; chan < 4; chan++ ) {
  1379. color[chan] = 255 * vm->vmap->val[vm->index][chan];
  1380. }
  1381. }
  1382. }
  1383. // find a matching vert
  1384. for ( lastmv = NULL, mv = mvHash[v]; mv != NULL; lastmv = mv, mv = mv->next ) {
  1385. if ( mv->tv != tv ) {
  1386. continue;
  1387. }
  1388. if ( *(unsigned *)mv->color != *(unsigned *)color ) {
  1389. continue;
  1390. }
  1391. if ( !normalsParsed ) {
  1392. // if we are going to create the normals, just
  1393. // matching texcoords is enough
  1394. break;
  1395. }
  1396. if ( mv->normal * normal > normalEpsilon ) {
  1397. break; // we already have this one
  1398. }
  1399. }
  1400. if ( !mv ) {
  1401. // allocate a new match vert and link to hash chain
  1402. mv = &mvTable[ tri->numVerts ];
  1403. mv->v = v;
  1404. mv->tv = tv;
  1405. mv->normal = normal;
  1406. *(unsigned *)mv->color = *(unsigned *)color;
  1407. mv->next = NULL;
  1408. if ( lastmv ) {
  1409. lastmv->next = mv;
  1410. } else {
  1411. mvHash[v] = mv;
  1412. }
  1413. tri->numVerts++;
  1414. }
  1415. tri->indexes[tri->numIndexes] = mv - mvTable;
  1416. tri->numIndexes++;
  1417. }
  1418. }
  1419. // allocate space for the indexes and copy them
  1420. if ( tri->numIndexes > layer->polygon.count * 3 ) {
  1421. common->FatalError( "ConvertLWOToModelSurfaces: index miscount in LWO file %s", name.c_str() );
  1422. }
  1423. if ( tri->numVerts > layer->polygon.count * 3 ) {
  1424. common->FatalError( "ConvertLWOToModelSurfaces: vertex miscount in LWO file %s", name.c_str() );
  1425. }
  1426. // now allocate and generate the combined vertexes
  1427. R_AllocStaticTriSurfVerts( tri, tri->numVerts );
  1428. for ( j = 0; j < tri->numVerts; j++ ) {
  1429. mv = &mvTable[j];
  1430. tri->verts[ j ].Clear();
  1431. tri->verts[ j ].xyz = vList[ mv->v ];
  1432. tri->verts[ j ].SetTexCoord( tvList[ mv->tv ] );
  1433. tri->verts[ j ].SetNormal( mv->normal );
  1434. *(unsigned *)tri->verts[j].color = *(unsigned *)mv->color;
  1435. }
  1436. R_StaticFree( mvTable );
  1437. R_StaticFree( mvHash );
  1438. // see if we need to merge with a previous surface of the same material
  1439. modelSurf = &this->surfaces[mergeTo[ i ]];
  1440. srfTriangles_t *mergeTri = modelSurf->geometry;
  1441. if ( !mergeTri ) {
  1442. modelSurf->geometry = tri;
  1443. } else {
  1444. modelSurf->geometry = R_MergeTriangles( mergeTri, tri );
  1445. R_FreeStaticTriSurf( tri );
  1446. R_FreeStaticTriSurf( mergeTri );
  1447. }
  1448. }
  1449. R_StaticFree( tvRemap );
  1450. R_StaticFree( vRemap );
  1451. R_StaticFree( tvList );
  1452. R_StaticFree( vList );
  1453. return true;
  1454. }
  1455. /*
  1456. =================
  1457. idRenderModelStatic::ConvertLWOToASE
  1458. =================
  1459. */
  1460. struct aseModel_s *idRenderModelStatic::ConvertLWOToASE( const struct st_lwObject *obj, const char *fileName ) {
  1461. int j, k;
  1462. aseModel_t *ase;
  1463. if ( !obj ) {
  1464. return NULL;
  1465. }
  1466. // NOTE: using new operator because aseModel_t contains idList class objects
  1467. ase = new (TAG_MODEL) aseModel_t;
  1468. ase->timeStamp = obj->timeStamp;
  1469. ase->objects.Resize( obj->nlayers, obj->nlayers );
  1470. int materialRef = 0;
  1471. for ( lwSurface *surf = obj->surf; surf; surf = surf->next ) {
  1472. aseMaterial_t *mat = (aseMaterial_t *)Mem_ClearedAlloc( sizeof( *mat ), TAG_MODEL );
  1473. strcpy( mat->name, surf->name );
  1474. mat->uTiling = mat->vTiling = 1;
  1475. mat->angle = mat->uOffset = mat->vOffset = 0;
  1476. ase->materials.Append( mat );
  1477. lwLayer *layer = obj->layer;
  1478. aseObject_t *object = (aseObject_t *)Mem_ClearedAlloc( sizeof( *object ), TAG_MODEL );
  1479. object->materialRef = materialRef++;
  1480. aseMesh_t *mesh = &object->mesh;
  1481. ase->objects.Append( object );
  1482. mesh->numFaces = layer->polygon.count;
  1483. mesh->numTVFaces = mesh->numFaces;
  1484. mesh->faces = (aseFace_t *)Mem_Alloc( mesh->numFaces * sizeof( mesh->faces[0] ), TAG_MODEL );
  1485. mesh->numVertexes = layer->point.count;
  1486. mesh->vertexes = (idVec3 *)Mem_Alloc( mesh->numVertexes * sizeof( mesh->vertexes[0] ), TAG_MODEL );
  1487. // vertex positions
  1488. if ( layer->point.count <= 0 ) {
  1489. common->Warning( "ConvertLWOToASE: model \'%s\' has bad or missing vertex data", name.c_str() );
  1490. }
  1491. for ( j = 0; j < layer->point.count; j++ ) {
  1492. mesh->vertexes[j].x = layer->point.pt[j].pos[0];
  1493. mesh->vertexes[j].y = layer->point.pt[j].pos[2];
  1494. mesh->vertexes[j].z = layer->point.pt[j].pos[1];
  1495. }
  1496. // vertex texture coords
  1497. mesh->numTVertexes = 0;
  1498. if ( layer->nvmaps ) {
  1499. for( lwVMap *vm = layer->vmap; vm; vm = vm->next ) {
  1500. if ( vm->type == LWID_('T','X','U','V') ) {
  1501. mesh->numTVertexes += vm->nverts;
  1502. }
  1503. }
  1504. }
  1505. if ( mesh->numTVertexes ) {
  1506. mesh->tvertexes = (idVec2 *)Mem_Alloc( mesh->numTVertexes * sizeof( mesh->tvertexes[0] ), TAG_MODEL );
  1507. int offset = 0;
  1508. for( lwVMap *vm = layer->vmap; vm; vm = vm->next ) {
  1509. if ( vm->type == LWID_('T','X','U','V') ) {
  1510. vm->offset = offset;
  1511. for ( k = 0; k < vm->nverts; k++ ) {
  1512. mesh->tvertexes[k + offset].x = vm->val[k][0];
  1513. mesh->tvertexes[k + offset].y = 1.0f - vm->val[k][1]; // invert the t
  1514. }
  1515. offset += vm->nverts;
  1516. }
  1517. }
  1518. } else {
  1519. common->Warning( "ConvertLWOToASE: model \'%s\' has bad or missing uv data", fileName );
  1520. mesh->numTVertexes = 1;
  1521. mesh->tvertexes = (idVec2 *)Mem_ClearedAlloc( mesh->numTVertexes * sizeof( mesh->tvertexes[0] ), TAG_MODEL );
  1522. }
  1523. mesh->normalsParsed = true;
  1524. mesh->colorsParsed = true; // because we are falling back to the surface color
  1525. // triangles
  1526. int faceIndex = 0;
  1527. for ( j = 0; j < layer->polygon.count; j++ ) {
  1528. lwPolygon *poly = &layer->polygon.pol[j];
  1529. if ( poly->surf != surf ) {
  1530. continue;
  1531. }
  1532. if ( poly->nverts != 3 ) {
  1533. common->Warning( "ConvertLWOToASE: model %s has too many verts for a poly! Make sure you triplet it down", fileName );
  1534. continue;
  1535. }
  1536. mesh->faces[faceIndex].faceNormal.x = poly->norm[0];
  1537. mesh->faces[faceIndex].faceNormal.y = poly->norm[2];
  1538. mesh->faces[faceIndex].faceNormal.z = poly->norm[1];
  1539. for ( k = 0; k < 3; k++ ) {
  1540. mesh->faces[faceIndex].vertexNum[k] = poly->v[k].index;
  1541. mesh->faces[faceIndex].vertexNormals[k].x = poly->v[k].norm[0];
  1542. mesh->faces[faceIndex].vertexNormals[k].y = poly->v[k].norm[2];
  1543. mesh->faces[faceIndex].vertexNormals[k].z = poly->v[k].norm[1];
  1544. // complete fallbacks
  1545. mesh->faces[faceIndex].tVertexNum[k] = 0;
  1546. mesh->faces[faceIndex].vertexColors[k][0] = surf->color.rgb[0] * 255;
  1547. mesh->faces[faceIndex].vertexColors[k][1] = surf->color.rgb[1] * 255;
  1548. mesh->faces[faceIndex].vertexColors[k][2] = surf->color.rgb[2] * 255;
  1549. mesh->faces[faceIndex].vertexColors[k][3] = 255;
  1550. // first set attributes from the vertex
  1551. lwPoint *pt = &layer->point.pt[poly->v[k].index];
  1552. int nvm;
  1553. for ( nvm = 0; nvm < pt->nvmaps; nvm++ ) {
  1554. lwVMapPt *vm = &pt->vm[nvm];
  1555. if ( vm->vmap->type == LWID_('T','X','U','V') ) {
  1556. mesh->faces[faceIndex].tVertexNum[k] = vm->index + vm->vmap->offset;
  1557. }
  1558. if ( vm->vmap->type == LWID_('R','G','B','A') ) {
  1559. for ( int chan = 0; chan < 4; chan++ ) {
  1560. mesh->faces[faceIndex].vertexColors[k][chan] = 255 * vm->vmap->val[vm->index][chan];
  1561. }
  1562. }
  1563. }
  1564. // then override with polygon attributes
  1565. for ( nvm = 0; nvm < poly->v[k].nvmaps; nvm++ ) {
  1566. lwVMapPt *vm = &poly->v[k].vm[nvm];
  1567. if ( vm->vmap->type == LWID_('T','X','U','V') ) {
  1568. mesh->faces[faceIndex].tVertexNum[k] = vm->index + vm->vmap->offset;
  1569. }
  1570. if ( vm->vmap->type == LWID_('R','G','B','A') ) {
  1571. for ( int chan = 0; chan < 4; chan++ ) {
  1572. mesh->faces[faceIndex].vertexColors[k][chan] = 255 * vm->vmap->val[vm->index][chan];
  1573. }
  1574. }
  1575. }
  1576. }
  1577. faceIndex++;
  1578. }
  1579. mesh->numFaces = faceIndex;
  1580. mesh->numTVFaces = faceIndex;
  1581. aseFace_t *newFaces = ( aseFace_t* )Mem_Alloc( mesh->numFaces * sizeof ( mesh->faces[0] ), TAG_MODEL );
  1582. memcpy( newFaces, mesh->faces, sizeof( mesh->faces[0] ) * mesh->numFaces );
  1583. Mem_Free( mesh->faces );
  1584. mesh->faces = newFaces;
  1585. }
  1586. return ase;
  1587. }
  1588. /*
  1589. =================
  1590. idRenderModelStatic::ConvertMAToModelSurfaces
  1591. =================
  1592. */
  1593. bool idRenderModelStatic::ConvertMAToModelSurfaces (const struct maModel_s *ma ) {
  1594. maObject_t * object;
  1595. maMesh_t * mesh;
  1596. maMaterial_t * material;
  1597. const idMaterial *im1, *im2;
  1598. srfTriangles_t *tri;
  1599. int objectNum;
  1600. int i, j, k;
  1601. int v, tv;
  1602. int * vRemap;
  1603. int * tvRemap;
  1604. matchVert_t * mvTable; // all of the match verts
  1605. matchVert_t ** mvHash; // points inside mvTable for each xyz index
  1606. matchVert_t * lastmv;
  1607. matchVert_t * mv;
  1608. idVec3 normal;
  1609. float uOffset, vOffset, textureSin, textureCos;
  1610. float uTiling, vTiling;
  1611. int * mergeTo;
  1612. byte * color;
  1613. static byte identityColor[4] = { 255, 255, 255, 255 };
  1614. modelSurface_t surf, *modelSurf;
  1615. if ( !ma ) {
  1616. return false;
  1617. }
  1618. if ( ma->objects.Num() < 1 ) {
  1619. return false;
  1620. }
  1621. timeStamp = ma->timeStamp;
  1622. // the modeling programs can save out multiple surfaces with a common
  1623. // material, but we would like to mege them together where possible
  1624. // meaning that this->NumSurfaces() <= ma->objects.currentElements
  1625. mergeTo = (int *)_alloca( ma->objects.Num() * sizeof( *mergeTo ) );
  1626. surf.geometry = NULL;
  1627. if ( ma->materials.Num() == 0 ) {
  1628. // if we don't have any materials, dump everything into a single surface
  1629. surf.shader = tr.defaultMaterial;
  1630. surf.id = 0;
  1631. this->AddSurface( surf );
  1632. for ( i = 0; i < ma->objects.Num(); i++ ) {
  1633. mergeTo[i] = 0;
  1634. }
  1635. } else if ( !r_mergeModelSurfaces.GetBool() ) {
  1636. // don't merge any
  1637. for ( i = 0; i < ma->objects.Num(); i++ ) {
  1638. mergeTo[i] = i;
  1639. object = ma->objects[i];
  1640. if(object->materialRef >= 0) {
  1641. material = ma->materials[object->materialRef];
  1642. surf.shader = declManager->FindMaterial( material->name );
  1643. } else {
  1644. surf.shader = tr.defaultMaterial;
  1645. }
  1646. surf.id = this->NumSurfaces();
  1647. this->AddSurface( surf );
  1648. }
  1649. } else {
  1650. // search for material matches
  1651. for ( i = 0; i < ma->objects.Num(); i++ ) {
  1652. object = ma->objects[i];
  1653. if(object->materialRef >= 0) {
  1654. material = ma->materials[object->materialRef];
  1655. im1 = declManager->FindMaterial( material->name );
  1656. } else {
  1657. im1 = tr.defaultMaterial;
  1658. }
  1659. if ( im1->IsDiscrete() ) {
  1660. // flares, autosprites, etc
  1661. j = this->NumSurfaces();
  1662. } else {
  1663. for ( j = 0; j < this->NumSurfaces(); j++ ) {
  1664. modelSurf = &this->surfaces[j];
  1665. im2 = modelSurf->shader;
  1666. if ( im1 == im2 ) {
  1667. // merge this
  1668. mergeTo[i] = j;
  1669. break;
  1670. }
  1671. }
  1672. }
  1673. if ( j == this->NumSurfaces() ) {
  1674. // didn't merge
  1675. mergeTo[i] = j;
  1676. surf.shader = im1;
  1677. surf.id = this->NumSurfaces();
  1678. this->AddSurface( surf );
  1679. }
  1680. }
  1681. }
  1682. idVectorSubset<idVec3, 3> vertexSubset;
  1683. idVectorSubset<idVec2, 2> texCoordSubset;
  1684. // build the surfaces
  1685. for ( objectNum = 0; objectNum < ma->objects.Num(); objectNum++ ) {
  1686. object = ma->objects[objectNum];
  1687. mesh = &object->mesh;
  1688. if(object->materialRef >= 0) {
  1689. material = ma->materials[object->materialRef];
  1690. im1 = declManager->FindMaterial( material->name );
  1691. } else {
  1692. im1 = tr.defaultMaterial;
  1693. }
  1694. bool normalsParsed = mesh->normalsParsed;
  1695. // completely ignore any explict normals on surfaces with a renderbump command
  1696. // which will guarantee the best contours and least vertexes.
  1697. const char *rb = im1->GetRenderBump();
  1698. if ( rb != NULL && rb[0] != NULL ) {
  1699. normalsParsed = false;
  1700. }
  1701. // It seems like the tools our artists are using often generate
  1702. // verts and texcoords slightly separated that should be merged
  1703. // note that we really should combine the surfaces with common materials
  1704. // before doing this operation, because we can miss a slop combination
  1705. // if they are in different surfaces
  1706. vRemap = (int *)R_StaticAlloc( mesh->numVertexes * sizeof( vRemap[0] ), TAG_MODEL );
  1707. if ( fastLoad ) {
  1708. // renderbump doesn't care about vertex count
  1709. for ( j = 0; j < mesh->numVertexes; j++ ) {
  1710. vRemap[j] = j;
  1711. }
  1712. } else {
  1713. float vertexEpsilon = r_slopVertex.GetFloat();
  1714. float expand = 2 * 32 * vertexEpsilon;
  1715. idVec3 mins, maxs;
  1716. SIMDProcessor->MinMax( mins, maxs, mesh->vertexes, mesh->numVertexes );
  1717. mins -= idVec3( expand, expand, expand );
  1718. maxs += idVec3( expand, expand, expand );
  1719. vertexSubset.Init( mins, maxs, 32, 1024 );
  1720. for ( j = 0; j < mesh->numVertexes; j++ ) {
  1721. vRemap[j] = vertexSubset.FindVector( mesh->vertexes, j, vertexEpsilon );
  1722. }
  1723. }
  1724. tvRemap = (int *)R_StaticAlloc( mesh->numTVertexes * sizeof( tvRemap[0] ), TAG_MODEL );
  1725. if ( fastLoad ) {
  1726. // renderbump doesn't care about vertex count
  1727. for ( j = 0; j < mesh->numTVertexes; j++ ) {
  1728. tvRemap[j] = j;
  1729. }
  1730. } else {
  1731. float texCoordEpsilon = r_slopTexCoord.GetFloat();
  1732. float expand = 2 * 32 * texCoordEpsilon;
  1733. idVec2 mins, maxs;
  1734. SIMDProcessor->MinMax( mins, maxs, mesh->tvertexes, mesh->numTVertexes );
  1735. mins -= idVec2( expand, expand );
  1736. maxs += idVec2( expand, expand );
  1737. texCoordSubset.Init( mins, maxs, 32, 1024 );
  1738. for ( j = 0; j < mesh->numTVertexes; j++ ) {
  1739. tvRemap[j] = texCoordSubset.FindVector( mesh->tvertexes, j, texCoordEpsilon );
  1740. }
  1741. }
  1742. // we need to find out how many unique vertex / texcoord / color combinations
  1743. // there are, because MA tracks them separately but we need them unified
  1744. // the maximum possible number of combined vertexes is the number of indexes
  1745. mvTable = (matchVert_t *)R_ClearedStaticAlloc( mesh->numFaces * 3 * sizeof( mvTable[0] ) );
  1746. // we will have a hash chain based on the xyz values
  1747. mvHash = (matchVert_t **)R_ClearedStaticAlloc( mesh->numVertexes * sizeof( mvHash[0] ) );
  1748. // allocate triangle surface
  1749. tri = R_AllocStaticTriSurf();
  1750. tri->numVerts = 0;
  1751. tri->numIndexes = 0;
  1752. R_AllocStaticTriSurfIndexes( tri, mesh->numFaces * 3 );
  1753. tri->generateNormals = !normalsParsed;
  1754. // init default normal, color and tex coord index
  1755. normal.Zero();
  1756. color = identityColor;
  1757. tv = 0;
  1758. // find all the unique combinations
  1759. float normalEpsilon = 1.0f - r_slopNormal.GetFloat();
  1760. for ( j = 0; j < mesh->numFaces; j++ ) {
  1761. for ( k = 0; k < 3; k++ ) {
  1762. v = mesh->faces[j].vertexNum[k];
  1763. if ( v < 0 || v >= mesh->numVertexes ) {
  1764. common->Error( "ConvertMAToModelSurfaces: bad vertex index in MA file %s", name.c_str() );
  1765. }
  1766. // collapse the position if it was slightly offset
  1767. v = vRemap[v];
  1768. // we may or may not have texcoords to compare
  1769. if ( mesh->numTVertexes != 0 ) {
  1770. tv = mesh->faces[j].tVertexNum[k];
  1771. if ( tv < 0 || tv >= mesh->numTVertexes ) {
  1772. common->Error( "ConvertMAToModelSurfaces: bad tex coord index in MA file %s", name.c_str() );
  1773. }
  1774. // collapse the tex coord if it was slightly offset
  1775. tv = tvRemap[tv];
  1776. }
  1777. // we may or may not have normals to compare
  1778. if ( normalsParsed ) {
  1779. normal = mesh->faces[j].vertexNormals[k];
  1780. }
  1781. //BSM: Todo: Fix the vertex colors
  1782. // we may or may not have colors to compare
  1783. if ( mesh->faces[j].vertexColors[k] != -1 && mesh->faces[j].vertexColors[k] != -999 ) {
  1784. color = &mesh->colors[mesh->faces[j].vertexColors[k]*4];
  1785. }
  1786. // find a matching vert
  1787. for ( lastmv = NULL, mv = mvHash[v]; mv != NULL; lastmv = mv, mv = mv->next ) {
  1788. if ( mv->tv != tv ) {
  1789. continue;
  1790. }
  1791. if ( *(unsigned *)mv->color != *(unsigned *)color ) {
  1792. continue;
  1793. }
  1794. if ( !normalsParsed ) {
  1795. // if we are going to create the normals, just
  1796. // matching texcoords is enough
  1797. break;
  1798. }
  1799. if ( mv->normal * normal > normalEpsilon ) {
  1800. break; // we already have this one
  1801. }
  1802. }
  1803. if ( !mv ) {
  1804. // allocate a new match vert and link to hash chain
  1805. mv = &mvTable[ tri->numVerts ];
  1806. mv->v = v;
  1807. mv->tv = tv;
  1808. mv->normal = normal;
  1809. *(unsigned *)mv->color = *(unsigned *)color;
  1810. mv->next = NULL;
  1811. if ( lastmv ) {
  1812. lastmv->next = mv;
  1813. } else {
  1814. mvHash[v] = mv;
  1815. }
  1816. tri->numVerts++;
  1817. }
  1818. tri->indexes[tri->numIndexes] = mv - mvTable;
  1819. tri->numIndexes++;
  1820. }
  1821. }
  1822. // allocate space for the indexes and copy them
  1823. if ( tri->numIndexes > mesh->numFaces * 3 ) {
  1824. common->FatalError( "ConvertMAToModelSurfaces: index miscount in MA file %s", name.c_str() );
  1825. }
  1826. if ( tri->numVerts > mesh->numFaces * 3 ) {
  1827. common->FatalError( "ConvertMAToModelSurfaces: vertex miscount in MA file %s", name.c_str() );
  1828. }
  1829. // an MA allows the texture coordinates to be scaled, translated, and rotated
  1830. //BSM: Todo: Does Maya support this and if so how
  1831. //if ( ase->materials.Num() == 0 ) {
  1832. uOffset = vOffset = 0.0f;
  1833. uTiling = vTiling = 1.0f;
  1834. textureSin = 0.0f;
  1835. textureCos = 1.0f;
  1836. //} else {
  1837. // material = ase->materials[object->materialRef];
  1838. // uOffset = -material->uOffset;
  1839. // vOffset = material->vOffset;
  1840. // uTiling = material->uTiling;
  1841. // vTiling = material->vTiling;
  1842. // textureSin = idMath::Sin( material->angle );
  1843. // textureCos = idMath::Cos( material->angle );
  1844. //}
  1845. // now allocate and generate the combined vertexes
  1846. R_AllocStaticTriSurfVerts( tri, tri->numVerts );
  1847. for ( j = 0; j < tri->numVerts; j++ ) {
  1848. mv = &mvTable[j];
  1849. tri->verts[ j ].Clear();
  1850. tri->verts[ j ].xyz = mesh->vertexes[ mv->v ];
  1851. tri->verts[ j ].SetNormal( mv->normal );
  1852. *(unsigned *)tri->verts[j].color = *(unsigned *)mv->color;
  1853. if ( mesh->numTVertexes != 0 ) {
  1854. const idVec2 &tv = mesh->tvertexes[ mv->tv ];
  1855. float u = tv.x * uTiling + uOffset;
  1856. float v = tv.y * vTiling + vOffset;
  1857. tri->verts[j].SetTexCoord( u * textureCos + v * textureSin, u * -textureSin + v * textureCos );
  1858. }
  1859. }
  1860. R_StaticFree( mvTable );
  1861. R_StaticFree( mvHash );
  1862. R_StaticFree( tvRemap );
  1863. R_StaticFree( vRemap );
  1864. // see if we need to merge with a previous surface of the same material
  1865. modelSurf = &this->surfaces[mergeTo[ objectNum ]];
  1866. srfTriangles_t *mergeTri = modelSurf->geometry;
  1867. if ( !mergeTri ) {
  1868. modelSurf->geometry = tri;
  1869. } else {
  1870. modelSurf->geometry = R_MergeTriangles( mergeTri, tri );
  1871. R_FreeStaticTriSurf( tri );
  1872. R_FreeStaticTriSurf( mergeTri );
  1873. }
  1874. }
  1875. return true;
  1876. }
  1877. /*
  1878. =================
  1879. idRenderModelStatic::LoadASE
  1880. =================
  1881. */
  1882. bool idRenderModelStatic::LoadASE( const char *fileName ) {
  1883. aseModel_t *ase;
  1884. ase = ASE_Load( fileName );
  1885. if ( ase == NULL ) {
  1886. return false;
  1887. }
  1888. ConvertASEToModelSurfaces( ase );
  1889. ASE_Free( ase );
  1890. return true;
  1891. }
  1892. /*
  1893. =================
  1894. idRenderModelStatic::LoadLWO
  1895. =================
  1896. */
  1897. bool idRenderModelStatic::LoadLWO( const char *fileName ) {
  1898. unsigned int failID;
  1899. int failPos;
  1900. lwObject *lwo;
  1901. lwo = lwGetObject( fileName, &failID, &failPos );
  1902. if ( lwo == NULL ) {
  1903. return false;
  1904. }
  1905. ConvertLWOToModelSurfaces( lwo );
  1906. lwFreeObject( lwo );
  1907. return true;
  1908. }
  1909. /*
  1910. =================
  1911. idRenderModelStatic::LoadMA
  1912. =================
  1913. */
  1914. bool idRenderModelStatic::LoadMA( const char *fileName ) {
  1915. maModel_t *ma;
  1916. ma = MA_Load( fileName );
  1917. if ( ma == NULL ) {
  1918. return false;
  1919. }
  1920. ConvertMAToModelSurfaces( ma );
  1921. MA_Free( ma );
  1922. return true;
  1923. }
  1924. //=============================================================================
  1925. /*
  1926. ================
  1927. idRenderModelStatic::PurgeModel
  1928. ================
  1929. */
  1930. void idRenderModelStatic::PurgeModel() {
  1931. for ( int i = 0; i < surfaces.Num(); i++ ) {
  1932. modelSurface_t * surf = &surfaces[i];
  1933. if ( surf->geometry ) {
  1934. R_FreeStaticTriSurf( surf->geometry );
  1935. }
  1936. }
  1937. surfaces.Clear();
  1938. if ( jointsInverted != NULL ) {
  1939. Mem_Free( jointsInverted );
  1940. jointsInverted = NULL;
  1941. }
  1942. purged = true;
  1943. }
  1944. /*
  1945. ==============
  1946. idRenderModelStatic::FreeVertexCache
  1947. We are about to restart the vertex cache, so dump everything
  1948. ==============
  1949. */
  1950. void idRenderModelStatic::FreeVertexCache() {
  1951. for ( int j = 0; j < surfaces.Num(); j++ ) {
  1952. srfTriangles_t *tri = surfaces[j].geometry;
  1953. if ( tri == NULL ) {
  1954. continue;
  1955. }
  1956. R_FreeStaticTriSurfVertexCaches( tri );
  1957. }
  1958. }
  1959. /*
  1960. ================
  1961. idRenderModelStatic::ReadFromDemoFile
  1962. ================
  1963. */
  1964. void idRenderModelStatic::ReadFromDemoFile( class idDemoFile *f ) {
  1965. PurgeModel();
  1966. InitEmpty( f->ReadHashString() );
  1967. int i, j, numSurfaces;
  1968. f->ReadInt( numSurfaces );
  1969. for ( i = 0; i < numSurfaces; i++ ) {
  1970. modelSurface_t surf;
  1971. surf.shader = declManager->FindMaterial( f->ReadHashString() );
  1972. srfTriangles_t *tri = R_AllocStaticTriSurf();
  1973. f->ReadInt( tri->numIndexes );
  1974. R_AllocStaticTriSurfIndexes( tri, tri->numIndexes );
  1975. for ( j = 0; j < tri->numIndexes; ++j )
  1976. f->ReadInt( (int&)tri->indexes[j] );
  1977. f->ReadInt( tri->numVerts );
  1978. R_AllocStaticTriSurfVerts( tri, tri->numVerts );
  1979. idVec3 tNormal, tTangent, tBiTangent;
  1980. for ( j = 0; j < tri->numVerts; ++j ) {
  1981. f->ReadVec3( tri->verts[j].xyz );
  1982. f->ReadBigArray( tri->verts[j].st, 2 );
  1983. f->ReadBigArray( tri->verts[j].normal, 4 );
  1984. f->ReadBigArray( tri->verts[j].tangent, 4 );
  1985. f->ReadUnsignedChar( tri->verts[j].color[0] );
  1986. f->ReadUnsignedChar( tri->verts[j].color[1] );
  1987. f->ReadUnsignedChar( tri->verts[j].color[2] );
  1988. f->ReadUnsignedChar( tri->verts[j].color[3] );
  1989. }
  1990. surf.geometry = tri;
  1991. this->AddSurface( surf );
  1992. }
  1993. this->FinishSurfaces();
  1994. }
  1995. /*
  1996. ================
  1997. idRenderModelStatic::WriteToDemoFile
  1998. ================
  1999. */
  2000. void idRenderModelStatic::WriteToDemoFile( class idDemoFile *f ) {
  2001. int data[1];
  2002. // note that it has been updated
  2003. lastArchivedFrame = tr.frameCount;
  2004. data[0] = DC_DEFINE_MODEL;
  2005. f->WriteInt( data[0] );
  2006. f->WriteHashString( this->Name() );
  2007. int i, j, iData = surfaces.Num();
  2008. f->WriteInt( iData );
  2009. for ( i = 0; i < surfaces.Num(); i++ ) {
  2010. const modelSurface_t *surf = &surfaces[i];
  2011. f->WriteHashString( surf->shader->GetName() );
  2012. srfTriangles_t *tri = surf->geometry;
  2013. f->WriteInt( tri->numIndexes );
  2014. for ( j = 0; j < tri->numIndexes; ++j )
  2015. f->WriteInt( (int&)tri->indexes[j] );
  2016. f->WriteInt( tri->numVerts );
  2017. for ( j = 0; j < tri->numVerts; ++j ) {
  2018. f->WriteVec3( tri->verts[j].xyz );
  2019. f->WriteBigArray( tri->verts[j].st, 2 );
  2020. f->WriteBigArray( tri->verts[j].normal, 4 );
  2021. f->WriteBigArray( tri->verts[j].tangent, 4 );
  2022. f->WriteUnsignedChar( tri->verts[j].color[0] );
  2023. f->WriteUnsignedChar( tri->verts[j].color[1] );
  2024. f->WriteUnsignedChar( tri->verts[j].color[2] );
  2025. f->WriteUnsignedChar( tri->verts[j].color[3] );
  2026. }
  2027. }
  2028. }
  2029. /*
  2030. ================
  2031. idRenderModelStatic::IsLoaded
  2032. ================
  2033. */
  2034. bool idRenderModelStatic::IsLoaded() {
  2035. return !purged;
  2036. }
  2037. /*
  2038. ================
  2039. idRenderModelStatic::SetLevelLoadReferenced
  2040. ================
  2041. */
  2042. void idRenderModelStatic::SetLevelLoadReferenced( bool referenced ) {
  2043. levelLoadReferenced = referenced;
  2044. }
  2045. /*
  2046. ================
  2047. idRenderModelStatic::IsLevelLoadReferenced
  2048. ================
  2049. */
  2050. bool idRenderModelStatic::IsLevelLoadReferenced() {
  2051. return levelLoadReferenced;
  2052. }
  2053. /*
  2054. =================
  2055. idRenderModelStatic::TouchData
  2056. =================
  2057. */
  2058. void idRenderModelStatic::TouchData() {
  2059. for ( int i = 0; i < surfaces.Num(); i++ ) {
  2060. const modelSurface_t *surf = &surfaces[i];
  2061. // re-find the material to make sure it gets added to the
  2062. // level keep list
  2063. declManager->FindMaterial( surf->shader->GetName() );
  2064. }
  2065. }
  2066. /*
  2067. =================
  2068. idRenderModelStatic::DeleteSurfaceWithId
  2069. =================
  2070. */
  2071. bool idRenderModelStatic::DeleteSurfaceWithId( int id ) {
  2072. int i;
  2073. for ( i = 0; i < surfaces.Num(); i++ ) {
  2074. if ( surfaces[i].id == id ) {
  2075. R_FreeStaticTriSurf( surfaces[i].geometry );
  2076. surfaces.RemoveIndex( i );
  2077. return true;
  2078. }
  2079. }
  2080. return false;
  2081. }
  2082. /*
  2083. =================
  2084. idRenderModelStatic::DeleteSurfacesWithNegativeId
  2085. =================
  2086. */
  2087. void idRenderModelStatic::DeleteSurfacesWithNegativeId() {
  2088. for ( int i = 0; i < surfaces.Num(); i++ ) {
  2089. if ( surfaces[i].id < 0 ) {
  2090. R_FreeStaticTriSurf( surfaces[i].geometry );
  2091. surfaces.RemoveIndex( i );
  2092. i--;
  2093. }
  2094. }
  2095. }
  2096. /*
  2097. =================
  2098. idRenderModelStatic::FindSurfaceWithId
  2099. =================
  2100. */
  2101. bool idRenderModelStatic::FindSurfaceWithId( int id, int &surfaceNum ) const {
  2102. for ( int i = 0; i < surfaces.Num(); i++ ) {
  2103. if ( surfaces[i].id == id ) {
  2104. surfaceNum = i;
  2105. return true;
  2106. }
  2107. }
  2108. return false;
  2109. }