From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llflexibleobject.cpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'indra/newview/llflexibleobject.cpp') diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index e935bc5553..c619c19493 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -60,8 +60,8 @@ LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectD { static U32 seed = 0; mID = seed++; - mInitialized = FALSE; - mUpdated = FALSE; + mInitialized = false; + mUpdated = false; mInitializedRes = -1; mSimulateRes = 0; mCollisionSphereRadius = 0.f; @@ -119,7 +119,7 @@ LLQuaternion LLVolumeImplFlexible::getFrameRotation() const return mVO->getRenderRotation(); } -void LLVolumeImplFlexible::onParameterChanged(U16 param_type, LLNetworkData *data, BOOL in_use, bool local_origin) +void LLVolumeImplFlexible::onParameterChanged(U16 param_type, LLNetworkData *data, bool in_use, bool local_origin) { if (param_type == LLNetworkData::PARAMS_FLEXIBLE) { @@ -324,7 +324,7 @@ void LLVolumeImplFlexible::updateRenderRes() { mSimulateRes = new_res; setAttributesOfAllSections(); - mInitialized = TRUE; + mInitialized = true; } } //--------------------------------------------------------------------------------- @@ -433,7 +433,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate() LLPath *path = &volume->getPath(); if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible()) { - BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE; + bool force_update = mSimulateRes == 0 ? true : false; doIdleUpdate(); if (!force_update || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) @@ -668,7 +668,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate() S32 num_render_sections = 1<getPathLength() != num_render_sections+1) { - ((LLVOVolume*) mVO)->mVolumeChanged = TRUE; + ((LLVOVolume*) mVO)->mVolumeChanged = true; volume->resizePath(num_render_sections+1); } @@ -708,7 +708,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate() if (!mUpdated || (np-pos).magVec()/mVO->mDrawable->mDistanceWRTCamera > 0.001f) { new_point->mPos.load3((newSection[i].mPosition * rel_xform).mV); - mUpdated = FALSE; + mUpdated = false; } new_point->mRot.loadu(LLMatrix3(rot)); @@ -741,17 +741,17 @@ void LLVolumeImplFlexible::doFlexibleRebuild(bool rebuild_volume) volume->regen(); } - mUpdated = TRUE; + mUpdated = true; } //------------------------------------------------------------------ -void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped) +void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, bool damped) { setAttributesOfAllSections((LLVector3*) &scale); } -BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) +bool LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) { LL_PROFILE_ZONE_SCOPED; LLVOVolume *volume = (LLVOVolume*)mVO; @@ -770,21 +770,21 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) LLVOAvatar* avatar = (LLVOAvatar*) parent; if (avatar->isImpostor() && !avatar->needsImpostorUpdate()) { - return TRUE; + return true; } } } if (volume->mDrawable.isNull()) { - return TRUE; // No update to complete + return true; // No update to complete } if (volume->mLODChanged) { LLVolumeParams volume_params = volume->getVolume()->getParams(); volume->setVolume(volume_params, 0); - mUpdated = FALSE; + mUpdated = false; } volume->updateRelativeXform(); @@ -792,12 +792,12 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) doFlexibleUpdate(); // Object may have been rotated, which means it needs a rebuild. See SL-47220 - BOOL rotated = FALSE; + bool rotated = false; LLQuaternion cur_rotation = getFrameRotation(); if ( cur_rotation != mLastFrameRotation ) { mLastFrameRotation = cur_rotation; - rotated = TRUE; + rotated = true; } if (volume->mLODChanged || volume->mFaceMappingChanged || @@ -822,14 +822,14 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) volume->genBBoxes(isVolumeGlobal()); } - volume->mVolumeChanged = FALSE; - volume->mLODChanged = FALSE; - volume->mFaceMappingChanged = FALSE; + volume->mVolumeChanged = false; + volume->mLODChanged = false; + volume->mFaceMappingChanged = false; // clear UV flag drawable->clearState(LLDrawable::UV); - return TRUE; + return true; } //---------------------------------------------------------------------------------- -- cgit v1.2.3 From f9473e8afcb624cc1b101195bf15943ec372b56f Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Mon, 6 May 2024 16:52:34 +0200 Subject: secondlife/viewer#1333 BOOL to bool conversion leftovers: ternaries --- indra/newview/llflexibleobject.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview/llflexibleobject.cpp') diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index c619c19493..74298c2b3d 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -433,7 +433,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate() LLPath *path = &volume->getPath(); if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible()) { - bool force_update = mSimulateRes == 0 ? true : false; + bool force_update = mSimulateRes == 0; doIdleUpdate(); if (!force_update || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) @@ -442,10 +442,10 @@ void LLVolumeImplFlexible::doFlexibleUpdate() } } - if(!mInitialized || !mAttributes) + if (!mInitialized || !mAttributes) { //the object is not visible - return ; + return; } // Fix for MAINT-1894 @@ -456,7 +456,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate() { return; } - + S32 num_sections = 1 << mSimulateRes; F32 secondsThisFrame = mTimer.getElapsedTimeAndResetF32(); -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llflexibleobject.cpp | 1878 ++++++++++++++++++------------------ 1 file changed, 939 insertions(+), 939 deletions(-) (limited to 'indra/newview/llflexibleobject.cpp') diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index cef4bd284d..4d82611def 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -1,939 +1,939 @@ -/** - * @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$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "pipeline.h" -#include "lldrawpoolbump.h" -#include "llface.h" -#include "llflexibleobject.h" -#include "llglheaders.h" -#include "llrendersphere.h" -#include "llviewerobject.h" -#include "llagent.h" -#include "llsky.h" -#include "llviewercamera.h" -#include "llviewertexturelist.h" -#include "llviewercontrol.h" -#include "llviewerobjectlist.h" -#include "llviewerregion.h" -#include "llworld.h" -#include "llvoavatar.h" - -static const F32 SEC_PER_FLEXI_FRAME = 1.f / 60.f; // 60 flexi updates per second -/*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f; -std::vector LLVolumeImplFlexible::sInstanceList; - -// LLFlexibleObjectData::pack/unpack now in llprimitive.cpp - -//----------------------------------------------- -// constructor -//----------------------------------------------- -LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectData* attributes) : - 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); -}//----------------------------------------------- - -LLVolumeImplFlexible::~LLVolumeImplFlexible() -{ - S32 end_idx = sInstanceList.size()-1; - - if (end_idx != mInstanceIndex) - { - sInstanceList[mInstanceIndex] = sInstanceList[end_idx]; - sInstanceList[mInstanceIndex]->mInstanceIndex = mInstanceIndex; - } - - sInstanceList.pop_back(); -} - -//static -void LLVolumeImplFlexible::updateClass() -{ - LL_PROFILE_ZONE_SCOPED; - - U64 virtual_frame_num = LLTimer::getElapsedSeconds() / SEC_PER_FLEXI_FRAME; - for (std::vector::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(); -} - -LLQuaternion LLVolumeImplFlexible::getFrameRotation() const -{ - 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(); - } -} - -void LLVolumeImplFlexible::onShift(const LLVector4a &shift_vector) -{ - //VECTORIZE THIS - LLVector3 shift(shift_vector.getF32ptr()); - for (int section = 0; section < (1<mDrawable->getScale(); - F32 source_section_length = scale.mV[VZ] / (F32)(1< 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=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; stepmScale, 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 ¶ms = 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; - } -}//----------------------------------------------------------------------------------- - - -void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, const S32 detail) -{ -} - - -void LLVolumeImplFlexible::updateRenderRes() -{ - if (!mAttributes) - return; - - LLDrawable* drawablep = mVO->mDrawable; - - 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; - - // 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); - - // 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; - } -} -//--------------------------------------------------------------------------------- -// 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. -//--------------------------------------------------------------------------------- -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(); - - mVO->shrinkWrap(); - 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; -} - -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; - 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< 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 -1); - S32 num_render_sections = 1<getPathLength() != num_render_sections+1) - { - ((LLVOVolume*) mVO)->mVolumeChanged = true; - volume->resizePath(num_render_sections+1); - } - - LLPath::PathPt *new_point; - - LLFlexibleObjectSection newSection[ (1<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) - { - LL_PROFILE_ZONE_SCOPED; - doFlexibleRebuild(false); - } -} - -void LLVolumeImplFlexible::doFlexibleRebuild(bool rebuild_volume) -{ - LLVolume* volume = mVO->getVolume(); - if (volume) - { - if (rebuild_volume) - { - volume->setDirty(); - } - volume->regen(); - } - - mUpdated = true; -} - -//------------------------------------------------------------------ - -void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, bool damped) -{ - 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; -} - -//---------------------------------------------------------------------------------- -void LLVolumeImplFlexible::setCollisionSphere( LLVector3 p, F32 r ) -{ - mCollisionSpherePosition = p; - mCollisionSphereRadius = r; - -}//------------------------------------------------------------------ - - -//---------------------------------------------------------------------------------- -void LLVolumeImplFlexible::setUsingCollisionSphere( bool u ) -{ -}//------------------------------------------------------------------ - - -//---------------------------------------------------------------------------------- -void LLVolumeImplFlexible::setRenderingCollisionSphere( bool r ) -{ -}//------------------------------------------------------------------ - -//------------------------------------------------------------------ -LLVector3 LLVolumeImplFlexible::getEndPosition() -{ - S32 num_sections = 1 << mAttributes->getSimulateLOD(); - return mSection[ num_sections ].mPosition; - -}//------------------------------------------------------------------ - - -//------------------------------------------------------------------ -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; - -}//------------------------------------------------------------------ - -LLVector3 LLVolumeImplFlexible::getPivotPosition() const -{ - 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); - -}//------------------------------------------------------------------ - - -//------------------------------------------------------------------ -LLQuaternion LLVolumeImplFlexible::getEndRotation() -{ - 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); -} - -const LLMatrix4& LLVolumeImplFlexible::getWorldMatrix(LLXformMatrix* xform) const -{ - return xform->getWorldMatrix(); -} +/** + * @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$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "pipeline.h" +#include "lldrawpoolbump.h" +#include "llface.h" +#include "llflexibleobject.h" +#include "llglheaders.h" +#include "llrendersphere.h" +#include "llviewerobject.h" +#include "llagent.h" +#include "llsky.h" +#include "llviewercamera.h" +#include "llviewertexturelist.h" +#include "llviewercontrol.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llworld.h" +#include "llvoavatar.h" + +static const F32 SEC_PER_FLEXI_FRAME = 1.f / 60.f; // 60 flexi updates per second +/*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f; +std::vector LLVolumeImplFlexible::sInstanceList; + +// LLFlexibleObjectData::pack/unpack now in llprimitive.cpp + +//----------------------------------------------- +// constructor +//----------------------------------------------- +LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectData* attributes) : + 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); +}//----------------------------------------------- + +LLVolumeImplFlexible::~LLVolumeImplFlexible() +{ + S32 end_idx = sInstanceList.size()-1; + + if (end_idx != mInstanceIndex) + { + sInstanceList[mInstanceIndex] = sInstanceList[end_idx]; + sInstanceList[mInstanceIndex]->mInstanceIndex = mInstanceIndex; + } + + sInstanceList.pop_back(); +} + +//static +void LLVolumeImplFlexible::updateClass() +{ + LL_PROFILE_ZONE_SCOPED; + + U64 virtual_frame_num = LLTimer::getElapsedSeconds() / SEC_PER_FLEXI_FRAME; + for (std::vector::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(); +} + +LLQuaternion LLVolumeImplFlexible::getFrameRotation() const +{ + 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(); + } +} + +void LLVolumeImplFlexible::onShift(const LLVector4a &shift_vector) +{ + //VECTORIZE THIS + LLVector3 shift(shift_vector.getF32ptr()); + for (int section = 0; section < (1<mDrawable->getScale(); + F32 source_section_length = scale.mV[VZ] / (F32)(1< 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=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; stepmScale, 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 ¶ms = 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; + } +}//----------------------------------------------------------------------------------- + + +void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, const S32 detail) +{ +} + + +void LLVolumeImplFlexible::updateRenderRes() +{ + if (!mAttributes) + return; + + LLDrawable* drawablep = mVO->mDrawable; + + 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; + + // 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); + + // 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; + } +} +//--------------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------------- +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(); + + mVO->shrinkWrap(); + 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; +} + +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; + 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< 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 -1); + S32 num_render_sections = 1<getPathLength() != num_render_sections+1) + { + ((LLVOVolume*) mVO)->mVolumeChanged = true; + volume->resizePath(num_render_sections+1); + } + + LLPath::PathPt *new_point; + + LLFlexibleObjectSection newSection[ (1<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) + { + LL_PROFILE_ZONE_SCOPED; + doFlexibleRebuild(false); + } +} + +void LLVolumeImplFlexible::doFlexibleRebuild(bool rebuild_volume) +{ + LLVolume* volume = mVO->getVolume(); + if (volume) + { + if (rebuild_volume) + { + volume->setDirty(); + } + volume->regen(); + } + + mUpdated = true; +} + +//------------------------------------------------------------------ + +void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, bool damped) +{ + 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; +} + +//---------------------------------------------------------------------------------- +void LLVolumeImplFlexible::setCollisionSphere( LLVector3 p, F32 r ) +{ + mCollisionSpherePosition = p; + mCollisionSphereRadius = r; + +}//------------------------------------------------------------------ + + +//---------------------------------------------------------------------------------- +void LLVolumeImplFlexible::setUsingCollisionSphere( bool u ) +{ +}//------------------------------------------------------------------ + + +//---------------------------------------------------------------------------------- +void LLVolumeImplFlexible::setRenderingCollisionSphere( bool r ) +{ +}//------------------------------------------------------------------ + +//------------------------------------------------------------------ +LLVector3 LLVolumeImplFlexible::getEndPosition() +{ + S32 num_sections = 1 << mAttributes->getSimulateLOD(); + return mSection[ num_sections ].mPosition; + +}//------------------------------------------------------------------ + + +//------------------------------------------------------------------ +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; + +}//------------------------------------------------------------------ + +LLVector3 LLVolumeImplFlexible::getPivotPosition() const +{ + 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); + +}//------------------------------------------------------------------ + + +//------------------------------------------------------------------ +LLQuaternion LLVolumeImplFlexible::getEndRotation() +{ + 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); +} + +const LLMatrix4& LLVolumeImplFlexible::getWorldMatrix(LLXformMatrix* xform) const +{ + return xform->getWorldMatrix(); +} -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/newview/llflexibleobject.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llflexibleobject.cpp') diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 4d82611def..367803b78a 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -72,13 +72,13 @@ LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectD mVO->mDrawable->makeActive() ; } - mInstanceIndex = sInstanceList.size(); + mInstanceIndex = static_cast(sInstanceList.size()); sInstanceList.push_back(this); }//----------------------------------------------- LLVolumeImplFlexible::~LLVolumeImplFlexible() { - S32 end_idx = sInstanceList.size()-1; + S32 end_idx = static_cast(sInstanceList.size()) - 1; if (end_idx != mInstanceIndex) { -- cgit v1.2.3