Browse Source

fixes to smoothing

David Rose 19 years ago
parent
commit
1ca01f215c

+ 27 - 0
direct/src/deadrec/smoothMover.I

@@ -666,6 +666,33 @@ get_reset_velocity_age() {
   return _reset_velocity_age;
   return _reset_velocity_age;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: SmoothMover::set_directional_velocity
+//       Access: Published, Static
+//  Description: Sets the flag that indicates whether the avatar's
+//               direction is considered in computing the velocity.
+//               When this is true, velocity is automatically
+//               decomposed into a forward and a lateral velocity (and
+//               both may be positive or negative); when it is false,
+//               all velocity is always returned as forward velocity
+//               (and it is always positive).
+////////////////////////////////////////////////////////////////////
+INLINE void SmoothMover::
+set_directional_velocity(bool flag) {
+  _directional_velocity = flag;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SmoothMover::get_directional_velocity
+//       Access: Published, Static
+//  Description: Returns the current state of the 'directional
+//               velocity' flag.  See set_directional_velocity().
+////////////////////////////////////////////////////////////////////
+INLINE bool SmoothMover::
+get_directional_velocity() {
+  return _directional_velocity;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: SmoothMover::get_avg_timestamp_delay
 //     Function: SmoothMover::get_avg_timestamp_delay
 //       Access: Private
 //       Access: Private

+ 59 - 26
direct/src/deadrec/smoothMover.cxx

@@ -60,6 +60,7 @@ SmoothMover() {
   _prediction_mode = PM_off;
   _prediction_mode = PM_off;
   _delay = 0.2;
   _delay = 0.2;
   _accept_clock_skew = true;
   _accept_clock_skew = true;
+  _directional_velocity = true;
   _max_position_age = 0.25;
   _max_position_age = 0.25;
   _expected_broadcast_period = 0.2;
   _expected_broadcast_period = 0.2;
   _reset_velocity_age = 0.3;
   _reset_velocity_age = 0.3;
@@ -220,6 +221,10 @@ compute_smooth_position(double timestamp) {
     if (_smooth_position_known) {
     if (_smooth_position_known) {
       double age = timestamp - _smooth_timestamp;
       double age = timestamp - _smooth_timestamp;
       if (age > _reset_velocity_age) {
       if (age > _reset_velocity_age) {
+        if (deadrec_cat.is_debug()) {
+          deadrec_cat.debug()
+            << "points empty; reset velocity, age = " << age << "\n";
+        }
         _smooth_forward_velocity = 0.0;
         _smooth_forward_velocity = 0.0;
         _smooth_lateral_velocity = 0.0;
         _smooth_lateral_velocity = 0.0;
         _smooth_rotational_velocity = 0.0;
         _smooth_rotational_velocity = 0.0;
@@ -258,7 +263,9 @@ compute_smooth_position(double timestamp) {
 
 
   if (deadrec_cat.is_spam()) {
   if (deadrec_cat.is_spam()) {
     deadrec_cat.spam()
     deadrec_cat.spam()
-      << "time = " << timestamp << ", " << _points.size() << " points, last = " << _last_point_before << ", " << _last_point_after << "\n";
+      << "time = " << timestamp << ", " << _points.size()
+      << " points, last = " << _last_point_before << ", " 
+      << _last_point_after << "\n";
     deadrec_cat.spam(false)
     deadrec_cat.spam(false)
       << "  ";
       << "  ";
     for (int pi = 0; pi < (int)_points.size(); pi++) {
     for (int pi = 0; pi < (int)_points.size(); pi++) {
@@ -367,11 +374,12 @@ compute_smooth_position(double timestamp) {
       set_smooth_pos(point._pos, point._hpr, timestamp);
       set_smooth_pos(point._pos, point._hpr, timestamp);
     }
     }
 
 
-    if (orig_timestamp - _last_heard_from > _reset_velocity_age) {
-      // Furthermore, if we haven't heard from this client in a while,
-      // reset the velocity.  This decision is based entirely on our
-      // local timestamps, not on the other client's reported
-      // timestamps.
+    double age = timestamp - timestamp_before;
+    if (age > _reset_velocity_age) {
+      if (deadrec_cat.is_spam()) {
+        deadrec_cat.spam()
+          << "  reset_velocity, age = " << age << "\n";
+      }
       _smooth_forward_velocity = 0.0;
       _smooth_forward_velocity = 0.0;
       _smooth_lateral_velocity = 0.0;
       _smooth_lateral_velocity = 0.0;
       _smooth_rotational_velocity = 0.0;
       _smooth_rotational_velocity = 0.0;
@@ -390,8 +398,17 @@ compute_smooth_position(double timestamp) {
     
     
     if (point_b._pos == point_a._pos && point_b._hpr == point_a._hpr) {
     if (point_b._pos == point_a._pos && point_b._hpr == point_a._hpr) {
       // The points are equivalent, so just return that.
       // The points are equivalent, so just return that.
+      if (deadrec_cat.is_spam()) {
+        deadrec_cat.spam()
+          << "Points are equivalent\n";
+      }
       set_smooth_pos(point_b._pos, point_b._hpr, timestamp);
       set_smooth_pos(point_b._pos, point_b._hpr, timestamp);
 
 
+      // This implies that velocity is 0.
+      _smooth_forward_velocity = 0.0;
+      _smooth_lateral_velocity = 0.0;
+      _smooth_rotational_velocity = 0.0;
+
     } else {
     } else {
       // The points are different, so we have to do some work.
       // The points are different, so we have to do some work.
       double age = (point_a._timestamp - point_b._timestamp);
       double age = (point_a._timestamp - point_b._timestamp);
@@ -400,9 +417,18 @@ compute_smooth_position(double timestamp) {
         // If the first point is too old, assume there were a lot of
         // If the first point is too old, assume there were a lot of
         // implicit standing still messages that weren't sent.  Insert a new
         // implicit standing still messages that weren't sent.  Insert a new
         // sample point to reflect this.
         // sample point to reflect this.
+        if (deadrec_cat.is_spam()) {
+          deadrec_cat.spam()
+            << "  first point too old: age = " << age << "\n";
+        }
         SamplePoint new_point = point_b;
         SamplePoint new_point = point_b;
         new_point._timestamp = point_a._timestamp - _expected_broadcast_period;
         new_point._timestamp = point_a._timestamp - _expected_broadcast_period;
-        if (new_point._timestamp > timestamp) {
+        if (deadrec_cat.is_spam()) {
+          deadrec_cat.spam()
+            << "  constructed new timestamp at " << new_point._timestamp
+            << "\n";
+        }
+        if (new_point._timestamp > point_b._timestamp) {
           _points.insert(_points.begin() + point_after, new_point);
           _points.insert(_points.begin() + point_after, new_point);
           
           
           // Now we've monkeyed with the sequence.  Start over.
           // Now we've monkeyed with the sequence.  Start over.
@@ -655,28 +681,35 @@ linear_interpolate(int point_before, int point_after, double timestamp) {
 void SmoothMover::
 void SmoothMover::
 compute_velocity(const LVector3f &pos_delta, const LVecBase3f &hpr_delta,
 compute_velocity(const LVector3f &pos_delta, const LVecBase3f &hpr_delta,
                  double age) {
                  double age) {
-  // Also compute the velocity.  To get just the forward component
-  // of velocity, we need to project the velocity vector onto the y
-  // axis, as rotated by the current hpr.
-  if (!_computed_forward_axis) {
-    LMatrix3f rot_mat;
-    compose_matrix(rot_mat, LVecBase3f(1.0, 1.0, 1.0), _smooth_hpr);
-    _forward_axis = LVector3f(0.0, 1.0, 0.0) * rot_mat;
+  _smooth_rotational_velocity = hpr_delta[0] / age;
 
 
-    if (deadrec_cat.is_spam()) {
-      deadrec_cat.spam()
-        << "  compute forward_axis = " << _forward_axis << "\n";
+  if (_directional_velocity) {
+    // To get just the forward component of velocity, we need to project
+    // the velocity vector onto the y axis, as rotated by the current
+    // hpr.
+    if (!_computed_forward_axis) {
+      LMatrix3f rot_mat;
+      compose_matrix(rot_mat, LVecBase3f(1.0, 1.0, 1.0), _smooth_hpr);
+      _forward_axis = LVector3f(0.0, 1.0, 0.0) * rot_mat;
+      
+      if (deadrec_cat.is_spam()) {
+        deadrec_cat.spam()
+          << "  compute forward_axis = " << _forward_axis << "\n";
+      }
     }
     }
-  }
-   
-  LVector3f lateral_axis = _forward_axis.cross(LVector3f(0.0,0.0,1.0));
-
-  float forward_distance = pos_delta.dot(_forward_axis);
-  float lateral_distance = pos_delta.dot(lateral_axis);
+    
+    LVector3f lateral_axis = _forward_axis.cross(LVector3f(0.0,0.0,1.0));
+    
+    float forward_distance = pos_delta.dot(_forward_axis);
+    float lateral_distance = pos_delta.dot(lateral_axis);
+    
+    _smooth_forward_velocity = forward_distance / age;
+    _smooth_lateral_velocity = lateral_distance / age;
 
 
-  _smooth_forward_velocity = forward_distance / age;
-  _smooth_lateral_velocity = lateral_distance / age;
-  _smooth_rotational_velocity = hpr_delta[0] / age;
+  } else {
+    _smooth_forward_velocity = pos_delta.length();
+    _smooth_lateral_velocity = 0.0f;
+  }   
 
 
   if (deadrec_cat.is_spam()) {
   if (deadrec_cat.is_spam()) {
     deadrec_cat.spam()
     deadrec_cat.spam()

+ 4 - 0
direct/src/deadrec/smoothMover.h

@@ -146,6 +146,9 @@ PUBLISHED:
   INLINE void set_reset_velocity_age(double age); 
   INLINE void set_reset_velocity_age(double age); 
   INLINE double get_reset_velocity_age(); 
   INLINE double get_reset_velocity_age(); 
 
 
+  INLINE void set_directional_velocity(bool flag); 
+  INLINE bool get_directional_velocity(); 
+
   void output(ostream &out) const;
   void output(ostream &out) const;
   void write(ostream &out) const;
   void write(ostream &out) const;
 
 
@@ -213,6 +216,7 @@ private:
   double _max_position_age;
   double _max_position_age;
   double _expected_broadcast_period;
   double _expected_broadcast_period;
   double _reset_velocity_age;
   double _reset_velocity_age;
+  bool _directional_velocity;
 };
 };
 
 
 #include "smoothMover.I"
 #include "smoothMover.I"

+ 0 - 1
direct/src/distributed/DistributedSmoothNode.py

@@ -381,7 +381,6 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
         This assumes you have a client repository that knows its
         This assumes you have a client repository that knows its
         localAvatarDoId -- stored in self.cr.localAvatarDoId
         localAvatarDoId -- stored in self.cr.localAvatarDoId
         """
         """
-
         if smoothing and EnableSmoothing:
         if smoothing and EnableSmoothing:
             if prediction and EnablePrediction:
             if prediction and EnablePrediction:
                 # Prediction and smoothing.
                 # Prediction and smoothing.

+ 2 - 1
direct/src/distributed/DistributedSmoothNodeBase.py

@@ -7,7 +7,7 @@ from direct.showbase.PythonUtil import randFloat, Enum
 class DistributedSmoothNodeBase:
 class DistributedSmoothNodeBase:
     """common base class for DistributedSmoothNode and DistributedSmoothNodeAI
     """common base class for DistributedSmoothNode and DistributedSmoothNodeAI
     """
     """
-    BroadcastTypes = Enum('FULL, XYH')
+    BroadcastTypes = Enum('FULL, XYH, XY')
     
     
     def __init__(self):
     def __init__(self):
         self.cnode = CDistributedSmoothNodeBase()
         self.cnode = CDistributedSmoothNodeBase()
@@ -51,6 +51,7 @@ class DistributedSmoothNodeBase:
         broadcastFuncs = {
         broadcastFuncs = {
             BT.FULL: self.cnode.broadcastPosHprFull,
             BT.FULL: self.cnode.broadcastPosHprFull,
             BT.XYH:  self.cnode.broadcastPosHprXyh,
             BT.XYH:  self.cnode.broadcastPosHprXyh,
+            BT.XY:  self.cnode.broadcastPosHprXy,
             }
             }
         self.d_broadcastPosHpr = broadcastFuncs[self.broadcastType]
         self.d_broadcastPosHpr = broadcastFuncs[self.broadcastType]
         
         

+ 36 - 0
direct/src/distributed/cDistributedSmoothNodeBase.cxx

@@ -235,6 +235,42 @@ broadcast_pos_hpr_xyh() {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CDistributedSmoothNodeBase::broadcast_pos_hpr_xy
+//       Access: Published
+//  Description: Examines only X and Y of the pos/hpr information,
+//               and broadcasts the appropriate messages.
+////////////////////////////////////////////////////////////////////
+void CDistributedSmoothNodeBase::
+broadcast_pos_hpr_xy() {
+  LPoint3f xyz = _node_path.get_pos();
+
+  int flags = 0;
+
+  if (!IS_THRESHOLD_EQUAL(_store_xyz[0], xyz[0], smooth_node_epsilon)) {
+    _store_xyz[0] = xyz[0];
+    flags |= F_new_x;
+  }
+
+  if (!IS_THRESHOLD_EQUAL(_store_xyz[1], xyz[1], smooth_node_epsilon)) {
+    _store_xyz[1] = xyz[1];
+    flags |= F_new_y;
+  }
+
+  if (flags == 0) {
+    // No change.  Send one and only one "stop" message.
+    if (!_store_stop) {
+      _store_stop = true;
+      d_setSmStop();
+    }
+
+  } else {
+    // Any other change.
+    _store_stop = false;
+    d_setSmXY(_store_xyz[0], _store_xyz[1]);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CDistributedSmoothNodeBase::begin_send_update
 //     Function: CDistributedSmoothNodeBase::begin_send_update
 //       Access: Private
 //       Access: Private

+ 1 - 0
direct/src/distributed/cDistributedSmoothNodeBase.h

@@ -56,6 +56,7 @@ PUBLISHED:
 
 
   void broadcast_pos_hpr_full();
   void broadcast_pos_hpr_full();
   void broadcast_pos_hpr_xyh();
   void broadcast_pos_hpr_xyh();
+  void broadcast_pos_hpr_xy();
 
 
 private:
 private:
   INLINE static bool only_changed(int flags, int compare);
   INLINE static bool only_changed(int flags, int compare);