summaryrefslogtreecommitdiff
path: root/indra/newview/llflexibleobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llflexibleobject.cpp')
-rwxr-xr-x[-rw-r--r--]indra/newview/llflexibleobject.cpp253
1 files changed, 169 insertions, 84 deletions
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index 32a533570a..98c0c0bf51 100644..100755
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -44,9 +44,11 @@
#include "llvoavatar.h"
/*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f;
+std::vector<LLVolumeImplFlexible*> LLVolumeImplFlexible::sInstanceList;
+std::vector<S32> LLVolumeImplFlexible::sUpdateDelay;
static LLFastTimer::DeclareTimer FTM_FLEXIBLE_REBUILD("Rebuild");
-static LLFastTimer::DeclareTimer FTM_DO_FLEXIBLE_UPDATE("Update");
+static LLFastTimer::DeclareTimer FTM_DO_FLEXIBLE_UPDATE("Flexible Update");
// LLFlexibleObjectData::pack/unpack now in llprimitive.cpp
@@ -64,14 +66,51 @@ LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectD
mSimulateRes = 0;
mFrameNum = 0;
mCollisionSphereRadius = 0.f;
- mRenderRes = 1;
-
+ mRenderRes = -1;
+
if(mVO->mDrawable.notNull())
{
mVO->mDrawable->makeActive() ;
}
+
+ mInstanceIndex = sInstanceList.size();
+ sInstanceList.push_back(this);
+ sUpdateDelay.push_back(0);
}//-----------------------------------------------
+LLVolumeImplFlexible::~LLVolumeImplFlexible()
+{
+ S32 end_idx = sInstanceList.size()-1;
+
+ if (end_idx != mInstanceIndex)
+ {
+ sInstanceList[mInstanceIndex] = sInstanceList[end_idx];
+ sInstanceList[mInstanceIndex]->mInstanceIndex = mInstanceIndex;
+ sUpdateDelay[mInstanceIndex] = sUpdateDelay[end_idx];
+ }
+
+ sInstanceList.pop_back();
+ sUpdateDelay.pop_back();
+}
+
+//static
+void LLVolumeImplFlexible::updateClass()
+{
+ std::vector<S32>::iterator delay_iter = sUpdateDelay.begin();
+
+ for (std::vector<LLVolumeImplFlexible*>::iterator iter = sInstanceList.begin();
+ iter != sInstanceList.end();
+ ++iter)
+ {
+ --(*delay_iter);
+ if (*delay_iter <= 0)
+ {
+ (*iter)->doIdleUpdate();
+ }
+ ++delay_iter;
+ }
+}
+
LLVector3 LLVolumeImplFlexible::getFramePosition() const
{
return mVO->getRenderPosition();
@@ -231,9 +270,6 @@ void LLVolumeImplFlexible::setAttributesOfAllSections(LLVector3* inScale)
mSection[0].mVelocity.setVec(0,0,0);
mSection[0].mAxisRotation.setQuat(begin_rot,0,0,1);
- LLVector3 parentSectionPosition = mSection[0].mPosition;
- LLVector3 last_direction = mSection[0].mDirection;
-
remapSections(mSection, mInitializedRes, mSection, mSimulateRes);
mInitializedRes = mSimulateRes;
@@ -255,50 +291,31 @@ void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, cons
{
}
-//---------------------------------------------------------------------------------
-// This calculates the physics of the flexible object. Note that it has to be 0
-// updated every time step. In the future, perhaps there could be an
-// optimization similar to what Havok does for objects that are stationary.
-//---------------------------------------------------------------------------------
-static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies");
-BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
+
+void LLVolumeImplFlexible::updateRenderRes()
{
- if (mVO->mDrawable.isNull())
- {
- // Don't do anything until we have a drawable
- return FALSE; // (we are not initialized or updated)
- }
+ if (!mAttributes)
+ return;
- BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE;
+ LLDrawable* drawablep = mVO->mDrawable;
- //flexible objects never go static
- mVO->mDrawable->mQuietCount = 0;
- if (!mVO->mDrawable->isRoot())
- {
- LLViewerObject* parent = (LLViewerObject*) mVO->getParent();
- parent->mDrawable->mQuietCount = 0;
- }
-
- LLFastTimer ftm(FTM_FLEXIBLE_UPDATE);
-
S32 new_res = mAttributes->getSimulateLOD();
- //number of segments only cares about z axis
- F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, mVO->mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
+#if 1 //optimal approximation of previous behavior that doesn't rely on atan2
+ F32 app_angle = mVO->getScale().mV[2]/drawablep->mDistanceWRTCamera;
// Rendering sections increases with visible angle on the screen
- mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/LLViewerCamera::getInstance()->getView());
- if (mRenderRes > FLEXIBLE_OBJECT_MAX_SECTIONS)
- {
- mRenderRes = FLEXIBLE_OBJECT_MAX_SECTIONS;
- }
-
+ mRenderRes = (S32) (12.f*app_angle);
+#else //legacy behavior
+ //number of segments only cares about z axis
+ F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, drawablep->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
- // Bottom cap at 1/4 the original number of sections
- if (mRenderRes < mAttributes->getSimulateLOD()-1)
- {
- mRenderRes = mAttributes->getSimulateLOD()-1;
- }
+ // Rendering sections increases with visible angle on the screen
+ mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/LLViewerCamera::getInstance()->getView());
+#endif
+
+ mRenderRes = llclamp(mRenderRes, new_res-1, (S32) FLEXIBLE_OBJECT_MAX_SECTIONS);
+
// Throttle back simulation of segments we're not rendering
if (mRenderRes < new_res)
{
@@ -311,43 +328,87 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6
setAttributesOfAllSections();
mInitialized = TRUE;
}
- if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
- {
- return FALSE; // (we are not initialized or updated)
- }
-
- bool visible = mVO->mDrawable->isVisible();
+}
+//---------------------------------------------------------------------------------
+// This calculates the physics of the flexible object. Note that it has to be 0
+// updated every time step. In the future, perhaps there could be an
+// optimization similar to what Havok does for objects that are stationary.
+//---------------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies");
+void LLVolumeImplFlexible::doIdleUpdate()
+{
+ LLDrawable* drawablep = mVO->mDrawable;
- if (force_update && visible)
+ if (drawablep)
{
- gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE);
- }
- else if (visible &&
- !mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) &&
- mVO->getPixelArea() > 256.f)
- {
- U32 id;
- F32 pixel_area = mVO->getPixelArea();
+ //LLFastTimer ftm(FTM_FLEXIBLE_UPDATE);
- if (mVO->isRootEdit())
- {
- id = mID;
- }
- else
+ //ensure drawable is active
+ drawablep->makeActive();
+
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
{
- LLVOVolume* parent = (LLVOVolume*) mVO->getParent();
- id = parent->getVolumeInterfaceID();
- }
+ bool visible = drawablep->isVisible();
- U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1;
+ if (mRenderRes == -1)
+ {
+ updateRenderRes();
+ gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE);
+ sUpdateDelay[mInstanceIndex] = 0;
+ }
+ else
+ {
+ F32 pixel_area = mVO->getPixelArea();
+
+ U32 update_period = (U32) (llmax((S32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f))),0)+1);
+ // MAINT-1890 Clamp the update period to ensure that the update_period is no greater than 32 frames
+ update_period = llclamp(update_period, 0U, 32U);
+
+ if (visible)
+ {
+ if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1) &&
+ pixel_area > 256.f)
+ {
+ U32 id;
+
+ if (mVO->isRootEdit())
+ {
+ id = mID;
+ }
+ else
+ {
+ LLVOVolume* parent = (LLVOVolume*) mVO->getParent();
+ id = parent->getVolumeInterfaceID();
+ }
+
+ if (mVO->isRootEdit())
+ {
+ id = mID;
+ }
+ else
+ {
+ LLVOVolume* parent = (LLVOVolume*) mVO->getParent();
+ id = parent->getVolumeInterfaceID();
+ }
+
+ if ((LLDrawable::getCurrentFrame()+id)%update_period == 0)
+ {
+ sUpdateDelay[mInstanceIndex] = (S32) update_period-1;
+
+ updateRenderRes();
+
+ gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE);
+ }
+ }
+ }
+ else
+ {
+ sUpdateDelay[mInstanceIndex] = (S32) update_period;
+ }
+}
- if ((LLDrawable::getCurrentFrame()+id)%update_period == 0)
- {
- gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE);
}
}
-
- return force_update;
}
inline S32 log2(S32 x)
@@ -368,18 +429,29 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
LLPath *path = &volume->getPath();
if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible())
{
- mVO->markForUpdate(TRUE);
- if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0))
+ BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE;
+ doIdleUpdate();
+
+ if (!force_update || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
{
return; // we did not get updated or initialized, proceeding without can be dangerous
}
}
- if(!mInitialized)
+ if(!mInitialized || !mAttributes)
{
//the object is not visible
return ;
}
+
+ // Fix for MAINT-1894
+ // Skipping the flexible update if render res is negative. If we were to continue with a negative value,
+ // the subsequent S32 num_render_sections = 1<<mRenderRes; code will specify a really large number of
+ // render sections which will then create a length exception in the std::vector::resize() method.
+ if (mRenderRes < 0)
+ {
+ return;
+ }
S32 num_sections = 1 << mSimulateRes;
@@ -588,6 +660,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
mSection[i].mdPosition = (mSection[i].mPosition - mSection[i-1].mPosition) * inv_section_length;
// Create points
+ llassert(mRenderRes > -1)
S32 num_render_sections = 1<<mRenderRes;
if (path->getPathLength() != num_render_sections+1)
{
@@ -619,30 +692,36 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
LLVector4(z_axis, 0.f),
LLVector4(delta_pos, 1.f));
+ LL_CHECK_MEMORY
for (i=0; i<=num_render_sections; ++i)
{
new_point = &path->mPath[i];
LLVector3 pos = newSection[i].mPosition * rel_xform;
LLQuaternion rot = mSection[i].mAxisRotation * newSection[i].mRotation * delta_rot;
-
- if (!mUpdated || (new_point->mPos-pos).magVec()/mVO->mDrawable->mDistanceWRTCamera > 0.001f)
+
+ LLVector3 np(new_point->mPos.getF32ptr());
+
+ if (!mUpdated || (np-pos).magVec()/mVO->mDrawable->mDistanceWRTCamera > 0.001f)
{
- new_point->mPos = newSection[i].mPosition * rel_xform;
+ new_point->mPos.load3((newSection[i].mPosition * rel_xform).mV);
mUpdated = FALSE;
}
- new_point->mRot = rot;
- new_point->mScale = newSection[i].mScale;
+ new_point->mRot.loadu(LLMatrix3(rot));
+ new_point->mScale.set(newSection[i].mScale.mV[0], newSection[i].mScale.mV[1], 0,1);
new_point->mTexT = ((F32)i)/(num_render_sections);
}
-
+ LL_CHECK_MEMORY
mLastSegmentRotation = parentSegmentRotation;
}
+static LLFastTimer::DeclareTimer FTM_FLEXI_PREBUILD("Flexi Prebuild");
+
void LLVolumeImplFlexible::preRebuild()
{
if (!mUpdated)
{
+ LLFastTimer t(FTM_FLEXI_PREBUILD);
doFlexibleRebuild();
}
}
@@ -729,7 +808,11 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
else if (!mUpdated || rotated)
{
volume->mDrawable->setState(LLDrawable::REBUILD_POSITION);
- volume->dirtyMesh();
+ LLSpatialGroup* group = volume->mDrawable->getSpatialGroup();
+ if (group)
+ {
+ group->dirtyMesh();
+ }
volume->genBBoxes(isVolumeGlobal());
}
@@ -814,15 +897,17 @@ LLQuaternion LLVolumeImplFlexible::getEndRotation()
}//------------------------------------------------------------------
-void LLVolumeImplFlexible::updateRelativeXform()
+void LLVolumeImplFlexible::updateRelativeXform(bool force_identity)
{
LLQuaternion delta_rot;
LLVector3 delta_pos, delta_scale;
LLVOVolume* vo = (LLVOVolume*) mVO;
+ bool use_identity = vo->mDrawable->isSpatialRoot() || force_identity;
+
//matrix from local space to parent relative/global space
- delta_rot = vo->mDrawable->isSpatialRoot() ? LLQuaternion() : vo->mDrawable->getRotation();
- delta_pos = vo->mDrawable->isSpatialRoot() ? LLVector3(0,0,0) : vo->mDrawable->getPosition();
+ delta_rot = use_identity ? LLQuaternion() : vo->mDrawable->getRotation();
+ delta_pos = use_identity ? LLVector3(0,0,0) : vo->mDrawable->getPosition();
delta_scale = LLVector3(1,1,1);
// Vertex transform (4x4)