Panda3D
 All Classes Functions Variables Enumerations
transformState.h
00001 // Filename: transformState.h
00002 // Created by:  drose (25Feb02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #ifndef TRANSFORMSTATE_H
00016 #define TRANSFORMSTATE_H
00017 
00018 #include "pandabase.h"
00019 
00020 #include "nodeCachedReferenceCount.h"
00021 #include "pointerTo.h"
00022 #include "luse.h"
00023 #include "event.h"
00024 #include "updateSeq.h"
00025 #include "pStatCollector.h"
00026 #include "geomEnums.h"
00027 #include "lightReMutex.h"
00028 #include "lightReMutexHolder.h"
00029 #include "lightMutex.h"
00030 #include "lightMutexHolder.h"
00031 #include "config_pgraph.h"
00032 #include "deletedChain.h"
00033 #include "simpleHashMap.h"
00034 #include "cacheStats.h"
00035 
00036 class GraphicsStateGuardianBase;
00037 class FactoryParams;
00038 
00039 ////////////////////////////////////////////////////////////////////
00040 //       Class : TransformState
00041 // Description : Indicates a coordinate-system transform on vertices.
00042 //               TransformStates are the primary means for storing
00043 //               transformations on the scene graph.
00044 //
00045 //               Transforms may be specified in one of two ways:
00046 //               componentwise, with a pos-hpr-scale, or with an
00047 //               arbitrary transform matrix.  If you specify a
00048 //               transform componentwise, it will remember its
00049 //               original components.
00050 //
00051 //               TransformState objects are managed very much like
00052 //               RenderState objects.  They are immutable and
00053 //               reference-counted automatically.
00054 //
00055 //               You should not attempt to create or modify a
00056 //               TransformState object directly.  Instead, call one of
00057 //               the make() functions to create one for you.  And
00058 //               instead of modifying a TransformState object, create a
00059 //               new one.
00060 ////////////////////////////////////////////////////////////////////
00061 class EXPCL_PANDA_PGRAPH TransformState : public NodeCachedReferenceCount {
00062 protected:
00063   TransformState();
00064 
00065 private:
00066   TransformState(const TransformState &copy);
00067   void operator = (const TransformState &copy);
00068 
00069 public:
00070   virtual ~TransformState();
00071   ALLOC_DELETED_CHAIN(TransformState);
00072 
00073 PUBLISHED:
00074   INLINE bool operator < (const TransformState &other) const;
00075   INLINE int compare_to(const TransformState &other) const;
00076   int compare_to(const TransformState &other, bool uniquify_matrix) const;
00077   INLINE size_t get_hash() const;
00078 
00079   static CPT(TransformState) make_identity();
00080   static CPT(TransformState) make_invalid();
00081   INLINE static CPT(TransformState) make_pos(const LVecBase3 &pos);
00082   INLINE static CPT(TransformState) make_hpr(const LVecBase3 &hpr);
00083   INLINE static CPT(TransformState) make_quat(const LQuaternion &quat);
00084   INLINE static CPT(TransformState) make_pos_hpr(const LVecBase3 &pos,
00085                                                  const LVecBase3 &hpr);
00086   INLINE static CPT(TransformState) make_scale(PN_stdfloat scale);
00087   INLINE static CPT(TransformState) make_scale(const LVecBase3 &scale);
00088   INLINE static CPT(TransformState) make_shear(const LVecBase3 &shear);
00089   INLINE static CPT(TransformState) make_pos_hpr_scale(const LVecBase3 &pos,
00090                                                        const LVecBase3 &hpr, 
00091                                                        const LVecBase3 &scale);
00092   INLINE static CPT(TransformState) make_pos_quat_scale(const LVecBase3 &pos,
00093                                                         const LQuaternion &quat, 
00094                                                         const LVecBase3 &scale);
00095   static CPT(TransformState) make_pos_hpr_scale_shear(const LVecBase3 &pos,
00096                                                       const LVecBase3 &hpr, 
00097                                                       const LVecBase3 &scale,
00098                                                       const LVecBase3 &shear);
00099   static CPT(TransformState) make_pos_quat_scale_shear(const LVecBase3 &pos,
00100                                                        const LQuaternion &quat, 
00101                                                        const LVecBase3 &scale,
00102                                                        const LVecBase3 &shear);
00103   static CPT(TransformState) make_mat(const LMatrix4 &mat);
00104 
00105 
00106   INLINE static CPT(TransformState) make_pos2d(const LVecBase2 &pos);
00107   INLINE static CPT(TransformState) make_rotate2d(PN_stdfloat rotate);
00108   INLINE static CPT(TransformState) make_pos_rotate2d(const LVecBase2 &pos,
00109                                                       PN_stdfloat rotate);
00110   INLINE static CPT(TransformState) make_scale2d(PN_stdfloat scale);
00111   INLINE static CPT(TransformState) make_scale2d(const LVecBase2 &scale);
00112   INLINE static CPT(TransformState) make_shear2d(PN_stdfloat shear);
00113   INLINE static CPT(TransformState) make_pos_rotate_scale2d(const LVecBase2 &pos,
00114                                                             PN_stdfloat rotate, 
00115                                                             const LVecBase2 &scale);
00116   static CPT(TransformState) make_pos_rotate_scale_shear2d(const LVecBase2 &pos,
00117                                                            PN_stdfloat rotate,
00118                                                            const LVecBase2 &scale,
00119                                                            PN_stdfloat shear);
00120   static CPT(TransformState) make_mat3(const LMatrix3 &mat);
00121 
00122 
00123   INLINE bool is_identity() const;
00124   INLINE bool is_invalid() const;
00125   INLINE bool is_singular() const;
00126   INLINE bool is_2d() const;
00127 
00128   INLINE bool has_components() const;
00129   INLINE bool components_given() const;
00130   INLINE bool hpr_given() const;
00131   INLINE bool quat_given() const;
00132   INLINE bool has_pos() const;
00133   INLINE bool has_hpr() const;
00134   INLINE bool has_quat() const;
00135   INLINE bool has_scale() const;
00136   INLINE bool has_identity_scale() const;
00137   INLINE bool has_uniform_scale() const;
00138   INLINE bool has_shear() const;
00139   INLINE bool has_nonzero_shear() const;
00140   INLINE bool has_mat() const;
00141 
00142   INLINE const LPoint3 &get_pos() const;
00143   INLINE const LVecBase3 &get_hpr() const;
00144   INLINE const LQuaternion &get_quat() const;
00145   INLINE const LQuaternion &get_norm_quat() const;
00146   INLINE const LVecBase3 &get_scale() const;
00147   INLINE PN_stdfloat get_uniform_scale() const;
00148   INLINE const LVecBase3 &get_shear() const;
00149   INLINE const LMatrix4 &get_mat() const;
00150 
00151   INLINE LVecBase2 get_pos2d() const;
00152   INLINE PN_stdfloat get_rotate2d() const;
00153   INLINE LVecBase2 get_scale2d() const;
00154   INLINE PN_stdfloat get_shear2d() const;
00155   INLINE LMatrix3 get_mat3() const;
00156 
00157   CPT(TransformState) set_pos(const LVecBase3 &pos) const;
00158   CPT(TransformState) set_hpr(const LVecBase3 &hpr) const;
00159   CPT(TransformState) set_quat(const LQuaternion &quat) const;
00160   CPT(TransformState) set_scale(const LVecBase3 &scale) const;
00161   CPT(TransformState) set_shear(const LVecBase3 &shear) const;
00162 
00163   CPT(TransformState) set_pos2d(const LVecBase2 &pos) const;
00164   CPT(TransformState) set_rotate2d(PN_stdfloat rotate) const;
00165   CPT(TransformState) set_scale2d(const LVecBase2 &scale) const;
00166   CPT(TransformState) set_shear2d(PN_stdfloat shear) const;
00167 
00168   CPT(TransformState) compose(const TransformState *other) const;
00169   CPT(TransformState) invert_compose(const TransformState *other) const;
00170 
00171   INLINE CPT(TransformState) get_inverse() const;
00172   INLINE CPT(TransformState) get_unique() const;
00173 
00174   INLINE int get_geom_rendering(int geom_rendering) const;
00175 
00176   virtual bool unref() const;
00177 
00178   INLINE void cache_ref() const;
00179   INLINE bool cache_unref() const;
00180   INLINE void node_ref() const;
00181   INLINE bool node_unref() const;
00182 
00183   INLINE int get_composition_cache_num_entries() const;
00184   INLINE int get_invert_composition_cache_num_entries() const;
00185 
00186   INLINE int get_composition_cache_size() const;
00187   INLINE const TransformState *get_composition_cache_source(int n) const;
00188   INLINE const TransformState *get_composition_cache_result(int n) const;
00189   INLINE int get_invert_composition_cache_size() const;
00190   INLINE const TransformState *get_invert_composition_cache_source(int n) const;
00191   INLINE const TransformState *get_invert_composition_cache_result(int n) const;
00192   bool validate_composition_cache() const;
00193 #ifdef HAVE_PYTHON
00194   PyObject *get_composition_cache() const;
00195   PyObject *get_invert_composition_cache() const;
00196 #endif  // HAVE_PYTHON
00197 
00198   void output(ostream &out) const;
00199   void write(ostream &out, int indent_level) const;
00200   void write_composition_cache(ostream &out, int indent_level) const;
00201 
00202   static int get_num_states();
00203   static int get_num_unused_states();
00204   static int clear_cache();
00205   static int garbage_collect();
00206   static void list_cycles(ostream &out);
00207   static void list_states(ostream &out);
00208   static bool validate_states();
00209 #ifdef HAVE_PYTHON
00210   static PyObject *get_states();
00211   static PyObject *get_unused_states();
00212 #endif  // HAVE_PYTHON
00213 
00214 
00215 public:
00216   static void init_states();
00217 
00218   INLINE static void flush_level();
00219 
00220 private:
00221   INLINE bool do_cache_unref() const;
00222   INLINE bool do_node_unref() const;
00223 
00224   class CompositionCycleDescEntry {
00225   public:
00226     INLINE CompositionCycleDescEntry(const TransformState *obj,
00227                                      const TransformState *result,
00228                                      bool inverted);
00229 
00230     const TransformState *_obj;
00231     const TransformState *_result;
00232     bool _inverted;
00233   };
00234   typedef pvector<CompositionCycleDescEntry> CompositionCycleDesc;
00235 
00236   static CPT(TransformState) return_new(TransformState *state);
00237   static CPT(TransformState) return_unique(TransformState *state);
00238 
00239   CPT(TransformState) do_compose(const TransformState *other) const;
00240   CPT(TransformState) store_compose(const TransformState *other, const TransformState *result);
00241   CPT(TransformState) do_invert_compose(const TransformState *other) const;
00242   CPT(TransformState) store_invert_compose(const TransformState *other, const TransformState *result);
00243   void detect_and_break_cycles();
00244   static bool r_detect_cycles(const TransformState *start_state,
00245                               const TransformState *current_state,
00246                               int length, UpdateSeq this_seq,
00247                               CompositionCycleDesc *cycle_desc);
00248   static bool r_detect_reverse_cycles(const TransformState *start_state,
00249                                       const TransformState *current_state,
00250                                       int length, UpdateSeq this_seq,
00251                                       CompositionCycleDesc *cycle_desc);
00252 
00253   void release_new();
00254   void remove_cache_pointers();
00255 
00256 private:
00257   // This mutex protects _states.  It also protects any modification
00258   // to the cache, which is encoded in _composition_cache and
00259   // _invert_composition_cache.
00260   static LightReMutex *_states_lock;
00261   class Empty {
00262   };
00263   typedef SimpleHashMap<const TransformState *, Empty, indirect_compare_to_hash<const TransformState *> > States;
00264   static States *_states;
00265   static CPT(TransformState) _identity_state;
00266   static CPT(TransformState) _invalid_state;
00267 
00268   // This iterator records the entry corresponding to this
00269   // TransformState object in the above global set.  We keep the index
00270   // around so we can remove it when the TransformState destructs.
00271   int _saved_entry;
00272 
00273   // This data structure manages the job of caching the composition of
00274   // two TransformStates.  It's complicated because we have to be sure to
00275   // remove the entry if *either* of the input TransformStates destructs.
00276   // To implement this, we always record Composition entries in pairs,
00277   // one in each of the two involved TransformState objects.
00278     
00279   // The first element of the map is the object we compose with.  This
00280   // is not reference counted within this map; instead we store a
00281   // companion pointer in the other object, and remove the references
00282   // explicitly when either object destructs.
00283   class Composition {
00284   public:
00285     INLINE Composition();
00286     INLINE Composition(const Composition &copy);
00287 
00288     // _result is reference counted if and only if it is not the same
00289     // pointer as this.
00290     const TransformState *_result;
00291   };
00292 
00293   typedef SimpleHashMap<const TransformState *, Composition, pointer_hash> CompositionCache;
00294   CompositionCache _composition_cache;
00295   CompositionCache _invert_composition_cache;
00296 
00297   // This is used to mark nodes as we visit them to detect cycles.
00298   UpdateSeq _cycle_detect;
00299   static UpdateSeq _last_cycle_detect;
00300 
00301   // This keeps track of our current position through the garbage
00302   // collection cycle.
00303   static int _garbage_index;
00304 
00305   static PStatCollector _cache_update_pcollector;
00306   static PStatCollector _garbage_collect_pcollector;
00307   static PStatCollector _transform_compose_pcollector;
00308   static PStatCollector _transform_invert_pcollector;
00309   static PStatCollector _transform_calc_pcollector;
00310   static PStatCollector _transform_break_cycles_pcollector;
00311   static PStatCollector _transform_new_pcollector;
00312   static PStatCollector _transform_validate_pcollector;
00313   static PStatCollector _transform_hash_pcollector;
00314 
00315   static PStatCollector _node_counter;
00316   static PStatCollector _cache_counter;
00317 
00318 private:
00319   // This is the actual data within the TransformState.
00320   INLINE void check_hash() const;
00321   INLINE void check_singular() const;
00322   INLINE void check_components() const;
00323   INLINE void check_hpr() const;
00324   INLINE void check_quat() const;
00325   INLINE void check_norm_quat() const;
00326   INLINE void check_mat() const;
00327   INLINE void calc_hash();
00328   void do_calc_hash();
00329   void calc_singular();
00330   INLINE void calc_components();
00331   void do_calc_components();
00332   INLINE void calc_hpr();
00333   void do_calc_hpr();
00334   void calc_quat();
00335   void calc_norm_quat();
00336   INLINE void calc_mat();
00337   void do_calc_mat();
00338 
00339   INLINE void check_uniform_scale();
00340   INLINE void check_uniform_scale2d();
00341 
00342   INLINE void set_destructing();
00343   INLINE bool is_destructing() const;
00344 
00345   INLINE void consider_update_pstats(int old_referenced_bits) const;
00346   static void update_pstats(int old_referenced_bits, int new_referenced_bits);
00347 
00348   enum Flags {
00349     F_is_identity        = 0x00000001,
00350     F_is_singular        = 0x00000002,
00351     F_singular_known     = 0x00000004,  // set if we know F_is_singular
00352     F_components_given   = 0x00000008,
00353     F_components_known   = 0x00000010,  // set if we know F_has_components
00354     F_has_components     = 0x00000020,
00355     F_mat_known          = 0x00000040,  // set if _mat is defined
00356     F_is_invalid         = 0x00000080,
00357     F_quat_given         = 0x00000100,
00358     F_quat_known         = 0x00000200,  // set if _quat is defined
00359     F_hpr_given          = 0x00000400,
00360     F_hpr_known          = 0x00000800,  // set if _hpr is defined
00361     F_uniform_scale      = 0x00001000,
00362     F_identity_scale     = 0x00002000,
00363     F_has_nonzero_shear  = 0x00004000,
00364     F_is_destructing     = 0x00008000,
00365     F_is_2d              = 0x00010000,
00366     F_hash_known         = 0x00020000,
00367     F_norm_quat_known    = 0x00040000,
00368   };
00369   LPoint3 _pos;
00370   LVecBase3 _hpr, _scale, _shear;
00371   LQuaternion _quat, _norm_quat;
00372   LMatrix4 _mat;
00373   LMatrix4 *_inv_mat;
00374   size_t _hash;
00375   
00376   unsigned int _flags;
00377 
00378   // This mutex protects _flags, and all of the above computed values.
00379   LightMutex _lock;
00380 
00381   static CacheStats _cache_stats;
00382 
00383 public:
00384   static void register_with_read_factory();
00385   virtual void write_datagram(BamWriter *manager, Datagram &dg);
00386   static PT(TypedWritableReferenceCount) change_this(TypedWritableReferenceCount *old_ptr, BamReader *manager);
00387 
00388 protected:
00389   static TypedWritable *make_from_bam(const FactoryParams &params);
00390   void fillin(DatagramIterator &scan, BamReader *manager);
00391   
00392 public:
00393   static TypeHandle get_class_type() {
00394     return _type_handle;
00395   }
00396   static void init_type() {
00397     NodeCachedReferenceCount::init_type();
00398     register_type(_type_handle, "TransformState",
00399                   NodeCachedReferenceCount::get_class_type());
00400   }
00401   virtual TypeHandle get_type() const {
00402     return get_class_type();
00403   }
00404   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00405 
00406 private:
00407   static TypeHandle _type_handle;
00408 };
00409 
00410 INLINE ostream &operator << (ostream &out, const TransformState &state) {
00411   state.output(out);
00412   return out;
00413 }
00414 
00415 #include "transformState.I"
00416 
00417 #endif
00418 
 All Classes Functions Variables Enumerations