interiorLMManager.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  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/interiorLMManager.h"
  23. #include "gfx/gfxTextureManager.h"
  24. #include "gfx/bitmap/gBitmap.h"
  25. #include "interior/interiorRes.h"
  26. #include "interior/interiorInstance.h"
  27. #include "interior/interior.h"
  28. //------------------------------------------------------------------------------
  29. // Globals
  30. InteriorLMManager gInteriorLMManager;
  31. //------------------------------------------------------------------------------
  32. InteriorLMManager::InteriorLMManager()
  33. {
  34. VECTOR_SET_ASSOCIATION( mInteriors );
  35. }
  36. InteriorLMManager::~InteriorLMManager()
  37. {
  38. for(U32 i = 0; i < mInteriors.size(); i++)
  39. removeInterior(LM_HANDLE(i));
  40. }
  41. //------------------------------------------------------------------------------
  42. void InteriorLMManager::addInterior(LM_HANDLE & interiorHandle, U32 numLightmaps, Interior * interior)
  43. {
  44. interiorHandle = mInteriors.size();
  45. mInteriors.increment();
  46. mInteriors.last() = new InteriorLMInfo;
  47. mInteriors.last()->mInterior = interior;
  48. mInteriors.last()->mHandlePtr = &interiorHandle;
  49. mInteriors.last()->mNumLightmaps = numLightmaps;
  50. // create base instance
  51. addInstance(interiorHandle, mInteriors.last()->mBaseInstanceHandle, 0);
  52. AssertFatal(mInteriors.last()->mBaseInstanceHandle == LM_HANDLE(0), "InteriorLMManager::addInterior: invalid base instance handle");
  53. // steal the lightmaps from the interior
  54. Vector<GFXTexHandle>& texHandles = getHandles(interiorHandle, 0);
  55. for(U32 i = 0; i < interior->mLightmaps.size(); i++)
  56. {
  57. AssertFatal(interior->mLightmaps[i], "InteriorLMManager::addInterior: interior missing lightmap");
  58. texHandles[i].set(interior->mLightmaps[i], &GFXDefaultPersistentProfile, true, String("Interior Lightmap"));
  59. }
  60. interior->mLightmaps.clear();
  61. }
  62. void InteriorLMManager::removeInterior(LM_HANDLE interiorHandle)
  63. {
  64. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::removeInterior: invalid interior handle");
  65. AssertFatal(mInteriors[interiorHandle]->mInstances.size() == 1, "InteriorLMManager::removeInterior: cannot remove base interior");
  66. // remove base instance
  67. removeInstance(interiorHandle, 0);
  68. *mInteriors[interiorHandle]->mHandlePtr = LM_HANDLE(-1);
  69. delete mInteriors[interiorHandle];
  70. // last one? otherwise move it
  71. if((mInteriors.size()-1) != interiorHandle)
  72. {
  73. mInteriors[interiorHandle] = mInteriors.last();
  74. *(mInteriors[interiorHandle]->mHandlePtr) = interiorHandle;
  75. }
  76. mInteriors.decrement();
  77. }
  78. //------------------------------------------------------------------------------
  79. void InteriorLMManager::addInstance(LM_HANDLE interiorHandle, LM_HANDLE & instanceHandle, InteriorInstance * instance)
  80. {
  81. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::addInstance: invalid interior handle");
  82. AssertFatal(interiorHandle == *(mInteriors[interiorHandle]->mHandlePtr), "InteriorLMManager::addInstance: invalid handle value");
  83. InteriorLMInfo * interiorInfo = mInteriors[interiorHandle];
  84. // create the instance info and fill
  85. InstanceLMInfo * instanceInfo = new InstanceLMInfo;
  86. instanceInfo->mInstance = instance;
  87. instanceInfo->mHandlePtr = &instanceHandle;
  88. instanceHandle = interiorInfo->mInstances.size();
  89. interiorInfo->mInstances.push_back(instanceInfo);
  90. // create/clear list
  91. instanceInfo->mLightmapHandles.setSize(interiorInfo->mNumLightmaps);
  92. for(U32 i = 0; i < instanceInfo->mLightmapHandles.size(); i++)
  93. instanceInfo->mLightmapHandles[i] = NULL;
  94. }
  95. void InteriorLMManager::removeInstance(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle)
  96. {
  97. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::removeInstance: invalid interior handle");
  98. AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::removeInstance: invalid instance handle");
  99. AssertFatal(!(instanceHandle == mInteriors[interiorHandle]->mBaseInstanceHandle &&
  100. mInteriors[interiorHandle]->mInstances.size() > 1), "InteriorLMManager::removeInstance: invalid base instance");
  101. InteriorLMInfo * itrInfo = mInteriors[interiorHandle];
  102. // kill it
  103. InstanceLMInfo * instInfo = itrInfo->mInstances[instanceHandle];
  104. for(U32 i = 0; i < instInfo->mLightmapHandles.size(); i++)
  105. instInfo->mLightmapHandles[i] = NULL;
  106. // reset on last instance removal only (multi detailed shapes share the same instance handle)
  107. if(itrInfo->mInstances.size() == 1)
  108. *instInfo->mHandlePtr = LM_HANDLE(-1);
  109. delete instInfo;
  110. // last one? otherwise move it
  111. if((itrInfo->mInstances.size()-1) != instanceHandle)
  112. {
  113. itrInfo->mInstances[instanceHandle] = itrInfo->mInstances.last();
  114. *(itrInfo->mInstances[instanceHandle]->mHandlePtr) = instanceHandle;
  115. }
  116. itrInfo->mInstances.decrement();
  117. }
  118. void InteriorLMManager::useBaseTextures(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle)
  119. {
  120. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::useBaseTextures: invalid interior handle");
  121. AssertFatal(interiorHandle == *(mInteriors[interiorHandle]->mHandlePtr), "InteriorLMManager::useBaseTextures: invalid handle value");
  122. // Make sure the base light maps are loaded
  123. loadBaseLightmaps(interiorHandle,instanceHandle);
  124. // Install base lightmaps for this instance...
  125. Vector<GFXTexHandle>& baseHandles = getHandles(interiorHandle, 0);
  126. Vector<GFXTexHandle>& texHandles = getHandles(interiorHandle, instanceHandle);
  127. for(U32 i = 0; i < baseHandles.size(); i++)
  128. texHandles[i] = baseHandles[i];
  129. }
  130. //------------------------------------------------------------------------------
  131. void InteriorLMManager::destroyBitmaps()
  132. {
  133. for(S32 i = mInteriors.size() - 1; i >= 0; i--)
  134. {
  135. InteriorLMInfo * interiorInfo = mInteriors[i];
  136. for(S32 j = interiorInfo->mInstances.size() - 1; j >= 0; j--)
  137. {
  138. InstanceLMInfo * instanceInfo = interiorInfo->mInstances[j];
  139. for(S32 k = instanceInfo->mLightmapHandles.size() - 1; k >= 0; k--)
  140. {
  141. if(!instanceInfo->mLightmapHandles[k])
  142. continue;
  143. GFXTextureObject * texObj = instanceInfo->mLightmapHandles[k];
  144. if(!texObj || !texObj->mBitmap)
  145. continue;
  146. // don't remove 'keep' bitmaps
  147. if(!interiorInfo->mInterior->mLightmapKeep[k])
  148. {
  149. // SAFE_DELETE(texObj->mBitmap);
  150. // texObj->bitmap = 0;
  151. }
  152. }
  153. }
  154. }
  155. }
  156. void InteriorLMManager::destroyTextures()
  157. {
  158. for(S32 i = mInteriors.size() - 1; i >= 0; i--)
  159. {
  160. InteriorLMInfo * interiorInfo = mInteriors[i];
  161. for(S32 j = interiorInfo->mInstances.size() - 1; j >= 0; j--)
  162. {
  163. InstanceLMInfo * instanceInfo = interiorInfo->mInstances[j];
  164. for(S32 k = interiorInfo->mNumLightmaps - 1; k >= 0; k--)
  165. {
  166. // will want to remove the vector here eventually... so dont clear
  167. instanceInfo->mLightmapHandles[k] = NULL;
  168. }
  169. }
  170. }
  171. }
  172. void InteriorLMManager::downloadGLTextures()
  173. {
  174. for(S32 i = mInteriors.size() - 1; i >= 0; i--)
  175. downloadGLTextures(i);
  176. }
  177. void InteriorLMManager::downloadGLTextures(LM_HANDLE interiorHandle)
  178. {
  179. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::downloadGLTextures: invalid interior handle");
  180. InteriorLMInfo * interiorInfo = mInteriors[interiorHandle];
  181. // The bit vector is used to keep track of which lightmap sets need
  182. // to be loaded from the shared "base" instance. Every instance
  183. // can have it's own lightmap set due to mission lighting.
  184. BitVector needTexture;
  185. needTexture.setSize(interiorInfo->mNumLightmaps);
  186. needTexture.clear();
  187. for(S32 j = interiorInfo->mInstances.size() - 1; j >= 0; j--)
  188. {
  189. InstanceLMInfo * instanceInfo = interiorInfo->mInstances[j];
  190. for(S32 k = instanceInfo->mLightmapHandles.size() - 1; k >= 0; k--)
  191. {
  192. // All instances can share the base instances static lightmaps.
  193. // Test here to see if we need to load those lightmaps.
  194. if ((j == 0) && !needTexture.test(k))
  195. continue;
  196. if (!instanceInfo->mLightmapHandles[k])
  197. {
  198. needTexture.set(k);
  199. continue;
  200. }
  201. GFXTexHandle texObj = instanceInfo->mLightmapHandles[k];
  202. if (!texObj || !texObj->mBitmap)
  203. {
  204. needTexture.set(k);
  205. continue;
  206. }
  207. instanceInfo->mLightmapHandles[k].set( texObj->mBitmap, &GFXDefaultPersistentProfile, false, String("Interior Lightmap Handle") );
  208. }
  209. }
  210. }
  211. bool InteriorLMManager::loadBaseLightmaps(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle)
  212. {
  213. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::loadBaseLightmaps: invalid interior handle");
  214. AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::loadBaseLightmaps: invalid instance handle");
  215. // must use a valid instance handle
  216. if(!instanceHandle)
  217. return(false);
  218. InteriorLMInfo * interiorInfo = mInteriors[interiorHandle];
  219. if(!interiorInfo->mNumLightmaps)
  220. return(false);
  221. InstanceLMInfo * baseInstanceInfo = interiorInfo->mInstances[0];
  222. // already loaded? (if any bitmap is present, then assumed that all will be)
  223. GFXTexHandle texture (baseInstanceInfo->mLightmapHandles[0]);
  224. if(texture.isValid() && texture.getBitmap())
  225. return(true);
  226. InstanceLMInfo * instanceInfo = interiorInfo->mInstances[instanceHandle];
  227. Resource<InteriorResource> & interiorRes = instanceInfo->mInstance->getResource();
  228. if(!bool(interiorRes))
  229. return(false);
  230. GBitmap *** pBitmaps = 0;
  231. if(!instanceInfo->mInstance->readLightmaps(&pBitmaps))
  232. return(false);
  233. for(U32 i = 0; i < interiorRes->getNumDetailLevels(); i++)
  234. {
  235. Interior * interior = interiorRes->getDetailLevel(i);
  236. AssertFatal(interior, "InteriorLMManager::loadBaseLightmaps: invalid detail level in resource");
  237. AssertFatal(interior->getLMHandle() != LM_HANDLE(-1), "InteriorLMManager::loadBaseLightmaps: interior not added to manager");
  238. AssertFatal(interior->getLMHandle() < mInteriors.size(), "InteriorLMManager::loadBaseLightmaps: invalid interior");
  239. InteriorLMInfo * interiorInfo = mInteriors[interior->getLMHandle()];
  240. InstanceLMInfo * baseInstanceInfo = interiorInfo->mInstances[0];
  241. for(U32 j = 0; j < interiorInfo->mNumLightmaps; j++)
  242. {
  243. AssertFatal(pBitmaps[i][j], "InteriorLMManager::loadBaseLightmaps: invalid bitmap");
  244. if (baseInstanceInfo->mLightmapHandles[j])
  245. {
  246. GFXTextureObject * texObj = baseInstanceInfo->mLightmapHandles[j];
  247. texObj->mBitmap = pBitmaps[i][j];
  248. }
  249. else
  250. baseInstanceInfo->mLightmapHandles[j].set( pBitmaps[i][j], &GFXDefaultPersistentProfile, false, String("Interior Lightmap Handle") );
  251. }
  252. }
  253. delete [] pBitmaps;
  254. return(true);
  255. }
  256. //------------------------------------------------------------------------------
  257. GFXTexHandle &InteriorLMManager::getHandle(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index)
  258. {
  259. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::getHandle: invalid interior handle");
  260. AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::getHandle: invalid instance handle");
  261. AssertFatal(index < mInteriors[interiorHandle]->mNumLightmaps, "InteriorLMManager::getHandle: invalid texture index");
  262. // valid? if not, then get base lightmap handle
  263. if(!mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index])
  264. {
  265. AssertFatal(mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index], "InteriorLMManager::getHandle: invalid base texture handle");
  266. return(mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index]);
  267. }
  268. return(mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index]);
  269. }
  270. GBitmap * InteriorLMManager::getBitmap(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index)
  271. {
  272. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::getBitmap: invalid interior handle");
  273. AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::getBitmap: invalid instance handle");
  274. AssertFatal(index < mInteriors[interiorHandle]->mNumLightmaps, "InteriorLMManager::getBitmap: invalid texture index");
  275. if(!mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index])
  276. {
  277. AssertFatal(mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index], "InteriorLMManager::getBitmap: invalid base texture handle");
  278. return(mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index]->getBitmap());
  279. }
  280. return(mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index]->getBitmap());
  281. }
  282. Vector<GFXTexHandle> & InteriorLMManager::getHandles(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle)
  283. {
  284. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::getHandles: invalid interior handle");
  285. AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::getHandles: invalid instance handle");
  286. return(mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles);
  287. }
  288. //------------------------------------------------------------------------------
  289. void InteriorLMManager::clearLightmaps(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle)
  290. {
  291. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::clearLightmaps: invalid interior handle");
  292. AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::clearLightmaps: invalid instance handle");
  293. for(U32 i = 0; i < mInteriors[interiorHandle]->mNumLightmaps; i++)
  294. mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[i] = 0;
  295. }
  296. //------------------------------------------------------------------------------
  297. GFXTexHandle &InteriorLMManager::duplicateBaseLightmap(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index)
  298. {
  299. AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::duplicateBaseLightmap: invalid interior handle");
  300. AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::duplicateBaseLightmap: invalid instance handle");
  301. AssertFatal(index < mInteriors[interiorHandle]->mNumLightmaps, "InteriorLMManager::duplicateBaseLightmap: invalid texture index");
  302. // already exists?
  303. GFXTexHandle texHandle = mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index];
  304. if(texHandle && texHandle->getBitmap() )
  305. return mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index];
  306. AssertFatal(mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index], "InteriorLMManager::duplicateBaseLightmap: invalid base handle");
  307. // copy it
  308. GBitmap * src = mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index]->getBitmap();
  309. GBitmap * dest = new GBitmap(*src);
  310. // don't want this texture to be downloaded yet (SceneLighting will take care of that)
  311. GFXTexHandle tHandle( dest, &GFXDefaultPersistentProfile, true, String("Interior Lightmap Handle 2") );
  312. mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index] = tHandle;
  313. return mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index];
  314. }