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

游戏引擎

开发平台:

C++ Builder

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