00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llvotree.h"
00035
00036 #include "lldrawpooltree.h"
00037
00038 #include "llviewercontrol.h"
00039 #include "lldir.h"
00040 #include "llprimitive.h"
00041 #include "lltree_common.h"
00042 #include "llxmltree.h"
00043 #include "material_codes.h"
00044 #include "object_flags.h"
00045
00046 #include "llagent.h"
00047 #include "lldrawable.h"
00048 #include "llface.h"
00049 #include "llviewercamera.h"
00050 #include "llviewerimagelist.h"
00051 #include "llviewerobjectlist.h"
00052 #include "llviewerregion.h"
00053 #include "llworld.h"
00054 #include "noise.h"
00055 #include "pipeline.h"
00056 #include "llspatialpartition.h"
00057 #include "llviewerwindow.h"
00058
00059 extern LLPipeline gPipeline;
00060
00061 const S32 MAX_SLICES = 32;
00062 const F32 LEAF_LEFT = 0.52f;
00063 const F32 LEAF_RIGHT = 0.98f;
00064 const F32 LEAF_TOP = 1.0f;
00065 const F32 LEAF_BOTTOM = 0.52f;
00066 const F32 LEAF_WIDTH = 1.f;
00067
00068 S32 LLVOTree::sLODVertexOffset[4];
00069 S32 LLVOTree::sLODVertexCount[4];
00070 S32 LLVOTree::sLODIndexOffset[4];
00071 S32 LLVOTree::sLODIndexCount[4];
00072 S32 LLVOTree::sLODSlices[4] = {10, 5, 4, 3};
00073 F32 LLVOTree::sLODAngles[4] = {30.f, 20.f, 15.f, 0.f};
00074
00075 F32 LLVOTree::sTreeFactor = 1.f;
00076
00077 LLVOTree::SpeciesMap LLVOTree::sSpeciesTable;
00078 S32 LLVOTree::sMaxTreeSpecies = 0;
00079
00080
00081
00082 LLVOTree::LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp):
00083 LLViewerObject(id, pcode, regionp)
00084 {
00085 mSpecies = 0;
00086 mFrameCount = 0;
00087 mWind = mRegionp->mWind.getVelocity(getPositionRegion());
00088 }
00089
00090
00091 LLVOTree::~LLVOTree()
00092 {
00093 if (mData)
00094 {
00095 delete[] mData;
00096 mData = NULL;
00097 }
00098 }
00099
00100
00101 void LLVOTree::initClass()
00102 {
00103 std::string xml_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"trees.xml");
00104
00105 LLXmlTree tree_def_tree;
00106
00107 if (!tree_def_tree.parseFile(xml_filename))
00108 {
00109 llerrs << "Failed to parse tree file." << llendl;
00110 }
00111
00112 LLXmlTreeNode* rootp = tree_def_tree.getRoot();
00113
00114 for (LLXmlTreeNode* tree_def = rootp->getFirstChild();
00115 tree_def;
00116 tree_def = rootp->getNextChild())
00117 {
00118 if (!tree_def->hasName("tree"))
00119 {
00120 llwarns << "Invalid tree definition node " << tree_def->getName() << llendl;
00121 continue;
00122 }
00123 F32 F32_val;
00124 LLUUID id;
00125 S32 S32_val;
00126
00127 BOOL success = TRUE;
00128
00129
00130
00131 S32 species;
00132 static LLStdStringHandle species_id_string = LLXmlTree::addAttributeString("species_id");
00133 if (!tree_def->getFastAttributeS32(species_id_string, species))
00134 {
00135 llwarns << "No species id defined" << llendl;
00136 continue;
00137 }
00138
00139 if (species < 0)
00140 {
00141 llwarns << "Invalid species id " << species << llendl;
00142 continue;
00143 }
00144
00145 if (sSpeciesTable.count(species))
00146 {
00147 llwarns << "Tree species " << species << " already defined! Duplicate discarded." << llendl;
00148 continue;
00149 }
00150
00151 TreeSpeciesData* newTree = new TreeSpeciesData();
00152
00153 static LLStdStringHandle texture_id_string = LLXmlTree::addAttributeString("texture_id");
00154 success &= tree_def->getFastAttributeUUID(texture_id_string, id);
00155 newTree->mTextureID = id;
00156
00157 static LLStdStringHandle droop_string = LLXmlTree::addAttributeString("droop");
00158 success &= tree_def->getFastAttributeF32(droop_string, F32_val);
00159 newTree->mDroop = F32_val;
00160
00161 static LLStdStringHandle twist_string = LLXmlTree::addAttributeString("twist");
00162 success &= tree_def->getFastAttributeF32(twist_string, F32_val);
00163 newTree->mTwist = F32_val;
00164
00165 static LLStdStringHandle branches_string = LLXmlTree::addAttributeString("branches");
00166 success &= tree_def->getFastAttributeF32(branches_string, F32_val);
00167 newTree->mBranches = F32_val;
00168
00169 static LLStdStringHandle depth_string = LLXmlTree::addAttributeString("depth");
00170 success &= tree_def->getFastAttributeS32(depth_string, S32_val);
00171 newTree->mDepth = S32_val;
00172
00173 static LLStdStringHandle scale_step_string = LLXmlTree::addAttributeString("scale_step");
00174 success &= tree_def->getFastAttributeF32(scale_step_string, F32_val);
00175 newTree->mScaleStep = F32_val;
00176
00177 static LLStdStringHandle trunk_depth_string = LLXmlTree::addAttributeString("trunk_depth");
00178 success &= tree_def->getFastAttributeS32(trunk_depth_string, S32_val);
00179 newTree->mTrunkDepth = S32_val;
00180
00181 static LLStdStringHandle branch_length_string = LLXmlTree::addAttributeString("branch_length");
00182 success &= tree_def->getFastAttributeF32(branch_length_string, F32_val);
00183 newTree->mBranchLength = F32_val;
00184
00185 static LLStdStringHandle trunk_length_string = LLXmlTree::addAttributeString("trunk_length");
00186 success &= tree_def->getFastAttributeF32(trunk_length_string, F32_val);
00187 newTree->mTrunkLength = F32_val;
00188
00189 static LLStdStringHandle leaf_scale_string = LLXmlTree::addAttributeString("leaf_scale");
00190 success &= tree_def->getFastAttributeF32(leaf_scale_string, F32_val);
00191 newTree->mLeafScale = F32_val;
00192
00193 static LLStdStringHandle billboard_scale_string = LLXmlTree::addAttributeString("billboard_scale");
00194 success &= tree_def->getFastAttributeF32(billboard_scale_string, F32_val);
00195 newTree->mBillboardScale = F32_val;
00196
00197 static LLStdStringHandle billboard_ratio_string = LLXmlTree::addAttributeString("billboard_ratio");
00198 success &= tree_def->getFastAttributeF32(billboard_ratio_string, F32_val);
00199 newTree->mBillboardRatio = F32_val;
00200
00201 static LLStdStringHandle trunk_aspect_string = LLXmlTree::addAttributeString("trunk_aspect");
00202 success &= tree_def->getFastAttributeF32(trunk_aspect_string, F32_val);
00203 newTree->mTrunkAspect = F32_val;
00204
00205 static LLStdStringHandle branch_aspect_string = LLXmlTree::addAttributeString("branch_aspect");
00206 success &= tree_def->getFastAttributeF32(branch_aspect_string, F32_val);
00207 newTree->mBranchAspect = F32_val;
00208
00209 static LLStdStringHandle leaf_rotate_string = LLXmlTree::addAttributeString("leaf_rotate");
00210 success &= tree_def->getFastAttributeF32(leaf_rotate_string, F32_val);
00211 newTree->mRandomLeafRotate = F32_val;
00212
00213 static LLStdStringHandle noise_mag_string = LLXmlTree::addAttributeString("noise_mag");
00214 success &= tree_def->getFastAttributeF32(noise_mag_string, F32_val);
00215 newTree->mNoiseMag = F32_val;
00216
00217 static LLStdStringHandle noise_scale_string = LLXmlTree::addAttributeString("noise_scale");
00218 success &= tree_def->getFastAttributeF32(noise_scale_string, F32_val);
00219 newTree->mNoiseScale = F32_val;
00220
00221 static LLStdStringHandle taper_string = LLXmlTree::addAttributeString("taper");
00222 success &= tree_def->getFastAttributeF32(taper_string, F32_val);
00223 newTree->mTaper = F32_val;
00224
00225 static LLStdStringHandle repeat_z_string = LLXmlTree::addAttributeString("repeat_z");
00226 success &= tree_def->getFastAttributeF32(repeat_z_string, F32_val);
00227 newTree->mRepeatTrunkZ = F32_val;
00228
00229 sSpeciesTable[species] = newTree;
00230
00231 if (species >= sMaxTreeSpecies) sMaxTreeSpecies = species + 1;
00232
00233 if (!success)
00234 {
00235 LLString name;
00236 static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
00237 tree_def->getFastAttributeString(name_string, name);
00238 llwarns << "Incomplete definition of tree " << name << llendl;
00239 }
00240 }
00241
00242 BOOL have_all_trees = TRUE;
00243 LLString err;
00244 char buffer[10];
00245
00246 for (S32 i=0;i<sMaxTreeSpecies;++i)
00247 {
00248 if (!sSpeciesTable.count(i))
00249 {
00250 snprintf(buffer,10," %d",i);
00251 err.append(buffer);
00252 have_all_trees = FALSE;
00253 }
00254 }
00255
00256 if (!have_all_trees)
00257 {
00258 LLStringBase<char>::format_map_t args;
00259 args["[SPECIES]"] = err;
00260 gViewerWindow->alertXml("ErrorUndefinedTrees", args );
00261 }
00262 };
00263
00264
00265 void LLVOTree::cleanupClass()
00266 {
00267 std::for_each(sSpeciesTable.begin(), sSpeciesTable.end(), DeletePairedPointer());
00268 }
00269
00270 U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys,
00271 void **user_data,
00272 U32 block_num, EObjectUpdateType update_type,
00273 LLDataPacker *dp)
00274 {
00275
00276 U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
00277
00278 if ( (getVelocity().magVecSquared() > 0.f)
00279 ||(getAcceleration().magVecSquared() > 0.f)
00280 ||(getAngularVelocity().magVecSquared() > 0.f))
00281 {
00282 llinfos << "ACK! Moving tree!" << llendl;
00283 setVelocity(LLVector3::zero);
00284 setAcceleration(LLVector3::zero);
00285 setAngularVelocity(LLVector3::zero);
00286 }
00287
00288 if (update_type == OUT_TERSE_IMPROVED)
00289 {
00290
00291 return retval;
00292 }
00293
00294
00295
00296
00297 if (mData)
00298 {
00299 mSpecies = ((U8 *)mData)[0];
00300 }
00301
00302 if (!sSpeciesTable.count(mSpecies))
00303 {
00304 if (sSpeciesTable.size())
00305 {
00306 SpeciesMap::const_iterator it = sSpeciesTable.begin();
00307 mSpecies = (*it).first;
00308 }
00309 }
00310
00311
00312
00313
00314 mTreeImagep = gImageList.getImage(sSpeciesTable[mSpecies]->mTextureID);
00315 if (mTreeImagep)
00316 {
00317 mTreeImagep->bindTexture(0);
00318 }
00319 mBranchLength = sSpeciesTable[mSpecies]->mBranchLength;
00320 mTrunkLength = sSpeciesTable[mSpecies]->mTrunkLength;
00321 mLeafScale = sSpeciesTable[mSpecies]->mLeafScale;
00322 mDroop = sSpeciesTable[mSpecies]->mDroop;
00323 mTwist = sSpeciesTable[mSpecies]->mTwist;
00324 mBranches = sSpeciesTable[mSpecies]->mBranches;
00325 mDepth = sSpeciesTable[mSpecies]->mDepth;
00326 mScaleStep = sSpeciesTable[mSpecies]->mScaleStep;
00327 mTrunkDepth = sSpeciesTable[mSpecies]->mTrunkDepth;
00328 mBillboardScale = sSpeciesTable[mSpecies]->mBillboardScale;
00329 mBillboardRatio = sSpeciesTable[mSpecies]->mBillboardRatio;
00330 mTrunkAspect = sSpeciesTable[mSpecies]->mTrunkAspect;
00331 mBranchAspect = sSpeciesTable[mSpecies]->mBranchAspect;
00332
00333 return retval;
00334 }
00335
00336 BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
00337 {
00338 const U16 FRAMES_PER_WIND_UPDATE = 20;
00339 const F32 TREE_WIND_SENSITIVITY = 0.005f;
00340 const F32 TREE_TRUNK_STIFFNESS = 0.1f;
00341
00342 if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE)))
00343 {
00344 return TRUE;
00345 }
00346
00347 F32 mass_inv;
00348
00349
00350
00351 if (!(mFrameCount % FRAMES_PER_WIND_UPDATE))
00352 {
00353
00354 mWind = mRegionp->mWind.getVelocity(getPositionRegion());
00355 }
00356 mFrameCount++;
00357
00358 mass_inv = 1.f/(5.f + mDepth*mBranches*0.2f);
00359 mTrunkVel += (mWind * mass_inv * TREE_WIND_SENSITIVITY);
00360 mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS);
00361 mTrunkBend += mTrunkVel;
00362 mTrunkVel *= 0.99f;
00363
00364 if (mTrunkBend.magVec() > 1.f)
00365 {
00366 mTrunkBend.normVec();
00367 }
00368
00369 if (mTrunkVel.magVec() > 1.f)
00370 {
00371 mTrunkVel.normVec();
00372 }
00373
00374 return TRUE;
00375 }
00376
00377
00378 const F32 TREE_BLEND_MIN = 1.f;
00379 const F32 TREE_BLEND_RANGE = 1.f;
00380
00381
00382 void LLVOTree::render(LLAgent &agent)
00383 {
00384 }
00385
00386
00387 void LLVOTree::setPixelAreaAndAngle(LLAgent &agent)
00388 {
00389
00390 LLViewerObject::setPixelAreaAndAngle(agent);
00391
00392
00393
00394
00395 LLVector3 relative_position = getPositionAgent() - agent.getCameraPositionAgent();
00396 F32 range = relative_position.magVec();
00397
00398 F32 max_scale = mBillboardScale * getMaxScale();
00399 F32 area = max_scale * (max_scale*mBillboardRatio);
00400
00401
00402 F32 pixels_per_meter = LLViewerCamera::getInstance()->getViewHeightInPixels() /
00403 (tan(LLViewerCamera::getInstance()->getView()) * range);
00404
00405 mPixelArea = (pixels_per_meter) * (pixels_per_meter) * area;
00406 #if 0
00407
00408
00409
00410 mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG;
00411 #endif
00412 }
00413
00414 void LLVOTree::updateTextures(LLAgent &agent)
00415 {
00416 if (mTreeImagep)
00417 {
00418 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
00419 {
00420 setDebugText(llformat("%4.0f", fsqrtf(mPixelArea)));
00421 }
00422 mTreeImagep->addTextureStats(mPixelArea);
00423 }
00424
00425 }
00426
00427
00428 LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline)
00429 {
00430 pipeline->allocDrawable(this);
00431 mDrawable->setLit(FALSE);
00432
00433 mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TREE);
00434
00435 LLDrawPoolTree *poolp = (LLDrawPoolTree*) gPipeline.getPool(LLDrawPool::POOL_TREE, mTreeImagep);
00436
00437
00438 LLFace *facep = mDrawable->addFace(poolp, mTreeImagep);
00439 facep->setSize(1, 3);
00440
00441 updateRadius();
00442
00443 return mDrawable;
00444 }
00445
00446
00447
00448 const S32 LEAF_INDICES = 24;
00449 const S32 LEAF_VERTICES = 16;
00450
00451 BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
00452 {
00453 LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TREE);
00454 const F32 SRR3 = 0.577350269f;
00455 const F32 SRR2 = 0.707106781f;
00456 U32 i, j;
00457
00458 U32 slices = MAX_SLICES;
00459
00460 S32 max_indices = LEAF_INDICES;
00461 S32 max_vertices = LEAF_VERTICES;
00462 S32 lod;
00463
00464 LLFace *face = drawable->getFace(0);
00465
00466 face->mCenterAgent = getPositionAgent();
00467 face->mCenterLocal = face->mCenterAgent;
00468
00469 for (lod = 0; lod < 4; lod++)
00470 {
00471 slices = sLODSlices[lod];
00472 sLODVertexOffset[lod] = max_vertices;
00473 sLODVertexCount[lod] = slices*slices;
00474 sLODIndexOffset[lod] = max_indices;
00475 sLODIndexCount[lod] = (slices-1)*(slices-1)*6;
00476 max_indices += sLODIndexCount[lod];
00477 max_vertices += sLODVertexCount[lod];
00478 }
00479
00480 LLStrider<LLVector3> vertices;
00481 LLStrider<LLVector3> normals;
00482 LLStrider<LLVector2> tex_coords;
00483 LLStrider<U16> indicesp;
00484
00485 face->setSize(max_vertices, max_indices);
00486
00487 face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
00488 face->mVertexBuffer->allocateBuffer(max_vertices, max_indices, TRUE);
00489 face->setGeomIndex(0);
00490 face->setIndicesIndex(0);
00491
00492 face->getGeometry(vertices, normals, tex_coords, indicesp);
00493
00494
00495 S32 vertex_count = 0;
00496 S32 index_count = 0;
00497
00498
00499 *(normals++) = LLVector3(-SRR2, -SRR2, 0.f);
00500 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
00501 *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f);
00502 vertex_count++;
00503
00504 *(normals++) = LLVector3(SRR3, -SRR3, SRR3);
00505 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
00506 *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
00507 vertex_count++;
00508
00509 *(normals++) = LLVector3(-SRR3, -SRR3, SRR3);
00510 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
00511 *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
00512 vertex_count++;
00513
00514 *(normals++) = LLVector3(SRR2, -SRR2, 0.f);
00515 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
00516 *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f);
00517 vertex_count++;
00518
00519
00520 *(indicesp++) = 0;
00521 index_count++;
00522 *(indicesp++) = 1;
00523 index_count++;
00524 *(indicesp++) = 2;
00525 index_count++;
00526
00527 *(indicesp++) = 0;
00528 index_count++;
00529 *(indicesp++) = 3;
00530 index_count++;
00531 *(indicesp++) = 1;
00532 index_count++;
00533
00534
00535 *(normals++) = LLVector3(-SRR2, SRR2, 0.f);
00536 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
00537 *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f);
00538 vertex_count++;
00539
00540 *(normals++) = LLVector3(SRR3, SRR3, SRR3);
00541 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
00542 *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
00543 vertex_count++;
00544
00545 *(normals++) = LLVector3(-SRR3, SRR3, SRR3);
00546 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
00547 *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
00548 vertex_count++;
00549
00550 *(normals++) = LLVector3(SRR2, SRR2, 0.f);
00551 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
00552 *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f);
00553 vertex_count++;
00554
00555 *(indicesp++) = 4;
00556 index_count++;
00557 *(indicesp++) = 6;
00558 index_count++;
00559 *(indicesp++) = 5;
00560 index_count++;
00561
00562 *(indicesp++) = 4;
00563 index_count++;
00564 *(indicesp++) = 5;
00565 index_count++;
00566 *(indicesp++) = 7;
00567 index_count++;
00568
00569
00570
00571 *(normals++) = LLVector3(SRR2, -SRR2, 0.f);
00572 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
00573 *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f);
00574 vertex_count++;
00575
00576 *(normals++) = LLVector3(SRR3, SRR3, SRR3);
00577 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
00578 *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);
00579 vertex_count++;
00580
00581 *(normals++) = LLVector3(SRR3, -SRR3, SRR3);
00582 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
00583 *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);
00584 vertex_count++;
00585
00586 *(normals++) = LLVector3(SRR2, SRR2, 0.f);
00587 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
00588 *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f);
00589 vertex_count++;
00590
00591 *(indicesp++) = 8;
00592 index_count++;
00593 *(indicesp++) = 9;
00594 index_count++;
00595 *(indicesp++) = 10;
00596 index_count++;
00597
00598 *(indicesp++) = 8;
00599 index_count++;
00600 *(indicesp++) = 11;
00601 index_count++;
00602 *(indicesp++) = 9;
00603 index_count++;
00604
00605
00606
00607 *(normals++) = LLVector3(-SRR2, -SRR2, 0.f);
00608 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM);
00609 *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f);
00610 vertex_count++;
00611
00612 *(normals++) = LLVector3(-SRR3, SRR3, SRR3);
00613 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP);
00614 *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);
00615 vertex_count++;
00616
00617 *(normals++) = LLVector3(-SRR3, -SRR3, SRR3);
00618 *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP);
00619 *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);
00620 vertex_count++;
00621
00622 *(normals++) = LLVector3(-SRR2, SRR2, 0.f);
00623 *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
00624 *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f);
00625 vertex_count++;
00626
00627 *(indicesp++) = 12;
00628 index_count++;
00629 *(indicesp++) = 14;
00630 index_count++;
00631 *(indicesp++) = 13;
00632 index_count++;
00633
00634 *(indicesp++) = 12;
00635 index_count++;
00636 *(indicesp++) = 13;
00637 index_count++;
00638 *(indicesp++) = 15;
00639 index_count++;
00640
00641
00642
00643
00644
00645
00646
00647
00648 for (lod = 0; lod < 4; lod++)
00649 {
00650 slices = sLODSlices[lod];
00651 F32 base_radius = 0.65f;
00652 F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper;
00653
00654
00655 F32 angle = 0;
00656 F32 angle_inc = 360.f/(slices-1);
00657 F32 z = 0.f;
00658 F32 z_inc = 1.f;
00659 if (slices > 3)
00660 {
00661 z_inc = 1.f/(slices - 3);
00662 }
00663 F32 radius = base_radius;
00664
00665 F32 x1,y1;
00666 F32 noise_scale = sSpeciesTable[mSpecies]->mNoiseMag;
00667 LLVector3 nvec;
00668
00669 const F32 cap_nudge = 0.1f;
00670
00671 const S32 fractal_depth = 5;
00672 F32 nvec_scale = 1.f * sSpeciesTable[mSpecies]->mNoiseScale;
00673 F32 nvec_scalez = 4.f * sSpeciesTable[mSpecies]->mNoiseScale;
00674
00675 F32 tex_z_repeat = sSpeciesTable[mSpecies]->mRepeatTrunkZ;
00676
00677 F32 start_radius;
00678 F32 nangle = 0;
00679 F32 height = 1.f;
00680 F32 r0;
00681
00682 for (i = 0; i < slices; i++)
00683 {
00684 if (i == 0)
00685 {
00686 z = - cap_nudge;
00687 r0 = 0.0;
00688 }
00689 else if (i == (slices - 1))
00690 {
00691 z = 1.f + cap_nudge;
00692 r0 = 0.0;
00693 }
00694 else
00695 {
00696 z = (i - 1) * z_inc;
00697 r0 = base_radius + (top_radius - base_radius)*z;
00698 }
00699
00700 for (j = 0; j < slices; j++)
00701 {
00702 if (slices - 1 == j)
00703 {
00704 angle = 0.f;
00705 }
00706 else
00707 {
00708 angle = j*angle_inc;
00709 }
00710
00711 nangle = angle;
00712
00713 x1 = cos(angle * DEG_TO_RAD);
00714 y1 = sin(angle * DEG_TO_RAD);
00715 LLVector2 tc;
00716
00717 start_radius = r0 * (1.f + 1.2f*fabs(z - 0.66f*height)/height);
00718 nvec.setVec( cos(nangle * DEG_TO_RAD)*start_radius*nvec_scale,
00719 sin(nangle * DEG_TO_RAD)*start_radius*nvec_scale,
00720 z*nvec_scalez);
00721
00722 radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale;
00723
00724 if (slices - 1 == j)
00725 {
00726
00727 tc = LLVector2(0.490f, (1.f - z/2.f)*tex_z_repeat);
00728 }
00729 else
00730 {
00731 tc = LLVector2((angle/360.f)*0.5f, (1.f - z/2.f)*tex_z_repeat);
00732 }
00733
00734 *(vertices++) = LLVector3(x1*radius, y1*radius, z);
00735 *(normals++) = LLVector3(x1, y1, 0.f);
00736 *(tex_coords++) = tc;
00737 vertex_count++;
00738 }
00739 }
00740
00741 for (i = 0; i < (slices - 1); i++)
00742 {
00743 for (j = 0; j < (slices - 1); j++)
00744 {
00745 S32 x1_offset = j+1;
00746 if ((j+1) == slices)
00747 {
00748 x1_offset = 0;
00749 }
00750
00751 *(indicesp) = j + (i*slices) + sLODVertexOffset[lod];
00752 llassert(*(indicesp) < (U32)max_vertices);
00753 indicesp++;
00754 index_count++;
00755 *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod];
00756 llassert(*(indicesp) < (U32)max_vertices);
00757 indicesp++;
00758 index_count++;
00759 *(indicesp) = j + ((i+1)*slices) + sLODVertexOffset[lod];
00760 llassert(*(indicesp) < (U32)max_vertices);
00761 indicesp++;
00762 index_count++;
00763
00764 *(indicesp) = j + (i*slices) + sLODVertexOffset[lod];
00765 llassert(*(indicesp) < (U32)max_vertices);
00766 indicesp++;
00767 index_count++;
00768 *(indicesp) = x1_offset + (i*slices) + sLODVertexOffset[lod];
00769 llassert(*(indicesp) < (U32)max_vertices);
00770 indicesp++;
00771 index_count++;
00772 *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod];
00773 llassert(*(indicesp) < (U32)max_vertices);
00774 indicesp++;
00775 index_count++;
00776 }
00777 }
00778 slices /= 2;
00779 }
00780
00781 face->mVertexBuffer->setBuffer(0);
00782 llassert(vertex_count == max_vertices);
00783 llassert(index_count == max_indices);
00784
00785 return TRUE;
00786 }
00787
00788 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)
00789 {
00790 U32 ret = 0;
00791
00792
00793
00794
00795
00796 static F32 constant_twist;
00797 static F32 width = 0;
00798
00799
00800
00801 F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength);
00802 F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect);
00803
00804 constant_twist = 360.f/branches;
00805
00806 if (!LLPipeline::sReflectionRender && stop_level >= 0)
00807 {
00808
00809
00810
00811 if (depth > stop_level)
00812 {
00813 {
00814 llassert(sLODIndexCount[trunk_LOD] > 0);
00815 width = scale * length * aspect;
00816 LLMatrix4 scale_mat;
00817 scale_mat.mMatrix[0][0] = width;
00818 scale_mat.mMatrix[1][1] = width;
00819 scale_mat.mMatrix[2][2] = scale*length;
00820 scale_mat *= matrix;
00821
00822 glLoadMatrixf((F32*) scale_mat.mMatrix);
00823 glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_SHORT, indicesp + sLODIndexOffset[trunk_LOD]);
00824 gPipeline.addTrianglesDrawn(LEAF_INDICES/3);
00825 stop_glerror();
00826 ret += sLODIndexCount[trunk_LOD];
00827 }
00828
00829
00830 for (S32 i=0; i < (S32)branches; i++)
00831 {
00832 LLMatrix4 trans_mat;
00833 trans_mat.setTranslation(0,0,scale*length);
00834 trans_mat *= matrix;
00835
00836 LLQuaternion rot =
00837 LLQuaternion(20.f*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)) *
00838 LLQuaternion(droop*DEG_TO_RAD, LLVector4(0.f, 1.f, 0.f)) *
00839 LLQuaternion(((constant_twist + ((i%2==0)?twist:-twist))*i)*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f));
00840
00841 LLMatrix4 rot_mat(rot);
00842 rot_mat *= trans_mat;
00843
00844 ret += drawBranchPipeline(rot_mat, indicesp, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
00845 }
00846
00847 if (trunk_depth)
00848 {
00849 LLMatrix4 trans_mat;
00850 trans_mat.setTranslation(0,0,scale*length);
00851 trans_mat *= matrix;
00852
00853 LLMatrix4 rot_mat(70.5f*DEG_TO_RAD, LLVector4(0,0,1));
00854 rot_mat *= trans_mat;
00855 ret += drawBranchPipeline(rot_mat, indicesp, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha);
00856 }
00857 }
00858 else
00859 {
00860
00861
00862
00863 {
00864 LLMatrix4 scale_mat;
00865 scale_mat.mMatrix[0][0] =
00866 scale_mat.mMatrix[1][1] =
00867 scale_mat.mMatrix[2][2] = scale*mLeafScale;
00868
00869 scale_mat *= matrix;
00870
00871
00872 glLoadMatrixf((F32*) scale_mat.mMatrix);
00873 glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp);
00874 gPipeline.addTrianglesDrawn(LEAF_INDICES/3);
00875 stop_glerror();
00876 ret += LEAF_INDICES;
00877 }
00878 }
00879 }
00880 else
00881 {
00882
00883
00884
00885
00886 LLMatrix4 scale_mat;
00887 scale_mat.mMatrix[0][0] =
00888 scale_mat.mMatrix[1][1] =
00889 scale_mat.mMatrix[2][2] = mBillboardScale*mBillboardRatio;
00890
00891 scale_mat *= matrix;
00892
00893 glMatrixMode(GL_TEXTURE);
00894 glTranslatef(0.0, -0.5, 0.0);
00895 glMatrixMode(GL_MODELVIEW);
00896
00897 glLoadMatrixf((F32*) scale_mat.mMatrix);
00898 glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp);
00899 gPipeline.addTrianglesDrawn(LEAF_INDICES/3);
00900 stop_glerror();
00901 ret += LEAF_INDICES;
00902
00903 glMatrixMode(GL_TEXTURE);
00904 glLoadIdentity();
00905 glMatrixMode(GL_MODELVIEW);
00906 }
00907
00908 return ret;
00909 }
00910
00911 void LLVOTree::updateRadius()
00912 {
00913 if (mDrawable.isNull())
00914 {
00915 return;
00916 }
00917
00918 mDrawable->setRadius(32.0f);
00919 }
00920
00921 void LLVOTree::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax)
00922 {
00923 F32 radius = getScale().magVec()*0.05f;
00924 LLVector3 center = getRenderPosition();
00925
00926 F32 sz = mBillboardScale*mBillboardRatio*radius*0.5f;
00927 LLVector3 size(sz,sz,sz);
00928
00929 center += LLVector3(0, 0, size.mV[2]) * getRotation();
00930
00931 newMin.setVec(center-size);
00932 newMax.setVec(center+size);
00933 mDrawable->setPositionGroup(center);
00934 }
00935
00936 U32 LLVOTree::getPartitionType() const
00937 {
00938 return LLViewerRegion::PARTITION_TREE;
00939 }
00940
00941 LLTreePartition::LLTreePartition()
00942 : LLSpatialPartition(0)
00943 {
00944 mRenderByGroup = FALSE;
00945 mDrawableType = LLPipeline::RENDER_TYPE_TREE;
00946 mPartitionType = LLViewerRegion::PARTITION_TREE;
00947 mSlopRatio = 0.f;
00948 mLODPeriod = 1;
00949 }
00950