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; }
U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, EObjectUpdateType update_type, LLDataPacker *dp) { // Do base class updates... U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); if ( (getVelocity().lengthSquared() > 0.f) ||(getAcceleration().lengthSquared() > 0.f) ||(getAngularVelocity().lengthSquared() > 0.f)) { llinfos << "ACK! Moving tree!" << llendl; setVelocity(LLVector3::zero); setAcceleration(LLVector3::zero); setAngularVelocity(LLVector3::zero); } if (update_type == OUT_TERSE_IMPROVED) { // Nothing else needs to be done for the terse message. return retval; } // // Load Instance-Specific data // if (mData) { mSpecies = ((U8 *)mData)[0]; } if (!sSpeciesTable.count(mSpecies)) { if (sSpeciesTable.size()) { SpeciesMap::const_iterator it = sSpeciesTable.begin(); mSpecies = (*it).first; } } // // Load Species-Specific data // mTreeImagep = gImageList.getImage(sSpeciesTable[mSpecies]->mTextureID); if (mTreeImagep) { gGL.getTexUnit(0)->bind(mTreeImagep.get()); } mBranchLength = sSpeciesTable[mSpecies]->mBranchLength; mTrunkLength = sSpeciesTable[mSpecies]->mTrunkLength; mLeafScale = sSpeciesTable[mSpecies]->mLeafScale; mDroop = sSpeciesTable[mSpecies]->mDroop; mTwist = sSpeciesTable[mSpecies]->mTwist; mBranches = sSpeciesTable[mSpecies]->mBranches; mDepth = sSpeciesTable[mSpecies]->mDepth; mScaleStep = sSpeciesTable[mSpecies]->mScaleStep; mTrunkDepth = sSpeciesTable[mSpecies]->mTrunkDepth; mBillboardScale = sSpeciesTable[mSpecies]->mBillboardScale; mBillboardRatio = sSpeciesTable[mSpecies]->mBillboardRatio; mTrunkAspect = sSpeciesTable[mSpecies]->mTrunkAspect; mBranchAspect = sSpeciesTable[mSpecies]->mBranchAspect; // position change not caused by us, etc. make sure to rebuild. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); return retval; }
U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, EObjectUpdateType update_type, LLDataPacker *dp) { // Do base class updates... U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); if ( (getVelocity().lengthSquared() > 0.f) ||(getAcceleration().lengthSquared() > 0.f) ||(getAngularVelocity().lengthSquared() > 0.f)) { llinfos << "ACK! Moving tree!" << llendl; setVelocity(LLVector3::zero); setAcceleration(LLVector3::zero); setAngularVelocity(LLVector3::zero); } if (update_type == OUT_TERSE_IMPROVED) { // Nothing else needs to be done for the terse message. return retval; } // // Load Instance-Specific data // if (mData) { mSpecies = ((U8 *)mData)[0]; } if (!sSpeciesTable.count(mSpecies)) { if (sSpeciesTable.size()) { SpeciesMap::const_iterator it = sSpeciesTable.begin(); mSpecies = (*it).first; } } // // Load Species-Specific data // static const S32 MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = 32 ; //frames. mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mTreeImagep->setMaxVirtualSizeResetInterval(MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); //allow to wait for at most 16 frames to reset virtual size. mBranchLength = sSpeciesTable[mSpecies]->mBranchLength; mTrunkLength = sSpeciesTable[mSpecies]->mTrunkLength; mLeafScale = sSpeciesTable[mSpecies]->mLeafScale; mDroop = sSpeciesTable[mSpecies]->mDroop; mTwist = sSpeciesTable[mSpecies]->mTwist; mBranches = sSpeciesTable[mSpecies]->mBranches; mDepth = sSpeciesTable[mSpecies]->mDepth; mScaleStep = sSpeciesTable[mSpecies]->mScaleStep; mTrunkDepth = sSpeciesTable[mSpecies]->mTrunkDepth; mBillboardScale = sSpeciesTable[mSpecies]->mBillboardScale; mBillboardRatio = sSpeciesTable[mSpecies]->mBillboardRatio; mTrunkAspect = sSpeciesTable[mSpecies]->mTrunkAspect; mBranchAspect = sSpeciesTable[mSpecies]->mBranchAspect; // position change not caused by us, etc. make sure to rebuild. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); return retval; }