PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llvotree.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1296 lines | 959 code | 234 blank | 103 comment | 87 complexity | eaace767def6319f7ec9aa09e3a32f90 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llvotree.cpp
  3. * @brief LLVOTree class implementation
  4. *
  5. * $LicenseInfo:firstyear=2002&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 "llvotree.h"
  28. #include "lldrawpooltree.h"
  29. #include "llviewercontrol.h"
  30. #include "lldir.h"
  31. #include "llprimitive.h"
  32. #include "lltree_common.h"
  33. #include "llxmltree.h"
  34. #include "material_codes.h"
  35. #include "object_flags.h"
  36. #include "llagentcamera.h"
  37. #include "lldrawable.h"
  38. #include "llface.h"
  39. #include "llviewercamera.h"
  40. #include "llviewertexturelist.h"
  41. #include "llviewerobjectlist.h"
  42. #include "llviewerregion.h"
  43. #include "llworld.h"
  44. #include "noise.h"
  45. #include "pipeline.h"
  46. #include "llspatialpartition.h"
  47. #include "llnotificationsutil.h"
  48. #include "raytrace.h"
  49. #include "llglslshader.h"
  50. extern LLPipeline gPipeline;
  51. const S32 MAX_SLICES = 32;
  52. const F32 LEAF_LEFT = 0.52f;
  53. const F32 LEAF_RIGHT = 0.98f;
  54. const F32 LEAF_TOP = 1.0f;
  55. const F32 LEAF_BOTTOM = 0.52f;
  56. const F32 LEAF_WIDTH = 1.f;
  57. const S32 LLVOTree::sMAX_NUM_TREE_LOD_LEVELS = 4 ;
  58. S32 LLVOTree::sLODVertexOffset[sMAX_NUM_TREE_LOD_LEVELS];
  59. S32 LLVOTree::sLODVertexCount[sMAX_NUM_TREE_LOD_LEVELS];
  60. S32 LLVOTree::sLODIndexOffset[sMAX_NUM_TREE_LOD_LEVELS];
  61. S32 LLVOTree::sLODIndexCount[sMAX_NUM_TREE_LOD_LEVELS];
  62. S32 LLVOTree::sLODSlices[sMAX_NUM_TREE_LOD_LEVELS] = {10, 5, 4, 3};
  63. F32 LLVOTree::sLODAngles[sMAX_NUM_TREE_LOD_LEVELS] = {30.f, 20.f, 15.f, F_ALMOST_ZERO};
  64. F32 LLVOTree::sTreeFactor = 1.f;
  65. LLVOTree::SpeciesMap LLVOTree::sSpeciesTable;
  66. S32 LLVOTree::sMaxTreeSpecies = 0;
  67. // Tree variables and functions
  68. LLVOTree::LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp):
  69. LLViewerObject(id, pcode, regionp)
  70. {
  71. mSpecies = 0;
  72. mFrameCount = 0;
  73. mWind = mRegionp->mWind.getVelocity(getPositionRegion());
  74. mTrunkLOD = 0;
  75. }
  76. LLVOTree::~LLVOTree()
  77. {
  78. if (mData)
  79. {
  80. delete[] mData;
  81. mData = NULL;
  82. }
  83. }
  84. //static
  85. bool LLVOTree::isTreeRenderingStopped()
  86. {
  87. return LLVOTree::sTreeFactor < LLVOTree::sLODAngles[sMAX_NUM_TREE_LOD_LEVELS - 1] ;
  88. }
  89. // static
  90. void LLVOTree::initClass()
  91. {
  92. std::string xml_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"trees.xml");
  93. LLXmlTree tree_def_tree;
  94. if (!tree_def_tree.parseFile(xml_filename))
  95. {
  96. llerrs << "Failed to parse tree file." << llendl;
  97. }
  98. LLXmlTreeNode* rootp = tree_def_tree.getRoot();
  99. for (LLXmlTreeNode* tree_def = rootp->getFirstChild();
  100. tree_def;
  101. tree_def = rootp->getNextChild())
  102. {
  103. if (!tree_def->hasName("tree"))
  104. {
  105. llwarns << "Invalid tree definition node " << tree_def->getName() << llendl;
  106. continue;
  107. }
  108. F32 F32_val;
  109. LLUUID id;
  110. S32 S32_val;
  111. BOOL success = TRUE;
  112. S32 species;
  113. static LLStdStringHandle species_id_string = LLXmlTree::addAttributeString("species_id");
  114. if (!tree_def->getFastAttributeS32(species_id_string, species))
  115. {
  116. llwarns << "No species id defined" << llendl;
  117. continue;
  118. }
  119. if (species < 0)
  120. {
  121. llwarns << "Invalid species id " << species << llendl;
  122. continue;
  123. }
  124. if (sSpeciesTable.count(species))
  125. {
  126. llwarns << "Tree species " << species << " already defined! Duplicate discarded." << llendl;
  127. continue;
  128. }
  129. TreeSpeciesData* newTree = new TreeSpeciesData();
  130. static LLStdStringHandle texture_id_string = LLXmlTree::addAttributeString("texture_id");
  131. success &= tree_def->getFastAttributeUUID(texture_id_string, id);
  132. newTree->mTextureID = id;
  133. static LLStdStringHandle droop_string = LLXmlTree::addAttributeString("droop");
  134. success &= tree_def->getFastAttributeF32(droop_string, F32_val);
  135. newTree->mDroop = F32_val;
  136. static LLStdStringHandle twist_string = LLXmlTree::addAttributeString("twist");
  137. success &= tree_def->getFastAttributeF32(twist_string, F32_val);
  138. newTree->mTwist = F32_val;
  139. static LLStdStringHandle branches_string = LLXmlTree::addAttributeString("branches");
  140. success &= tree_def->getFastAttributeF32(branches_string, F32_val);
  141. newTree->mBranches = F32_val;
  142. static LLStdStringHandle depth_string = LLXmlTree::addAttributeString("depth");
  143. success &= tree_def->getFastAttributeS32(depth_string, S32_val);
  144. newTree->mDepth = S32_val;
  145. static LLStdStringHandle scale_step_string = LLXmlTree::addAttributeString("scale_step");
  146. success &= tree_def->getFastAttributeF32(scale_step_string, F32_val);
  147. newTree->mScaleStep = F32_val;
  148. static LLStdStringHandle trunk_depth_string = LLXmlTree::addAttributeString("trunk_depth");
  149. success &= tree_def->getFastAttributeS32(trunk_depth_string, S32_val);
  150. newTree->mTrunkDepth = S32_val;
  151. static LLStdStringHandle branch_length_string = LLXmlTree::addAttributeString("branch_length");
  152. success &= tree_def->getFastAttributeF32(branch_length_string, F32_val);
  153. newTree->mBranchLength = F32_val;
  154. static LLStdStringHandle trunk_length_string = LLXmlTree::addAttributeString("trunk_length");
  155. success &= tree_def->getFastAttributeF32(trunk_length_string, F32_val);
  156. newTree->mTrunkLength = F32_val;
  157. static LLStdStringHandle leaf_scale_string = LLXmlTree::addAttributeString("leaf_scale");
  158. success &= tree_def->getFastAttributeF32(leaf_scale_string, F32_val);
  159. newTree->mLeafScale = F32_val;
  160. static LLStdStringHandle billboard_scale_string = LLXmlTree::addAttributeString("billboard_scale");
  161. success &= tree_def->getFastAttributeF32(billboard_scale_string, F32_val);
  162. newTree->mBillboardScale = F32_val;
  163. static LLStdStringHandle billboard_ratio_string = LLXmlTree::addAttributeString("billboard_ratio");
  164. success &= tree_def->getFastAttributeF32(billboard_ratio_string, F32_val);
  165. newTree->mBillboardRatio = F32_val;
  166. static LLStdStringHandle trunk_aspect_string = LLXmlTree::addAttributeString("trunk_aspect");
  167. success &= tree_def->getFastAttributeF32(trunk_aspect_string, F32_val);
  168. newTree->mTrunkAspect = F32_val;
  169. static LLStdStringHandle branch_aspect_string = LLXmlTree::addAttributeString("branch_aspect");
  170. success &= tree_def->getFastAttributeF32(branch_aspect_string, F32_val);
  171. newTree->mBranchAspect = F32_val;
  172. static LLStdStringHandle leaf_rotate_string = LLXmlTree::addAttributeString("leaf_rotate");
  173. success &= tree_def->getFastAttributeF32(leaf_rotate_string, F32_val);
  174. newTree->mRandomLeafRotate = F32_val;
  175. static LLStdStringHandle noise_mag_string = LLXmlTree::addAttributeString("noise_mag");
  176. success &= tree_def->getFastAttributeF32(noise_mag_string, F32_val);
  177. newTree->mNoiseMag = F32_val;
  178. static LLStdStringHandle noise_scale_string = LLXmlTree::addAttributeString("noise_scale");
  179. success &= tree_def->getFastAttributeF32(noise_scale_string, F32_val);
  180. newTree->mNoiseScale = F32_val;
  181. static LLStdStringHandle taper_string = LLXmlTree::addAttributeString("taper");
  182. success &= tree_def->getFastAttributeF32(taper_string, F32_val);
  183. newTree->mTaper = F32_val;
  184. static LLStdStringHandle repeat_z_string = LLXmlTree::addAttributeString("repeat_z");
  185. success &= tree_def->getFastAttributeF32(repeat_z_string, F32_val);
  186. newTree->mRepeatTrunkZ = F32_val;
  187. sSpeciesTable[species] = newTree;
  188. if (species >= sMaxTreeSpecies) sMaxTreeSpecies = species + 1;
  189. if (!success)
  190. {
  191. std::string name;
  192. static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
  193. tree_def->getFastAttributeString(name_string, name);
  194. llwarns << "Incomplete definition of tree " << name << llendl;
  195. }
  196. }
  197. BOOL have_all_trees = TRUE;
  198. std::string err;
  199. for (S32 i=0;i<sMaxTreeSpecies;++i)
  200. {
  201. if (!sSpeciesTable.count(i))
  202. {
  203. err.append(llformat(" %d",i));
  204. have_all_trees = FALSE;
  205. }
  206. }
  207. if (!have_all_trees)
  208. {
  209. LLSD args;
  210. args["SPECIES"] = err;
  211. LLNotificationsUtil::add("ErrorUndefinedTrees", args);
  212. }
  213. };
  214. //static
  215. void LLVOTree::cleanupClass()
  216. {
  217. std::for_each(sSpeciesTable.begin(), sSpeciesTable.end(), DeletePairedPointer());
  218. }
  219. U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys,
  220. void **user_data,
  221. U32 block_num, EObjectUpdateType update_type,
  222. LLDataPacker *dp)
  223. {
  224. // Do base class updates...
  225. U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
  226. if ( (getVelocity().lengthSquared() > 0.f)
  227. ||(getAcceleration().lengthSquared() > 0.f)
  228. ||(getAngularVelocity().lengthSquared() > 0.f))
  229. {
  230. llinfos << "ACK! Moving tree!" << llendl;
  231. setVelocity(LLVector3::zero);
  232. setAcceleration(LLVector3::zero);
  233. setAngularVelocity(LLVector3::zero);
  234. }
  235. if (update_type == OUT_TERSE_IMPROVED)
  236. {
  237. // Nothing else needs to be done for the terse message.
  238. return retval;
  239. }
  240. //
  241. // Load Instance-Specific data
  242. //
  243. if (mData)
  244. {
  245. mSpecies = ((U8 *)mData)[0];
  246. }
  247. if (!sSpeciesTable.count(mSpecies))
  248. {
  249. if (sSpeciesTable.size())
  250. {
  251. SpeciesMap::const_iterator it = sSpeciesTable.begin();
  252. mSpecies = (*it).first;
  253. }
  254. }
  255. //
  256. // Load Species-Specific data
  257. //
  258. static const S32 MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = 32 ; //frames.
  259. mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
  260. mTreeImagep->setMaxVirtualSizeResetInterval(MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); //allow to wait for at most 16 frames to reset virtual size.
  261. mBranchLength = sSpeciesTable[mSpecies]->mBranchLength;
  262. mTrunkLength = sSpeciesTable[mSpecies]->mTrunkLength;
  263. mLeafScale = sSpeciesTable[mSpecies]->mLeafScale;
  264. mDroop = sSpeciesTable[mSpecies]->mDroop;
  265. mTwist = sSpeciesTable[mSpecies]->mTwist;
  266. mBranches = sSpeciesTable[mSpecies]->mBranches;
  267. mDepth = sSpeciesTable[mSpecies]->mDepth;
  268. mScaleStep = sSpeciesTable[mSpecies]->mScaleStep;
  269. mTrunkDepth = sSpeciesTable[mSpecies]->mTrunkDepth;
  270. mBillboardScale = sSpeciesTable[mSpecies]->mBillboardScale;
  271. mBillboardRatio = sSpeciesTable[mSpecies]->mBillboardRatio;
  272. mTrunkAspect = sSpeciesTable[mSpecies]->mTrunkAspect;
  273. mBranchAspect = sSpeciesTable[mSpecies]->mBranchAspect;
  274. // position change not caused by us, etc. make sure to rebuild.
  275. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL);
  276. return retval;
  277. }
  278. BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
  279. {
  280. if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE)))
  281. {
  282. return TRUE;
  283. }
  284. S32 trunk_LOD = sMAX_NUM_TREE_LOD_LEVELS ;
  285. F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor;
  286. for (S32 j = 0; j < sMAX_NUM_TREE_LOD_LEVELS; j++)
  287. {
  288. if (app_angle > LLVOTree::sLODAngles[j])
  289. {
  290. trunk_LOD = j;
  291. break;
  292. }
  293. }
  294. if (mReferenceBuffer.isNull())
  295. {
  296. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
  297. }
  298. else if (trunk_LOD != mTrunkLOD)
  299. {
  300. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, FALSE);
  301. }
  302. else
  303. {
  304. // we're not animating but we may *still* need to
  305. // regenerate the mesh if we moved, since position
  306. // and rotation are baked into the mesh.
  307. // *TODO: I don't know what's so special about trees
  308. // that they don't get REBUILD_POSITION automatically
  309. // at a higher level.
  310. const LLVector3 &this_position = getPositionAgent();
  311. if (this_position != mLastPosition)
  312. {
  313. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION);
  314. mLastPosition = this_position;
  315. }
  316. else
  317. {
  318. const LLQuaternion &this_rotation = getRotation();
  319. if (this_rotation != mLastRotation)
  320. {
  321. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION);
  322. mLastRotation = this_rotation;
  323. }
  324. }
  325. }
  326. mTrunkLOD = trunk_LOD;
  327. return TRUE;
  328. }
  329. const F32 TREE_BLEND_MIN = 1.f;
  330. const F32 TREE_BLEND_RANGE = 1.f;
  331. void LLVOTree::render(LLAgent &agent)
  332. {
  333. }
  334. void LLVOTree::setPixelAreaAndAngle(LLAgent &agent)
  335. {
  336. LLVector3 center = getPositionAgent();//center of tree.
  337. LLVector3 viewer_pos_agent = gAgentCamera.getCameraPositionAgent();
  338. LLVector3 lookAt = center - viewer_pos_agent;
  339. F32 dist = lookAt.normVec() ;
  340. F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ;
  341. F32 range = dist - getMinScale()/2;
  342. if (range < F_ALMOST_ZERO || isHUDAttachment()) // range == zero
  343. {
  344. mAppAngle = 180.f;
  345. }
  346. else
  347. {
  348. mAppAngle = (F32) atan2( getMaxScale(), range) * RAD_TO_DEG;
  349. }
  350. F32 max_scale = mBillboardScale * getMaxScale();
  351. F32 area = max_scale * (max_scale*mBillboardRatio);
  352. // Compute pixels per meter at the given range
  353. F32 pixels_per_meter = LLViewerCamera::getInstance()->getViewHeightInPixels() / (tan(LLViewerCamera::getInstance()->getView()) * dist);
  354. mPixelArea = pixels_per_meter * pixels_per_meter * area ;
  355. F32 importance = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ;
  356. mPixelArea = LLFace::adjustPixelArea(importance, mPixelArea) ;
  357. if (mPixelArea > LLViewerCamera::getInstance()->getScreenPixelArea())
  358. {
  359. mAppAngle = 180.f;
  360. }
  361. #if 0
  362. // mAppAngle is a bit of voodoo;
  363. // use the one calculated LLViewerObject::setPixelAreaAndAngle above
  364. // to avoid LOD miscalculations
  365. mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG;
  366. #endif
  367. }
  368. void LLVOTree::updateTextures()
  369. {
  370. if (mTreeImagep)
  371. {
  372. if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
  373. {
  374. setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea)));
  375. }
  376. mTreeImagep->addTextureStats(mPixelArea);
  377. }
  378. }
  379. LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline)
  380. {
  381. pipeline->allocDrawable(this);
  382. mDrawable->setLit(FALSE);
  383. mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TREE);
  384. LLDrawPoolTree *poolp = (LLDrawPoolTree*) gPipeline.getPool(LLDrawPool::POOL_TREE, mTreeImagep);
  385. // Just a placeholder for an actual object...
  386. LLFace *facep = mDrawable->addFace(poolp, mTreeImagep);
  387. facep->setSize(1, 3);
  388. updateRadius();
  389. return mDrawable;
  390. }
  391. // Yes, I know this is bad. I'll clean this up soon. - djs 04/02/02
  392. const S32 LEAF_INDICES = 24;
  393. const S32 LEAF_VERTICES = 16;
  394. static LLFastTimer::DeclareTimer FTM_UPDATE_TREE("Update Tree");
  395. BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
  396. {
  397. LLFastTimer ftm(FTM_UPDATE_TREE);
  398. if(mTrunkLOD >= sMAX_NUM_TREE_LOD_LEVELS) //do not display the tree.
  399. {
  400. mReferenceBuffer = NULL ;
  401. mDrawable->getFace(0)->setVertexBuffer(NULL);
  402. return TRUE ;
  403. }
  404. if (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer())
  405. {
  406. const F32 SRR3 = 0.577350269f; // sqrt(1/3)
  407. const F32 SRR2 = 0.707106781f; // sqrt(1/2)
  408. U32 i, j;
  409. U32 slices = MAX_SLICES;
  410. S32 max_indices = LEAF_INDICES;
  411. S32 max_vertices = LEAF_VERTICES;
  412. S32 lod;
  413. LLFace *face = drawable->getFace(0);
  414. face->mCenterAgent = getPositionAgent();
  415. face->mCenterLocal = face->mCenterAgent;
  416. for (lod = 0; lod < sMAX_NUM_TREE_LOD_LEVELS; lod++)
  417. {
  418. slices = sLODSlices[lod];
  419. sLODVertexOffset[lod] = max_vertices;
  420. sLODVertexCount[lod] = slices*slices;
  421. sLODIndexOffset[lod] = max_indices;
  422. sLODIndexCount[lod] = (slices-1)*(slices-1)*6;
  423. max_indices += sLODIndexCount[lod];
  424. max_vertices += sLODVertexCount[lod];
  425. }
  426. mReferenceBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, 0);
  427. mReferenceBuffer->allocateBuffer(max_vertices, max_indices, TRUE);
  428. LLStrider<LLVector3> vertices;
  429. LLStrider<LLVector3> normals;
  430. LLStrider<LLVector2> tex_coords;
  431. LLStrider<U16> indicesp;
  432. mReferenceBuffer->getVertexStrider(vertices);
  433. mReferenceBuffer->getNormalStrider(normals);
  434. mReferenceBuffer->getTexCoord0Strider(tex_coords);
  435. mReferenceBuffer->getIndexStrider(indicesp);
  436. S32 vertex_count = 0;
  437. S32 index_count = 0;
  438. // First leaf
  439. *(normals++) = LLVector3(-SRR2, -SRR2, 0.f);
  440. *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
  441. *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f);
  442. vertex_count++;
  443. *(normals++) = LLVector3(SRR3, -SRR3, SRR3);
  444. *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
  445. *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
  446. vertex_count++;
  447. *(normals++) = LLVector3(-SRR3, -SRR3, SRR3);
  448. *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
  449. *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
  450. vertex_count++;
  451. *(normals++) = LLVector3(SRR2, -SRR2, 0.f);
  452. *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
  453. *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f);
  454. vertex_count++;
  455. *(indicesp++) = 0;
  456. index_count++;
  457. *(indicesp++) = 1;
  458. index_count++;
  459. *(indicesp++) = 2;
  460. index_count++;
  461. *(indicesp++) = 0;
  462. index_count++;
  463. *(indicesp++) = 3;
  464. index_count++;
  465. *(indicesp++) = 1;
  466. index_count++;
  467. // Same leaf, inverse winding/normals
  468. *(normals++) = LLVector3(-SRR2, SRR2, 0.f);
  469. *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
  470. *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f);
  471. vertex_count++;
  472. *(normals++) = LLVector3(SRR3, SRR3, SRR3);
  473. *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
  474. *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
  475. vertex_count++;
  476. *(normals++) = LLVector3(-SRR3, SRR3, SRR3);
  477. *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
  478. *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
  479. vertex_count++;
  480. *(normals++) = LLVector3(SRR2, SRR2, 0.f);
  481. *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
  482. *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f);
  483. vertex_count++;
  484. *(indicesp++) = 4;
  485. index_count++;
  486. *(indicesp++) = 6;
  487. index_count++;
  488. *(indicesp++) = 5;
  489. index_count++;
  490. *(indicesp++) = 4;
  491. index_count++;
  492. *(indicesp++) = 5;
  493. index_count++;
  494. *(indicesp++) = 7;
  495. index_count++;
  496. // next leaf
  497. *(normals++) = LLVector3(SRR2, -SRR2, 0.f);
  498. *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
  499. *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f);
  500. vertex_count++;
  501. *(normals++) = LLVector3(SRR3, SRR3, SRR3);
  502. *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
  503. *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);
  504. vertex_count++;
  505. *(normals++) = LLVector3(SRR3, -SRR3, SRR3);
  506. *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
  507. *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);
  508. vertex_count++;
  509. *(normals++) = LLVector3(SRR2, SRR2, 0.f);
  510. *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
  511. *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f);
  512. vertex_count++;
  513. *(indicesp++) = 8;
  514. index_count++;
  515. *(indicesp++) = 9;
  516. index_count++;
  517. *(indicesp++) = 10;
  518. index_count++;
  519. *(indicesp++) = 8;
  520. index_count++;
  521. *(indicesp++) = 11;
  522. index_count++;
  523. *(indicesp++) = 9;
  524. index_count++;
  525. // other side of same leaf
  526. *(normals++) = LLVector3(-SRR2, -SRR2, 0.f);
  527. *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
  528. *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f);
  529. vertex_count++;
  530. *(normals++) = LLVector3(-SRR3, SRR3, SRR3);
  531. *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
  532. *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);
  533. vertex_count++;
  534. *(normals++) = LLVector3(-SRR3, -SRR3, SRR3);
  535. *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
  536. *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);
  537. vertex_count++;
  538. *(normals++) = LLVector3(-SRR2, SRR2, 0.f);
  539. *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
  540. *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f);
  541. vertex_count++;
  542. *(indicesp++) = 12;
  543. index_count++;
  544. *(indicesp++) = 14;
  545. index_count++;
  546. *(indicesp++) = 13;
  547. index_count++;
  548. *(indicesp++) = 12;
  549. index_count++;
  550. *(indicesp++) = 13;
  551. index_count++;
  552. *(indicesp++) = 15;
  553. index_count++;
  554. // Generate geometry for the cylinders
  555. // Different LOD's
  556. // Generate the vertices
  557. // Generate the indices
  558. for (lod = 0; lod < sMAX_NUM_TREE_LOD_LEVELS; lod++)
  559. {
  560. slices = sLODSlices[lod];
  561. F32 base_radius = 0.65f;
  562. F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper;
  563. //llinfos << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << llendl;
  564. //llinfos << "Droop " << mDroop << ", branchlength: " << mBranchLength << llendl;
  565. F32 angle = 0;
  566. F32 angle_inc = 360.f/(slices-1);
  567. F32 z = 0.f;
  568. F32 z_inc = 1.f;
  569. if (slices > 3)
  570. {
  571. z_inc = 1.f/(slices - 3);
  572. }
  573. F32 radius = base_radius;
  574. F32 x1,y1;
  575. F32 noise_scale = sSpeciesTable[mSpecies]->mNoiseMag;
  576. LLVector3 nvec;
  577. const F32 cap_nudge = 0.1f; // Height to 'peak' the caps on top/bottom of branch
  578. const S32 fractal_depth = 5;
  579. F32 nvec_scale = 1.f * sSpeciesTable[mSpecies]->mNoiseScale;
  580. F32 nvec_scalez = 4.f * sSpeciesTable[mSpecies]->mNoiseScale;
  581. F32 tex_z_repeat = sSpeciesTable[mSpecies]->mRepeatTrunkZ;
  582. F32 start_radius;
  583. F32 nangle = 0;
  584. F32 height = 1.f;
  585. F32 r0;
  586. for (i = 0; i < slices; i++)
  587. {
  588. if (i == 0)
  589. {
  590. z = - cap_nudge;
  591. r0 = 0.0;
  592. }
  593. else if (i == (slices - 1))
  594. {
  595. z = 1.f + cap_nudge;//((i - 2) * z_inc) + cap_nudge;
  596. r0 = 0.0;
  597. }
  598. else
  599. {
  600. z = (i - 1) * z_inc;
  601. r0 = base_radius + (top_radius - base_radius)*z;
  602. }
  603. for (j = 0; j < slices; j++)
  604. {
  605. if (slices - 1 == j)
  606. {
  607. angle = 0.f;
  608. }
  609. else
  610. {
  611. angle = j*angle_inc;
  612. }
  613. nangle = angle;
  614. x1 = cos(angle * DEG_TO_RAD);
  615. y1 = sin(angle * DEG_TO_RAD);
  616. LLVector2 tc;
  617. // This isn't totally accurate. Should compute based on slope as well.
  618. start_radius = r0 * (1.f + 1.2f*fabs(z - 0.66f*height)/height);
  619. nvec.set( cos(nangle * DEG_TO_RAD)*start_radius*nvec_scale,
  620. sin(nangle * DEG_TO_RAD)*start_radius*nvec_scale,
  621. z*nvec_scalez);
  622. // First and last slice at 0 radius (to bring in top/bottom of structure)
  623. radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale;
  624. if (slices - 1 == j)
  625. {
  626. // Not 0.5 for slight slop factor to avoid edges on leaves
  627. tc = LLVector2(0.490f, (1.f - z/2.f)*tex_z_repeat);
  628. }
  629. else
  630. {
  631. tc = LLVector2((angle/360.f)*0.5f, (1.f - z/2.f)*tex_z_repeat);
  632. }
  633. *(vertices++) = LLVector3(x1*radius, y1*radius, z);
  634. *(normals++) = LLVector3(x1, y1, 0.f);
  635. *(tex_coords++) = tc;
  636. vertex_count++;
  637. }
  638. }
  639. for (i = 0; i < (slices - 1); i++)
  640. {
  641. for (j = 0; j < (slices - 1); j++)
  642. {
  643. S32 x1_offset = j+1;
  644. if ((j+1) == slices)
  645. {
  646. x1_offset = 0;
  647. }
  648. // Generate the matching quads
  649. *(indicesp) = j + (i*slices) + sLODVertexOffset[lod];
  650. llassert(*(indicesp) < (U32)max_vertices);
  651. indicesp++;
  652. index_count++;
  653. *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod];
  654. llassert(*(indicesp) < (U32)max_vertices);
  655. indicesp++;
  656. index_count++;
  657. *(indicesp) = j + ((i+1)*slices) + sLODVertexOffset[lod];
  658. llassert(*(indicesp) < (U32)max_vertices);
  659. indicesp++;
  660. index_count++;
  661. *(indicesp) = j + (i*slices) + sLODVertexOffset[lod];
  662. llassert(*(indicesp) < (U32)max_vertices);
  663. indicesp++;
  664. index_count++;
  665. *(indicesp) = x1_offset + (i*slices) + sLODVertexOffset[lod];
  666. llassert(*(indicesp) < (U32)max_vertices);
  667. indicesp++;
  668. index_count++;
  669. *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod];
  670. llassert(*(indicesp) < (U32)max_vertices);
  671. indicesp++;
  672. index_count++;
  673. }
  674. }
  675. slices /= 2;
  676. }
  677. mReferenceBuffer->flush();
  678. llassert(vertex_count == max_vertices);
  679. llassert(index_count == max_indices);
  680. }
  681. //generate tree mesh
  682. updateMesh();
  683. return TRUE;
  684. }
  685. void LLVOTree::updateMesh()
  686. {
  687. LLMatrix4 matrix;
  688. // Translate to tree base HACK - adjustment in Z plants tree underground
  689. const LLVector3 &pos_agent = getPositionAgent();
  690. //gGL.translatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f);
  691. LLMatrix4 trans_mat;
  692. trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f);
  693. trans_mat *= matrix;
  694. // Rotate to tree position and bend for current trunk/wind
  695. // Note that trunk stiffness controls the amount of bend at the trunk as
  696. // opposed to the crown of the tree
  697. //
  698. const F32 TRUNK_STIFF = 22.f;
  699. LLQuaternion rot =
  700. LLQuaternion(mTrunkBend.magVec()*TRUNK_STIFF*DEG_TO_RAD, LLVector4(mTrunkBend.mV[VX], mTrunkBend.mV[VY], 0)) *
  701. LLQuaternion(90.f*DEG_TO_RAD, LLVector4(0,0,1)) *
  702. getRotation();
  703. LLMatrix4 rot_mat(rot);
  704. rot_mat *= trans_mat;
  705. F32 radius = getScale().magVec()*0.05f;
  706. LLMatrix4 scale_mat;
  707. scale_mat.mMatrix[0][0] =
  708. scale_mat.mMatrix[1][1] =
  709. scale_mat.mMatrix[2][2] = radius;
  710. scale_mat *= rot_mat;
  711. // const F32 THRESH_ANGLE_FOR_BILLBOARD = 15.f;
  712. // const F32 BLEND_RANGE_FOR_BILLBOARD = 3.f;
  713. F32 droop = mDroop + 25.f*(1.f - mTrunkBend.magVec());
  714. S32 stop_depth = 0;
  715. F32 alpha = 1.0;
  716. U32 vert_count = 0;
  717. U32 index_count = 0;
  718. calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches);
  719. LLFace* facep = mDrawable->getFace(0);
  720. LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
  721. buff->allocateBuffer(vert_count, index_count, TRUE);
  722. facep->setVertexBuffer(buff);
  723. LLStrider<LLVector3> vertices;
  724. LLStrider<LLVector3> normals;
  725. LLStrider<LLVector2> tex_coords;
  726. LLStrider<U16> indices;
  727. U16 idx_offset = 0;
  728. buff->getVertexStrider(vertices);
  729. buff->getNormalStrider(normals);
  730. buff->getTexCoord0Strider(tex_coords);
  731. buff->getIndexStrider(indices);
  732. genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha);
  733. mReferenceBuffer->flush();
  734. buff->flush();
  735. }
  736. void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices,
  737. LLStrider<LLVector3>& normals,
  738. LLStrider<LLVector2>& tex_coords,
  739. LLStrider<U16>& indices,
  740. U16& cur_idx,
  741. LLMatrix4& matrix,
  742. LLMatrix4& norm_mat,
  743. S32 vert_start,
  744. S32 vert_count,
  745. S32 index_count,
  746. S32 index_offset)
  747. {
  748. LLStrider<LLVector3> v;
  749. LLStrider<LLVector3> n;
  750. LLStrider<LLVector2> t;
  751. LLStrider<U16> idx;
  752. mReferenceBuffer->getVertexStrider(v);
  753. mReferenceBuffer->getNormalStrider(n);
  754. mReferenceBuffer->getTexCoord0Strider(t);
  755. mReferenceBuffer->getIndexStrider(idx);
  756. //copy/transform vertices into mesh - check
  757. for (S32 i = 0; i < vert_count; i++)
  758. {
  759. U16 index = vert_start + i;
  760. *vertices++ = v[index] * matrix;
  761. LLVector3 norm = n[index] * norm_mat;
  762. norm.normalize();
  763. *normals++ = norm;
  764. *tex_coords++ = t[index];
  765. }
  766. //copy offset indices into mesh - check
  767. for (S32 i = 0; i < index_count; i++)
  768. {
  769. U16 index = index_offset + i;
  770. *indices++ = idx[index]-vert_start+cur_idx;
  771. }
  772. //increment index offset - check
  773. cur_idx += vert_count;
  774. }
  775. void LLVOTree::genBranchPipeline(LLStrider<LLVector3>& vertices,
  776. LLStrider<LLVector3>& normals,
  777. LLStrider<LLVector2>& tex_coords,
  778. LLStrider<U16>& indices,
  779. U16& index_offset,
  780. LLMatrix4& matrix,
  781. S32 trunk_LOD,
  782. S32 stop_level,
  783. U16 depth,
  784. U16 trunk_depth,
  785. F32 scale,
  786. F32 twist,
  787. F32 droop,
  788. F32 branches,
  789. F32 alpha)
  790. {
  791. //
  792. // Generates a tree mesh by recursing, generating branches and then a 'leaf' texture.
  793. static F32 constant_twist;
  794. static F32 width = 0;
  795. F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength);
  796. F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect);
  797. constant_twist = 360.f/branches;
  798. if (stop_level >= 0)
  799. {
  800. if (depth > stop_level)
  801. {
  802. {
  803. llassert(sLODIndexCount[trunk_LOD] > 0);
  804. width = scale * length * aspect;
  805. LLMatrix4 scale_mat;
  806. scale_mat.mMatrix[0][0] = width;
  807. scale_mat.mMatrix[1][1] = width;
  808. scale_mat.mMatrix[2][2] = scale*length;
  809. scale_mat *= matrix;
  810. glh::matrix4f norm((F32*) scale_mat.mMatrix);
  811. LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m);
  812. norm_mat.invert();
  813. appendMesh(vertices, normals, tex_coords, indices, index_offset, scale_mat, norm_mat,
  814. sLODVertexOffset[trunk_LOD], sLODVertexCount[trunk_LOD], sLODIndexCount[trunk_LOD], sLODIndexOffset[trunk_LOD]);
  815. }
  816. // Recurse to create more branches
  817. for (S32 i=0; i < (S32)branches; i++)
  818. {
  819. LLMatrix4 trans_mat;
  820. trans_mat.setTranslation(0,0,scale*length);
  821. trans_mat *= matrix;
  822. LLQuaternion rot =
  823. LLQuaternion(20.f*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)) *
  824. LLQuaternion(droop*DEG_TO_RAD, LLVector4(0.f, 1.f, 0.f)) *
  825. LLQuaternion(((constant_twist + ((i%2==0)?twist:-twist))*i)*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f));
  826. LLMatrix4 rot_mat(rot);
  827. rot_mat *= trans_mat;
  828. genBranchPipeline(vertices, normals, tex_coords, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
  829. }
  830. // Recurse to continue trunk
  831. if (trunk_depth)
  832. {
  833. LLMatrix4 trans_mat;
  834. trans_mat.setTranslation(0,0,scale*length);
  835. trans_mat *= matrix;
  836. LLMatrix4 rot_mat(70.5f*DEG_TO_RAD, LLVector4(0,0,1));
  837. rot_mat *= trans_mat; // rotate a bit around Z when ascending
  838. genBranchPipeline(vertices, normals, tex_coords, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha);
  839. }
  840. }
  841. else
  842. {
  843. //
  844. // Append leaves as two 90 deg crossed quads with leaf textures
  845. //
  846. {
  847. LLMatrix4 scale_mat;
  848. scale_mat.mMatrix[0][0] =
  849. scale_mat.mMatrix[1][1] =
  850. scale_mat.mMatrix[2][2] = scale*mLeafScale;
  851. scale_mat *= matrix;
  852. glh::matrix4f norm((F32*) scale_mat.mMatrix);
  853. LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m);
  854. appendMesh(vertices, normals, tex_coords, indices, index_offset, scale_mat, norm_mat, 0, LEAF_VERTICES, LEAF_INDICES, 0);
  855. }
  856. }
  857. }
  858. }
  859. void LLVOTree::calcNumVerts(U32& vert_count, U32& index_count, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 branches)
  860. {
  861. if (stop_level >= 0)
  862. {
  863. if (depth > stop_level)
  864. {
  865. index_count += sLODIndexCount[trunk_LOD];
  866. vert_count += sLODVertexCount[trunk_LOD];
  867. // Recurse to create more branches
  868. for (S32 i=0; i < (S32)branches; i++)
  869. {
  870. calcNumVerts(vert_count, index_count, trunk_LOD, stop_level, depth - 1, 0, branches);
  871. }
  872. // Recurse to continue trunk
  873. if (trunk_depth)
  874. {
  875. calcNumVerts(vert_count, index_count, trunk_LOD, stop_level, depth, trunk_depth-1, branches);
  876. }
  877. }
  878. else
  879. {
  880. index_count += LEAF_INDICES;
  881. vert_count += LEAF_VERTICES;
  882. }
  883. }
  884. else
  885. {
  886. index_count += LEAF_INDICES;
  887. vert_count += LEAF_VERTICES;
  888. }
  889. }
  890. U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha)
  891. {
  892. U32 ret = 0;
  893. //
  894. // Draws a tree by recursing, drawing branches and then a 'leaf' texture.
  895. // If stop_level = -1, simply draws the whole tree as a billboarded texture
  896. //
  897. static F32 constant_twist;
  898. static F32 width = 0;
  899. //F32 length = ((scale == 1.f)? mTrunkLength:mBranchLength);
  900. //F32 aspect = ((scale == 1.f)? mTrunkAspect:mBranchAspect);
  901. F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength);
  902. F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect);
  903. constant_twist = 360.f/branches;
  904. if (!LLPipeline::sReflectionRender && stop_level >= 0)
  905. {
  906. //
  907. // Draw the tree using recursion
  908. //
  909. if (depth > stop_level)
  910. {
  911. {
  912. llassert(sLODIndexCount[trunk_LOD] > 0);
  913. width = scale * length * aspect;
  914. LLMatrix4 scale_mat;
  915. scale_mat.mMatrix[0][0] = width;
  916. scale_mat.mMatrix[1][1] = width;
  917. scale_mat.mMatrix[2][2] = scale*length;
  918. scale_mat *= matrix;
  919. gGL.loadMatrix((F32*) scale_mat.mMatrix);
  920. gGL.syncMatrices();
  921. glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_SHORT, indicesp + sLODIndexOffset[trunk_LOD]);
  922. gPipeline.addTrianglesDrawn(LEAF_INDICES);
  923. stop_glerror();
  924. ret += sLODIndexCount[trunk_LOD];
  925. }
  926. // Recurse to create more branches
  927. for (S32 i=0; i < (S32)branches; i++)
  928. {
  929. LLMatrix4 trans_mat;
  930. trans_mat.setTranslation(0,0,scale*length);
  931. trans_mat *= matrix;
  932. LLQuaternion rot =
  933. LLQuaternion(20.f*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)) *
  934. LLQuaternion(droop*DEG_TO_RAD, LLVector4(0.f, 1.f, 0.f)) *
  935. LLQuaternion(((constant_twist + ((i%2==0)?twist:-twist))*i)*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f));
  936. LLMatrix4 rot_mat(rot);
  937. rot_mat *= trans_mat;
  938. ret += drawBranchPipeline(rot_mat, indicesp, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
  939. }
  940. // Recurse to continue trunk
  941. if (trunk_depth)
  942. {
  943. LLMatrix4 trans_mat;
  944. trans_mat.setTranslation(0,0,scale*length);
  945. trans_mat *= matrix;
  946. LLMatrix4 rot_mat(70.5f*DEG_TO_RAD, LLVector4(0,0,1));
  947. rot_mat *= trans_mat; // rotate a bit around Z when ascending
  948. ret += drawBranchPipeline(rot_mat, indicesp, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha);
  949. }
  950. }
  951. else
  952. {
  953. //
  954. // Draw leaves as two 90 deg crossed quads with leaf textures
  955. //
  956. {
  957. LLMatrix4 scale_mat;
  958. scale_mat.mMatrix[0][0] =
  959. scale_mat.mMatrix[1][1] =
  960. scale_mat.mMatrix[2][2] = scale*mLeafScale;
  961. scale_mat *= matrix;
  962. gGL.loadMatrix((F32*) scale_mat.mMatrix);
  963. gGL.syncMatrices();
  964. glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp);
  965. gPipeline.addTrianglesDrawn(LEAF_INDICES);
  966. stop_glerror();
  967. ret += LEAF_INDICES;
  968. }
  969. }
  970. }
  971. else
  972. {
  973. //
  974. // Draw the tree as a single billboard texture
  975. //
  976. LLMatrix4 scale_mat;
  977. scale_mat.mMatrix[0][0] =
  978. scale_mat.mMatrix[1][1] =
  979. scale_mat.mMatrix[2][2] = mBillboardScale*mBillboardRatio;
  980. scale_mat *= matrix;
  981. gGL.matrixMode(LLRender::MM_TEXTURE);
  982. gGL.translatef(0.0, -0.5, 0.0);
  983. gGL.matrixMode(LLRender::MM_MODELVIEW);
  984. gGL.loadMatrix((F32*) scale_mat.mMatrix);
  985. gGL.syncMatrices();
  986. glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp);
  987. gPipeline.addTrianglesDrawn(LEAF_INDICES);
  988. stop_glerror();
  989. ret += LEAF_INDICES;
  990. gGL.matrixMode(LLRender::MM_TEXTURE);
  991. gGL.loadIdentity();
  992. gGL.matrixMode(LLRender::MM_MODELVIEW);
  993. }
  994. return ret;
  995. }
  996. void LLVOTree::updateRadius()
  997. {
  998. if (mDrawable.isNull())
  999. {
  1000. return;
  1001. }
  1002. mDrawable->setRadius(32.0f);
  1003. }
  1004. void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
  1005. {
  1006. F32 radius = getScale().length()*0.05f;
  1007. LLVector3 center = getRenderPosition();
  1008. F32 sz = mBillboardScale*mBillboardRatio*radius*0.5f;
  1009. LLVector3 size(sz,sz,sz);
  1010. center += LLVector3(0, 0, size.mV[2]) * getRotation();
  1011. newMin.load3((center-size).mV);
  1012. newMax.load3((center+size).mV);
  1013. LLVector4a pos;
  1014. pos.load3(center.mV);
  1015. mDrawable->setPositionGroup(pos);
  1016. }
  1017. BOOL LLVOTree::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, BOOL pick_transparent, S32 *face_hitp,
  1018. LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
  1019. {
  1020. if (!lineSegmentBoundingBox(start, end))
  1021. {
  1022. return FALSE;
  1023. }
  1024. const LLVector4a* exta = mDrawable->getSpatialExtents();
  1025. //VECTORIZE THIS
  1026. LLVector3 ext[2];
  1027. ext[0].set(exta[0].getF32ptr());
  1028. ext[1].set(exta[1].getF32ptr());
  1029. LLVector3 center = (ext[1]+ext[0])*0.5f;
  1030. LLVector3 size = (ext[1]-ext[0]);
  1031. LLQuaternion quat = getRotation();
  1032. center -= LLVector3(0,0,size.magVec() * 0.25f)*quat;
  1033. size.scaleVec(LLVector3(0.25f, 0.25f, 1.f));
  1034. size.mV[0] = llmin(size.mV[0], 1.f);
  1035. size.mV[1] = llmin(size.mV[1], 1.f);
  1036. LLVector3 pos, norm;
  1037. if (linesegment_tetrahedron(start, end, center, size, quat, pos, norm))
  1038. {
  1039. if (intersection)
  1040. {
  1041. *intersection = pos;
  1042. }
  1043. if (normal)
  1044. {
  1045. *normal = norm;
  1046. }
  1047. return TRUE;
  1048. }
  1049. return FALSE;
  1050. }
  1051. U32 LLVOTree::getPartitionType() const
  1052. {
  1053. return LLViewerRegion::PARTITION_TREE;
  1054. }
  1055. LLTreePartition::LLTreePartition()
  1056. : LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB)
  1057. {
  1058. mDrawableType = LLPipeline::RENDER_TYPE_TREE;
  1059. mPartitionType = LLViewerRegion::PARTITION_TREE;
  1060. mSlopRatio = 0.f;
  1061. mLODPeriod = 1;
  1062. }