summaryrefslogtreecommitdiff
path: root/indra/newview/llflexibleobject.cpp
diff options
context:
space:
mode:
authorAndrey Lihatskiy <alihatskiy@productengine.com>2024-05-15 11:16:27 +0300
committerAndrey Lihatskiy <alihatskiy@productengine.com>2024-05-15 11:16:27 +0300
commitbccc10db9a90d365c353baebf443fde2030ce970 (patch)
tree2c2e1fd94b29667a809f8d7285d049f5ff5d424d /indra/newview/llflexibleobject.cpp
parent531cd34f670170ade57f8813fe48012b61a1d3c2 (diff)
parentbb3c36f5cbc0c3b542045fd27255eee24e03da22 (diff)
Merge branch 'main' into marchcat/x-b-merge
# Conflicts: # autobuild.xml # indra/cmake/ConfigurePkgConfig.cmake # indra/cmake/ICU4C.cmake # indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp # indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h # indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h # indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp # indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h # indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp # indra/newview/llappviewerlinux_api.h # indra/newview/llappviewerlinux_api_dbus.cpp # indra/newview/llappviewerlinux_api_dbus.h # indra/newview/llfloateremojipicker.cpp # indra/newview/lloutfitslist.cpp
Diffstat (limited to 'indra/newview/llflexibleobject.cpp')
-rw-r--r--indra/newview/llflexibleobject.cpp1448
1 files changed, 724 insertions, 724 deletions
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index e935bc5553..7ed62d68bd 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llflexibleobject.cpp
* @brief Flexible object implementation
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -53,40 +53,40 @@ std::vector<LLVolumeImplFlexible*> LLVolumeImplFlexible::sInstanceList;
// constructor
//-----------------------------------------------
LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectData* attributes) :
- mVO(vo),
- mAttributes(attributes),
- mLastFrameNum(0),
- mLastUpdatePeriod(0)
+ mVO(vo),
+ mAttributes(attributes),
+ mLastFrameNum(0),
+ mLastUpdatePeriod(0)
{
- static U32 seed = 0;
- mID = seed++;
- mInitialized = FALSE;
- mUpdated = FALSE;
- mInitializedRes = -1;
- mSimulateRes = 0;
- mCollisionSphereRadius = 0.f;
- mRenderRes = -1;
-
- if(mVO->mDrawable.notNull())
- {
- mVO->mDrawable->makeActive() ;
- }
-
- mInstanceIndex = sInstanceList.size();
- sInstanceList.push_back(this);
+ static U32 seed = 0;
+ mID = seed++;
+ mInitialized = FALSE;
+ mUpdated = FALSE;
+ mInitializedRes = -1;
+ mSimulateRes = 0;
+ mCollisionSphereRadius = 0.f;
+ mRenderRes = -1;
+
+ if(mVO->mDrawable.notNull())
+ {
+ mVO->mDrawable->makeActive() ;
+ }
+
+ mInstanceIndex = sInstanceList.size();
+ sInstanceList.push_back(this);
}//-----------------------------------------------
LLVolumeImplFlexible::~LLVolumeImplFlexible()
{
- S32 end_idx = sInstanceList.size()-1;
-
- if (end_idx != mInstanceIndex)
- {
- sInstanceList[mInstanceIndex] = sInstanceList[end_idx];
- sInstanceList[mInstanceIndex]->mInstanceIndex = mInstanceIndex;
- }
-
- sInstanceList.pop_back();
+ S32 end_idx = sInstanceList.size()-1;
+
+ if (end_idx != mInstanceIndex)
+ {
+ sInstanceList[mInstanceIndex] = sInstanceList[end_idx];
+ sInstanceList[mInstanceIndex]->mInstanceIndex = mInstanceIndex;
+ }
+
+ sInstanceList.pop_back();
}
//static
@@ -94,194 +94,194 @@ void LLVolumeImplFlexible::updateClass()
{
LL_PROFILE_ZONE_SCOPED;
- U64 virtual_frame_num = LLTimer::getElapsedSeconds() / SEC_PER_FLEXI_FRAME;
- for (std::vector<LLVolumeImplFlexible*>::iterator iter = sInstanceList.begin();
- iter != sInstanceList.end();
- ++iter)
- {
- // Note: by now update period might have changed
- if ((*iter)->mRenderRes == -1
- || (*iter)->mLastFrameNum + (*iter)->mLastUpdatePeriod <= virtual_frame_num
- || (*iter)->mLastFrameNum > virtual_frame_num) //time issues, overflow
- {
- (*iter)->doIdleUpdate();
- }
- }
+ U64 virtual_frame_num = LLTimer::getElapsedSeconds() / SEC_PER_FLEXI_FRAME;
+ for (std::vector<LLVolumeImplFlexible*>::iterator iter = sInstanceList.begin();
+ iter != sInstanceList.end();
+ ++iter)
+ {
+ // Note: by now update period might have changed
+ if ((*iter)->mRenderRes == -1
+ || (*iter)->mLastFrameNum + (*iter)->mLastUpdatePeriod <= virtual_frame_num
+ || (*iter)->mLastFrameNum > virtual_frame_num) //time issues, overflow
+ {
+ (*iter)->doIdleUpdate();
+ }
+ }
}
LLVector3 LLVolumeImplFlexible::getFramePosition() const
{
- return mVO->getRenderPosition();
+ return mVO->getRenderPosition();
}
LLQuaternion LLVolumeImplFlexible::getFrameRotation() const
{
- return mVO->getRenderRotation();
+ return mVO->getRenderRotation();
}
void LLVolumeImplFlexible::onParameterChanged(U16 param_type, LLNetworkData *data, BOOL in_use, bool local_origin)
{
- if (param_type == LLNetworkData::PARAMS_FLEXIBLE)
- {
- mAttributes = (LLFlexibleObjectData*)data;
- setAttributesOfAllSections();
- }
+ if (param_type == LLNetworkData::PARAMS_FLEXIBLE)
+ {
+ mAttributes = (LLFlexibleObjectData*)data;
+ setAttributesOfAllSections();
+ }
}
void LLVolumeImplFlexible::onShift(const LLVector4a &shift_vector)
-{
- //VECTORIZE THIS
- LLVector3 shift(shift_vector.getF32ptr());
- for (int section = 0; section < (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1; ++section)
- {
- mSection[section].mPosition += shift;
- }
+{
+ //VECTORIZE THIS
+ LLVector3 shift(shift_vector.getF32ptr());
+ for (int section = 0; section < (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1; ++section)
+ {
+ mSection[section].mPosition += shift;
+ }
}
//-----------------------------------------------------------------------------------------------
void LLVolumeImplFlexible::setParentPositionAndRotationDirectly( LLVector3 p, LLQuaternion r )
{
- mParentPosition = p;
- mParentRotation = r;
+ mParentPosition = p;
+ mParentRotation = r;
}//-----------------------------------------------------------------------------------------------------
void LLVolumeImplFlexible::remapSections(LLFlexibleObjectSection *source, S32 source_sections,
- LLFlexibleObjectSection *dest, S32 dest_sections)
-{
- S32 num_output_sections = 1<<dest_sections;
- LLVector3 scale = mVO->mDrawable->getScale();
- F32 source_section_length = scale.mV[VZ] / (F32)(1<<source_sections);
- F32 section_length = scale.mV[VZ] / (F32)num_output_sections;
- if (source_sections == -1)
- {
- // Generate all from section 0
- dest[0] = source[0];
- for (S32 section=0; section<num_output_sections; ++section)
- {
- dest[section+1] = dest[section];
- dest[section+1].mPosition += dest[section].mDirection * section_length;
- dest[section+1].mVelocity.setVec( LLVector3::zero );
- }
- }
- else if (source_sections > dest_sections)
- {
- // Copy, skipping sections
-
- S32 num_steps = 1<<(source_sections-dest_sections);
-
- // Copy from left to right since it may be an in-place computation
- for (S32 section=0; section<num_output_sections; ++section)
- {
- dest[section+1] = source[(section+1)*num_steps];
- }
- dest[0] = source[0];
- }
- else if (source_sections < dest_sections)
- {
- // Interpolate section info
- // Iterate from right to left since it may be an in-place computation
- S32 step_shift = dest_sections-source_sections;
- S32 num_steps = 1<<step_shift;
- for (S32 section=num_output_sections-num_steps; section>=0; section -= num_steps)
- {
- LLFlexibleObjectSection *last_source_section = &source[section>>step_shift];
- LLFlexibleObjectSection *source_section = &source[(section>>step_shift)+1];
-
- // Cubic interpolation of position
- // At^3 + Bt^2 + Ct + D = f(t)
- LLVector3 D = last_source_section->mPosition;
- LLVector3 C = last_source_section->mdPosition * source_section_length;
- LLVector3 Y = source_section->mdPosition * source_section_length - C; // Helper var
- LLVector3 X = (source_section->mPosition - D - C); // Helper var
- LLVector3 A = Y - 2*X;
- LLVector3 B = X - A;
-
- F32 t_inc = 1.f/F32(num_steps);
- F32 t = t_inc;
- for (S32 step=1; step<num_steps; ++step)
- {
- dest[section+step].mScale =
- lerp(last_source_section->mScale, source_section->mScale, t);
- dest[section+step].mAxisRotation =
- slerp(t, last_source_section->mAxisRotation, source_section->mAxisRotation);
-
- // Evaluate output interpolated values
- F32 t_sq = t*t;
- dest[section+step].mPosition = t_sq*(t*A + B) + t*C + D;
- dest[section+step].mRotation =
- slerp(t, last_source_section->mRotation, source_section->mRotation);
- dest[section+step].mVelocity = lerp(last_source_section->mVelocity, source_section->mVelocity, t);
- dest[section+step].mDirection = lerp(last_source_section->mDirection, source_section->mDirection, t);
- dest[section+step].mdPosition = lerp(last_source_section->mdPosition, source_section->mdPosition, t);
- dest[section+num_steps] = *source_section;
- t += t_inc;
- }
- }
- dest[0] = source[0];
- }
- else
- {
- // numbers are equal. copy info
- for (S32 section=0; section <= num_output_sections; ++section)
- {
- dest[section] = source[section];
- }
- }
+ LLFlexibleObjectSection *dest, S32 dest_sections)
+{
+ S32 num_output_sections = 1<<dest_sections;
+ LLVector3 scale = mVO->mDrawable->getScale();
+ F32 source_section_length = scale.mV[VZ] / (F32)(1<<source_sections);
+ F32 section_length = scale.mV[VZ] / (F32)num_output_sections;
+ if (source_sections == -1)
+ {
+ // Generate all from section 0
+ dest[0] = source[0];
+ for (S32 section=0; section<num_output_sections; ++section)
+ {
+ dest[section+1] = dest[section];
+ dest[section+1].mPosition += dest[section].mDirection * section_length;
+ dest[section+1].mVelocity.setVec( LLVector3::zero );
+ }
+ }
+ else if (source_sections > dest_sections)
+ {
+ // Copy, skipping sections
+
+ S32 num_steps = 1<<(source_sections-dest_sections);
+
+ // Copy from left to right since it may be an in-place computation
+ for (S32 section=0; section<num_output_sections; ++section)
+ {
+ dest[section+1] = source[(section+1)*num_steps];
+ }
+ dest[0] = source[0];
+ }
+ else if (source_sections < dest_sections)
+ {
+ // Interpolate section info
+ // Iterate from right to left since it may be an in-place computation
+ S32 step_shift = dest_sections-source_sections;
+ S32 num_steps = 1<<step_shift;
+ for (S32 section=num_output_sections-num_steps; section>=0; section -= num_steps)
+ {
+ LLFlexibleObjectSection *last_source_section = &source[section>>step_shift];
+ LLFlexibleObjectSection *source_section = &source[(section>>step_shift)+1];
+
+ // Cubic interpolation of position
+ // At^3 + Bt^2 + Ct + D = f(t)
+ LLVector3 D = last_source_section->mPosition;
+ LLVector3 C = last_source_section->mdPosition * source_section_length;
+ LLVector3 Y = source_section->mdPosition * source_section_length - C; // Helper var
+ LLVector3 X = (source_section->mPosition - D - C); // Helper var
+ LLVector3 A = Y - 2*X;
+ LLVector3 B = X - A;
+
+ F32 t_inc = 1.f/F32(num_steps);
+ F32 t = t_inc;
+ for (S32 step=1; step<num_steps; ++step)
+ {
+ dest[section+step].mScale =
+ lerp(last_source_section->mScale, source_section->mScale, t);
+ dest[section+step].mAxisRotation =
+ slerp(t, last_source_section->mAxisRotation, source_section->mAxisRotation);
+
+ // Evaluate output interpolated values
+ F32 t_sq = t*t;
+ dest[section+step].mPosition = t_sq*(t*A + B) + t*C + D;
+ dest[section+step].mRotation =
+ slerp(t, last_source_section->mRotation, source_section->mRotation);
+ dest[section+step].mVelocity = lerp(last_source_section->mVelocity, source_section->mVelocity, t);
+ dest[section+step].mDirection = lerp(last_source_section->mDirection, source_section->mDirection, t);
+ dest[section+step].mdPosition = lerp(last_source_section->mdPosition, source_section->mdPosition, t);
+ dest[section+num_steps] = *source_section;
+ t += t_inc;
+ }
+ }
+ dest[0] = source[0];
+ }
+ else
+ {
+ // numbers are equal. copy info
+ for (S32 section=0; section <= num_output_sections; ++section)
+ {
+ dest[section] = source[section];
+ }
+ }
}
//-----------------------------------------------------------------------------
void LLVolumeImplFlexible::setAttributesOfAllSections(LLVector3* inScale)
{
- LLVector2 bottom_scale, top_scale;
- F32 begin_rot = 0, end_rot = 0;
- if (mVO->getVolume())
- {
- const LLPathParams &params = mVO->getVolume()->getParams().getPathParams();
- bottom_scale = params.getBeginScale();
- top_scale = params.getEndScale();
- begin_rot = F_PI * params.getTwistBegin();
- end_rot = F_PI * params.getTwist();
- }
-
- if (!mVO->mDrawable)
- {
- return;
- }
-
- S32 num_sections = 1 << mSimulateRes;
-
- LLVector3 scale;
- if (inScale == (LLVector3*)NULL)
- {
- scale = mVO->mDrawable->getScale();
- }
- else
- {
- scale = *inScale;
- }
-
- mSection[0].mPosition = getAnchorPosition();
- mSection[0].mDirection = LLVector3::z_axis * getFrameRotation();
- mSection[0].mdPosition = mSection[0].mDirection;
- mSection[0].mScale.setVec(scale.mV[VX]*bottom_scale.mV[0], scale.mV[VY]*bottom_scale.mV[1]);
- mSection[0].mVelocity.setVec(0,0,0);
- mSection[0].mAxisRotation.setQuat(begin_rot,0,0,1);
-
- remapSections(mSection, mInitializedRes, mSection, mSimulateRes);
- mInitializedRes = mSimulateRes;
-
- F32 t_inc = 1.f/F32(num_sections);
- F32 t = t_inc;
-
- for ( int i=1; i<= num_sections; i++)
- {
- mSection[i].mAxisRotation.setQuat(lerp(begin_rot,end_rot,t),0,0,1);
- mSection[i].mScale = LLVector2(
- scale.mV[VX] * lerp(bottom_scale.mV[0], top_scale.mV[0], t),
- scale.mV[VY] * lerp(bottom_scale.mV[1], top_scale.mV[1], t));
- t += t_inc;
- }
+ LLVector2 bottom_scale, top_scale;
+ F32 begin_rot = 0, end_rot = 0;
+ if (mVO->getVolume())
+ {
+ const LLPathParams &params = mVO->getVolume()->getParams().getPathParams();
+ bottom_scale = params.getBeginScale();
+ top_scale = params.getEndScale();
+ begin_rot = F_PI * params.getTwistBegin();
+ end_rot = F_PI * params.getTwist();
+ }
+
+ if (!mVO->mDrawable)
+ {
+ return;
+ }
+
+ S32 num_sections = 1 << mSimulateRes;
+
+ LLVector3 scale;
+ if (inScale == (LLVector3*)NULL)
+ {
+ scale = mVO->mDrawable->getScale();
+ }
+ else
+ {
+ scale = *inScale;
+ }
+
+ mSection[0].mPosition = getAnchorPosition();
+ mSection[0].mDirection = LLVector3::z_axis * getFrameRotation();
+ mSection[0].mdPosition = mSection[0].mDirection;
+ mSection[0].mScale.setVec(scale.mV[VX]*bottom_scale.mV[0], scale.mV[VY]*bottom_scale.mV[1]);
+ mSection[0].mVelocity.setVec(0,0,0);
+ mSection[0].mAxisRotation.setQuat(begin_rot,0,0,1);
+
+ remapSections(mSection, mInitializedRes, mSection, mSimulateRes);
+ mInitializedRes = mSimulateRes;
+
+ F32 t_inc = 1.f/F32(num_sections);
+ F32 t = t_inc;
+
+ for ( int i=1; i<= num_sections; i++)
+ {
+ mSection[i].mAxisRotation.setQuat(lerp(begin_rot,end_rot,t),0,0,1);
+ mSection[i].mScale = LLVector2(
+ scale.mV[VX] * lerp(bottom_scale.mV[0], top_scale.mV[0], t),
+ scale.mV[VY] * lerp(bottom_scale.mV[1], top_scale.mV[1], t));
+ t += t_inc;
+ }
}//-----------------------------------------------------------------------------------
@@ -292,446 +292,446 @@ void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, cons
void LLVolumeImplFlexible::updateRenderRes()
{
- if (!mAttributes)
- return;
+ if (!mAttributes)
+ return;
- LLDrawable* drawablep = mVO->mDrawable;
+ LLDrawable* drawablep = mVO->mDrawable;
- S32 new_res = mAttributes->getSimulateLOD();
+ S32 new_res = mAttributes->getSimulateLOD();
#if 1 //optimal approximation of previous behavior that doesn't rely on atan2
- F32 app_angle = mVO->getScale().mV[2]/drawablep->mDistanceWRTCamera;
+ F32 app_angle = mVO->getScale().mV[2]/drawablep->mDistanceWRTCamera;
- // Rendering sections increases with visible angle on the screen
- mRenderRes = (S32) (12.f*app_angle);
+ // Rendering sections increases with visible angle on the screen
+ mRenderRes = (S32) (12.f*app_angle);
#else //legacy behavior
- //number of segments only cares about z axis
- F32 app_angle = ll_round((F32) atan2( mVO->getScale().mV[2]*2.f, drawablep->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
+ //number of segments only cares about z axis
+ F32 app_angle = ll_round((F32) atan2( mVO->getScale().mV[2]*2.f, drawablep->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
- // Rendering sections increases with visible angle on the screen
- mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/LLViewerCamera::getInstance()->getView());
+ // 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)
- {
- new_res = mRenderRes;
- }
-
- if (!mInitialized || (mSimulateRes != new_res))
- {
- mSimulateRes = new_res;
- setAttributesOfAllSections();
- mInitialized = TRUE;
- }
+
+ mRenderRes = llclamp(mRenderRes, new_res-1, (S32) FLEXIBLE_OBJECT_MAX_SECTIONS);
+
+ // Throttle back simulation of segments we're not rendering
+ if (mRenderRes < new_res)
+ {
+ new_res = mRenderRes;
+ }
+
+ if (!mInitialized || (mSimulateRes != new_res))
+ {
+ mSimulateRes = new_res;
+ setAttributesOfAllSections();
+ mInitialized = TRUE;
+ }
}
//---------------------------------------------------------------------------------
// 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.
+// updated every time step. In the future, perhaps there could be an
+// optimization similar to what Havok does for objects that are stationary.
//---------------------------------------------------------------------------------
void LLVolumeImplFlexible::doIdleUpdate()
{
- LLDrawable* drawablep = mVO->mDrawable;
-
- if (drawablep)
- {
- //ensure drawable is active
- drawablep->makeActive();
-
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
- {
- bool visible = drawablep->isVisible();
-
- if (mRenderRes == -1)
- {
- updateRenderRes();
- gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION);
- }
- else
- {
- F32 pixel_area = mVO->getPixelArea();
-
- // Note: Flexies afar will be rarely updated, closer ones will be updated more frequently.
- // But frequency differences are extremely noticeable, so consider modifying update factor,
- // or at least clamping value a bit more from both sides.
- 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, 1U, 32U);
-
- // We control how fast flexies update, buy splitting updates among frames
- U64 virtual_frame_num = LLTimer::getElapsedSeconds() / SEC_PER_FLEXI_FRAME;
-
- if (visible)
- {
- if (!drawablep->isState(LLDrawable::IN_REBUILD_Q) &&
- pixel_area > 256.f)
- {
- U32 id;
- if (mVO->isRootEdit())
- {
- id = mID;
- }
- else
- {
- LLVOVolume* parent = (LLVOVolume*)mVO->getParent();
- id = parent->getVolumeInterfaceID();
- }
-
-
- // Throttle flexies and spread load by preventing flexies from updating in same frame
- // Shows how many frames we need to wait before next update
- U64 throttling_delay = (virtual_frame_num + id) % update_period;
-
- if ((throttling_delay == 0 && mLastFrameNum < virtual_frame_num) //one or more virtual frames per frame
- || (mLastFrameNum + update_period < virtual_frame_num) // missed virtual frame
- || mLastFrameNum > virtual_frame_num) // overflow
- {
- // We need mLastFrameNum to compensate for 'unreliable time' and to filter 'duplicate' frames
- // If happened too late, subtract throttling_delay (it is zero otherwise)
- mLastFrameNum = virtual_frame_num - throttling_delay;
-
- // Store update period for updateClass()
- // Note: Consider substituting update_period with mLastUpdatePeriod everywhere.
- mLastUpdatePeriod = update_period;
-
- updateRenderRes();
+ LLDrawable* drawablep = mVO->mDrawable;
+
+ if (drawablep)
+ {
+ //ensure drawable is active
+ drawablep->makeActive();
+
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
+ {
+ bool visible = drawablep->isVisible();
+
+ if (mRenderRes == -1)
+ {
+ updateRenderRes();
+ gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION);
+ }
+ else
+ {
+ F32 pixel_area = mVO->getPixelArea();
+
+ // Note: Flexies afar will be rarely updated, closer ones will be updated more frequently.
+ // But frequency differences are extremely noticeable, so consider modifying update factor,
+ // or at least clamping value a bit more from both sides.
+ 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, 1U, 32U);
+
+ // We control how fast flexies update, buy splitting updates among frames
+ U64 virtual_frame_num = LLTimer::getElapsedSeconds() / SEC_PER_FLEXI_FRAME;
+
+ if (visible)
+ {
+ if (!drawablep->isState(LLDrawable::IN_REBUILD_Q) &&
+ pixel_area > 256.f)
+ {
+ U32 id;
+ if (mVO->isRootEdit())
+ {
+ id = mID;
+ }
+ else
+ {
+ LLVOVolume* parent = (LLVOVolume*)mVO->getParent();
+ id = parent->getVolumeInterfaceID();
+ }
+
+
+ // Throttle flexies and spread load by preventing flexies from updating in same frame
+ // Shows how many frames we need to wait before next update
+ U64 throttling_delay = (virtual_frame_num + id) % update_period;
+
+ if ((throttling_delay == 0 && mLastFrameNum < virtual_frame_num) //one or more virtual frames per frame
+ || (mLastFrameNum + update_period < virtual_frame_num) // missed virtual frame
+ || mLastFrameNum > virtual_frame_num) // overflow
+ {
+ // We need mLastFrameNum to compensate for 'unreliable time' and to filter 'duplicate' frames
+ // If happened too late, subtract throttling_delay (it is zero otherwise)
+ mLastFrameNum = virtual_frame_num - throttling_delay;
+
+ // Store update period for updateClass()
+ // Note: Consider substituting update_period with mLastUpdatePeriod everywhere.
+ mLastUpdatePeriod = update_period;
+
+ updateRenderRes();
mVO->shrinkWrap();
- gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION);
- }
- }
- }
- else
- {
- mLastFrameNum = virtual_frame_num;
- mLastUpdatePeriod = update_period;
- }
- }
-
- }
- }
+ gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION);
+ }
+ }
+ }
+ else
+ {
+ mLastFrameNum = virtual_frame_num;
+ mLastUpdatePeriod = update_period;
+ }
+ }
+
+ }
+ }
}
inline S32 log2(S32 x)
{
- S32 ret = 0;
- while (x > 1)
- {
- ++ret;
- x >>= 1;
- }
- return ret;
+ S32 ret = 0;
+ while (x > 1)
+ {
+ ++ret;
+ x >>= 1;
+ }
+ return ret;
}
void LLVolumeImplFlexible::doFlexibleUpdate()
{
LL_PROFILE_ZONE_SCOPED;
- LLVolume* volume = mVO->getVolume();
- LLPath *path = &volume->getPath();
- if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible())
- {
- 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 || !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;
+ LLVolume* volume = mVO->getVolume();
+ LLPath *path = &volume->getPath();
+ if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible())
+ {
+ 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 || !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;
F32 secondsThisFrame = mTimer.getElapsedTimeAndResetF32();
- if (secondsThisFrame > 0.2f)
- {
- secondsThisFrame = 0.2f;
- }
-
- LLVector3 BasePosition = getFramePosition();
- LLQuaternion BaseRotation = getFrameRotation();
- LLQuaternion parentSegmentRotation = BaseRotation;
- LLVector3 anchorDirectionRotated = LLVector3::z_axis * parentSegmentRotation;
- LLVector3 anchorScale = mVO->mDrawable->getScale();
-
- F32 section_length = anchorScale.mV[VZ] / (F32)num_sections;
- F32 inv_section_length = 1.f / section_length;
-
- S32 i;
-
- // ANCHOR position is offset from BASE position (centroid) by half the length
- LLVector3 AnchorPosition = BasePosition - (anchorScale.mV[VZ]/2 * anchorDirectionRotated);
-
- mSection[0].mPosition = AnchorPosition;
- mSection[0].mDirection = anchorDirectionRotated;
- mSection[0].mRotation = BaseRotation;
-
- LLQuaternion deltaRotation;
-
- LLVector3 lastPosition;
-
- // Coefficients which are constant across sections
- F32 t_factor = mAttributes->getTension() * 0.1f;
- t_factor = t_factor*(1 - pow(0.85f, secondsThisFrame*30));
- if ( t_factor > FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE )
- {
- t_factor = FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE;
- }
-
- F32 friction_coeff = (mAttributes->getAirFriction()*2+1);
- friction_coeff = pow(10.f, friction_coeff*secondsThisFrame);
- friction_coeff = (friction_coeff > 1) ? friction_coeff : 1;
- F32 momentum = 1.0f / friction_coeff;
-
- F32 wind_factor = (mAttributes->getWindSensitivity()*0.1f) * section_length * secondsThisFrame;
- F32 max_angle = atan(section_length*2.f);
-
- F32 force_factor = section_length * secondsThisFrame;
-
- // Update simulated sections
- for (i=1; i<=num_sections; ++i)
- {
- LLVector3 parentSectionVector;
- LLVector3 parentSectionPosition;
- LLVector3 parentDirection;
-
- //---------------------------------------------------
- // save value of position as lastPosition
- //---------------------------------------------------
- lastPosition = mSection[i].mPosition;
-
- //------------------------------------------------------------------------------------------
- // gravity
- //------------------------------------------------------------------------------------------
- mSection[i].mPosition.mV[2] -= mAttributes->getGravity() * force_factor;
-
- //------------------------------------------------------------------------------------------
- // wind force
- //------------------------------------------------------------------------------------------
- if (mAttributes->getWindSensitivity() > 0.001f)
- {
- mSection[i].mPosition += gAgent.getRegion()->mWind.getVelocity( mSection[i].mPosition ) * wind_factor;
- }
-
- //------------------------------------------------------------------------------------------
- // user-defined force
- //------------------------------------------------------------------------------------------
- mSection[i].mPosition += mAttributes->getUserForce() * force_factor;
-
- //---------------------------------------------------
- // tension (rigidity, stiffness)
- //---------------------------------------------------
- parentSectionPosition = mSection[i-1].mPosition;
- parentDirection = mSection[i-1].mDirection;
-
- if ( i == 1 )
- {
- parentSectionVector = mSection[0].mDirection;
- }
- else
- {
- parentSectionVector = mSection[i-2].mDirection;
- }
-
- LLVector3 currentVector = mSection[i].mPosition - parentSectionPosition;
-
- LLVector3 difference = (parentSectionVector*section_length) - currentVector;
- LLVector3 tensionForce = difference * t_factor;
-
- mSection[i].mPosition += tensionForce;
-
- //------------------------------------------------------------------------------------------
- // sphere collision, currently not used
- //------------------------------------------------------------------------------------------
- /*if ( mAttributes->mUsingCollisionSphere )
- {
- LLVector3 vectorToCenterOfCollisionSphere = mCollisionSpherePosition - mSection[i].mPosition;
- if ( vectorToCenterOfCollisionSphere.magVecSquared() < mCollisionSphereRadius * mCollisionSphereRadius )
- {
- F32 distanceToCenterOfCollisionSphere = vectorToCenterOfCollisionSphere.magVec();
- F32 penetration = mCollisionSphereRadius - distanceToCenterOfCollisionSphere;
-
- LLVector3 normalToCenterOfCollisionSphere;
-
- if ( distanceToCenterOfCollisionSphere > 0.0f )
- {
- normalToCenterOfCollisionSphere = vectorToCenterOfCollisionSphere / distanceToCenterOfCollisionSphere;
- }
- else // rare
- {
- normalToCenterOfCollisionSphere = LLVector3::x_axis; // arbitrary
- }
-
- // push the position out to the surface of the collision sphere
- mSection[i].mPosition -= normalToCenterOfCollisionSphere * penetration;
- }
- }*/
-
- //------------------------------------------------------------------------------------------
- // inertia
- //------------------------------------------------------------------------------------------
- mSection[i].mPosition += mSection[i].mVelocity * momentum;
-
- //------------------------------------------------------------------------------------------
- // clamp length & rotation
- //------------------------------------------------------------------------------------------
- mSection[i].mDirection = mSection[i].mPosition - parentSectionPosition;
- mSection[i].mDirection.normVec();
- deltaRotation.shortestArc( parentDirection, mSection[i].mDirection );
-
- F32 angle;
- LLVector3 axis;
- deltaRotation.getAngleAxis(&angle, axis);
- if (angle > F_PI) angle -= 2.f*F_PI;
- if (angle < -F_PI) angle += 2.f*F_PI;
- if (angle > max_angle)
- {
- //angle = 0.5f*(angle+max_angle);
- deltaRotation.setQuat(max_angle, axis);
- } else if (angle < -max_angle)
- {
- //angle = 0.5f*(angle-max_angle);
- deltaRotation.setQuat(-max_angle, axis);
- }
- LLQuaternion segment_rotation = parentSegmentRotation * deltaRotation;
- parentSegmentRotation = segment_rotation;
-
- mSection[i].mDirection = (parentDirection * deltaRotation);
- mSection[i].mPosition = parentSectionPosition + mSection[i].mDirection * section_length;
- mSection[i].mRotation = segment_rotation;
-
- if (i > 1)
- {
- // Propogate half the rotation up to the parent
- LLQuaternion halfDeltaRotation(angle/2, axis);
- mSection[i-1].mRotation = mSection[i-1].mRotation * halfDeltaRotation;
- }
-
- //------------------------------------------------------------------------------------------
- // calculate velocity
- //------------------------------------------------------------------------------------------
- mSection[i].mVelocity = mSection[i].mPosition - lastPosition;
- if (mSection[i].mVelocity.magVecSquared() > 1.f)
- {
- mSection[i].mVelocity.normVec();
- }
- }
-
- // Calculate derivatives (not necessary until normals are automagically generated)
- mSection[0].mdPosition = (mSection[1].mPosition - mSection[0].mPosition) * inv_section_length;
- // i = 1..NumSections-1
- for (i=1; i<num_sections; ++i)
- {
- // Quadratic numerical derivative of position
-
- // f(-L1) = aL1^2 - bL1 + c = f1
- // f(0) = c = f2
- // f(L2) = aL2^2 + bL2 + c = f3
- // f = ax^2 + bx + c
- // d/dx f = 2ax + b
- // d/dx f(0) = b
-
- // c = f2
- // a = [(f1-c)/L1 + (f3-c)/L2] / (L1+L2)
- // b = (f3-c-aL2^2)/L2
-
- LLVector3 a = (mSection[i-1].mPosition-mSection[i].mPosition +
- mSection[i+1].mPosition-mSection[i].mPosition) * 0.5f * inv_section_length * inv_section_length;
- LLVector3 b = (mSection[i+1].mPosition-mSection[i].mPosition - a*(section_length*section_length));
- b *= inv_section_length;
-
- mSection[i].mdPosition = b;
- }
-
- // i = NumSections
- 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)
- {
- ((LLVOVolume*) mVO)->mVolumeChanged = TRUE;
- volume->resizePath(num_render_sections+1);
- }
-
- LLPath::PathPt *new_point;
-
- LLFlexibleObjectSection newSection[ (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1 ];
- remapSections(mSection, mSimulateRes, newSection, mRenderRes);
-
- //generate transform from global to prim space
- LLVector3 delta_scale = LLVector3(1,1,1);
- LLVector3 delta_pos;
- LLQuaternion delta_rot;
-
- delta_rot = ~getFrameRotation();
- delta_pos = -getFramePosition()*delta_rot;
-
- // Vertex transform (4x4)
- LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
- LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
- LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
-
- LLMatrix4 rel_xform;
- rel_xform.initRows(LLVector4(x_axis, 0.f),
- LLVector4(y_axis, 0.f),
- 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;
-
- LLVector3 np(new_point->mPos.getF32ptr());
-
- if (!mUpdated || (np-pos).magVec()/mVO->mDrawable->mDistanceWRTCamera > 0.001f)
- {
- new_point->mPos.load3((newSection[i].mPosition * rel_xform).mV);
- mUpdated = FALSE;
- }
-
- 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;
+ if (secondsThisFrame > 0.2f)
+ {
+ secondsThisFrame = 0.2f;
+ }
+
+ LLVector3 BasePosition = getFramePosition();
+ LLQuaternion BaseRotation = getFrameRotation();
+ LLQuaternion parentSegmentRotation = BaseRotation;
+ LLVector3 anchorDirectionRotated = LLVector3::z_axis * parentSegmentRotation;
+ LLVector3 anchorScale = mVO->mDrawable->getScale();
+
+ F32 section_length = anchorScale.mV[VZ] / (F32)num_sections;
+ F32 inv_section_length = 1.f / section_length;
+
+ S32 i;
+
+ // ANCHOR position is offset from BASE position (centroid) by half the length
+ LLVector3 AnchorPosition = BasePosition - (anchorScale.mV[VZ]/2 * anchorDirectionRotated);
+
+ mSection[0].mPosition = AnchorPosition;
+ mSection[0].mDirection = anchorDirectionRotated;
+ mSection[0].mRotation = BaseRotation;
+
+ LLQuaternion deltaRotation;
+
+ LLVector3 lastPosition;
+
+ // Coefficients which are constant across sections
+ F32 t_factor = mAttributes->getTension() * 0.1f;
+ t_factor = t_factor*(1 - pow(0.85f, secondsThisFrame*30));
+ if ( t_factor > FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE )
+ {
+ t_factor = FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE;
+ }
+
+ F32 friction_coeff = (mAttributes->getAirFriction()*2+1);
+ friction_coeff = pow(10.f, friction_coeff*secondsThisFrame);
+ friction_coeff = (friction_coeff > 1) ? friction_coeff : 1;
+ F32 momentum = 1.0f / friction_coeff;
+
+ F32 wind_factor = (mAttributes->getWindSensitivity()*0.1f) * section_length * secondsThisFrame;
+ F32 max_angle = atan(section_length*2.f);
+
+ F32 force_factor = section_length * secondsThisFrame;
+
+ // Update simulated sections
+ for (i=1; i<=num_sections; ++i)
+ {
+ LLVector3 parentSectionVector;
+ LLVector3 parentSectionPosition;
+ LLVector3 parentDirection;
+
+ //---------------------------------------------------
+ // save value of position as lastPosition
+ //---------------------------------------------------
+ lastPosition = mSection[i].mPosition;
+
+ //------------------------------------------------------------------------------------------
+ // gravity
+ //------------------------------------------------------------------------------------------
+ mSection[i].mPosition.mV[2] -= mAttributes->getGravity() * force_factor;
+
+ //------------------------------------------------------------------------------------------
+ // wind force
+ //------------------------------------------------------------------------------------------
+ if (mAttributes->getWindSensitivity() > 0.001f)
+ {
+ mSection[i].mPosition += gAgent.getRegion()->mWind.getVelocity( mSection[i].mPosition ) * wind_factor;
+ }
+
+ //------------------------------------------------------------------------------------------
+ // user-defined force
+ //------------------------------------------------------------------------------------------
+ mSection[i].mPosition += mAttributes->getUserForce() * force_factor;
+
+ //---------------------------------------------------
+ // tension (rigidity, stiffness)
+ //---------------------------------------------------
+ parentSectionPosition = mSection[i-1].mPosition;
+ parentDirection = mSection[i-1].mDirection;
+
+ if ( i == 1 )
+ {
+ parentSectionVector = mSection[0].mDirection;
+ }
+ else
+ {
+ parentSectionVector = mSection[i-2].mDirection;
+ }
+
+ LLVector3 currentVector = mSection[i].mPosition - parentSectionPosition;
+
+ LLVector3 difference = (parentSectionVector*section_length) - currentVector;
+ LLVector3 tensionForce = difference * t_factor;
+
+ mSection[i].mPosition += tensionForce;
+
+ //------------------------------------------------------------------------------------------
+ // sphere collision, currently not used
+ //------------------------------------------------------------------------------------------
+ /*if ( mAttributes->mUsingCollisionSphere )
+ {
+ LLVector3 vectorToCenterOfCollisionSphere = mCollisionSpherePosition - mSection[i].mPosition;
+ if ( vectorToCenterOfCollisionSphere.magVecSquared() < mCollisionSphereRadius * mCollisionSphereRadius )
+ {
+ F32 distanceToCenterOfCollisionSphere = vectorToCenterOfCollisionSphere.magVec();
+ F32 penetration = mCollisionSphereRadius - distanceToCenterOfCollisionSphere;
+
+ LLVector3 normalToCenterOfCollisionSphere;
+
+ if ( distanceToCenterOfCollisionSphere > 0.0f )
+ {
+ normalToCenterOfCollisionSphere = vectorToCenterOfCollisionSphere / distanceToCenterOfCollisionSphere;
+ }
+ else // rare
+ {
+ normalToCenterOfCollisionSphere = LLVector3::x_axis; // arbitrary
+ }
+
+ // push the position out to the surface of the collision sphere
+ mSection[i].mPosition -= normalToCenterOfCollisionSphere * penetration;
+ }
+ }*/
+
+ //------------------------------------------------------------------------------------------
+ // inertia
+ //------------------------------------------------------------------------------------------
+ mSection[i].mPosition += mSection[i].mVelocity * momentum;
+
+ //------------------------------------------------------------------------------------------
+ // clamp length & rotation
+ //------------------------------------------------------------------------------------------
+ mSection[i].mDirection = mSection[i].mPosition - parentSectionPosition;
+ mSection[i].mDirection.normVec();
+ deltaRotation.shortestArc( parentDirection, mSection[i].mDirection );
+
+ F32 angle;
+ LLVector3 axis;
+ deltaRotation.getAngleAxis(&angle, axis);
+ if (angle > F_PI) angle -= 2.f*F_PI;
+ if (angle < -F_PI) angle += 2.f*F_PI;
+ if (angle > max_angle)
+ {
+ //angle = 0.5f*(angle+max_angle);
+ deltaRotation.setQuat(max_angle, axis);
+ } else if (angle < -max_angle)
+ {
+ //angle = 0.5f*(angle-max_angle);
+ deltaRotation.setQuat(-max_angle, axis);
+ }
+ LLQuaternion segment_rotation = parentSegmentRotation * deltaRotation;
+ parentSegmentRotation = segment_rotation;
+
+ mSection[i].mDirection = (parentDirection * deltaRotation);
+ mSection[i].mPosition = parentSectionPosition + mSection[i].mDirection * section_length;
+ mSection[i].mRotation = segment_rotation;
+
+ if (i > 1)
+ {
+ // Propogate half the rotation up to the parent
+ LLQuaternion halfDeltaRotation(angle/2, axis);
+ mSection[i-1].mRotation = mSection[i-1].mRotation * halfDeltaRotation;
+ }
+
+ //------------------------------------------------------------------------------------------
+ // calculate velocity
+ //------------------------------------------------------------------------------------------
+ mSection[i].mVelocity = mSection[i].mPosition - lastPosition;
+ if (mSection[i].mVelocity.magVecSquared() > 1.f)
+ {
+ mSection[i].mVelocity.normVec();
+ }
+ }
+
+ // Calculate derivatives (not necessary until normals are automagically generated)
+ mSection[0].mdPosition = (mSection[1].mPosition - mSection[0].mPosition) * inv_section_length;
+ // i = 1..NumSections-1
+ for (i=1; i<num_sections; ++i)
+ {
+ // Quadratic numerical derivative of position
+
+ // f(-L1) = aL1^2 - bL1 + c = f1
+ // f(0) = c = f2
+ // f(L2) = aL2^2 + bL2 + c = f3
+ // f = ax^2 + bx + c
+ // d/dx f = 2ax + b
+ // d/dx f(0) = b
+
+ // c = f2
+ // a = [(f1-c)/L1 + (f3-c)/L2] / (L1+L2)
+ // b = (f3-c-aL2^2)/L2
+
+ LLVector3 a = (mSection[i-1].mPosition-mSection[i].mPosition +
+ mSection[i+1].mPosition-mSection[i].mPosition) * 0.5f * inv_section_length * inv_section_length;
+ LLVector3 b = (mSection[i+1].mPosition-mSection[i].mPosition - a*(section_length*section_length));
+ b *= inv_section_length;
+
+ mSection[i].mdPosition = b;
+ }
+
+ // i = NumSections
+ 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)
+ {
+ ((LLVOVolume*) mVO)->mVolumeChanged = TRUE;
+ volume->resizePath(num_render_sections+1);
+ }
+
+ LLPath::PathPt *new_point;
+
+ LLFlexibleObjectSection newSection[ (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1 ];
+ remapSections(mSection, mSimulateRes, newSection, mRenderRes);
+
+ //generate transform from global to prim space
+ LLVector3 delta_scale = LLVector3(1,1,1);
+ LLVector3 delta_pos;
+ LLQuaternion delta_rot;
+
+ delta_rot = ~getFrameRotation();
+ delta_pos = -getFramePosition()*delta_rot;
+
+ // Vertex transform (4x4)
+ LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
+ LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
+ LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
+
+ LLMatrix4 rel_xform;
+ rel_xform.initRows(LLVector4(x_axis, 0.f),
+ LLVector4(y_axis, 0.f),
+ 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;
+
+ LLVector3 np(new_point->mPos.getF32ptr());
+
+ if (!mUpdated || (np-pos).magVec()/mVO->mDrawable->mDistanceWRTCamera > 0.001f)
+ {
+ new_point->mPos.load3((newSection[i].mPosition * rel_xform).mV);
+ mUpdated = FALSE;
+ }
+
+ 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;
}
void LLVolumeImplFlexible::preRebuild()
{
- if (!mUpdated)
- {
+ if (!mUpdated)
+ {
LL_PROFILE_ZONE_SCOPED;
- doFlexibleRebuild(false);
- }
+ doFlexibleRebuild(false);
+ }
}
void LLVolumeImplFlexible::doFlexibleRebuild(bool rebuild_volume)
{
- LLVolume* volume = mVO->getVolume();
+ LLVolume* volume = mVO->getVolume();
if (volume)
{
if (rebuild_volume)
@@ -740,103 +740,103 @@ void LLVolumeImplFlexible::doFlexibleRebuild(bool rebuild_volume)
}
volume->regen();
}
-
- mUpdated = TRUE;
+
+ mUpdated = TRUE;
}
//------------------------------------------------------------------
void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped)
{
- setAttributesOfAllSections((LLVector3*) &scale);
+ setAttributesOfAllSections((LLVector3*) &scale);
}
BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
{
LL_PROFILE_ZONE_SCOPED;
- LLVOVolume *volume = (LLVOVolume*)mVO;
-
- if (mVO->isAttachment())
- { //don't update flexible attachments for impostored avatars unless the
- //impostor is being updated this frame (w00!)
- LLViewerObject* parent = (LLViewerObject*) mVO->getParent();
- while (parent && !parent->isAvatar())
- {
- parent = (LLViewerObject*) parent->getParent();
- }
-
- if (parent)
- {
- LLVOAvatar* avatar = (LLVOAvatar*) parent;
- if (avatar->isImpostor() && !avatar->needsImpostorUpdate())
- {
- return TRUE;
- }
- }
- }
-
- if (volume->mDrawable.isNull())
- {
- return TRUE; // No update to complete
- }
-
- if (volume->mLODChanged)
- {
- LLVolumeParams volume_params = volume->getVolume()->getParams();
- volume->setVolume(volume_params, 0);
- mUpdated = FALSE;
- }
-
- volume->updateRelativeXform();
-
- doFlexibleUpdate();
-
- // Object may have been rotated, which means it needs a rebuild. See SL-47220
- BOOL rotated = FALSE;
- LLQuaternion cur_rotation = getFrameRotation();
- if ( cur_rotation != mLastFrameRotation )
- {
- mLastFrameRotation = cur_rotation;
- rotated = TRUE;
- }
-
- if (volume->mLODChanged || volume->mFaceMappingChanged ||
- volume->mVolumeChanged || drawable->isState(LLDrawable::REBUILD_MATERIAL))
- {
- volume->regenFaces();
- volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME);
- volume->dirtySpatialGroup();
- {
- doFlexibleRebuild(volume->mVolumeChanged);
- }
- volume->genBBoxes(isVolumeGlobal());
- }
- else if (!mUpdated || rotated)
- {
- volume->mDrawable->setState(LLDrawable::REBUILD_POSITION);
- LLSpatialGroup* group = volume->mDrawable->getSpatialGroup();
- if (group)
- {
- group->dirtyMesh();
- }
- volume->genBBoxes(isVolumeGlobal());
- }
-
- volume->mVolumeChanged = FALSE;
- volume->mLODChanged = FALSE;
- volume->mFaceMappingChanged = FALSE;
-
- // clear UV flag
- drawable->clearState(LLDrawable::UV);
-
- return TRUE;
+ LLVOVolume *volume = (LLVOVolume*)mVO;
+
+ if (mVO->isAttachment())
+ { //don't update flexible attachments for impostored avatars unless the
+ //impostor is being updated this frame (w00!)
+ LLViewerObject* parent = (LLViewerObject*) mVO->getParent();
+ while (parent && !parent->isAvatar())
+ {
+ parent = (LLViewerObject*) parent->getParent();
+ }
+
+ if (parent)
+ {
+ LLVOAvatar* avatar = (LLVOAvatar*) parent;
+ if (avatar->isImpostor() && !avatar->needsImpostorUpdate())
+ {
+ return TRUE;
+ }
+ }
+ }
+
+ if (volume->mDrawable.isNull())
+ {
+ return TRUE; // No update to complete
+ }
+
+ if (volume->mLODChanged)
+ {
+ LLVolumeParams volume_params = volume->getVolume()->getParams();
+ volume->setVolume(volume_params, 0);
+ mUpdated = FALSE;
+ }
+
+ volume->updateRelativeXform();
+
+ doFlexibleUpdate();
+
+ // Object may have been rotated, which means it needs a rebuild. See SL-47220
+ BOOL rotated = FALSE;
+ LLQuaternion cur_rotation = getFrameRotation();
+ if ( cur_rotation != mLastFrameRotation )
+ {
+ mLastFrameRotation = cur_rotation;
+ rotated = TRUE;
+ }
+
+ if (volume->mLODChanged || volume->mFaceMappingChanged ||
+ volume->mVolumeChanged || drawable->isState(LLDrawable::REBUILD_MATERIAL))
+ {
+ volume->regenFaces();
+ volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME);
+ volume->dirtySpatialGroup();
+ {
+ doFlexibleRebuild(volume->mVolumeChanged);
+ }
+ volume->genBBoxes(isVolumeGlobal());
+ }
+ else if (!mUpdated || rotated)
+ {
+ volume->mDrawable->setState(LLDrawable::REBUILD_POSITION);
+ LLSpatialGroup* group = volume->mDrawable->getSpatialGroup();
+ if (group)
+ {
+ group->dirtyMesh();
+ }
+ volume->genBBoxes(isVolumeGlobal());
+ }
+
+ volume->mVolumeChanged = FALSE;
+ volume->mLODChanged = FALSE;
+ volume->mFaceMappingChanged = FALSE;
+
+ // clear UV flag
+ drawable->clearState(LLDrawable::UV);
+
+ return TRUE;
}
//----------------------------------------------------------------------------------
void LLVolumeImplFlexible::setCollisionSphere( LLVector3 p, F32 r )
{
- mCollisionSpherePosition = p;
- mCollisionSphereRadius = r;
+ mCollisionSpherePosition = p;
+ mCollisionSphereRadius = r;
}//------------------------------------------------------------------
@@ -855,8 +855,8 @@ void LLVolumeImplFlexible::setRenderingCollisionSphere( bool r )
//------------------------------------------------------------------
LLVector3 LLVolumeImplFlexible::getEndPosition()
{
- S32 num_sections = 1 << mAttributes->getSimulateLOD();
- return mSection[ num_sections ].mPosition;
+ S32 num_sections = 1 << mAttributes->getSimulateLOD();
+ return mSection[ num_sections ].mPosition;
}//------------------------------------------------------------------
@@ -864,33 +864,33 @@ LLVector3 LLVolumeImplFlexible::getEndPosition()
//------------------------------------------------------------------
LLVector3 LLVolumeImplFlexible::getNodePosition( int nodeIndex )
{
- S32 num_sections = 1 << mAttributes->getSimulateLOD();
- if ( nodeIndex > num_sections - 1 )
- {
- nodeIndex = num_sections - 1;
- }
- else if ( nodeIndex < 0 )
- {
- nodeIndex = 0;
- }
-
- return mSection[ nodeIndex ].mPosition;
+ S32 num_sections = 1 << mAttributes->getSimulateLOD();
+ if ( nodeIndex > num_sections - 1 )
+ {
+ nodeIndex = num_sections - 1;
+ }
+ else if ( nodeIndex < 0 )
+ {
+ nodeIndex = 0;
+ }
+
+ return mSection[ nodeIndex ].mPosition;
}//------------------------------------------------------------------
LLVector3 LLVolumeImplFlexible::getPivotPosition() const
{
- return getAnchorPosition();
+ return getAnchorPosition();
}
//------------------------------------------------------------------
LLVector3 LLVolumeImplFlexible::getAnchorPosition() const
{
- LLVector3 BasePosition = getFramePosition();
- LLQuaternion parentSegmentRotation = getFrameRotation();
- LLVector3 anchorDirectionRotated = LLVector3::z_axis * parentSegmentRotation;
- LLVector3 anchorScale = mVO->mDrawable->getScale();
- return BasePosition - (anchorScale.mV[VZ]/2 * anchorDirectionRotated);
+ LLVector3 BasePosition = getFramePosition();
+ LLQuaternion parentSegmentRotation = getFrameRotation();
+ LLVector3 anchorDirectionRotated = LLVector3::z_axis * parentSegmentRotation;
+ LLVector3 anchorScale = mVO->mDrawable->getScale();
+ return BasePosition - (anchorScale.mV[VZ]/2 * anchorDirectionRotated);
}//------------------------------------------------------------------
@@ -898,42 +898,42 @@ LLVector3 LLVolumeImplFlexible::getAnchorPosition() const
//------------------------------------------------------------------
LLQuaternion LLVolumeImplFlexible::getEndRotation()
{
- return mLastSegmentRotation;
+ return mLastSegmentRotation;
}//------------------------------------------------------------------
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 = 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)
- LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
- LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
- LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
-
- vo->mRelativeXform.initRows(LLVector4(x_axis, 0.f),
- LLVector4(y_axis, 0.f),
- LLVector4(z_axis, 0.f),
- LLVector4(delta_pos, 1.f));
-
- x_axis.normVec();
- y_axis.normVec();
- z_axis.normVec();
-
- vo->mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
+ 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 = 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)
+ LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
+ LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
+ LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
+
+ vo->mRelativeXform.initRows(LLVector4(x_axis, 0.f),
+ LLVector4(y_axis, 0.f),
+ LLVector4(z_axis, 0.f),
+ LLVector4(delta_pos, 1.f));
+
+ x_axis.normVec();
+ y_axis.normVec();
+ z_axis.normVec();
+
+ vo->mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
}
const LLMatrix4& LLVolumeImplFlexible::getWorldMatrix(LLXformMatrix* xform) const
{
- return xform->getWorldMatrix();
+ return xform->getWorldMatrix();
}