transformState.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // Filename: transformState.h
  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. #ifndef TRANSFORMSTATE_H
  15. #define TRANSFORMSTATE_H
  16. #include "pandabase.h"
  17. #include "nodeCachedReferenceCount.h"
  18. #include "pointerTo.h"
  19. #include "luse.h"
  20. #include "pset.h"
  21. #include "event.h"
  22. #include "updateSeq.h"
  23. #include "pStatCollector.h"
  24. #include "geomEnums.h"
  25. #include "lightReMutex.h"
  26. #include "lightReMutexHolder.h"
  27. #include "lightMutex.h"
  28. #include "lightMutexHolder.h"
  29. #include "config_pgraph.h"
  30. #include "deletedChain.h"
  31. #include "simpleHashMap.h"
  32. #include "cacheStats.h"
  33. class GraphicsStateGuardianBase;
  34. class FactoryParams;
  35. ////////////////////////////////////////////////////////////////////
  36. // Class : TransformState
  37. // Description : Indicates a coordinate-system transform on vertices.
  38. // TransformStates are the primary means for storing
  39. // transformations on the scene graph.
  40. //
  41. // Transforms may be specified in one of two ways:
  42. // componentwise, with a pos-hpr-scale, or with an
  43. // arbitrary transform matrix. If you specify a
  44. // transform componentwise, it will remember its
  45. // original components.
  46. //
  47. // TransformState objects are managed very much like
  48. // RenderState objects. They are immutable and
  49. // reference-counted automatically.
  50. //
  51. // You should not attempt to create or modify a
  52. // TransformState object directly. Instead, call one of
  53. // the make() functions to create one for you. And
  54. // instead of modifying a TransformState object, create a
  55. // new one.
  56. ////////////////////////////////////////////////////////////////////
  57. class EXPCL_PANDA_PGRAPH TransformState : public NodeCachedReferenceCount {
  58. protected:
  59. TransformState();
  60. private:
  61. TransformState(const TransformState &copy);
  62. void operator = (const TransformState &copy);
  63. public:
  64. virtual ~TransformState();
  65. ALLOC_DELETED_CHAIN(TransformState);
  66. PUBLISHED:
  67. INLINE bool operator < (const TransformState &other) const;
  68. bool sorts_less(const TransformState &other, bool uniquify_matrix) const;
  69. INLINE size_t get_hash() const;
  70. static CPT(TransformState) make_identity();
  71. static CPT(TransformState) make_invalid();
  72. INLINE static CPT(TransformState) make_pos(const LVecBase3f &pos);
  73. INLINE static CPT(TransformState) make_hpr(const LVecBase3f &hpr);
  74. INLINE static CPT(TransformState) make_quat(const LQuaternionf &quat);
  75. INLINE static CPT(TransformState) make_pos_hpr(const LVecBase3f &pos,
  76. const LVecBase3f &hpr);
  77. INLINE static CPT(TransformState) make_scale(float scale);
  78. INLINE static CPT(TransformState) make_scale(const LVecBase3f &scale);
  79. INLINE static CPT(TransformState) make_shear(const LVecBase3f &shear);
  80. INLINE static CPT(TransformState) make_pos_hpr_scale(const LVecBase3f &pos,
  81. const LVecBase3f &hpr,
  82. const LVecBase3f &scale);
  83. INLINE static CPT(TransformState) make_pos_quat_scale(const LVecBase3f &pos,
  84. const LQuaternionf &quat,
  85. const LVecBase3f &scale);
  86. static CPT(TransformState) make_pos_hpr_scale_shear(const LVecBase3f &pos,
  87. const LVecBase3f &hpr,
  88. const LVecBase3f &scale,
  89. const LVecBase3f &shear);
  90. static CPT(TransformState) make_pos_quat_scale_shear(const LVecBase3f &pos,
  91. const LQuaternionf &quat,
  92. const LVecBase3f &scale,
  93. const LVecBase3f &shear);
  94. static CPT(TransformState) make_mat(const LMatrix4f &mat);
  95. INLINE static CPT(TransformState) make_pos2d(const LVecBase2f &pos);
  96. INLINE static CPT(TransformState) make_rotate2d(float rotate);
  97. INLINE static CPT(TransformState) make_pos_rotate2d(const LVecBase2f &pos,
  98. float rotate);
  99. INLINE static CPT(TransformState) make_scale2d(float scale);
  100. INLINE static CPT(TransformState) make_scale2d(const LVecBase2f &scale);
  101. INLINE static CPT(TransformState) make_shear2d(float shear);
  102. INLINE static CPT(TransformState) make_pos_rotate_scale2d(const LVecBase2f &pos,
  103. float rotate,
  104. const LVecBase2f &scale);
  105. static CPT(TransformState) make_pos_rotate_scale_shear2d(const LVecBase2f &pos,
  106. float rotate,
  107. const LVecBase2f &scale,
  108. float shear);
  109. static CPT(TransformState) make_mat3(const LMatrix3f &mat);
  110. INLINE bool is_identity() const;
  111. INLINE bool is_invalid() const;
  112. INLINE bool is_singular() const;
  113. INLINE bool is_2d() const;
  114. INLINE bool has_components() const;
  115. INLINE bool components_given() const;
  116. INLINE bool hpr_given() const;
  117. INLINE bool quat_given() const;
  118. INLINE bool has_pos() const;
  119. INLINE bool has_hpr() const;
  120. INLINE bool has_quat() const;
  121. INLINE bool has_scale() const;
  122. INLINE bool has_identity_scale() const;
  123. INLINE bool has_uniform_scale() const;
  124. INLINE bool has_shear() const;
  125. INLINE bool has_nonzero_shear() const;
  126. INLINE bool has_mat() const;
  127. INLINE const LPoint3f &get_pos() const;
  128. INLINE const LVecBase3f &get_hpr() const;
  129. INLINE const LQuaternionf &get_quat() const;
  130. INLINE const LQuaternionf &get_norm_quat() const;
  131. INLINE const LVecBase3f &get_scale() const;
  132. INLINE float get_uniform_scale() const;
  133. INLINE const LVecBase3f &get_shear() const;
  134. INLINE const LMatrix4f &get_mat() const;
  135. INLINE LVecBase2f get_pos2d() const;
  136. INLINE float get_rotate2d() const;
  137. INLINE LVecBase2f get_scale2d() const;
  138. INLINE float get_shear2d() const;
  139. INLINE LMatrix3f get_mat3() const;
  140. CPT(TransformState) set_pos(const LVecBase3f &pos) const;
  141. CPT(TransformState) set_hpr(const LVecBase3f &hpr) const;
  142. CPT(TransformState) set_quat(const LQuaternionf &quat) const;
  143. CPT(TransformState) set_scale(const LVecBase3f &scale) const;
  144. CPT(TransformState) set_shear(const LVecBase3f &shear) const;
  145. CPT(TransformState) set_pos2d(const LVecBase2f &pos) const;
  146. CPT(TransformState) set_rotate2d(float rotate) const;
  147. CPT(TransformState) set_scale2d(const LVecBase2f &scale) const;
  148. CPT(TransformState) set_shear2d(float shear) const;
  149. CPT(TransformState) compose(const TransformState *other) const;
  150. CPT(TransformState) invert_compose(const TransformState *other) const;
  151. INLINE CPT(TransformState) get_inverse() const;
  152. INLINE CPT(TransformState) get_unique() const;
  153. INLINE int get_geom_rendering(int geom_rendering) const;
  154. virtual bool unref() const;
  155. INLINE void cache_ref() const;
  156. INLINE bool cache_unref() const;
  157. INLINE void node_ref() const;
  158. INLINE bool node_unref() const;
  159. INLINE int get_composition_cache_num_entries() const;
  160. INLINE int get_invert_composition_cache_num_entries() const;
  161. INLINE int get_composition_cache_size() const;
  162. INLINE const TransformState *get_composition_cache_source(int n) const;
  163. INLINE const TransformState *get_composition_cache_result(int n) const;
  164. INLINE int get_invert_composition_cache_size() const;
  165. INLINE const TransformState *get_invert_composition_cache_source(int n) const;
  166. INLINE const TransformState *get_invert_composition_cache_result(int n) const;
  167. #ifdef HAVE_PYTHON
  168. PyObject *get_composition_cache() const;
  169. PyObject *get_invert_composition_cache() const;
  170. #endif // HAVE_PYTHON
  171. void output(ostream &out) const;
  172. void write(ostream &out, int indent_level) const;
  173. void write_composition_cache(ostream &out, int indent_level) const;
  174. static int get_num_states();
  175. static int get_num_unused_states();
  176. static int clear_cache();
  177. static void list_cycles(ostream &out);
  178. static void list_states(ostream &out);
  179. static bool validate_states();
  180. #ifdef HAVE_PYTHON
  181. static PyObject *get_states();
  182. #endif // HAVE_PYTHON
  183. public:
  184. static void init_states();
  185. INLINE static void flush_level();
  186. private:
  187. INLINE bool do_cache_unref() const;
  188. INLINE bool do_node_unref() const;
  189. class CompositionCycleDescEntry {
  190. public:
  191. INLINE CompositionCycleDescEntry(const TransformState *obj,
  192. const TransformState *result,
  193. bool inverted);
  194. const TransformState *_obj;
  195. const TransformState *_result;
  196. bool _inverted;
  197. };
  198. typedef pvector<CompositionCycleDescEntry> CompositionCycleDesc;
  199. static CPT(TransformState) return_new(TransformState *state);
  200. static CPT(TransformState) return_unique(TransformState *state);
  201. CPT(TransformState) do_compose(const TransformState *other) const;
  202. CPT(TransformState) do_invert_compose(const TransformState *other) const;
  203. static bool r_detect_cycles(const TransformState *start_state,
  204. const TransformState *current_state,
  205. int length, UpdateSeq this_seq,
  206. CompositionCycleDesc *cycle_desc);
  207. static bool r_detect_reverse_cycles(const TransformState *start_state,
  208. const TransformState *current_state,
  209. int length, UpdateSeq this_seq,
  210. CompositionCycleDesc *cycle_desc);
  211. void release_new();
  212. void remove_cache_pointers();
  213. private:
  214. // This mutex protects _states. It also protects any modification
  215. // to the cache, which is encoded in _composition_cache and
  216. // _invert_composition_cache.
  217. static LightReMutex *_states_lock;
  218. typedef phash_set<const TransformState *, indirect_less_hash<const TransformState *> > States;
  219. static States *_states;
  220. static CPT(TransformState) _identity_state;
  221. static CPT(TransformState) _invalid_state;
  222. // This iterator records the entry corresponding to this TransformState
  223. // object in the above global set. We keep the iterator around so
  224. // we can remove it when the TransformState destructs.
  225. States::iterator _saved_entry;
  226. // This data structure manages the job of caching the composition of
  227. // two TransformStates. It's complicated because we have to be sure to
  228. // remove the entry if *either* of the input TransformStates destructs.
  229. // To implement this, we always record Composition entries in pairs,
  230. // one in each of the two involved TransformState objects.
  231. // The first element of the map is the object we compose with. This
  232. // is not reference counted within this map; instead we store a
  233. // companion pointer in the other object, and remove the references
  234. // explicitly when either object destructs.
  235. class Composition {
  236. public:
  237. INLINE Composition();
  238. INLINE Composition(const Composition &copy);
  239. // _result is reference counted if and only if it is not the same
  240. // pointer as this.
  241. const TransformState *_result;
  242. };
  243. typedef SimpleHashMap<const TransformState *, Composition, pointer_hash> CompositionCache;
  244. CompositionCache _composition_cache;
  245. CompositionCache _invert_composition_cache;
  246. // This is used to mark nodes as we visit them to detect cycles.
  247. UpdateSeq _cycle_detect;
  248. static UpdateSeq _last_cycle_detect;
  249. static PStatCollector _cache_update_pcollector;
  250. static PStatCollector _transform_compose_pcollector;
  251. static PStatCollector _transform_invert_pcollector;
  252. static PStatCollector _transform_calc_pcollector;
  253. static PStatCollector _transform_break_cycles_pcollector;
  254. static PStatCollector _transform_new_pcollector;
  255. static PStatCollector _transform_validate_pcollector;
  256. static PStatCollector _transform_hash_pcollector;
  257. static PStatCollector _node_counter;
  258. static PStatCollector _cache_counter;
  259. private:
  260. // This is the actual data within the TransformState.
  261. INLINE void check_hash() const;
  262. INLINE void check_singular() const;
  263. INLINE void check_components() const;
  264. INLINE void check_hpr() const;
  265. INLINE void check_quat() const;
  266. INLINE void check_norm_quat() const;
  267. INLINE void check_mat() const;
  268. INLINE void calc_hash();
  269. void do_calc_hash();
  270. void calc_singular();
  271. INLINE void calc_components();
  272. void do_calc_components();
  273. INLINE void calc_hpr();
  274. void do_calc_hpr();
  275. void calc_quat();
  276. void calc_norm_quat();
  277. INLINE void calc_mat();
  278. void do_calc_mat();
  279. INLINE void check_uniform_scale();
  280. INLINE void check_uniform_scale2d();
  281. INLINE void set_destructing();
  282. INLINE bool is_destructing() const;
  283. INLINE void consider_update_pstats(int old_referenced_bits) const;
  284. static void update_pstats(int old_referenced_bits, int new_referenced_bits);
  285. enum Flags {
  286. F_is_identity = 0x00000001,
  287. F_is_singular = 0x00000002,
  288. F_singular_known = 0x00000004, // set if we know F_is_singular
  289. F_components_given = 0x00000008,
  290. F_components_known = 0x00000010, // set if we know F_has_components
  291. F_has_components = 0x00000020,
  292. F_mat_known = 0x00000040, // set if _mat is defined
  293. F_is_invalid = 0x00000080,
  294. F_quat_given = 0x00000100,
  295. F_quat_known = 0x00000200, // set if _quat is defined
  296. F_hpr_given = 0x00000400,
  297. F_hpr_known = 0x00000800, // set if _hpr is defined
  298. F_uniform_scale = 0x00001000,
  299. F_identity_scale = 0x00002000,
  300. F_has_nonzero_shear = 0x00004000,
  301. F_is_destructing = 0x00008000,
  302. F_is_2d = 0x00010000,
  303. F_hash_known = 0x00020000,
  304. F_norm_quat_known = 0x00040000,
  305. };
  306. LPoint3f _pos;
  307. LVecBase3f _hpr, _scale, _shear;
  308. LQuaternionf _quat, _norm_quat;
  309. LMatrix4f _mat;
  310. LMatrix4f *_inv_mat;
  311. size_t _hash;
  312. unsigned int _flags;
  313. // This mutex protects _flags, and all of the above computed values.
  314. LightMutex _lock;
  315. static CacheStats _cache_stats;
  316. public:
  317. static void register_with_read_factory();
  318. virtual void write_datagram(BamWriter *manager, Datagram &dg);
  319. static PT(TypedWritableReferenceCount) change_this(TypedWritableReferenceCount *old_ptr, BamReader *manager);
  320. protected:
  321. static TypedWritable *make_from_bam(const FactoryParams &params);
  322. void fillin(DatagramIterator &scan, BamReader *manager);
  323. public:
  324. static TypeHandle get_class_type() {
  325. return _type_handle;
  326. }
  327. static void init_type() {
  328. NodeCachedReferenceCount::init_type();
  329. register_type(_type_handle, "TransformState",
  330. NodeCachedReferenceCount::get_class_type());
  331. }
  332. virtual TypeHandle get_type() const {
  333. return get_class_type();
  334. }
  335. virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
  336. private:
  337. static TypeHandle _type_handle;
  338. };
  339. INLINE ostream &operator << (ostream &out, const TransformState &state) {
  340. state.output(out);
  341. return out;
  342. }
  343. #include "transformState.I"
  344. #endif