blInteriorSystem.cpp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
  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 "lighting/basic/blInteriorSystem.h"
  23. #include "lighting/lightingInterfaces.h"
  24. #include "lighting/common/shadowVolumeBSP.h"
  25. #include "interior/interiorInstance.h"
  26. #include "lighting/common/sceneLightingGlobals.h"
  27. #include "lighting/basic/basicLightManager.h"
  28. #include "gfx/bitmap/gBitmap.h"
  29. //#define SET_COLORS
  30. bool blInteriorSystem::smUseVertexLighting = false;
  31. //------------------------------------------------------------------------------
  32. // Class SceneLighting::PersistInfo::InteriorChunk
  33. //------------------------------------------------------------------------------
  34. struct blInteriorChunk : public PersistInfo::PersistChunk
  35. {
  36. typedef PersistChunk Parent;
  37. blInteriorChunk();
  38. ~blInteriorChunk();
  39. Vector<GBitmap*> sgNormalLightMaps;
  40. Vector<U32> mDetailLightmapCount;
  41. Vector<U32> mDetailLightmapIndices;
  42. Vector<GBitmap*> mLightmaps;
  43. bool mHasAlarmState;
  44. Vector<U32> mDetailVertexCount;
  45. Vector<ColorI> mVertexColorsNormal;
  46. Vector<ColorI> mVertexColorsAlarm;
  47. bool read(Stream &);
  48. bool write(Stream &);
  49. };
  50. blInteriorChunk::blInteriorChunk()
  51. {
  52. mChunkType = PersistChunk::InteriorChunkType;
  53. }
  54. blInteriorChunk::~blInteriorChunk()
  55. {
  56. for(U32 i = 0; i < mLightmaps.size(); i++)
  57. delete mLightmaps[i];
  58. }
  59. //------------------------------------------------------------------------------
  60. // - always read in vertex lighting, lightmaps may not be needed
  61. bool blInteriorChunk::read(Stream & stream)
  62. {
  63. if(!Parent::read(stream))
  64. return(false);
  65. U32 size;
  66. U32 i;
  67. // lightmaps->vertex-info
  68. // BTRTODO: FIX ME
  69. if (true)
  70. //if(!SceneLighting::smUseVertexLighting)
  71. {
  72. // size of this minichunk
  73. if(!stream.read(&size))
  74. return(false);
  75. // lightmaps
  76. stream.read(&size);
  77. mDetailLightmapCount.setSize(size);
  78. for(i = 0; i < size; i++)
  79. if(!stream.read(&mDetailLightmapCount[i]))
  80. return(false);
  81. stream.read(&size);
  82. mDetailLightmapIndices.setSize(size);
  83. for(i = 0; i < size; i++)
  84. if(!stream.read(&mDetailLightmapIndices[i]))
  85. return(false);
  86. if(!stream.read(&size))
  87. return(false);
  88. mLightmaps.setSize(size);
  89. for(i = 0; i < size; i++)
  90. {
  91. mLightmaps[i] = new GBitmap;
  92. if(!mLightmaps[i]->readBitmap("png",stream))
  93. return(false);
  94. }
  95. }
  96. else
  97. {
  98. // step past the lightmaps
  99. if(!stream.read(&size))
  100. return(false);
  101. if(!stream.setPosition(stream.getPosition() + size))
  102. return(false);
  103. }
  104. // size of the vertex lighting: need to reset stream position after zipStream reading
  105. U32 zipStreamEnd;
  106. if(!stream.read(&zipStreamEnd))
  107. return(false);
  108. zipStreamEnd += stream.getPosition();
  109. /*
  110. // vertex lighting
  111. ZipSubRStream zipStream;
  112. if(!zipStream.attachStream(&stream))
  113. return(false);
  114. if(!zipStream.read(&size))
  115. return(false);
  116. mHasAlarmState = bool(size);
  117. if(!zipStream.read(&size))
  118. return(false);
  119. mDetailVertexCount.setSize(size);
  120. for(i = 0; i < size; i++)
  121. if(!zipStream.read(&mDetailVertexCount[i]))
  122. return(false);
  123. size = 0;
  124. for(i = 0; i < mDetailVertexCount.size(); i++)
  125. size += mDetailVertexCount[i];
  126. mVertexColorsNormal.setSize(size);
  127. if(mHasAlarmState)
  128. mVertexColorsAlarm.setSize(size);
  129. U32 curPos = 0;
  130. for(i = 0; i < mDetailVertexCount.size(); i++)
  131. {
  132. U32 count = mDetailVertexCount[i];
  133. for(U32 j = 0; j < count; j++)
  134. if(!zipStream.read(&mVertexColorsNormal[curPos + j]))
  135. return(false);
  136. // read in the alarm info
  137. if(mHasAlarmState)
  138. {
  139. // same?
  140. if(!zipStream.read(&size))
  141. return(false);
  142. if(bool(size))
  143. dMemcpy(&mVertexColorsAlarm[curPos], &mVertexColorsNormal[curPos], count * sizeof(ColorI));
  144. else
  145. {
  146. for(U32 j = 0; j < count; j++)
  147. if(!zipStream.read(&mVertexColorsAlarm[curPos + j]))
  148. return(false);
  149. }
  150. }
  151. curPos += count;
  152. }
  153. zipStream.detachStream();
  154. */
  155. // since there is no resizeFilterStream the zipStream happily reads
  156. // off the end of the compressed block... reset the position
  157. stream.setPosition(zipStreamEnd);
  158. return(true);
  159. }
  160. bool blInteriorChunk::write(Stream & stream)
  161. {
  162. if(!Parent::write(stream))
  163. return(false);
  164. // lightmaps
  165. U32 startPos = stream.getPosition();
  166. if(!stream.write(U32(0)))
  167. return(false);
  168. U32 i;
  169. if(!stream.write(U32(mDetailLightmapCount.size())))
  170. return(false);
  171. for(i = 0; i < mDetailLightmapCount.size(); i++)
  172. if(!stream.write(mDetailLightmapCount[i]))
  173. return(false);
  174. if(!stream.write(U32(mDetailLightmapIndices.size())))
  175. return(false);
  176. for(i = 0; i < mDetailLightmapIndices.size(); i++)
  177. if(!stream.write(mDetailLightmapIndices[i]))
  178. return(false);
  179. if(!stream.write(U32(mLightmaps.size())))
  180. return(false);
  181. for(i = 0; i < mLightmaps.size(); i++)
  182. {
  183. AssertFatal(mLightmaps[i], "SceneLighting::blInteriorChunk::Write: Invalid bitmap!");
  184. if(!mLightmaps[i]->writeBitmap("png",stream))
  185. return(false);
  186. }
  187. // write out the lightmap portions size
  188. U32 endPos = stream.getPosition();
  189. if(!stream.setPosition(startPos))
  190. return(false);
  191. // don't include the offset in the size
  192. if(!stream.write(U32(endPos - startPos - sizeof(U32))))
  193. return(false);
  194. if(!stream.setPosition(endPos))
  195. return(false);
  196. // vertex lighting: needs the size of the vertex info because the
  197. // zip stream may read off the end of the chunk
  198. startPos = stream.getPosition();
  199. if(!stream.write(U32(0)))
  200. return(false);
  201. // write out the vertex lighting portions size
  202. endPos = stream.getPosition();
  203. if(!stream.setPosition(startPos))
  204. return(false);
  205. // don't include the offset in the size
  206. if(!stream.write(U32(endPos - startPos - sizeof(U32))))
  207. return(false);
  208. if(!stream.setPosition(endPos))
  209. return(false);
  210. return(true);
  211. }
  212. //
  213. // InteriorProxy (definition)
  214. //
  215. class blInteriorProxy : public SceneLighting::ObjectProxy
  216. {
  217. private:
  218. typedef ObjectProxy Parent;
  219. bool isShadowedBy(blInteriorProxy *);
  220. ShadowVolumeBSP::SVPoly * buildInteriorPoly(ShadowVolumeBSP * shadowVolumeBSP,
  221. Interior * detail, U32 surfaceIndex, LightInfo * light,
  222. bool createSurfaceInfo);
  223. public:
  224. blInteriorProxy(SceneObject * obj);
  225. ~blInteriorProxy();
  226. InteriorInstance * operator->() {return(static_cast<InteriorInstance*>(static_cast<SceneObject*>(mObj)));}
  227. InteriorInstance * getObject() {return(static_cast<InteriorInstance*>(static_cast<SceneObject*>(mObj)));}
  228. // current light info
  229. ShadowVolumeBSP * mBoxShadowBSP;
  230. Vector<ShadowVolumeBSP::SVPoly*> mLitBoxSurfaces;
  231. Vector<PlaneF> mOppositeBoxPlanes;
  232. Vector<PlaneF> mTerrainTestPlanes;
  233. struct sgSurfaceInfo
  234. {
  235. const Interior::Surface *sgSurface;
  236. U32 sgIndex;
  237. Interior *sgDetail;
  238. bool sgHasAlarm;
  239. };
  240. U32 sgCurrentSurfaceIndex;
  241. U32 sgSurfacesPerPass;
  242. InteriorInstance *sgInterior;
  243. Vector<LightInfo *> sgLights;
  244. Vector<sgSurfaceInfo> sgSurfaces;
  245. void sgAddLight(LightInfo *light, InteriorInstance *interior);
  246. //void sgLightUniversalPoint(LightInfo *light);
  247. void sgProcessSurface(const Interior::Surface &surface, U32 i, Interior *detail, bool hasAlarm);
  248. // lighting interface
  249. bool loadResources();
  250. void init();
  251. //bool tgePreLight(LightInfo* light);
  252. bool preLight(LightInfo *);
  253. void light(LightInfo *);
  254. void postLight(bool lastLight);
  255. //virtual void processLightingStart();
  256. //virtual bool processStartObjectLightingEvent(SceneLighting::ObjectProxy* objproxy, U32 current, U32 max);
  257. //virtual void processTGELightProcessEvent(U32 curr, U32 max, LightInfo*);
  258. virtual bool supportsShadowVolume();
  259. virtual void getClipPlanes(Vector<PlaneF>& planes);
  260. virtual void addToShadowVolume(ShadowVolumeBSP * shadowVolume, LightInfo * light, S32 level);
  261. // persist
  262. U32 getResourceCRC();
  263. bool setPersistInfo(PersistInfo::PersistChunk *);
  264. bool getPersistInfo(PersistInfo::PersistChunk *);
  265. };
  266. //------------------------------------------------------------------------------
  267. // Class SceneLighting::InteriorProxy:
  268. //------------------------------------------------------------------------------
  269. blInteriorProxy::blInteriorProxy(SceneObject * obj) :
  270. Parent(obj)
  271. {
  272. mBoxShadowBSP = 0;
  273. }
  274. blInteriorProxy::~blInteriorProxy()
  275. {
  276. delete mBoxShadowBSP;
  277. }
  278. bool blInteriorProxy::loadResources()
  279. {
  280. InteriorInstance * interior = getObject();
  281. if(!interior)
  282. return(false);
  283. Resource<InteriorResource> & interiorRes = interior->getResource();
  284. if(!bool(interiorRes))
  285. return(false);
  286. return(true);
  287. }
  288. void blInteriorProxy::init()
  289. {
  290. InteriorInstance * interior = getObject();
  291. if(!interior)
  292. return;
  293. }
  294. bool blInteriorProxy::supportsShadowVolume()
  295. {
  296. return true;
  297. }
  298. void blInteriorProxy::getClipPlanes(Vector<PlaneF>& planes)
  299. {
  300. for(U32 i = 0; i < mLitBoxSurfaces.size(); i++)
  301. planes.push_back(mLitBoxSurfaces[i]->mPlane);
  302. }
  303. ShadowVolumeBSP::SVPoly * blInteriorProxy::buildInteriorPoly(ShadowVolumeBSP * shadowVolumeBSP,
  304. Interior * detail, U32 surfaceIndex, LightInfo * light,
  305. bool createSurfaceInfo)
  306. {
  307. InteriorInstance* interior = dynamic_cast<InteriorInstance*>(getObject());
  308. if (!interior)
  309. return NULL;
  310. // transform and add the points...
  311. const MatrixF & transform = interior->getTransform();
  312. const VectorF & scale = interior->getScale();
  313. const Interior::Surface & surface = detail->mSurfaces[surfaceIndex];
  314. ShadowVolumeBSP::SVPoly * poly = shadowVolumeBSP->createPoly();
  315. poly->mWindingCount = surface.windingCount;
  316. // project these points
  317. for(U32 j = 0; j < poly->mWindingCount; j++)
  318. {
  319. Point3F iPnt = detail->mPoints[detail->mWindings[surface.windingStart + j]].point;
  320. Point3F tPnt;
  321. iPnt.convolve(scale);
  322. transform.mulP(iPnt, &tPnt);
  323. poly->mWinding[j] = tPnt;
  324. }
  325. // convert from fan
  326. U32 tmpIndices[ShadowVolumeBSP::SVPoly::MaxWinding];
  327. Point3F fanIndices[ShadowVolumeBSP::SVPoly::MaxWinding];
  328. tmpIndices[0] = 0;
  329. U32 idx = 1;
  330. U32 i;
  331. for(i = 1; i < poly->mWindingCount; i += 2)
  332. tmpIndices[idx++] = i;
  333. for(i = ((poly->mWindingCount - 1) & (~0x1)); i > 0; i -= 2)
  334. tmpIndices[idx++] = i;
  335. idx = 0;
  336. for(i = 0; i < poly->mWindingCount; i++)
  337. if(surface.fanMask & (1 << i))
  338. fanIndices[idx++] = poly->mWinding[tmpIndices[i]];
  339. // set the data
  340. poly->mWindingCount = idx;
  341. for(i = 0; i < poly->mWindingCount; i++)
  342. poly->mWinding[i] = fanIndices[i];
  343. // flip the plane - shadow volumes face inwards
  344. PlaneF plane = detail->getPlane(surface.planeIndex);
  345. if(!Interior::planeIsFlipped(surface.planeIndex))
  346. plane.neg();
  347. // transform the plane
  348. mTransformPlane(transform, scale, plane, &poly->mPlane);
  349. shadowVolumeBSP->buildPolyVolume(poly, light);
  350. // do surface info?
  351. if(createSurfaceInfo)
  352. {
  353. ShadowVolumeBSP::SurfaceInfo * surfaceInfo = new ShadowVolumeBSP::SurfaceInfo;
  354. shadowVolumeBSP->mSurfaces.push_back(surfaceInfo);
  355. // fill it
  356. surfaceInfo->mSurfaceIndex = surfaceIndex;
  357. surfaceInfo->mShadowVolume = shadowVolumeBSP->getShadowVolume(poly->mShadowVolume);
  358. // POLY and POLY node gets it too
  359. ShadowVolumeBSP::SVNode * traverse = shadowVolumeBSP->getShadowVolume(poly->mShadowVolume);
  360. while(traverse->mFront)
  361. {
  362. traverse->mSurfaceInfo = surfaceInfo;
  363. traverse = traverse->mFront;
  364. }
  365. // get some info from the poly node
  366. poly->mSurfaceInfo = traverse->mSurfaceInfo = surfaceInfo;
  367. surfaceInfo->mPlaneIndex = traverse->mPlaneIndex;
  368. }
  369. return(poly);
  370. }
  371. void blInteriorProxy::addToShadowVolume(ShadowVolumeBSP * shadowVolume, LightInfo * light, S32 level)
  372. {
  373. if(light->getType() != LightInfo::Vector)
  374. return;
  375. ColorF ambient = light->getAmbient();
  376. bool shadowedTree = true;
  377. InteriorInstance* interior = dynamic_cast<InteriorInstance*>(getObject());
  378. if (!interior)
  379. return;
  380. Resource<InteriorResource> mInteriorRes = interior->getResource();
  381. // check if just getting shadow detail
  382. if(level == SceneLighting::SHADOW_DETAIL)
  383. {
  384. shadowedTree = false;
  385. level = mInteriorRes->getNumDetailLevels() - 1;
  386. }
  387. Interior * detail = mInteriorRes->getDetailLevel(level);
  388. bool hasAlarm = detail->hasAlarmState();
  389. // make sure surfaces do not get processed more than once
  390. BitVector surfaceProcessed;
  391. surfaceProcessed.setSize(detail->mSurfaces.size());
  392. surfaceProcessed.clear();
  393. ColorI color = light->getAmbient();
  394. // go through the zones of the interior and grab outside visible surfaces
  395. for(U32 i = 0; i < detail->getNumZones(); i++)
  396. {
  397. Interior::Zone & zone = detail->mZones[i];
  398. for(U32 j = 0; j < zone.surfaceCount; j++)
  399. {
  400. U32 surfaceIndex = detail->mZoneSurfaces[zone.surfaceStart + j];
  401. // dont reprocess a surface
  402. if(surfaceProcessed.test(surfaceIndex))
  403. continue;
  404. surfaceProcessed.set(surfaceIndex);
  405. Interior::Surface & surface = detail->mSurfaces[surfaceIndex];
  406. // outside visible?
  407. if(!(surface.surfaceFlags & Interior::SurfaceOutsideVisible))
  408. continue;
  409. // good surface?
  410. PlaneF plane = detail->getPlane(surface.planeIndex);
  411. if(Interior::planeIsFlipped(surface.planeIndex))
  412. plane.neg();
  413. // project the plane
  414. PlaneF projPlane;
  415. mTransformPlane(interior->getTransform(), interior->getScale(), plane, &projPlane);
  416. // fill with ambient? (need to do here, because surface will not be
  417. // added to the SVBSP tree)
  418. F32 dot = mDot(projPlane, light->getDirection());
  419. if(dot > -gParellelVectorThresh)// && !(GFX->getPixelShaderVersion() > 0.0) )
  420. {
  421. if(shadowedTree)
  422. {
  423. // alarm lighting
  424. GFXTexHandle normHandle = gInteriorLMManager.duplicateBaseLightmap(detail->getLMHandle(), interior->getLMHandle(), detail->getNormalLMapIndex(surfaceIndex));
  425. GFXTexHandle alarmHandle;
  426. GBitmap * normLightmap = normHandle->getBitmap();
  427. GBitmap * alarmLightmap = 0;
  428. // check if they share the lightmap
  429. if(hasAlarm)
  430. {
  431. if(detail->getNormalLMapIndex(surfaceIndex) != detail->getAlarmLMapIndex(surfaceIndex))
  432. {
  433. alarmHandle = gInteriorLMManager.duplicateBaseLightmap(detail->getLMHandle(), interior->getLMHandle(), detail->getAlarmLMapIndex(surfaceIndex));
  434. alarmLightmap = alarmHandle->getBitmap();
  435. }
  436. }
  437. //
  438. // Support for interior light map border sizes.
  439. //
  440. U32 xlen, ylen, xoff, yoff;
  441. U32 lmborder = detail->getLightMapBorderSize();
  442. xlen = surface.mapSizeX + (lmborder * 2);
  443. ylen = surface.mapSizeY + (lmborder * 2);
  444. xoff = surface.mapOffsetX - lmborder;
  445. yoff = surface.mapOffsetY - lmborder;
  446. // attemp to light normal and alarm lighting
  447. for(U32 c = 0; c < 2; c++)
  448. {
  449. GBitmap * lightmap = (c == 0) ? normLightmap : alarmLightmap;
  450. if(!lightmap)
  451. continue;
  452. // fill it
  453. for(U32 y = 0; y < ylen; y++)
  454. {
  455. for(U32 x = 0; x < xlen; x++)
  456. {
  457. ColorI outColor(255, 0, 0, 255);
  458. #ifndef SET_COLORS
  459. ColorI lmColor(0, 0, 0, 255);
  460. lightmap->getColor(xoff + x, yoff + y, lmColor);
  461. U32 _r = static_cast<U32>( color.red ) + static_cast<U32>( lmColor.red );
  462. U32 _g = static_cast<U32>( color.green ) + static_cast<U32>( lmColor.green );
  463. U32 _b = static_cast<U32>( color.blue ) + static_cast<U32>( lmColor.blue );
  464. outColor.red = mClamp(_r, 0, 255);
  465. outColor.green = mClamp(_g, 0, 255);
  466. outColor.blue = mClamp(_b, 0, 255);
  467. #endif
  468. lightmap->setColor(xoff + x, yoff + y, outColor);
  469. }
  470. }
  471. }
  472. }
  473. continue;
  474. }
  475. ShadowVolumeBSP::SVPoly * poly = buildInteriorPoly(shadowVolume, detail,
  476. surfaceIndex, light, shadowedTree);
  477. // insert it into the SVBSP tree
  478. shadowVolume->insertPoly(poly);
  479. }
  480. }
  481. }
  482. bool blInteriorProxy::preLight(LightInfo * light)
  483. {
  484. // create shadow volume of the bounding box of this object
  485. InteriorInstance * interior = getObject();
  486. if(!interior)
  487. return(false);
  488. if(light->getType() != LightInfo::Vector)
  489. return(false);
  490. // reset
  491. mLitBoxSurfaces.clear();
  492. const Box3F & objBox = interior->getObjBox();
  493. const MatrixF & objTransform = interior->getTransform();
  494. const VectorF & objScale = interior->getScale();
  495. // grab the surfaces which form the shadow volume
  496. U32 numPlanes = 0;
  497. PlaneF testPlanes[3];
  498. U32 planeIndices[3];
  499. // grab the bounding planes which face the light
  500. U32 i;
  501. for(i = 0; (i < 6) && (numPlanes < 3); i++)
  502. {
  503. PlaneF plane;
  504. plane.x = BoxNormals[i].x;
  505. plane.y = BoxNormals[i].y;
  506. plane.z = BoxNormals[i].z;
  507. if(i&1)
  508. plane.d = (((const float*)objBox.minExtents)[(i-1)>>1]);
  509. else
  510. plane.d = -(((const float*)objBox.maxExtents)[i>>1]);
  511. // project
  512. mTransformPlane(objTransform, objScale, plane, &testPlanes[numPlanes]);
  513. planeIndices[numPlanes] = i;
  514. if(mDot(testPlanes[numPlanes], light->getDirection()) < gParellelVectorThresh)
  515. numPlanes++;
  516. }
  517. AssertFatal(numPlanes, "blInteriorProxy::preLight: no planes found");
  518. // project the points
  519. Point3F projPnts[8];
  520. for(i = 0; i < 8; i++)
  521. {
  522. Point3F pnt;
  523. pnt.set(BoxPnts[i].x ? objBox.maxExtents.x : objBox.minExtents.x,
  524. BoxPnts[i].y ? objBox.maxExtents.y : objBox.minExtents.y,
  525. BoxPnts[i].z ? objBox.maxExtents.z : objBox.minExtents.z);
  526. // scale it
  527. pnt.convolve(objScale);
  528. objTransform.mulP(pnt, &projPnts[i]);
  529. }
  530. mBoxShadowBSP = new ShadowVolumeBSP;
  531. // insert the shadow volumes for the surfaces
  532. for(i = 0; i < numPlanes; i++)
  533. {
  534. ShadowVolumeBSP::SVPoly * poly = mBoxShadowBSP->createPoly();
  535. poly->mWindingCount = 4;
  536. U32 j;
  537. for(j = 0; j < 4; j++)
  538. poly->mWinding[j] = projPnts[BoxVerts[planeIndices[i]][j]];
  539. testPlanes[i].neg();
  540. poly->mPlane = testPlanes[i];
  541. mBoxShadowBSP->buildPolyVolume(poly, light);
  542. mLitBoxSurfaces.push_back(mBoxShadowBSP->copyPoly(poly));
  543. mBoxShadowBSP->insertPoly(poly);
  544. // create the opposite planes for testing against terrain
  545. Point3F pnts[3];
  546. for(j = 0; j < 3; j++)
  547. pnts[j] = projPnts[BoxVerts[planeIndices[i]^1][j]];
  548. PlaneF plane(pnts[2], pnts[1], pnts[0]);
  549. mOppositeBoxPlanes.push_back(plane);
  550. }
  551. // grab the unique planes for terrain checks
  552. for(i = 0; i < numPlanes; i++)
  553. {
  554. U32 mask = 0;
  555. for(U32 j = 0; j < numPlanes; j++)
  556. mask |= BoxSharedEdgeMask[planeIndices[i]][planeIndices[j]];
  557. ShadowVolumeBSP::SVNode * traverse = mBoxShadowBSP->getShadowVolume(mLitBoxSurfaces[i]->mShadowVolume);
  558. while(traverse->mFront)
  559. {
  560. if(!(mask & 1))
  561. mTerrainTestPlanes.push_back(mBoxShadowBSP->getPlane(traverse->mPlaneIndex));
  562. mask >>= 1;
  563. traverse = traverse->mFront;
  564. }
  565. }
  566. // there will be 2 duplicate node planes if there were only 2 planes lit
  567. if(numPlanes == 2)
  568. {
  569. for(S32 i = 0; i < mTerrainTestPlanes.size(); i++)
  570. for(U32 j = 0; j < mTerrainTestPlanes.size(); j++)
  571. {
  572. if(i == j)
  573. continue;
  574. if((mDot(mTerrainTestPlanes[i], mTerrainTestPlanes[j]) > gPlaneNormThresh) &&
  575. (mFabs(mTerrainTestPlanes[i].d - mTerrainTestPlanes[j].d) < gPlaneDistThresh))
  576. {
  577. mTerrainTestPlanes.erase(i);
  578. i--;
  579. break;
  580. }
  581. }
  582. }
  583. return(true);
  584. }
  585. bool blInteriorProxy::isShadowedBy(blInteriorProxy * test)
  586. {
  587. // add if overlapping world box
  588. if((*this)->getWorldBox().isOverlapped((*test)->getWorldBox()))
  589. return(true);
  590. // test the box shadow volume
  591. for(U32 i = 0; i < mLitBoxSurfaces.size(); i++)
  592. {
  593. ShadowVolumeBSP::SVPoly * poly = mBoxShadowBSP->copyPoly(mLitBoxSurfaces[i]);
  594. if(test->mBoxShadowBSP->testPoly(poly))
  595. return(true);
  596. }
  597. return(false);
  598. }
  599. void blInteriorProxy::light(LightInfo * light)
  600. {
  601. Platform::setMathControlStateKnown();
  602. InteriorInstance * interior = getObject();
  603. if(!interior)
  604. return;
  605. ColorF ambient = light->getAmbient();
  606. S32 time = Platform::getRealMilliseconds();
  607. // create own shadow volume
  608. ShadowVolumeBSP shadowVolume;
  609. // add the other objects lit surfaces into shadow volume
  610. for(ObjectProxy ** itr = gLighting->mLitObjects.begin(); itr != gLighting->mLitObjects.end(); itr++)
  611. {
  612. if(!(*itr)->getObject())
  613. continue;
  614. ObjectProxy* obj = *itr;
  615. if (obj != this)
  616. {
  617. if (obj->supportsShadowVolume())
  618. obj->addToShadowVolume(&shadowVolume, light, SceneLighting::SHADOW_DETAIL);
  619. }
  620. /*
  621. // insert the terrain squares
  622. if(gLighting->isTerrain((*itr)->mObj))
  623. {
  624. TerrainProxy * terrain = static_cast<TerrainProxy*>(*itr);
  625. Vector<PlaneF> clipPlanes;
  626. clipPlanes = mTerrainTestPlanes;
  627. for(U32 i = 0; i < mOppositeBoxPlanes.size(); i++)
  628. clipPlanes.push_back(mOppositeBoxPlanes[i]);
  629. Vector<U16> shadowList;
  630. if(terrain->getShadowedSquares(clipPlanes, shadowList))
  631. {
  632. TerrainBlock * block = static_cast<TerrainBlock*>((*itr)->getObject());
  633. Point3F offset;
  634. block->getTransform().getColumn(3, &offset);
  635. F32 squareSize = block->getSquareSize();
  636. for(U32 j = 0; j < shadowList.size(); j++)
  637. {
  638. Point2I pos(shadowList[j] & TerrainBlock::BlockMask, shadowList[j] >> TerrainBlock::BlockShift);
  639. Point2F wPos(pos.x * squareSize + offset.x,
  640. pos.y * squareSize + offset.y);
  641. Point3F pnts[4];
  642. pnts[0].set(wPos.x, wPos.y, fixedToFloat(block->getHeight(pos.x, pos.y)));
  643. pnts[1].set(wPos.x + squareSize, wPos.y, fixedToFloat(block->getHeight(pos.x + 1, pos.y)));
  644. pnts[2].set(wPos.x + squareSize, wPos.y + squareSize, fixedToFloat(block->getHeight(pos.x + 1, pos.y + 1)));
  645. pnts[3].set(wPos.x, wPos.y + squareSize, fixedToFloat(block->getHeight(pos.x, pos.y + 1)));
  646. GridSquare * gs = block->findSquare(0, pos);
  647. U32 squareIdx = (gs->flags & GridSquare::Split45) ? 0 : 2;
  648. for(U32 k = squareIdx; k < (squareIdx + 2); k++)
  649. {
  650. // face plane inwards
  651. PlaneF plane(pnts[TerrainSquareIndices[k][2]],
  652. pnts[TerrainSquareIndices[k][1]],
  653. pnts[TerrainSquareIndices[k][0]]);
  654. if(mDot(plane, light->mDirection) > gParellelVectorThresh)
  655. {
  656. ShadowVolumeBSP::SVPoly * poly = shadowVolume.createPoly();
  657. poly->mWindingCount = 3;
  658. poly->mWinding[0] = pnts[TerrainSquareIndices[k][0]];
  659. poly->mWinding[1] = pnts[TerrainSquareIndices[k][1]];
  660. poly->mWinding[2] = pnts[TerrainSquareIndices[k][2]];
  661. poly->mPlane = plane;
  662. // create the shadow volume for this and insert
  663. shadowVolume.buildPolyVolume(poly, light);
  664. shadowVolume.insertPoly(poly);
  665. }
  666. }
  667. }
  668. }
  669. }*/
  670. }
  671. // light all details
  672. for(U32 i = 0; i < interior->getResource()->getNumDetailLevels(); i++)
  673. {
  674. // clear lightmaps
  675. Interior * detail = interior->getResource()->getDetailLevel(i);
  676. gInteriorLMManager.clearLightmaps(detail->getLMHandle(), interior->getLMHandle());
  677. // clear out the last inserted interior
  678. shadowVolume.removeLastInterior();
  679. bool hasAlarm = detail->hasAlarmState();
  680. addToShadowVolume(&shadowVolume, light, i);
  681. //gLighting->addInterior(&shadowVolume, *this, light, i);
  682. for(U32 j = 0; j < shadowVolume.mSurfaces.size(); j++)
  683. {
  684. ShadowVolumeBSP::SurfaceInfo * surfaceInfo = shadowVolume.mSurfaces[j];
  685. U32 surfaceIndex = surfaceInfo->mSurfaceIndex;
  686. const Interior::Surface & surface = detail->getSurface(surfaceIndex);
  687. // alarm lighting
  688. GFXTexHandle normHandle = gInteriorLMManager.duplicateBaseLightmap(detail->getLMHandle(), interior->getLMHandle(), detail->getNormalLMapIndex(surfaceIndex));
  689. GFXTexHandle alarmHandle;
  690. GBitmap * normLightmap = normHandle->getBitmap();
  691. GBitmap * alarmLightmap = 0;
  692. // check if the lightmaps are shared
  693. if(hasAlarm)
  694. {
  695. if(detail->getNormalLMapIndex(surfaceIndex) != detail->getAlarmLMapIndex(surfaceIndex))
  696. {
  697. alarmHandle = gInteriorLMManager.duplicateBaseLightmap(detail->getLMHandle(), interior->getLMHandle(), detail->getAlarmLMapIndex(surfaceIndex));
  698. alarmLightmap = alarmHandle->getBitmap();
  699. }
  700. }
  701. // points right way?
  702. PlaneF plane = detail->getPlane(surface.planeIndex);
  703. if(Interior::planeIsFlipped(surface.planeIndex))
  704. plane.neg();
  705. const MatrixF & transform = interior->getTransform();
  706. const Point3F & scale = interior->getScale();
  707. //
  708. PlaneF projPlane;
  709. mTransformPlane(transform, scale, plane, &projPlane);
  710. F32 dot = mDot(projPlane, -light->getDirection());
  711. // cancel out lambert dot product and ambient lighting on hardware
  712. // with pixel shaders
  713. if( GFX->getPixelShaderVersion() > 0.0 )
  714. {
  715. dot = 1.0f;
  716. ambient.set( 0.0f, 0.0f, 0.0f );
  717. }
  718. // shadowed?
  719. if(!surfaceInfo->mShadowed.size())
  720. {
  721. // calc the color and convert to U8 rep
  722. ColorF tmp = (light->getColor() * dot) + ambient;
  723. tmp.clamp();
  724. ColorI color = tmp;
  725. // attempt to light both the normal and the alarm states
  726. for(U32 c = 0; c < 2; c++)
  727. {
  728. GBitmap * lightmap = (c == 0) ? normLightmap : alarmLightmap;
  729. if(!lightmap)
  730. continue;
  731. //
  732. // Support for interior light map border sizes.
  733. //
  734. U32 xlen, ylen, xoff, yoff;
  735. U32 lmborder = detail->getLightMapBorderSize();
  736. xlen = surface.mapSizeX + (lmborder * 2);
  737. ylen = surface.mapSizeY + (lmborder * 2);
  738. xoff = surface.mapOffsetX - lmborder;
  739. yoff = surface.mapOffsetY - lmborder;
  740. // fill it
  741. for(U32 y = 0; y < ylen; y++)
  742. {
  743. for(U32 x = 0; x < xlen; x++)
  744. {
  745. ColorI outColor(0, 255, 0, 255);
  746. #ifndef SET_COLORS
  747. ColorI lmColor(0, 0, 0, 255);
  748. lightmap->getColor(xoff + x, yoff + y, lmColor);
  749. U32 _r = static_cast<U32>( color.red ) + static_cast<U32>( lmColor.red );
  750. U32 _g = static_cast<U32>( color.green ) + static_cast<U32>( lmColor.green );
  751. U32 _b = static_cast<U32>( color.blue ) + static_cast<U32>( lmColor.blue );
  752. outColor.red = mClamp(_r, 0, 255);
  753. outColor.green = mClamp(_g, 0, 255);
  754. outColor.blue = mClamp(_b, 0, 255);
  755. #endif
  756. lightmap->setColor(xoff + x, yoff + y, outColor);
  757. }
  758. }
  759. }
  760. if(!surfaceInfo->mShadowed.size())
  761. continue;
  762. }
  763. //
  764. // Support for interior light map border sizes.
  765. //
  766. U32 xlen, ylen, xoff, yoff;
  767. U32 lmborder = detail->getLightMapBorderSize();
  768. xlen = surface.mapSizeX + (lmborder * 2);
  769. ylen = surface.mapSizeY + (lmborder * 2);
  770. xoff = surface.mapOffsetX - lmborder;
  771. yoff = surface.mapOffsetY - lmborder;
  772. // get the lmagGen...
  773. const Interior::TexGenPlanes & lmTexGenEQ = detail->getLMTexGenEQ(surfaceIndex);
  774. const F32 * const lGenX = lmTexGenEQ.planeX;
  775. const F32 * const lGenY = lmTexGenEQ.planeY;
  776. AssertFatal((lGenX[0] * lGenX[1] == 0.f) &&
  777. (lGenX[0] * lGenX[2] == 0.f) &&
  778. (lGenX[1] * lGenX[2] == 0.f), "Bad lmTexGen!");
  779. AssertFatal((lGenY[0] * lGenY[1] == 0.f) &&
  780. (lGenY[0] * lGenY[2] == 0.f) &&
  781. (lGenY[1] * lGenY[2] == 0.f), "Bad lmTexGen!");
  782. // get the axis index for the texgens (could be swapped)
  783. S32 si=0;
  784. S32 ti=0;
  785. S32 axis = -1;
  786. //
  787. if(lGenX[0] == 0.f && lGenY[0] == 0.f) // YZ
  788. {
  789. axis = 0;
  790. if(lGenX[1] == 0.f) { // swapped?
  791. si = 2;
  792. ti = 1;
  793. } else {
  794. si = 1;
  795. ti = 2;
  796. }
  797. }
  798. else if(lGenX[1] == 0.f && lGenY[1] == 0.f) // XZ
  799. {
  800. axis = 1;
  801. if(lGenX[0] == 0.f) { // swapped?
  802. si = 2;
  803. ti = 0;
  804. } else {
  805. si = 0;
  806. ti = 2;
  807. }
  808. }
  809. else if(lGenX[2] == 0.f && lGenY[2] == 0.f) // XY
  810. {
  811. axis = 2;
  812. if(lGenX[0] == 0.f) { // swapped?
  813. si = 1;
  814. ti = 0;
  815. } else {
  816. si = 0;
  817. ti = 1;
  818. }
  819. }
  820. AssertFatal(!(axis == -1), "SceneLighting::lightInterior: bad TexGen!");
  821. const F32 * pNormal = ((const F32*)plane);
  822. Point3F start;
  823. F32 * pStart = ((F32*)start);
  824. F32 lumelScale = 1.0 / (lGenX[si] * normLightmap->getWidth());
  825. // get the start point on the lightmap
  826. pStart[si] = (((xoff * lumelScale) / (1.0 / lGenX[si])) - lGenX[3] ) / lGenX[si];
  827. pStart[ti] = (((yoff * lumelScale) / (1.0 / lGenY[ti])) - lGenY[3] ) / lGenY[ti];
  828. pStart[axis] = ((pNormal[si] * pStart[si]) + (pNormal[ti] * pStart[ti]) + plane.d) / -pNormal[axis];
  829. start.convolve(scale);
  830. transform.mulP(start);
  831. // get the s/t vecs oriented on the surface
  832. Point3F sVec;
  833. Point3F tVec;
  834. F32 * pSVec = ((F32*)sVec);
  835. F32 * pTVec = ((F32*)tVec);
  836. F32 angle;
  837. Point3F planeNormal;
  838. // s
  839. pSVec[si] = 1.f;
  840. pSVec[ti] = 0.f;
  841. planeNormal = plane;
  842. ((F32*)planeNormal)[ti] = 0.f;
  843. planeNormal.normalize();
  844. angle = mAcos(mClampF(((F32*)planeNormal)[axis], -1.f, 1.f));
  845. pSVec[axis] = (((F32*)planeNormal)[si] < 0.f) ? mTan(angle) : -mTan(angle);
  846. // t
  847. pTVec[ti] = 1.f;
  848. pTVec[si] = 0.f;
  849. planeNormal = plane;
  850. ((F32*)planeNormal)[si] = 0.f;
  851. planeNormal.normalize();
  852. angle = mAcos(mClampF(((F32*)planeNormal)[axis], -1.f, 1.f));
  853. pTVec[axis] = (((F32*)planeNormal)[ti] < 0.f) ? mTan(angle) : -mTan(angle);
  854. // scale the vectors
  855. sVec *= lumelScale;
  856. tVec *= lumelScale;
  857. // project vecs
  858. transform.mulV(sVec);
  859. sVec.convolve(scale);
  860. transform.mulV(tVec);
  861. tVec.convolve(scale);
  862. Point3F & curPos = start;
  863. Point3F sRun = sVec * xlen;
  864. // get the lexel area
  865. Point3F cross;
  866. mCross(sVec, tVec, &cross);
  867. F32 maxLexelArea = cross.len();
  868. const PlaneF & surfacePlane = shadowVolume.getPlane(surfaceInfo->mPlaneIndex);
  869. // get the world coordinate for each lexel
  870. for(U32 y = 0; y < ylen; y++)
  871. {
  872. for(U32 x = 0; x < xlen; x++)
  873. {
  874. ShadowVolumeBSP::SVPoly * poly = shadowVolume.createPoly();
  875. poly->mPlane = surfacePlane;
  876. poly->mWindingCount = 4;
  877. // set the poly indices
  878. poly->mWinding[0] = curPos;
  879. poly->mWinding[1] = curPos + sVec;
  880. poly->mWinding[2] = curPos + sVec + tVec;
  881. poly->mWinding[3] = curPos + tVec;
  882. //// insert poly which has been clipped to own shadow volume
  883. //ShadowVolumeBSP::SVPoly * store = 0;
  884. //shadowVolume.clipToSelf(surfaceInfo->mShadowVolume, &store, poly);
  885. //if(!store)
  886. // continue;
  887. //F32 lexelArea = shadowVolume.getPolySurfaceArea(store);
  888. //F32 area = shadowVolume.getLitSurfaceArea(store, surfaceInfo);
  889. F32 area = shadowVolume.getLitSurfaceArea(poly, surfaceInfo);
  890. F32 shadowScale = mClampF(area / maxLexelArea, 0.f, 1.f);
  891. // get the color into U8
  892. ColorF tmp = (light->getColor() * dot * shadowScale) + ambient;
  893. tmp.clamp();
  894. ColorI color = tmp;
  895. // attempt to light both normal and alarm lightmaps
  896. for(U32 c = 0; c < 2; c++)
  897. {
  898. GBitmap * lightmap = (c == 0) ? normLightmap : alarmLightmap;
  899. if(!lightmap)
  900. continue;
  901. ColorI outColor(0, 0, 255, 255);
  902. #ifndef SET_COLORS
  903. ColorI lmColor(0, 0, 0, 255);
  904. lightmap->getColor(xoff + x, yoff + y, lmColor);
  905. U32 _r = static_cast<U32>( color.red ) + static_cast<U32>( lmColor.red );
  906. U32 _g = static_cast<U32>( color.green ) + static_cast<U32>( lmColor.green );
  907. U32 _b = static_cast<U32>( color.blue ) + static_cast<U32>( lmColor.blue );
  908. outColor.red = mClamp(_r, 0, 255);
  909. outColor.green = mClamp(_g, 0, 255);
  910. outColor.blue = mClamp(_b, 0, 255);
  911. #endif
  912. lightmap->setColor(xoff + x, yoff + y, outColor);
  913. }
  914. curPos += sVec;
  915. }
  916. curPos -= sRun;
  917. curPos += tVec;
  918. }
  919. }
  920. }
  921. Con::printf(" = interior lit in %3.3f seconds", (Platform::getRealMilliseconds()-time)/1000.f);
  922. }
  923. void blInteriorProxy::postLight(bool lastLight)
  924. {
  925. delete mBoxShadowBSP;
  926. mBoxShadowBSP = 0;
  927. InteriorInstance * interior = getObject();
  928. if(!interior)
  929. return;
  930. }
  931. //------------------------------------------------------------------------------
  932. U32 blInteriorProxy::getResourceCRC()
  933. {
  934. InteriorInstance * interior = getObject();
  935. if(!interior)
  936. return(0);
  937. return(interior->getCRC());
  938. }
  939. //------------------------------------------------------------------------------
  940. bool blInteriorProxy::setPersistInfo(PersistInfo::PersistChunk * info)
  941. {
  942. if(!Parent::setPersistInfo(info))
  943. return(false);
  944. blInteriorChunk * chunk = dynamic_cast<blInteriorChunk*>(info);
  945. AssertFatal(chunk, "blInteriorProxy::setPersistInfo: invalid info chunk!");
  946. InteriorInstance * interior = getObject();
  947. if(!interior)
  948. return(false);
  949. U32 numDetails = interior->getNumDetailLevels();
  950. // check the lighting method
  951. // BTRTODO: Restore
  952. // AssertFatal(SceneLighting::smUseVertexLighting == Interior::smUseVertexLighting, "blInteriorProxy::setPersistInfo: invalid vertex lighting state");
  953. // if(SceneLighting::smUseVertexLighting != Interior::smUseVertexLighting)
  954. // return(false);
  955. /*
  956. // process the vertex lighting...
  957. if(chunk->mDetailVertexCount.size() != numDetails)
  958. return(false);
  959. AssertFatal(chunk->mVertexColorsNormal.size(), "blInteriorProxy::setPersistInfo: invalid chunk info");
  960. AssertFatal(!chunk->mHasAlarmState || chunk->mVertexColorsAlarm.size(), "blInteriorProxy::setPersistInfo: invalid chunk info");
  961. AssertFatal(!(chunk->mHasAlarmState ^ interior->getDetailLevel(0)->hasAlarmState()), "blInteriorProxy::setPersistInfo: invalid chunk info");
  962. U32 curPos = 0;
  963. for(U32 i = 0; i < numDetails; i++)
  964. {
  965. U32 count = chunk->mDetailVertexCount[i];
  966. Vector<ColorI>* normal = interior->getVertexColorsNormal(i);
  967. Vector<ColorI>* alarm = interior->getVertexColorsAlarm(i);
  968. AssertFatal(normal != NULL && alarm != NULL, "Error, bad vectors returned!");
  969. normal->setSize(count);
  970. dMemcpy(normal->address(), &chunk->mVertexColorsNormal[curPos], count * sizeof(ColorI));
  971. if(chunk->mHasAlarmState)
  972. {
  973. alarm->setSize(count);
  974. dMemcpy(alarm->address(), &chunk->mVertexColorsAlarm[curPos], count * sizeof(ColorI));
  975. }
  976. curPos += count;
  977. }
  978. */
  979. // need lightmaps?
  980. //if(!SceneLighting::smUseVertexLighting)
  981. // BTRTODO: Fix me
  982. if (!false)
  983. {
  984. if(chunk->mDetailLightmapCount.size() != numDetails)
  985. return(false);
  986. LM_HANDLE instanceHandle = interior->getLMHandle();
  987. U32 idx = 0;
  988. for(U32 i = 0; i < numDetails; i++)
  989. {
  990. Interior * detail = interior->getDetailLevel(i);
  991. LM_HANDLE interiorHandle = detail->getLMHandle();
  992. Vector<GFXTexHandle> & baseHandles = gInteriorLMManager.getHandles(interiorHandle, 0);
  993. if(chunk->mDetailLightmapCount[i] > baseHandles.size())
  994. return(false);
  995. for(U32 j = 0; j < chunk->mDetailLightmapCount[i]; j++)
  996. {
  997. U32 baseIndex = chunk->mDetailLightmapIndices[idx];
  998. if(baseIndex >= baseHandles.size())
  999. return(false);
  1000. AssertFatal(chunk->mLightmaps[idx], "blInteriorProxy::setPersistInfo: bunk bitmap!");
  1001. if(chunk->mLightmaps[idx]->getWidth() != baseHandles[baseIndex]->getWidth() ||
  1002. chunk->mLightmaps[idx]->getHeight() != baseHandles[baseIndex]->getHeight())
  1003. return(false);
  1004. GFXTexHandle tHandle = gInteriorLMManager.duplicateBaseLightmap(interiorHandle, instanceHandle, baseIndex);
  1005. // create the diff bitmap
  1006. tHandle->getBitmap()->combine( baseHandles[baseIndex]->getBitmap(),
  1007. chunk->mLightmaps[idx],
  1008. GFXTOPAdd );
  1009. idx++;
  1010. }
  1011. }
  1012. }
  1013. return(true);
  1014. }
  1015. bool blInteriorProxy::getPersistInfo(PersistInfo::PersistChunk * info)
  1016. {
  1017. if(!Parent::getPersistInfo(info))
  1018. return(false);
  1019. blInteriorChunk* chunk = dynamic_cast<blInteriorChunk*>(info);
  1020. AssertFatal(chunk, "blInteriorProxy::getPersistInfo: invalid info chunk!");
  1021. InteriorInstance * interior = getObject();
  1022. if(!interior)
  1023. return(false);
  1024. LM_HANDLE instanceHandle = interior->getLMHandle();
  1025. AssertFatal(!chunk->mDetailLightmapCount.size(), "blInteriorProxy::getPersistInfo: invalid array!");
  1026. AssertFatal(!chunk->mDetailLightmapIndices.size(), "blInteriorProxy::getPersistInfo: invalid array!");
  1027. AssertFatal(!chunk->mLightmaps.size(), "blInteriorProxy::getPersistInfo: invalid array!");
  1028. U32 numDetails = interior->getNumDetailLevels();
  1029. U32 i;
  1030. for(i = 0; i < numDetails; i++)
  1031. {
  1032. Interior * detail = interior->getDetailLevel(i);
  1033. LM_HANDLE interiorHandle = detail->getLMHandle();
  1034. Vector<GFXTexHandle> & baseHandles = gInteriorLMManager.getHandles(interiorHandle, 0);
  1035. Vector<GFXTexHandle> & instanceHandles = gInteriorLMManager.getHandles(interiorHandle, instanceHandle);
  1036. U32 litCount = 0;
  1037. // walk all the instance lightmaps and grab diff lighting from them
  1038. for(U32 j = 0; j < instanceHandles.size(); j++)
  1039. {
  1040. if(!instanceHandles[j])
  1041. continue;
  1042. litCount++;
  1043. chunk->mDetailLightmapIndices.push_back(j);
  1044. GBitmap * baseBitmap = baseHandles[j]->getBitmap();
  1045. GBitmap * instanceBitmap = instanceHandles[j]->getBitmap();
  1046. Point2I extent(baseBitmap->getWidth(), baseBitmap->getHeight());
  1047. GBitmap * diffLightmap = new GBitmap(extent.x, extent.y, false);
  1048. // diffLightmap = instanceBitmap - baseBitmap
  1049. diffLightmap->combine( instanceBitmap, baseBitmap, GFXTOPSubtract );
  1050. chunk->mLightmaps.push_back(diffLightmap);
  1051. }
  1052. chunk->mDetailLightmapCount.push_back(litCount);
  1053. }
  1054. // process the vertex lighting...
  1055. AssertFatal(!chunk->mDetailVertexCount.size(), "blInteriorProxy::getPersistInfo: invalid chunk info");
  1056. AssertFatal(!chunk->mVertexColorsNormal.size(), "blInteriorProxy::getPersistInfo: invalid chunk info");
  1057. AssertFatal(!chunk->mVertexColorsAlarm.size(), "blInteriorProxy::getPersistInfo: invalid chunk info");
  1058. chunk->mHasAlarmState = interior->getDetailLevel(0)->hasAlarmState();
  1059. chunk->mDetailVertexCount.setSize(numDetails);
  1060. U32 size = 0;
  1061. for(i = 0; i < numDetails; i++)
  1062. {
  1063. Interior * detail = interior->getDetailLevel(i);
  1064. U32 count = detail->getWindingCount();
  1065. chunk->mDetailVertexCount[i] = count;
  1066. size += count;
  1067. }
  1068. /*
  1069. chunk->mVertexColorsNormal.setSize(size);
  1070. if(chunk->mHasAlarmState)
  1071. chunk->mVertexColorsAlarm.setSize(size);
  1072. U32 curPos = 0;
  1073. for(i = 0; i < numDetails; i++)
  1074. {
  1075. Vector<ColorI>* normal = interior->getVertexColorsNormal(i);
  1076. Vector<ColorI>* alarm = interior->getVertexColorsAlarm(i);
  1077. AssertFatal(normal != NULL && alarm != NULL, "Error, no normal or alarm vertex colors!");
  1078. U32 count = chunk->mDetailVertexCount[i];
  1079. dMemcpy(&chunk->mVertexColorsNormal[curPos], normal->address(), count * sizeof(ColorI));
  1080. if(chunk->mHasAlarmState)
  1081. dMemcpy(&chunk->mVertexColorsAlarm[curPos], alarm->address(), count * sizeof(ColorI));
  1082. curPos += count;
  1083. }
  1084. */
  1085. return(true);
  1086. }
  1087. SceneLighting::ObjectProxy* blInteriorSystem::createObjectProxy(SceneObject* obj, SceneLighting::ObjectProxyList* sceneObjects)
  1088. {
  1089. if ((obj->getTypeMask() & InteriorObjectType) != 0)
  1090. {
  1091. return new blInteriorProxy(obj);
  1092. } else {
  1093. return NULL;
  1094. }
  1095. }
  1096. PersistInfo::PersistChunk* blInteriorSystem::createPersistChunk(const U32 chunkType)
  1097. {
  1098. if (chunkType == PersistInfo::PersistChunk::InteriorChunkType)
  1099. {
  1100. return new blInteriorChunk;
  1101. } else {
  1102. return NULL;
  1103. }
  1104. }
  1105. bool blInteriorSystem::createPersistChunkFromProxy(SceneLighting::ObjectProxy* objproxy, PersistInfo::PersistChunk **ret)
  1106. {
  1107. if ((objproxy->mObj->getTypeMask() & InteriorObjectType) != 0)
  1108. {
  1109. *ret = new blInteriorChunk;
  1110. return true;
  1111. } else {
  1112. return false;
  1113. }
  1114. }
  1115. void blInteriorSystem::init()
  1116. {
  1117. }
  1118. U32 blInteriorSystem::addObjectType()
  1119. {
  1120. return InteriorObjectType;
  1121. }
  1122. U32 blInteriorSystem::addToClippingMask()
  1123. {
  1124. return InteriorObjectType;
  1125. }
  1126. void blInteriorSystem::processLightingBegin()
  1127. {
  1128. // Store the vertex lighting state when we being lighting, we compare this when we finish lighting
  1129. smUseVertexLighting = Interior::smUseVertexLighting;
  1130. }
  1131. void blInteriorSystem::processLightingCompleted(bool success)
  1132. {
  1133. if(success)
  1134. {
  1135. AssertFatal(smUseVertexLighting == Interior::smUseVertexLighting, "SceneLighting::completed: vertex lighting state changed during scene light");
  1136. // cannot do anything if vertex state has changed (since we only load in what is needed)
  1137. if(smUseVertexLighting == Interior::smUseVertexLighting)
  1138. {
  1139. if(!smUseVertexLighting)
  1140. {
  1141. gInteriorLMManager.downloadGLTextures();
  1142. gInteriorLMManager.destroyBitmaps();
  1143. }
  1144. else
  1145. gInteriorLMManager.destroyTextures();
  1146. }
  1147. }
  1148. }
  1149. // Given a ray, this will return the color from the lightmap of this object, return true if handled
  1150. bool blInteriorSystem::getColorFromRayInfo(RayInfo collision, ColorF& result)
  1151. {
  1152. InteriorInstance* interior = dynamic_cast<InteriorInstance*>(collision.object);
  1153. if (interior == NULL)
  1154. return false;
  1155. interior->getRenderWorldTransform().mulP(collision.point);
  1156. Interior *detail = interior->getDetailLevel(0);
  1157. AssertFatal((detail), "SceneObject::getLightingAmbientColor: invalid interior");
  1158. if(collision.face < detail->getSurfaceCount())
  1159. {
  1160. const Interior::Surface &surface = detail->getSurface(collision.face);
  1161. const Interior::TexGenPlanes &texgen = detail->getLMTexGenEQ(collision.face);
  1162. GBitmap* lightmap = gInteriorLMManager.getHandle(detail->getLMHandle(),
  1163. interior->getLMHandle(), detail->getNormalLMapIndex(collision.face)).getBitmap();
  1164. if (!lightmap)
  1165. return false;
  1166. Point2F uv;
  1167. uv.x = mDot(texgen.planeX, collision.point) + texgen.planeX.d;
  1168. uv.y = mDot(texgen.planeY, collision.point) + texgen.planeY.d;
  1169. U32 size = (U32)(uv.x * F32(lightmap->getWidth()));
  1170. size = mClamp(size, surface.mapOffsetX, (surface.mapOffsetX + surface.mapSizeX));
  1171. uv.x = F32(size) / F32(lightmap->getWidth());
  1172. size = (U32)(uv.y * F32(lightmap->getHeight()));
  1173. size = mClamp(size, surface.mapOffsetY, (surface.mapOffsetY + surface.mapSizeY));
  1174. uv.y = F32(size) / F32(lightmap->getHeight());
  1175. result = lightmap->sampleTexel(uv.x, uv.y);
  1176. return true;
  1177. }
  1178. return false;
  1179. }