llvosurfacepatch.cpp 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. /**
  2. * @file llvosurfacepatch.cpp
  3. * @brief Viewer-object derived "surface patch", which is a piece of terrain
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, 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 "llvosurfacepatch.h"
  34. #include "llfasttimer.h"
  35. #include "llprimitive.h"
  36. #include "lldrawable.h"
  37. #include "lldrawpoolterrain.h"
  38. #include "llface.h"
  39. #include "llpipeline.h"
  40. #include "llsky.h"
  41. #include "llspatialpartition.h"
  42. #include "llsurfacepatch.h"
  43. #include "llsurface.h"
  44. #include "llviewerobjectlist.h"
  45. #include "llviewershadermgr.h"
  46. #include "llvlcomposition.h"
  47. #include "llvovolume.h"
  48. F32 LLVOSurfacePatch::sLODFactor = 1.f;
  49. ///////////////////////////////////////////////////////////////////////////////
  50. // LLTerrainPartition class (declared in llspatialpartition.h)
  51. ///////////////////////////////////////////////////////////////////////////////
  52. LLTerrainPartition::LLTerrainPartition(LLViewerRegion* regionp)
  53. : LLSpatialPartition(gUsePBRShaders ? LLDrawPoolTerrain::VERTEX_DATA_MASK_PBR
  54. : LLDrawPoolTerrain::VERTEX_DATA_MASK,
  55. false, regionp)
  56. {
  57. mOcclusionEnabled = false;
  58. mInfiniteFarClip = true;
  59. mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN;
  60. mPartitionType = LLViewerRegion::PARTITION_TERRAIN;
  61. }
  62. //virtual
  63. LLVertexBuffer* LLTerrainPartition::createVertexBuffer(U32 type_mask)
  64. {
  65. LLVertexBuffer* bufferp;
  66. if (gUsePBRShaders)
  67. {
  68. bufferp = new LLVertexBuffer(type_mask | LLVertexBuffer::MAP_TANGENT);
  69. }
  70. else
  71. {
  72. // Note: texture coordinates 2 and 3 exist, but use the same data as
  73. // texture coordinate 1
  74. constexpr U32 typemask = LLVertexBuffer::MAP_VERTEX |
  75. LLVertexBuffer::MAP_NORMAL |
  76. LLVertexBuffer::MAP_TEXCOORD0 |
  77. LLVertexBuffer::MAP_TEXCOORD1 |
  78. LLVertexBuffer::MAP_COLOR;
  79. bufferp = new LLVertexBuffer(typemask);
  80. // Mask out coordinates 2 and 3 in the mask passed to
  81. // setupVertexBuffer() (this used to be done via a virtual method in
  82. // a LLVertexBufferTerrain() derived class). HB
  83. bufferp->setTypeMaskMask(LLVertexBuffer::MAP_TEXCOORD2 |
  84. LLVertexBuffer::MAP_TEXCOORD3);
  85. }
  86. #if LL_DEBUG_VB_ALLOC
  87. bufferp->setOwner("LLTerrainPartition");
  88. #endif
  89. return bufferp;
  90. }
  91. //virtual
  92. void LLTerrainPartition::getGeometry(LLSpatialGroup* groupp)
  93. {
  94. LL_FAST_TIMER(FTM_REBUILD_TERRAIN_VB);
  95. LLVertexBuffer* bufferp = groupp->mVertexBuffer;
  96. // Get vertex buffer striders
  97. LLStrider<LLVector3> vertices, normals;
  98. LLStrider<LLVector2> texcoords, texcoords2;
  99. LLStrider<U16> indices;
  100. if (!bufferp || !bufferp->getVertexStrider(vertices) ||
  101. !bufferp->getNormalStrider(normals) ||
  102. !bufferp->getTexCoord0Strider(texcoords) ||
  103. !bufferp->getTexCoord1Strider(texcoords2) ||
  104. !bufferp->getIndexStrider(indices))
  105. {
  106. return;
  107. }
  108. // For PBR terrain only
  109. LLStrider<LLVector4a> tangents;
  110. if (gUsePBRShaders && !bufferp->getTangentStrider(tangents))
  111. {
  112. return;
  113. }
  114. LLStrider<LLVector3> vertices0_orig, normals_orig;
  115. LLStrider<LLVector2> texcoords_orig;
  116. LLStrider<U16> indices_orig;
  117. bool has_tangents = gUsePBRShaders && tangents.get() != NULL;
  118. if (has_tangents)
  119. {
  120. vertices0_orig = vertices;
  121. normals_orig = normals;
  122. texcoords_orig = texcoords;
  123. indices_orig = indices;
  124. }
  125. U32 indices_index = 0;
  126. U32 index_offset = 0;
  127. for (S32 i = 0, count = mFaceList.size(); i < count; ++i)
  128. {
  129. LLFace* facep = mFaceList[i];
  130. if (!facep) continue; // Paranoia
  131. facep->setIndicesIndex(indices_index);
  132. facep->setGeomIndex(index_offset);
  133. facep->setVertexBuffer(bufferp);
  134. LLVOSurfacePatch* patchp = (LLVOSurfacePatch*)facep->getViewerObject();
  135. patchp->getTerrainGeometry(vertices, normals, texcoords, texcoords2,
  136. indices);
  137. indices_index += facep->getIndicesCount();
  138. index_offset += facep->getGeomCount();
  139. }
  140. // For PBR terrain only
  141. if (has_tangents)
  142. {
  143. LLVector4a* verts = new LLVector4a[index_offset];
  144. LLVector4a* norms = new LLVector4a[index_offset];
  145. LLVector4a* tgts = new LLVector4a[index_offset];
  146. std::vector<LLVector2> tcoords(indices_index);
  147. for (U32 i = 0; i < index_offset; ++i)
  148. {
  149. F32* vertp = vertices0_orig[i].mV;
  150. verts[i] = LLVector4a(vertp[0], vertp[1], vertp[2], 1.f);
  151. F32* normp = normals_orig[i].mV;
  152. norms[i] = LLVector4a(normp[0], normp[1], normp[2], 1.f);
  153. tgts[i] = tangents[i];
  154. tcoords[i] = texcoords_orig[i];
  155. }
  156. std::vector<U16> inds(indices_index);
  157. for (U32 i = 0; i < indices_index; ++i)
  158. {
  159. inds[i] = indices_orig[i];
  160. }
  161. calculate_tangent_array(index_offset, verts, norms, tcoords.data(),
  162. indices_index / 3, inds.data(), tgts);
  163. for (U32 i = 0; i < index_offset; ++i)
  164. {
  165. tangents[i] = tgts[i];
  166. }
  167. delete[] verts;
  168. delete[] norms;
  169. delete[] tgts;
  170. }
  171. bufferp->unmapBuffer();
  172. mFaceList.clear();
  173. }
  174. ///////////////////////////////////////////////////////////////////////////////
  175. // LLVOSurfacePatch class
  176. ///////////////////////////////////////////////////////////////////////////////
  177. LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID& id, LLViewerRegion* regionp)
  178. : LLStaticViewerObject(id, LL_VO_SURFACE_PATCH, regionp),
  179. mDirtiedPatch(false),
  180. mPool(NULL),
  181. mBaseComp(0),
  182. mPatchp(NULL),
  183. mDirtyTexture(false),
  184. mDirtyTerrain(false),
  185. mLastNorthStride(0),
  186. mLastEastStride(0),
  187. mLastStride(0),
  188. mLastLength(0)
  189. {
  190. // Terrain must draw during selection passes so it can block objects behind
  191. // it.
  192. mCanSelect = true;
  193. // Hack for setting scale for bounding boxes/visibility.
  194. setScale(LLVector3(16.f, 16.f, 16.f));
  195. }
  196. //virtual
  197. LLVOSurfacePatch::~LLVOSurfacePatch()
  198. {
  199. mPatchp = NULL;
  200. }
  201. //virtual
  202. void LLVOSurfacePatch::markDead()
  203. {
  204. if (mPatchp)
  205. {
  206. mPatchp->clearVObj();
  207. mPatchp = NULL;
  208. }
  209. LLViewerObject::markDead();
  210. }
  211. //virtual
  212. void LLVOSurfacePatch::setPixelAreaAndAngle()
  213. {
  214. mAppAngle = 50;
  215. mPixelArea = 500 * 500;
  216. }
  217. LLFacePool* LLVOSurfacePatch::getPool()
  218. {
  219. mPool =
  220. (LLDrawPoolTerrain*)gPipeline.getPool(LLDrawPool::POOL_TERRAIN,
  221. mPatchp->getSurface()->getSTexture());
  222. return mPool;
  223. }
  224. //virtual
  225. LLDrawable* LLVOSurfacePatch::createDrawable()
  226. {
  227. gPipeline.allocDrawable(this);
  228. mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TERRAIN);
  229. mBaseComp = llfloor(mPatchp->getMinComposition());
  230. S32 min_comp = llfloor(mPatchp->getMinComposition());
  231. S32 max_comp = llceil(mPatchp->getMaxComposition());
  232. if (max_comp - min_comp + 1 > 3 &&
  233. mPatchp->getMinComposition() - min_comp >
  234. max_comp - mPatchp->getMaxComposition())
  235. {
  236. // The top side runs over more
  237. ++mBaseComp;
  238. }
  239. mDrawable->addFace(getPool(), NULL);
  240. return mDrawable;
  241. }
  242. //virtual
  243. void LLVOSurfacePatch::updateGL()
  244. {
  245. if (mPatchp)
  246. {
  247. mPatchp->updateGL();
  248. }
  249. }
  250. //virtual
  251. bool LLVOSurfacePatch::updateGeometry(LLDrawable* drawable)
  252. {
  253. LL_FAST_TIMER(FTM_UPDATE_TERRAIN);
  254. dirtySpatialGroup();
  255. S32 min_comp = lltrunc(mPatchp->getMinComposition());
  256. S32 max_comp = lltrunc(ceil(mPatchp->getMaxComposition()));
  257. // Pick the two closest detail textures for this patch then create the draw
  258. // pool for it. Actually, should get the average composition instead of the
  259. // center.
  260. S32 new_base_comp = lltrunc(mPatchp->getMinComposition());
  261. if (max_comp - min_comp + 1 > 3 &&
  262. mPatchp->getMinComposition() - min_comp >
  263. max_comp - mPatchp->getMaxComposition())
  264. {
  265. // The top side runs over more
  266. ++new_base_comp;
  267. }
  268. mBaseComp = new_base_comp;
  269. // Figure out the strides
  270. mLastStride = mPatchp->getRenderStride();
  271. mLastLength = mPatchp->getSurface()->getGridsPerPatchEdge() / mLastStride;
  272. if (mPatchp->getNeighborPatch(NORTH))
  273. {
  274. mLastNorthStride = mPatchp->getNeighborPatch(NORTH)->getRenderStride();
  275. }
  276. else
  277. {
  278. mLastNorthStride = mLastStride;
  279. }
  280. if (mPatchp->getNeighborPatch(EAST))
  281. {
  282. mLastEastStride = mPatchp->getNeighborPatch(EAST)->getRenderStride();
  283. }
  284. else
  285. {
  286. mLastEastStride = mLastStride;
  287. }
  288. return true;
  289. }
  290. //virtual
  291. void LLVOSurfacePatch::updateFaceSize(S32 idx)
  292. {
  293. if (idx)
  294. {
  295. llwarns << "Terrain partition requested invalid face !" << llendl;
  296. return;
  297. }
  298. LLFace* facep = mDrawable->getFace(idx);
  299. if (!facep)
  300. {
  301. return;
  302. }
  303. S32 num_vertices = 0;
  304. S32 num_indices = 0;
  305. if (mLastStride)
  306. {
  307. getGeomSizesMain(mLastStride, num_vertices, num_indices);
  308. getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices,
  309. num_indices);
  310. getGeomSizesEast(mLastStride, mLastEastStride, num_vertices,
  311. num_indices);
  312. }
  313. facep->setSize(num_vertices, num_indices);
  314. }
  315. void LLVOSurfacePatch::getTerrainGeometry(LLStrider<LLVector3>& verticesp,
  316. LLStrider<LLVector3>& normalsp,
  317. LLStrider<LLVector2>& tex_coords0p,
  318. LLStrider<LLVector2>& tex_coords1p,
  319. LLStrider<U16>& indicesp)
  320. {
  321. LLFace* facep = mDrawable->getFace(0);
  322. if (facep)
  323. {
  324. U32 index_offset = facep->getGeomIndex();
  325. updateMainGeometry(facep, verticesp, normalsp, tex_coords0p,
  326. tex_coords1p, indicesp, index_offset);
  327. updateNorthGeometry(facep, verticesp, normalsp, tex_coords0p,
  328. tex_coords1p, indicesp, index_offset);
  329. updateEastGeometry(facep, verticesp, normalsp, tex_coords0p,
  330. tex_coords1p, indicesp, index_offset);
  331. }
  332. }
  333. void LLVOSurfacePatch::updateMainGeometry(LLFace* facep,
  334. LLStrider<LLVector3>& verticesp,
  335. LLStrider<LLVector3>& normalsp,
  336. LLStrider<LLVector2>& tex_coords0p,
  337. LLStrider<LLVector2>& tex_coords1p,
  338. LLStrider<U16>& indicesp,
  339. U32& index_offset)
  340. {
  341. llassert(mLastStride > 0);
  342. U32 render_stride = mLastStride;
  343. U32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
  344. S32 vert_size = patch_size / render_stride;
  345. // Render the main patch
  346. U32 index;
  347. S32 num_vertices = 0;
  348. S32 num_indices = 0;
  349. // First, figure out how many vertices we need...
  350. getGeomSizesMain(render_stride, num_vertices, num_indices);
  351. if (num_vertices > 0)
  352. {
  353. facep->mCenterAgent = mPatchp->getPointAgent(8, 8);
  354. // Generate patch points first
  355. for (S32 j = 0; j < vert_size; ++j)
  356. {
  357. for (S32 i = 0; i < vert_size; ++i)
  358. {
  359. S32 x = i * render_stride;
  360. S32 y = j * render_stride;
  361. mPatchp->eval(x, y, render_stride, verticesp.get(),
  362. normalsp.get(), tex_coords0p.get(),
  363. tex_coords1p.get());
  364. verticesp++;
  365. normalsp++;
  366. tex_coords0p++;
  367. tex_coords1p++;
  368. }
  369. }
  370. for (S32 j = 0; j < vert_size - 1; ++j)
  371. {
  372. if (j % 2)
  373. {
  374. for (S32 i = vert_size - 1; i > 0; --i)
  375. {
  376. index = (i - 1) + j * vert_size;
  377. *(indicesp++) = index_offset + index;
  378. index = i + (j + 1) * vert_size;
  379. *(indicesp++) = index_offset + index;
  380. index = (i - 1) + (j + 1) * vert_size;
  381. *(indicesp++) = index_offset + index;
  382. index = (i - 1) + j * vert_size;
  383. *(indicesp++) = index_offset + index;
  384. index = i + j * vert_size;
  385. *(indicesp++) = index_offset + index;
  386. index = i + (j + 1) * vert_size;
  387. *(indicesp++) = index_offset + index;
  388. }
  389. }
  390. else
  391. {
  392. for (S32 i = 0; i < vert_size - 1; ++i)
  393. {
  394. index = i + j * vert_size;
  395. *(indicesp++) = index_offset + index;
  396. index = (i + 1) + (j + 1) * vert_size;
  397. *(indicesp++) = index_offset + index;
  398. index = i + (j + 1) * vert_size;
  399. *(indicesp++) = index_offset + index;
  400. index = i + j * vert_size;
  401. *(indicesp++) = index_offset + index;
  402. index = (i + 1) + j * vert_size;
  403. *(indicesp++) = index_offset + index;
  404. index = (i + 1) + (j + 1) * vert_size;
  405. *(indicesp++) = index_offset + index;
  406. }
  407. }
  408. }
  409. }
  410. index_offset += num_vertices;
  411. }
  412. void LLVOSurfacePatch::updateNorthGeometry(LLFace* facep,
  413. LLStrider<LLVector3>& verticesp,
  414. LLStrider<LLVector3>& normalsp,
  415. LLStrider<LLVector2>& tex_coords0p,
  416. LLStrider<LLVector2>& tex_coords1p,
  417. LLStrider<U16>& indicesp,
  418. U32& index_offset)
  419. {
  420. S32 num_vertices;
  421. U32 render_stride = mLastStride;
  422. S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
  423. S32 length = patch_size / render_stride;
  424. S32 half_length = length / 2;
  425. U32 north_stride = mLastNorthStride;
  426. // Render the north strip
  427. // Stride lengths are the same
  428. if (north_stride == render_stride)
  429. {
  430. num_vertices = 2 * length + 1;
  431. facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) +
  432. mPatchp->getPointAgent(8, 16)) * 0.5f;
  433. // Main patch
  434. for (S32 i = 0; i < length; ++i)
  435. {
  436. S32 x = i * render_stride;
  437. S32 y = 16 - render_stride;
  438. mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(),
  439. tex_coords0p.get(), tex_coords1p.get());
  440. verticesp++;
  441. normalsp++;
  442. tex_coords0p++;
  443. tex_coords1p++;
  444. }
  445. // North patch
  446. for (S32 i = 0; i <= length; ++i)
  447. {
  448. S32 x = i * render_stride;
  449. mPatchp->eval(x, 16, render_stride, verticesp.get(),
  450. normalsp.get(), tex_coords0p.get(),
  451. tex_coords1p.get());
  452. verticesp++;
  453. normalsp++;
  454. tex_coords0p++;
  455. tex_coords1p++;
  456. }
  457. for (S32 i = 0; i < length; ++i)
  458. {
  459. // Generate indices
  460. *(indicesp++) = index_offset + i;
  461. *(indicesp++) = index_offset + length + i + 1;
  462. *(indicesp++) = index_offset + length + i;
  463. if (i != length - 1)
  464. {
  465. *(indicesp++) = index_offset + i;
  466. *(indicesp++) = index_offset + i + 1;
  467. *(indicesp++) = index_offset + length + i + 1;
  468. }
  469. }
  470. }
  471. else if (north_stride > render_stride)
  472. {
  473. // North stride is longer (has less vertices)
  474. num_vertices = length + length / 2 + 1;
  475. facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) +
  476. mPatchp->getPointAgent(8, 16)) * 0.5f;
  477. // Iterate through this patch's points
  478. for (S32 i = 0; i < length; ++i)
  479. {
  480. S32 x = i * render_stride;
  481. S32 y = 16 - render_stride;
  482. mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(),
  483. tex_coords0p.get(), tex_coords1p.get());
  484. verticesp++;
  485. normalsp++;
  486. tex_coords0p++;
  487. tex_coords1p++;
  488. }
  489. // Iterate through the north patch's points
  490. for (S32 i = 0; i <= length; i += 2)
  491. {
  492. S32 x = i * render_stride;
  493. mPatchp->eval(x, 16, render_stride, verticesp.get(),
  494. normalsp.get(), tex_coords0p.get(),
  495. tex_coords1p.get());
  496. verticesp++;
  497. normalsp++;
  498. tex_coords0p++;
  499. tex_coords1p++;
  500. }
  501. for (S32 i = 0; i < length; ++i)
  502. {
  503. if (!(i % 2))
  504. {
  505. *(indicesp++) = index_offset + i;
  506. *(indicesp++) = index_offset + i + 1;
  507. *(indicesp++) = index_offset + length + i / 2;
  508. *(indicesp++) = index_offset + i + 1;
  509. *(indicesp++) = index_offset + length + i / 2 + 1;
  510. *(indicesp++) = index_offset + length + i / 2;
  511. }
  512. else if (i < (length - 1))
  513. {
  514. *(indicesp++) = index_offset + i;
  515. *(indicesp++) = index_offset + i + 1;
  516. *(indicesp++) = index_offset + length + i / 2 + 1;
  517. }
  518. }
  519. }
  520. else
  521. {
  522. // North stride is shorter (more vertices)
  523. length = patch_size / north_stride;
  524. half_length = length / 2;
  525. num_vertices = length + half_length + 1;
  526. facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) +
  527. mPatchp->getPointAgent(16, 8)) * 0.5f;
  528. // Iterate through this patch's points
  529. for (S32 i = 0; i < length; i += 2)
  530. {
  531. S32 x = i * north_stride;
  532. S32 y = 16 - render_stride;
  533. mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(),
  534. tex_coords0p.get(), tex_coords1p.get());
  535. verticesp++;
  536. normalsp++;
  537. tex_coords0p++;
  538. tex_coords1p++;
  539. }
  540. // Iterate through the north patch's points
  541. for (S32 i = 0; i <= length; ++i)
  542. {
  543. S32 x = i * north_stride;
  544. mPatchp->eval(x, 16, render_stride, verticesp.get(),
  545. normalsp.get(), tex_coords0p.get(),
  546. tex_coords1p.get());
  547. verticesp++;
  548. normalsp++;
  549. tex_coords0p++;
  550. tex_coords1p++;
  551. }
  552. for (S32 i = 0; i < length; ++i)
  553. {
  554. if (!(i % 2))
  555. {
  556. *(indicesp++) = index_offset + half_length + i;
  557. *(indicesp++) = index_offset + i / 2;
  558. *(indicesp++) = index_offset + half_length + i + 1;
  559. }
  560. else if (i < length - 2)
  561. {
  562. *(indicesp++) = index_offset + half_length + i;
  563. *(indicesp++) = index_offset + i / 2;
  564. *(indicesp++) = index_offset + i / 2 + 1;
  565. *(indicesp++) = index_offset + half_length + i;
  566. *(indicesp++) = index_offset + i / 2 + 1;
  567. *(indicesp++) = index_offset + half_length + i + 1;
  568. }
  569. else
  570. {
  571. *(indicesp++) = index_offset + half_length + i;
  572. *(indicesp++) = index_offset + i / 2;
  573. *(indicesp++) = index_offset + half_length + i + 1;
  574. }
  575. }
  576. }
  577. index_offset += num_vertices;
  578. }
  579. void LLVOSurfacePatch::updateEastGeometry(LLFace* facep,
  580. LLStrider<LLVector3>& verticesp,
  581. LLStrider<LLVector3>& normalsp,
  582. LLStrider<LLVector2>& tex_coords0p,
  583. LLStrider<LLVector2>& tex_coords1p,
  584. LLStrider<U16>& indicesp,
  585. U32& index_offset)
  586. {
  587. S32 num_vertices;
  588. U32 render_stride = mLastStride;
  589. S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
  590. S32 length = patch_size / render_stride;
  591. S32 half_length = length / 2;
  592. U32 east_stride = mLastEastStride;
  593. // Stride lengths are the same
  594. if (east_stride == render_stride)
  595. {
  596. num_vertices = 2 * length + 1;
  597. facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) +
  598. mPatchp->getPointAgent(8, 16)) * 0.5f;
  599. // Main patch
  600. for (S32 i = 0; i < length; ++i)
  601. {
  602. S32 x = 16 - render_stride;
  603. S32 y = i * render_stride;
  604. mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(),
  605. tex_coords0p.get(), tex_coords1p.get());
  606. verticesp++;
  607. normalsp++;
  608. tex_coords0p++;
  609. tex_coords1p++;
  610. }
  611. // East patch
  612. for (S32 i = 0; i <= length; ++i)
  613. {
  614. S32 y = i * render_stride;
  615. mPatchp->eval(16, y, render_stride, verticesp.get(),
  616. normalsp.get(), tex_coords0p.get(),
  617. tex_coords1p.get());
  618. verticesp++;
  619. normalsp++;
  620. tex_coords0p++;
  621. tex_coords1p++;
  622. }
  623. for (S32 i = 0; i < length; ++i)
  624. {
  625. // Generate indices
  626. *(indicesp++) = index_offset + i;
  627. *(indicesp++) = index_offset + length + i;
  628. *(indicesp++) = index_offset + length + i + 1;
  629. if (i != length - 1)
  630. {
  631. *(indicesp++) = index_offset + i;
  632. *(indicesp++) = index_offset + length + i + 1;
  633. *(indicesp++) = index_offset + i + 1;
  634. }
  635. }
  636. }
  637. else if (east_stride > render_stride)
  638. {
  639. // East stride is longer (has less vertices)
  640. num_vertices = length + half_length + 1;
  641. facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) +
  642. mPatchp->getPointAgent(8, 16)) * 0.5f;
  643. // Iterate through this patch's points
  644. for (S32 i = 0; i < length; ++i)
  645. {
  646. S32 x = 16 - render_stride;
  647. S32 y = i * render_stride;
  648. mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(),
  649. tex_coords0p.get(), tex_coords1p.get());
  650. verticesp++;
  651. normalsp++;
  652. tex_coords0p++;
  653. tex_coords1p++;
  654. }
  655. // Iterate through the east patch's points
  656. for (S32 i = 0; i <= length; i += 2)
  657. {
  658. S32 y = i * render_stride;
  659. mPatchp->eval(16, y, render_stride, verticesp.get(),
  660. normalsp.get(), tex_coords0p.get(),
  661. tex_coords1p.get());
  662. verticesp++;
  663. normalsp++;
  664. tex_coords0p++;
  665. tex_coords1p++;
  666. }
  667. for (S32 i = 0; i < length; ++i)
  668. {
  669. if (!(i % 2))
  670. {
  671. *(indicesp++) = index_offset + i;
  672. *(indicesp++) = index_offset + length + i / 2;
  673. *(indicesp++) = index_offset + i + 1;
  674. *(indicesp++) = index_offset + i + 1;
  675. *(indicesp++) = index_offset + length + i / 2;
  676. *(indicesp++) = index_offset + length + i / 2 + 1;
  677. }
  678. else if (i < (length - 1))
  679. {
  680. *(indicesp++) = index_offset + i;
  681. *(indicesp++) = index_offset + length + i / 2 + 1;
  682. *(indicesp++) = index_offset + i + 1;
  683. }
  684. }
  685. }
  686. else
  687. {
  688. // East stride is shorter (more vertices)
  689. length = patch_size / east_stride;
  690. half_length = length / 2;
  691. num_vertices = length + length / 2 + 1;
  692. facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) +
  693. mPatchp->getPointAgent(16, 8)) * 0.5f;
  694. // Iterate through this patch's points
  695. for (S32 i = 0; i < length; i += 2)
  696. {
  697. S32 x = 16 - render_stride;
  698. S32 y = i * east_stride;
  699. mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(),
  700. tex_coords0p.get(), tex_coords1p.get());
  701. verticesp++;
  702. normalsp++;
  703. tex_coords0p++;
  704. tex_coords1p++;
  705. }
  706. // Iterate through the east patch's points
  707. for (S32 i = 0; i <= length; ++i)
  708. {
  709. S32 y = i * east_stride;
  710. mPatchp->eval(16, y, render_stride, verticesp.get(),
  711. normalsp.get(), tex_coords0p.get(),
  712. tex_coords1p.get());
  713. verticesp++;
  714. normalsp++;
  715. tex_coords0p++;
  716. tex_coords1p++;
  717. }
  718. for (S32 i = 0; i < length; ++i)
  719. {
  720. if (!(i % 2))
  721. {
  722. *(indicesp++) = index_offset + half_length + i;
  723. *(indicesp++) = index_offset + half_length + i + 1;
  724. *(indicesp++) = index_offset + i / 2;
  725. }
  726. else if (i < length - 2)
  727. {
  728. *(indicesp++) = index_offset + half_length + i;
  729. *(indicesp++) = index_offset + i / 2 + 1;
  730. *(indicesp++) = index_offset + i / 2;
  731. *(indicesp++) = index_offset + half_length + i;
  732. *(indicesp++) = index_offset + half_length + i + 1;
  733. *(indicesp++) = index_offset + i / 2 + 1;
  734. }
  735. else
  736. {
  737. *(indicesp++) = index_offset + half_length + i;
  738. *(indicesp++) = index_offset + half_length + i + 1;
  739. *(indicesp++) = index_offset + i / 2;
  740. }
  741. }
  742. }
  743. index_offset += num_vertices;
  744. }
  745. void LLVOSurfacePatch::setPatch(LLSurfacePatch* patchp)
  746. {
  747. mPatchp = patchp;
  748. dirtyPatch();
  749. }
  750. void LLVOSurfacePatch::dirtyPatch()
  751. {
  752. mDirtiedPatch = true;
  753. dirtyGeom();
  754. mDirtyTerrain = true;
  755. LLVector3 center = mPatchp->getCenterRegion();
  756. LLSurface* surfacep = mPatchp->getSurface();
  757. setPositionRegion(center);
  758. F32 scale_factor = surfacep->getGridsPerPatchEdge() *
  759. surfacep->getMetersPerGrid();
  760. setScale(LLVector3(scale_factor, scale_factor,
  761. mPatchp->getMaxZ() - mPatchp->getMinZ()));
  762. }
  763. void LLVOSurfacePatch::dirtyGeom()
  764. {
  765. if (mDrawable)
  766. {
  767. gPipeline.markRebuild(mDrawable);
  768. LLFace* facep = mDrawable->getFace(0);
  769. if (facep)
  770. {
  771. facep->setVertexBuffer(NULL);
  772. }
  773. mDrawable->movePartition();
  774. }
  775. }
  776. void LLVOSurfacePatch::getGeomSizesMain(S32 stride, S32& num_vertices,
  777. S32& num_indices)
  778. {
  779. S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
  780. // First, figure out how many vertices we need...
  781. S32 vert_size = patch_size / stride;
  782. if (vert_size >= 2)
  783. {
  784. num_vertices += vert_size * vert_size;
  785. num_indices += 6 * (vert_size - 1) * (vert_size - 1);
  786. }
  787. }
  788. void LLVOSurfacePatch::getGeomSizesNorth(S32 stride, S32 north_stride,
  789. S32& num_vertices, S32& num_indices)
  790. {
  791. S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
  792. S32 length = patch_size / stride;
  793. // Stride lengths are the same
  794. if (north_stride == stride)
  795. {
  796. num_vertices += 2 * length + 1;
  797. num_indices += length * 6 - 3;
  798. }
  799. else if (north_stride > stride)
  800. {
  801. // North stride is longer (has less vertices)
  802. num_vertices += length + length / 2 + 1;
  803. num_indices += (length / 2) * 9 - 3;
  804. }
  805. else
  806. {
  807. // North stride is shorter (more vertices)
  808. length = patch_size / north_stride;
  809. num_vertices += length + length / 2 + 1;
  810. num_indices += 9 * (length / 2) - 3;
  811. }
  812. }
  813. void LLVOSurfacePatch::getGeomSizesEast(S32 stride, S32 east_stride,
  814. S32& num_vertices, S32& num_indices)
  815. {
  816. S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
  817. S32 length = patch_size / stride;
  818. // Stride lengths are the same
  819. if (east_stride == stride)
  820. {
  821. num_vertices += 2 * length + 1;
  822. num_indices += length * 6 - 3;
  823. }
  824. else if (east_stride > stride)
  825. {
  826. // East stride is longer (has less vertices)
  827. num_vertices += length + length / 2 + 1;
  828. num_indices += (length / 2) * 9 - 3;
  829. }
  830. else
  831. {
  832. // East stride is shorter (more vertices)
  833. length = patch_size / east_stride;
  834. num_vertices += length + length / 2 + 1;
  835. num_indices += 9* (length / 2) - 3;
  836. }
  837. }
  838. bool LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start,
  839. const LLVector4a& end, S32 face,
  840. bool pick_transparent,
  841. bool pick_rigged, S32* face_hitp,
  842. LLVector4a* intersection,
  843. LLVector2* tex_coord,
  844. LLVector4a* normal,
  845. LLVector4a* tangent)
  846. {
  847. if (!lineSegmentBoundingBox(start, end))
  848. {
  849. return false;
  850. }
  851. LLVector4a da;
  852. da.setSub(end, start);
  853. LLVector3 delta(da.getF32ptr());
  854. LLVector3 pdelta = delta;
  855. pdelta.mV[2] = 0;
  856. F32 plength = pdelta.length();
  857. F32 tdelta = plength != 0.f ? 1.f / plength : F32_MAX / 10000.f;
  858. LLVector3 v_start(start.getF32ptr());
  859. LLVector3 origin = v_start - mRegionp->getOriginAgent();
  860. if (mRegionp->getLandHeightRegion(origin) > origin.mV[2])
  861. {
  862. // Origin is under ground, treat as no intersection
  863. return false;
  864. }
  865. // Step one meter at a time until intersection point found
  866. // VECTORIZE THIS
  867. const LLVector4a* exta = mDrawable->getSpatialExtents();
  868. LLVector3 ext[2];
  869. ext[0].set(exta[0].getF32ptr());
  870. ext[1].set(exta[1].getF32ptr());
  871. F32 rad = (delta * tdelta).lengthSquared();
  872. F32 t = 0.f;
  873. while (t <= 1.f)
  874. {
  875. LLVector3 sample = origin + delta * t;
  876. if (AABBSphereIntersectR2(ext[0], ext[1],
  877. sample + mRegionp->getOriginAgent(),
  878. rad))
  879. {
  880. F32 height = mRegionp->getLandHeightRegion(sample);
  881. if (height > sample.mV[2])
  882. {
  883. // Ray went below ground, positive intersection. Quick and
  884. // dirty binary search to get impact point.
  885. tdelta = -tdelta * 0.5f;
  886. F32 err_dist = 0.001f;
  887. F32 dist = fabsf(sample.mV[2] - height);
  888. while (dist > err_dist && tdelta * tdelta > 0.f)
  889. {
  890. t += tdelta;
  891. sample = origin + delta * t;
  892. height = mRegionp->getLandHeightRegion(sample);
  893. if ((tdelta < 0 && height < sample.mV[2]) ||
  894. (height > sample.mV[2] && tdelta > 0))
  895. { // jumped over intersection point, go back
  896. tdelta = -tdelta;
  897. }
  898. tdelta *= 0.5f;
  899. dist = fabsf(sample.mV[2] - height);
  900. }
  901. if (intersection)
  902. {
  903. F32 height = mRegionp->getLandHeightRegion(sample);
  904. if (fabsf(sample.mV[2] - height) < delta.length() * tdelta)
  905. {
  906. sample.mV[2] = mRegionp->getLandHeightRegion(sample);
  907. }
  908. intersection->load3((sample + mRegionp->getOriginAgent()).mV);
  909. }
  910. if (normal)
  911. {
  912. normal->load3((mRegionp->getLand().resolveNormalGlobal(mRegionp->getPosGlobalFromRegion(sample))).mV);
  913. }
  914. return true;
  915. }
  916. }
  917. t += tdelta;
  918. if (t > 1 && t < 1.f + tdelta * 0.99f)
  919. {
  920. // Make sure end point is checked (saves vertical lines coming up
  921. // negative)
  922. t = 1.f;
  923. }
  924. }
  925. return false;
  926. }
  927. void LLVOSurfacePatch::updateSpatialExtents(LLVector4a& new_min,
  928. LLVector4a& new_max)
  929. {
  930. LLVector3 posAgent = getPositionAgent();
  931. LLVector3 scale = getScale();
  932. // Make z-axis scale at least 1 to avoid shadow artifacts on totally flat
  933. // land
  934. scale.mV[VZ] = llmax(scale.mV[VZ], 1.f);
  935. // Changing to 2.f makes the culling a -little- better, but still wrong
  936. new_min.load3((posAgent - scale * 0.5f).mV);
  937. new_max.load3((posAgent + scale * 0.5f).mV);
  938. LLVector4a pos;
  939. pos.setAdd(new_min, new_max);
  940. pos.mul(0.5f);
  941. mDrawable->setPositionGroup(pos);
  942. }