Smoother movement fixes for better stopping/starting and timestamp issues. Fixes problem where distributed smooth objects will stop movement at the wrong location or will slide around when first being generated.

This commit is contained in:
Justin Butler 2008-11-22 00:45:17 +00:00
parent 05d992e886
commit 4c09b6307b
4 changed files with 56 additions and 22 deletions

View File

@ -273,13 +273,23 @@ get_sample_hpr() const {
// actual receipt time. // actual receipt time.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void SmoothMover:: INLINE void SmoothMover::
set_phony_timestamp() { set_phony_timestamp(double timestamp, bool period_adjust) {
double now = ClockObject::get_global_clock()->get_frame_time(); double now = ClockObject::get_global_clock()->get_frame_time();
if (timestamp != 0.0)
// we were given a specific timestamp to use
now = timestamp;
// adjust by _delay when creating the timestamp since other // adjust by _delay when creating the timestamp since other
// timestamps received from network updates are adjusted by this // timestamps received from network updates are adjusted by this
_sample._timestamp = now - _delay; if (period_adjust) {
_sample._timestamp = now - _expected_broadcast_period;
}
else
_sample._timestamp = now;
_has_most_recent_timestamp = true; _has_most_recent_timestamp = true;
_most_recent_timestamp = now; _most_recent_timestamp = _sample._timestamp;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -72,7 +72,8 @@ PUBLISHED:
INLINE const LPoint3f &get_sample_pos() const; INLINE const LPoint3f &get_sample_pos() const;
INLINE const LVecBase3f &get_sample_hpr() const; INLINE const LVecBase3f &get_sample_hpr() const;
INLINE void set_phony_timestamp(); INLINE void set_phony_timestamp(double timestamp = 0.0, bool period_adjust = false);
INLINE void set_timestamp(double timestamp); INLINE void set_timestamp(double timestamp);
INLINE bool has_most_recent_timestamp() const; INLINE bool has_most_recent_timestamp() const;

View File

@ -179,14 +179,31 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
self.smoother.setPhonyTimestamp() self.smoother.setPhonyTimestamp()
self.smoother.markPosition() self.smoother.markPosition()
def _checkResume(self): def _checkResume(self,timestamp):
""" """
Determine if we were previously stopped and now need to Determine if we were previously stopped and now need to
resume movement by making sure any old stored positions resume movement by making sure any old stored positions
reflect the node's current position reflect the node's current position
""" """
if (self.stopped): if (self.stopped):
self.reloadPosition() currTime = globalClock.getFrameTime()
now = currTime - self.smoother.getExpectedBroadcastPeriod()
last = self.smoother.getMostRecentTimestamp()
if (now > last):
# only set a new timestamp postion if we still have
# a position being smoothed to (so we don't interrupt
# any current smoothing and only do this if the object
# is actually locally stopped)
if (timestamp == None):
# no timestamp, use current time
local = 0.0
else:
local = globalClockDelta.networkToLocalTime(
timestamp, currTime)
self.smoother.setPhonyTimestamp(local,True)
self.smoother.markPosition()
self.stopped = False self.stopped = False
# distributed set pos and hpr functions # distributed set pos and hpr functions
@ -195,50 +212,50 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
self.stopped = True self.stopped = True
def setSmH(self, h, timestamp=None): def setSmH(self, h, timestamp=None):
self._checkResume() self._checkResume(timestamp)
self.setComponentH(h) self.setComponentH(h)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmZ(self, z, timestamp=None): def setSmZ(self, z, timestamp=None):
self._checkResume() self._checkResume(timestamp)
self.setComponentZ(z) self.setComponentZ(z)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmXY(self, x, y, timestamp=None): def setSmXY(self, x, y, timestamp=None):
self._checkResume() self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
self.setComponentY(y) self.setComponentY(y)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmXZ(self, x, z, timestamp=None): def setSmXZ(self, x, z, timestamp=None):
self._checkResume() self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
self.setComponentZ(z) self.setComponentZ(z)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmPos(self, x, y, z, timestamp=None): def setSmPos(self, x, y, z, timestamp=None):
self._checkResume() self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
self.setComponentY(y) self.setComponentY(y)
self.setComponentZ(z) self.setComponentZ(z)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmHpr(self, h, p, r, timestamp=None): def setSmHpr(self, h, p, r, timestamp=None):
self._checkResume() self._checkResume(timestamp)
self.setComponentH(h) self.setComponentH(h)
self.setComponentP(p) self.setComponentP(p)
self.setComponentR(r) self.setComponentR(r)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmXYH(self, x, y, h, timestamp): def setSmXYH(self, x, y, h, timestamp):
self._checkResume() self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
self.setComponentY(y) self.setComponentY(y)
self.setComponentH(h) self.setComponentH(h)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmXYZH(self, x, y, z, h, timestamp=None): def setSmXYZH(self, x, y, z, h, timestamp=None):
self._checkResume() self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
self.setComponentY(y) self.setComponentY(y)
self.setComponentZ(z) self.setComponentZ(z)
self.setComponentH(h) self.setComponentH(h)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmPosHpr(self, x, y, z, h, p, r, timestamp=None): def setSmPosHpr(self, x, y, z, h, p, r, timestamp=None):
self._checkResume() self._checkResume(timestamp)
self.setComponentX(x) self.setComponentX(x)
self.setComponentY(y) self.setComponentY(y)
self.setComponentZ(z) self.setComponentZ(z)
@ -246,8 +263,9 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
self.setComponentP(p) self.setComponentP(p)
self.setComponentR(r) self.setComponentR(r)
self.setComponentTLive(timestamp) self.setComponentTLive(timestamp)
def setSmPosHprL(self, l, x, y, z, h, p, r, timestamp=None): def setSmPosHprL(self, l, x, y, z, h, p, r, timestamp=None):
self._checkResume() self._checkResume(timestamp)
self.setComponentL(l) self.setComponentL(l)
self.setComponentX(x) self.setComponentX(x)
self.setComponentY(y) self.setComponentY(y)
@ -304,10 +322,11 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
self.smoother.clearPositions(1) self.smoother.clearPositions(1)
self.smoother.markPosition() self.smoother.markPosition()
# jbutler: took this out, appears it is not needed since # mark position only takes most recent position sent over the wire
# markPosition above stored the node's position, and this # and applies it to the smoother's sample points, but we still
# just reapplies the poition to the node # need to make sure and apply that position to the actual node
#self.forceToTruePosition() # path
self.forceToTruePosition()
@report(types = ['args'], dConfigParam = 'want-smoothnode-report') @report(types = ['args'], dConfigParam = 'want-smoothnode-report')
def setComponentTLive(self, timestamp): def setComponentTLive(self, timestamp):

View File

@ -16,7 +16,7 @@ class DistributedSmoothNodeBase:
BroadcastTypes = Enum('FULL, XYH, XY') BroadcastTypes = Enum('FULL, XYH, XY')
def __init__(self): def __init__(self):
pass self.__broadcastPeriod = None
def generate(self): def generate(self):
self.cnode = CDistributedSmoothNodeBase() self.cnode = CDistributedSmoothNodeBase()
@ -47,6 +47,10 @@ class DistributedSmoothNodeBase:
# call this at any time to change the delay between broadcasts # call this at any time to change the delay between broadcasts
self.__broadcastPeriod = period self.__broadcastPeriod = period
def getPosHprBroadcastPeriod(self):
# query the current delay between broadcasts
return self.__broadcastPeriod
def stopPosHprBroadcast(self): def stopPosHprBroadcast(self):
taskMgr.remove(self.getPosHprBroadcastTaskName()) taskMgr.remove(self.getPosHprBroadcastTaskName())
# Delete this callback because it maintains a reference to self # Delete this callback because it maintains a reference to self