define SmoothMover
This commit is contained in:
parent
e0bc027a90
commit
59642233cb
|
|
@ -4,16 +4,16 @@
|
|||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx
|
||||
|
||||
#define SOURCES \
|
||||
correction.h prediction.h
|
||||
smoothMover.h smoothMover.I
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
correction.cxx prediction.cxx
|
||||
smoothMover.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
correction.h prediction.h
|
||||
smoothMover.h smoothMover.I
|
||||
|
||||
#define IGATESCAN \
|
||||
correction.h prediction.h
|
||||
all
|
||||
|
||||
#define LOCAL_LIBS \
|
||||
directbase
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "prediction.cxx"
|
||||
#include "correction.cxx"
|
||||
#include "smoothMover.cxx"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,339 @@
|
|||
// Filename: smoothMover.I
|
||||
// Created by: drose (19Oct01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_scale
|
||||
// Access: Published
|
||||
// Description: Specifies the current scale that should be applied to
|
||||
// the transform. This is not smoothed along with pos
|
||||
// and hpr, but rather takes effect immediately; it is
|
||||
// only here at all so we can return a complete matrix
|
||||
// in get_smooth_mat().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_scale(float sx, float sy, float sz) {
|
||||
return set_sx(sx) | set_sy(sy) | set_sz(sz);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_sx
|
||||
// Access: Published
|
||||
// Description: Sets the X-axis scale only. See set_scale().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_sx(float sx) {
|
||||
bool result = (sx != _scale[0]);
|
||||
_scale[0] = sx;
|
||||
_computed_smooth_mat = _computed_smooth_mat && !result;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_sy
|
||||
// Access: Published
|
||||
// Description: Sets the Y-axis scale only. See set_scale().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_sy(float sy) {
|
||||
bool result = (sy != _scale[1]);
|
||||
_scale[1] = sy;
|
||||
_computed_smooth_mat = _computed_smooth_mat && !result;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_sz
|
||||
// Access: Published
|
||||
// Description: Sets the Z-axis scale only. See set_scale().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_sz(float sz) {
|
||||
bool result = (sz != _scale[2]);
|
||||
_scale[2] = sz;
|
||||
_computed_smooth_mat = _computed_smooth_mat && !result;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_pos
|
||||
// Access: Published
|
||||
// Description: Specifies the position of the SmoothMover at a
|
||||
// particular time in the past. When mark_position() is
|
||||
// called, this will be recorded (along with hpr and
|
||||
// timestamp) in a position report, which will then be
|
||||
// used along with all other position reports to
|
||||
// determine the smooth position at any particular
|
||||
// instant.
|
||||
//
|
||||
// The return value is true if any parameter has changed
|
||||
// since the last call to set_pos(), or false if they
|
||||
// are the same.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_pos(float x, float y, float z) {
|
||||
return set_x(x) | set_y(y) | set_z(z);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_x
|
||||
// Access: Published
|
||||
// Description: Sets the X position only. See set_pos().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_x(float x) {
|
||||
bool result = (x != _sample._pos[0]);
|
||||
_sample._pos[0] = x;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_y
|
||||
// Access: Published
|
||||
// Description: Sets the Y position only. See set_pos().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_y(float y) {
|
||||
bool result = (y != _sample._pos[1]);
|
||||
_sample._pos[1] = y;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_z
|
||||
// Access: Published
|
||||
// Description: Sets the Z position only. See set_pos().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_z(float z) {
|
||||
bool result = (z != _sample._pos[2]);
|
||||
_sample._pos[2] = z;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_hpr
|
||||
// Access: Published
|
||||
// Description: Specifies the orientation of the SmoothMover at a
|
||||
// particular time in the past. When mark_position() is
|
||||
// called, this will be recorded (along with hpr and
|
||||
// timestamp) in a position report, which will then be
|
||||
// used along with all other position reports to
|
||||
// determine the smooth position at any particular
|
||||
// instant.
|
||||
//
|
||||
// The return value is true if any parameter has changed
|
||||
// since the last call to set_hpr(), or false if they
|
||||
// are the same.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_hpr(float h, float p, float r) {
|
||||
return set_h(h) | set_p(p) | set_r(r);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_h
|
||||
// Access: Published
|
||||
// Description: Sets the heading only. See set_hpr().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_h(float h) {
|
||||
bool result = (h != _sample._hpr[0]);
|
||||
_sample._hpr[0] = h;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_p
|
||||
// Access: Published
|
||||
// Description: Sets the pitch only. See set_hpr().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_p(float p) {
|
||||
bool result = (p != _sample._hpr[1]);
|
||||
_sample._hpr[1] = p;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_r
|
||||
// Access: Published
|
||||
// Description: Sets the roll only. See set_hpr().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool SmoothMover::
|
||||
set_r(float r) {
|
||||
bool result = (r != _sample._hpr[2]);
|
||||
_sample._hpr[2] = r;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_timestamp
|
||||
// Access: Published
|
||||
// Description: Specifies the time that the current position report
|
||||
// applies. This should be called, along with set_pos()
|
||||
// and set_hpr(), before a call to mark_position().
|
||||
//
|
||||
// With no parameter, set_timestamp uses
|
||||
// ClockObject::get_frame_time() as the default time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SmoothMover::
|
||||
set_timestamp() {
|
||||
set_timestamp(ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_timestamp
|
||||
// Access: Published
|
||||
// Description: Specifies the time that the current position report
|
||||
// applies. This should be called, along with set_pos()
|
||||
// and set_hpr(), before a call to mark_position().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SmoothMover::
|
||||
set_timestamp(double timestamp) {
|
||||
_sample._timestamp = timestamp;
|
||||
_sample._flags |= F_got_timestamp;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::compute_smooth_position
|
||||
// Access: Published
|
||||
// Description: Computes the smoothed position (and orientation) of
|
||||
// the mover at the indicated point in time, based on
|
||||
// the previous position reports. After this call has
|
||||
// been made, get_smooth_pos() etc. may be called to
|
||||
// retrieve the smoothed position.
|
||||
//
|
||||
// With no parameter, the function uses
|
||||
// ClockObject::get_frame_time() as the default time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SmoothMover::
|
||||
compute_smooth_position() {
|
||||
compute_smooth_position(ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::get_smooth_pos
|
||||
// Access: Published
|
||||
// Description: Returns the smoothed position as computed by a
|
||||
// previous call to compute_smooth_position().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LPoint3f &SmoothMover::
|
||||
get_smooth_pos() const {
|
||||
return _smooth_pos;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::get_smooth_hpr
|
||||
// Access: Published
|
||||
// Description: Returns the smoothed orientation as computed by a
|
||||
// previous call to compute_smooth_position().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LVecBase3f &SmoothMover::
|
||||
get_smooth_hpr() const {
|
||||
return _smooth_hpr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::get_smooth_mat
|
||||
// Access: Published
|
||||
// Description: Returns the complete smoothed transformation matrix
|
||||
// as computed by a previous call to
|
||||
// compute_smooth_position().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LMatrix4f &SmoothMover::
|
||||
get_smooth_mat() {
|
||||
if (!_computed_smooth_mat) {
|
||||
compose_smooth_mat();
|
||||
}
|
||||
return _smooth_mat;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_smooth_mode
|
||||
// Access: Published, Static
|
||||
// Description: Sets the smoothing mode of all SmoothMovers in the
|
||||
// world. If this is SM_off, no smoothing or prediction
|
||||
// will be performed, and get_smooth_pos() will simply
|
||||
// return the position last set by mark_position().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SmoothMover::
|
||||
set_smooth_mode(SmoothMover::SmoothMode mode) {
|
||||
_smooth_mode = mode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::get_smooth_mode
|
||||
// Access: Published, Static
|
||||
// Description: Returns the smoothing mode of all SmoothMovers in the
|
||||
// world. See set_smooth_mode().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE SmoothMover::SmoothMode SmoothMover::
|
||||
get_smooth_mode() {
|
||||
return _smooth_mode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_prediction_mode
|
||||
// Access: Published, Static
|
||||
// Description: Sets the predictioning mode of all SmoothMovers in the
|
||||
// world. If this is PM_off, no prediction will be
|
||||
// performed, but smoothing might still be performed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SmoothMover::
|
||||
set_prediction_mode(SmoothMover::PredictionMode mode) {
|
||||
_prediction_mode = mode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::get_prediction_mode
|
||||
// Access: Published, Static
|
||||
// Description: Returns the predictioning mode of all SmoothMovers in the
|
||||
// world. See set_prediction_mode().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE SmoothMover::PredictionMode SmoothMover::
|
||||
get_prediction_mode() {
|
||||
return _prediction_mode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::set_delay
|
||||
// Access: Published, Static
|
||||
// Description: Sets the amount of time, in seconds, to delay the
|
||||
// computed position of a SmoothMover. This is
|
||||
// particularly useful when the prediction mode is off,
|
||||
// because it can allow the apparent motion of an avatar
|
||||
// to appear smooth without relying on prediction, at
|
||||
// the cost of introducing additional lag in the
|
||||
// avatar's apparent position.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SmoothMover::
|
||||
set_delay(double delay) {
|
||||
_delay = delay;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::get_delay
|
||||
// Access: Published, Static
|
||||
// Description: Returns the amount of time, in seconds, to delay the
|
||||
// computed position of a SmoothMover. See set_delay().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double SmoothMover::
|
||||
get_delay() {
|
||||
return _delay;
|
||||
}
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
// Filename: smoothMover.cxx
|
||||
// Created by: drose (19Oct01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "smoothMover.h"
|
||||
#include "notify.h"
|
||||
#include "compose_matrix.h"
|
||||
|
||||
SmoothMover::SmoothMode SmoothMover::_smooth_mode = SmoothMover::SM_off;
|
||||
SmoothMover::PredictionMode SmoothMover::_prediction_mode = SmoothMover::PM_off;
|
||||
double SmoothMover::_delay = 0.0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SmoothMover::
|
||||
SmoothMover() {
|
||||
_scale.set(1.0, 1.0, 1.0);
|
||||
_sample._pos.set(0.0, 0.0, 0.0);
|
||||
_sample._hpr.set(0.0, 0.0, 0.0);
|
||||
_sample._timestamp = 0.0;
|
||||
_sample._flags = 0;
|
||||
|
||||
_smooth_pos.set(0.0, 0.0, 0.0);
|
||||
_smooth_hpr.set(0.0, 0.0, 0.0);
|
||||
_smooth_mat = LMatrix4f::ident_mat();
|
||||
_computed_smooth_mat = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::Destructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SmoothMover::
|
||||
~SmoothMover() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::mark_position
|
||||
// Access: Published
|
||||
// Description: Stores the position, orientation, and timestamp (if
|
||||
// relevant) indicated by previous calls to set_pos(),
|
||||
// set_hpr(), and set_timestamp() in a new position
|
||||
// report.
|
||||
//
|
||||
// When compute_smooth_position() is called, it uses
|
||||
// these stored position reports to base its computation
|
||||
// of the known position.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SmoothMover::
|
||||
mark_position() {
|
||||
if (_smooth_mode == SM_off) {
|
||||
// With smoothing disabled, mark_position() simply stores its
|
||||
// current position in the smooth_position members.
|
||||
_smooth_pos = _sample._pos;
|
||||
_smooth_hpr = _sample._hpr;
|
||||
_computed_smooth_mat = false;
|
||||
|
||||
} else {
|
||||
// Otherwise, smoothing is in effect and we store a true position
|
||||
// report.
|
||||
|
||||
if (_points.full()) {
|
||||
// If we have too many position reports, throw away the oldest
|
||||
// one.
|
||||
_points.pop_front();
|
||||
}
|
||||
|
||||
_points.push_back(_sample);
|
||||
_sample._flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::compute_smooth_position
|
||||
// Access: Published
|
||||
// Description: Computes the smoothed position (and orientation) of
|
||||
// the mover at the indicated point in time, based on
|
||||
// the previous position reports. After this call has
|
||||
// been made, get_smooth_pos() etc. may be called to
|
||||
// retrieve the smoothed position.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SmoothMover::
|
||||
compute_smooth_position(double timestamp) {
|
||||
if (_smooth_mode == SM_off || _points.empty()) {
|
||||
// With smoothing disabled, or with no position reports available,
|
||||
// this function does nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
// First, back up in time by the specified delay factor.
|
||||
timestamp -= _delay;
|
||||
|
||||
// Now look for the two bracketing position reports.
|
||||
int point_before = -1;
|
||||
double timestamp_before = 0.0;
|
||||
int point_after = -1;
|
||||
double timestamp_after = 0.0;
|
||||
|
||||
int num_points = _points.size();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
const SamplePoint &point = _points[i];
|
||||
if (point._timestamp <= timestamp) {
|
||||
// This point is before the desired time. Find the newest of
|
||||
// these.
|
||||
if (point_before == -1 || point._timestamp > timestamp_before) {
|
||||
point_before = i;
|
||||
timestamp_before = point._timestamp;
|
||||
}
|
||||
}
|
||||
if (point._timestamp >= timestamp) {
|
||||
// This point is after the desired time. Find the oldest of
|
||||
// these.
|
||||
if (point_after == -1 || point._timestamp < timestamp_after) {
|
||||
point_after = i;
|
||||
timestamp_after = point._timestamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (point_before == -1) {
|
||||
nassertv(point_after != -1);
|
||||
// If we only have an after point, we have to start there.
|
||||
const SamplePoint &point = _points[point_after];
|
||||
_smooth_pos = point._pos;
|
||||
_smooth_hpr = point._hpr;
|
||||
_computed_smooth_mat = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (point_after == -1) {
|
||||
// If we only have a before point, we have to stop there, unless
|
||||
// we have prediction in effect.
|
||||
const SamplePoint &point = _points[point_before];
|
||||
_smooth_pos = point._pos;
|
||||
_smooth_hpr = point._hpr;
|
||||
_computed_smooth_mat = false;
|
||||
|
||||
} else {
|
||||
// If we have two points, we can linearly interpolate between them.
|
||||
const SamplePoint &point_b = _points[point_before];
|
||||
const SamplePoint &point_a = _points[point_after];
|
||||
|
||||
double t = (timestamp - timestamp_before) / (timestamp_after - timestamp_before);
|
||||
_smooth_pos = point_b._pos + t * (point_a._pos - point_b._pos);
|
||||
_smooth_hpr = point_b._hpr + t * (point_a._hpr - point_b._hpr);
|
||||
_computed_smooth_mat = false;
|
||||
}
|
||||
|
||||
// Assume we'll never get another compute_smooth_position() request
|
||||
// for an older time than this, and remove all the timestamps at the
|
||||
// head of the queue before point_before.
|
||||
while (!_points.empty() && _points.front()._timestamp < timestamp_before) {
|
||||
_points.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::output
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SmoothMover::
|
||||
output(ostream &out) const {
|
||||
out << "SmoothMover, " << _points.size() << " sample points.";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::write
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SmoothMover::
|
||||
write(ostream &out) const {
|
||||
out << "SmoothMover, " << _points.size() << " sample points:\n";
|
||||
int num_points = _points.size();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
const SamplePoint &point = _points[i];
|
||||
out << " " << i << ". time = " << point._timestamp << " pos = "
|
||||
<< point._pos << " hpr = " << point._hpr << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SmoothMover::compose_smooth_mat
|
||||
// Access: Private
|
||||
// Description: Computes the smooth_mat based on smooth_pos and
|
||||
// smooth_hpr.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SmoothMover::
|
||||
compose_smooth_mat() {
|
||||
compose_matrix(_smooth_mat, _scale, _smooth_hpr, _smooth_pos);
|
||||
_computed_smooth_mat = true;
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
// Filename: smoothMover.h
|
||||
// Created by: drose (19Oct01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SMOOTHMOVER_H
|
||||
#define SMOOTHMOVER_H
|
||||
|
||||
#include "directbase.h"
|
||||
#include "luse.h"
|
||||
#include "clockObject.h"
|
||||
#include "circBuffer.h"
|
||||
|
||||
static const int max_position_reports = 10;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : SmoothMover
|
||||
// Description : This class handles smoothing of sampled motion points
|
||||
// over time, e.g. for smoothing the apparent movement
|
||||
// of remote avatars, whose positions are sent via
|
||||
// occasional telemetry updates.
|
||||
//
|
||||
// It can operate in any of three modes: off, in which
|
||||
// it does not smooth any motion but provides the last
|
||||
// position it was told; smoothing only, in which it
|
||||
// smooths motion information but never tries to
|
||||
// anticipate where the avatar might be going; or full
|
||||
// prediction, in which it smooths motion as well as
|
||||
// tries to predict the avatar's position in lead of the
|
||||
// last position update. The assumption is that all
|
||||
// SmoothMovers in the world will be operating in the
|
||||
// same mode together.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DIRECT SmoothMover {
|
||||
PUBLISHED:
|
||||
SmoothMover();
|
||||
~SmoothMover();
|
||||
|
||||
// This method is just used to specify a scale which is only used
|
||||
// when composing the matrix for return by get_smooth_mat(). It
|
||||
// might change from time to time, but it is not smoothed.
|
||||
INLINE bool set_scale(float sx, float sy, float sz);
|
||||
INLINE bool set_sx(float sx);
|
||||
INLINE bool set_sy(float sy);
|
||||
INLINE bool set_sz(float sz);
|
||||
|
||||
// These methods are used to specify each position update. Call the
|
||||
// appropriate set_* function(s), as needed, and then call
|
||||
// mark_position(). The return value of each function is true if
|
||||
// the parameter value has changed, or false if it remains the same
|
||||
// as last time.
|
||||
INLINE bool set_pos(float x, float y, float z);
|
||||
INLINE bool set_x(float x);
|
||||
INLINE bool set_y(float y);
|
||||
INLINE bool set_z(float z);
|
||||
|
||||
INLINE bool set_hpr(float h, float p, float r);
|
||||
INLINE bool set_h(float h);
|
||||
INLINE bool set_p(float p);
|
||||
INLINE bool set_r(float r);
|
||||
|
||||
INLINE void set_timestamp();
|
||||
INLINE void set_timestamp(double timestamp);
|
||||
|
||||
void mark_position();
|
||||
|
||||
INLINE void compute_smooth_position();
|
||||
void compute_smooth_position(double timestamp);
|
||||
|
||||
INLINE const LPoint3f &get_smooth_pos() const;
|
||||
INLINE const LVecBase3f &get_smooth_hpr() const;
|
||||
INLINE const LMatrix4f &get_smooth_mat();
|
||||
|
||||
// These static methods control the global properties of all
|
||||
// SmoothMovers.
|
||||
enum SmoothMode {
|
||||
SM_off,
|
||||
SM_on,
|
||||
};
|
||||
enum PredictionMode {
|
||||
PM_off,
|
||||
PM_on,
|
||||
};
|
||||
|
||||
INLINE static void set_smooth_mode(SmoothMode mode);
|
||||
INLINE static SmoothMode get_smooth_mode();
|
||||
|
||||
INLINE static void set_prediction_mode(PredictionMode mode);
|
||||
INLINE static PredictionMode get_prediction_mode();
|
||||
|
||||
INLINE static void set_delay(double delay);
|
||||
INLINE static double get_delay();
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out) const;
|
||||
|
||||
private:
|
||||
void compose_smooth_mat();
|
||||
|
||||
enum Flags {
|
||||
F_got_timestamp = 0x0001,
|
||||
};
|
||||
|
||||
LVecBase3f _scale;
|
||||
|
||||
class SamplePoint {
|
||||
public:
|
||||
LPoint3f _pos;
|
||||
LVecBase3f _hpr;
|
||||
double _timestamp;
|
||||
int _flags;
|
||||
};
|
||||
SamplePoint _sample;
|
||||
|
||||
LPoint3f _smooth_pos;
|
||||
LVecBase3f _smooth_hpr;
|
||||
LMatrix4f _smooth_mat;
|
||||
bool _computed_smooth_mat;
|
||||
|
||||
|
||||
typedef CircBuffer<SamplePoint, max_position_reports> Points;
|
||||
Points _points;
|
||||
|
||||
static SmoothMode _smooth_mode;
|
||||
static PredictionMode _prediction_mode;
|
||||
static double _delay;
|
||||
};
|
||||
|
||||
#include "smoothMover.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -3,8 +3,6 @@
|
|||
from ShowBaseGlobal import *
|
||||
import NodePath
|
||||
import DistributedObject
|
||||
import Correction
|
||||
import Prediction
|
||||
import Task
|
||||
|
||||
class DistributedNode(DistributedObject.DistributedObject, NodePath.NodePath):
|
||||
|
|
@ -16,7 +14,6 @@ class DistributedNode(DistributedObject.DistributedObject, NodePath.NodePath):
|
|||
except:
|
||||
self.DistributedNode_initialized = 1
|
||||
DistributedObject.DistributedObject.__init__(self, cr)
|
||||
self.DeadReckoningFlag = 0
|
||||
return None
|
||||
|
||||
def disable(self):
|
||||
|
|
@ -33,37 +30,8 @@ class DistributedNode(DistributedObject.DistributedObject, NodePath.NodePath):
|
|||
DistributedObject.DistributedObject.delete(self)
|
||||
|
||||
def generate(self):
|
||||
# Turn on dead reckoning
|
||||
#print ("Turning on dead reckoning!!!")
|
||||
#self.deadReckoningOn()
|
||||
DistributedObject.DistributedObject.generate(self)
|
||||
|
||||
def deadReckoningOn(self):
|
||||
# Be sure that it isn't already on
|
||||
self.deadReckoningOff()
|
||||
|
||||
self.deadReckoningFlag = 1
|
||||
|
||||
self.Predictor = NullPrediction(Point3(self.getX(), self.getY(),
|
||||
self.getZ()))
|
||||
self.Corrector = SplineCorrection(Point3(self.getX(), self.getY(),
|
||||
self.getZ()), Vec3(0))
|
||||
taskName = self.taskName("correctionPos")
|
||||
# remove any old tasks
|
||||
taskMgr.removeTasksNamed(taskName)
|
||||
# spawn new task
|
||||
task = Task.Task(self.correctPos)
|
||||
taskMgr.spawnTaskNamed(task, taskName)
|
||||
return self.deadReckoningFlag
|
||||
|
||||
def deadReckoningOff(self):
|
||||
self.deadReckoningFlag = 0
|
||||
self.Predictor = None
|
||||
self.Corrector = None
|
||||
taskName = self.taskName("correctionPos")
|
||||
taskMgr.removeTasksNamed(taskName)
|
||||
return self.deadReckoningFlag
|
||||
|
||||
### setParent ###
|
||||
|
||||
def b_setParent(self, parentString):
|
||||
|
|
@ -145,80 +113,3 @@ class DistributedNode(DistributedObject.DistributedObject, NodePath.NodePath):
|
|||
def d_setPosHpr(self, x, y, z, h, p, r):
|
||||
self.sendUpdate("setPosHpr", [x, y, z, h, p, r])
|
||||
|
||||
###### Dead Reckoned set pos and hpr functions ######
|
||||
|
||||
def setDRX(self, x):
|
||||
curPoint = self.Predictor.getPos()
|
||||
self.Predictor.newTelemetry(x, curPoint[1], curPoint[2])
|
||||
def d_setDRX(self, x):
|
||||
self.sendUpdate("setDRX", [x])
|
||||
|
||||
def setDRY(self, y):
|
||||
curPoint = self.Predictor.getPos()
|
||||
self.Predictor.newTelemetry(curPoint[0], y, curPoint[2])
|
||||
def d_setDRY(self, y):
|
||||
self.sendUpdate("setDRY", [y])
|
||||
|
||||
def setDRZ(self, z):
|
||||
curPoint = self.Predictor.getPos()
|
||||
self.Predictor.newTelemetry(curPoint[0], curPoint[1], z)
|
||||
def d_setDRZ(self, z):
|
||||
self.sendUpdate("setDRZ", [z])
|
||||
|
||||
def setDRH(self, h):
|
||||
self.setH(h)
|
||||
def d_setDRH(self, h):
|
||||
self.sendUpdate("setDRH", [h])
|
||||
|
||||
def setDRP(self, p):
|
||||
self.setP(p)
|
||||
def d_setDRP(self, p):
|
||||
self.sendUpdate("setDRP", [p])
|
||||
|
||||
def setDRR(self, r):
|
||||
self.setR(r)
|
||||
def d_setDRR(self, r):
|
||||
self.sendUpdate("setDRR", [r])
|
||||
|
||||
def setDRXY(self, x, y):
|
||||
curPoint = self.Predictor.getPos()
|
||||
self.Predictor.newTelemetry(Point3(x, y, curPoint[2]))
|
||||
def d_setDRXY(self, x, y):
|
||||
self.sendUpdate("setDRXY", [x, y])
|
||||
|
||||
def setDRPos(self, x, y, z):
|
||||
self.Predictor.newTelemetry(Point3(x, y, z))
|
||||
def d_setDRPos(self, x, y, z):
|
||||
self.sendUpdate("setDRPos", [x, y, z])
|
||||
|
||||
def setDRHpr(self, h, p, r):
|
||||
self.setHpr(h, p, r)
|
||||
def d_setDRHpr(self, h, p, r):
|
||||
self.sendUpdate("setDRHpr", [h, p, r])
|
||||
|
||||
def setDRXYH(self, x, y, h):
|
||||
curPoint = self.Predictor.getPos()
|
||||
self.Predictor.newTelemetry(Point3(x, y, curPoint[2]))
|
||||
self.setH(h)
|
||||
def d_setDRXYH(self, x, y, h):
|
||||
self.sendUpdate("setDRXYH", [x, y, h])
|
||||
|
||||
def setDRXYZH(self, x, y, z, h):
|
||||
self.Predictor.newTelemetry(Point3(x, y, z))
|
||||
self.setH(h)
|
||||
def d_setDRXYZH(self, x, y, z, h):
|
||||
self.sendUpdate("setDRXYZH", [x, y, z, h])
|
||||
|
||||
def setDRPosHpr(self, x, y, z, h, p, r):
|
||||
self.Predictor.newTelemetry(Point3(x, y, z))
|
||||
NodePath.NodePath.setHpr(self, h, p, r)
|
||||
def d_setDRPosHpr(self, x, y, z, h, p, r):
|
||||
self.sendUpdate("setDRPosHpr", [x, y, z, h, p, r])
|
||||
|
||||
def correctPos(self, task):
|
||||
self.Corrector.newTarget(self.Predictor.getPos(),
|
||||
self.Predictor.getVel())
|
||||
self.Corrector.step()
|
||||
NodePath.NodePath.setPos(self, self.Corrector.getPos())
|
||||
return Task.cont
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue