Panda3D
Loading...
Searching...
No Matches
smoothMover.I
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file smoothMover.I
10 * @author drose
11 * @date 2001-10-19
12 */
13
14/**
15 * Specifies the position of the SmoothMover at a particular time in the past.
16 * When mark_position() is called, this will be recorded (along with hpr and
17 * timestamp) in a position report, which will then be used along with all
18 * other position reports to determine the smooth position at any particular
19 * instant.
20 *
21 * The return value is true if any parameter has changed since the last call
22 * to set_pos(), or false if they are the same.
23 */
24INLINE bool SmoothMover::
25set_pos(const LVecBase3 &pos) {
26 return set_pos(pos[0], pos[1], pos[2]);
27}
28
29/**
30 * Specifies the position of the SmoothMover at a particular time in the past.
31 * When mark_position() is called, this will be recorded (along with hpr and
32 * timestamp) in a position report, which will then be used along with all
33 * other position reports to determine the smooth position at any particular
34 * instant.
35 *
36 * The return value is true if any parameter has changed since the last call
37 * to set_pos(), or false if they are the same.
38 */
39INLINE bool SmoothMover::
40set_pos(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
41 bool x_changed = set_x(x);
42 bool y_changed = set_y(y);
43 bool z_changed = set_z(z);
44 return x_changed || y_changed || z_changed;
45}
46
47/**
48 * Sets the X position only. See set_pos().
49 */
50INLINE bool SmoothMover::
51set_x(PN_stdfloat x) {
52 bool result = (x != _sample._pos[0]);
53 /*
54 if (deadrec_cat.is_debug()) {
55 deadrec_cat.debug() << "set_x " << x << "\n";
56 }
57 */
58 _sample._pos[0] = x;
59 return result;
60}
61
62/**
63 * Sets the Y position only. See set_pos().
64 */
65INLINE bool SmoothMover::
66set_y(PN_stdfloat y) {
67 bool result = (y != _sample._pos[1]);
68 /*
69 if (deadrec_cat.is_debug()) {
70 deadrec_cat.debug() << "set_y " << y << "\n";
71 }
72 */
73 _sample._pos[1] = y;
74 return result;
75}
76
77/**
78 * Sets the Z position only. See set_pos().
79 */
80INLINE bool SmoothMover::
81set_z(PN_stdfloat z) {
82 bool result = (z != _sample._pos[2]);
83 /*
84 if (deadrec_cat.is_debug()) {
85 deadrec_cat.debug() << "set_z " << z << "\n";
86 }
87 */
88 _sample._pos[2] = z;
89 return result;
90}
91
92/**
93 * Specifies the orientation of the SmoothMover at a particular time in the
94 * past. When mark_position() is called, this will be recorded (along with
95 * hpr and timestamp) in a position report, which will then be used along with
96 * all other position reports to determine the smooth position at any
97 * particular instant.
98 *
99 * The return value is true if any parameter has changed since the last call
100 * to set_hpr(), or false if they are the same.
101 */
102INLINE bool SmoothMover::
103set_hpr(const LVecBase3 &hpr) {
104 return set_hpr(hpr[0], hpr[1], hpr[2]);
105}
106
107/**
108 * Specifies the orientation of the SmoothMover at a particular time in the
109 * past. When mark_position() is called, this will be recorded (along with
110 * hpr and timestamp) in a position report, which will then be used along with
111 * all other position reports to determine the smooth position at any
112 * particular instant.
113 *
114 * The return value is true if any parameter has changed since the last call
115 * to set_hpr(), or false if they are the same.
116 */
117INLINE bool SmoothMover::
118set_hpr(PN_stdfloat h, PN_stdfloat p, PN_stdfloat r) {
119 bool h_changed = set_h(h);
120 bool p_changed = set_p(p);
121 bool r_changed = set_r(r);
122 return h_changed || p_changed || r_changed;
123}
124
125/**
126 * Sets the heading only. See set_hpr().
127 */
128INLINE bool SmoothMover::
129set_h(PN_stdfloat h) {
130 bool result = (h != _sample._hpr[0]);
131 /*
132 if (deadrec_cat.is_debug()) {
133 deadrec_cat.debug() << "set_h " << h << "\n";
134 }
135 */
136 _sample._hpr[0] = h;
137 return result;
138}
139
140/**
141 * Sets the pitch only. See set_hpr().
142 */
143INLINE bool SmoothMover::
144set_p(PN_stdfloat p) {
145 bool result = (p != _sample._hpr[1]);
146 /*
147 if (deadrec_cat.is_debug()) {
148 deadrec_cat.debug() << "set_p " << p << "\n";
149 }
150 */
151 _sample._hpr[1] = p;
152 return result;
153}
154
155/**
156 * Sets the roll only. See set_hpr().
157 */
158INLINE bool SmoothMover::
159set_r(PN_stdfloat r) {
160 bool result = (r != _sample._hpr[2]);
161 /*
162 if (deadrec_cat.is_debug()) {
163 deadrec_cat.debug() << "set_r " << r << "\n";
164 }
165 */
166 _sample._hpr[2] = r;
167 return result;
168}
169
170/**
171 * Specifies the position and orientation of the SmoothMover at a particular
172 * time in the past. When mark_position() is called, this will be recorded
173 * (along with timestamp) in a position report, which will then be used along
174 * with all other position reports to determine the smooth position at any
175 * particular instant.
176 *
177 * The return value is true if any parameter has changed since the last call
178 * to set_pos_hpr(), or false if they are the same.
179 */
180INLINE bool SmoothMover::
181set_pos_hpr(const LVecBase3 &pos, const LVecBase3 &hpr) {
182 bool pos_changed = set_pos(pos);
183 bool hpr_changed = set_hpr(hpr);
184 return pos_changed || hpr_changed;
185}
186
187/**
188 * Specifies the position of the SmoothMover at a particular time in the past.
189 * When mark_position() is called, this will be recorded (along with
190 * timestamp) in a position report, which will then be used along with all
191 * other position reports to determine the smooth position at any particular
192 * instant.
193 *
194 * The return value is true if any parameter has changed since the last call
195 * to set_pos_hpr(), or false if they are the same.
196 */
197INLINE bool SmoothMover::
198set_pos_hpr(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r) {
199 bool pos_changed = set_pos(x, y, z);
200 bool hpr_changed = set_hpr(h, p, r);
201 return pos_changed || hpr_changed;
202}
203
204/**
205 * Returns the current position of the working sample point. This position is
206 * updated periodically by set_x(), set_y(), etc., and its current value is
207 * copied to the sample point table when mark_position() is called.
208 */
209INLINE const LPoint3 &SmoothMover::
210get_sample_pos() const {
211 return _sample._pos;
212}
213
214/**
215 * Returns the current orientation of the working sample point. This
216 * orientation is updated periodically by set_h(), set_p(), etc., and its
217 * current value is copied to the sample point table when mark_position() is
218 * called.
219 */
220INLINE const LVecBase3 &SmoothMover::
221get_sample_hpr() const {
222 return _sample._hpr;
223}
224
225/**
226 * Lies and specifies that the current position report was received now. This
227 * is usually used for very old position reports for which we're not sure of
228 * the actual receipt time.
229 */
230INLINE void SmoothMover::
231set_phony_timestamp(double timestamp, bool period_adjust) {
233 if (timestamp != 0.0)
234 // we were given a specific timestamp to use
235 now = timestamp;
236
237 // adjust by _delay when creating the timestamp since other timestamps
238 // received from network updates are adjusted by this
239 if (period_adjust) {
240 _sample._timestamp = now - _expected_broadcast_period;
241 }
242 else
243 _sample._timestamp = now;
244
245 _has_most_recent_timestamp = true;
246 _most_recent_timestamp = _sample._timestamp;
247
248}
249
250/**
251 * Specifies the time that the current position report applies. This should
252 * be called, along with set_pos() and set_hpr(), before a call to
253 * mark_position().
254 */
255INLINE void SmoothMover::
256set_timestamp(double timestamp) {
257 /*
258 if (deadrec_cat.is_debug()) {
259 deadrec_cat.debug() << "set_timestamp " << timestamp << "\n";
260 }
261 */
262 _sample._timestamp = timestamp;
263 _has_most_recent_timestamp = true;
264 _most_recent_timestamp = timestamp;
265 record_timestamp_delay(timestamp);
266}
267
268/**
269 * Returns true if we have most recently recorded timestamp
270 */
271INLINE bool SmoothMover::
273 return _has_most_recent_timestamp;
274}
275
276/**
277 * Returns most recently recorded timestamp
278 */
279INLINE double SmoothMover::
281 return _most_recent_timestamp;
282}
283
284/**
285 * Computes the smoothed position (and orientation) of the mover at the
286 * indicated point in time, based on the previous position reports. After
287 * this call has been made, get_smooth_pos() etc. may be called to retrieve
288 * the smoothed position.
289 *
290 * With no parameter, the function uses ClockObject::get_frame_time() as the
291 * default time.
292 */
297
298/**
299 * Returns the smoothed position as computed by a previous call to
300 * compute_smooth_position().
301 */
302INLINE const LPoint3 &SmoothMover::
303get_smooth_pos() const {
304 return _smooth_pos;
305}
306
307/**
308 * Returns the smoothed position as computed by a previous call to
309 * compute_smooth_position().
310 */
311INLINE const LVecBase3 &SmoothMover::
312get_forward_axis() const {
313 return _forward_axis;
314}
315
316/**
317 * Returns the smoothed orientation as computed by a previous call to
318 * compute_smooth_position().
319 */
320INLINE const LVecBase3 &SmoothMover::
321get_smooth_hpr() const {
322 return _smooth_hpr;
323}
324
325/**
326 * Applies the smoothed position to the indicated NodePath. This is
327 * equivalent to calling node.set_pos(smooth_mover->get_smooth_pos()). It
328 * exists as an optimization only, to avoid the overhead of passing the return
329 * value through Python.
330 */
331INLINE void SmoothMover::
332apply_smooth_pos(NodePath &node) const {
333 node.set_pos(get_smooth_pos());
334}
335
336/**
337 * Applies the smoothed position and orientation to the indicated NodePath.
338 * This is equivalent to calling
339 * node.set_pos_hpr(smooth_mover->get_smooth_pos(),
340 * smooth_mover->get_smooth_hpr()). It exists as an optimization only, to
341 * avoid the overhead of passing the return value through Python.
342 */
343INLINE void SmoothMover::
344apply_smooth_pos_hpr(NodePath &pos_node, NodePath &hpr_node) const {
345 pos_node.set_pos(get_smooth_pos());
346 hpr_node.set_hpr(get_smooth_hpr());
347}
348
349/**
350 * Applies the smoothed orientation to the indicated NodePath. This is
351 * equivalent to calling node.set_hpr(smooth_mover->get_smooth_hpr()). It
352 * exists as an optimization only, to avoid the overhead of passing the return
353 * value through Python.
354 */
355INLINE void SmoothMover::
356apply_smooth_hpr(NodePath &node) const {
357 node.set_hpr(get_smooth_hpr());
358}
359
360/**
361 * A further optimization to reduce Python calls. This computes the smooth
362 * position and applies it to the indicated node in one call.
363 */
364INLINE void SmoothMover::
367 apply_smooth_pos(node);
368 }
369}
370
371/**
372 * A further optimization to reduce Python calls. This computes the smooth
373 * position and applies it to the indicated node or nodes in one call. The
374 * pos_node and hpr_node might be the same NodePath.
375 */
376INLINE void SmoothMover::
379 apply_smooth_pos(pos_node);
380 apply_smooth_hpr(hpr_node);
381 }
382}
383
384/**
385 * A further optimization to reduce Python calls. This computes the smooth
386 * position and applies it to the indicated node or nodes in one call. The
387 * pos_node and hpr_node might be the same NodePath.
388 */
389INLINE void SmoothMover::
392 apply_smooth_hpr(hpr_node);
393 }
394}
395
396/**
397 * Returns the speed at which the avatar is moving, in feet per second, along
398 * its own forward axis (after applying the avatar's hpr). This will be a
399 * positive number if the avatar is moving forward, and a negative number if
400 * it is moving backward.
401 */
402INLINE PN_stdfloat SmoothMover::
404 return _smooth_forward_velocity;
405}
406
407/**
408 * Returns the speed at which the avatar is moving, in feet per second, along
409 * its own lateral axis (after applying the avatar's hpr). This will be a
410 * positive number if the avatar is moving right, and a negative number if it
411 * is moving left.
412 */
413INLINE PN_stdfloat SmoothMover::
415 return _smooth_lateral_velocity;
416}
417
418/**
419 * Returns the speed at which the avatar is rotating in the horizontal plane
420 * (i.e. heading), in degrees per second. This may be positive or negative,
421 * according to the direction of rotation.
422 */
423INLINE PN_stdfloat SmoothMover::
425 return _smooth_rotational_velocity;
426}
427
428/**
429 * Sets the smoothing mode of all SmoothMovers in the world. If this is
430 * SM_off, no smoothing or prediction will be performed, and get_smooth_pos()
431 * will simply return the position last set by mark_position().
432 */
433INLINE void SmoothMover::
434set_smooth_mode(SmoothMover::SmoothMode mode) {
435 _smooth_mode = mode;
436}
437
438/**
439 * Returns the smoothing mode of all SmoothMovers in the world. See
440 * set_smooth_mode().
441 */
442INLINE SmoothMover::SmoothMode SmoothMover::
444 return _smooth_mode;
445}
446
447/**
448 * Sets the predictioning mode of all SmoothMovers in the world. If this is
449 * PM_off, no prediction will be performed, but smoothing might still be
450 * performed.
451 */
452INLINE void SmoothMover::
453set_prediction_mode(SmoothMover::PredictionMode mode) {
454 _prediction_mode = mode;
455}
456
457/**
458 * Returns the predictioning mode of all SmoothMovers in the world. See
459 * set_prediction_mode().
460 */
461INLINE SmoothMover::PredictionMode SmoothMover::
463 return _prediction_mode;
464}
465
466/**
467 * Sets the amount of time, in seconds, to delay the computed position of a
468 * SmoothMover. This is particularly useful when the prediction mode is off,
469 * because it can allow the apparent motion of an avatar to appear smooth
470 * without relying on prediction, at the cost of introducing additional lag in
471 * the avatar's apparent position.
472 */
473INLINE void SmoothMover::
474set_delay(double delay) {
475 _delay = delay;
476}
477
478/**
479 * Returns the amount of time, in seconds, to delay the computed position of a
480 * SmoothMover. See set_delay().
481 */
482INLINE double SmoothMover::
483get_delay() {
484 return _delay;
485}
486
487/**
488 * Sets the 'accept clock skew' flag. When this flag is true, clock skew from
489 * the other clients will be tolerated by delaying each smooth mover's
490 * position an additional amount, on top of that specified by set_delay(),
491 * based on the measured average latency for timestamp messages received by
492 * the client.
493 *
494 * In this way, if the other client has significant clock skew with respect to
495 * our clock, it will be evident as a large positive or negative average
496 * latency for timestamps. By subtracting out this average latency, we
497 * compensate for poor clock sync.
498 */
499INLINE void SmoothMover::
500set_accept_clock_skew(bool flag) {
501 _accept_clock_skew = flag;
502}
503
504/**
505 * Returns the current state of the 'accept clock skew' flag. See
506 * set_accept_clock_skew().
507 */
508INLINE bool SmoothMover::
510 return _accept_clock_skew;
511}
512
513/**
514 * Sets the maximum amount of time a position is allowed to remain unchanged
515 * before assuming it represents the avatar actually standing still.
516 */
517INLINE void SmoothMover::
518set_max_position_age(double age) {
519 _max_position_age = age;
520}
521
522/**
523 * Returns the maximum amount of time a position is allowed to remain
524 * unchanged before assuming it represents the avatar actually standing still.
525 */
526INLINE double SmoothMover::
528 return _max_position_age;
529}
530
531/**
532 * Sets the interval at which we expect the SmoothNodes to broadcast their
533 * position, in elapsed seconds. This controls the length of time we assume
534 * the object has truly stopped, when we receive a long sequence of no
535 * updates.
536 */
537INLINE void SmoothMover::
538set_expected_broadcast_period(double period) {
539 _expected_broadcast_period = period;
540}
541
542/**
543 * Returns the interval at which we expect the SmoothNodes to broadcast their
544 * position, in elapsed seconds. See set_expected_broadcast_period().
545 */
546INLINE double SmoothMover::
548 return _expected_broadcast_period;
549}
550
551/**
552 * Sets the amount of time that should elapse after the last position report
553 * before the velocity is reset to 0. This is similar to max_position_age,
554 * but it is only used to determine the resetting of the reported velocity.
555 * It should always be greater than or equal to max_position_age.
556 */
557INLINE void SmoothMover::
558set_reset_velocity_age(double age) {
559 _reset_velocity_age = age;
560}
561
562/**
563 * Returns the amount of time that should elapse after the last position
564 * report before the velocity is reset to 0. See set_reset_velocity_age().
565 */
566INLINE double SmoothMover::
568 return _reset_velocity_age;
569}
570
571/**
572 * Sets the flag that indicates whether the avatar's direction is considered
573 * in computing the velocity. When this is true, velocity is automatically
574 * decomposed into a forward and a lateral velocity (and both may be positive
575 * or negative); when it is false, all velocity is always returned as forward
576 * velocity (and it is always positive).
577 */
578INLINE void SmoothMover::
579set_directional_velocity(bool flag) {
580 _directional_velocity = flag;
581}
582
583/**
584 * Returns the current state of the 'directional velocity' flag. See
585 * set_directional_velocity().
586 */
587INLINE bool SmoothMover::
589 return _directional_velocity;
590}
591
592/**
593 * Sets the flag that indicates whether to assume that the node stopped moving
594 * during periods when we don't get enough position updates. If true, the
595 * object will stand still momentarily. If false, the object will
596 * continuously lerp between the position updates that we did get.
597 */
598INLINE void SmoothMover::
600 _default_to_standing_still = flag;
601}
602
603/**
604 * Returns the current state of the 'default to standing still' flag. See
605 * set_default_to_standing_still().
606 */
607INLINE bool SmoothMover::
609 return _default_to_standing_still;
610}
611
612/**
613 * Returns the average delay observed in the last n timestamps received from
614 * this client, in seconds. This number represents the combination of the
615 * network lag from this client, as well as the client's clock skew relative
616 * to our clock. It could be negative if the client's clock is running faster
617 * than our clock.
618 */
619INLINE double SmoothMover::
620get_avg_timestamp_delay() const {
621 nassertr(!_timestamp_delays.empty(), 0.0);
622 return (double)_net_timestamp_delay / (double)_timestamp_delays.size() / 1000.0;
623}
int size() const
Returns the number of items currently in the buffer.
Definition circBuffer.I:42
bool empty() const
Returns true if the buffer is empty.
Definition circBuffer.I:54
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
Definition clockObject.h:91
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
void set_hpr(PN_stdfloat h, PN_stdfloat p, PN_stdfloat r)
Sets the rotation component of the transform, leaving translation and scale untouched.
Definition nodePath.I:651
const LPoint3 & get_sample_pos() const
Returns the current position of the working sample point.
void set_expected_broadcast_period(double period)
Sets the interval at which we expect the SmoothNodes to broadcast their position, in elapsed seconds.
double get_delay()
Returns the amount of time, in seconds, to delay the computed position of a SmoothMover.
bool get_directional_velocity()
Returns the current state of the 'directional velocity' flag.
bool get_default_to_standing_still()
Returns the current state of the 'default to standing still' flag.
void set_prediction_mode(PredictionMode mode)
Sets the predictioning mode of all SmoothMovers in the world.
bool compute_smooth_position()
Computes the smoothed position (and orientation) of the mover at the indicated point in time,...
bool set_y(PN_stdfloat y)
Sets the Y position only.
Definition smoothMover.I:66
void apply_smooth_hpr(NodePath &node) const
Applies the smoothed orientation to the indicated NodePath.
const LVecBase3 & get_sample_hpr() const
Returns the current orientation of the working sample point.
void set_max_position_age(double age)
Sets the maximum amount of time a position is allowed to remain unchanged before assuming it represen...
void compute_and_apply_smooth_hpr(NodePath &hpr_node)
A further optimization to reduce Python calls.
bool set_pos(const LVecBase3 &pos)
Specifies the position of the SmoothMover at a particular time in the past.
Definition smoothMover.I:25
void set_timestamp(double timestamp)
Specifies the time that the current position report applies.
bool set_pos_hpr(const LVecBase3 &pos, const LVecBase3 &hpr)
Specifies the position and orientation of the SmoothMover at a particular time in the past.
SmoothMode get_smooth_mode()
Returns the smoothing mode of all SmoothMovers in the world.
bool set_hpr(const LVecBase3 &hpr)
Specifies the orientation of the SmoothMover at a particular time in the past.
bool has_most_recent_timestamp() const
Returns true if we have most recently recorded timestamp.
double get_most_recent_timestamp() const
Returns most recently recorded timestamp.
void set_delay(double delay)
Sets the amount of time, in seconds, to delay the computed position of a SmoothMover.
PN_stdfloat get_smooth_lateral_velocity() const
Returns the speed at which the avatar is moving, in feet per second, along its own lateral axis (afte...
void apply_smooth_pos(NodePath &node) const
Applies the smoothed position to the indicated NodePath.
double get_reset_velocity_age()
Returns the amount of time that should elapse after the last position report before the velocity is r...
bool set_h(PN_stdfloat h)
Sets the heading only.
PN_stdfloat get_smooth_rotational_velocity() const
Returns the speed at which the avatar is rotating in the horizontal plane (i.e.
double get_expected_broadcast_period()
Returns the interval at which we expect the SmoothNodes to broadcast their position,...
bool set_z(PN_stdfloat z)
Sets the Z position only.
Definition smoothMover.I:81
void set_phony_timestamp(double timestamp=0.0, bool period_adjust=false)
Lies and specifies that the current position report was received now.
void apply_smooth_pos_hpr(NodePath &pos_node, NodePath &hpr_node) const
Applies the smoothed position and orientation to the indicated NodePath.
void compute_and_apply_smooth_pos_hpr(NodePath &pos_node, NodePath &hpr_node)
A further optimization to reduce Python calls.
bool set_x(PN_stdfloat x)
Sets the X position only.
Definition smoothMover.I:51
PredictionMode get_prediction_mode()
Returns the predictioning mode of all SmoothMovers in the world.
const LVecBase3 & get_smooth_hpr() const
Returns the smoothed orientation as computed by a previous call to compute_smooth_position().
void set_directional_velocity(bool flag)
Sets the flag that indicates whether the avatar's direction is considered in computing the velocity.
void set_default_to_standing_still(bool flag)
Sets the flag that indicates whether to assume that the node stopped moving during periods when we do...
void set_smooth_mode(SmoothMode mode)
Sets the smoothing mode of all SmoothMovers in the world.
bool set_r(PN_stdfloat r)
Sets the roll only.
void compute_and_apply_smooth_pos(NodePath &node)
A further optimization to reduce Python calls.
bool set_p(PN_stdfloat p)
Sets the pitch only.
void set_accept_clock_skew(bool flag)
Sets the 'accept clock skew' flag.
const LVecBase3 & get_forward_axis() const
Returns the smoothed position as computed by a previous call to compute_smooth_position().
bool get_accept_clock_skew()
Returns the current state of the 'accept clock skew' flag.
double get_max_position_age()
Returns the maximum amount of time a position is allowed to remain unchanged before assuming it repre...
PN_stdfloat get_smooth_forward_velocity() const
Returns the speed at which the avatar is moving, in feet per second, along its own forward axis (afte...
void set_reset_velocity_age(double age)
Sets the amount of time that should elapse after the last position report before the velocity is rese...
const LPoint3 & get_smooth_pos() const
Returns the smoothed position as computed by a previous call to compute_smooth_position().