interiorIO.cpp 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "interior/interior.h"
  23. #include "core/bitVector.h"
  24. #include "core/stream/stream.h"
  25. #include "math/mathIO.h"
  26. #include "gfx/bitmap/gBitmap.h"
  27. #include "interior/interiorSubObject.h"
  28. #include "console/console.h"
  29. #include "core/frameAllocator.h"
  30. #include "materials/materialList.h"
  31. int QSORT_CALLBACK cmpU32(const void* p1, const void* p2)
  32. {
  33. return S32(*((U32*)p1)) - S32(*((U32*)p2));
  34. }
  35. //------------------------------------------------------------------------------
  36. //-------------------------------------- PERSISTENCE IMPLEMENTATION
  37. //
  38. U32 Interior::smFileVersion = 14;
  39. bool Interior::read(Stream& stream)
  40. {
  41. AssertFatal(stream.hasCapability(Stream::StreamRead), "Interior::read: non-read capable stream passed");
  42. AssertFatal(stream.getStatus() == Stream::Ok, "Interior::read: Error, stream in inconsistent state");
  43. S32 i;
  44. // Version this stream. We only load stream of the current version
  45. U32 fileVersion;
  46. stream.read(&fileVersion);
  47. // We need to store the version in case there is any post processing that
  48. // needs to take place that is dependent on the file version
  49. mFileVersion = fileVersion;
  50. if (fileVersion > smFileVersion)
  51. {
  52. Con::errorf(ConsoleLogEntry::General, "Interior::read: incompatible file version found.");
  53. return false;
  54. }
  55. // Geometry factors...
  56. stream.read(&mDetailLevel);
  57. stream.read(&mMinPixels);
  58. mathRead(stream, &mBoundingBox);
  59. mathRead(stream, &mBoundingSphere);
  60. stream.read(&mHasAlarmState);
  61. stream.read(&mNumLightStateEntries);
  62. // Now read in our data vectors.
  63. S32 vectorSize;
  64. // mPlanes
  65. readPlaneVector(stream);
  66. // mPoints
  67. stream.read(&vectorSize);
  68. mPoints.setSize(vectorSize);
  69. for (i = 0; i < mPoints.size(); i++)
  70. mathRead(stream, &mPoints[i].point);
  71. // mPointVisibility
  72. stream.read(&vectorSize);
  73. mPointVisibility.setSize(vectorSize);
  74. stream.read(vectorSize, mPointVisibility.address());
  75. // mTexGenEQs
  76. stream.read(&vectorSize);
  77. mTexGenEQs.setSize(vectorSize);
  78. for(i = 0; i < mTexGenEQs.size(); i++)
  79. {
  80. mathRead(stream, &mTexGenEQs[i].planeX);
  81. mathRead(stream, &mTexGenEQs[i].planeY);
  82. }
  83. // mBSPNodes;
  84. stream.read(&vectorSize);
  85. mBSPNodes.setSize(vectorSize);
  86. for(i = 0; i < mBSPNodes.size(); i++)
  87. {
  88. stream.read(&mBSPNodes[i].planeIndex);
  89. if (fileVersion >= 14)
  90. {
  91. stream.read(&mBSPNodes[i].frontIndex);
  92. stream.read(&mBSPNodes[i].backIndex);
  93. }
  94. else
  95. {
  96. U16 frontIndex, backIndex;
  97. stream.read(&frontIndex);
  98. stream.read(&backIndex);
  99. mBSPNodes[i].frontIndex = U32(frontIndex);
  100. mBSPNodes[i].backIndex = U32(backIndex);
  101. }
  102. }
  103. // mBSPSolidLeaves
  104. stream.read(&vectorSize);
  105. mBSPSolidLeaves.setSize(vectorSize);
  106. for(i = 0; i < mBSPSolidLeaves.size(); i++)
  107. {
  108. stream.read(&mBSPSolidLeaves[i].surfaceIndex);
  109. stream.read(&mBSPSolidLeaves[i].surfaceCount);
  110. }
  111. // MaterialList
  112. if(mMaterialList != NULL)
  113. delete mMaterialList;
  114. mMaterialList = new MaterialList;
  115. mMaterialList->read(stream);
  116. // mWindings
  117. stream.read(&vectorSize);
  118. mWindings.setSize(vectorSize);
  119. for(i = 0; i < mWindings.size(); i++)
  120. {
  121. stream.read(&mWindings[i]);
  122. }
  123. // mWindingIndices
  124. stream.read(&vectorSize);
  125. mWindingIndices.setSize(vectorSize);
  126. for(i = 0; i < mWindingIndices.size(); i++)
  127. {
  128. stream.read(&mWindingIndices[i].windingStart);
  129. stream.read(&mWindingIndices[i].windingCount);
  130. }
  131. // mEdges
  132. if (fileVersion >= 12)
  133. {
  134. stream.read(&vectorSize);
  135. mEdges.setSize(vectorSize);
  136. for (i = 0; i < mEdges.size(); i++)
  137. {
  138. stream.read(&mEdges[i].vertexes[0]);
  139. stream.read(&mEdges[i].vertexes[1]);
  140. stream.read(&mEdges[i].faces[0]);
  141. stream.read(&mEdges[i].faces[1]);
  142. }
  143. }
  144. // mZones
  145. stream.read(&vectorSize);
  146. mZones.setSize(vectorSize);
  147. for(i = 0; i < mZones.size(); i++)
  148. {
  149. stream.read(&mZones[i].portalStart);
  150. stream.read(&mZones[i].portalCount);
  151. stream.read(&mZones[i].surfaceStart);
  152. stream.read(&mZones[i].surfaceCount);
  153. if (fileVersion >= 12)
  154. {
  155. stream.read(&mZones[i].staticMeshStart);
  156. stream.read(&mZones[i].staticMeshCount);
  157. }
  158. else
  159. {
  160. mZones[i].staticMeshStart = 0;
  161. mZones[i].staticMeshCount = 0;
  162. }
  163. stream.read(&mZones[i].flags);
  164. mZones[i].zoneId = 0;
  165. }
  166. // Zone surfaces
  167. stream.read(&vectorSize);
  168. mZoneSurfaces.setSize(vectorSize);
  169. for(i = 0; i < mZoneSurfaces.size(); i++)
  170. stream.read(&mZoneSurfaces[i]);
  171. // Zone static meshes
  172. if (fileVersion >= 12)
  173. {
  174. stream.read(&vectorSize);
  175. mZoneStaticMeshes.setSize(vectorSize);
  176. for (i = 0; i < mZoneStaticMeshes.size(); i++)
  177. stream.read(&mZoneStaticMeshes[i]);
  178. }
  179. // mZonePortalList;
  180. stream.read(&vectorSize);
  181. mZonePortalList.setSize(vectorSize);
  182. for(i = 0; i < mZonePortalList.size(); i++)
  183. stream.read(&mZonePortalList[i]);
  184. // mPortals
  185. stream.read(&vectorSize);
  186. mPortals.setSize(vectorSize);
  187. for(i = 0; i < mPortals.size(); i++)
  188. {
  189. stream.read(&mPortals[i].planeIndex);
  190. stream.read(&mPortals[i].triFanCount);
  191. stream.read(&mPortals[i].triFanStart);
  192. stream.read(&mPortals[i].zoneFront);
  193. stream.read(&mPortals[i].zoneBack);
  194. }
  195. // mSurfaces
  196. stream.read(&vectorSize);
  197. mSurfaces.setSize(vectorSize);
  198. mLMTexGenEQs.setSize(vectorSize);
  199. // Couple of hoops to *attempt* to detect that we are loading
  200. // a TGE version 0 Interior and not a TGEA verison 0
  201. U32 surfacePos = stream.getPosition();
  202. bool tgeInterior = false;
  203. // First attempt to read this as though it isn't a TGE version 0 Interior
  204. for(i = 0; i < mSurfaces.size(); i++)
  205. {
  206. // If we end up reading any invalid data in this loop then odds
  207. // are that we are no longer correctly reading from the stream
  208. // and have gotten off because this is a TGE version 0 Interior
  209. Surface& surface = mSurfaces[i];
  210. if (readSurface(stream, surface, mLMTexGenEQs[i], false) == false)
  211. {
  212. tgeInterior = true;
  213. break;
  214. }
  215. }
  216. // If this is a version 0 Interior and we failed to read it as a
  217. // TGEA version 0 Interior then attempt to read it as a TGE version 0
  218. if (fileVersion == 0 && tgeInterior)
  219. {
  220. // Set our stream position back to the start of the surfaces
  221. stream.setPosition(surfacePos);
  222. // Try reading in the surfaces again
  223. for(i = 0; i < mSurfaces.size(); i++)
  224. {
  225. Surface& surface = mSurfaces[i];
  226. // If we fail on any of the surfaces then bail
  227. if (readSurface(stream, surface, mLMTexGenEQs[i], true) == false)
  228. return false;
  229. }
  230. }
  231. // If we failed to read but this isn't a version 0 Interior
  232. // then something has gone horribly wrong
  233. else if (fileVersion != 0 && tgeInterior)
  234. return false;
  235. // Edges
  236. if (fileVersion == 5)
  237. {
  238. stream.read(&vectorSize);
  239. mEdges.setSize(vectorSize);
  240. for (i = 0; i < mEdges.size(); i++)
  241. {
  242. stream.read(&mEdges[i].vertexes[0]);
  243. stream.read(&mEdges[i].vertexes[1]);
  244. U32 normals[2];
  245. stream.read(&normals[0]);
  246. stream.read(&normals[1]);
  247. if (fileVersion > 2) // version 3 is where surface id's get added
  248. {
  249. stream.read(&mEdges[i].faces[0]);
  250. stream.read(&mEdges[i].faces[1]);
  251. }
  252. }
  253. }
  254. // mNormals
  255. if (fileVersion == 5)
  256. {
  257. stream.read(&vectorSize);
  258. Vector<Point3F> normals;
  259. normals.setSize(vectorSize);
  260. for(i = 0; i < normals.size(); i++)
  261. mathRead(stream, &normals[i]);
  262. // mNormalIndices
  263. stream.read(&vectorSize);
  264. Vector<U16> normalIndices;
  265. normalIndices.setSize(vectorSize);
  266. for (i = 0; i < normalIndices.size(); i++)
  267. stream.read(&normalIndices[i]);
  268. }
  269. // NormalLMapIndices
  270. stream.read(&vectorSize);
  271. mNormalLMapIndices.setSize(vectorSize);
  272. for (U32 i = 0; i < mNormalLMapIndices.size(); i++)
  273. {
  274. if (fileVersion >= 13)
  275. stream.read(&mNormalLMapIndices[i]);
  276. else
  277. {
  278. U8 index = 0;
  279. stream.read(&index);
  280. mNormalLMapIndices[i] = (U32)index;
  281. }
  282. }
  283. // AlarmLMapIndices
  284. stream.read(&vectorSize);
  285. mAlarmLMapIndices.setSize(vectorSize);
  286. for (U32 i = 0; i < mAlarmLMapIndices.size(); i++)
  287. {
  288. if (fileVersion >= 13)
  289. stream.read(&mAlarmLMapIndices[i]);
  290. else
  291. {
  292. U8 index = 0;
  293. stream.read(&index);
  294. mAlarmLMapIndices[i] = (U32)index;
  295. }
  296. }
  297. // mNullSurfaces
  298. stream.read(&vectorSize);
  299. mNullSurfaces.setSize(vectorSize);
  300. for(i = 0; i < mNullSurfaces.size(); i++)
  301. {
  302. stream.read(&mNullSurfaces[i].windingStart);
  303. stream.read(&mNullSurfaces[i].planeIndex);
  304. stream.read(&mNullSurfaces[i].surfaceFlags);
  305. if (fileVersion >= 13)
  306. stream.read(&mNullSurfaces[i].windingCount);
  307. else
  308. {
  309. U8 count;
  310. stream.read(&count);
  311. mNullSurfaces[i].windingCount = (U32)count;
  312. }
  313. }
  314. // mLightmaps
  315. stream.read(&vectorSize);
  316. mLightmaps.setSize(vectorSize);
  317. mLightmapKeep.setSize(vectorSize);
  318. GBitmap dummyBmp;
  319. for(i = 0; i < mLightmaps.size(); i++)
  320. {
  321. mLightmaps[i] = new GBitmap;
  322. mLightmaps[i]->readBitmap("png",stream);
  323. if (!tgeInterior && (fileVersion == 0 || fileVersion == 5 || fileVersion >= 12))
  324. {
  325. // The "light normal maps" or "light direction maps" were
  326. // removed from Torque 3D... this just reads and throws
  327. // them away.
  328. dummyBmp.readBitmap("png",stream);
  329. }
  330. stream.read(&mLightmapKeep[i]);
  331. }
  332. // mSolidLeafSurfaces
  333. stream.read(&vectorSize);
  334. mSolidLeafSurfaces.setSize(vectorSize);
  335. for(i = 0; i < mSolidLeafSurfaces.size(); i++)
  336. {
  337. stream.read(&mSolidLeafSurfaces[i]);
  338. }
  339. // mAnimatedLights
  340. mNumTriggerableLights = 0;
  341. stream.read(&vectorSize);
  342. mAnimatedLights.setSize(vectorSize);
  343. for(i = 0; i < mAnimatedLights.size(); i++)
  344. {
  345. stream.read(&mAnimatedLights[i].nameIndex);
  346. stream.read(&mAnimatedLights[i].stateIndex);
  347. stream.read(&mAnimatedLights[i].stateCount);
  348. stream.read(&mAnimatedLights[i].flags);
  349. stream.read(&mAnimatedLights[i].duration);
  350. if((mAnimatedLights[i].flags & AnimationAmbient) == 0)
  351. mNumTriggerableLights++;
  352. }
  353. // mLightStates
  354. stream.read(&vectorSize);
  355. mLightStates.setSize(vectorSize);
  356. for(i = 0; i < mLightStates.size(); i++)
  357. {
  358. stream.read(&mLightStates[i].red);
  359. stream.read(&mLightStates[i].green);
  360. stream.read(&mLightStates[i].blue);
  361. stream.read(&mLightStates[i].activeTime);
  362. stream.read(&mLightStates[i].dataIndex);
  363. stream.read(&mLightStates[i].dataCount);
  364. }
  365. // mStateData
  366. stream.read(&vectorSize);
  367. mStateData.setSize(vectorSize);
  368. for(i = 0; i < mStateData.size(); i++)
  369. {
  370. stream.read(&mStateData[i].surfaceIndex);
  371. stream.read(&mStateData[i].mapIndex);
  372. stream.read(&mStateData[i].lightStateIndex);
  373. }
  374. // mStateDataBuffer
  375. stream.read(&vectorSize);
  376. mStateDataBuffer.setSize(vectorSize);
  377. U32 flags;
  378. stream.read(&flags);
  379. stream.read(mStateDataBuffer.size(), mStateDataBuffer.address());
  380. // mNameBuffer
  381. stream.read(&vectorSize);
  382. mNameBuffer.setSize(vectorSize);
  383. stream.read(mNameBuffer.size(), mNameBuffer.address());
  384. // mSubObjects
  385. stream.read(&vectorSize);
  386. mSubObjects.setSize(vectorSize);
  387. for (i = 0; i < mSubObjects.size(); i++)
  388. {
  389. InteriorSubObject* iso = InteriorSubObject::readISO(stream);
  390. AssertFatal(iso != NULL, "Error, bad sub object in stream!");
  391. mSubObjects[i] = iso;
  392. }
  393. // Convex hulls
  394. stream.read(&vectorSize);
  395. mConvexHulls.setSize(vectorSize);
  396. for(i = 0; i < mConvexHulls.size(); i++)
  397. {
  398. stream.read(&mConvexHulls[i].hullStart);
  399. stream.read(&mConvexHulls[i].hullCount);
  400. stream.read(&mConvexHulls[i].minX);
  401. stream.read(&mConvexHulls[i].maxX);
  402. stream.read(&mConvexHulls[i].minY);
  403. stream.read(&mConvexHulls[i].maxY);
  404. stream.read(&mConvexHulls[i].minZ);
  405. stream.read(&mConvexHulls[i].maxZ);
  406. stream.read(&mConvexHulls[i].surfaceStart);
  407. stream.read(&mConvexHulls[i].surfaceCount);
  408. stream.read(&mConvexHulls[i].planeStart);
  409. stream.read(&mConvexHulls[i].polyListPlaneStart);
  410. stream.read(&mConvexHulls[i].polyListPointStart);
  411. stream.read(&mConvexHulls[i].polyListStringStart);
  412. if (fileVersion >= 12)
  413. stream.read(&mConvexHulls[i].staticMesh);
  414. else
  415. mConvexHulls[i].staticMesh = false;
  416. }
  417. // Convex hull emit strings
  418. stream.read(&vectorSize);
  419. mConvexHullEmitStrings.setSize(vectorSize);
  420. stream.read(mConvexHullEmitStrings.size(), mConvexHullEmitStrings.address());
  421. // Hull indices
  422. stream.read(&vectorSize);
  423. mHullIndices.setSize(vectorSize);
  424. for(i = 0; i < mHullIndices.size(); i++)
  425. stream.read(&mHullIndices[i]);
  426. // Hull plane indices
  427. stream.read(&vectorSize);
  428. mHullPlaneIndices.setSize(vectorSize);
  429. for(i = 0; i < mHullPlaneIndices.size(); i++)
  430. stream.read(&mHullPlaneIndices[i]);
  431. // Hull emit string indices
  432. stream.read(&vectorSize);
  433. mHullEmitStringIndices.setSize(vectorSize);
  434. for(i = 0; i < mHullEmitStringIndices.size(); i++)
  435. stream.read(&mHullEmitStringIndices[i]);
  436. // Hull surface indices
  437. stream.read(&vectorSize);
  438. mHullSurfaceIndices.setSize(vectorSize);
  439. for(i = 0; i < mHullSurfaceIndices.size(); i++)
  440. stream.read(&mHullSurfaceIndices[i]);
  441. // PolyList planes
  442. stream.read(&vectorSize);
  443. mPolyListPlanes.setSize(vectorSize);
  444. for(i = 0; i < mPolyListPlanes.size(); i++)
  445. stream.read(&mPolyListPlanes[i]);
  446. // PolyList points
  447. stream.read(&vectorSize);
  448. mPolyListPoints.setSize(vectorSize);
  449. for(i = 0; i < mPolyListPoints.size(); i++)
  450. stream.read(&mPolyListPoints[i]);
  451. // PolyList strings
  452. stream.read(&vectorSize);
  453. mPolyListStrings.setSize(vectorSize);
  454. for(i = 0; i < mPolyListStrings.size(); i++)
  455. stream.read(&mPolyListStrings[i]);
  456. // Coord bins
  457. for(i = 0; i < NumCoordBins * NumCoordBins; i++)
  458. {
  459. stream.read(&mCoordBins[i].binStart);
  460. stream.read(&mCoordBins[i].binCount);
  461. }
  462. // Coord bin indices
  463. stream.read(&vectorSize);
  464. mCoordBinIndices.setSize(vectorSize);
  465. for(i = 0; i < mCoordBinIndices.size(); i++)
  466. stream.read(&mCoordBinIndices[i]);
  467. // Coord bin mode
  468. stream.read(&mCoordBinMode);
  469. // Ambient colors
  470. stream.read(&mBaseAmbient);
  471. stream.read(&mAlarmAmbient);
  472. if (fileVersion >= 10)
  473. {
  474. // Static meshes
  475. stream.read(&vectorSize);
  476. mStaticMeshes.setSize(vectorSize);
  477. for (i = 0; i < mStaticMeshes.size(); i++)
  478. {
  479. mStaticMeshes[i] = new InteriorSimpleMesh;
  480. mStaticMeshes[i]->read(stream);
  481. }
  482. }
  483. if (fileVersion >= 11)
  484. {
  485. // Normals
  486. stream.read(&vectorSize);
  487. mNormals.setSize(vectorSize);
  488. for (i = 0; i < mNormals.size(); i++)
  489. mathRead(stream, &mNormals[i]);
  490. // TexMatrices
  491. stream.read(&vectorSize);
  492. mTexMatrices.setSize(vectorSize);
  493. for (i = 0; i < mTexMatrices.size(); i++)
  494. {
  495. stream.read(&mTexMatrices[i].T);
  496. stream.read(&mTexMatrices[i].N);
  497. stream.read(&mTexMatrices[i].B);
  498. }
  499. // TexMatIndices
  500. stream.read(&vectorSize);
  501. mTexMatIndices.setSize(vectorSize);
  502. for (i = 0; i < mTexMatIndices.size(); i++)
  503. stream.read(&mTexMatIndices[i]);
  504. }
  505. // For future expandability
  506. U32 dummy;
  507. if (fileVersion < 10)
  508. {
  509. stream.read(&dummy); if (dummy != 0) return false;
  510. }
  511. if (fileVersion < 11)
  512. {
  513. stream.read(&dummy); if (dummy != 0) return false;
  514. stream.read(&dummy); if (dummy != 0) return false;
  515. }
  516. //
  517. // Support for interior light map border sizes.
  518. //
  519. U32 extendedlightmapdata;
  520. stream.read(&extendedlightmapdata);
  521. if(extendedlightmapdata == 1)
  522. {
  523. stream.read(&mLightMapBorderSize);
  524. //future expansion under current block (avoid using too
  525. //many of the above expansion slots by allowing nested
  526. //blocks)...
  527. stream.read(&dummy); if (dummy != 0) return false;
  528. }
  529. // Setup the zone planes
  530. setupZonePlanes();
  531. truncateZoneTree();
  532. buildSurfaceZones();
  533. return (stream.getStatus() == Stream::Ok);
  534. }
  535. bool Interior::write(Stream& stream) const
  536. {
  537. AssertFatal(stream.hasCapability(Stream::StreamWrite), "Interior::write: non-write capable stream passed");
  538. AssertFatal(stream.getStatus() == Stream::Ok, "Interior::write: Error, stream in inconsistent state");
  539. U32 i;
  540. // Version this stream
  541. stream.write(smFileVersion);
  542. stream.write(mDetailLevel);
  543. stream.write(mMinPixels);
  544. mathWrite(stream, mBoundingBox);
  545. mathWrite(stream, mBoundingSphere);
  546. stream.write(mHasAlarmState);
  547. stream.write(mNumLightStateEntries);
  548. // Now write out our data vectors. Remember, for cross-platform capability, no
  549. // structure writing is allowed...
  550. // mPlanes
  551. writePlaneVector(stream);
  552. // mPoints
  553. stream.write(mPoints.size());
  554. for (i = 0; i < mPoints.size(); i++)
  555. mathWrite(stream, mPoints[i].point);
  556. // mPointVisibility
  557. stream.write(mPointVisibility.size());
  558. stream.write(mPointVisibility.size(), mPointVisibility.address());
  559. // mTexGenEQs
  560. stream.write(mTexGenEQs.size());
  561. for (i = 0; i < mTexGenEQs.size(); i++)
  562. {
  563. mathWrite(stream, mTexGenEQs[i].planeX);
  564. mathWrite(stream, mTexGenEQs[i].planeY);
  565. }
  566. // mBSPNodes;
  567. stream.write(mBSPNodes.size());
  568. for (i = 0; i < mBSPNodes.size(); i++)
  569. {
  570. stream.write(mBSPNodes[i].planeIndex);
  571. if (smFileVersion < 14)
  572. {
  573. stream.write(U16(mBSPNodes[i].frontIndex));
  574. stream.write(U16(mBSPNodes[i].backIndex));
  575. }
  576. else
  577. {
  578. stream.write(mBSPNodes[i].frontIndex);
  579. stream.write(mBSPNodes[i].backIndex);
  580. }
  581. }
  582. // mBSPSolidLeaves
  583. stream.write(mBSPSolidLeaves.size());
  584. for (i = 0; i < mBSPSolidLeaves.size(); i++)
  585. {
  586. stream.write(mBSPSolidLeaves[i].surfaceIndex);
  587. stream.write(mBSPSolidLeaves[i].surfaceCount);
  588. }
  589. // MaterialList
  590. mMaterialList->write(stream);
  591. // mWindings
  592. stream.write(mWindings.size());
  593. for (i = 0; i < mWindings.size(); i++)
  594. {
  595. stream.write(mWindings[i]);
  596. }
  597. // mWindingIndices
  598. stream.write(mWindingIndices.size());
  599. for (i = 0; i < mWindingIndices.size(); i++)
  600. {
  601. stream.write(mWindingIndices[i].windingStart);
  602. stream.write(mWindingIndices[i].windingCount);
  603. }
  604. // mEdges
  605. if (smFileVersion >= 12)
  606. {
  607. stream.write(mEdges.size());
  608. for (i = 0; i < mEdges.size(); i++)
  609. {
  610. stream.write(mEdges[i].vertexes[0]);
  611. stream.write(mEdges[i].vertexes[1]);
  612. stream.write(mEdges[i].faces[0]);
  613. stream.write(mEdges[i].faces[1]);
  614. }
  615. }
  616. // mZones
  617. stream.write(mZones.size());
  618. for (i = 0; i < mZones.size(); i++)
  619. {
  620. stream.write(mZones[i].portalStart);
  621. stream.write(mZones[i].portalCount);
  622. stream.write(mZones[i].surfaceStart);
  623. stream.write(mZones[i].surfaceCount);
  624. if (smFileVersion >= 12)
  625. {
  626. stream.write(mZones[i].staticMeshStart);
  627. stream.write(mZones[i].staticMeshCount);
  628. }
  629. stream.write(mZones[i].flags);
  630. }
  631. // Zone surfaces
  632. stream.write(mZoneSurfaces.size());
  633. for (i = 0; i < mZoneSurfaces.size(); i++)
  634. stream.write(mZoneSurfaces[i]);
  635. // Zone static meshes
  636. if (smFileVersion >= 12)
  637. {
  638. stream.write(mZoneStaticMeshes.size());
  639. for (i = 0; i < mZoneStaticMeshes.size(); i++)
  640. stream.write(mZoneStaticMeshes[i]);
  641. }
  642. // mZonePortalList;
  643. stream.write(mZonePortalList.size());
  644. for (i = 0; i < mZonePortalList.size(); i++)
  645. stream.write(mZonePortalList[i]);
  646. // mPortals
  647. stream.write(mPortals.size());
  648. for (i = 0; i < mPortals.size(); i++)
  649. {
  650. stream.write(mPortals[i].planeIndex);
  651. stream.write(mPortals[i].triFanCount);
  652. stream.write(mPortals[i].triFanStart);
  653. stream.write(mPortals[i].zoneFront);
  654. stream.write(mPortals[i].zoneBack);
  655. }
  656. // mSurfaces
  657. stream.write(mSurfaces.size());
  658. for (i = 0; i < mSurfaces.size(); i++)
  659. {
  660. stream.write(mSurfaces[i].windingStart);
  661. if (smFileVersion >= 13)
  662. stream.write(mSurfaces[i].windingCount);
  663. else
  664. {
  665. U8 count = (U8)mSurfaces[i].windingCount;
  666. stream.write(count);
  667. }
  668. stream.write(mSurfaces[i].planeIndex);
  669. stream.write(mSurfaces[i].textureIndex);
  670. stream.write(mSurfaces[i].texGenIndex);
  671. stream.write(mSurfaces[i].surfaceFlags);
  672. stream.write(mSurfaces[i].fanMask);
  673. writeLMapTexGen(stream, mLMTexGenEQs[i].planeX, mLMTexGenEQs[i].planeY);
  674. stream.write(mSurfaces[i].lightCount);
  675. stream.write(mSurfaces[i].lightStateInfoStart);
  676. if (smFileVersion >= 13)
  677. {
  678. stream.write(mSurfaces[i].mapOffsetX);
  679. stream.write(mSurfaces[i].mapOffsetY);
  680. stream.write(mSurfaces[i].mapSizeX);
  681. stream.write(mSurfaces[i].mapSizeY);
  682. }
  683. else
  684. {
  685. U8 offX, offY, sizeX, sizeY;
  686. offX = (U8)mSurfaces[i].mapOffsetX;
  687. offY = (U8)mSurfaces[i].mapOffsetY;
  688. sizeX = (U8)mSurfaces[i].mapSizeX;
  689. sizeY = (U8)mSurfaces[i].mapSizeY;
  690. stream.write(offX);
  691. stream.write(offY);
  692. stream.write(sizeX);
  693. stream.write(sizeY);
  694. }
  695. if (smFileVersion == 0 || smFileVersion >= 12)
  696. stream.write(mSurfaces[i].unused);
  697. }
  698. // NormalLMapIndices
  699. stream.write(mNormalLMapIndices.size());
  700. for (U32 i = 0; i < mNormalLMapIndices.size(); i++)
  701. {
  702. if (smFileVersion >= 13)
  703. stream.write(mNormalLMapIndices[i]);
  704. else
  705. {
  706. U8 index = (U8)mNormalLMapIndices[i];
  707. stream.write(index);
  708. }
  709. }
  710. // AlarmLMapIndices
  711. stream.write(mAlarmLMapIndices.size());
  712. for (U32 i = 0; i < mAlarmLMapIndices.size(); i++)
  713. {
  714. if (smFileVersion >= 13)
  715. stream.write(mAlarmLMapIndices[i]);
  716. else
  717. {
  718. U8 index = (U8)mAlarmLMapIndices[i];
  719. stream.write(index);
  720. }
  721. }
  722. // mNullSurfaces
  723. stream.write(mNullSurfaces.size());
  724. for(i = 0; i < mNullSurfaces.size(); i++)
  725. {
  726. stream.write(mNullSurfaces[i].windingStart);
  727. stream.write(mNullSurfaces[i].planeIndex);
  728. stream.write(mNullSurfaces[i].surfaceFlags);
  729. if (smFileVersion >= 13)
  730. stream.write(mNullSurfaces[i].windingCount);
  731. else
  732. {
  733. U8 count = (U8)mNullSurfaces[i].windingCount;
  734. stream.write(count);
  735. }
  736. }
  737. // mLightmaps
  738. stream.write(mLightmaps.size());
  739. for(i = 0; i < mLightmaps.size(); i++)
  740. {
  741. mLightmaps[i]->writeBitmap("png",stream);
  742. if (smFileVersion == 0 || smFileVersion >= 12)
  743. {
  744. // The "light normal maps" or "light direction maps" were
  745. // removed from Torque 3D... this just writes a dummy 2x2
  746. // texture so that the read/write functions don't change.
  747. GBitmap dummyBmp( 2, 2 );
  748. dummyBmp.writeBitmap("png",stream);
  749. }
  750. stream.write(mLightmapKeep[i]);
  751. }
  752. // mSolidLeafSurfaces
  753. stream.write(mSolidLeafSurfaces.size());
  754. for(i = 0; i < mSolidLeafSurfaces.size(); i++)
  755. {
  756. stream.write(mSolidLeafSurfaces[i]);
  757. }
  758. // Animated lights
  759. stream.write(mAnimatedLights.size());
  760. for(i = 0; i < mAnimatedLights.size(); i++)
  761. {
  762. stream.write(mAnimatedLights[i].nameIndex);
  763. stream.write(mAnimatedLights[i].stateIndex);
  764. stream.write(mAnimatedLights[i].stateCount);
  765. stream.write(mAnimatedLights[i].flags);
  766. stream.write(mAnimatedLights[i].duration);
  767. }
  768. stream.write(mLightStates.size());
  769. for(i = 0; i < mLightStates.size(); i++)
  770. {
  771. stream.write(mLightStates[i].red);
  772. stream.write(mLightStates[i].green);
  773. stream.write(mLightStates[i].blue);
  774. stream.write(mLightStates[i].activeTime);
  775. stream.write(mLightStates[i].dataIndex);
  776. stream.write(mLightStates[i].dataCount);
  777. }
  778. // mStateData
  779. stream.write(mStateData.size());
  780. for(i = 0; i < mStateData.size(); i++)
  781. {
  782. stream.write(mStateData[i].surfaceIndex);
  783. stream.write(mStateData[i].mapIndex);
  784. stream.write(mStateData[i].lightStateIndex);
  785. }
  786. // mStateDataBuffer: Note: superfluous 0 is for flags in future versions.
  787. // that may add compression. This way, we can maintain
  788. // compatability with previous versions.
  789. stream.write(mStateDataBuffer.size());
  790. stream.write(U32(0));
  791. stream.write(mStateDataBuffer.size(), mStateDataBuffer.address());
  792. // mNameBuffer
  793. stream.write(mNameBuffer.size());
  794. stream.write(mNameBuffer.size(), mNameBuffer.address());
  795. // mSubObjects
  796. stream.write(mSubObjects.size());
  797. for (i = 0; i < mSubObjects.size(); i++)
  798. {
  799. bool writeSuccess = mSubObjects[i]->writeISO(stream);
  800. AssertFatal(writeSuccess == true, "Error writing sub object to stream!");
  801. }
  802. // Convex hulls
  803. stream.write(mConvexHulls.size());
  804. for(i = 0; i < mConvexHulls.size(); i++)
  805. {
  806. stream.write(mConvexHulls[i].hullStart);
  807. stream.write(mConvexHulls[i].hullCount);
  808. stream.write(mConvexHulls[i].minX);
  809. stream.write(mConvexHulls[i].maxX);
  810. stream.write(mConvexHulls[i].minY);
  811. stream.write(mConvexHulls[i].maxY);
  812. stream.write(mConvexHulls[i].minZ);
  813. stream.write(mConvexHulls[i].maxZ);
  814. stream.write(mConvexHulls[i].surfaceStart);
  815. stream.write(mConvexHulls[i].surfaceCount);
  816. stream.write(mConvexHulls[i].planeStart);
  817. stream.write(mConvexHulls[i].polyListPlaneStart);
  818. stream.write(mConvexHulls[i].polyListPointStart);
  819. stream.write(mConvexHulls[i].polyListStringStart);
  820. if (smFileVersion >= 12)
  821. stream.write(mConvexHulls[i].staticMesh);
  822. }
  823. stream.write(mConvexHullEmitStrings.size());
  824. stream.write(mConvexHullEmitStrings.size(), mConvexHullEmitStrings.address());
  825. stream.write(mHullIndices.size());
  826. for(i = 0; i < mHullIndices.size(); i++)
  827. stream.write(mHullIndices[i]);
  828. stream.write(mHullPlaneIndices.size());
  829. for(i = 0; i < mHullPlaneIndices.size(); i++)
  830. stream.write(mHullPlaneIndices[i]);
  831. stream.write(mHullEmitStringIndices.size());
  832. for(i = 0; i < mHullEmitStringIndices.size(); i++)
  833. stream.write(mHullEmitStringIndices[i]);
  834. stream.write(mHullSurfaceIndices.size());
  835. for(i = 0; i < mHullSurfaceIndices.size(); i++)
  836. stream.write(mHullSurfaceIndices[i]);
  837. stream.write(mPolyListPlanes.size());
  838. for(i = 0; i < mPolyListPlanes.size(); i++)
  839. stream.write(mPolyListPlanes[i]);
  840. stream.write(mPolyListPoints.size());
  841. for(i = 0; i < mPolyListPoints.size(); i++)
  842. stream.write(mPolyListPoints[i]);
  843. stream.write(mPolyListStrings.size());
  844. for(i = 0; i < mPolyListStrings.size(); i++)
  845. stream.write(mPolyListStrings[i]);
  846. // Coord bins
  847. for(i = 0; i < NumCoordBins * NumCoordBins; i++)
  848. {
  849. stream.write(mCoordBins[i].binStart);
  850. stream.write(mCoordBins[i].binCount);
  851. }
  852. stream.write(mCoordBinIndices.size());
  853. for(i = 0; i < mCoordBinIndices.size(); i++)
  854. stream.write(mCoordBinIndices[i]);
  855. stream.write(mCoordBinMode);
  856. // Ambient colors...
  857. stream.write(mBaseAmbient);
  858. stream.write(mAlarmAmbient);
  859. if (smFileVersion >= 10)
  860. {
  861. // Static meshes
  862. stream.write(mStaticMeshes.size());
  863. for (i = 0; i < mStaticMeshes.size(); i++)
  864. mStaticMeshes[i]->write(stream);
  865. }
  866. else
  867. stream.write(U32(0));
  868. if (smFileVersion >= 11)
  869. {
  870. // Normals
  871. stream.write(mNormals.size());
  872. for (i = 0; i < mNormals.size(); i++)
  873. mathWrite(stream, mNormals[i]);
  874. // TexMatrices
  875. stream.write(mTexMatrices.size());
  876. for (i = 0; i < mTexMatrices.size(); i++)
  877. {
  878. stream.write(mTexMatrices[i].T);
  879. stream.write(mTexMatrices[i].N);
  880. stream.write(mTexMatrices[i].B);
  881. }
  882. // TexMatIndices
  883. stream.write(mTexMatIndices.size());
  884. for (i = 0; i < mTexMatIndices.size(); i++)
  885. stream.write(mTexMatIndices[i]);
  886. }
  887. else
  888. {
  889. stream.write(U32(0));
  890. stream.write(U32(0));
  891. }
  892. //
  893. // Support for interior light map border sizes.
  894. //
  895. if(mLightMapBorderSize > 0)
  896. {
  897. stream.write(U32(1));//flag new block...
  898. stream.write(U32(mLightMapBorderSize));//new block data..
  899. //future expansion under current block (avoid using too
  900. //many of the above expansion slots by allowing nested
  901. //blocks)...
  902. stream.write(U32(0));
  903. }
  904. else
  905. {
  906. stream.write(U32(0));
  907. }
  908. return stream.getStatus() == Stream::Ok;
  909. }
  910. bool Interior::readVehicleCollision(Stream& stream)
  911. {
  912. AssertFatal(stream.hasCapability(Stream::StreamRead), "Interior::read: non-read capable stream passed");
  913. AssertFatal(stream.getStatus() == Stream::Ok, "Interior::read: Error, stream in inconsistent state");
  914. S32 i;
  915. // Version this stream. We only load stream of the current version
  916. U32 fileVersion;
  917. stream.read(&fileVersion);
  918. if (fileVersion > smFileVersion)
  919. {
  920. Con::errorf(ConsoleLogEntry::General, "Interior::read: incompatible file version found.");
  921. return false;
  922. }
  923. U32 vectorSize;
  924. // Convex hulls
  925. stream.read(&vectorSize);
  926. mVehicleConvexHulls.setSize(vectorSize);
  927. for(i = 0; i < mVehicleConvexHulls.size(); i++)
  928. {
  929. stream.read(&mVehicleConvexHulls[i].hullStart);
  930. stream.read(&mVehicleConvexHulls[i].hullCount);
  931. stream.read(&mVehicleConvexHulls[i].minX);
  932. stream.read(&mVehicleConvexHulls[i].maxX);
  933. stream.read(&mVehicleConvexHulls[i].minY);
  934. stream.read(&mVehicleConvexHulls[i].maxY);
  935. stream.read(&mVehicleConvexHulls[i].minZ);
  936. stream.read(&mVehicleConvexHulls[i].maxZ);
  937. stream.read(&mVehicleConvexHulls[i].surfaceStart);
  938. stream.read(&mVehicleConvexHulls[i].surfaceCount);
  939. stream.read(&mVehicleConvexHulls[i].planeStart);
  940. stream.read(&mVehicleConvexHulls[i].polyListPlaneStart);
  941. stream.read(&mVehicleConvexHulls[i].polyListPointStart);
  942. stream.read(&mVehicleConvexHulls[i].polyListStringStart);
  943. }
  944. stream.read(&vectorSize);
  945. mVehicleConvexHullEmitStrings.setSize(vectorSize);
  946. stream.read(mVehicleConvexHullEmitStrings.size(), mVehicleConvexHullEmitStrings.address());
  947. stream.read(&vectorSize);
  948. mVehicleHullIndices.setSize(vectorSize);
  949. for(i = 0; i < mVehicleHullIndices.size(); i++)
  950. stream.read(&mVehicleHullIndices[i]);
  951. stream.read(&vectorSize);
  952. mVehicleHullPlaneIndices.setSize(vectorSize);
  953. for(i = 0; i < mVehicleHullPlaneIndices.size(); i++)
  954. stream.read(&mVehicleHullPlaneIndices[i]);
  955. stream.read(&vectorSize);
  956. mVehicleHullEmitStringIndices.setSize(vectorSize);
  957. for(i = 0; i < mVehicleHullEmitStringIndices.size(); i++)
  958. stream.read(&mVehicleHullEmitStringIndices[i]);
  959. stream.read(&vectorSize);
  960. mVehicleHullSurfaceIndices.setSize(vectorSize);
  961. for(i = 0; i < mVehicleHullSurfaceIndices.size(); i++)
  962. stream.read(&mVehicleHullSurfaceIndices[i]);
  963. stream.read(&vectorSize);
  964. mVehiclePolyListPlanes.setSize(vectorSize);
  965. for(i = 0; i < mVehiclePolyListPlanes.size(); i++)
  966. stream.read(&mVehiclePolyListPlanes[i]);
  967. stream.read(&vectorSize);
  968. mVehiclePolyListPoints.setSize(vectorSize);
  969. for(i = 0; i < mVehiclePolyListPoints.size(); i++)
  970. stream.read(&mVehiclePolyListPoints[i]);
  971. stream.read(&vectorSize);
  972. mVehiclePolyListStrings.setSize(vectorSize);
  973. for(i = 0; i < mVehiclePolyListStrings.size(); i++)
  974. stream.read(&mVehiclePolyListStrings[i]);
  975. stream.read(&vectorSize);
  976. mVehicleNullSurfaces.setSize(vectorSize);
  977. for(i = 0; i < mVehicleNullSurfaces.size(); i++)
  978. {
  979. stream.read(&mVehicleNullSurfaces[i].windingStart);
  980. stream.read(&mVehicleNullSurfaces[i].planeIndex);
  981. stream.read(&mVehicleNullSurfaces[i].surfaceFlags);
  982. stream.read(&mVehicleNullSurfaces[i].windingCount);
  983. }
  984. stream.read(&vectorSize);
  985. mVehiclePoints.setSize(vectorSize);
  986. for(i = 0; i < mVehiclePoints.size(); i++)
  987. mathRead(stream, &mVehiclePoints[i].point);
  988. stream.read(&vectorSize);
  989. mVehiclePlanes.setSize(vectorSize);
  990. for(i = 0; i < mVehiclePlanes.size(); i++)
  991. mathRead(stream, &mVehiclePlanes[i]);
  992. stream.read(&vectorSize);
  993. mVehicleWindings.setSize(vectorSize);
  994. for(i = 0; i < mVehicleWindings.size(); i++)
  995. {
  996. stream.read(&mVehicleWindings[i]);
  997. }
  998. stream.read(&vectorSize);
  999. mVehicleWindingIndices.setSize(vectorSize);
  1000. for(i = 0; i < mVehicleWindingIndices.size(); i++)
  1001. {
  1002. stream.read(&mVehicleWindingIndices[i].windingStart);
  1003. stream.read(&mVehicleWindingIndices[i].windingCount);
  1004. }
  1005. return true;
  1006. }
  1007. bool Interior::writeVehicleCollision(Stream& stream) const
  1008. {
  1009. AssertFatal(stream.hasCapability(Stream::StreamWrite), "Interior::write: non-write capable stream passed");
  1010. AssertFatal(stream.getStatus() == Stream::Ok, "Interior::write: Error, stream in inconsistent state");
  1011. U32 i;
  1012. // Version this stream
  1013. stream.write(smFileVersion);
  1014. // Convex hulls
  1015. stream.write(mVehicleConvexHulls.size());
  1016. for(i = 0; i < mVehicleConvexHulls.size(); i++)
  1017. {
  1018. stream.write(mVehicleConvexHulls[i].hullStart);
  1019. stream.write(mVehicleConvexHulls[i].hullCount);
  1020. stream.write(mVehicleConvexHulls[i].minX);
  1021. stream.write(mVehicleConvexHulls[i].maxX);
  1022. stream.write(mVehicleConvexHulls[i].minY);
  1023. stream.write(mVehicleConvexHulls[i].maxY);
  1024. stream.write(mVehicleConvexHulls[i].minZ);
  1025. stream.write(mVehicleConvexHulls[i].maxZ);
  1026. stream.write(mVehicleConvexHulls[i].surfaceStart);
  1027. stream.write(mVehicleConvexHulls[i].surfaceCount);
  1028. stream.write(mVehicleConvexHulls[i].planeStart);
  1029. stream.write(mVehicleConvexHulls[i].polyListPlaneStart);
  1030. stream.write(mVehicleConvexHulls[i].polyListPointStart);
  1031. stream.write(mVehicleConvexHulls[i].polyListStringStart);
  1032. }
  1033. stream.write(mVehicleConvexHullEmitStrings.size());
  1034. stream.write(mVehicleConvexHullEmitStrings.size(), mVehicleConvexHullEmitStrings.address());
  1035. stream.write(mVehicleHullIndices.size());
  1036. for(i = 0; i < mVehicleHullIndices.size(); i++)
  1037. stream.write(mVehicleHullIndices[i]);
  1038. stream.write(mVehicleHullPlaneIndices.size());
  1039. for(i = 0; i < mVehicleHullPlaneIndices.size(); i++)
  1040. stream.write(mVehicleHullPlaneIndices[i]);
  1041. stream.write(mVehicleHullEmitStringIndices.size());
  1042. for(i = 0; i < mVehicleHullEmitStringIndices.size(); i++)
  1043. stream.write(mVehicleHullEmitStringIndices[i]);
  1044. stream.write(mVehicleHullSurfaceIndices.size());
  1045. for(i = 0; i < mVehicleHullSurfaceIndices.size(); i++)
  1046. stream.write(mVehicleHullSurfaceIndices[i]);
  1047. stream.write(mVehiclePolyListPlanes.size());
  1048. for(i = 0; i < mVehiclePolyListPlanes.size(); i++)
  1049. stream.write(mVehiclePolyListPlanes[i]);
  1050. stream.write(mVehiclePolyListPoints.size());
  1051. for(i = 0; i < mVehiclePolyListPoints.size(); i++)
  1052. stream.write(mVehiclePolyListPoints[i]);
  1053. stream.write(mVehiclePolyListStrings.size());
  1054. for(i = 0; i < mVehiclePolyListStrings.size(); i++)
  1055. stream.write(mVehiclePolyListStrings[i]);
  1056. stream.write(mVehicleNullSurfaces.size());
  1057. for(i = 0; i < mVehicleNullSurfaces.size(); i++)
  1058. {
  1059. stream.write(mVehicleNullSurfaces[i].windingStart);
  1060. stream.write(mVehicleNullSurfaces[i].planeIndex);
  1061. stream.write(mVehicleNullSurfaces[i].surfaceFlags);
  1062. stream.write(mVehicleNullSurfaces[i].windingCount);
  1063. }
  1064. stream.write(mVehiclePoints.size());
  1065. for(i = 0; i < mVehiclePoints.size(); i++)
  1066. mathWrite(stream, mVehiclePoints[i].point);
  1067. stream.write(mVehiclePlanes.size());
  1068. for(i = 0; i < mVehiclePlanes.size(); i++)
  1069. mathWrite(stream, mVehiclePlanes[i]);
  1070. stream.write(mVehicleWindings.size());
  1071. for(i = 0; i < mVehicleWindings.size(); i++)
  1072. stream.write(mVehicleWindings[i]);
  1073. stream.write(mVehicleWindingIndices.size());
  1074. for(i = 0; i < mVehicleWindingIndices.size(); i++)
  1075. {
  1076. stream.write(mVehicleWindingIndices[i].windingStart);
  1077. stream.write(mVehicleWindingIndices[i].windingCount);
  1078. }
  1079. return true;
  1080. }
  1081. bool Interior::readSurface(Stream& stream, Surface& surface, TexGenPlanes& texgens, const bool tgeInterior)
  1082. {
  1083. // If we end up reading any invalid data then odds are that we
  1084. // are no longer correctly reading from the stream and have gotten
  1085. // off because this is a TGE version 0 Interior so we bail.
  1086. // That is why you will see checks all the way through
  1087. stream.read(&surface.windingStart);
  1088. if (surface.windingStart >= mWindings.size())
  1089. return false;
  1090. if (mFileVersion >= 13)
  1091. stream.read(&surface.windingCount);
  1092. else
  1093. {
  1094. U8 count;
  1095. stream.read(&count);
  1096. surface.windingCount = (U32)count;
  1097. }
  1098. if (surface.windingStart + surface.windingCount > mWindings.size())
  1099. return false;
  1100. stream.read(&surface.planeIndex);
  1101. if (U32(surface.planeIndex & ~0x8000) >= mPlanes.size())
  1102. return false;
  1103. stream.read(&surface.textureIndex);
  1104. if (surface.textureIndex >= mMaterialList->size())
  1105. return false;
  1106. stream.read(&surface.texGenIndex);
  1107. if (surface.texGenIndex >= mTexGenEQs.size())
  1108. return false;
  1109. stream.read(&surface.surfaceFlags);
  1110. stream.read(&surface.fanMask);
  1111. // If reading the lightmap texgen fails then most likely this is a
  1112. // TGE version 0 Interior (it gets offset by the "unused" read below
  1113. if (readLMapTexGen(stream, texgens.planeX, texgens.planeY) == false)
  1114. return false;
  1115. stream.read(&surface.lightCount);
  1116. stream.read(&surface.lightStateInfoStart);
  1117. if (mFileVersion >= 13)
  1118. {
  1119. stream.read(&surface.mapOffsetX);
  1120. stream.read(&surface.mapOffsetY);
  1121. stream.read(&surface.mapSizeX);
  1122. stream.read(&surface.mapSizeY);
  1123. }
  1124. else
  1125. {
  1126. U8 offX, offY, sizeX, sizeY;
  1127. stream.read(&offX);
  1128. stream.read(&offY);
  1129. stream.read(&sizeX);
  1130. stream.read(&sizeY);
  1131. surface.mapOffsetX = (U32)offX;
  1132. surface.mapOffsetY = (U32)offY;
  1133. surface.mapSizeX = (U32)sizeX;
  1134. surface.mapSizeY = (U32)sizeY;
  1135. }
  1136. if (!tgeInterior && (mFileVersion == 0 || mFileVersion == 5 || mFileVersion >= 12))
  1137. stream.read(&surface.unused);
  1138. if (mFileVersion == 5)
  1139. {
  1140. U32 brushId;
  1141. stream.read(&brushId);
  1142. }
  1143. return true;
  1144. }
  1145. bool Interior::readLMapTexGen(Stream& stream, PlaneF& planeX, PlaneF& planeY)
  1146. {
  1147. F32 genX[4];
  1148. F32 genY[4];
  1149. for(U32 i = 0; i < 4; i++)
  1150. {
  1151. genX[i] = 0.0f;
  1152. genY[i] = 0.0f;
  1153. }
  1154. U16 finalWord;
  1155. stream.read(&finalWord);
  1156. stream.read(&genX[3]);
  1157. stream.read(&genY[3]);
  1158. // Unpack the final word.
  1159. U32 logScaleY = (finalWord >> 0) & ((1 << 6) - 1);
  1160. U32 logScaleX = (finalWord >> 6) & ((1 << 6) - 1);
  1161. U16 stEnc = (finalWord >> 13) & 7;
  1162. S32 sc, tc;
  1163. switch(stEnc)
  1164. {
  1165. case 0: sc = 0; tc = 1; break;
  1166. case 1: sc = 0; tc = 2; break;
  1167. case 2: sc = 1; tc = 0; break;
  1168. case 3: sc = 1; tc = 2; break;
  1169. case 4: sc = 2; tc = 0; break;
  1170. case 5: sc = 2; tc = 1; break;
  1171. default:
  1172. sc = tc = -1;
  1173. // This is potentially an invalid st coord encoding however *most* times
  1174. // this is caused by attempting to load a TGE version 0 Interior
  1175. return false;
  1176. }
  1177. U32 invScaleX = 1 << logScaleX;
  1178. U32 invScaleY = 1 << logScaleY;
  1179. genX[sc] = F32(1.0 / F64(invScaleX));
  1180. genY[tc] = F32(1.0 / F64(invScaleY));
  1181. planeX.x = genX[0];
  1182. planeX.y = genX[1];
  1183. planeX.z = genX[2];
  1184. planeX.d = genX[3];
  1185. planeY.x = genY[0];
  1186. planeY.y = genY[1];
  1187. planeY.z = genY[2];
  1188. planeY.d = genY[3];
  1189. return stream.getStatus() == Stream::Ok;
  1190. }
  1191. bool Interior::writeLMapTexGen(Stream& stream, const PlaneF& planeX, const PlaneF& planeY) const
  1192. {
  1193. F32 genX[4], genY[4];
  1194. genX[0] = planeX.x;
  1195. genX[1] = planeX.y;
  1196. genX[2] = planeX.z;
  1197. genX[3] = planeX.d;
  1198. genY[0] = planeY.x;
  1199. genY[1] = planeY.y;
  1200. genY[2] = planeY.z;
  1201. genY[3] = planeY.d;
  1202. // The tex gen for lmaps is a special case.
  1203. // there are only 4 parameters that matter,
  1204. // an inverse power of 2 in the x and y, and the
  1205. // fp offsets in x and y. We can encode the
  1206. // scales completely in U16 and we'll just write out
  1207. // the offsets. First, determine which coords we're
  1208. // writing...
  1209. //
  1210. S32 sc = -1;
  1211. S32 tc = -1;
  1212. if(genX[0] != 0.0) sc = 0;
  1213. else if(genX[1] != 0.0) sc = 1;
  1214. else if(genX[2] != 0.0) sc = 2;
  1215. if(genY[0] != 0.0) tc = 0;
  1216. else if(genY[1] != 0.0) tc = 1;
  1217. else if(genY[2] != 0.0) tc = 2;
  1218. AssertFatal(sc != -1 && tc != -1 && sc != tc, "Hm, something wrong here.");
  1219. U32 invScaleX = U32((1.0f / genX[sc]) + 0.5);
  1220. U32 invScaleY = U32((1.0f / genY[tc]) + 0.5);
  1221. AssertISV(invScaleX && isPow2(invScaleX) && invScaleY && isPow2(invScaleY), "Not a power of 2? Something wrong");
  1222. U32 logScaleX = getBinLog2(invScaleX);
  1223. U32 logScaleY = getBinLog2(invScaleY);
  1224. AssertFatal(logScaleX < 63 && logScaleY < 63, "Error, you've set the lightmap scale WAAYYY to high!");
  1225. // We need 3 bits to encode sc and tc, which leaves us 6 bits for logScaleX
  1226. // and logScaleY
  1227. S16 stEnc = -1;
  1228. if(sc == 0 && tc == 1) stEnc = 0;
  1229. else if(sc == 0 && tc == 2) stEnc = 1;
  1230. else if(sc == 1 && tc == 0) stEnc = 2;
  1231. else if(sc == 1 && tc == 2) stEnc = 3;
  1232. else if(sc == 2 && tc == 0) stEnc = 4;
  1233. else if(sc == 2 && tc == 1) stEnc = 5;
  1234. AssertFatal(stEnc != -1, avar("Hm. This should never happen. (%d, %d)", sc, tc));
  1235. U16 finalWord = U16(stEnc) << 13;
  1236. finalWord |= logScaleX << 6;
  1237. finalWord |= logScaleY << 0;
  1238. stream.write(finalWord);
  1239. stream.write(genX[3]);
  1240. stream.write(genY[3]);
  1241. return stream.getStatus() == Stream::Ok;
  1242. }
  1243. bool Interior::writePlaneVector(Stream& stream) const
  1244. {
  1245. // This is pretty slow, but who cares?
  1246. //
  1247. Vector<Point3F> uniqueNormals(mPlanes.size());
  1248. Vector<U16> uniqueIndices(mPlanes.size());
  1249. U32 i;
  1250. for(i = 0; i < mPlanes.size(); i++)
  1251. {
  1252. bool inserted = false;
  1253. for(U32 j = 0; j < uniqueNormals.size(); j++)
  1254. {
  1255. if(mPlanes[i] == uniqueNormals[j])
  1256. {
  1257. // Hah! Already have this one...
  1258. uniqueIndices.push_back(j);
  1259. inserted = true;
  1260. break;
  1261. }
  1262. }
  1263. if(inserted == false)
  1264. {
  1265. // Gotta do it ourselves...
  1266. uniqueIndices.push_back(uniqueNormals.size());
  1267. uniqueNormals.push_back(Point3F(mPlanes[i].x, mPlanes[i].y, mPlanes[i].z));
  1268. }
  1269. }
  1270. // Ok, what we have now, is a list of unique normals, a set of indices into
  1271. // that vector, and the distances that we still have to write out by hand.
  1272. // Hop to it!
  1273. stream.write(uniqueNormals.size());
  1274. for(i = 0; i < uniqueNormals.size(); i++)
  1275. mathWrite(stream, uniqueNormals[i]);
  1276. stream.write(mPlanes.size());
  1277. for(i = 0; i < mPlanes.size(); i++)
  1278. {
  1279. stream.write(uniqueIndices[i]);
  1280. stream.write(mPlanes[i].d);
  1281. }
  1282. return(stream.getStatus() == Stream::Ok);
  1283. }
  1284. bool Interior::readPlaneVector(Stream& stream)
  1285. {
  1286. U32 vectorSize;
  1287. stream.read(&vectorSize);
  1288. Point3F* normals = new Point3F[vectorSize];
  1289. U32 i;
  1290. for(i = 0; i < vectorSize; i++)
  1291. mathRead(stream, &normals[i]);
  1292. U16 index;
  1293. stream.read(&vectorSize);
  1294. mPlanes.setSize(vectorSize);
  1295. for(i = 0; i < mPlanes.size(); i++)
  1296. {
  1297. stream.read(&index);
  1298. stream.read(&mPlanes[i].d);
  1299. mPlanes[i].x = normals[index].x;
  1300. mPlanes[i].y = normals[index].y;
  1301. mPlanes[i].z = normals[index].z;
  1302. }
  1303. delete [] normals;
  1304. return(stream.getStatus() == Stream::Ok);
  1305. }
  1306. bool Interior::getUnifiedZone(const U32 index, S32* zone)
  1307. {
  1308. if(isBSPLeafIndex(index))
  1309. {
  1310. if(isBSPSolidLeaf(index))
  1311. *zone = -1;
  1312. else
  1313. *zone = S32(getBSPEmptyLeafZone(index));
  1314. return true;
  1315. }
  1316. else
  1317. {
  1318. S32 frontZone, backZone;
  1319. bool frontUnified = getUnifiedZone(mBSPNodes[index].frontIndex, &frontZone);
  1320. bool backUnified = getUnifiedZone(mBSPNodes[index].backIndex, &backZone);
  1321. if(frontUnified && backUnified)
  1322. {
  1323. if(frontZone == backZone)
  1324. {
  1325. *zone = frontZone;
  1326. return true;
  1327. }
  1328. else
  1329. {
  1330. if(frontZone == -1 || backZone == -1)
  1331. {
  1332. // DMMFIX: Once the interior file format is able to distinguish
  1333. // between structural and detail nodes in the runtime bsp,
  1334. // we can make this work a little better.
  1335. return false;
  1336. }
  1337. else
  1338. {
  1339. // Not equal, and neither is -1, no unified zone possible
  1340. return false;
  1341. }
  1342. }
  1343. }
  1344. else
  1345. {
  1346. return false;
  1347. }
  1348. }
  1349. }
  1350. void Interior::truncateZoneNode(const U32 index)
  1351. {
  1352. S32 unifiedZone;
  1353. bool unified = getUnifiedZone(index, &unifiedZone);
  1354. if(unified)
  1355. {
  1356. // Aha!
  1357. if(isBSPLeafIndex(index))
  1358. return;
  1359. if(unifiedZone == -1)
  1360. mBSPNodes[index].terminalZone = U16(0xFFFF);
  1361. else
  1362. mBSPNodes[index].terminalZone = U16(0x8000) | U16(unifiedZone);
  1363. }
  1364. else
  1365. {
  1366. // Sigh.
  1367. if(isBSPLeafIndex(mBSPNodes[index].frontIndex) == false)
  1368. truncateZoneNode(mBSPNodes[index].frontIndex);
  1369. if(isBSPLeafIndex(mBSPNodes[index].backIndex) == false)
  1370. truncateZoneNode(mBSPNodes[index].backIndex);
  1371. }
  1372. }
  1373. void Interior::truncateZoneTree()
  1374. {
  1375. for(U32 i = 0; i < mBSPNodes.size(); i++)
  1376. {
  1377. mBSPNodes[i].terminalZone = 0;
  1378. }
  1379. if(mBSPNodes.size() > 0)
  1380. truncateZoneNode(0);
  1381. }
  1382. void Interior::setupZonePlanes()
  1383. {
  1384. U16* temp = new U16[mPlanes.size() * mZones.size()];
  1385. U32 tempSize = 0;
  1386. for(U32 i = 0; i < mZones.size(); i++)
  1387. {
  1388. Zone& rZone = mZones[i];
  1389. BitVector usedPlanes;
  1390. usedPlanes.setSize(mPlanes.size());
  1391. usedPlanes.clear();
  1392. U32 j;
  1393. for(j = 0; j < rZone.surfaceCount; j++)
  1394. {
  1395. Surface& rSurface = mSurfaces[mZoneSurfaces[rZone.surfaceStart + j]];
  1396. usedPlanes.set(getPlaneIndex(rSurface.planeIndex));
  1397. }
  1398. rZone.planeStart = tempSize;
  1399. for(j = 0; j < mPlanes.size(); j++)
  1400. {
  1401. if(usedPlanes.test(j))
  1402. {
  1403. AssertFatal(tempSize < mPlanes.size() * mZones.size(), "Error, out of bounds plane list!");
  1404. temp[tempSize++] = j;
  1405. }
  1406. }
  1407. rZone.planeCount = tempSize - rZone.planeStart;
  1408. }
  1409. mZonePlanes.setSize(tempSize);
  1410. for(U32 j = 0; j < tempSize; j++)
  1411. mZonePlanes[j] = temp[j];
  1412. delete [] temp;
  1413. }