153 lines
5.6 KiB
C++
153 lines
5.6 KiB
C++
/**
|
|
* @file fsregioncross.h
|
|
* @brief Improvements to region crossing display
|
|
* @author nagle@animats.com
|
|
*
|
|
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
|
* Phoenix Firestorm Viewer Source Code
|
|
* Copyright (C) 2020 Animats
|
|
*
|
|
* 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
|
|
*
|
|
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
|
* http://www.firestormviewer.org
|
|
*/
|
|
|
|
#ifndef FS_FSREGIONCROSS_H
|
|
#define FS_FSREGIONCROSS_H
|
|
|
|
//
|
|
// Improved region crossing support.
|
|
//
|
|
|
|
class LLViewerObject;
|
|
|
|
// LowPassFilter -- a simple Kalman low-pass filter.
|
|
//
|
|
// Supports nonuniform time deltas between samples, since object update times are not consistent.
|
|
//
|
|
class LowPassFilter
|
|
{
|
|
private:
|
|
LLVector3 mFiltered; // filtered value
|
|
bool mInitialized;
|
|
|
|
public:
|
|
LowPassFilter() :
|
|
mInitialized(false),
|
|
mFiltered()
|
|
{ }
|
|
|
|
void update(const LLVector3& val, F32 dt); // add new value into filter
|
|
|
|
const LLVector3& get() const // get filtered output
|
|
{
|
|
return mFiltered; // already stored
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
mInitialized = false;
|
|
}
|
|
};
|
|
|
|
// RegionCrossExtrapolateImpl -- the extrapolation limit calculator.
|
|
//
|
|
// One of these is created when an object is sat upon. If the
|
|
// seat moves, it's effectively a vehicle, so we start calculating
|
|
// region crossing safe extrapolation times. If the seat never moves,
|
|
// we still allocate one of these, but it doesn't do anything.
|
|
// When the avatar stands, this object is released.
|
|
// If the LLViewerObject is deleted, so is this object.
|
|
//
|
|
class RegionCrossExtrapolateImpl // Implementation of region cross extrapolation control
|
|
{
|
|
private:
|
|
const LLViewerObject& mOwner; // ref to owning object
|
|
F64 mPreviousUpdateTime; // previous update time
|
|
LowPassFilter mFilteredVel; // filtered velocity
|
|
LowPassFilter mFilteredAngVel; // filtered angular velocity
|
|
bool mMoved; // seen to move at least once
|
|
|
|
public:
|
|
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
|
|
};
|
|
|
|
// 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.
|
|
// Call "update" for each new object update.
|
|
// Call "changedlink" for any object update which changes parenting.
|
|
// Get the extrapolation limit time with getextraptimelimit.
|
|
//
|
|
class RegionCrossExtrapolate
|
|
{
|
|
private:
|
|
std::unique_ptr<RegionCrossExtrapolateImpl> mImpl;
|
|
|
|
protected:
|
|
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
|
|
}
|
|
}
|
|
|
|
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())
|
|
{
|
|
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
|
|
}
|
|
|
|
F32 getextraptimelimit() const // get extrapolation time limit
|
|
{
|
|
if (mImpl.get())
|
|
{
|
|
return mImpl->getextraptimelimit(); // get extrapolation time limit if vehicle
|
|
}
|
|
return std::numeric_limits<F32>::infinity(); // no limit if not a vehicle
|
|
}
|
|
};
|
|
|
|
#endif // FS_REGIONCROSS_H
|