PageRenderTime 38ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llvlcomposition.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 501 lines | 349 code | 82 blank | 70 comment | 42 complexity | 1697b735e6dbc7192db1cb668bf2df48 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llvlcomposition.cpp
  3. * @brief Viewer-side representation of a composition layer...
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llvlcomposition.h"
  28. #include "imageids.h"
  29. #include "llerror.h"
  30. #include "v3math.h"
  31. #include "llsurface.h"
  32. #include "lltextureview.h"
  33. #include "llviewertexture.h"
  34. #include "llviewertexturelist.h"
  35. #include "llviewerregion.h"
  36. #include "noise.h"
  37. #include "llregionhandle.h" // for from_region_handle
  38. #include "llviewercontrol.h"
  39. F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F32 x_frac, const F32 y_frac)
  40. {
  41. // Not sure if this is the right math...
  42. // Take weighted average of all four points (bilinear interpolation)
  43. F32 result;
  44. const F32 inv_x_frac = 1.f - x_frac;
  45. const F32 inv_y_frac = 1.f - y_frac;
  46. result = inv_x_frac*inv_y_frac*v00
  47. + x_frac*inv_y_frac*v10
  48. + inv_x_frac*y_frac*v01
  49. + x_frac*y_frac*v11;
  50. return result;
  51. }
  52. LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) :
  53. LLViewerLayer(width, scale),
  54. mParamsReady(FALSE)
  55. {
  56. mSurfacep = surfacep;
  57. // Load Terrain Textures - Original ones
  58. setDetailTextureID(0, TERRAIN_DIRT_DETAIL);
  59. setDetailTextureID(1, TERRAIN_GRASS_DETAIL);
  60. setDetailTextureID(2, TERRAIN_MOUNTAIN_DETAIL);
  61. setDetailTextureID(3, TERRAIN_ROCK_DETAIL);
  62. // Initialize the texture matrix to defaults.
  63. for (S32 i = 0; i < CORNER_COUNT; ++i)
  64. {
  65. mStartHeight[i] = gSavedSettings.getF32("TerrainColorStartHeight");
  66. mHeightRange[i] = gSavedSettings.getF32("TerrainColorHeightRange");
  67. }
  68. mTexScaleX = 16.f;
  69. mTexScaleY = 16.f;
  70. mTexturesLoaded = FALSE;
  71. }
  72. LLVLComposition::~LLVLComposition()
  73. {
  74. }
  75. void LLVLComposition::setSurface(LLSurface *surfacep)
  76. {
  77. mSurfacep = surfacep;
  78. }
  79. void LLVLComposition::setDetailTextureID(S32 corner, const LLUUID& id)
  80. {
  81. if(id.isNull())
  82. {
  83. return;
  84. }
  85. mDetailTextures[corner] = LLViewerTextureManager::getFetchedTexture(id);
  86. mDetailTextures[corner]->setNoDelete() ;
  87. mRawImages[corner] = NULL;
  88. }
  89. BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
  90. const F32 width, const F32 height)
  91. {
  92. if (!mParamsReady)
  93. {
  94. // All the parameters haven't been set yet (we haven't gotten the message from the sim)
  95. return FALSE;
  96. }
  97. llassert(mSurfacep);
  98. if (!mSurfacep || !mSurfacep->getRegion())
  99. {
  100. // We don't always have the region yet here....
  101. return FALSE;
  102. }
  103. S32 x_begin, y_begin, x_end, y_end;
  104. x_begin = llround( x * mScaleInv );
  105. y_begin = llround( y * mScaleInv );
  106. x_end = llround( (x + width) * mScaleInv );
  107. y_end = llround( (y + width) * mScaleInv );
  108. if (x_end > mWidth)
  109. {
  110. x_end = mWidth;
  111. }
  112. if (y_end > mWidth)
  113. {
  114. y_end = mWidth;
  115. }
  116. LLVector3d origin_global = from_region_handle(mSurfacep->getRegion()->getHandle());
  117. // For perlin noise generation...
  118. const F32 slope_squared = 1.5f*1.5f;
  119. const F32 xyScale = 4.9215f; //0.93284f;
  120. const F32 zScale = 4; //0.92165f;
  121. const F32 z_offset = 0.f;
  122. const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus
  123. // simple height)
  124. // Heights map into textures as 0-1 = first, 1-2 = second, etc.
  125. // So we need to compress heights into this range.
  126. const S32 NUM_TEXTURES = 4;
  127. const F32 xyScaleInv = (1.f / xyScale);
  128. const F32 zScaleInv = (1.f / zScale);
  129. const F32 inv_width = 1.f/mWidth;
  130. // OK, for now, just have the composition value equal the height at the point.
  131. for (S32 j = y_begin; j < y_end; j++)
  132. {
  133. for (S32 i = x_begin; i < x_end; i++)
  134. {
  135. F32 vec[3];
  136. F32 vec1[3];
  137. F32 twiddle;
  138. // Bilinearly interpolate the start height and height range of the textures
  139. F32 start_height = bilinear(mStartHeight[SOUTHWEST],
  140. mStartHeight[SOUTHEAST],
  141. mStartHeight[NORTHWEST],
  142. mStartHeight[NORTHEAST],
  143. i*inv_width, j*inv_width); // These will be bilinearly interpolated
  144. F32 height_range = bilinear(mHeightRange[SOUTHWEST],
  145. mHeightRange[SOUTHEAST],
  146. mHeightRange[NORTHWEST],
  147. mHeightRange[NORTHEAST],
  148. i*inv_width, j*inv_width); // These will be bilinearly interpolated
  149. LLVector3 location(i*mScale, j*mScale, 0.f);
  150. F32 height = mSurfacep->resolveHeightRegion(location) + z_offset;
  151. // Step 0: Measure the exact height at this texel
  152. vec[0] = (F32)(origin_global.mdV[VX]+location.mV[VX])*xyScaleInv; // Adjust to non-integer lattice
  153. vec[1] = (F32)(origin_global.mdV[VY]+location.mV[VY])*xyScaleInv;
  154. vec[2] = height*zScaleInv;
  155. //
  156. // Choose material value by adding to the exact height a random value
  157. //
  158. vec1[0] = vec[0]*(0.2222222222f);
  159. vec1[1] = vec[1]*(0.2222222222f);
  160. vec1[2] = vec[2]*(0.2222222222f);
  161. twiddle = noise2(vec1)*6.5f; // Low freq component for large divisions
  162. twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component
  163. twiddle *= noise_magnitude;
  164. F32 scaled_noisy_height = (height + twiddle - start_height) * F32(NUM_TEXTURES) / height_range;
  165. scaled_noisy_height = llmax(0.f, scaled_noisy_height);
  166. scaled_noisy_height = llmin(3.f, scaled_noisy_height);
  167. *(mDatap + i + j*mWidth) = scaled_noisy_height;
  168. }
  169. }
  170. return TRUE;
  171. }
  172. static const U32 BASE_SIZE = 128;
  173. BOOL LLVLComposition::generateComposition()
  174. {
  175. if (!mParamsReady)
  176. {
  177. // All the parameters haven't been set yet (we haven't gotten the message from the sim)
  178. return FALSE;
  179. }
  180. for (S32 i = 0; i < 4; i++)
  181. {
  182. if (mDetailTextures[i]->getDiscardLevel() < 0)
  183. {
  184. mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); // in case we are at low detail
  185. mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE);
  186. return FALSE;
  187. }
  188. if ((mDetailTextures[i]->getDiscardLevel() != 0 &&
  189. (mDetailTextures[i]->getWidth() < BASE_SIZE ||
  190. mDetailTextures[i]->getHeight() < BASE_SIZE)))
  191. {
  192. S32 width = mDetailTextures[i]->getFullWidth();
  193. S32 height = mDetailTextures[i]->getFullHeight();
  194. S32 min_dim = llmin(width, height);
  195. S32 ddiscard = 0;
  196. while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
  197. {
  198. ddiscard++;
  199. min_dim /= 2;
  200. }
  201. mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); // in case we are at low detail
  202. mDetailTextures[i]->setMinDiscardLevel(ddiscard);
  203. return FALSE;
  204. }
  205. }
  206. return TRUE;
  207. }
  208. BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
  209. const F32 width, const F32 height)
  210. {
  211. llassert(mSurfacep);
  212. llassert(x >= 0.f);
  213. llassert(y >= 0.f);
  214. LLTimer gen_timer;
  215. ///////////////////////////
  216. //
  217. // Generate raw data arrays for surface textures
  218. //
  219. //
  220. // These have already been validated by generateComposition.
  221. U8* st_data[4];
  222. S32 st_data_size[4]; // for debugging
  223. for (S32 i = 0; i < 4; i++)
  224. {
  225. if (mRawImages[i].isNull())
  226. {
  227. // Read back a raw image for this discard level, if it exists
  228. S32 min_dim = llmin(mDetailTextures[i]->getFullWidth(), mDetailTextures[i]->getFullHeight());
  229. S32 ddiscard = 0;
  230. while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
  231. {
  232. ddiscard++;
  233. min_dim /= 2;
  234. }
  235. BOOL delete_raw = (mDetailTextures[i]->reloadRawImage(ddiscard) != NULL) ;
  236. if(mDetailTextures[i]->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later.
  237. {
  238. if(delete_raw)
  239. {
  240. mDetailTextures[i]->destroyRawImage() ;
  241. }
  242. lldebugs << "cached raw data for terrain detail texture is not ready yet: " << mDetailTextures[i]->getID() << llendl;
  243. return FALSE;
  244. }
  245. mRawImages[i] = mDetailTextures[i]->getRawImage() ;
  246. if(delete_raw)
  247. {
  248. mDetailTextures[i]->destroyRawImage() ;
  249. }
  250. if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE ||
  251. mDetailTextures[i]->getHeight(ddiscard) != BASE_SIZE ||
  252. mDetailTextures[i]->getComponents() != 3)
  253. {
  254. LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3);
  255. newraw->composite(mRawImages[i]);
  256. mRawImages[i] = newraw; // deletes old
  257. }
  258. }
  259. st_data[i] = mRawImages[i]->getData();
  260. st_data_size[i] = mRawImages[i]->getDataSize();
  261. }
  262. ///////////////////////////////////////
  263. //
  264. // Generate and clamp x/y bounding box.
  265. //
  266. //
  267. S32 x_begin, y_begin, x_end, y_end;
  268. x_begin = (S32)(x * mScaleInv);
  269. y_begin = (S32)(y * mScaleInv);
  270. x_end = llround( (x + width) * mScaleInv );
  271. y_end = llround( (y + width) * mScaleInv );
  272. if (x_end > mWidth)
  273. {
  274. llwarns << "x end > width" << llendl;
  275. x_end = mWidth;
  276. }
  277. if (y_end > mWidth)
  278. {
  279. llwarns << "y end > width" << llendl;
  280. y_end = mWidth;
  281. }
  282. ///////////////////////////////////////////
  283. //
  284. // Generate target texture information, stride ratios.
  285. //
  286. //
  287. LLViewerTexture *texturep;
  288. U32 tex_width, tex_height, tex_comps;
  289. U32 tex_stride;
  290. F32 tex_x_scalef, tex_y_scalef;
  291. S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end;
  292. F32 tex_x_ratiof, tex_y_ratiof;
  293. texturep = mSurfacep->getSTexture();
  294. tex_width = texturep->getWidth();
  295. tex_height = texturep->getHeight();
  296. tex_comps = texturep->getComponents();
  297. tex_stride = tex_width * tex_comps;
  298. U32 st_comps = 3;
  299. U32 st_width = BASE_SIZE;
  300. U32 st_height = BASE_SIZE;
  301. if (tex_comps != st_comps)
  302. {
  303. llwarns << "Base texture comps != input texture comps" << llendl;
  304. return FALSE;
  305. }
  306. tex_x_scalef = (F32)tex_width / (F32)mWidth;
  307. tex_y_scalef = (F32)tex_height / (F32)mWidth;
  308. tex_x_begin = (S32)((F32)x_begin * tex_x_scalef);
  309. tex_y_begin = (S32)((F32)y_begin * tex_y_scalef);
  310. tex_x_end = (S32)((F32)x_end * tex_x_scalef);
  311. tex_y_end = (S32)((F32)y_end * tex_y_scalef);
  312. tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width;
  313. tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height;
  314. LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
  315. U8 *rawp = raw->getData();
  316. F32 tex_width_inv = 1.f/tex_width;
  317. F32 tex_height_inv = 1.f/tex_height;
  318. F32 st_x_stride, st_y_stride;
  319. st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width);
  320. st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height);
  321. llassert(st_x_stride > 0.f);
  322. llassert(st_y_stride > 0.f);
  323. ////////////////////////////////
  324. //
  325. // Iterate through the target texture, striding through the
  326. // subtextures and interpolating appropriately.
  327. //
  328. //
  329. F32 sti, stj;
  330. S32 st_offset;
  331. sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width));
  332. stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height));
  333. st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps;
  334. for (S32 j = tex_y_begin; j < tex_y_end; j++)
  335. {
  336. U32 offset = j * tex_stride + tex_x_begin * tex_comps;
  337. sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width);
  338. for (S32 i = tex_x_begin; i < tex_x_end; i++)
  339. {
  340. S32 tex0, tex1;
  341. F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof);
  342. tex0 = llfloor( composition );
  343. tex0 = llclamp(tex0, 0, 3);
  344. composition -= tex0;
  345. tex1 = tex0 + 1;
  346. tex1 = llclamp(tex1, 0, 3);
  347. F32 xy_int_i, xy_int_j;
  348. xy_int_i = i * tex_width_inv;
  349. xy_int_j = j * tex_height_inv;
  350. st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps;
  351. for (U32 k = 0; k < tex_comps; k++)
  352. {
  353. // Linearly interpolate based on composition.
  354. if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1])
  355. {
  356. // SJB: This shouldn't be happening, but does... Rounding error?
  357. //llwarns << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << llendl;
  358. //llwarns << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << llendl;
  359. }
  360. else
  361. {
  362. F32 a = *(st_data[tex0] + st_offset);
  363. F32 b = *(st_data[tex1] + st_offset);
  364. rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) );
  365. }
  366. offset++;
  367. st_offset++;
  368. }
  369. sti += st_x_stride;
  370. if (sti >= st_width)
  371. {
  372. sti -= st_width;
  373. }
  374. }
  375. stj += st_y_stride;
  376. if (stj >= st_height)
  377. {
  378. stj -= st_height;
  379. }
  380. }
  381. if (!texturep->hasGLTexture())
  382. {
  383. texturep->createGLTexture(0, raw);
  384. }
  385. texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin);
  386. LLSurface::sTextureUpdateTime += gen_timer.getElapsedTimeF32();
  387. LLSurface::sTexelsUpdated += (tex_x_end - tex_x_begin) * (tex_y_end - tex_y_begin);
  388. for (S32 i = 0; i < 4; i++)
  389. {
  390. // Un-boost detatil textures (will get re-boosted if rendering in high detail)
  391. mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_NONE);
  392. mDetailTextures[i]->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1);
  393. }
  394. return TRUE;
  395. }
  396. LLUUID LLVLComposition::getDetailTextureID(S32 corner)
  397. {
  398. return mDetailTextures[corner]->getID();
  399. }
  400. LLViewerFetchedTexture* LLVLComposition::getDetailTexture(S32 corner)
  401. {
  402. return mDetailTextures[corner];
  403. }
  404. F32 LLVLComposition::getStartHeight(S32 corner)
  405. {
  406. return mStartHeight[corner];
  407. }
  408. void LLVLComposition::setStartHeight(S32 corner, const F32 start_height)
  409. {
  410. mStartHeight[corner] = start_height;
  411. }
  412. F32 LLVLComposition::getHeightRange(S32 corner)
  413. {
  414. return mHeightRange[corner];
  415. }
  416. void LLVLComposition::setHeightRange(S32 corner, const F32 range)
  417. {
  418. mHeightRange[corner] = range;
  419. }