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