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

Generated on Fri May 16 08:34:23 2008 for SecondLife by  doxygen 1.5.5