/indra/newview/llvosurfacepatch.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 1108 lines · 846 code · 176 blank · 86 comment · 98 complexity · b05355290d673137284204883a987731 MD5 · raw file

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