lltextureatlas.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:10k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lltextureatlas.cpp
  3.  * @brief LLTextureAtlas class implementation.
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "linden_common.h"
  34. #include "llerror.h"
  35. #include "llimage.h"
  36. #include "llmath.h"
  37. #include "llgl.h"
  38. #include "llrender.h"
  39. #include "lltextureatlas.h"
  40. //-------------------
  41. S16 LLTextureAtlas::sMaxSubTextureSize = 64 ;
  42. S16 LLTextureAtlas::sSlotSize = 32 ;
  43. #ifndef DEBUG_ATLAS
  44. #define DEBUG_ATLAS 0
  45. #endif
  46. #ifndef DEBUG_USAGE_BITS
  47. #define DEBUG_USAGE_BITS 0
  48. #endif
  49. //**************************************************************************************************************
  50. LLTextureAtlas::LLTextureAtlas(U8 ncomponents, S16 atlas_dim) : 
  51.     LLViewerTexture(atlas_dim * sSlotSize, atlas_dim * sSlotSize, ncomponents, TRUE),
  52. mAtlasDim(atlas_dim),
  53. mNumSlotsReserved(0),
  54. mMaxSlotsInAtlas(atlas_dim * atlas_dim)
  55. {
  56. generateEmptyUsageBits() ;
  57. //generate an empty texture
  58. generateGLTexture() ;
  59. LLPointer<LLImageRaw> image_raw = new LLImageRaw(mFullWidth, mFullHeight, mComponents);
  60. createGLTexture(0, image_raw, 0);
  61. image_raw = NULL;
  62. }
  63. LLTextureAtlas::~LLTextureAtlas() 
  64. {
  65. if(mSpatialGroupList.size() > 0)
  66. {
  67. llerrs << "Not clean up the spatial groups!" << llendl ;
  68. }
  69. releaseUsageBits() ;
  70. }
  71. //virtual 
  72. S8 LLTextureAtlas::getType() const
  73. {
  74. return LLViewerTexture::ATLAS_TEXTURE ;
  75. }
  76. void LLTextureAtlas::getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yoffset)
  77. {
  78. xoffset = (F32)col / mAtlasDim ;
  79. yoffset = (F32)row / mAtlasDim ;
  80. }
  81. void LLTextureAtlas::getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale)
  82. {
  83. xscale = (F32)w / (mAtlasDim * sSlotSize) ;
  84. yscale = (F32)h / (mAtlasDim * sSlotSize) ;
  85. }
  86. //insert a texture piece into the atlas
  87. LLGLuint LLTextureAtlas::insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row)
  88. {
  89. if(!getTexName())
  90. {
  91. return 0 ;
  92. }
  93. S32 w = raw_image->getWidth() ;
  94. S32 h = raw_image->getHeight() ;
  95. if(w < 8 || w > sMaxSubTextureSize || h < 8 || h > sMaxSubTextureSize)
  96. {
  97. //size overflow
  98. return 0 ;
  99. }
  100. BOOL res = gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getTexName());
  101. if (!res) 
  102. {
  103. llerrs << "bindTexture failed" << llendl;
  104. }
  105. GLint xoffset = sSlotSize * slot_col ;
  106. GLint yoffset = sSlotSize * slot_row ;
  107. if(!source_gl_tex->preAddToAtlas(discard_level, raw_image))
  108. {
  109. return 0 ;
  110. }
  111. glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, TRUE);
  112. glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h,
  113. mGLTexturep->getPrimaryFormat(), mGLTexturep->getFormatType(), raw_image->getData());
  114. source_gl_tex->postAddToAtlas() ;
  115. return getTexName();
  116. }
  117. //release a sub-texture slot from the atlas
  118. void LLTextureAtlas::releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width)
  119. {
  120. unmarkUsageBits(slot_width, slot_col, slot_row) ;
  121. mNumSlotsReserved -= slot_width * slot_width ;
  122. }
  123. BOOL LLTextureAtlas::isEmpty() const 
  124. {
  125. return !mNumSlotsReserved ;
  126. }
  127. BOOL LLTextureAtlas::isFull(S8 to_be_reserved) const 
  128. {
  129. return mNumSlotsReserved + to_be_reserved > mMaxSlotsInAtlas ;
  130. }
  131. F32  LLTextureAtlas::getFullness() const 
  132. {
  133. return (F32)mNumSlotsReserved / mMaxSlotsInAtlas ;
  134. }
  135. void LLTextureAtlas::addSpatialGroup(LLSpatialGroup* groupp) 
  136. {
  137. if(groupp && !hasSpatialGroup(groupp))
  138. {
  139. mSpatialGroupList.push_back(groupp);
  140. }
  141. }
  142. void LLTextureAtlas::removeSpatialGroup(LLSpatialGroup* groupp) 
  143. {
  144. if(groupp)
  145. {
  146. mSpatialGroupList.remove(groupp);
  147. }
  148. }
  149. void LLTextureAtlas::clearSpatialGroup() 
  150. {
  151. mSpatialGroupList.clear();
  152. }
  153. void LLTextureAtlas::removeLastSpatialGroup() 
  154. {
  155. mSpatialGroupList.pop_back() ;
  156. }
  157. LLSpatialGroup* LLTextureAtlas::getLastSpatialGroup() 
  158. {
  159. if(mSpatialGroupList.size() > 0)
  160. {
  161. return mSpatialGroupList.back() ;
  162. }
  163. return NULL ;
  164. }
  165. BOOL LLTextureAtlas::hasSpatialGroup(LLSpatialGroup* groupp) 
  166. {
  167. for(std::list<LLSpatialGroup*>::iterator iter = mSpatialGroupList.begin(); iter != mSpatialGroupList.end() ; ++iter)
  168. {
  169. if(*iter == groupp)
  170. {
  171. return TRUE ;
  172. }
  173. }
  174. return FALSE ;
  175. }
  176. //--------------------------------------------------------------------------------------
  177. //private
  178. void LLTextureAtlas::generateEmptyUsageBits()
  179. {
  180. S32 col_len = (mAtlasDim + 7) >> 3 ;
  181. mUsageBits = new U8*[mAtlasDim] ;
  182. *mUsageBits = new U8[mAtlasDim * col_len] ;
  183. mUsageBits[0] = *mUsageBits ;
  184. for(S32 i = 1 ; i < mAtlasDim ; i++)
  185. {
  186.    mUsageBits[i] = mUsageBits[i-1] + col_len ;
  187.    for(S32 j = 0 ; j < col_len ; j++)
  188.    {
  189.    //init by 0 for all bits.
  190.    mUsageBits[i][j] = 0 ;
  191.    }
  192. }
  193. //do not forget mUsageBits[0]!
  194. for(S32 j = 0 ; j < col_len ; j++)
  195. {
  196. //init by 0 for all bits.
  197. mUsageBits[0][j] = 0 ;
  198. }
  199. mTestBits = NULL ;
  200. #if DEBUG_USAGE_BITS
  201. //------------
  202. //test
  203. mTestBits = new U8*[mAtlasDim] ;
  204. *mTestBits = new U8[mAtlasDim * mAtlasDim] ;
  205. mTestBits[0] = *mTestBits ;
  206. for(S32 i = 1 ; i < mAtlasDim ; i++)
  207. {
  208.    mTestBits[i] = mTestBits[i-1] + mAtlasDim ;
  209.    for(S32 j = 0 ; j < mAtlasDim ; j++)
  210.    {
  211.    //init by 0 for all bits.
  212.    mTestBits[i][j] = 0 ;
  213.    }
  214. }
  215. for(S32 j = 0 ; j < mAtlasDim ; j++)
  216. {
  217. //init by 0 for all bits.
  218. mTestBits[0][j] = 0 ;
  219. }
  220. #endif
  221. }
  222. void LLTextureAtlas::releaseUsageBits()
  223. {
  224.    if(mUsageBits)
  225.    {
  226.        delete[] *mUsageBits ;
  227.        delete[] mUsageBits ;
  228.    }
  229.    mUsageBits = NULL ;
  230.    //test
  231.    if( mTestBits)
  232.    {
  233.    delete[] *mTestBits;
  234.    delete[]  mTestBits;
  235.    }
  236.     mTestBits = NULL ;
  237. }
  238. void LLTextureAtlas::markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row)
  239. {
  240. S16 x = col >> 3 ;
  241. for(S8 i = 0 ; i < bits_len ; i++)
  242. {
  243. mUsageBits[row + i][x] |= mask ;
  244. }
  245. #if DEBUG_USAGE_BITS
  246. //test
  247. for(S8 i = row ; i < row + bits_len ; i++)
  248. {
  249. for(S8 j = col ; j < col + bits_len ; j++)
  250. {
  251. mTestBits[i][j] = 1 ;
  252. }
  253. }
  254. #endif
  255. }
  256. void LLTextureAtlas::unmarkUsageBits(S8 bits_len, S16 col, S16 row)
  257. {
  258. S16 x = col >> 3 ;
  259. U8  mask = 1 ;
  260. for(S8 i = 1 ; i < bits_len ; i++)
  261. {
  262. mask |= (1 << i) ;
  263. }
  264. mask <<= (col & 7) ;
  265. mask = ~mask ;
  266. for(S8 i = 0 ; i < bits_len ; i++)
  267. {
  268. mUsageBits[row + i][x] &= mask ;
  269. }
  270. #if DEBUG_USAGE_BITS
  271. //test
  272. for(S8 i = row ; i < row + bits_len ; i++)
  273. {
  274. for(S8 j = col ; j < col + bits_len ; j++)
  275. {
  276. mTestBits[i][j] = 0 ;
  277. }
  278. }
  279. #endif
  280. }
  281. //return true if any of bits in the range marked.
  282. BOOL LLTextureAtlas::areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row)
  283. {
  284. BOOL ret = FALSE ;
  285. S16 x = col >> 3 ;
  286. for(S8 i = 0 ; i < bits_len ; i++)
  287. {
  288. if(mUsageBits[row + i][x] & mask)
  289. {
  290. ret = TRUE ;
  291. break ;
  292. //return TRUE ;
  293. }
  294. }
  295. #if DEBUG_USAGE_BITS
  296. //test
  297. BOOL ret2 = FALSE ;
  298. for(S8 i = row ; i < row + bits_len ; i++)
  299. {
  300. for(S8 j = col ; j < col + bits_len ; j++)
  301. {
  302. if(mTestBits[i][j])
  303. {
  304. ret2 = TRUE ;
  305. }
  306. }
  307. }
  308. if(ret != ret2)
  309. {
  310. llerrs << "bits map corrupted." << llendl ;
  311. }
  312. #endif
  313. return ret ;//FALSE ;
  314. }
  315. //----------------------------------------------------------------------
  316. //
  317. //index order: Z order, i.e.: 
  318. // |-----|-----|-----|-----|
  319. // |  10 |  11 | 14  | 15  |
  320. // |-----|-----|-----|-----|
  321. // |   8 |   9 | 12  | 13  |
  322. // |-----|-----|-----|-----|
  323. // |   2 |   3 |   6 |   7 |
  324. // |-----|-----|-----|-----|
  325. // |   0 |   1 |   4 |   5 |
  326. // |-----|-----|-----|-----|
  327. void LLTextureAtlas::getPositionFromIndex(S16 index, S16& col, S16& row)
  328. {
  329. col = 0 ;
  330. row = 0 ;
  331. S16 index_copy = index ;
  332. for(S16 i = 0 ; index_copy && i < 16 ; i += 2)
  333. {
  334. col |= ((index & (1 << i)) >> i) << (i >> 1) ;
  335. row |= ((index & (1 << (i + 1))) >> (i + 1)) << (i >> 1) ;
  336. index_copy >>= 2 ;
  337. }
  338. }
  339. void LLTextureAtlas::getIndexFromPosition(S16 col, S16 row, S16& index)
  340. {
  341. index = 0 ;
  342. S16 col_copy = col ;
  343. S16 row_copy = row ;
  344. for(S16 i = 0 ; (col_copy || row_copy) && i < 16 ; i++)
  345. {
  346. index |= ((col & 1 << i) << i) | ((row & 1 << i) << ( i + 1)) ;
  347. col_copy >>= 1 ;
  348. row_copy >>= 1 ;
  349. }
  350. }
  351. //----------------------------------------------------------------------
  352. //return TRUE if succeeds.
  353. BOOL LLTextureAtlas::getNextAvailableSlot(S8 bits_len, S16& col, S16& row)
  354. {
  355.     S16 index_step = bits_len * bits_len ;
  356.     U8 mask = 1 ;
  357. for(S8 i = 1 ; i < bits_len ; i++)
  358. {
  359. mask |= (1 << i) ;
  360. }
  361.    
  362. U8 cur_mask ;
  363. for(S16 index = 0 ; index < mMaxSlotsInAtlas ; index += index_step)
  364.     {
  365. getPositionFromIndex(index, col, row) ;
  366. cur_mask = mask << (col & 7) ;
  367. if(!areUsageBitsMarked(bits_len, cur_mask, col, row))
  368. {
  369. markUsageBits(bits_len, cur_mask, col, row) ;
  370. mNumSlotsReserved += bits_len * bits_len ;
  371. return TRUE ;
  372. }
  373.     }
  374.    return FALSE ;
  375. }