Panda3D
|
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 ©); 00067 void operator = (const TransformState ©); 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 ©); 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 ¶ms); 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