BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE))) { return TRUE; } S32 trunk_LOD = sMAX_NUM_TREE_LOD_LEVELS ; F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor; for (S32 j = 0; j < sMAX_NUM_TREE_LOD_LEVELS; j++) { if (app_angle > LLVOTree::sLODAngles[j]) { trunk_LOD = j; break; } } if (mReferenceBuffer.isNull()) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } else if (trunk_LOD != mTrunkLOD) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, FALSE); } else { // we're not animating but we may *still* need to // regenerate the mesh if we moved, since position // and rotation are baked into the mesh. // *TODO: I don't know what's so special about trees // that they don't get REBUILD_POSITION automatically // at a higher level. const LLVector3 &this_position = getPositionAgent(); if (this_position != mLastPosition) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); mLastPosition = this_position; } else { const LLQuaternion &this_rotation = getRotation(); if (this_rotation != mLastRotation) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); mLastRotation = this_rotation; } } } mTrunkLOD = trunk_LOD; return TRUE; }
BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { const U16 FRAMES_PER_WIND_UPDATE = 20; // How many frames between wind update per tree const F32 TREE_WIND_SENSITIVITY = 0.005f; const F32 TREE_TRUNK_STIFFNESS = 0.1f; if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE))) { return TRUE; } //it's cheaper to check if wind is enabled first if (gLLWindEnabled && gSavedSettings.getBOOL("RenderAnimateTrees")) { F32 mass_inv; // For all tree objects, update the trunk bending with the current wind // Walk sprite list in order away from viewer if (!(mFrameCount % FRAMES_PER_WIND_UPDATE)) { // If needed, Get latest wind for this tree mWind = mRegionp->mWind.getVelocity(getPositionRegion()); } mFrameCount++; mass_inv = 1.f/(5.f + mDepth*mBranches*0.2f); mTrunkVel += (mWind * mass_inv * TREE_WIND_SENSITIVITY); // Pull in direction of wind mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS); // Restoring force in direction of trunk mTrunkBend += mTrunkVel; mTrunkVel *= 0.99f; // Add damping if (mTrunkBend.length() > 1.f) { mTrunkBend.normalize(); } if (mTrunkVel.length() > 1.f) { mTrunkVel.normalize(); } } S32 trunk_LOD = 0; F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor; for (S32 j = 0; j < 4; j++) { if (app_angle > LLVOTree::sLODAngles[j]) { trunk_LOD = j; break; } } if (!gLLWindEnabled || !gSavedSettings.getBOOL("RenderAnimateTrees")) { if (mReferenceBuffer.isNull()) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } else if (trunk_LOD != mTrunkLOD) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, FALSE); } else { // we're not animating but we may *still* need to // regenerate the mesh if we moved, since position // and rotation are baked into the mesh. // *TODO: I don't know what's so special about trees // that they don't get REBUILD_POSITION automatically // at a higher level. const LLVector3 &this_position = getPositionAgent(); if (this_position != mLastPosition) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); mLastPosition = this_position; } else { const LLQuaternion &this_rotation = getRotation(); if (this_rotation != mLastRotation) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); mLastRotation = this_rotation; } } } } mTrunkLOD = trunk_LOD; return TRUE; }