From 29f8de325c3d4d6437c7f19ece029b59fa5c6f29 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Thu, 16 Apr 2020 10:34:52 +0200 Subject: [PATCH] Clean this up a bit --- indra/newview/fsregioncross.cpp | 141 +++++++++++++++++--------------- indra/newview/fsregioncross.h | 88 ++++++++++++-------- 2 files changed, 130 insertions(+), 99 deletions(-) diff --git a/indra/newview/fsregioncross.cpp b/indra/newview/fsregioncross.cpp index 5a6cab98a8..f7644d8bfe 100644 --- a/indra/newview/fsregioncross.cpp +++ b/indra/newview/fsregioncross.cpp @@ -24,14 +24,14 @@ * The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA * http://www.firestormviewer.org */ - -#include "llviewerprecompiledheaders.h" // regular Firestorm includes -#include "llviewercontrol.h" -#include "llmath.h" // normal build -#include "llviewerobject.h" -#include "llframetimer.h" + +#include "llviewerprecompiledheaders.h" #include "fsregioncross.h" -// +#include "llframetimer.h" +#include "llmath.h" +#include "llviewercontrol.h" +#include "llviewerobject.h" + // Improved region crossing time limit prediction. // // Applied when @@ -55,15 +55,14 @@ // Potential vehicle, but might be just a chair. // We don't start the movement averaging until there's movement at least once. // -RegionCrossExtrapolateImpl::RegionCrossExtrapolateImpl(const LLViewerObject& vo) : // constructor - mOwner(vo), // back ref to owner - mPreviousUpdateTime(0), // time of last update - mMoved(false) // has not moved yet +RegionCrossExtrapolateImpl::RegionCrossExtrapolateImpl(const LLViewerObject& vo) : + mOwner(vo), + mPreviousUpdateTime(0), + mMoved(false) { - LL_INFOS() << "Object " << vo.getID().asString() << " has sitter." << LL_ENDL; // log sit event + LL_INFOS() << "Object " << vo.getID().asString() << " has sitter." << LL_ENDL; } -// // update -- called for each object update message to "vehicle" objects. // // This is called for any object with an avatar sitting on it. @@ -71,42 +70,49 @@ RegionCrossExtrapolateImpl::RegionCrossExtrapolateImpl(const LLViewerObject& vo) // If it has moved, we treat it as a vehicle. // void RegionCrossExtrapolateImpl::update() -{ - if (!mMoved) // if not seen to move - { LLVector3 rawvel = mOwner.getVelocity(); // velocity in world coords - if (rawvel.mV[VX] != 0.0 || rawvel.mV[VY] != 0.0 || rawvel.mV[VZ] != 0) // check for nonzero velocity - { mMoved = true; } // moved, has seated avatar, thus is vehicle +{ + if (!mMoved) + { + LLVector3 rawvel = mOwner.getVelocity(); // velocity in world coords + if (rawvel.mV[VX] != 0.f || rawvel.mV[VY] != 0.f || rawvel.mV[VZ] != 0.f) // check for nonzero velocity + { + mMoved = true; // moved, has seated avatar, thus is vehicle + } else - { return; } // sitting on stationary object, skip this + { + return; // sitting on stationary object, skip this + } } + // Moving seat - do the extrapolation calculations - F64 dt = 1.0/45.0; // dt used on first value - one physics frame on server - F64 now = LLFrameTimer::getElapsedSeconds(); // timestamp + F64 dt = 1.0 / 45.0; // dt used on first value - one physics frame on server + F64 now = LLFrameTimer::getElapsedSeconds(); if (mPreviousUpdateTime != 0.0) - { dt = now - mPreviousUpdateTime; // change since last update + { + dt = now - mPreviousUpdateTime; // change since last update // Could adjust here for ping time and time dilation, but the filter isn't that // sensitive to minor variations dt and it would just complicate things. } + mPreviousUpdateTime = now; - LLQuaternion rot = mOwner.getRotationRegion(); // transform in global coords - const LLQuaternion& inverserot = rot.conjugate(); // transform global to local - LLVector3 vel = mOwner.getVelocity()*inverserot; // velocity in object coords - LLVector3 angvel = mOwner.getAngularVelocity()*inverserot; // angular velocity in object coords - mFilteredVel.update(vel,dt); // accum into filter in object coords - mFilteredAngVel.update(angvel,dt); // accum into filter in object coords + LLQuaternion rot = mOwner.getRotationRegion(); // transform in global coords + const LLQuaternion& inverserot = rot.conjugate(); // transform global to local + LLVector3 vel = mOwner.getVelocity() * inverserot; // velocity in object coords + LLVector3 angvel = mOwner.getAngularVelocity() * inverserot; // angular velocity in object coords + mFilteredVel.update(vel, dt); // accum into filter in object coords + mFilteredAngVel.update(angvel, dt); // accum into filter in object coords } -// + // dividesafe -- floating divide with divide by zero check // // Returns infinity for a divide by near zero. // static inline F32 dividesafe(F32 num, F32 denom) -{ return((denom > FP_MAG_THRESHOLD // avoid divide by zero - || denom < -FP_MAG_THRESHOLD) - ? (num / denom) - : std::numeric_limits::infinity()); // return infinity if zero divide +{ + return ((denom > FP_MAG_THRESHOLD || denom < -FP_MAG_THRESHOLD) // avoid divide by zero + ? (num / denom) : std::numeric_limits::infinity()); // return infinity if zero divide } -// + // getextraptimelimit -- don't extrapolate further ahead than this during a region crossing. // // Returns seconds of extrapolation that will probably stay within set limits of error. @@ -117,36 +123,43 @@ F32 RegionCrossExtrapolateImpl::getextraptimelimit() const // The limits can be adjusted as debug symbols or in settings.xml, but that should not be necessary. static LLCachedControl fsRegionCrossingPositionErrorLimit(gSavedSettings, "FSRegionCrossingPositionErrorLimit"); static LLCachedControl fsRegionCrossingAngleErrorLimit(gSavedSettings, "FSRegionCrossingAngleErrorLimit"); - // Time limit is max allowed error / error. Returns worst case (smallest) of vel and angular vel limits. + + // Time limit is max allowed error / error. Returns worst case (smallest) of vel and angular vel limits. LLQuaternion rot = mOwner.getRotationRegion(); // transform in global coords const LLQuaternion& inverserot = rot.conjugate(); // transform global to local - // Calculate safe extrapolation time limit. - F32 extrapTimeLimit = llmin(dividesafe(fsRegionCrossingPositionErrorLimit, ((mOwner.getVelocity()*inverserot - mFilteredVel.get()).length())), - dividesafe(fsRegionCrossingAngleErrorLimit, ((mOwner.getAngularVelocity()*inverserot - mFilteredAngVel.get()).length()))); - LL_INFOS() << "Region cross extrapolation safe limit " << extrapTimeLimit << " secs." << LL_ENDL; - return(extrapTimeLimit); // do not extrapolate more than this -} -// + // Calculate safe extrapolation time limit. + F32 extrapTimeLimit = llmin(dividesafe(fsRegionCrossingPositionErrorLimit, ((mOwner.getVelocity() * inverserot - mFilteredVel.get()).length())), + dividesafe(fsRegionCrossingAngleErrorLimit, ((mOwner.getAngularVelocity() * inverserot - mFilteredAngVel.get()).length()))); + + LL_INFOS() << "Region cross extrapolation safe limit " << extrapTimeLimit << " secs." << LL_ENDL; + return extrapTimeLimit; // do not extrapolate more than this +} + // ifsaton -- True if object is being sat upon. // // Potential vehicle. // -BOOL RegionCrossExtrapolate::ifsaton(const LLViewerObject& vo) // true if root object and being sat on -{ if (!vo.isRoot()) { return(false); } // not root, cannot be sat upon +bool RegionCrossExtrapolate::ifsaton(const LLViewerObject& vo) // true if root object and being sat on +{ + if (!vo.isRoot()) + { + return false; // not root, cannot be sat upon + } + for (auto iter = vo.getChildren().begin(); // check for avatar as child of root - iter != vo.getChildren().end(); iter++) - { - LLViewerObject* child = *iter; // get child - if (child->isAvatar()) // avatar as child - { - return(true); // we have a sitter - } - } - return(false); // no avatar children, not sat on + iter != vo.getChildren().end(); iter++) + { + LLViewerObject* child = *iter; + if (child->isAvatar()) + { + return true; + } + } + + return false; // no avatar children, not sat on } -// // LowPassFilter -- the low pass filter for smoothing velocities. // // Works on vectors. @@ -167,17 +180,17 @@ BOOL RegionCrossExtrapolate::ifsaton(const LLViewerObject& vo) // true if root void LowPassFilter::update(const LLVector3& val, F32 secs) // add new value into filter { static LLCachedControl fsRegionCrossingSmoothingTime(gSavedSettings, "FSRegionCrossingSmoothingTime"); - if (!mInitialized) // if not initialized yet - { mFiltered = val; // just use new value + if (!mInitialized) + { + mFiltered = val; // just use new value mInitialized = true; return; } - F32 filtermult = 1.0; // no filtering if zero filter time - if (fsRegionCrossingSmoothingTime > 0.001) // avoid divide by zero - { filtermult = 1.0 - 1.0/pow(1.0+1.0/fsRegionCrossingSmoothingTime,secs); } // filter scale factor - mFiltered = val * filtermult + mFiltered*(1.0-filtermult); // low pass filter + + F32 filtermult = 1.0f; // no filtering if zero filter time + if (fsRegionCrossingSmoothingTime > F_ALMOST_ZERO) // avoid divide by zero + { + filtermult = 1.0f - 1.0f / pow(1.0f + 1.0f / fsRegionCrossingSmoothingTime, secs); // filter scale factor + } + mFiltered = val * filtermult + mFiltered * (1.0f - filtermult); // low pass filter } - - - - diff --git a/indra/newview/fsregioncross.h b/indra/newview/fsregioncross.h index a1b85afd00..626036ed7a 100644 --- a/indra/newview/fsregioncross.h +++ b/indra/newview/fsregioncross.h @@ -32,9 +32,8 @@ // Improved region crossing support. // -class LLViewerObject; // forward declaration +class LLViewerObject; -// // LowPassFilter -- a simple Kalman low-pass filter. // // Supports nonuniform time deltas between samples, since object update times are not consistent. @@ -43,26 +42,27 @@ class LowPassFilter { private: LLVector3 mFiltered; // filtered value - BOOL mInitialized; // true if initialized + bool mInitialized; + public: - LowPassFilter() : // constructor + LowPassFilter() : mInitialized(false), - mFiltered(0.0,0.0,0.0) - {} + mFiltered() + { } + void update(const LLVector3& val, F32 dt); // add new value into filter - + const LLVector3& get() const // get filtered output { - return(mFiltered); // already stored + return mFiltered; // already stored } - - void clear() + + void clear() { - mInitialized = false; // not initialized yet + mInitialized = false; } }; -// // RegionCrossExtrapolateImpl -- the extrapolation limit calculator. // // One of these is created when an object is sat upon. If the @@ -79,16 +79,15 @@ private: F64 mPreviousUpdateTime; // previous update time LowPassFilter mFilteredVel; // filtered velocity LowPassFilter mFilteredAngVel; // filtered angular velocity - BOOL mMoved; // seen to move at least once + bool mMoved; // seen to move at least once public: - RegionCrossExtrapolateImpl(const LLViewerObject& vo); // constructor + RegionCrossExtrapolateImpl(const LLViewerObject& vo); void update(); // update on object update message F32 getextraptimelimit() const; // don't extrapolate more than this - BOOL hasmoved() const { return(mMoved); } // true if has been seen to move with sitter + bool hasmoved() const { return (mMoved); } // true if has been seen to move with sitter }; -// // RegionCrossExtrapolate -- calculate safe limit on how long to extrapolate after a region crossing // // Member object of llViewerObject. For vehicles, a RegionCrossExtrapolateImpl is allocated to do the real work. @@ -96,38 +95,57 @@ public: // Call "changedlink" for any object update which changes parenting. // Get the extrapolation limit time with getextraptimelimit. // -class LLViewerObject; // forward -class RegionCrossExtrapolate { +class RegionCrossExtrapolate +{ private: - std::unique_ptr mImpl; // pointer to region cross extrapolator, if present - + std::unique_ptr mImpl; + protected: - BOOL ifsaton(const LLViewerObject& vo); // true if root object and being sat on - + bool ifsaton(const LLViewerObject& vo); // true if root object and being sat on + public: void update(const LLViewerObject& vo) // new object update message received - { if (mImpl.get()) { mImpl->update(); } // update extrapolator if present + { + if (mImpl.get()) + { + mImpl->update(); // update extrapolator if present + } } - + void changedlink(const LLViewerObject& vo) // parent or child changed, check if extrapolation object needed { if (ifsaton(vo)) // if this object is now the root of a linkset with an avatar - { if (!mImpl.get()) // if no extrapolation implementor - { mImpl.reset(new RegionCrossExtrapolateImpl(vo)); } // add an extrapolator - } else { // not a vehicle + { + if (!mImpl.get()) // if no extrapolation implementor + { + mImpl.reset(new RegionCrossExtrapolateImpl(vo)); // add an extrapolator + } + } + else // not a vehicle + { if (mImpl.get()) - { mImpl.reset(); } // no longer needed + { + mImpl.reset(); // no longer needed + } } } - - BOOL ismovingssaton(const LLViewerObject &vo) - { if (!mImpl.get()) { return(false); } // not sat on - return(mImpl->hasmoved()); // sat on, check for moving + + bool ismovingssaton(const LLViewerObject &vo) + { + if (!mImpl.get()) + { + return (false); // not sat on + } + return mImpl->hasmoved(); // sat on, check for moving } - + F32 getextraptimelimit() const // get extrapolation time limit - { if (mImpl.get()) { return(mImpl->getextraptimelimit()); } // get extrapolation time limit if vehicle - return(std::numeric_limits::infinity()); // no limit if not a vehicle + { + if (mImpl.get()) + { + return mImpl->getextraptimelimit(); // get extrapolation time limit if vehicle + } + return std::numeric_limits::infinity(); // no limit if not a vehicle } };