aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llvotree.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llvotree.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llvotree.cpp925
1 files changed, 925 insertions, 0 deletions
diff --git a/linden/indra/newview/llvotree.cpp b/linden/indra/newview/llvotree.cpp
new file mode 100644
index 0000000..9808a02
--- /dev/null
+++ b/linden/indra/newview/llvotree.cpp
@@ -0,0 +1,925 @@
1/**
2 * @file llvotree.cpp
3 * @brief LLVOTree class implementation
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llvotree.h"
31
32#include "llviewercontrol.h"
33#include "lldir.h"
34#include "llprimitive.h"
35#include "lltree_common.h"
36#include "llxmltree.h"
37#include "material_codes.h"
38#include "object_flags.h"
39
40#include "llagent.h"
41#include "llagparray.h"
42#include "llcylinder.h"
43#include "lldrawable.h"
44#include "llface.h"
45#include "llviewercamera.h"
46#include "llviewerimagelist.h"
47#include "llviewerobjectlist.h"
48#include "llviewerregion.h"
49#include "llworld.h"
50#include "noise.h"
51#include "pipeline.h"
52#include "llviewerwindow.h"
53
54extern LLPipeline gPipeline;
55
56LLGLuint mLeafDList;
57
58S32 LLVOTree::sLODVertexOffset[4];
59S32 LLVOTree::sLODVertexCount[4];
60S32 LLVOTree::sLODIndexOffset[4];
61S32 LLVOTree::sLODIndexCount[4];
62S32 LLVOTree::sLODSlices[4] = {10, 5, 4, 3};
63F32 LLVOTree::sLODAngles[4] = {30.f, 20.f, 15.f, 0.f};
64
65F32 LLVOTree::sTreeFactor = 1.f;
66
67LLVOTree::SpeciesMap LLVOTree::sSpeciesTable;
68S32 LLVOTree::sMaxTreeSpecies = 0;
69
70// Tree variables and functions
71
72LLVOTree::LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp):
73 LLViewerObject(id, pcode, regionp)
74{
75 mSpecies = 0;
76 mFrameCount = 0;
77 mWind = mRegionp->mWind.getVelocity(getPositionRegion());
78}
79
80
81LLVOTree::~LLVOTree()
82{
83 if (mData)
84 {
85 delete[] mData;
86 mData = NULL;
87 }
88}
89
90// static
91void LLVOTree::initClass()
92{
93 std::string xml_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"trees.xml");
94
95 LLXmlTree tree_def_tree;
96
97 if (!tree_def_tree.parseFile(xml_filename))
98 {
99 llerrs << "Failed to parse tree file." << llendl;
100 }
101
102 LLXmlTreeNode* rootp = tree_def_tree.getRoot();
103
104 for (LLXmlTreeNode* tree_def = rootp->getFirstChild();
105 tree_def;
106 tree_def = rootp->getNextChild())
107 {
108 if (!tree_def->hasName("tree"))
109 {
110 llwarns << "Invalid tree definition node " << tree_def->getName() << llendl;
111 continue;
112 }
113 F32 F32_val;
114 LLUUID id;
115 S32 S32_val;
116
117 BOOL success = TRUE;
118
119
120
121 S32 species;
122 static LLStdStringHandle species_id_string = LLXmlTree::addAttributeString("species_id");
123 if (!tree_def->getFastAttributeS32(species_id_string, species))
124 {
125 llwarns << "No species id defined" << llendl;
126 continue;
127 }
128
129 if (species < 0)
130 {
131 llwarns << "Invalid species id " << species << llendl;
132 continue;
133 }
134
135 if (sSpeciesTable.count(species))
136 {
137 llwarns << "Tree species " << species << " already defined! Duplicate discarded." << llendl;
138 continue;
139 }
140
141 TreeSpeciesData* newTree = new TreeSpeciesData();
142
143 static LLStdStringHandle texture_id_string = LLXmlTree::addAttributeString("texture_id");
144 success &= tree_def->getFastAttributeUUID(texture_id_string, id);
145 newTree->mTextureID = id;
146
147 static LLStdStringHandle droop_string = LLXmlTree::addAttributeString("droop");
148 success &= tree_def->getFastAttributeF32(droop_string, F32_val);
149 newTree->mDroop = F32_val;
150
151 static LLStdStringHandle twist_string = LLXmlTree::addAttributeString("twist");
152 success &= tree_def->getFastAttributeF32(twist_string, F32_val);
153 newTree->mTwist = F32_val;
154
155 static LLStdStringHandle branches_string = LLXmlTree::addAttributeString("branches");
156 success &= tree_def->getFastAttributeF32(branches_string, F32_val);
157 newTree->mBranches = F32_val;
158
159 static LLStdStringHandle depth_string = LLXmlTree::addAttributeString("depth");
160 success &= tree_def->getFastAttributeS32(depth_string, S32_val);
161 newTree->mDepth = S32_val;
162
163 static LLStdStringHandle scale_step_string = LLXmlTree::addAttributeString("scale_step");
164 success &= tree_def->getFastAttributeF32(scale_step_string, F32_val);
165 newTree->mScaleStep = F32_val;
166
167 static LLStdStringHandle trunk_depth_string = LLXmlTree::addAttributeString("trunk_depth");
168 success &= tree_def->getFastAttributeS32(trunk_depth_string, S32_val);
169 newTree->mTrunkDepth = S32_val;
170
171 static LLStdStringHandle branch_length_string = LLXmlTree::addAttributeString("branch_length");
172 success &= tree_def->getFastAttributeF32(branch_length_string, F32_val);
173 newTree->mBranchLength = F32_val;
174
175 static LLStdStringHandle trunk_length_string = LLXmlTree::addAttributeString("trunk_length");
176 success &= tree_def->getFastAttributeF32(trunk_length_string, F32_val);
177 newTree->mTrunkLength = F32_val;
178
179 static LLStdStringHandle leaf_scale_string = LLXmlTree::addAttributeString("leaf_scale");
180 success &= tree_def->getFastAttributeF32(leaf_scale_string, F32_val);
181 newTree->mLeafScale = F32_val;
182
183 static LLStdStringHandle billboard_scale_string = LLXmlTree::addAttributeString("billboard_scale");
184 success &= tree_def->getFastAttributeF32(billboard_scale_string, F32_val);
185 newTree->mBillboardScale = F32_val;
186
187 static LLStdStringHandle billboard_ratio_string = LLXmlTree::addAttributeString("billboard_ratio");
188 success &= tree_def->getFastAttributeF32(billboard_ratio_string, F32_val);
189 newTree->mBillboardRatio = F32_val;
190
191 static LLStdStringHandle trunk_aspect_string = LLXmlTree::addAttributeString("trunk_aspect");
192 success &= tree_def->getFastAttributeF32(trunk_aspect_string, F32_val);
193 newTree->mTrunkAspect = F32_val;
194
195 static LLStdStringHandle branch_aspect_string = LLXmlTree::addAttributeString("branch_aspect");
196 success &= tree_def->getFastAttributeF32(branch_aspect_string, F32_val);
197 newTree->mBranchAspect = F32_val;
198
199 static LLStdStringHandle leaf_rotate_string = LLXmlTree::addAttributeString("leaf_rotate");
200 success &= tree_def->getFastAttributeF32(leaf_rotate_string, F32_val);
201 newTree->mRandomLeafRotate = F32_val;
202
203 static LLStdStringHandle noise_mag_string = LLXmlTree::addAttributeString("noise_mag");
204 success &= tree_def->getFastAttributeF32(noise_mag_string, F32_val);
205 newTree->mNoiseMag = F32_val;
206
207 static LLStdStringHandle noise_scale_string = LLXmlTree::addAttributeString("noise_scale");
208 success &= tree_def->getFastAttributeF32(noise_scale_string, F32_val);
209 newTree->mNoiseScale = F32_val;
210
211 static LLStdStringHandle taper_string = LLXmlTree::addAttributeString("taper");
212 success &= tree_def->getFastAttributeF32(taper_string, F32_val);
213 newTree->mTaper = F32_val;
214
215 static LLStdStringHandle repeat_z_string = LLXmlTree::addAttributeString("repeat_z");
216 success &= tree_def->getFastAttributeF32(repeat_z_string, F32_val);
217 newTree->mRepeatTrunkZ = F32_val;
218
219 sSpeciesTable[species] = newTree;
220
221 if (species >= sMaxTreeSpecies) sMaxTreeSpecies = species + 1;
222
223 if (!success)
224 {
225 LLString name;
226 static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
227 tree_def->getFastAttributeString(name_string, name);
228 llwarns << "Incomplete definition of tree " << name << llendl;
229 }
230 }
231
232 BOOL have_all_trees = TRUE;
233 LLString err;
234 char buffer[10];
235
236 for (S32 i=0;i<sMaxTreeSpecies;++i)
237 {
238 if (!sSpeciesTable.count(i))
239 {
240 snprintf(buffer,10," %d",i);
241 err.append(buffer);
242 have_all_trees = FALSE;
243 }
244 }
245
246 if (!have_all_trees)
247 {
248 LLStringBase<char>::format_map_t args;
249 args["[SPECIES]"] = err;
250 gViewerWindow->alertXml("ErrorUndefinedTrees", args );
251 }
252};
253
254//static
255void LLVOTree::cleanupClass()
256{
257 std::for_each(sSpeciesTable.begin(), sSpeciesTable.end(), DeletePairedPointer());
258}
259
260U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys,
261 void **user_data,
262 U32 block_num, EObjectUpdateType update_type,
263 LLDataPacker *dp)
264{
265 // Do base class updates...
266 U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
267
268 if ( (getVelocity().magVecSquared() > 0.f)
269 ||(getAcceleration().magVecSquared() > 0.f)
270 ||(getAngularVelocity().magVecSquared() > 0.f))
271 {
272 llinfos << "ACK! Moving tree!" << llendl;
273 setVelocity(LLVector3::zero);
274 setAcceleration(LLVector3::zero);
275 setAngularVelocity(LLVector3::zero);
276 }
277
278 if (update_type == OUT_TERSE_IMPROVED)
279 {
280 // Nothing else needs to be done for the terse message.
281 return retval;
282 }
283
284 //
285 // Load Instance-Specific data
286 //
287 if (mData)
288 {
289 mSpecies = ((U8 *)mData)[0];
290 }
291
292 if (!sSpeciesTable.count(mSpecies))
293 {
294 if (sSpeciesTable.size())
295 {
296 SpeciesMap::const_iterator it = sSpeciesTable.begin();
297 mSpecies = (*it).first;
298 }
299 }
300
301 //
302 // Load Species-Specific data
303 //
304 mTreeImagep = gImageList.getImage(sSpeciesTable[mSpecies]->mTextureID);
305 if (mTreeImagep)
306 {
307 mTreeImagep->bindTexture(0);
308 mTreeImagep->setClamp(TRUE, TRUE);
309 }
310 mBranchLength = sSpeciesTable[mSpecies]->mBranchLength;
311 mTrunkLength = sSpeciesTable[mSpecies]->mTrunkLength;
312 mLeafScale = sSpeciesTable[mSpecies]->mLeafScale;
313 mDroop = sSpeciesTable[mSpecies]->mDroop;
314 mTwist = sSpeciesTable[mSpecies]->mTwist;
315 mBranches = sSpeciesTable[mSpecies]->mBranches;
316 mDepth = sSpeciesTable[mSpecies]->mDepth;
317 mScaleStep = sSpeciesTable[mSpecies]->mScaleStep;
318 mTrunkDepth = sSpeciesTable[mSpecies]->mTrunkDepth;
319 mBillboardScale = sSpeciesTable[mSpecies]->mBillboardScale;
320 mBillboardRatio = sSpeciesTable[mSpecies]->mBillboardRatio;
321 mTrunkAspect = sSpeciesTable[mSpecies]->mTrunkAspect;
322 mBranchAspect = sSpeciesTable[mSpecies]->mBranchAspect;
323
324 return retval;
325}
326
327BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
328{
329 const U16 FRAMES_PER_WIND_UPDATE = 20; // How many frames between wind update per tree
330 const F32 TREE_WIND_SENSITIVITY = 0.005f;
331 const F32 TREE_TRUNK_STIFFNESS = 0.1f;
332
333 if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE)))
334 {
335 return TRUE;
336 }
337
338 F32 mass_inv;
339
340 // For all tree objects, update the trunk bending with the current wind
341 // Walk sprite list in order away from viewer
342 if (!(mFrameCount % FRAMES_PER_WIND_UPDATE))
343 {
344 // If needed, Get latest wind for this tree
345 mWind = mRegionp->mWind.getVelocity(getPositionRegion());
346 }
347 mFrameCount++;
348
349 mass_inv = 1.f/(5.f + mDepth*mBranches*0.2f);
350 mTrunkVel += (mWind * mass_inv * TREE_WIND_SENSITIVITY); // Pull in direction of wind
351 mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS); // Restoring force in direction of trunk
352 mTrunkBend += mTrunkVel;
353 mTrunkVel *= 0.99f; // Add damping
354
355 if (mTrunkBend.magVec() > 1.f)
356 {
357 mTrunkBend.normVec();
358 }
359
360 if (mTrunkVel.magVec() > 1.f)
361 {
362 mTrunkVel.normVec();
363 }
364
365 return TRUE;
366}
367
368
369const F32 TREE_BLEND_MIN = 1.f;
370const F32 TREE_BLEND_RANGE = 1.f;
371
372
373void LLVOTree::render(LLAgent &agent)
374{
375}
376
377
378void LLVOTree::setPixelAreaAndAngle(LLAgent &agent)
379{
380 // First calculate values as for any other object (for mAppAngle)
381 LLViewerObject::setPixelAreaAndAngle(agent);
382
383 // Re-calculate mPixelArea accurately
384
385 // This should be the camera's center, as soon as we move to all region-local.
386 LLVector3 relative_position = getPositionAgent() - agent.getCameraPositionAgent();
387 F32 range = relative_position.magVec(); // ugh, square root
388
389 F32 max_scale = mBillboardScale * getMaxScale();
390 F32 area = max_scale * (max_scale*mBillboardRatio);
391
392 // Compute pixels per meter at the given range
393 F32 pixels_per_meter = gCamera->getViewHeightInPixels() /
394 (tan(gCamera->getView()) * range);
395
396 mPixelArea = (pixels_per_meter) * (pixels_per_meter) * area;
397#if 0
398 // mAppAngle is a bit of voodoo;
399 // use the one calculated LLViewerObject::setPixelAreaAndAngle above
400 // to avoid LOD miscalculations
401 mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG;
402#endif
403}
404
405void LLVOTree::updateTextures(LLAgent &agent)
406{
407 F32 texel_area_ratio = 1.f;
408 F32 cos_angle = 1.f;
409 if (mTreeImagep)
410 {
411 mTreeImagep->addTextureStats(mPixelArea, texel_area_ratio, cos_angle);
412 }
413
414}
415
416
417LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline)
418{
419 pipeline->allocDrawable(this);
420 mDrawable->setLit(FALSE);
421
422 mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TREE);
423
424 LLDrawPool *poolp = gPipeline.getPool(LLDrawPool::POOL_TREE, mTreeImagep);
425
426 // Just a placeholder for an actual object...
427 LLFace *facep = mDrawable->addFace(poolp, mTreeImagep, TRUE);
428 facep->setSize(1, 3);
429
430 gPipeline.markMaterialed(mDrawable);
431
432 updateRadius();
433
434 return mDrawable;
435}
436
437
438// Yes, I know this is bad. I'll clean this up soon. - djs 04/02/02
439const S32 LEAF_INDICES = 24;
440const S32 LEAF_VERTICES = 16;
441
442BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
443{
444 U32 i, j;
445 const S32 MAX_SLICES = 32;
446
447 const F32 LEAF_LEFT = 0.52f;
448 const F32 LEAF_RIGHT = 0.98f;
449 const F32 LEAF_TOP = 1.0f;
450 const F32 LEAF_BOTTOM = 0.52f;
451
452 const F32 LEAF_WIDTH = 1.f;
453
454
455 U32 slices = MAX_SLICES;
456
457 S32 max_indices = LEAF_INDICES;
458 S32 max_vertices = LEAF_VERTICES;
459 S32 lod;
460
461 LLFace *face = drawable->getFace(0);
462
463 face->mCenterAgent = getPositionAgent();
464 face->mCenterLocal = face->mCenterAgent;
465
466 LLDrawPool *poolp = face->getPool();
467
468 if (poolp->getVertexCount())
469 {
470 return TRUE;
471 }
472
473 if (!face->getDirty())
474 {
475 return FALSE;
476 }
477
478 poolp->setDirty();
479
480 for (lod = 0; lod < 4; lod++)
481 {
482 slices = sLODSlices[lod];
483 sLODVertexOffset[lod] = max_vertices;
484 sLODVertexCount[lod] = slices*slices;
485 sLODIndexOffset[lod] = max_indices;
486 sLODIndexCount[lod] = (slices-1)*(slices-1)*6;
487 max_indices += sLODIndexCount[lod];
488 max_vertices += sLODVertexCount[lod];
489 }
490
491 LLStrider<LLVector3> vertices;
492 LLStrider<LLVector3> normals;
493 LLStrider<LLVector2> tex_coords;
494 U32 *indicesp;
495
496 face->setSize(max_vertices, max_indices);
497 face->getGeometry(vertices, normals, tex_coords, indicesp);
498
499 S32 vertex_count = 0;
500 S32 index_count = 0;
501
502 // First leaf
503 for (i = 0; i < 4; i++)
504 {
505 *(normals++) = LLVector3(0.f, 0.f, 1.f);
506 }
507
508 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
509 *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f);
510 vertex_count++;
511
512 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
513 *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
514 vertex_count++;
515
516 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
517 *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
518 vertex_count++;
519
520 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
521 *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f);
522 vertex_count++;
523
524
525 *(indicesp++) = 0;
526 index_count++;
527 *(indicesp++) = 1;
528 index_count++;
529 *(indicesp++) = 2;
530 index_count++;
531
532 *(indicesp++) = 0;
533 index_count++;
534 *(indicesp++) = 3;
535 index_count++;
536 *(indicesp++) = 1;
537 index_count++;
538
539 // Same leaf, inverse winding/normals
540 for (i = 0; i < 4; i++)
541 {
542 *(normals++) = LLVector3(0.f, 0.f, 1.f);
543 }
544
545 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
546 *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f);
547 vertex_count++;
548
549 //*(tex_coords++) = LLVector2(1.f, 1.0f);
550 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
551 *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
552 vertex_count++;
553
554 //*(tex_coords++) = LLVector2(0.52f, 1.0f);
555 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
556 *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
557 vertex_count++;
558
559 //*(tex_coords++) = LLVector2(1.f, 0.52f);
560 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
561 *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f);
562 vertex_count++;
563
564 *(indicesp++) = 4;
565 index_count++;
566 *(indicesp++) = 6;
567 index_count++;
568 *(indicesp++) = 5;
569 index_count++;
570
571 *(indicesp++) = 4;
572 index_count++;
573 *(indicesp++) = 5;
574 index_count++;
575 *(indicesp++) = 7;
576 index_count++;
577
578
579 for (i = 0; i < 4; i++)
580 {
581 *(normals++) = LLVector3(0.f, 0.f, 1.f);
582 }
583
584 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
585 *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f);
586 vertex_count++;
587
588 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
589 *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);
590 vertex_count++;
591
592 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
593 *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);
594 vertex_count++;
595
596 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
597 *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f);
598 vertex_count++;
599
600 *(indicesp++) = 8;
601 index_count++;
602 *(indicesp++) = 9;
603 index_count++;
604 *(indicesp++) = 10;
605 index_count++;
606
607 *(indicesp++) = 8;
608 index_count++;
609 *(indicesp++) = 11;
610 index_count++;
611 *(indicesp++) = 9;
612 index_count++;
613
614 for (i = 0; i < 4; i++)
615 {
616 *(normals++) = LLVector3(0.f, 0.f, 1.f);
617 }
618
619 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
620 *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f);
621 vertex_count++;
622
623 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
624 *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);
625 vertex_count++;
626
627 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
628 *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);
629 vertex_count++;
630
631 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
632 *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f);
633 vertex_count++;
634
635
636 *(indicesp++) = 12;
637 index_count++;
638 *(indicesp++) = 14;
639 index_count++;
640 *(indicesp++) = 13;
641 index_count++;
642
643 *(indicesp++) = 12;
644 index_count++;
645 *(indicesp++) = 13;
646 index_count++;
647 *(indicesp++) = 15;
648 index_count++;
649
650 // Generate geometry for the cylinders
651
652 // Different LOD's
653
654 // Generate the vertices
655 // Generate the indices
656
657 for (lod = 0; lod < 4; lod++)
658 {
659 slices = sLODSlices[lod];
660 F32 base_radius = 0.65f;
661 F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper;
662 //llinfos << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << llendl;
663 //llinfos << "Droop " << mDroop << ", branchlength: " << mBranchLength << llendl;
664 F32 angle = 0;
665 F32 angle_inc = 360.f/(slices-1);
666 F32 z = 0.f;
667 F32 z_inc = 1.f;
668 if (slices > 3)
669 {
670 z_inc = 1.f/(slices - 3);
671 }
672 F32 radius = base_radius;
673
674 F32 x1,y1;
675 F32 noise_scale = sSpeciesTable[mSpecies]->mNoiseMag;
676 LLVector3 nvec;
677
678 const F32 cap_nudge = 0.1f; // Height to 'peak' the caps on top/bottom of branch
679
680 const S32 fractal_depth = 5;
681 F32 nvec_scale = 1.f * sSpeciesTable[mSpecies]->mNoiseScale;
682 F32 nvec_scalez = 4.f * sSpeciesTable[mSpecies]->mNoiseScale;
683
684 F32 tex_z_repeat = sSpeciesTable[mSpecies]->mRepeatTrunkZ;
685
686 F32 start_radius;
687 F32 nangle = 0;
688 F32 height = 1.f;
689 F32 r0;
690
691 for (i = 0; i < slices; i++)
692 {
693 if (i == 0)
694 {
695 z = - cap_nudge;
696 r0 = 0.0;
697 }
698 else if (i == (slices - 1))
699 {
700 z = 1.f + cap_nudge;//((i - 2) * z_inc) + cap_nudge;
701 r0 = 0.0;
702 }
703 else
704 {
705 z = (i - 1) * z_inc;
706 r0 = base_radius + (top_radius - base_radius)*z;
707 }
708
709 for (j = 0; j < slices; j++)
710 {
711 if (slices - 1 == j)
712 {
713 angle = 0.f;
714 }
715 else
716 {
717 angle = j*angle_inc;
718 }
719
720 nangle = angle;
721
722 x1 = cos(angle * DEG_TO_RAD);
723 y1 = sin(angle * DEG_TO_RAD);
724 LLVector2 tc;
725 // This isn't totally accurate. Should compute based on slope as well.
726 start_radius = r0 * (1.f + 1.2f*fabs(z - 0.66f*height)/height);
727 nvec.setVec( cos(nangle * DEG_TO_RAD)*start_radius*nvec_scale,
728 sin(nangle * DEG_TO_RAD)*start_radius*nvec_scale,
729 z*nvec_scalez);
730 // First and last slice at 0 radius (to bring in top/bottom of structure)
731 radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale;
732
733 if (slices - 1 == j)
734 {
735 // Not 0.5 for slight slop factor to avoid edges on leaves
736 tc = LLVector2(0.490f, (1.f - z/2.f)*tex_z_repeat);
737 }
738 else
739 {
740 tc = LLVector2((angle/360.f)*0.5f, (1.f - z/2.f)*tex_z_repeat);
741 }
742
743 *(vertices++) = LLVector3(x1*radius, y1*radius, z);
744 *(normals++) = LLVector3(x1, y1, 0.f);
745 *(tex_coords++) = tc;
746 vertex_count++;
747 }
748 }
749
750 for (i = 0; i < (slices - 1); i++)
751 {
752 for (j = 0; j < (slices - 1); j++)
753 {
754 S32 x1_offset = j+1;
755 if ((j+1) == slices)
756 {
757 x1_offset = 0;
758 }
759 // Generate the matching quads
760 *(indicesp) = j + (i*slices) + sLODVertexOffset[lod];
761 llassert(*(indicesp) < (U32)max_vertices);
762 indicesp++;
763 index_count++;
764 *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod];
765 llassert(*(indicesp) < (U32)max_vertices);
766 indicesp++;
767 index_count++;
768 *(indicesp) = j + ((i+1)*slices) + sLODVertexOffset[lod];
769 llassert(*(indicesp) < (U32)max_vertices);
770 indicesp++;
771 index_count++;
772
773 *(indicesp) = j + (i*slices) + sLODVertexOffset[lod];
774 llassert(*(indicesp) < (U32)max_vertices);
775 indicesp++;
776 index_count++;
777 *(indicesp) = x1_offset + (i*slices) + sLODVertexOffset[lod];
778 llassert(*(indicesp) < (U32)max_vertices);
779 indicesp++;
780 index_count++;
781 *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod];
782 llassert(*(indicesp) < (U32)max_vertices);
783 indicesp++;
784 index_count++;
785 }
786 }
787 slices /= 2;
788 }
789
790 llassert(vertex_count == max_vertices);
791 llassert(index_count == max_indices);
792
793 return TRUE;
794}
795
796void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha)
797{
798 //
799 // Draws a tree by recursing, drawing branches and then a 'leaf' texture.
800 // If stop_level = -1, simply draws the whole tree as a billboarded texture
801 //
802
803 if (!draw_pool->getIndexCount())
804 {
805 return; // safety net
806 }
807
808 static F32 constant_twist;
809 static F32 width = 0;
810
811 //F32 length = ((scale == 1.f)? mTrunkLength:mBranchLength);
812 //F32 aspect = ((scale == 1.f)? mTrunkAspect:mBranchAspect);
813 F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength);
814 F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect);
815
816 constant_twist = 360.f/branches;
817
818 if (stop_level >= 0)
819 {
820 //
821 // Draw the tree using recursion
822 //
823 if (depth > stop_level)
824 {
825 {
826 llassert(sLODIndexCount[trunk_LOD] > 0);
827 width = scale * length * aspect;
828 glPushMatrix();
829 glScalef(width,width,scale * length);
830 //glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_INT, draw_pool.getRawIndices() + sLODIndexOffset[trunk_LOD]);
831 glDrawRangeElements(GL_TRIANGLES,
832 sLODVertexOffset[trunk_LOD],
833 sLODVertexOffset[trunk_LOD] + sLODVertexCount[trunk_LOD]-1,
834 sLODIndexCount[trunk_LOD],
835 GL_UNSIGNED_INT,
836 draw_pool->getRawIndices() + sLODIndexOffset[trunk_LOD]);
837 stop_glerror();
838 draw_pool->addIndicesDrawn(sLODIndexCount[trunk_LOD]);
839 glPopMatrix();
840 }
841
842 // Recurse to create more branches
843 for (S32 i=0; i < (S32)branches; i++)
844 {
845 glPushMatrix();
846 glTranslatef(0.f, 0.f, scale * length);
847 glRotatef((constant_twist + ((i%2==0)?twist:-twist))*i, 0.f, 0.f, 1.f);
848 glRotatef(droop, 0.f, 1.f, 0.f);
849 glRotatef(20.f, 0.f, 0.f, 1.f); // rotate 20deg about axis of new branch to add some random variation
850 drawBranchPipeline(draw_pool, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
851 glPopMatrix();
852 }
853 // Recurse to continue trunk
854 if (trunk_depth)
855 {
856 glPushMatrix();
857 glTranslatef(0.f, 0.f, scale * length);
858 glRotatef(70.5f, 0.f, 0.f, 1.f); // rotate a bit around Z when ascending
859 drawBranchPipeline(draw_pool, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha);
860 glPopMatrix();
861 }
862 }
863 else
864 {
865 //
866 // Draw leaves as two 90 deg crossed quads with leaf textures
867 //
868 {
869 glPushMatrix();
870 //glRotatef(llFrand(50.0), llFrand(1.0), llFrand(1.0), llFrand(1.0);
871 //width = scale * (TREE_BRANCH_ASPECT + TREE_LEAF_ASPECT);
872 glScalef(scale*mLeafScale, scale*mLeafScale, scale*mLeafScale);
873 //glScalef(1.5f*width*mLeafScale,1,1.5f*scale*mLeafScale);
874// glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, draw_pool.getRawIndices());
875 glDrawRangeElements(GL_TRIANGLES,
876 0,
877 LEAF_VERTICES-1,
878 LEAF_INDICES,
879 GL_UNSIGNED_INT,
880 draw_pool->getRawIndices());
881 stop_glerror();
882 draw_pool->addIndicesDrawn(LEAF_INDICES);
883 glPopMatrix();
884 }
885 }
886 }
887 else
888 {
889 //
890 // Draw the tree as a single billboard texture
891 //
892
893 glMatrixMode(GL_TEXTURE);
894 glPushMatrix();
895 glTranslatef(0.0, -0.5, 0.0);
896 glMatrixMode(GL_MODELVIEW);
897 {
898 glPushMatrix();
899 glScalef(mBillboardScale*mBillboardRatio, mBillboardScale*mBillboardRatio, mBillboardScale);
900// glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, draw_pool.getRawIndices());
901 glDrawRangeElements(GL_TRIANGLES,
902 0,
903 LEAF_VERTICES-1,
904 LEAF_INDICES,
905 GL_UNSIGNED_INT,
906 draw_pool->getRawIndices());
907 stop_glerror();
908 draw_pool->addIndicesDrawn(LEAF_INDICES);
909 glPopMatrix();
910 }
911 glMatrixMode(GL_TEXTURE);
912 glPopMatrix();
913 glMatrixMode(GL_MODELVIEW);
914 }
915}
916
917void LLVOTree::updateRadius()
918{
919 if (mDrawable.isNull())
920 {
921 return;
922 }
923
924 mDrawable->setRadius(32.0f);
925}