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