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

游戏引擎

开发平台:

C++ Builder

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