llvotree.cpp

Go to the documentation of this file.
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 // Tree variables and functions
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 // static
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];                /* Flawfinder: ignore */
00240 
00241                 for (S32 i=0;i<sMaxTreeSpecies;++i)
00242                 {
00243                         if (!sSpeciesTable.count(i))
00244                         {
00245                                 snprintf(buffer,10," %d",i);            /* Flawfinder: ignore */
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 //static
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         // Do base class updates...
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                 // Nothing else needs to be done for the terse message.
00286                 return retval;
00287         }
00288 
00289         // 
00290         //  Load Instance-Specific data 
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         //  Load Species-Specific data 
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;                          //  How many frames between wind update per tree
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         //  For all tree objects, update the trunk bending with the current wind 
00346         //  Walk sprite list in order away from viewer 
00347         if (!(mFrameCount % FRAMES_PER_WIND_UPDATE)) 
00348         {
00349                 //  If needed, Get latest wind for this tree
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);                //  Pull in direction of wind
00356         mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS);            //  Restoring force in direction of trunk       
00357         mTrunkBend += mTrunkVel;
00358         mTrunkVel *= 0.99f;                                                                     //  Add damping
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         // First calculate values as for any other object (for mAppAngle)
00386         LLViewerObject::setPixelAreaAndAngle(agent);
00387 
00388         // Re-calculate mPixelArea accurately
00389         
00390         // This should be the camera's center, as soon as we move to all region-local.
00391         LLVector3 relative_position = getPositionAgent() - agent.getCameraPositionAgent();
00392         F32 range = relative_position.magVec();                         // ugh, square root
00393 
00394         F32 max_scale = mBillboardScale * getMaxScale();
00395         F32 area = max_scale * (max_scale*mBillboardRatio);
00396 
00397         // Compute pixels per meter at the given range
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         // mAppAngle is a bit of voodoo;
00404         // use the one calculated LLViewerObject::setPixelAreaAndAngle above
00405         // to avoid LOD miscalculations
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         // Just a placeholder for an actual object...
00434         LLFace *facep = mDrawable->addFace(poolp, mTreeImagep);
00435         facep->setSize(1, 3);
00436 
00437         updateRadius();
00438 
00439         return mDrawable;
00440 }
00441 
00442 
00443 // Yes, I know this is bad.  I'll clean this up soon. - djs 04/02/02
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         // First leaf
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         // Same leaf, inverse winding/normals
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         //*(tex_coords++) =     LLVector2(1.f, 1.0f);
00549         *(tex_coords++) =       LLVector2(LEAF_RIGHT, LEAF_TOP);
00550         *(vertices++) =         LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
00551         vertex_count++;
00552 
00553         //*(tex_coords++) =     LLVector2(0.52f, 1.0f);
00554         *(tex_coords++) =       LLVector2(LEAF_LEFT, LEAF_TOP);
00555         *(vertices++) =         LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
00556         vertex_count++;
00557 
00558         //*(tex_coords++) =     LLVector2(1.f, 0.52f);
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         // Generate geometry for the cylinders
00650 
00651         // Different LOD's
00652 
00653         // Generate the vertices
00654         // Generate the indices
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                 //llinfos << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << llendl;
00662                 //llinfos << "Droop " << mDroop << ", branchlength: " << mBranchLength << llendl;
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;                     // Height to 'peak' the caps on top/bottom of branch
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;//((i - 2) * z_inc) + 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                                 // This isn't totally accurate.  Should compute based on slope as well.
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                                 // First and last slice at 0 radius (to bring in top/bottom of structure)
00730                                 radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale;
00731 
00732                                 if (slices - 1 == j)
00733                                 {
00734                                         // Not 0.5 for slight slop factor to avoid edges on leaves
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                                 // Generate the matching quads
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         //  Draws a tree by recursing, drawing branches and then a 'leaf' texture.
00800         //  If stop_level = -1, simply draws the whole tree as a billboarded texture
00801         //
00802         
00803         static F32 constant_twist;
00804         static F32 width = 0;
00805 
00806         //F32 length = ((scale == 1.f)? mTrunkLength:mBranchLength);
00807         //F32 aspect = ((scale == 1.f)? mTrunkAspect:mBranchAspect);
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                 //  Draw the tree using recursion
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                                 /*glDrawRangeElements(GL_TRIANGLES,
00827                                                                         sLODVertexOffset[trunk_LOD],
00828                                                                         sLODVertexOffset[trunk_LOD] + sLODVertexCount[trunk_LOD]-1,
00829                                                                         sLODIndexCount[trunk_LOD],
00830                                                                         GL_UNSIGNED_INT,
00831                                                                         indicesp + sLODIndexOffset[trunk_LOD]);*/
00832                                 stop_glerror();
00833                                 ret += sLODIndexCount[trunk_LOD];
00834                                 glPopMatrix();
00835                         }
00836                         
00837                         // Recurse to create more branches
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);                         // rotate 20deg about axis of new branch to add some random variation
00845                                 ret += drawBranchPipeline(indicesp, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
00846                                 glPopMatrix();
00847                         }
00848                         //  Recurse to continue trunk
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);                                        // rotate a bit around Z when ascending 
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                         //  Draw leaves as two 90 deg crossed quads with leaf textures
00862                         //
00863                         {
00864                                 glPushMatrix();
00865                                 //glRotatef(llFrand(50.0), llFrand(1.0), llFrand(1.0), llFrand(1.0);
00866                                 //width = scale * (TREE_BRANCH_ASPECT + TREE_LEAF_ASPECT);
00867                                 glScalef(scale*mLeafScale, scale*mLeafScale, scale*mLeafScale);
00868                                 //glScalef(1.5f*width*mLeafScale,1,1.5f*scale*mLeafScale);
00869                                 glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, indicesp);
00870                                 /*glDrawRangeElements(GL_TRIANGLES,
00871                                                                         0,
00872                                                                         LEAF_VERTICES-1,
00873                                                                         LEAF_INDICES,
00874                                                                         GL_UNSIGNED_INT,
00875                                                                         indicesp);*/
00876                                 stop_glerror();
00877                                 ret += LEAF_INDICES;
00878                                 glPopMatrix();
00879                         }
00880                 }
00881         }
00882         else
00883         {
00884                 //
00885                 //  Draw the tree as a single billboard texture 
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 /*                      glDrawRangeElements(GL_TRIANGLES,
00897                                                                 0,
00898                                                                 LEAF_VERTICES-1,
00899                                                                 LEAF_INDICES,
00900                                                                 GL_UNSIGNED_INT,
00901                                                                 indicesp);*/
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 

Generated on Thu Jul 1 06:09:43 2010 for Second Life Viewer by  doxygen 1.4.7