diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 301624f94..297648a40 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12221,7 +12221,7 @@ This should be as low as possible, but too low may break functionality 0 - + RenderNoAlpha Comment diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index d2faca835..bb2fb09eb 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -104,12 +104,12 @@ void LLDrawPoolTree::render(S32 pass) LLGLState test(GL_ALPHA_TEST, LLGLSLShader::sNoFixedFunction ? 0 : 1); LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); - /*static const LLCachedControl render_animate_trees("RenderAnimateTrees",false); - if (render_animate_trees) + static LLCachedControl sRenderAnimateTrees("RenderAnimateTrees", false); + if (sRenderAnimateTrees) { renderTree(); } - else*/ + else gGL.getTexUnit(sDiffTex)->bind(mTexturep); for (std::vector::iterator iter = mDrawFace.begin(); @@ -209,7 +209,7 @@ void LLDrawPoolTree::endShadowPass(S32 pass) gDeferredTreeShadowProgram.unbind(); } -/* +// void LLDrawPoolTree::renderTree(BOOL selecting) { LLGLState normalize(GL_NORMALIZE, TRUE); @@ -331,7 +331,7 @@ void LLDrawPoolTree::renderTree(BOOL selecting) //gGL.popMatrix(); } } -}*/ +}// BOOL LLDrawPoolTree::verify() const { diff --git a/indra/newview/lldrawpooltree.h b/indra/newview/lldrawpooltree.h index 5c63e8f4e..714dc25e1 100644 --- a/indra/newview/lldrawpooltree.h +++ b/indra/newview/lldrawpooltree.h @@ -75,8 +75,8 @@ public: static S32 sDiffTex; -//private: - //void renderTree(BOOL selecting = FALSE); +private: + void renderTree(BOOL selecting = FALSE); }; #endif // LL_LLDRAWPOOLTREE_H diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 8fd959cf2..545de0e3b 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -642,7 +642,7 @@ void settings_setup_listeners() gSavedSettings.getControl("OctreeAlphaDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeAttachmentSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("RenderMaxTextureIndex")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); - //gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); + gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderDepthOfField")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index a4d57e2d3..aab4c8acc 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -49,6 +49,7 @@ #include "llagentcamera.h" #include "lldrawable.h" #include "llface.h" +#include "llselectmgr.h" #include "llviewercamera.h" #include "llviewertexturelist.h" #include "llviewerobjectlist.h" @@ -57,6 +58,7 @@ #include "noise.h" #include "pipeline.h" #include "llspatialpartition.h" +//#include "llviewerwindow.h" #include "llnotificationsutil.h" #include "raytrace.h" #include "llglslshader.h" @@ -356,12 +358,47 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, void 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; } - - S32 trunk_LOD = sMAX_NUM_TREE_LOD_LEVELS ; + + static LLCachedControl sRenderAnimateTrees(gSavedSettings, "RenderAnimateTrees"); + if (sRenderAnimateTrees) + { + 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 = sMAX_NUM_TREE_LOD_LEVELS; F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor; for (S32 j = 0; j < sMAX_NUM_TREE_LOD_LEVELS; j++) @@ -373,41 +410,45 @@ void LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } } - if (mReferenceBuffer.isNull()) + if (!sRenderAnimateTrees) { - 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 = getPositionRegion(); - if (this_position != mLastPosition) + if (mReferenceBuffer.isNull()) { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); - mLastPosition = this_position; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); + } + else if (trunk_LOD != mTrunkLOD) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, FALSE); } else { - const LLQuaternion &this_rotation = getRotation(); - - if (this_rotation != mLastRotation) + // 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 = getPositionRegion(); + if (this_position != mLastPosition) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); - mLastRotation = this_rotation; + 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; } const F32 TREE_BLEND_MIN = 1.f; @@ -540,8 +581,9 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) max_indices += sLODIndexCount[lod]; max_vertices += sLODVertexCount[lod]; } - - mReferenceBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, 0); + + static LLCachedControl sRenderAnimateTrees(gSavedSettings, "RenderAnimateTrees"); + mReferenceBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, sRenderAnimateTrees ? GL_STATIC_DRAW_ARB : 0); mReferenceBuffer->allocateBuffer(max_vertices, max_indices, TRUE); LLStrider vertices; @@ -844,10 +886,18 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) llassert(vertex_count == max_vertices); llassert(index_count == max_indices); } - - //generate tree mesh - updateMesh(); + static LLCachedControl sRenderAnimateTrees(gSavedSettings, "RenderAnimateTrees"); + if (sRenderAnimateTrees) + { + mDrawable->getFace(0)->setVertexBuffer(mReferenceBuffer); + } + else + { + //generate tree mesh + updateMesh(); + } + return TRUE; } @@ -1314,3 +1364,110 @@ LLTreePartition::LLTreePartition() mLODPeriod = 1; } +void LLVOTree::generateSilhouetteVertices(std::vector &vertices, + std::vector &normals, + const LLVector3& obj_cam_vec, + const LLMatrix4& local_matrix, + const LLMatrix3& normal_matrix) +{ + vertices.clear(); + normals.clear(); + + F32 height = mBillboardScale; // *mBillboardRatio * 0.5; + F32 width = height * mTrunkAspect; + + LLVector3 position1 = LLVector3(-width * 0.5, 0, 0) * local_matrix; + LLVector3 position2 = LLVector3(-width * 0.5, 0, height) * local_matrix; + LLVector3 position3 = LLVector3(width * 0.5, 0, height) * local_matrix; + LLVector3 position4 = LLVector3(width * 0.5, 0, 0) * local_matrix; + + LLVector3 position5 = LLVector3(0, -width * 0.5, 0) * local_matrix; + LLVector3 position6 = LLVector3(0, -width * 0.5, height) * local_matrix; + LLVector3 position7 = LLVector3(0, width * 0.5, height) * local_matrix; + LLVector3 position8 = LLVector3(0, width * 0.5, 0) * local_matrix; + + LLVector3 normal = (position1 - position2) % (position2 - position3); + normal.normalize(); + + vertices.push_back(position1); + normals.push_back(normal); + vertices.push_back(position2); + normals.push_back(normal); + + vertices.push_back(position2); + normals.push_back(normal); + vertices.push_back(position3); + normals.push_back(normal); + + vertices.push_back(position3); + normals.push_back(normal); + vertices.push_back(position4); + normals.push_back(normal); + + vertices.push_back(position4); + normals.push_back(normal); + vertices.push_back(position1); + normals.push_back(normal); + + normal = (position5 - position6) % (position6 - position7); + normal.normalize(); + + vertices.push_back(position5); + normals.push_back(normal); + vertices.push_back(position6); + normals.push_back(normal); + + vertices.push_back(position6); + normals.push_back(normal); + vertices.push_back(position7); + normals.push_back(normal); + + vertices.push_back(position7); + normals.push_back(normal); + vertices.push_back(position8); + normals.push_back(normal); + + vertices.push_back(position8); + normals.push_back(normal); + vertices.push_back(position5); + normals.push_back(normal); +} + +void LLVOTree::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) +{ + LLVector3 position; + LLQuaternion rotation; + + if (mDrawable->isActive()) + { + if (mDrawable->isSpatialRoot()) + { + position = LLVector3(); + rotation = LLQuaternion(); + } + else + { + position = mDrawable->getPosition(); + rotation = mDrawable->getRotation(); + } + } + else + { + position = getPosition() + getRegion()->getOriginAgent(); + rotation = getRotation(); + } + + // trees have bizzare scaling rules... because it's cool to make needless exceptions + // PS: the trees are the last remaining tidbit of Philip's code. take a look sometime. + F32 radius = getScale().length() * 0.05f; + LLVector3 scale = LLVector3(1, 1, 1) * radius; + + // compose final matrix + LLMatrix4 local_matrix; + local_matrix.initAll(scale, rotation, position); + + generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, + LLVector3(0, 0, 0), local_matrix, LLMatrix3()); + + nodep->mSilhouetteExists = TRUE; +} diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h index f90503030..277280a2c 100644 --- a/indra/newview/llvotree.h +++ b/indra/newview/llvotree.h @@ -39,6 +39,7 @@ class LLFace; class LLDrawPool; +class LLSelectNode; class LLViewerFetchedTexture; class LLVOTree : public LLViewerObject @@ -122,8 +123,9 @@ public: LLVector3* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point LLVector3* normal = NULL, // return the surface normal at the intersection point - LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point - ); + LLVector3* bi_normal = NULL); // return the surface bi-normal at the intersection point + + void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point); static S32 sMaxTreeSpecies; @@ -162,6 +164,7 @@ public: friend class LLDrawPoolTree; protected: LLVector3 mTrunkBend; // Accumulated wind (used for blowing trees) + LLVector3 mTrunkVel; // LLVector3 mWind; LLPointer mReferenceBuffer; //reference geometry for generating tree mesh @@ -201,6 +204,13 @@ protected: static S32 sLODVertexCount[4]; static S32 sLODSlices[4]; static F32 sLODAngles[4]; + +private: + void generateSilhouetteVertices(std::vector &vertices, + std::vector &normals, + const LLVector3& view_vec, + const LLMatrix4& mat, + const LLMatrix3& norm_mat); }; #endif