Panda3D
transformState.cxx
1 // Filename: transformState.cxx
2 // Created by: drose (25Feb02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "transformState.h"
16 #include "compose_matrix.h"
17 #include "bamReader.h"
18 #include "bamWriter.h"
19 #include "datagramIterator.h"
20 #include "indent.h"
21 #include "compareTo.h"
22 #include "pStatTimer.h"
23 #include "config_pgraph.h"
24 #include "lightReMutexHolder.h"
25 #include "lightMutexHolder.h"
26 #include "thread.h"
27 #include "py_panda.h"
28 
29 LightReMutex *TransformState::_states_lock = NULL;
30 TransformState::States *TransformState::_states = NULL;
31 CPT(TransformState) TransformState::_identity_state;
32 CPT(TransformState) TransformState::_invalid_state;
33 UpdateSeq TransformState::_last_cycle_detect;
34 int TransformState::_garbage_index = 0;
35 bool TransformState::_uniquify_matrix = true;
36 
37 PStatCollector TransformState::_cache_update_pcollector("*:State Cache:Update");
38 PStatCollector TransformState::_garbage_collect_pcollector("*:State Cache:Garbage Collect");
39 PStatCollector TransformState::_transform_compose_pcollector("*:State Cache:Compose Transform");
40 PStatCollector TransformState::_transform_invert_pcollector("*:State Cache:Invert Transform");
41 PStatCollector TransformState::_transform_calc_pcollector("*:State Cache:Calc Components");
42 PStatCollector TransformState::_transform_break_cycles_pcollector("*:State Cache:Break Cycles");
43 PStatCollector TransformState::_transform_new_pcollector("*:State Cache:New");
44 PStatCollector TransformState::_transform_validate_pcollector("*:State Cache:Validate");
45 PStatCollector TransformState::_transform_hash_pcollector("*:State Cache:Calc Hash");
46 PStatCollector TransformState::_node_counter("TransformStates:On nodes");
47 PStatCollector TransformState::_cache_counter("TransformStates:Cached");
48 
49 CacheStats TransformState::_cache_stats;
50 
51 TypeHandle TransformState::_type_handle;
52 
53 ////////////////////////////////////////////////////////////////////
54 // Function: TransformState::Constructor
55 // Access: Protected
56 // Description: Actually, this could be a private constructor, since
57 // no one inherits from TransformState, but gcc gives us a
58 // spurious warning if all constructors are private.
59 ////////////////////////////////////////////////////////////////////
60 TransformState::
61 TransformState() : _lock("TransformState") {
62  if (_states == (States *)NULL) {
63  init_states();
64  }
65  _saved_entry = -1;
66  _flags = F_is_identity | F_singular_known | F_is_2d;
67  _inv_mat = (LMatrix4 *)NULL;
68  _cache_stats.add_num_states(1);
69 }
70 
71 ////////////////////////////////////////////////////////////////////
72 // Function: TransformState::Copy Constructor
73 // Access: Private
74 // Description: TransformStates are not meant to be copied.
75 ////////////////////////////////////////////////////////////////////
76 TransformState::
77 TransformState(const TransformState &) {
78  nassertv(false);
79 }
80 
81 ////////////////////////////////////////////////////////////////////
82 // Function: TransformState::Copy Assignment Operator
83 // Access: Private
84 // Description: TransformStates are not meant to be copied.
85 ////////////////////////////////////////////////////////////////////
86 void TransformState::
87 operator = (const TransformState &) {
88  nassertv(false);
89 }
90 
91 ////////////////////////////////////////////////////////////////////
92 // Function: TransformState::Destructor
93 // Access: Public, Virtual
94 // Description: The destructor is responsible for removing the
95 // TransformState from the global set if it is there.
96 ////////////////////////////////////////////////////////////////////
97 TransformState::
98 ~TransformState() {
99  // We'd better not call the destructor twice on a particular object.
100  nassertv(!is_destructing());
101  set_destructing();
102 
103  // Free the inverse matrix computation, if it has been stored.
104  if (_inv_mat != (LMatrix4 *)NULL) {
105  delete _inv_mat;
106  _inv_mat = (LMatrix4 *)NULL;
107  }
108 
109  LightReMutexHolder holder(*_states_lock);
110 
111  // unref() should have cleared these.
112  nassertv(_saved_entry == -1);
113  nassertv(_composition_cache.is_empty() && _invert_composition_cache.is_empty());
114 
115  // If this was true at the beginning of the destructor, but is no
116  // longer true now, probably we've been double-deleted.
117  nassertv(get_ref_count() == 0);
118  _cache_stats.add_num_states(-1);
119 }
120 
121 ////////////////////////////////////////////////////////////////////
122 // Function: TransformState::compare_to
123 // Access: Published
124 // Description: Provides an arbitrary ordering among all unique
125 // TransformStates, so we can store the essentially
126 // different ones in a big set and throw away the rest.
127 //
128 // Note that if this returns 0, it doesn't necessarily
129 // imply that operator == returns true; it uses a very
130 // slightly different comparison threshold.
131 //
132 // If uniquify_matrix is true, then matrix-defined
133 // TransformStates are also uniqified. If
134 // uniquify_matrix is false, then only component-defined
135 // TransformStates are uniquified, which is less
136 // expensive.
137 ////////////////////////////////////////////////////////////////////
138 int TransformState::
139 compare_to(const TransformState &other, bool uniquify_matrix) const {
140  static const int significant_flags =
141  (F_is_invalid | F_is_identity | F_components_given | F_hpr_given | F_quat_given | F_is_2d);
142 
143  int flags = (_flags & significant_flags);
144  int other_flags = (other._flags & significant_flags);
145  if (flags != other_flags) {
146  return flags < other_flags ? -1 : 1;
147  }
148 
149  if ((_flags & (F_is_invalid | F_is_identity)) != 0) {
150  // All invalid transforms are equivalent to each other, and all
151  // identity transforms are equivalent to each other.
152  return 0;
153  }
154 
155  if ((_flags & F_components_given) != 0) {
156  // If the transform was specified componentwise, compare them
157  // componentwise.
158  int c = _pos.compare_to(other._pos);
159  if (c != 0) {
160  return c;
161  }
162 
163  if ((_flags & F_hpr_given) != 0) {
164  c = _hpr.compare_to(other._hpr);
165  if (c != 0) {
166  return c;
167  }
168  } else if ((_flags & F_quat_given) != 0) {
169  c = _quat.compare_to(other._quat);
170  if (c != 0) {
171  return c;
172  }
173  }
174 
175  c = _scale.compare_to(other._scale);
176  if (c != 0) {
177  return c;
178  }
179 
180  c = _shear.compare_to(other._shear);
181  return c;
182  }
183 
184  // Otherwise, compare the matrices . . .
185  if (uniquify_matrix) {
186  // . . . but only if the user thinks that's a worthwhile
187  // comparison.
188  return get_mat().compare_to(other.get_mat());
189 
190  } else {
191  // If not, we just compare the pointers.
192  if (this != &other) {
193  return (this < &other) ? -1 : 1;
194  }
195  return 0;
196  }
197 }
198 
199 ////////////////////////////////////////////////////////////////////
200 // Function: TransformState::operator ==
201 // Access: Published
202 // Description: Tests equivalence between two transform states.
203 // We use this instead of compare_to since this is
204 // faster, and we don't need an ordering between
205 // TransformStates because we use a hash map.
206 //
207 // If uniquify_matrix is true, then matrix-defined
208 // TransformStates are also uniqified. If
209 // uniquify_matrix is false, then only component-defined
210 // TransformStates are uniquified, which is less
211 // expensive.
212 ////////////////////////////////////////////////////////////////////
213 bool TransformState::
214 operator == (const TransformState &other) const {
215  static const int significant_flags =
216  (F_is_invalid | F_is_identity | F_components_given | F_hpr_given | F_quat_given | F_is_2d);
217 
218  int flags = (_flags & significant_flags);
219  int other_flags = (other._flags & significant_flags);
220  if (flags != other_flags) {
221  return false;
222  }
223 
224  if ((_flags & (F_is_invalid | F_is_identity)) != 0) {
225  // All invalid transforms are equivalent to each other, and all
226  // identity transforms are equivalent to each other.
227  return true;
228  }
229 
230  if ((_flags & F_components_given) != 0) {
231  // If the transform was specified componentwise, compare them
232  // componentwise.
233  if (_pos != other._pos) {
234  return false;
235  }
236 
237  if ((_flags & F_hpr_given) != 0) {
238  if (_hpr != other._hpr) {
239  return false;
240  }
241  } else if ((_flags & F_quat_given) != 0) {
242  if (_quat != other._quat) {
243  return false;
244  }
245  }
246 
247  if (_scale != other._scale) {
248  return false;
249  }
250 
251  return (_shear == other._shear);
252  }
253 
254  // Otherwise, compare the matrices . . .
255  if (_uniquify_matrix) {
256  // . . . but only if the user thinks that's a worthwhile
257  // comparison.
258  return get_mat().almost_equal(other.get_mat());
259 
260  } else {
261  // If not, we just compare the pointers.
262  return (this == &other);
263  }
264 }
265 
266 ////////////////////////////////////////////////////////////////////
267 // Function: TransformState::make_identity
268 // Access: Published, Static
269 // Description: Constructs an identity transform.
270 ////////////////////////////////////////////////////////////////////
271 CPT(TransformState) TransformState::
272 make_identity() {
273  // The identity state is asked for so often, we make it a special case
274  // and store a pointer forever once we find it the first time.
275  if (_identity_state == (TransformState *)NULL) {
276  TransformState *state = new TransformState;
277  _identity_state = return_unique(state);
278  }
279 
280  return _identity_state;
281 }
282 
283 ////////////////////////////////////////////////////////////////////
284 // Function: TransformState::make_invalid
285 // Access: Published, Static
286 // Description: Constructs an invalid transform; for instance, the
287 // result of inverting a singular matrix.
288 ////////////////////////////////////////////////////////////////////
289 CPT(TransformState) TransformState::
290 make_invalid() {
291  if (_invalid_state == (TransformState *)NULL) {
292  TransformState *state = new TransformState;
293  state->_flags = F_is_invalid | F_singular_known | F_is_singular | F_components_known | F_mat_known;
294  _invalid_state = return_unique(state);
295  }
296 
297  return _invalid_state;
298 }
299 
300 ////////////////////////////////////////////////////////////////////
301 // Function: TransformState::make_pos_hpr_scale_shear
302 // Access: Published, Static
303 // Description: Makes a new TransformState with the specified
304 // components.
305 ////////////////////////////////////////////////////////////////////
306 CPT(TransformState) TransformState::
307 make_pos_hpr_scale_shear(const LVecBase3 &pos, const LVecBase3 &hpr,
308  const LVecBase3 &scale, const LVecBase3 &shear) {
309  nassertr(!(pos.is_nan() || hpr.is_nan() || scale.is_nan() || shear.is_nan()) , make_invalid());
310  // Make a special-case check for the identity transform.
311  if (pos == LVecBase3(0.0f, 0.0f, 0.0f) &&
312  hpr == LVecBase3(0.0f, 0.0f, 0.0f) &&
313  scale == LVecBase3(1.0f, 1.0f, 1.0f) &&
314  shear == LVecBase3(0.0f, 0.0f, 0.0f)) {
315  return make_identity();
316  }
317 
318  TransformState *state = new TransformState;
319  state->_pos = pos;
320  state->_hpr = hpr;
321  state->_scale = scale;
322  state->_shear = shear;
323  state->_flags = F_components_given | F_hpr_given | F_components_known | F_hpr_known | F_has_components;
324  state->check_uniform_scale();
325  return return_new(state);
326 }
327 
328 ////////////////////////////////////////////////////////////////////
329 // Function: TransformState::make_pos_quat_scale_shear
330 // Access: Published, Static
331 // Description: Makes a new TransformState with the specified
332 // components.
333 ////////////////////////////////////////////////////////////////////
334 CPT(TransformState) TransformState::
335 make_pos_quat_scale_shear(const LVecBase3 &pos, const LQuaternion &quat,
336  const LVecBase3 &scale, const LVecBase3 &shear) {
337  nassertr(!(pos.is_nan() || quat.is_nan() || scale.is_nan() || shear.is_nan()) , make_invalid());
338  // Make a special-case check for the identity transform.
339  if (pos == LVecBase3(0.0f, 0.0f, 0.0f) &&
340  quat == LQuaternion::ident_quat() &&
341  scale == LVecBase3(1.0f, 1.0f, 1.0f) &&
342  shear == LVecBase3(0.0f, 0.0f, 0.0f)) {
343  return make_identity();
344  }
345 
346  TransformState *state = new TransformState;
347  state->_pos = pos;
348  state->_quat = quat;
349  state->_scale = scale;
350  state->_shear = shear;
351  state->_flags = F_components_given | F_quat_given | F_components_known | F_quat_known | F_has_components;
352  state->check_uniform_scale();
353  return return_new(state);
354 }
355 
356 ////////////////////////////////////////////////////////////////////
357 // Function: TransformState::make_mat
358 // Access: Published, Static
359 // Description: Makes a new TransformState with the specified
360 // transformation matrix.
361 ////////////////////////////////////////////////////////////////////
362 CPT(TransformState) TransformState::
363 make_mat(const LMatrix4 &mat) {
364  nassertr(!mat.is_nan(), make_invalid());
365  // Make a special-case check for the identity matrix.
366  if (mat.is_identity()) {
367  return make_identity();
368  }
369 
370  TransformState *state = new TransformState;
371  state->_mat = mat;
372  state->_flags = F_mat_known;
373  return return_new(state);
374 }
375 
376 ////////////////////////////////////////////////////////////////////
377 // Function: TransformState::make_pos_rotate_scale_shear2d
378 // Access: Published, Static
379 // Description: Makes a new two-dimensional TransformState with the
380 // specified components.
381 ////////////////////////////////////////////////////////////////////
382 CPT(TransformState) TransformState::
383 make_pos_rotate_scale_shear2d(const LVecBase2 &pos, PN_stdfloat rotate,
384  const LVecBase2 &scale,
385  PN_stdfloat shear) {
386  nassertr(!(pos.is_nan() || cnan(rotate) || scale.is_nan() || cnan(shear)) , make_invalid());
387  // Make a special-case check for the identity transform.
388  if (pos == LVecBase2(0.0f, 0.0f) &&
389  rotate == 0.0f &&
390  scale == LVecBase2(1.0f, 1.0f) &&
391  shear == 0.0f) {
392  return make_identity();
393  }
394 
395  TransformState *state = new TransformState;
396  state->_pos.set(pos[0], pos[1], 0.0f);
397  switch (get_default_coordinate_system()) {
398  default:
399  case CS_zup_right:
400  state->_hpr.set(rotate, 0.0f, 0.0f);
401  break;
402  case CS_zup_left:
403  state->_hpr.set(-rotate, 0.0f, 0.0f);
404  break;
405  case CS_yup_right:
406  state->_hpr.set(0.0f, 0.0f, -rotate);
407  break;
408  case CS_yup_left:
409  state->_hpr.set(0.0, 0.0f, rotate);
410  break;
411  }
412  state->_scale.set(scale[0], scale[1], 1.0f);
413  state->_shear.set(shear, 0.0f, 0.0f);
414  state->_flags = F_components_given | F_hpr_given | F_components_known | F_hpr_known | F_has_components | F_is_2d;
415  state->check_uniform_scale2d();
416  return return_new(state);
417 }
418 
419 
420 ////////////////////////////////////////////////////////////////////
421 // Function: TransformState::make_mat3
422 // Access: Published, Static
423 // Description: Makes a new two-dimensional TransformState with the
424 // specified 3x3 transformation matrix.
425 ////////////////////////////////////////////////////////////////////
426 CPT(TransformState) TransformState::
427 make_mat3(const LMatrix3 &mat) {
428  nassertr(!mat.is_nan(), make_invalid());
429  // Make a special-case check for the identity matrix.
430  if (mat.is_identity()) {
431  return make_identity();
432  }
433 
434  TransformState *state = new TransformState;
435  state->_mat.set(mat(0, 0), mat(0, 1), 0.0f, mat(0, 2),
436  mat(1, 0), mat(1, 1), 0.0f, mat(1, 2),
437  0.0f, 0.0f, 1.0f, 0.0f,
438  mat(2, 0), mat(2, 1), 0.0f, mat(2, 2));
439  state->_flags = F_mat_known | F_is_2d;
440  return return_new(state);
441 }
442 
443 ////////////////////////////////////////////////////////////////////
444 // Function: TransformState::set_pos
445 // Access: Published
446 // Description: Returns a new TransformState object that represents the
447 // original TransformState with its pos component
448 // replaced with the indicated value.
449 ////////////////////////////////////////////////////////////////////
450 CPT(TransformState) TransformState::
451 set_pos(const LVecBase3 &pos) const {
452  nassertr(!pos.is_nan(), this);
453  nassertr(!is_invalid(), this);
454  if (is_identity() || components_given()) {
455  // If we started with a componentwise transform, we keep it that
456  // way.
457  if (quat_given()) {
458  return make_pos_quat_scale_shear(pos, get_quat(), get_scale(), get_shear());
459  } else {
460  return make_pos_hpr_scale_shear(pos, get_hpr(), get_scale(), get_shear());
461  }
462 
463  } else {
464  // Otherwise, we have a matrix transform, and we keep it that way.
465  LMatrix4 mat = get_mat();
466  mat.set_row(3, pos);
467  return make_mat(mat);
468  }
469 }
470 
471 ////////////////////////////////////////////////////////////////////
472 // Function: TransformState::set_hpr
473 // Access: Published
474 // Description: Returns a new TransformState object that represents the
475 // original TransformState with its rotation component
476 // replaced with the indicated value, if possible.
477 ////////////////////////////////////////////////////////////////////
478 CPT(TransformState) TransformState::
479 set_hpr(const LVecBase3 &hpr) const {
480  nassertr(!hpr.is_nan(), this);
481  nassertr(!is_invalid(), this);
482  // nassertr(has_components(), this);
483  return make_pos_hpr_scale_shear(get_pos(), hpr, get_scale(), get_shear());
484 }
485 
486 ////////////////////////////////////////////////////////////////////
487 // Function: TransformState::set_quat
488 // Access: Published
489 // Description: Returns a new TransformState object that represents the
490 // original TransformState with its rotation component
491 // replaced with the indicated value, if possible.
492 ////////////////////////////////////////////////////////////////////
493 CPT(TransformState) TransformState::
494 set_quat(const LQuaternion &quat) const {
495  nassertr(!quat.is_nan(), this);
496  nassertr(!is_invalid(), this);
497  // nassertr(has_components(), this);
498  return make_pos_quat_scale_shear(get_pos(), quat, get_scale(), get_shear());
499 }
500 
501 ////////////////////////////////////////////////////////////////////
502 // Function: TransformState::set_scale
503 // Access: Published
504 // Description: Returns a new TransformState object that represents the
505 // original TransformState with its scale component
506 // replaced with the indicated value, if possible.
507 ////////////////////////////////////////////////////////////////////
508 CPT(TransformState) TransformState::
509 set_scale(const LVecBase3 &scale) const {
510  nassertr(!scale.is_nan(), this);
511  nassertr(!is_invalid(), this);
512 
513  if (is_2d() && scale[0] == scale[1] && scale[1] == scale[2]) {
514  // Don't inflate from 2-d to 3-d just because we got a uniform
515  // scale.
516  return make_pos_rotate_scale_shear2d(get_pos2d(), get_rotate2d(),
517  LVecBase2(scale[0], scale[0]),
518  get_shear2d());
519  }
520 
521  // nassertr(has_components(), this);
522  if (quat_given()) {
523  return make_pos_quat_scale_shear(get_pos(), get_quat(), scale, get_shear());
524  } else {
525  return make_pos_hpr_scale_shear(get_pos(), get_hpr(), scale, get_shear());
526  }
527 }
528 
529 ////////////////////////////////////////////////////////////////////
530 // Function: TransformState::set_shear
531 // Access: Published
532 // Description: Returns a new TransformState object that represents the
533 // original TransformState with its shear component
534 // replaced with the indicated value, if possible.
535 ////////////////////////////////////////////////////////////////////
536 CPT(TransformState) TransformState::
537 set_shear(const LVecBase3 &shear) const {
538  nassertr(!shear.is_nan(), this);
539  nassertr(!is_invalid(), this);
540  // nassertr(has_components(), this);
541  if (quat_given()) {
542  return make_pos_quat_scale_shear(get_pos(), get_quat(), get_scale(), shear);
543  } else {
544  return make_pos_hpr_scale_shear(get_pos(), get_hpr(), get_scale(), shear);
545  }
546 }
547 
548 ////////////////////////////////////////////////////////////////////
549 // Function: TransformState::set_pos2d
550 // Access: Published
551 // Description: Returns a new TransformState object that represents the
552 // original 2-d TransformState with its pos component
553 // replaced with the indicated value.
554 ////////////////////////////////////////////////////////////////////
555 CPT(TransformState) TransformState::
556 set_pos2d(const LVecBase2 &pos) const {
557  nassertr(!pos.is_nan(), this);
558  nassertr(!is_invalid(), this);
559  if (!is_2d()) {
560  return set_pos(LVecBase3(pos[0], pos[1], 0.0f));
561  }
562 
563  if (is_identity() || components_given()) {
564  // If we started with a componentwise transform, we keep it that
565  // way.
566  return make_pos_rotate_scale_shear2d(pos, get_rotate2d(), get_scale2d(),
567  get_shear2d());
568 
569  } else {
570  // Otherwise, we have a matrix transform, and we keep it that way.
571  LMatrix3 mat = get_mat3();
572  mat.set_row(2, pos);
573  return make_mat3(mat);
574  }
575 }
576 
577 ////////////////////////////////////////////////////////////////////
578 // Function: TransformState::set_rotate2d
579 // Access: Published
580 // Description: Returns a new TransformState object that represents the
581 // original 2-d TransformState with its rotation component
582 // replaced with the indicated value, if possible.
583 ////////////////////////////////////////////////////////////////////
584 CPT(TransformState) TransformState::
585 set_rotate2d(PN_stdfloat rotate) const {
586  nassertr(!cnan(rotate), this);
587  nassertr(!is_invalid(), this);
588 
589  if (!is_2d()) {
590  switch (get_default_coordinate_system()) {
591  default:
592  case CS_zup_right:
593  return set_hpr(LVecBase3(rotate, 0.0f, 0.0f));
594  case CS_zup_left:
595  return set_hpr(LVecBase3(-rotate, 0.0f, 0.0f));
596  case CS_yup_right:
597  return set_hpr(LVecBase3(0.0f, 0.0f, -rotate));
598  case CS_yup_left:
599  return set_hpr(LVecBase3(0.0f, 0.0f, rotate));
600  }
601  }
602 
603  return make_pos_rotate_scale_shear2d(get_pos2d(), rotate, get_scale2d(),
604  get_shear2d());
605 }
606 
607 ////////////////////////////////////////////////////////////////////
608 // Function: TransformState::set_scale2d
609 // Access: Published
610 // Description: Returns a new TransformState object that represents the
611 // original 2-d TransformState with its scale component
612 // replaced with the indicated value, if possible.
613 ////////////////////////////////////////////////////////////////////
614 CPT(TransformState) TransformState::
615 set_scale2d(const LVecBase2 &scale) const {
616  nassertr(!scale.is_nan(), this);
617  nassertr(!is_invalid(), this);
618 
619  if (!is_2d()) {
620  return set_scale(LVecBase3(scale[0], scale[1], 1.0f));
621  }
622  return make_pos_rotate_scale_shear2d(get_pos2d(), get_rotate2d(),
623  scale, get_shear2d());
624 }
625 
626 ////////////////////////////////////////////////////////////////////
627 // Function: TransformState::set_shear2d
628 // Access: Published
629 // Description: Returns a new TransformState object that represents the
630 // original 2-d TransformState with its shear component
631 // replaced with the indicated value, if possible.
632 ////////////////////////////////////////////////////////////////////
633 CPT(TransformState) TransformState::
634 set_shear2d(PN_stdfloat shear) const {
635  nassertr(!cnan(shear), this);
636  nassertr(!is_invalid(), this);
637  if (!is_2d()) {
638  return set_shear(LVecBase3(shear, 0.0f, 0.0f));
639  }
640  return make_pos_rotate_scale_shear2d(get_pos2d(), get_rotate2d(),
641  get_scale2d(), shear);
642 }
643 
644 ////////////////////////////////////////////////////////////////////
645 // Function: TransformState::compose
646 // Access: Published
647 // Description: Returns a new TransformState object that represents the
648 // composition of this state with the other state.
649 //
650 // The result of this operation is cached, and will be
651 // retained as long as both this TransformState object and
652 // the other TransformState object continue to exist.
653 // Should one of them destruct, the cached entry will be
654 // removed, and its pointer will be allowed to destruct
655 // as well.
656 ////////////////////////////////////////////////////////////////////
657 CPT(TransformState) TransformState::
658 compose(const TransformState *other) const {
659  // We handle identity as a trivial special case.
660  if (is_identity()) {
661  return other;
662  }
663  if (other->is_identity()) {
664  return this;
665  }
666 
667  // If either transform is invalid, the result is invalid.
668  if (is_invalid()) {
669  return this;
670  }
671  if (other->is_invalid()) {
672  return other;
673  }
674 
675  if (!transform_cache) {
676  return do_compose(other);
677  }
678 
679  // Is this composition already cached?
680  CPT(TransformState) result;
681  {
682  LightReMutexHolder holder(*_states_lock);
683  int index = _composition_cache.find(other);
684  if (index != -1) {
685  const Composition &comp = _composition_cache.get_data(index);
686  result = comp._result;
687  }
688  if (result != (TransformState *)NULL) {
689  _cache_stats.inc_hits();
690  }
691  }
692 
693  if (result != (TransformState *)NULL) {
694  // Success!
695  return result;
696  }
697 
698  // Not in the cache. Compute a new result. It's important that we
699  // don't hold the lock while we do this, or we lose the benefit of
700  // parallelization.
701  result = do_compose(other);
702 
703  // It's OK to cast away the constness of this pointer, because the
704  // cache is a transparent property of the class.
705  return ((TransformState *)this)->store_compose(other, result);
706 }
707 
708 ////////////////////////////////////////////////////////////////////
709 // Function: TransformState::invert_compose
710 // Access: Published
711 // Description: Returns a new TransformState object that represents the
712 // composition of this state's inverse with the other
713 // state.
714 //
715 // This is similar to compose(), but is particularly
716 // useful for computing the relative state of a node as
717 // viewed from some other node.
718 ////////////////////////////////////////////////////////////////////
719 CPT(TransformState) TransformState::
720 invert_compose(const TransformState *other) const {
721  // This method isn't strictly const, because it updates the cache,
722  // but we pretend that it is because it's only a cache which is
723  // transparent to the rest of the interface.
724 
725  // We handle identity as a trivial special case.
726  if (is_identity()) {
727  return other;
728  }
729  // Unlike compose(), the case of other->is_identity() is not quite as
730  // trivial for invert_compose().
731 
732  // If either transform is invalid, the result is invalid.
733  if (is_invalid()) {
734  return this;
735  }
736  if (other->is_invalid()) {
737  return other;
738  }
739 
740  if (other == this) {
741  // a->invert_compose(a) always produces identity.
742  return make_identity();
743  }
744 
745  if (!transform_cache) {
746  return do_invert_compose(other);
747  }
748 
749  LightReMutexHolder holder(*_states_lock);
750 
751  CPT(TransformState) result;
752  {
753  LightReMutexHolder holder(*_states_lock);
754  int index = _invert_composition_cache.find(other);
755  if (index != -1) {
756  const Composition &comp = _invert_composition_cache.get_data(index);
757  result = comp._result;
758  }
759  if (result != (TransformState *)NULL) {
760  _cache_stats.inc_hits();
761  }
762  }
763 
764  if (result != (TransformState *)NULL) {
765  // Success!
766  return result;
767  }
768 
769  // Not in the cache. Compute a new result. It's important that we
770  // don't hold the lock while we do this, or we lose the benefit of
771  // parallelization.
772  result = do_invert_compose(other);
773 
774  // It's OK to cast away the constness of this pointer, because the
775  // cache is a transparent property of the class.
776  return ((TransformState *)this)->store_invert_compose(other, result);
777 }
778 
779 ////////////////////////////////////////////////////////////////////
780 // Function: TransformState::unref
781 // Access: Published, Virtual
782 // Description: This method overrides ReferenceCount::unref() to
783 // check whether the remaining reference count is
784 // entirely in the cache, and if so, it checks for and
785 // breaks a cycle in the cache involving this object.
786 // This is designed to prevent leaks from cyclical
787 // references within the cache.
788 ////////////////////////////////////////////////////////////////////
789 bool TransformState::
790 unref() const {
791  if (!transform_cache || garbage_collect_states) {
792  // If we're not using the cache at all, or if we're relying on
793  // garbage collection, just allow the pointer to unref normally.
794  return ReferenceCount::unref();
795  }
796 
797  // Here is the normal refcounting case, with a normal cache, and
798  // without garbage collection in effect. In this case we will pull
799  // the object out of the cache when its reference count goes to 0.
800 
801  // We always have to grab the lock, since we will definitely need to
802  // be holding it if we happen to drop the reference count to 0.
803  // Having to grab the lock at every call to unref() is a big
804  // limiting factor on parallelization.
805  LightReMutexHolder holder(*_states_lock);
806 
807  if (auto_break_cycles && uniquify_transforms) {
808  if (get_cache_ref_count() > 0 &&
809  get_ref_count() == get_cache_ref_count() + 1) {
810  // If we are about to remove the one reference that is not in the
811  // cache, leaving only references in the cache, then we need to
812  // check for a cycle involving this TransformState and break it if
813  // it exists.
814  ((TransformState *)this)->detect_and_break_cycles();
815  }
816  }
817 
818  if (ReferenceCount::unref()) {
819  // The reference count is still nonzero.
820  return true;
821  }
822 
823  // The reference count has just reached zero. Make sure the object
824  // is removed from the global object pool, before anyone else finds
825  // it and tries to ref it.
826  ((TransformState *)this)->release_new();
827  ((TransformState *)this)->remove_cache_pointers();
828 
829  return false;
830 }
831 
832 ////////////////////////////////////////////////////////////////////
833 // Function: TransformState::validate_composition_cache
834 // Access: Published
835 // Description: Returns true if the composition cache and invert
836 // composition cache for this particular TransformState
837 // are self-consistent and valid, false otherwise.
838 ////////////////////////////////////////////////////////////////////
839 bool TransformState::
840 validate_composition_cache() const {
841  LightReMutexHolder holder(*_states_lock);
842 
843  int size = _composition_cache.get_size();
844  for (int i = 0; i < size; ++i) {
845  if (!_composition_cache.has_element(i)) {
846  continue;
847  }
848  const TransformState *source = _composition_cache.get_key(i);
849  if (source != (TransformState *)NULL) {
850  // Check that the source also has a pointer back to this one. We
851  // always add entries to the composition cache in pairs.
852  int ri = source->_composition_cache.find(this);
853  if (ri == -1) {
854  // Failure! There is no back-pointer.
855  pgraph_cat.error()
856  << "TransformState::composition cache is inconsistent!\n";
857  pgraph_cat.error(false)
858  << *this << " compose " << *source << "\n";
859  pgraph_cat.error(false)
860  << "but no reverse\n";
861  return false;
862  }
863  }
864  }
865 
866  size = _invert_composition_cache.get_size();
867  for (int i = 0; i < size; ++i) {
868  if (!_invert_composition_cache.has_element(i)) {
869  continue;
870  }
871  const TransformState *source = _invert_composition_cache.get_key(i);
872  if (source != (TransformState *)NULL) {
873  // Check that the source also has a pointer back to this one. We
874  // always add entries to the composition cache in pairs.
875  int ri = source->_invert_composition_cache.find(this);
876  if (ri == -1) {
877  // Failure! There is no back-pointer.
878  pgraph_cat.error()
879  << "TransformState::invert composition cache is inconsistent!\n";
880  pgraph_cat.error(false)
881  << *this << " invert compose " << *source << "\n";
882  pgraph_cat.error(false)
883  << "but no reverse\n";
884  return false;
885  }
886  }
887  }
888 
889  return true;
890 }
891 
892 ////////////////////////////////////////////////////////////////////
893 // Function: TransformState::output
894 // Access: Published
895 // Description:
896 ////////////////////////////////////////////////////////////////////
897 void TransformState::
898 output(ostream &out) const {
899  out << "T:";
900  if (is_invalid()) {
901  out << "(invalid)";
902 
903  } else if (is_identity()) {
904  out << "(identity)";
905 
906  } else if (has_components()) {
907  bool output_hpr = !get_hpr().almost_equal(LVecBase3(0.0f, 0.0f, 0.0f));
908 
909  if (!components_given()) {
910  // A leading "m" indicates the transform was described as a full
911  // matrix, and we are decomposing it for the benefit of the
912  // user.
913  out << "m";
914 
915  } else if (output_hpr && quat_given()) {
916  // A leading "q" indicates that the pos, scale, and shear are
917  // exactly as specified, but the rotation was described as a
918  // quaternion, and we are decomposing that to hpr for the
919  // benefit of the user.
920  out << "q";
921  }
922 
923  char lead = '(';
924  if (is_2d()) {
925  if (!get_pos2d().almost_equal(LVecBase2(0.0f, 0.0f))) {
926  out << lead << "pos " << get_pos2d();
927  lead = ' ';
928  }
929  if (output_hpr) {
930  out << lead << "rotate " << get_rotate2d();
931  lead = ' ';
932  }
933  if (!get_scale2d().almost_equal(LVecBase2(1.0f, 1.0f))) {
934  if (has_uniform_scale()) {
935  out << lead << "scale " << get_uniform_scale();
936  lead = ' ';
937  } else {
938  out << lead << "scale " << get_scale2d();
939  lead = ' ';
940  }
941  }
942  if (has_nonzero_shear()) {
943  out << lead << "shear " << get_shear2d();
944  lead = ' ';
945  }
946  } else {
947  if (!get_pos().almost_equal(LVecBase3(0.0f, 0.0f, 0.0f))) {
948  out << lead << "pos " << get_pos();
949  lead = ' ';
950  }
951  if (output_hpr) {
952  out << lead << "hpr " << get_hpr();
953  lead = ' ';
954  }
955  if (!get_scale().almost_equal(LVecBase3(1.0f, 1.0f, 1.0f))) {
956  if (has_uniform_scale()) {
957  out << lead << "scale " << get_uniform_scale();
958  lead = ' ';
959  } else {
960  out << lead << "scale " << get_scale();
961  lead = ' ';
962  }
963  }
964  if (has_nonzero_shear()) {
965  out << lead << "shear " << get_shear();
966  lead = ' ';
967  }
968  }
969  if (lead == '(') {
970  out << "(almost identity)";
971  } else {
972  out << ")";
973  }
974 
975  } else {
976  if (is_2d()) {
977  out << get_mat3();
978  } else {
979  out << get_mat();
980  }
981  }
982 }
983 
984 ////////////////////////////////////////////////////////////////////
985 // Function: TransformState::write
986 // Access: Published
987 // Description:
988 ////////////////////////////////////////////////////////////////////
989 void TransformState::
990 write(ostream &out, int indent_level) const {
991  indent(out, indent_level) << *this << "\n";
992 }
993 
994 ////////////////////////////////////////////////////////////////////
995 // Function: TransformState::write_composition_cache
996 // Access: Published
997 // Description: Writes a brief description of the composition cache
998 // and invert composition cache to the indicated
999 // ostream. This is not useful except for performance
1000 // analysis, to examine the cache structure.
1001 ////////////////////////////////////////////////////////////////////
1002 void TransformState::
1003 write_composition_cache(ostream &out, int indent_level) const {
1004  indent(out, indent_level + 2) << _composition_cache << "\n";
1005  indent(out, indent_level + 2) << _invert_composition_cache << "\n";
1006 }
1007 
1008 ////////////////////////////////////////////////////////////////////
1009 // Function: TransformState::get_num_states
1010 // Access: Published, Static
1011 // Description: Returns the total number of unique TransformState
1012 // objects allocated in the world. This will go up and
1013 // down during normal operations.
1014 ////////////////////////////////////////////////////////////////////
1015 int TransformState::
1016 get_num_states() {
1017  if (_states == (States *)NULL) {
1018  return 0;
1019  }
1020  LightReMutexHolder holder(*_states_lock);
1021  return _states->get_num_entries();
1022 }
1023 
1024 ////////////////////////////////////////////////////////////////////
1025 // Function: TransformState::get_num_unused_states
1026 // Access: Published, Static
1027 // Description: Returns the total number of TransformState objects that
1028 // have been allocated but have no references outside of
1029 // the internal TransformState cache.
1030 //
1031 // A nonzero return value is not necessarily indicative
1032 // of leaked references; it is normal for two
1033 // TransformState objects, both of which have references
1034 // held outside the cache, to have the result of their
1035 // composition stored within the cache. This result
1036 // will be retained within the cache until one of the
1037 // base TransformStates is released.
1038 //
1039 // Use list_cycles() to get an idea of the number of
1040 // actual "leaked" TransformState objects.
1041 ////////////////////////////////////////////////////////////////////
1042 int TransformState::
1043 get_num_unused_states() {
1044  if (_states == (States *)NULL) {
1045  return 0;
1046  }
1047  LightReMutexHolder holder(*_states_lock);
1048 
1049  // First, we need to count the number of times each TransformState
1050  // object is recorded in the cache. We could just trust
1051  // get_cache_ref_count(), but we'll be extra cautious for now.
1052  typedef pmap<const TransformState *, int> StateCount;
1053  StateCount state_count;
1054 
1055  int size = _states->get_size();
1056  for (int si = 0; si < size; ++si) {
1057  if (!_states->has_element(si)) {
1058  continue;
1059  }
1060  const TransformState *state = _states->get_key(si);
1061 
1062  int i;
1063  int cache_size = state->_composition_cache.get_size();
1064  for (i = 0; i < cache_size; ++i) {
1065  if (state->_composition_cache.has_element(i)) {
1066  const TransformState *result = state->_composition_cache.get_data(i)._result;
1067  if (result != (const TransformState *)NULL && result != state) {
1068  // Here's a TransformState that's recorded in the cache.
1069  // Count it.
1070  pair<StateCount::iterator, bool> ir =
1071  state_count.insert(StateCount::value_type(result, 1));
1072  if (!ir.second) {
1073  // If the above insert operation fails, then it's already in
1074  // the cache; increment its value.
1075  (*(ir.first)).second++;
1076  }
1077  }
1078  }
1079  }
1080  cache_size = state->_invert_composition_cache.get_size();
1081  for (i = 0; i < cache_size; ++i) {
1082  if (state->_invert_composition_cache.has_element(i)) {
1083  const TransformState *result = state->_invert_composition_cache.get_data(i)._result;
1084  if (result != (const TransformState *)NULL && result != state) {
1085  pair<StateCount::iterator, bool> ir =
1086  state_count.insert(StateCount::value_type(result, 1));
1087  if (!ir.second) {
1088  (*(ir.first)).second++;
1089  }
1090  }
1091  }
1092  }
1093  }
1094 
1095  // Now that we have the appearance count of each TransformState
1096  // object, we can tell which ones are unreferenced outside of the
1097  // TransformState cache, by comparing these to the reference counts.
1098  int num_unused = 0;
1099 
1100  StateCount::iterator sci;
1101  for (sci = state_count.begin(); sci != state_count.end(); ++sci) {
1102  const TransformState *state = (*sci).first;
1103  int count = (*sci).second;
1104  nassertr(count == state->get_cache_ref_count(), num_unused);
1105  nassertr(count <= state->get_ref_count(), num_unused);
1106  if (count == state->get_ref_count()) {
1107  num_unused++;
1108 
1109  if (pgraph_cat.is_debug()) {
1110  pgraph_cat.debug()
1111  << "Unused state: " << (void *)state << ":"
1112  << state->get_ref_count() << " =\n";
1113  state->write(pgraph_cat.debug(false), 2);
1114  }
1115  }
1116  }
1117 
1118  return num_unused;
1119 }
1120 
1121 ////////////////////////////////////////////////////////////////////
1122 // Function: TransformState::clear_cache
1123 // Access: Published, Static
1124 // Description: Empties the cache of composed TransformStates. This
1125 // makes every TransformState forget what results when
1126 // it is composed with other TransformStates.
1127 //
1128 // This will eliminate any TransformState objects that
1129 // have been allocated but have no references outside of
1130 // the internal TransformState map. It will not
1131 // eliminate TransformState objects that are still in
1132 // use.
1133 //
1134 // Nowadays, this method should not be necessary, as
1135 // reference-count cycles in the composition cache
1136 // should be automatically detected and broken.
1137 //
1138 // The return value is the number of TransformStates
1139 // freed by this operation.
1140 ////////////////////////////////////////////////////////////////////
1141 int TransformState::
1142 clear_cache() {
1143  if (_states == (States *)NULL) {
1144  return 0;
1145  }
1146  LightReMutexHolder holder(*_states_lock);
1147 
1148  PStatTimer timer(_cache_update_pcollector);
1149  int orig_size = _states->get_num_entries();
1150 
1151  // First, we need to copy the entire set of states to a temporary
1152  // vector, reference-counting each object. That way we can walk
1153  // through the copy, without fear of dereferencing (and deleting)
1154  // the objects in the map as we go.
1155  {
1156  typedef pvector< CPT(TransformState) > TempStates;
1157  TempStates temp_states;
1158  temp_states.reserve(orig_size);
1159 
1160  int size = _states->get_size();
1161  for (int si = 0; si < size; ++si) {
1162  if (!_states->has_element(si)) {
1163  continue;
1164  }
1165  const TransformState *state = _states->get_key(si);
1166  temp_states.push_back(state);
1167  }
1168 
1169  // Now it's safe to walk through the list, destroying the cache
1170  // within each object as we go. Nothing will be destructed till
1171  // we're done.
1172  TempStates::iterator ti;
1173  for (ti = temp_states.begin(); ti != temp_states.end(); ++ti) {
1174  TransformState *state = (TransformState *)(*ti).p();
1175 
1176  int i;
1177  int cache_size = state->_composition_cache.get_size();
1178  for (i = 0; i < cache_size; ++i) {
1179  if (state->_composition_cache.has_element(i)) {
1180  const TransformState *result = state->_composition_cache.get_data(i)._result;
1181  if (result != (const TransformState *)NULL && result != state) {
1182  result->cache_unref();
1183  nassertr(result->get_ref_count() > 0, 0);
1184  }
1185  }
1186  }
1187  _cache_stats.add_total_size(-state->_composition_cache.get_num_entries());
1188  state->_composition_cache.clear();
1189 
1190  cache_size = state->_invert_composition_cache.get_size();
1191  for (i = 0; i < cache_size; ++i) {
1192  if (state->_invert_composition_cache.has_element(i)) {
1193  const TransformState *result = state->_invert_composition_cache.get_data(i)._result;
1194  if (result != (const TransformState *)NULL && result != state) {
1195  result->cache_unref();
1196  nassertr(result->get_ref_count() > 0, 0);
1197  }
1198  }
1199  }
1200  _cache_stats.add_total_size(-state->_invert_composition_cache.get_num_entries());
1201  state->_invert_composition_cache.clear();
1202  }
1203 
1204  // Once this block closes and the temp_states object goes away,
1205  // all the destruction will begin. Anything whose reference was
1206  // held only within the various objects' caches will go away.
1207  }
1208 
1209  int new_size = _states->get_num_entries();
1210  return orig_size - new_size;
1211 }
1212 
1213 ////////////////////////////////////////////////////////////////////
1214 // Function: TransformState::garbage_collect
1215 // Access: Published, Static
1216 // Description: Performs a garbage-collection cycle. This must be
1217 // called periodically if garbage-collect-states is true
1218 // to ensure that TransformStates get cleaned up
1219 // appropriately. It does no harm to call it even if
1220 // this variable is not true, but there is probably no
1221 // advantage in that case.
1222 ////////////////////////////////////////////////////////////////////
1223 int TransformState::
1224 garbage_collect() {
1225  if (_states == (States *)NULL || !garbage_collect_states) {
1226  return 0;
1227  }
1228  LightReMutexHolder holder(*_states_lock);
1229 
1230  PStatTimer timer(_garbage_collect_pcollector);
1231  int orig_size = _states->get_num_entries();
1232 
1233  // How many elements to process this pass?
1234  int size = _states->get_size();
1235  int num_this_pass = int(size * garbage_collect_states_rate);
1236  if (num_this_pass <= 0) {
1237  return 0;
1238  }
1239  num_this_pass = min(num_this_pass, size);
1240  int stop_at_element = (_garbage_index + num_this_pass) % size;
1241 
1242  int num_elements = 0;
1243  int si = _garbage_index;
1244  do {
1245  if (_states->has_element(si)) {
1246  ++num_elements;
1247  TransformState *state = (TransformState *)_states->get_key(si);
1248  if (auto_break_cycles && uniquify_transforms) {
1249  if (state->get_cache_ref_count() > 0 &&
1250  state->get_ref_count() == state->get_cache_ref_count()) {
1251  // If we have removed all the references to this state not in
1252  // the cache, leaving only references in the cache, then we
1253  // need to check for a cycle involving this TransformState and
1254  // break it if it exists.
1255  state->detect_and_break_cycles();
1256  }
1257  }
1258 
1259  if (state->get_ref_count() == 1) {
1260  // This state has recently been unreffed to 1 (the one we
1261  // added when we stored it in the cache). Now it's time to
1262  // delete it. This is safe, because we're holding the
1263  // _states_lock, so it's not possible for some other thread to
1264  // find the state in the cache and ref it while we're doing
1265  // this.
1266  state->release_new();
1267  state->remove_cache_pointers();
1268  state->cache_unref();
1269  delete state;
1270  }
1271  }
1272 
1273  si = (si + 1) % size;
1274  } while (si != stop_at_element);
1275  _garbage_index = si;
1276  nassertr(_states->validate(), 0);
1277 
1278  int new_size = _states->get_num_entries();
1279  return orig_size - new_size;
1280 }
1281 
1282 ////////////////////////////////////////////////////////////////////
1283 // Function: TransformState::list_cycles
1284 // Access: Published, Static
1285 // Description: Detects all of the reference-count cycles in the
1286 // cache and reports them to standard output.
1287 //
1288 // These cycles may be inadvertently created when state
1289 // compositions cycle back to a starting point.
1290 // Nowadays, these cycles should be automatically
1291 // detected and broken, so this method should never list
1292 // any cycles unless there is a bug in that detection
1293 // logic.
1294 //
1295 // The cycles listed here are not leaks in the strictest
1296 // sense of the word, since they can be reclaimed by a
1297 // call to clear_cache(); but they will not be reclaimed
1298 // automatically.
1299 ////////////////////////////////////////////////////////////////////
1300 void TransformState::
1301 list_cycles(ostream &out) {
1302  if (_states == (States *)NULL) {
1303  return;
1304  }
1305  LightReMutexHolder holder(*_states_lock);
1306 
1307  typedef pset<const TransformState *> VisitedStates;
1308  VisitedStates visited;
1309  CompositionCycleDesc cycle_desc;
1310 
1311  int size = _states->get_size();
1312  for (int si = 0; si < size; ++si) {
1313  if (!_states->has_element(si)) {
1314  continue;
1315  }
1316  const TransformState *state = _states->get_key(si);
1317 
1318  bool inserted = visited.insert(state).second;
1319  if (inserted) {
1320  ++_last_cycle_detect;
1321  if (r_detect_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) {
1322  // This state begins a cycle.
1323  CompositionCycleDesc::reverse_iterator csi;
1324 
1325  out << "\nCycle detected of length " << cycle_desc.size() + 1 << ":\n"
1326  << "state " << (void *)state << ":" << state->get_ref_count()
1327  << " =\n";
1328  state->write(out, 2);
1329  for (csi = cycle_desc.rbegin(); csi != cycle_desc.rend(); ++csi) {
1330  const CompositionCycleDescEntry &entry = (*csi);
1331  if (entry._inverted) {
1332  out << "invert composed with ";
1333  } else {
1334  out << "composed with ";
1335  }
1336  out << (const void *)entry._obj << ":" << entry._obj->get_ref_count()
1337  << " " << *entry._obj << "\n"
1338  << "produces " << (const void *)entry._result << ":"
1339  << entry._result->get_ref_count() << " =\n";
1340  entry._result->write(out, 2);
1341  visited.insert(entry._result);
1342  }
1343 
1344  cycle_desc.clear();
1345  } else {
1346  ++_last_cycle_detect;
1347  if (r_detect_reverse_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) {
1348  // This state begins a cycle.
1349  CompositionCycleDesc::iterator csi;
1350 
1351  out << "\nReverse cycle detected of length " << cycle_desc.size() + 1 << ":\n"
1352  << "state ";
1353  for (csi = cycle_desc.begin(); csi != cycle_desc.end(); ++csi) {
1354  const CompositionCycleDescEntry &entry = (*csi);
1355  out << (const void *)entry._result << ":"
1356  << entry._result->get_ref_count() << " =\n";
1357  entry._result->write(out, 2);
1358  out << (const void *)entry._obj << ":"
1359  << entry._obj->get_ref_count() << " =\n";
1360  entry._obj->write(out, 2);
1361  visited.insert(entry._result);
1362  }
1363  out << (void *)state << ":"
1364  << state->get_ref_count() << " =\n";
1365  state->write(out, 2);
1366 
1367  cycle_desc.clear();
1368  }
1369  }
1370  }
1371  }
1372 }
1373 
1374 
1375 ////////////////////////////////////////////////////////////////////
1376 // Function: TransformState::list_states
1377 // Access: Published, Static
1378 // Description: Lists all of the TransformStates in the cache to the
1379 // output stream, one per line. This can be quite a lot
1380 // of output if the cache is large, so be prepared.
1381 ////////////////////////////////////////////////////////////////////
1382 void TransformState::
1383 list_states(ostream &out) {
1384  if (_states == (States *)NULL) {
1385  out << "0 states:\n";
1386  return;
1387  }
1388  LightReMutexHolder holder(*_states_lock);
1389 
1390  out << _states->get_num_entries() << " states:\n";
1391 
1392  int size = _states->get_size();
1393  for (int si = 0; si < size; ++si) {
1394  if (!_states->has_element(si)) {
1395  continue;
1396  }
1397  const TransformState *state = _states->get_key(si);
1398  state->write(out, 2);
1399  }
1400 }
1401 
1402 ////////////////////////////////////////////////////////////////////
1403 // Function: TransformState::validate_states
1404 // Access: Published, Static
1405 // Description: Ensures that the cache is still stored in sorted
1406 // order, and that none of the cache elements have been
1407 // inadvertently deleted. Returns true if so, false if
1408 // there is a problem (which implies someone has
1409 // modified one of the supposedly-const TransformState
1410 // objects).
1411 ////////////////////////////////////////////////////////////////////
1412 bool TransformState::
1413 validate_states() {
1414  if (_states == (States *)NULL) {
1415  return true;
1416  }
1417 
1418  PStatTimer timer(_transform_validate_pcollector);
1419 
1420  LightReMutexHolder holder(*_states_lock);
1421  if (_states->is_empty()) {
1422  return true;
1423  }
1424 
1425  if (!_states->validate()) {
1426  pgraph_cat.error()
1427  << "TransformState::_states cache is invalid!\n";
1428  return false;
1429  }
1430 
1431  int size = _states->get_size();
1432  int si = 0;
1433  while (si < size && !_states->has_element(si)) {
1434  ++si;
1435  }
1436  nassertr(si < size, false);
1437  nassertr(_states->get_key(si)->get_ref_count() >= 0, false);
1438  int snext = si;
1439  ++snext;
1440  while (snext < size && !_states->has_element(snext)) {
1441  ++snext;
1442  }
1443  while (snext < size) {
1444  nassertr(_states->get_key(snext)->get_ref_count() >= 0, false);
1445  const TransformState *ssi = _states->get_key(si);
1446  if (!ssi->validate_composition_cache()) {
1447  return false;
1448  }
1449  const TransformState *ssnext = _states->get_key(snext);
1450  bool c = (*ssi) == (*ssnext);
1451  bool ci = (*ssnext) == (*ssi);
1452  if (c != ci) {
1453  pgraph_cat.error()
1454  << "TransformState::operator == () not defined properly!\n";
1455  pgraph_cat.error(false)
1456  << "(a, b): " << c << "\n";
1457  pgraph_cat.error(false)
1458  << "(b, a): " << ci << "\n";
1459  ssi->write(pgraph_cat.error(false), 2);
1460  ssnext->write(pgraph_cat.error(false), 2);
1461  return false;
1462  }
1463  si = snext;
1464  ++snext;
1465  while (snext < size && !_states->has_element(snext)) {
1466  ++snext;
1467  }
1468  }
1469 
1470  return true;
1471 }
1472 
1473 ////////////////////////////////////////////////////////////////////
1474 // Function: TransformState::init_states
1475 // Access: Public, Static
1476 // Description: Make sure the global _states map is allocated. This
1477 // only has to be done once. We could make this map
1478 // static, but then we run into problems if anyone
1479 // creates a TransformState object at static init time;
1480 // it also seems to cause problems when the Panda shared
1481 // library is unloaded at application exit time.
1482 ////////////////////////////////////////////////////////////////////
1483 void TransformState::
1484 init_states() {
1485  _states = new States;
1486 
1487  ConfigVariableBool uniquify_matrix
1488  ("uniquify-matrix", true,
1489  PRC_DESC("Set this true to look up arbitrary 4x4 transform matrices in "
1490  "the cache, to ensure that two differently-computed transforms "
1491  "that happen to encode the same matrix will be collapsed into "
1492  "a single pointer. Nowadays, with the transforms stored in a "
1493  "hashtable, we're generally better off with this set true."));
1494 
1495  // Store this at the beginning, so that we don't have to query this
1496  // every time that the comparison operator is invoked.
1497  _uniquify_matrix = uniquify_matrix;
1498 
1499  // TODO: we should have a global Panda mutex to allow us to safely
1500  // create _states_lock without a startup race condition. For the
1501  // meantime, this is OK because we guarantee that this method is
1502  // called at static init time, presumably when there is still only
1503  // one thread in the world.
1504  _states_lock = new LightReMutex("TransformState::_states_lock");
1505  _cache_stats.init();
1507 }
1508 
1509 ////////////////////////////////////////////////////////////////////
1510 // Function: TransformState::return_new
1511 // Access: Private, Static
1512 // Description: This function is used to share a common TransformState
1513 // pointer for all equivalent TransformState objects.
1514 //
1515 // This is different from return_unique() in that it
1516 // does not actually guarantee a unique pointer, unless
1517 // uniquify-transforms is set.
1518 ////////////////////////////////////////////////////////////////////
1519 CPT(TransformState) TransformState::
1520 return_new(TransformState *state) {
1521  nassertr(state != (TransformState *)NULL, state);
1522  if (!uniquify_transforms && !state->is_identity()) {
1523  return state;
1524  }
1525 
1526  return return_unique(state);
1527 }
1528 
1529 ////////////////////////////////////////////////////////////////////
1530 // Function: TransformState::return_unique
1531 // Access: Private, Static
1532 // Description: This function is used to share a common TransformState
1533 // pointer for all equivalent TransformState objects.
1534 //
1535 // See the similar logic in RenderState. The idea is to
1536 // create a new TransformState object and pass it
1537 // through this function, which will share the pointer
1538 // with a previously-created TransformState object if it
1539 // is equivalent.
1540 ////////////////////////////////////////////////////////////////////
1541 CPT(TransformState) TransformState::
1542 return_unique(TransformState *state) {
1543  nassertr(state != (TransformState *)NULL, state);
1544 
1545  if (!transform_cache) {
1546  return state;
1547  }
1548 
1549 #ifndef NDEBUG
1550  if (paranoid_const) {
1551  nassertr(validate_states(), state);
1552  }
1553 #endif
1554 
1555  PStatTimer timer(_transform_new_pcollector);
1556 
1557  LightReMutexHolder holder(*_states_lock);
1558 
1559  if (state->_saved_entry != -1) {
1560  // This state is already in the cache.
1561  //nassertr(_states->find(state) == state->_saved_entry, state);
1562  return state;
1563  }
1564 
1565  // Save the state in a local PointerTo so that it will be freed at
1566  // the end of this function if no one else uses it.
1567  CPT(TransformState) pt_state = state;
1568 
1569  int si = _states->find(state);
1570  if (si != -1) {
1571  // There's an equivalent state already in the set. Return it.
1572  return _states->get_key(si);
1573  }
1574 
1575  // Not already in the set; add it.
1576  if (garbage_collect_states) {
1577  // If we'll be garbage collecting states explicitly, we'll
1578  // increment the reference count when we store it in the cache, so
1579  // that it won't be deleted while it's in it.
1580  state->cache_ref();
1581  }
1582  si = _states->store(state, Empty());
1583 
1584  // Save the index and return the input state.
1585  state->_saved_entry = si;
1586  return pt_state;
1587 }
1588 
1589 ////////////////////////////////////////////////////////////////////
1590 // Function: TransformState::do_compose
1591 // Access: Private
1592 // Description: The private implemention of compose(); this actually
1593 // composes two TransformStates, without bothering with the
1594 // cache.
1595 ////////////////////////////////////////////////////////////////////
1596 CPT(TransformState) TransformState::
1597 do_compose(const TransformState *other) const {
1598  PStatTimer timer(_transform_compose_pcollector);
1599 
1600  nassertr((_flags & F_is_invalid) == 0, this);
1601  nassertr((other->_flags & F_is_invalid) == 0, other);
1602 
1603  if (compose_componentwise &&
1604  has_uniform_scale() &&
1605  !has_nonzero_shear() && !other->has_nonzero_shear() &&
1606  ((components_given() && other->has_components()) ||
1607  (other->components_given() && has_components()))) {
1608  // We will do this operation componentwise if *either* transform
1609  // was given componentwise (and there is no non-uniform scale in
1610  // the way).
1611 
1612  CPT(TransformState) result;
1613  if (is_2d() && other->is_2d()) {
1614  // Do a 2-d compose.
1615  LVecBase2 pos = get_pos2d();
1616  PN_stdfloat rotate = get_rotate2d();
1617  LQuaternion quat = get_norm_quat();
1618  PN_stdfloat scale = get_uniform_scale();
1619 
1620  LPoint3 op = quat.xform(other->get_pos());
1621  pos += LVecBase2(op[0], op[1]) * scale;
1622 
1623  rotate += other->get_rotate2d();
1624  LVecBase2 new_scale = other->get_scale2d() * scale;
1625 
1626  result = make_pos_rotate_scale2d(pos, rotate, new_scale);
1627 
1628  } else {
1629  // A normal 3-d compose.
1630  LVecBase3 pos = get_pos();
1631  LQuaternion quat = get_norm_quat();
1632  PN_stdfloat scale = get_uniform_scale();
1633 
1634  pos += quat.xform(other->get_pos()) * scale;
1635  quat = other->get_norm_quat() * quat;
1636  LVecBase3 new_scale = other->get_scale() * scale;
1637 
1638  result = make_pos_quat_scale(pos, quat, new_scale);
1639  }
1640 
1641 #ifndef NDEBUG
1642  if (paranoid_compose) {
1643  // Now verify against the matrix.
1644  LMatrix4 new_mat;
1645  new_mat.multiply(other->get_mat(), get_mat());
1646  if (!new_mat.almost_equal(result->get_mat(), 0.1)) {
1647  CPT(TransformState) correct = make_mat(new_mat);
1648  pgraph_cat.warning()
1649  << "Componentwise composition of " << *this << " and " << *other
1650  << " produced:\n"
1651  << *result << "\n instead of:\n" << *correct << "\n";
1652  result = correct;
1653  }
1654  }
1655 #endif // NDEBUG
1656 
1657  return result;
1658  }
1659 
1660  // Do the operation with matrices.
1661  if (is_2d() && other->is_2d()) {
1662  LMatrix3 new_mat = other->get_mat3() * get_mat3();
1663  return make_mat3(new_mat);
1664  } else {
1665  LMatrix4 new_mat;
1666  new_mat.multiply(other->get_mat(), get_mat());
1667  return make_mat(new_mat);
1668  }
1669 }
1670 
1671 ////////////////////////////////////////////////////////////////////
1672 // Function: TransformState::store_compose
1673 // Access: Private
1674 // Description: Stores the result of a composition in the cache.
1675 // Returns the stored result (it may be a different
1676 // object than the one passed in, due to another thread
1677 // having computed the composition first).
1678 ////////////////////////////////////////////////////////////////////
1679 CPT(TransformState) TransformState::
1680 store_compose(const TransformState *other, const TransformState *result) {
1681  // Identity should have already been screened.
1682  nassertr(!is_identity(), other);
1683  nassertr(!other->is_identity(), this);
1684 
1685  // So should have validity.
1686  nassertr(!is_invalid(), this);
1687  nassertr(!other->is_invalid(), other);
1688 
1689  LightReMutexHolder holder(*_states_lock);
1690 
1691  // Is this composition already cached?
1692  int index = _composition_cache.find(other);
1693  if (index != -1) {
1694  Composition &comp = _composition_cache.modify_data(index);
1695  if (comp._result == (const TransformState *)NULL) {
1696  // Well, it wasn't cached already, but we already had an entry
1697  // (probably created for the reverse direction), so use the same
1698  // entry to store the new result.
1699  comp._result = result;
1700 
1701  if (result != (const TransformState *)this) {
1702  // See the comments below about the need to up the reference
1703  // count only when the result is not the same as this.
1704  result->cache_ref();
1705  }
1706  }
1707  // Here's the cache!
1708  _cache_stats.inc_hits();
1709  return comp._result;
1710  }
1711  _cache_stats.inc_misses();
1712 
1713  // We need to make a new cache entry, both in this object and in the
1714  // other object. We make both records so the other TransformState
1715  // object will know to delete the entry from this object when it
1716  // destructs, and vice-versa.
1717 
1718  // The cache entry in this object is the only one that indicates the
1719  // result; the other will be NULL for now.
1720  _cache_stats.add_total_size(1);
1721  _cache_stats.inc_adds(_composition_cache.get_size() == 0);
1722 
1723  _composition_cache[other]._result = result;
1724 
1725  if (other != this) {
1726  _cache_stats.add_total_size(1);
1727  _cache_stats.inc_adds(other->_composition_cache.get_size() == 0);
1728  ((TransformState *)other)->_composition_cache[this]._result = NULL;
1729  }
1730 
1731  if (result != (TransformState *)this) {
1732  // If the result of do_compose() is something other than this,
1733  // explicitly increment the reference count. We have to be sure
1734  // to decrement it again later, when the composition entry is
1735  // removed from the cache.
1736  result->cache_ref();
1737 
1738  // (If the result was just this again, we still store the
1739  // result, but we don't increment the reference count, since
1740  // that would be a self-referential leak.)
1741  }
1742 
1743  _cache_stats.maybe_report("TransformState");
1744 
1745  return result;
1746 }
1747 
1748 ////////////////////////////////////////////////////////////////////
1749 // Function: TransformState::store_invert_compose
1750 // Access: Private
1751 // Description: Stores the result of a composition in the cache.
1752 // Returns the stored result (it may be a different
1753 // object than the one passed in, due to another thread
1754 // having computed the composition first).
1755 ////////////////////////////////////////////////////////////////////
1756 CPT(TransformState) TransformState::
1757 store_invert_compose(const TransformState *other, const TransformState *result) {
1758  // Identity should have already been screened.
1759  nassertr(!is_identity(), other);
1760 
1761  // So should have validity.
1762  nassertr(!is_invalid(), this);
1763  nassertr(!other->is_invalid(), other);
1764 
1765  nassertr(other != this, make_identity());
1766 
1767  LightReMutexHolder holder(*_states_lock);
1768 
1769  // Is this composition already cached?
1770  int index = _invert_composition_cache.find(other);
1771  if (index != -1) {
1772  Composition &comp = ((TransformState *)this)->_invert_composition_cache.modify_data(index);
1773  if (comp._result == (const TransformState *)NULL) {
1774  // Well, it wasn't cached already, but we already had an entry
1775  // (probably created for the reverse direction), so use the same
1776  // entry to store the new result.
1777  comp._result = result;
1778 
1779  if (result != (const TransformState *)this) {
1780  // See the comments below about the need to up the reference
1781  // count only when the result is not the same as this.
1782  result->cache_ref();
1783  }
1784  }
1785  // Here's the cache!
1786  _cache_stats.inc_hits();
1787  return comp._result;
1788  }
1789  _cache_stats.inc_misses();
1790 
1791  // We need to make a new cache entry, both in this object and in the
1792  // other object. We make both records so the other TransformState
1793  // object will know to delete the entry from this object when it
1794  // destructs, and vice-versa.
1795 
1796  // The cache entry in this object is the only one that indicates the
1797  // result; the other will be NULL for now.
1798  _cache_stats.add_total_size(1);
1799  _cache_stats.inc_adds(_invert_composition_cache.get_size() == 0);
1800  _invert_composition_cache[other]._result = result;
1801 
1802  if (other != this) {
1803  _cache_stats.add_total_size(1);
1804  _cache_stats.inc_adds(other->_invert_composition_cache.get_size() == 0);
1805  ((TransformState *)other)->_invert_composition_cache[this]._result = NULL;
1806  }
1807 
1808  if (result != (TransformState *)this) {
1809  // If the result of compose() is something other than this,
1810  // explicitly increment the reference count. We have to be sure
1811  // to decrement it again later, when the composition entry is
1812  // removed from the cache.
1813  result->cache_ref();
1814 
1815  // (If the result was just this again, we still store the
1816  // result, but we don't increment the reference count, since
1817  // that would be a self-referential leak.)
1818  }
1819 
1820  return result;
1821 }
1822 
1823 ////////////////////////////////////////////////////////////////////
1824 // Function: TransformState::do_invert_compose
1825 // Access: Private
1826 // Description: The private implemention of invert_compose().
1827 ////////////////////////////////////////////////////////////////////
1828 CPT(TransformState) TransformState::
1829 do_invert_compose(const TransformState *other) const {
1830  PStatTimer timer(_transform_invert_pcollector);
1831 
1832  nassertr((_flags & F_is_invalid) == 0, this);
1833  nassertr((other->_flags & F_is_invalid) == 0, other);
1834 
1835  if (compose_componentwise &&
1836  has_uniform_scale() &&
1837  !has_nonzero_shear() && !other->has_nonzero_shear() &&
1838  ((components_given() && other->has_components()) ||
1839  (other->components_given() && has_components()))) {
1840  // We will do this operation componentwise if *either* transform
1841  // was given componentwise (and there is no non-uniform scale in
1842  // the way).
1843 
1844  CPT(TransformState) result;
1845  if (is_2d() && other->is_2d()) {
1846  // Do a 2-d invert compose.
1847  LVecBase2 pos = get_pos2d();
1848  PN_stdfloat rotate = get_rotate2d();
1849  LQuaternion quat = get_norm_quat();
1850  PN_stdfloat scale = get_uniform_scale();
1851 
1852  // First, invert our own transform.
1853  if (scale == 0.0f) {
1854  ((TransformState *)this)->_flags |= F_is_singular | F_singular_known;
1855  return make_invalid();
1856  }
1857  scale = 1.0f / scale;
1858  quat.invert_in_place();
1859  rotate = -rotate;
1860  LVecBase3 mp = quat.xform(-LVecBase3(pos[0], pos[1], 0.0f));
1861  pos = LVecBase2(mp[0], mp[1]) * scale;
1862  LVecBase2 new_scale(scale, scale);
1863 
1864  // Now compose the inverted transform with the other transform.
1865  if (!other->is_identity()) {
1866  LPoint3 op = quat.xform(other->get_pos());
1867  pos += LVecBase2(op[0], op[1]) * scale;
1868 
1869  rotate += other->get_rotate2d();
1870  new_scale = other->get_scale2d() * scale;
1871  }
1872 
1873  result = make_pos_rotate_scale2d(pos, rotate, new_scale);
1874 
1875  } else {
1876  // Do a normal, 3-d invert compose.
1877  LVecBase3 pos = get_pos();
1878  LQuaternion quat = get_norm_quat();
1879  PN_stdfloat scale = get_uniform_scale();
1880 
1881  // First, invert our own transform.
1882  if (scale == 0.0f) {
1883  ((TransformState *)this)->_flags |= F_is_singular | F_singular_known;
1884  return make_invalid();
1885  }
1886  scale = 1.0f / scale;
1887  quat.invert_in_place();
1888  pos = quat.xform(-pos) * scale;
1889  LVecBase3 new_scale(scale, scale, scale);
1890 
1891  // Now compose the inverted transform with the other transform.
1892  if (!other->is_identity()) {
1893  pos += quat.xform(other->get_pos()) * scale;
1894  quat = other->get_norm_quat() * quat;
1895  new_scale = other->get_scale() * scale;
1896  }
1897 
1898  result = make_pos_quat_scale(pos, quat, new_scale);
1899  }
1900 
1901 #ifndef NDEBUG
1902  if (paranoid_compose) {
1903  // Now verify against the matrix.
1904  if (is_singular()) {
1905  pgraph_cat.warning()
1906  << "Unexpected singular matrix found for " << *this << "\n";
1907  } else {
1908  nassertr(_inv_mat != (LMatrix4 *)NULL, make_invalid());
1909  LMatrix4 new_mat;
1910  new_mat.multiply(other->get_mat(), *_inv_mat);
1911  if (!new_mat.almost_equal(result->get_mat(), 0.1)) {
1912  CPT(TransformState) correct = make_mat(new_mat);
1913  pgraph_cat.warning()
1914  << "Componentwise invert-composition of " << *this << " and " << *other
1915  << " produced:\n"
1916  << *result << "\n instead of:\n" << *correct << "\n";
1917  result = correct;
1918  }
1919  }
1920  }
1921 #endif // NDEBUG
1922 
1923  return result;
1924  }
1925 
1926  if (is_singular()) {
1927  return make_invalid();
1928  }
1929 
1930  // Now that is_singular() has returned false, we can assume that
1931  // _inv_mat has been allocated and filled in.
1932  nassertr(_inv_mat != (LMatrix4 *)NULL, make_invalid());
1933 
1934  if (is_2d() && other->is_2d()) {
1935  const LMatrix4 &i = *_inv_mat;
1936  LMatrix3 inv3(i(0, 0), i(0, 1), i(0, 3),
1937  i(1, 0), i(1, 1), i(1, 3),
1938  i(3, 0), i(3, 1), i(3, 3));
1939  if (other->is_identity()) {
1940  return make_mat3(inv3);
1941  } else {
1942  return make_mat3(other->get_mat3() * inv3);
1943  }
1944  } else {
1945  if (other->is_identity()) {
1946  return make_mat(*_inv_mat);
1947  } else {
1948  return make_mat(other->get_mat() * (*_inv_mat));
1949  }
1950  }
1951 }
1952 
1953 ////////////////////////////////////////////////////////////////////
1954 // Function: TransformState::detect_and_break_cycles
1955 // Access: Private
1956 // Description: Detects whether there is a cycle in the cache that
1957 // begins with this state. If any are detected, breaks
1958 // them by removing this state from the cache.
1959 ////////////////////////////////////////////////////////////////////
1960 void TransformState::
1961 detect_and_break_cycles() {
1962  PStatTimer timer(_transform_break_cycles_pcollector);
1963 
1964  ++_last_cycle_detect;
1965  if (r_detect_cycles(this, this, 1, _last_cycle_detect, NULL)) {
1966  // Ok, we have a cycle. This will be a leak unless we break the
1967  // cycle by freeing the cache on this object.
1968  if (pgraph_cat.is_debug()) {
1969  pgraph_cat.debug()
1970  << "Breaking cycle involving " << (*this) << "\n";
1971  }
1972 
1973  remove_cache_pointers();
1974  } else {
1975  ++_last_cycle_detect;
1976  if (r_detect_reverse_cycles(this, this, 1, _last_cycle_detect, NULL)) {
1977  if (pgraph_cat.is_debug()) {
1978  pgraph_cat.debug()
1979  << "Breaking cycle involving " << (*this) << "\n";
1980  }
1981 
1982  remove_cache_pointers();
1983  }
1984  }
1985 }
1986 
1987 ////////////////////////////////////////////////////////////////////
1988 // Function: TransformState::r_detect_cycles
1989 // Access: Private, Static
1990 // Description: Detects whether there is a cycle in the cache that
1991 // begins with the indicated state. Returns true if at
1992 // least one cycle is found, false if this state is not
1993 // part of any cycles. If a cycle is found and
1994 // cycle_desc is not NULL, then cycle_desc is filled in
1995 // with the list of the steps of the cycle, in reverse
1996 // order.
1997 ////////////////////////////////////////////////////////////////////
1998 bool TransformState::
1999 r_detect_cycles(const TransformState *start_state,
2000  const TransformState *current_state,
2001  int length, UpdateSeq this_seq,
2002  TransformState::CompositionCycleDesc *cycle_desc) {
2003  if (current_state->_cycle_detect == this_seq) {
2004  // We've already seen this state; therefore, we've found a cycle.
2005 
2006  // However, we only care about cycles that return to the starting
2007  // state and involve more than two steps. If only one or two
2008  // nodes are involved, it doesn't represent a memory leak, so no
2009  // problem there.
2010  return (current_state == start_state && length > 2);
2011  }
2012  ((TransformState *)current_state)->_cycle_detect = this_seq;
2013 
2014  int i;
2015  int cache_size = current_state->_composition_cache.get_size();
2016  for (i = 0; i < cache_size; ++i) {
2017  if (current_state->_composition_cache.has_element(i)) {
2018  const TransformState *result = current_state->_composition_cache.get_data(i)._result;
2019  if (result != (const TransformState *)NULL) {
2020  if (r_detect_cycles(start_state, result, length + 1,
2021  this_seq, cycle_desc)) {
2022  // Cycle detected.
2023  if (cycle_desc != (CompositionCycleDesc *)NULL) {
2024  const TransformState *other = current_state->_composition_cache.get_key(i);
2025  CompositionCycleDescEntry entry(other, result, false);
2026  cycle_desc->push_back(entry);
2027  }
2028  return true;
2029  }
2030  }
2031  }
2032  }
2033 
2034  cache_size = current_state->_invert_composition_cache.get_size();
2035  for (i = 0; i < cache_size; ++i) {
2036  if (current_state->_invert_composition_cache.has_element(i)) {
2037  const TransformState *result = current_state->_invert_composition_cache.get_data(i)._result;
2038  if (result != (const TransformState *)NULL) {
2039  if (r_detect_cycles(start_state, result, length + 1,
2040  this_seq, cycle_desc)) {
2041  // Cycle detected.
2042  if (cycle_desc != (CompositionCycleDesc *)NULL) {
2043  const TransformState *other = current_state->_invert_composition_cache.get_key(i);
2044  CompositionCycleDescEntry entry(other, result, true);
2045  cycle_desc->push_back(entry);
2046  }
2047  return true;
2048  }
2049  }
2050  }
2051  }
2052 
2053  // No cycle detected.
2054  return false;
2055 }
2056 
2057 ////////////////////////////////////////////////////////////////////
2058 // Function: TransformState::r_detect_reverse_cycles
2059 // Access: Private, Static
2060 // Description: Works the same as r_detect_cycles, but checks for
2061 // cycles in the reverse direction along the cache
2062 // chain. (A cycle may appear in either direction, and
2063 // we must check both.)
2064 ////////////////////////////////////////////////////////////////////
2065 bool TransformState::
2066 r_detect_reverse_cycles(const TransformState *start_state,
2067  const TransformState *current_state,
2068  int length, UpdateSeq this_seq,
2069  TransformState::CompositionCycleDesc *cycle_desc) {
2070  if (current_state->_cycle_detect == this_seq) {
2071  // We've already seen this state; therefore, we've found a cycle.
2072 
2073  // However, we only care about cycles that return to the starting
2074  // state and involve more than two steps. If only one or two
2075  // nodes are involved, it doesn't represent a memory leak, so no
2076  // problem there.
2077  return (current_state == start_state && length > 2);
2078  }
2079  ((TransformState *)current_state)->_cycle_detect = this_seq;
2080 
2081  int i;
2082  int cache_size = current_state->_composition_cache.get_size();
2083  for (i = 0; i < cache_size; ++i) {
2084  if (current_state->_composition_cache.has_element(i)) {
2085  const TransformState *other = current_state->_composition_cache.get_key(i);
2086  if (other != current_state) {
2087  int oi = other->_composition_cache.find(current_state);
2088  nassertr(oi != -1, false);
2089 
2090  const TransformState *result = other->_composition_cache.get_data(oi)._result;
2091  if (result != (const TransformState *)NULL) {
2092  if (r_detect_reverse_cycles(start_state, result, length + 1,
2093  this_seq, cycle_desc)) {
2094  // Cycle detected.
2095  if (cycle_desc != (CompositionCycleDesc *)NULL) {
2096  const TransformState *other = current_state->_composition_cache.get_key(i);
2097  CompositionCycleDescEntry entry(other, result, false);
2098  cycle_desc->push_back(entry);
2099  }
2100  return true;
2101  }
2102  }
2103  }
2104  }
2105  }
2106 
2107  cache_size = current_state->_invert_composition_cache.get_size();
2108  for (i = 0; i < cache_size; ++i) {
2109  if (current_state->_invert_composition_cache.has_element(i)) {
2110  const TransformState *other = current_state->_invert_composition_cache.get_key(i);
2111  if (other != current_state) {
2112  int oi = other->_invert_composition_cache.find(current_state);
2113  nassertr(oi != -1, false);
2114 
2115  const TransformState *result = other->_invert_composition_cache.get_data(oi)._result;
2116  if (result != (const TransformState *)NULL) {
2117  if (r_detect_reverse_cycles(start_state, result, length + 1,
2118  this_seq, cycle_desc)) {
2119  // Cycle detected.
2120  if (cycle_desc != (CompositionCycleDesc *)NULL) {
2121  const TransformState *other = current_state->_invert_composition_cache.get_key(i);
2122  CompositionCycleDescEntry entry(other, result, false);
2123  cycle_desc->push_back(entry);
2124  }
2125  return true;
2126  }
2127  }
2128  }
2129  }
2130  }
2131 
2132  // No cycle detected.
2133  return false;
2134 }
2135 
2136 
2137 ////////////////////////////////////////////////////////////////////
2138 // Function: TransformState::release_new
2139 // Access: Private
2140 // Description: This inverse of return_new, this releases this object
2141 // from the global TransformState table.
2142 //
2143 // You must already be holding _states_lock before you
2144 // call this method.
2145 ////////////////////////////////////////////////////////////////////
2146 void TransformState::
2147 release_new() {
2148  nassertv(_states_lock->debug_is_locked());
2149 
2150  if (_saved_entry != -1) {
2151  //nassertv(_states->find(this) == _saved_entry);
2152  _saved_entry = _states->find(this);
2153  _states->remove_element(_saved_entry);
2154  _saved_entry = -1;
2155  }
2156 }
2157 
2158 ////////////////////////////////////////////////////////////////////
2159 // Function: TransformState::remove_cache_pointers
2160 // Access: Private
2161 // Description: Remove all pointers within the cache from and to this
2162 // particular TransformState. The pointers to this
2163 // object may be scattered around in the various
2164 // CompositionCaches from other TransformState objects.
2165 //
2166 // You must already be holding _states_lock before you
2167 // call this method.
2168 ////////////////////////////////////////////////////////////////////
2169 void TransformState::
2170 remove_cache_pointers() {
2171  nassertv(_states_lock->debug_is_locked());
2172 
2173  // Fortunately, since we added CompositionCache records in pairs, we
2174  // know exactly the set of TransformState objects that have us in their
2175  // cache: it's the same set of TransformState objects that we have in
2176  // our own cache.
2177 
2178  // We do need to put considerable thought into this loop, because as
2179  // we clear out cache entries we'll cause other TransformState
2180  // objects to destruct, which could cause things to get pulled out
2181  // of our own _composition_cache map. We want to allow this (so
2182  // that we don't encounter any just-destructed pointers in our
2183  // cache), but we don't want to get bitten by this cascading effect.
2184  // Instead of walking through the map from beginning to end,
2185  // therefore, we just pull out the first one each time, and erase
2186  // it.
2187 
2188 #ifdef DO_PSTATS
2189  if (_composition_cache.is_empty() && _invert_composition_cache.is_empty()) {
2190  return;
2191  }
2192  PStatTimer timer(_cache_update_pcollector);
2193 #endif // DO_PSTATS
2194 
2195  // There are lots of ways to do this loop wrong. Be very careful if
2196  // you need to modify it for any reason.
2197  int i = 0;
2198  while (!_composition_cache.is_empty()) {
2199  // Scan for the next used slot in the table.
2200  while (!_composition_cache.has_element(i)) {
2201  ++i;
2202  }
2203 
2204  // It is possible that the "other" TransformState object is
2205  // currently within its own destructor. We therefore can't use a
2206  // PT() to hold its pointer; that could end up calling its
2207  // destructor twice. Fortunately, we don't need to hold its
2208  // reference count to ensure it doesn't destruct while we process
2209  // this loop; as long as we ensure that no *other* TransformState
2210  // objects destruct, there will be no reason for that one to.
2211  TransformState *other = (TransformState *)_composition_cache.get_key(i);
2212 
2213  // We hold a copy of the composition result so we can dereference
2214  // it later.
2215  Composition comp = _composition_cache.get_data(i);
2216 
2217  // Now we can remove the element from our cache. We do this now,
2218  // rather than later, before any other TransformState objects have
2219  // had a chance to destruct, so we are confident that our iterator
2220  // is still valid.
2221  _composition_cache.remove_element(i);
2222  _cache_stats.add_total_size(-1);
2223  _cache_stats.inc_dels();
2224 
2225  if (other != this) {
2226  int oi = other->_composition_cache.find(this);
2227 
2228  // We may or may not still be listed in the other's cache (it
2229  // might be halfway through pulling entries out, from within its
2230  // own destructor).
2231  if (oi != -1) {
2232  // Hold a copy of the other composition result, too.
2233  Composition ocomp = other->_composition_cache.get_data(oi);
2234 
2235  other->_composition_cache.remove_element(oi);
2236  _cache_stats.add_total_size(-1);
2237  _cache_stats.inc_dels();
2238 
2239  // It's finally safe to let our held pointers go away. This may
2240  // have cascading effects as other TransformState objects are
2241  // destructed, but there will be no harm done if they destruct
2242  // now.
2243  if (ocomp._result != (const TransformState *)NULL && ocomp._result != other) {
2244  cache_unref_delete(ocomp._result);
2245  }
2246  }
2247  }
2248 
2249  // It's finally safe to let our held pointers go away. (See
2250  // comment above.)
2251  if (comp._result != (const TransformState *)NULL && comp._result != this) {
2252  cache_unref_delete(comp._result);
2253  }
2254  }
2255 
2256  // A similar bit of code for the invert cache.
2257  i = 0;
2258  while (!_invert_composition_cache.is_empty()) {
2259  while (!_invert_composition_cache.has_element(i)) {
2260  ++i;
2261  }
2262 
2263  TransformState *other = (TransformState *)_invert_composition_cache.get_key(i);
2264  nassertv(other != this);
2265  Composition comp = _invert_composition_cache.get_data(i);
2266  _invert_composition_cache.remove_element(i);
2267  _cache_stats.add_total_size(-1);
2268  _cache_stats.inc_dels();
2269  if (other != this) {
2270  int oi = other->_invert_composition_cache.find(this);
2271  if (oi != -1) {
2272  Composition ocomp = other->_invert_composition_cache.get_data(oi);
2273  other->_invert_composition_cache.remove_element(oi);
2274  _cache_stats.add_total_size(-1);
2275  _cache_stats.inc_dels();
2276  if (ocomp._result != (const TransformState *)NULL && ocomp._result != other) {
2277  cache_unref_delete(ocomp._result);
2278  }
2279  }
2280  }
2281  if (comp._result != (const TransformState *)NULL && comp._result != this) {
2282  cache_unref_delete(comp._result);
2283  }
2284  }
2285 }
2286 
2287 ////////////////////////////////////////////////////////////////////
2288 // Function: TransformState::do_calc_hash
2289 // Access: Private
2290 // Description: Computes a suitable hash value for phash_map.
2291 ////////////////////////////////////////////////////////////////////
2292 void TransformState::
2293 do_calc_hash() {
2294  PStatTimer timer(_transform_hash_pcollector);
2295  _hash = 0;
2296 
2297  static const int significant_flags =
2298  (F_is_invalid | F_is_identity | F_components_given | F_hpr_given | F_is_2d);
2299 
2300  int flags = (_flags & significant_flags);
2301  _hash = int_hash::add_hash(_hash, flags);
2302 
2303  if ((_flags & (F_is_invalid | F_is_identity)) == 0) {
2304  // Only bother to put the rest of the stuff in the hash if the
2305  // transform is not invalid or empty.
2306 
2307  if ((_flags & F_components_given) != 0) {
2308  // If the transform was specified componentwise, hash it
2309  // componentwise.
2310  _hash = _pos.add_hash(_hash);
2311  if ((_flags & F_hpr_given) != 0) {
2312  _hash = _hpr.add_hash(_hash);
2313 
2314  } else if ((_flags & F_quat_given) != 0) {
2315  _hash = _quat.add_hash(_hash);
2316  }
2317 
2318  _hash = _scale.add_hash(_hash);
2319  _hash = _shear.add_hash(_hash);
2320 
2321  } else {
2322  // Otherwise, hash the matrix . . .
2323  if (_uniquify_matrix) {
2324  // . . . but only if the user thinks that's worthwhile.
2325  if ((_flags & F_mat_known) == 0) {
2326  // Calculate the matrix without doubly-locking.
2327  do_calc_mat();
2328  }
2329  _hash = _mat.add_hash(_hash);
2330 
2331  } else {
2332  // Otherwise, hash the pointer only--any two different
2333  // matrix-based TransformStates are considered to be different,
2334  // even if their matrices have the same values.
2335 
2336  _hash = pointer_hash::add_hash(_hash, this);
2337  }
2338  }
2339  }
2340 
2341  _flags |= F_hash_known;
2342 }
2343 
2344 ////////////////////////////////////////////////////////////////////
2345 // Function: TransformState::calc_singular
2346 // Access: Private
2347 // Description: Determines whether the transform is singular (i.e. it
2348 // scales to zero, and has no inverse).
2349 ////////////////////////////////////////////////////////////////////
2350 void TransformState::
2351 calc_singular() {
2352  LightMutexHolder holder(_lock);
2353  if ((_flags & F_singular_known) != 0) {
2354  // Someone else computed it first.
2355  return;
2356  }
2357 
2358  PStatTimer timer(_transform_calc_pcollector);
2359 
2360  nassertv((_flags & F_is_invalid) == 0);
2361 
2362  // We determine if a matrix is singular by attempting to invert it
2363  // (and we save the result of this invert operation for a subsequent
2364  // do_invert_compose() call, which is almost certain to be made if
2365  // someone is asking whether we're singular).
2366 
2367  // This should be NULL if no one has called calc_singular() yet.
2368  nassertv(_inv_mat == (LMatrix4 *)NULL);
2369  _inv_mat = new LMatrix4;
2370 
2371  if ((_flags & F_mat_known) == 0) {
2372  do_calc_mat();
2373  }
2374  bool inverted = _inv_mat->invert_from(_mat);
2375 
2376  if (!inverted) {
2377  _flags |= F_is_singular;
2378  delete _inv_mat;
2379  _inv_mat = (LMatrix4 *)NULL;
2380  }
2381  _flags |= F_singular_known;
2382 }
2383 
2384 ////////////////////////////////////////////////////////////////////
2385 // Function: TransformState::do_calc_components
2386 // Access: Private
2387 // Description: This is the implementation of calc_components(); it
2388 // assumes the lock is already held.
2389 ////////////////////////////////////////////////////////////////////
2390 void TransformState::
2391 do_calc_components() {
2392  if ((_flags & F_components_known) != 0) {
2393  // Someone else computed it first.
2394  return;
2395  }
2396 
2397  PStatTimer timer(_transform_calc_pcollector);
2398 
2399  nassertv((_flags & F_is_invalid) == 0);
2400  if ((_flags & F_is_identity) != 0) {
2401  _scale.set(1.0f, 1.0f, 1.0f);
2402  _shear.set(0.0f, 0.0f, 0.0f);
2403  _hpr.set(0.0f, 0.0f, 0.0f);
2404  _quat = LQuaternion::ident_quat();
2405  _pos.set(0.0f, 0.0f, 0.0f);
2406  _flags |= F_has_components | F_components_known | F_hpr_known | F_quat_known | F_uniform_scale | F_identity_scale;
2407 
2408  } else {
2409  // If we don't have components and we're not identity, the only
2410  // other explanation is that we were constructed via a matrix.
2411  nassertv((_flags & F_mat_known) != 0);
2412 
2413  if ((_flags & F_mat_known) == 0) {
2414  do_calc_mat();
2415  }
2416  bool possible = decompose_matrix(_mat, _scale, _shear, _hpr, _pos);
2417  if (!possible) {
2418  // Some matrices can't be decomposed into scale, hpr, pos. In
2419  // this case, we now know that we cannot compute the components;
2420  // but the closest approximations are stored, at least.
2421  _flags |= F_components_known | F_hpr_known;
2422 
2423  } else {
2424  // Otherwise, we do have the components, or at least the hpr.
2425  _flags |= F_has_components | F_components_known | F_hpr_known;
2426  check_uniform_scale();
2427  }
2428 
2429  // However, we can always get at least the pos.
2430  _mat.get_row3(_pos, 3);
2431  }
2432 }
2433 
2434 ////////////////////////////////////////////////////////////////////
2435 // Function: TransformState::do_calc_hpr
2436 // Access: Private
2437 // Description: This is the implementation of calc_hpr(); it
2438 // assumes the lock is already held.
2439 ////////////////////////////////////////////////////////////////////
2440 void TransformState::
2441 do_calc_hpr() {
2442  if ((_flags & F_hpr_known) != 0) {
2443  // Someone else computed it first.
2444  return;
2445  }
2446 
2447  PStatTimer timer(_transform_calc_pcollector);
2448 
2449  nassertv((_flags & F_is_invalid) == 0);
2450  if ((_flags & F_components_known) == 0) {
2451  do_calc_components();
2452  }
2453  if ((_flags & F_hpr_known) == 0) {
2454  // If we don't know the hpr yet, we must have been given a quat.
2455  // Decompose it.
2456  nassertv((_flags & F_quat_known) != 0);
2457  _hpr = _quat.get_hpr();
2458  _flags |= F_hpr_known;
2459  }
2460 }
2461 
2462 ////////////////////////////////////////////////////////////////////
2463 // Function: TransformState::calc_quat
2464 // Access: Private
2465 // Description: Derives the quat from the hpr.
2466 ////////////////////////////////////////////////////////////////////
2467 void TransformState::
2468 calc_quat() {
2469  LightMutexHolder holder(_lock);
2470  if ((_flags & F_quat_known) != 0) {
2471  // Someone else computed it first.
2472  return;
2473  }
2474 
2475  PStatTimer timer(_transform_calc_pcollector);
2476 
2477  nassertv((_flags & F_is_invalid) == 0);
2478  if ((_flags & F_components_known) == 0) {
2479  do_calc_components();
2480  }
2481  if ((_flags & F_quat_known) == 0) {
2482  // If we don't know the quat yet, we must have been given a hpr.
2483  // Decompose it.
2484  nassertv((_flags & F_hpr_known) != 0);
2485  _quat.set_hpr(_hpr);
2486  _flags |= F_quat_known;
2487  }
2488 }
2489 
2490 ////////////////////////////////////////////////////////////////////
2491 // Function: TransformState::calc_norm_quat
2492 // Access: Private
2493 // Description: Derives the normalized quat from the quat.
2494 ////////////////////////////////////////////////////////////////////
2495 void TransformState::
2496 calc_norm_quat() {
2497  PStatTimer timer(_transform_calc_pcollector);
2498 
2499  LQuaternion quat = get_quat();
2500  LightMutexHolder holder(_lock);
2501  _norm_quat = quat;
2502  _norm_quat.normalize();
2503  _flags |= F_norm_quat_known;
2504 }
2505 
2506 ////////////////////////////////////////////////////////////////////
2507 // Function: TransformState::do_calc_mat
2508 // Access: Private
2509 // Description: This is the implementation of calc_mat(); it
2510 // assumes the lock is already held.
2511 ////////////////////////////////////////////////////////////////////
2512 void TransformState::
2513 do_calc_mat() {
2514  if ((_flags & F_mat_known) != 0) {
2515  // Someone else computed it first.
2516  return;
2517  }
2518 
2519  PStatTimer timer(_transform_calc_pcollector);
2520 
2521  nassertv((_flags & F_is_invalid) == 0);
2522  if ((_flags & F_is_identity) != 0) {
2523  _mat = LMatrix4::ident_mat();
2524 
2525  } else {
2526  // If we don't have a matrix and we're not identity, the only
2527  // other explanation is that we were constructed via components.
2528  nassertv((_flags & F_components_known) != 0);
2529  if ((_flags & F_hpr_known) == 0) {
2530  do_calc_hpr();
2531  }
2532 
2533  compose_matrix(_mat, _scale, _shear, get_hpr(), _pos);
2534  }
2535  _flags |= F_mat_known;
2536 }
2537 
2538 ////////////////////////////////////////////////////////////////////
2539 // Function: TransformState::update_pstats
2540 // Access: Private
2541 // Description: Moves the TransformState object from one PStats category
2542 // to another, so that we can track in PStats how many
2543 // pointers are held by nodes, and how many are held in
2544 // the cache only.
2545 ////////////////////////////////////////////////////////////////////
2546 void TransformState::
2547 update_pstats(int old_referenced_bits, int new_referenced_bits) {
2548 #ifdef DO_PSTATS
2549  if ((old_referenced_bits & R_node) != 0) {
2550  _node_counter.sub_level(1);
2551  } else if ((old_referenced_bits & R_cache) != 0) {
2552  _cache_counter.sub_level(1);
2553  }
2554  if ((new_referenced_bits & R_node) != 0) {
2555  _node_counter.add_level(1);
2556  } else if ((new_referenced_bits & R_cache) != 0) {
2557  _cache_counter.add_level(1);
2558  }
2559 #endif // DO_PSTATS
2560 }
2561 
2562 ////////////////////////////////////////////////////////////////////
2563 // Function: TransformState::register_with_read_factory
2564 // Access: Public, Static
2565 // Description: Tells the BamReader how to create objects of type
2566 // TransformState.
2567 ////////////////////////////////////////////////////////////////////
2568 void TransformState::
2569 register_with_read_factory() {
2570  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
2571 }
2572 
2573 ////////////////////////////////////////////////////////////////////
2574 // Function: TransformState::write_datagram
2575 // Access: Public, Virtual
2576 // Description: Writes the contents of this object to the datagram
2577 // for shipping out to a Bam file.
2578 ////////////////////////////////////////////////////////////////////
2579 void TransformState::
2580 write_datagram(BamWriter *manager, Datagram &dg) {
2581  TypedWritable::write_datagram(manager, dg);
2582 
2583  if ((_flags & F_is_identity) != 0) {
2584  // Identity, nothing much to that.
2585  int flags = F_is_identity | F_singular_known | F_is_2d;
2586  dg.add_uint32(flags);
2587 
2588  } else if ((_flags & F_is_invalid) != 0) {
2589  // Invalid, nothing much to that either.
2590  int flags = F_is_invalid | F_singular_known | F_is_singular | F_components_known | F_mat_known;
2591  dg.add_uint32(flags);
2592 
2593  } else if ((_flags & F_components_given) != 0) {
2594  // A component-based transform.
2595  int flags = F_components_given | F_components_known | F_has_components;
2596  flags |= (_flags & F_is_2d);
2597  if ((_flags & F_quat_given) != 0) {
2598  flags |= (F_quat_given | F_quat_known);
2599  } else if ((_flags & F_hpr_given) != 0) {
2600  flags |= (F_hpr_given | F_hpr_known);
2601  }
2602 
2603  dg.add_uint32(flags);
2604 
2605  _pos.write_datagram(dg);
2606  if ((_flags & F_quat_given) != 0) {
2607  _quat.write_datagram(dg);
2608  } else {
2609  get_hpr().write_datagram(dg);
2610  }
2611  _scale.write_datagram(dg);
2612  _shear.write_datagram(dg);
2613 
2614  } else {
2615  // A general matrix.
2616  nassertv((_flags & F_mat_known) != 0);
2617  int flags = F_mat_known;
2618  flags |= (_flags & F_is_2d);
2619  dg.add_uint32(flags);
2620  _mat.write_datagram(dg);
2621  }
2622 }
2623 
2624 ////////////////////////////////////////////////////////////////////
2625 // Function: TransformState::change_this
2626 // Access: Public, Static
2627 // Description: Called immediately after complete_pointers(), this
2628 // gives the object a chance to adjust its own pointer
2629 // if desired. Most objects don't change pointers after
2630 // completion, but some need to.
2631 //
2632 // Once this function has been called, the old pointer
2633 // will no longer be accessed.
2634 ////////////////////////////////////////////////////////////////////
2635 PT(TypedWritableReferenceCount) TransformState::
2636 change_this(TypedWritableReferenceCount *old_ptr, BamReader *manager) {
2637  // First, uniquify the pointer.
2638  TransformState *state = DCAST(TransformState, old_ptr);
2639  CPT(TransformState) pointer = return_unique(state);
2640 
2641  // We have to cast the pointer back to non-const, because the bam
2642  // reader expects that.
2643  return (TransformState *)pointer.p();
2644 }
2645 
2646 ////////////////////////////////////////////////////////////////////
2647 // Function: TransformState::make_from_bam
2648 // Access: Protected, Static
2649 // Description: This function is called by the BamReader's factory
2650 // when a new object of type TransformState is encountered
2651 // in the Bam file. It should create the TransformState
2652 // and extract its information from the file.
2653 ////////////////////////////////////////////////////////////////////
2654 TypedWritable *TransformState::
2655 make_from_bam(const FactoryParams &params) {
2656  TransformState *state = new TransformState;
2657  DatagramIterator scan;
2658  BamReader *manager;
2659 
2660  parse_params(params, scan, manager);
2661  state->fillin(scan, manager);
2662  manager->register_change_this(change_this, state);
2663 
2664  return state;
2665 }
2666 
2667 ////////////////////////////////////////////////////////////////////
2668 // Function: TransformState::fillin
2669 // Access: Protected
2670 // Description: This internal function is called by make_from_bam to
2671 // read in all of the relevant data from the BamFile for
2672 // the new TransformState.
2673 ////////////////////////////////////////////////////////////////////
2674 void TransformState::
2675 fillin(DatagramIterator &scan, BamReader *manager) {
2676  TypedWritable::fillin(scan, manager);
2677  _flags = scan.get_uint32();
2678 
2679  if ((_flags & F_components_given) != 0) {
2680  // Componentwise transform.
2681  _pos.read_datagram(scan);
2682  if ((_flags & F_quat_given) != 0) {
2683  _quat.read_datagram(scan);
2684  } else {
2685  _hpr.read_datagram(scan);
2686  }
2687  _scale.read_datagram(scan);
2688  _shear.read_datagram(scan);
2689 
2690  check_uniform_scale();
2691  }
2692 
2693  if ((_flags & F_mat_known) != 0) {
2694  // General matrix.
2695  _mat.read_datagram(scan);
2696  }
2697 }
static const LQuaternionf & ident_quat()
Returns an identity quaternion.
Definition: lquaternion.h:851
static const LMatrix4f & ident_mat()
Returns an identity matrix.
Definition: lmatrix.h:903
static size_t add_hash(size_t start, const void *key)
Adds the indicated key into a running hash.
Definition: stl_compares.I:133
This is the base class for all three-component vectors and points.
Definition: lvecBase3.h:105
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
bool almost_equal(const LMatrix4f &other, float threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
Definition: lmatrix.cxx:879
This is a convenience class to specialize ConfigVariable as a boolean type.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
A lightweight reentrant mutex.
Definition: lightReMutex.h:34
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:34
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
Definition: lvecBase3.h:464
void set_row(int row, const LVecBase3f &v)
Replaces the indicated row of the matrix from a three-component vector.
Definition: lmatrix.h:2958
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
bool is_nan() const
Returns true if any component of the matrix is not-a-number, false otherwise.
Definition: lmatrix.h:1417
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class&#39;s make_from_bam() method to read in all...
void register_change_this(ChangeThisFunc func, TypedWritable *whom)
Called by an object reading itself from the bam file to indicate that the object pointer that will be...
Definition: bamReader.cxx:917
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:39
static size_t add_hash(size_t start, const Key &key)
Adds the indicated key into a running hash.
Definition: stl_compares.I:122
static Thread * get_main_thread()
Returns a pointer to the "main" Thread object–this is the Thread that started the whole process...
Definition: thread.I:107
bool invert_in_place()
Inverts the current quat.
Definition: lquaternion.h:817
A lightweight class that represents a single element that may be timed and/or counted via stats...
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
Similar to MutexHolder, but for a light mutex.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
This is the base class for all two-component vectors and points.
Definition: lvecBase2.h:105
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
LVecBase3f xform(const LVecBase3f &v) const
Transforms a 3-d vector by the indicated rotation.
Definition: lquaternion.h:280
bool is_nan() const
Returns true if any component of the matrix is not-a-number, false otherwise.
Definition: lmatrix.h:3147
Similar to MutexHolder, but for a light reentrant mutex.
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:90
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
This is used to track the utilization of the TransformState and RenderState caches, for low-level performance tuning information.
Definition: cacheStats.h:28
This is the base quaternion class.
Definition: lquaternion.h:96
void add_uint32(PN_uint32 value)
Adds an unsigned 32-bit integer to the datagram.
Definition: datagram.I:192
bool is_identity() const
Returns true if this is (close enough to) the identity matrix, false otherwise.
Definition: lmatrix.h:3162
bool is_identity() const
Returns true if this is (close enough to) the identity matrix, false otherwise.
Definition: lmatrix.h:1433
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
Definition: lvecBase4.h:576
void set_row(int row, const LVecBase4f &v)
Replaces the indicated row of the matrix.
Definition: lmatrix.h:1187
This is our own Panda specialization on the default STL set.
Definition: pset.h:52
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
Definition: lvecBase2.h:431
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
This is a 3-by-3 transform matrix.
Definition: lmatrix.h:110
This is a sequence number that increments monotonically.
Definition: updateSeq.h:43
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
virtual bool unref() const
Explicitly decrements the reference count.
int size() const
Returns the number of texture stages in the collection.