diff options
Diffstat (limited to 'indra/newview/llflexibleobject.cpp')
-rw-r--r-- | indra/newview/llflexibleobject.cpp | 832 |
1 files changed, 832 insertions, 0 deletions
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp new file mode 100644 index 0000000000..4f821a7978 --- /dev/null +++ b/indra/newview/llflexibleobject.cpp @@ -0,0 +1,832 @@ +/** + * @file llflexibleobject.cpp + * @brief Flexible object implementation + * + * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "pipeline.h" +#include "lldrawpoolbump.h" +#include "llface.h" +#include "llflexibleobject.h" +#include "llglheaders.h" +#include "llsphere.h" +#include "llviewerobject.h" +#include "llimagegl.h" +#include "llagent.h" +#include "llsky.h" +#include "llviewercamera.h" +#include "llviewerimagelist.h" +#include "llviewercontrol.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llworld.h" + +/*static*/ LLVolumeImplFlexible::lodset_t LLVolumeImplFlexible::sLODBins[ FLEXIBLE_OBJECT_MAX_LOD ]; +/*static*/ U64 LLVolumeImplFlexible::sCurrentUpdateFrame = 0; +/*static*/ U32 LLVolumeImplFlexible::sDebugInserted = 0; +/*static*/ U32 LLVolumeImplFlexible::sDebugVisible = 0; + +/*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f; + +// LLFlexibleObjectData::pack/unpack now in llprimitive.cpp + +//----------------------------------------------- +// constructor +//----------------------------------------------- +LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectData* attributes) : + mVO(vo), mAttributes(attributes) +{ + mInitialized = FALSE; + mUpdated = FALSE; + mJustShifted = FALSE; + mInitializedRes = -1; + mSimulateRes = 0; + mFrameNum = 0; + mLastUpdate = 0; + +}//----------------------------------------------- + +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 LLVector3 &shift_vector) +{ + for (int section = 0; section < (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1; ++section) + { + mSection[section].mPosition += shift_vector; + } + mVO->getVolume()->mBounds[0] += shift_vector; +} + +//----------------------------------------------------------------------------------------------- +void LLVolumeImplFlexible::setParentPositionAndRotationDirectly( LLVector3 p, LLQuaternion 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]; + } + } +} + + +//----------------------------------------------------------------------------- +void LLVolumeImplFlexible::setAttributesOfAllSections() +{ + 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(); + } + + S32 num_sections = 1 << mSimulateRes; + + + LLVector3 scale = mVO->mDrawable->getScale(); + + 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); + + LLVector3 parentSectionPosition = mSection[0].mPosition; + LLVector3 last_direction = mSection[0].mDirection; + + 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; + } + mLastUpdate = 0; +}//----------------------------------------------------------------------------------- + + +void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, const S32 detail) +{ + doIdleUpdate(gAgent, *gWorldp, 0.0); + if (mVO && mVO->mDrawable.notNull()) + { + gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + gPipeline.markMoved(mVO->mDrawable); + } +} + +//--------------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------------- +BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +{ + if (mVO->mDrawable.isNull()) + { + // Don't do anything until we have a drawable + return TRUE; + } + + //flexible objects never go static + mVO->mDrawable->mQuietCount = 0; + if (!mVO->mDrawable->isRoot()) + { + mVO->mDrawable->getParent()->mQuietCount = 0; + } + + if (((LLVOVolume*)mVO)->mLODChanged || + mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1)) + { + mLastUpdate = 0; // Force an immediate update + } + // Relegate invisible objects to the lowest priority bin + S32 lod = 0; + F32 app_angle = mVO->getAppAngle()*DEG_TO_RAD/gCamera->getView(); + if (mVO->mDrawable->isVisible()) + { + sDebugVisible++; + if (mVO->isSelected()) + { + // Force selected objects to update *every* frame + lod = FLEXIBLE_OBJECT_MAX_LOD-1; + } + else + { + if (app_angle > 0) + { + lod = 5 - (S32)(1.0f/sqrtf(app_angle)); + if (lod < 1) + { + lod = 1; + } + } + + if (mVO->isAttachment()) + { + lod += 3; + } + } + } + + S32 new_res = mAttributes->getSimulateLOD(); + // Rendering sections increases with visible angle on the screen + mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle); + if (mRenderRes > FLEXIBLE_OBJECT_MAX_SECTIONS) + { + mRenderRes = FLEXIBLE_OBJECT_MAX_SECTIONS; + } + // Bottom cap at 1/4 the original number of sections + if (mRenderRes < mAttributes->getSimulateLOD()-1) + { + mRenderRes = mAttributes->getSimulateLOD()-1; + } + // 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; + } + + sLODBins[lod].insert(this); + sDebugInserted++; + return TRUE; +} + +// static +void LLVolumeImplFlexible::resetUpdateBins() +{ + U32 lod; + for (lod=0; lod<FLEXIBLE_OBJECT_MAX_LOD; ++lod) + { + sLODBins[lod].clear(); + } + ++sCurrentUpdateFrame; + sDebugInserted = 0; + sDebugVisible = 0; +} + +inline S32 log2(S32 x) +{ + S32 ret = 0; + while (x > 1) + { + ++ret; + x >>= 1; + } + return ret; +} + +// static +void LLVolumeImplFlexible::doFlexibleUpdateBins() +{ + U32 lod; + U32 updated = 0; + U32 regen = 0; + U32 newflexies = 0; + F32 time_alloc[FLEXIBLE_OBJECT_MAX_LOD]; + F32 total_time_alloc = 0; + + bool new_objects_only = false; + + if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) + { + new_objects_only = true; + } + + for (lod=0; lod<FLEXIBLE_OBJECT_MAX_LOD; ++lod) + { + int count = sLODBins[lod].size(); + if (count > 0) + { + time_alloc[lod] = (F32)((lod+1)*(log2(count))); + } + else + { + time_alloc[lod] = 0; + } + total_time_alloc += time_alloc[lod]; + } + total_time_alloc = FLEXIBLE_OBJECT_TIMESLICE * (sUpdateFactor+0.01f) / total_time_alloc; + + { + LLFastTimer t(LLFastTimer::FTM_FLEXIBLE_UPDATE); + LLTimer timer; + for (lod=0; lod<FLEXIBLE_OBJECT_MAX_LOD; ++lod) + { + LLVolumeImplFlexible::lodset_t::iterator itor = sLODBins[lod].begin(); + int bin_count = 0; + if (!new_objects_only) + { + timer.reset(); + double end_time = time_alloc[lod] * total_time_alloc; + for (; itor!=sLODBins[lod].end(); ++itor) + { + + (*itor)->doFlexibleUpdate(); + ++updated; + (*itor)->doFlexibleRebuild(); + ++bin_count; + ++regen; + if (timer.getElapsedTimeF64() > end_time) + { + break; + } + } + } + for (; itor != sLODBins[lod].end(); ++itor) + { + if ((*itor)->getLastUpdate() == 0) + { + // *Always* update newly-created objects, or objects which have changed LOD + (*itor)->doFlexibleUpdate(); + (*itor)->doFlexibleRebuild(); + ++newflexies; + } + } + } + } +} + +void LLVolumeImplFlexible::doFlexibleUpdate() +{ + LLPath *path = &mVO->getVolume()->getPath(); + 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; + } + + // 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 + S32 num_render_sections = 1<<mRenderRes; + path->resizePath(num_render_sections+1); + + LLPath::PathPt *new_point; + + LLFlexibleObjectSection newSection[ (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1 ]; + remapSections(mSection, mSimulateRes, newSection, mRenderRes); + + for (i=0; i<=num_render_sections; ++i) + { + new_point = &path->mPath[i]; + new_point->mPos = newSection[i].mPosition; + new_point->mRot = mSection[i].mAxisRotation * newSection[i].mRotation; + new_point->mScale = newSection[i].mScale; + new_point->mTexT = ((F32)i)/(num_render_sections); + } + + mLastSegmentRotation = parentSegmentRotation; +} + +void LLVolumeImplFlexible::doFlexibleRebuild() +{ + mVO->getVolume()->regen(); + + mVO->markForUpdate(TRUE); + + mUpdated = TRUE; + + mLastUpdate = sCurrentUpdateFrame; +}//------------------------------------------------------------------ + +void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped) +{ + setAttributesOfAllSections(); +} + +BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) +{ + BOOL compiled = FALSE; + + LLVOVolume *volume = (LLVOVolume*)mVO; + + if (volume->mDrawable.isNull()) // Not sure why this is happening, but it is... + { + return TRUE; // No update to complete + } + + volume->calcAllTEsSame(); + + if (volume->mVolumeChanged || volume->mFaceMappingChanged) + { + compiled = TRUE; + volume->regenFaces(); + } + else if (volume->mLODChanged) + { + LLPointer<LLVolume> old_volumep, new_volumep; + F32 old_lod, new_lod; + + old_volumep = volume->getVolume(); + old_lod = old_volumep->getDetail(); + + LLVolumeParams volume_params = volume->getVolume()->getParams(); + volume->setVolume(volume_params, 0); + doFlexibleUpdate(); + volume->getVolume()->regen(); + + new_volumep = volume->getVolume(); + new_lod = new_volumep->getDetail(); + + if (new_lod != old_lod) + { + compiled = TRUE; + if (new_volumep->getNumFaces() != old_volumep->getNumFaces()) + { + volume->regenFaces(); + } + } + } + + if (mUpdated) + { + compiled = TRUE; + mUpdated = FALSE; + } + + if(compiled) + { + volume->updateRelativeXform(isVolumeGlobal()); + volume->genTriangles(isVolumeGlobal()); + LLPipeline::sCompiles++; + } + + volume->mVolumeChanged = FALSE; + volume->mLODChanged = FALSE; + volume->mFaceMappingChanged = FALSE; + + // clear UV flag + drawable->clearState(LLDrawable::UV); + + drawable->movePartition(); + + 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 global_volume) +{ + LLVOVolume* vo = (LLVOVolume*) mVO; + + LLVector3 delta_scale = LLVector3(1,1,1); + LLVector3 delta_pos; + LLQuaternion delta_rot; + + if (!mVO->mDrawable->isRoot()) + { //global to parent relative + LLViewerObject* parent = (LLViewerObject*) vo->getParent(); + delta_rot = ~parent->getRenderRotation(); + delta_pos = -parent->getRenderPosition()*delta_rot; + } + else + { //global to local + 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; + + 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(); +} |