builder.cxx 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Filename: builder.cxx
  2. // Created by: drose (09Sep97)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
  8. //
  9. // All use of this software is subject to the terms of the Panda 3d
  10. // Software license. You should have received a copy of this license
  11. // along with this source code; you will also find a current copy of
  12. // the license at http://www.panda3d.org/license.txt .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. #include "builderFuncs.h"
  19. #include "builderMisc.h"
  20. #include "notify.h"
  21. #include "pmap.h"
  22. #include "builder.h"
  23. #include "pandaNode.h"
  24. #include "geomNode.h"
  25. #include "dcast.h"
  26. ////////////////////////////////////////////////////////////////////
  27. // Function: Builder::Constructor
  28. // Access: Public
  29. // Description:
  30. ////////////////////////////////////////////////////////////////////
  31. Builder::
  32. Builder() {
  33. _bi = _buckets.end();
  34. }
  35. ////////////////////////////////////////////////////////////////////
  36. // Function: Builder::Destructor
  37. // Access: Public
  38. // Description:
  39. ////////////////////////////////////////////////////////////////////
  40. Builder::
  41. ~Builder() {
  42. // Free all the buckets we allocated. We allocated 'em, we free
  43. // 'em.
  44. Buckets::iterator bi;
  45. for (bi = _buckets.begin();
  46. bi != _buckets.end();
  47. ++bi) {
  48. BuilderBucket *bucket = (*bi).get_bucket();
  49. delete bucket;
  50. }
  51. }
  52. // We use the NodeMap class to build up a map of Nodes to GeomNodes.
  53. // There may be several buckets that point to the same Node; these
  54. // should all be given the same GeomNode, when possible.
  55. // However, if two buckets have different sets of scene graph
  56. // properties--that is, the _trans member is different--they must be
  57. // given separate GeomNodes.
  58. // Furthermore, it's possible to name each bucket. If two buckets
  59. // with the same Node pointer have different names, then they should
  60. // be given two different GeomNodes.
  61. class NodeMap : public Namable {
  62. public:
  63. NodeMap(PandaNode *node, const BuilderBucket *bucket)
  64. : _node(node), _bucket(bucket) { }
  65. bool operator < (const NodeMap &other) const {
  66. if (_node != other._node) {
  67. return _node < other._node;
  68. }
  69. if (_bucket->get_name() != other._bucket->get_name()) {
  70. return _bucket->get_name() < other._bucket->get_name();
  71. }
  72. return 0;
  73. }
  74. PandaNode *_node;
  75. // Although a bucket pointer is stored here in the NodeMap class,
  76. // you should not use it except to extract the name and/or the
  77. // _trans member. Remember, this bucket pointer stands for any of
  78. // possibly several bucket pointers, all different, except that they
  79. // share the same name.
  80. const BuilderBucket *_bucket;
  81. };
  82. ////////////////////////////////////////////////////////////////////
  83. // Function: Builder::build
  84. // Access: Public
  85. // Description: Creates Geoms for all the primitives added to all
  86. // buckets, and adds them where appropriate to place
  87. // them in the scene graph under their respective
  88. // parents, and/or returns a single GeomNode that
  89. // contains all geometry whose bucket did not reference
  90. // a particular scene graph node to parent them to.
  91. //
  92. // If a bucket's _node pointer was a GeomNode, the
  93. // geometry will be added directly to that node. If the
  94. // _node pointer was any other kind of node, a GeomNode
  95. // will be created and parented to that node, and its
  96. // name will be the name of the bucket. In this case,
  97. // the name of the bucket can also be used to different
  98. // nodes: if two buckets reference the same node, but
  99. // have different names, then two different GeomNodes
  100. // are created, one with each name.
  101. ////////////////////////////////////////////////////////////////////
  102. GeomNode *Builder::
  103. build(const string &default_name) {
  104. typedef pmap<NodeMap, GeomNode *> GeomNodeMap;
  105. GeomNodeMap geom_nodes;
  106. // First, build all the Geoms and create GeomNodes for them. Each
  107. // unique Node gets its own GeomNode. If the Node is itself a
  108. // GeomNode, that GeomNode is used directly.
  109. Buckets::iterator i;
  110. for (i = _buckets.begin();
  111. i != _buckets.end();
  112. ++i) {
  113. BuilderBucket *bucket = (*i).get_bucket();
  114. PandaNode *node = bucket->_node;
  115. // const string &name = bucket->get_name();
  116. GeomNode *geom_node = NULL;
  117. if (node!=NULL && node->is_of_type(GeomNode::get_class_type())) {
  118. // The node is a GeomNode. In this case, we simply use that
  119. // node. We can't separate them out by name in this case; we'll
  120. // just assign to it the first nonempty name we encounter.
  121. geom_node = DCAST(GeomNode, node);
  122. // Since the caller already created this GeomNode and passed it
  123. // in, we'll leave it up to the caller to name the node and set
  124. // up the state transitions leading into it.
  125. } else {
  126. // The node is not a GeomNode, so look it up in the map.
  127. GeomNodeMap::iterator f = geom_nodes.find(NodeMap(node, bucket));
  128. if (f != geom_nodes.end()) {
  129. geom_node = (*f).second;
  130. } else {
  131. // No such node/name combination. Create a new one.
  132. geom_node = bucket->make_geom_node();
  133. if (geom_node != NULL) {
  134. geom_nodes[NodeMap(node, bucket)] = geom_node;
  135. }
  136. }
  137. }
  138. if (geom_node != NULL) {
  139. (*i).build(geom_node);
  140. }
  141. }
  142. // Now go through and parent the geom_nodes under their respective
  143. // group nodes. Save out the geom_node associated with a NULL Node;
  144. // this one is returned from this function.
  145. GeomNode *base_geom_node = NULL;
  146. GeomNodeMap::iterator gi;
  147. for (gi = geom_nodes.begin();
  148. gi != geom_nodes.end();
  149. ++gi) {
  150. const NodeMap &nm = (*gi).first;
  151. GeomNode *geom_node = (*gi).second;
  152. PandaNode *node = nm._node;
  153. const string &name = nm._bucket->get_name();
  154. // Assign the name to the geom, if it doesn't have one already.
  155. if (!geom_node->has_name()) {
  156. if (!name.empty()) {
  157. geom_node->set_name(name);
  158. } else if (!default_name.empty()) {
  159. geom_node->set_name(default_name);
  160. }
  161. }
  162. // Only reparent the geom_node if it has no parent already.
  163. int num_parents = geom_node->get_num_parents();
  164. if (num_parents == 0) {
  165. if (geom_node->get_num_geoms() == 0) {
  166. // If there was nothing added, never mind.
  167. delete geom_node;
  168. } else if (node==NULL) {
  169. nassertr(base_geom_node == NULL, NULL);
  170. base_geom_node = geom_node;
  171. } else {
  172. node->add_child(geom_node);
  173. }
  174. }
  175. }
  176. return base_geom_node;
  177. }
  178. ////////////////////////////////////////////////////////////////////
  179. // Function: Builder::add_bucket
  180. // Access: Protected
  181. // Description: Adds a new BuilderBucket just like the given one to
  182. // the set of all used BuilderBuckets, and makes it the
  183. // current bucket. Future primitives will be added to
  184. // this bucket.
  185. ////////////////////////////////////////////////////////////////////
  186. void Builder::
  187. add_bucket(const BuilderBucket &bucket) {
  188. // Optimization: maybe it's the same bucket we used last time.
  189. if (_bi != _buckets.end() &&
  190. (*_bi) == BuilderBucketNode((BuilderBucket *)&bucket)) {
  191. return;
  192. }
  193. // Nope. Look again.
  194. _bi = _buckets.find((BuilderBucket *)&bucket);
  195. if (_bi == _buckets.end()) {
  196. BuilderBucket *new_bucket = bucket.make_copy();
  197. _bi = _buckets.insert(new_bucket).first;
  198. }
  199. }