New object/avatar interp.
This commit is contained in:
@@ -13395,6 +13395,28 @@
|
|||||||
<key>Value</key>
|
<key>Value</key>
|
||||||
<integer>1</integer>
|
<integer>1</integer>
|
||||||
</map>
|
</map>
|
||||||
|
<key>InterpolationTime</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>How long to extrapolate object motion after last packet received</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>F32</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
</map>
|
||||||
|
<key>InterpolationPhaseOut</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>Seconds to phase out interpolated motion</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>F32</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
</map>
|
||||||
<key>VerboseLogs</key>
|
<key>VerboseLogs</key>
|
||||||
<map>
|
<map>
|
||||||
<key>Comment</key>
|
<key>Comment</key>
|
||||||
|
|||||||
@@ -106,8 +106,8 @@
|
|||||||
|
|
||||||
//#define DEBUG_UPDATE_TYPE
|
//#define DEBUG_UPDATE_TYPE
|
||||||
|
|
||||||
BOOL gVelocityInterpolate = TRUE;
|
BOOL LLViewerObject::sVelocityInterpolate = TRUE;
|
||||||
BOOL gPingInterpolate = TRUE;
|
BOOL LLViewerObject::sPingInterpolate = TRUE;
|
||||||
|
|
||||||
U32 LLViewerObject::sNumZombieObjects = 0;
|
U32 LLViewerObject::sNumZombieObjects = 0;
|
||||||
S32 LLViewerObject::sNumObjects = 0;
|
S32 LLViewerObject::sNumObjects = 0;
|
||||||
@@ -118,6 +118,10 @@ S32 LLViewerObject::sAxisArrowLength(50);
|
|||||||
BOOL LLViewerObject::sPulseEnabled(FALSE);
|
BOOL LLViewerObject::sPulseEnabled(FALSE);
|
||||||
BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE
|
BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE
|
||||||
|
|
||||||
|
// sMaxUpdateInterpolationTime must be greater than sPhaseOutUpdateInterpolationTime
|
||||||
|
F64 LLViewerObject::sMaxUpdateInterpolationTime = 3.0; // For motion interpolation: after X seconds with no updates, don't predict object motion
|
||||||
|
F64 LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0; // For motion interpolation: after Y seconds with no updates, taper off motion prediction
|
||||||
|
|
||||||
// static
|
// static
|
||||||
LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
|
LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
|
||||||
{
|
{
|
||||||
@@ -1899,9 +1903,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new_rot.normalize();
|
new_rot.normQuat();
|
||||||
|
|
||||||
if (gPingInterpolate)
|
if (sPingInterpolate)
|
||||||
{
|
{
|
||||||
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender());
|
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender());
|
||||||
if (cdp)
|
if (cdp)
|
||||||
@@ -2064,7 +2068,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
|
|||||||
|
|
||||||
// U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay();
|
// U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay();
|
||||||
mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds();
|
mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds();
|
||||||
mLastMessageUpdateSecs = LLFrameTimer::getElapsedSeconds();
|
mLastMessageUpdateSecs = mLastInterpUpdateSecs;
|
||||||
if (mDrawable.notNull())
|
if (mDrawable.notNull())
|
||||||
{
|
{
|
||||||
// Don't clear invisibility flag on update if still orphaned!
|
// Don't clear invisibility flag on update if still orphaned!
|
||||||
@@ -2101,7 +2105,7 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
|
|||||||
|
|
||||||
// CRO - don't velocity interp linked objects!
|
// CRO - don't velocity interp linked objects!
|
||||||
// Leviathan - but DO velocity interp joints
|
// Leviathan - but DO velocity interp joints
|
||||||
if (!mStatic && gVelocityInterpolate && !isSelected())
|
if (!mStatic && sVelocityInterpolate && !isSelected())
|
||||||
{
|
{
|
||||||
// calculate dt from last update
|
// calculate dt from last update
|
||||||
F32 dt_raw = (F32)(time - mLastInterpUpdateSecs);
|
F32 dt_raw = (F32)(time - mLastInterpUpdateSecs);
|
||||||
@@ -2191,48 +2195,170 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{ // Move object based on it's velocity and rotation
|
||||||
// linear motion
|
interpolateLinearMotion(time, dt);
|
||||||
// PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object
|
|
||||||
// updates represents the average velocity of the last timestep, rather than the final velocity.
|
|
||||||
// the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically
|
|
||||||
//
|
|
||||||
// There is a problem here if dt is negative. . .
|
|
||||||
|
|
||||||
// *TODO: should also wrap linear accel/velocity in check
|
|
||||||
// to see if object is selected, instead of explicitly
|
|
||||||
// zeroing it out
|
|
||||||
LLVector3 accel = getAcceleration();
|
|
||||||
LLVector3 vel = getVelocity();
|
|
||||||
|
|
||||||
if (!(accel.isExactlyZero() && vel.isExactlyZero()))
|
|
||||||
{
|
|
||||||
LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
|
|
||||||
|
|
||||||
// region local
|
|
||||||
setPositionRegion(pos + getPositionRegion());
|
|
||||||
setVelocity(vel + accel*dt);
|
|
||||||
|
|
||||||
// for objects that are spinning but not translating, make sure to flag them as having moved
|
|
||||||
setChanged(MOVED | SILHOUETTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
mLastInterpUpdateSecs = time;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gNoRender)
|
|
||||||
{
|
|
||||||
// Skip drawable stuff if not rendering.
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateDrawable(FALSE);
|
updateDrawable(FALSE);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Move an object due to idle-time viewer side updates by iterpolating motion
|
||||||
|
void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt)
|
||||||
|
{
|
||||||
|
// linear motion
|
||||||
|
// PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object
|
||||||
|
// updates represents the average velocity of the last timestep, rather than the final velocity.
|
||||||
|
// the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically
|
||||||
|
//
|
||||||
|
// *TODO: should also wrap linear accel/velocity in check
|
||||||
|
// to see if object is selected, instead of explicitly
|
||||||
|
// zeroing it out
|
||||||
|
|
||||||
|
F64 time_since_last_update = time - mLastMessageUpdateSecs;
|
||||||
|
if (time_since_last_update <= 0.0 || dt <= 0.f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVector3 accel = getAcceleration();
|
||||||
|
LLVector3 vel = getVelocity();
|
||||||
|
|
||||||
|
if (sMaxUpdateInterpolationTime <= 0.0)
|
||||||
|
{ // Old code path ... unbounded, simple interpolation
|
||||||
|
if (!(accel.isExactlyZero() && vel.isExactlyZero()))
|
||||||
|
{
|
||||||
|
LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
|
||||||
|
|
||||||
|
// region local
|
||||||
|
setPositionRegion(pos + getPositionRegion());
|
||||||
|
setVelocity(vel + accel*dt);
|
||||||
|
|
||||||
|
// for objects that are spinning but not translating, make sure to flag them as having moved
|
||||||
|
setChanged(MOVED | SILHOUETTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!accel.isExactlyZero() || !vel.isExactlyZero()) // object is moving
|
||||||
|
{ // Object is moving, and hasn't been too long since we got an update from the server
|
||||||
|
|
||||||
|
// Calculate predicted position and velocity
|
||||||
|
LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
|
||||||
|
LLVector3 new_v = accel * dt;
|
||||||
|
|
||||||
|
if (time_since_last_update > sPhaseOutUpdateInterpolationTime &&
|
||||||
|
sPhaseOutUpdateInterpolationTime > 0.0)
|
||||||
|
{ // Haven't seen a viewer update in a while, check to see if the ciruit is still active
|
||||||
|
if (mRegionp)
|
||||||
|
{ // The simulator will NOT send updates if the object continues normally on the path
|
||||||
|
// predicted by the velocity and the acceleration (often gravity) sent to the viewer
|
||||||
|
// So check to see if the circuit is blocked, which means the sim is likely in a long lag
|
||||||
|
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit( mRegionp->getHost() );
|
||||||
|
if (cdp)
|
||||||
|
{
|
||||||
|
// Find out how many seconds since last packet arrived on the circuit
|
||||||
|
F64 time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime();
|
||||||
|
|
||||||
|
if (!cdp->isAlive() || // Circuit is dead or blocked
|
||||||
|
cdp->isBlocked() || // or doesn't seem to be getting any packets
|
||||||
|
(time_since_last_packet > sPhaseOutUpdateInterpolationTime))
|
||||||
|
{
|
||||||
|
// Start to reduce motion interpolation since we haven't seen a server update in a while
|
||||||
|
F64 time_since_last_interpolation = time - mLastInterpUpdateSecs;
|
||||||
|
F64 phase_out = 1.0;
|
||||||
|
if (time_since_last_update > sMaxUpdateInterpolationTime)
|
||||||
|
{ // Past the time limit, so stop the object
|
||||||
|
phase_out = 0.0;
|
||||||
|
//llinfos << "Motion phase out to zero" << llendl;
|
||||||
|
|
||||||
|
// Kill angular motion as well. Note - not adding this due to paranoia
|
||||||
|
// about stopping rotation for llTargetOmega objects and not having it restart
|
||||||
|
// setAngularVelocity(LLVector3::zero);
|
||||||
|
}
|
||||||
|
else if (mLastInterpUpdateSecs - mLastMessageUpdateSecs > sPhaseOutUpdateInterpolationTime)
|
||||||
|
{ // Last update was already phased out a bit
|
||||||
|
phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) /
|
||||||
|
(sMaxUpdateInterpolationTime - time_since_last_interpolation);
|
||||||
|
//llinfos << "Continuing motion phase out of " << (F32) phase_out << llendl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Phase out from full value
|
||||||
|
phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) /
|
||||||
|
(sMaxUpdateInterpolationTime - sPhaseOutUpdateInterpolationTime);
|
||||||
|
//llinfos << "Starting motion phase out of " << (F32) phase_out << llendl;
|
||||||
|
}
|
||||||
|
phase_out = llclamp(phase_out, 0.0, 1.0);
|
||||||
|
|
||||||
|
new_pos = new_pos * ((F32) phase_out);
|
||||||
|
new_v = new_v * ((F32) phase_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_pos = new_pos + getPositionRegion();
|
||||||
|
new_v = new_v + vel;
|
||||||
|
|
||||||
|
|
||||||
|
// Clamp interpolated position to minimum underground and maximum region height
|
||||||
|
LLVector3d new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos);
|
||||||
|
F32 min_height;
|
||||||
|
if (isAvatar())
|
||||||
|
{ // Make a better guess about AVs not going underground
|
||||||
|
min_height = LLWorld::getInstance()->resolveLandHeightGlobal(new_pos_global);
|
||||||
|
min_height += (0.5f * getScale().mV[VZ]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // This will put the object underground, but we can't tell if it will stop
|
||||||
|
// at ground level or not
|
||||||
|
min_height = LLWorld::getInstance()->getMinAllowedZ(this, new_pos_global);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_pos.mV[VZ] = llmax(min_height, new_pos.mV[VZ]);
|
||||||
|
new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]);
|
||||||
|
|
||||||
|
// Check to see if it's going off the region
|
||||||
|
LLVector3 temp(new_pos);
|
||||||
|
if (temp.clamp(0.f, mRegionp->getWidth()))
|
||||||
|
{ // Going off this region, so see if we might end up on another region
|
||||||
|
LLVector3d old_pos_global = mRegionp->getPosGlobalFromRegion(getPositionRegion());
|
||||||
|
new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); // Re-fetch in case it got clipped above
|
||||||
|
|
||||||
|
// Clip the positions to known regions
|
||||||
|
LLVector3d clip_pos_global = LLWorld::getInstance()->clipToVisibleRegions(old_pos_global, new_pos_global);
|
||||||
|
if (clip_pos_global != new_pos_global)
|
||||||
|
{ // Was clipped, so this means we hit a edge where there is no region to enter
|
||||||
|
|
||||||
|
//llinfos << "Hit empty region edge, clipped predicted position to " << mRegionp->getPosRegionFromGlobal(clip_pos_global)
|
||||||
|
// << " from " << new_pos << llendl;
|
||||||
|
new_pos = mRegionp->getPosRegionFromGlobal(clip_pos_global);
|
||||||
|
|
||||||
|
// Stop motion and get server update for bouncing on the edge
|
||||||
|
new_v.clear();
|
||||||
|
setAcceleration(LLVector3::zero);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Let predicted movement cross into another region
|
||||||
|
//llinfos << "Predicting region crossing to " << new_pos << llendl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set new position and velocity
|
||||||
|
setPositionRegion(new_pos);
|
||||||
|
setVelocity(new_v);
|
||||||
|
|
||||||
|
// for objects that are spinning but not translating, make sure to flag them as having moved
|
||||||
|
setChanged(MOVED | SILHOUETTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the last time we did anything
|
||||||
|
mLastInterpUpdateSecs = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size)
|
BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size)
|
||||||
{
|
{
|
||||||
LLMemType mt(LLMemType::MTYPE_OBJECT);
|
LLMemType mt(LLMemType::MTYPE_OBJECT);
|
||||||
@@ -2930,6 +3056,8 @@ void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped)
|
|||||||
{
|
{
|
||||||
if (!mOnMap)
|
if (!mOnMap)
|
||||||
{
|
{
|
||||||
|
llassert_always(LLWorld::getInstance()->getRegionFromHandle(getRegion()->getHandle()));
|
||||||
|
|
||||||
gObjectList.addToMap(this);
|
gObjectList.addToMap(this);
|
||||||
mOnMap = TRUE;
|
mOnMap = TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -545,6 +545,9 @@ private:
|
|||||||
ExtraParameter* getExtraParameterEntryCreate(U16 param_type);
|
ExtraParameter* getExtraParameterEntryCreate(U16 param_type);
|
||||||
bool unpackParameterEntry(U16 param_type, LLDataPacker *dp);
|
bool unpackParameterEntry(U16 param_type, LLDataPacker *dp);
|
||||||
|
|
||||||
|
// Motion prediction between updates
|
||||||
|
void interpolateLinearMotion(const F64 & time, const F32 & dt);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//
|
//
|
||||||
// Viewer-side only types - use the LL_PCODE_APP mask.
|
// Viewer-side only types - use the LL_PCODE_APP mask.
|
||||||
@@ -735,8 +738,24 @@ protected:
|
|||||||
mutable LLVector3 mPositionRegion;
|
mutable LLVector3 mPositionRegion;
|
||||||
mutable LLVector3 mPositionAgent;
|
mutable LLVector3 mPositionAgent;
|
||||||
|
|
||||||
|
static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64) value; }
|
||||||
|
static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64) value; }
|
||||||
|
|
||||||
|
static void setVelocityInterpolate(BOOL value) { sVelocityInterpolate = value; }
|
||||||
|
static void setPingInterpolate(BOOL value) { sPingInterpolate = value; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static S32 sNumObjects;
|
static S32 sNumObjects;
|
||||||
|
|
||||||
|
static F64 sPhaseOutUpdateInterpolationTime; // For motion interpolation
|
||||||
|
static F64 sMaxUpdateInterpolationTime; // For motion interpolation
|
||||||
|
|
||||||
|
static BOOL sVelocityInterpolate;
|
||||||
|
static BOOL sPingInterpolate;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// For objects that are attachments
|
||||||
|
//--------------------------------------------------------------------
|
||||||
public:
|
public:
|
||||||
// <edit>
|
// <edit>
|
||||||
S32 getAttachmentPoint();
|
S32 getAttachmentPoint();
|
||||||
@@ -816,7 +835,4 @@ public:
|
|||||||
virtual void updateDrawable(BOOL force_damped);
|
virtual void updateDrawable(BOOL force_damped);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern BOOL gVelocityInterpolate;
|
|
||||||
extern BOOL gPingInterpolate;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -597,33 +597,30 @@ void LLViewerObjectList::dirtyAllObjectInventory()
|
|||||||
void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
|
void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
|
||||||
{
|
{
|
||||||
S32 i;
|
S32 i;
|
||||||
S32 const objects_size = mObjects.size();
|
S32 num_objects = 0;
|
||||||
LLViewerObject *objectp;
|
LLViewerObject *objectp;
|
||||||
|
|
||||||
S32 num_updates, max_value;
|
S32 num_updates, max_value;
|
||||||
// The list can have shrinked since mCurLazyUpdateIndex was last updated.
|
|
||||||
if (mCurLazyUpdateIndex >= objects_size)
|
|
||||||
{
|
|
||||||
mCurLazyUpdateIndex = 0;
|
|
||||||
}
|
|
||||||
if (NUM_BINS - 1 == mCurBin)
|
if (NUM_BINS - 1 == mCurBin)
|
||||||
{
|
{
|
||||||
num_updates = objects_size - mCurLazyUpdateIndex;
|
num_updates = (S32) mObjects.size() - mCurLazyUpdateIndex;
|
||||||
max_value = objects_size;
|
max_value = (S32) mObjects.size();
|
||||||
gTextureList.setUpdateStats(TRUE);
|
gTextureList.setUpdateStats(TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
num_updates = (objects_size / NUM_BINS) + 1;
|
num_updates = ((S32) mObjects.size() / NUM_BINS) + 1;
|
||||||
max_value = llmin(objects_size, mCurLazyUpdateIndex + num_updates);
|
max_value = llmin((S32) mObjects.size(), mCurLazyUpdateIndex + num_updates);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gNoRender)
|
|
||||||
|
// Slam priorities for textures that we care about (hovered, selected, and focused)
|
||||||
|
// Hovered
|
||||||
|
// Assumes only one level deep of parenting
|
||||||
|
LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode();
|
||||||
|
if (nodep)
|
||||||
{
|
{
|
||||||
// Slam priorities for textures that we care about (hovered, selected, and focused)
|
objectp = nodep->getObject();
|
||||||
// Hovered
|
|
||||||
// Assumes only one level deep of parenting
|
|
||||||
objectp = gHoverView->getLastHoverObject();
|
|
||||||
if (objectp)
|
if (objectp)
|
||||||
{
|
{
|
||||||
objectp->boostTexturePriority();
|
objectp->boostTexturePriority();
|
||||||
@@ -654,6 +651,8 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
|
|||||||
objectp = mObjects[i];
|
objectp = mObjects[i];
|
||||||
if (!objectp->isDead())
|
if (!objectp->isDead())
|
||||||
{
|
{
|
||||||
|
num_objects++;
|
||||||
|
|
||||||
// Update distance & gpw
|
// Update distance & gpw
|
||||||
objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area
|
objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area
|
||||||
objectp->updateTextures(); // Update the image levels of textures for this object.
|
objectp->updateTextures(); // Update the image levels of textures for this object.
|
||||||
@@ -661,7 +660,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mCurLazyUpdateIndex = max_value;
|
mCurLazyUpdateIndex = max_value;
|
||||||
if (mCurLazyUpdateIndex == objects_size)
|
if (mCurLazyUpdateIndex == mObjects.size())
|
||||||
{
|
{
|
||||||
mCurLazyUpdateIndex = 0;
|
mCurLazyUpdateIndex = 0;
|
||||||
}
|
}
|
||||||
@@ -861,9 +860,24 @@ private:
|
|||||||
void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
|
void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
|
||||||
{
|
{
|
||||||
LLMemType mt(LLMemType::MTYPE_OBJECT);
|
LLMemType mt(LLMemType::MTYPE_OBJECT);
|
||||||
|
|
||||||
// Update globals
|
// Update globals
|
||||||
gVelocityInterpolate = gSavedSettings.getBOOL("VelocityInterpolate");
|
LLViewerObject::setVelocityInterpolate( gSavedSettings.getBOOL("VelocityInterpolate") );
|
||||||
gPingInterpolate = gSavedSettings.getBOOL("PingInterpolate");
|
LLViewerObject::setPingInterpolate( gSavedSettings.getBOOL("PingInterpolate") );
|
||||||
|
|
||||||
|
F32 interp_time = gSavedSettings.getF32("InterpolationTime");
|
||||||
|
F32 phase_out_time = gSavedSettings.getF32("InterpolationPhaseOut");
|
||||||
|
if (interp_time < 0.0 ||
|
||||||
|
phase_out_time < 0.0 ||
|
||||||
|
phase_out_time > interp_time)
|
||||||
|
{
|
||||||
|
llwarns << "Invalid values for InterpolationTime or InterpolationPhaseOut, resetting to defaults" << llendl;
|
||||||
|
interp_time = 3.0f;
|
||||||
|
phase_out_time = 1.0f;
|
||||||
|
}
|
||||||
|
LLViewerObject::setPhaseOutUpdateInterpolationTime( interp_time );
|
||||||
|
LLViewerObject::setMaxUpdateInterpolationTime( phase_out_time );
|
||||||
|
|
||||||
gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures");
|
gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures");
|
||||||
|
|
||||||
// update global timer
|
// update global timer
|
||||||
|
|||||||
Reference in New Issue
Block a user