Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/builder/builder.cxx

Go to the documentation of this file.
00001 // Filename: builder.cxx
00002 // Created by:  drose (09Sep97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "builderFuncs.h"
00020 #include "builderMisc.h"
00021 #include "notify.h"
00022 #include "pmap.h"
00023 #include "builder.h"
00024 #include "pandaNode.h"
00025 #include "geomNode.h"
00026 #include "dcast.h"
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: Builder::Constructor
00030 //       Access: Public
00031 //  Description:
00032 ////////////////////////////////////////////////////////////////////
00033 Builder::
00034 Builder() {
00035   _bi = _buckets.end();
00036 }
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: Builder::Destructor
00040 //       Access: Public
00041 //  Description:
00042 ////////////////////////////////////////////////////////////////////
00043 Builder::
00044 ~Builder() {
00045   // Free all the buckets we allocated.  We allocated 'em, we free
00046   // 'em.
00047   Buckets::iterator bi;
00048   for (bi = _buckets.begin();
00049        bi != _buckets.end();
00050        ++bi) {
00051     BuilderBucket *bucket = (*bi).get_bucket();
00052     delete bucket;
00053   }
00054 }
00055 
00056 
00057 // We use the NodeMap class to build up a map of Nodes to GeomNodes.
00058 // There may be several buckets that point to the same Node; these
00059 // should all be given the same GeomNode, when possible.
00060 
00061 // However, if two buckets have different sets of scene graph
00062 // properties--that is, the _trans member is different--they must be
00063 // given separate GeomNodes.
00064 
00065 // Furthermore, it's possible to name each bucket.  If two buckets
00066 // with the same Node pointer have different names, then they should
00067 // be given two different GeomNodes.
00068 
00069 class NodeMap : public Namable {
00070 public:
00071   NodeMap(PandaNode *node, const BuilderBucket *bucket)
00072     : _node(node), _bucket(bucket) { }
00073 
00074   bool operator < (const NodeMap &other) const {
00075     if (_node != other._node) {
00076       return _node < other._node;
00077     }
00078     if (_bucket->get_name() != other._bucket->get_name()) {
00079       return _bucket->get_name() < other._bucket->get_name();
00080     }
00081     return 0;
00082   }
00083 
00084   PandaNode *_node;
00085 
00086   // Although a bucket pointer is stored here in the NodeMap class,
00087   // you should not use it except to extract the name and/or the
00088   // _trans member.  Remember, this bucket pointer stands for any of
00089   // possibly several bucket pointers, all different, except that they
00090   // share the same name.
00091   const BuilderBucket *_bucket;
00092 };
00093 
00094 
00095 
00096 ////////////////////////////////////////////////////////////////////
00097 //     Function: Builder::build
00098 //       Access: Public
00099 //  Description: Creates Geoms for all the primitives added to all
00100 //               buckets, and adds them where appropriate to place
00101 //               them in the scene graph under their respective
00102 //               parents, and/or returns a single GeomNode that
00103 //               contains all geometry whose bucket did not reference
00104 //               a particular scene graph node to parent them to.
00105 //
00106 //               If a bucket's _node pointer was a GeomNode, the
00107 //               geometry will be added directly to that node.  If the
00108 //               _node pointer was any other kind of node, a GeomNode
00109 //               will be created and parented to that node, and its
00110 //               name will be the name of the bucket.  In this case,
00111 //               the name of the bucket can also be used to different
00112 //               nodes: if two buckets reference the same node, but
00113 //               have different names, then two different GeomNodes
00114 //               are created, one with each name.
00115 ////////////////////////////////////////////////////////////////////
00116 GeomNode *Builder::
00117 build(const string &default_name) {
00118   typedef pmap<NodeMap, GeomNode *> GeomNodeMap;
00119   GeomNodeMap geom_nodes;
00120 
00121   // First, build all the Geoms and create GeomNodes for them.  Each
00122   // unique Node gets its own GeomNode.  If the Node is itself a
00123   // GeomNode, that GeomNode is used directly.
00124   Buckets::iterator i;
00125   for (i = _buckets.begin();
00126        i != _buckets.end();
00127        ++i) {
00128     BuilderBucket *bucket = (*i).get_bucket();
00129     PandaNode *node = bucket->_node;
00130     //    const string &name = bucket->get_name();
00131     GeomNode *geom_node = NULL;
00132 
00133     if (node!=NULL && node->is_of_type(GeomNode::get_class_type())) {
00134       // The node is a GeomNode.  In this case, we simply use that
00135       // node.  We can't separate them out by name in this case; we'll
00136       // just assign to it the first nonempty name we encounter.
00137       geom_node = DCAST(GeomNode, node);
00138 
00139       // Since the caller already created this GeomNode and passed it
00140       // in, we'll leave it up to the caller to name the node and set
00141       // up the state transitions leading into it.
00142 
00143     } else {
00144       // The node is not a GeomNode, so look it up in the map.
00145       GeomNodeMap::iterator f = geom_nodes.find(NodeMap(node, bucket));
00146       if (f != geom_nodes.end()) {
00147         geom_node = (*f).second;
00148 
00149       } else {
00150         // No such node/name combination.  Create a new one.
00151         geom_node = bucket->make_geom_node();
00152         if (geom_node != NULL) {
00153           geom_nodes[NodeMap(node, bucket)] = geom_node;
00154         }
00155       }
00156     }
00157 
00158     if (geom_node != NULL) {
00159       (*i).build(geom_node);
00160     }
00161   }
00162 
00163   // Now go through and parent the geom_nodes under their respective
00164   // group nodes.  Save out the geom_node associated with a NULL Node;
00165   // this one is returned from this function.
00166 
00167   GeomNode *base_geom_node = NULL;
00168 
00169   GeomNodeMap::iterator gi;
00170 
00171   for (gi = geom_nodes.begin();
00172        gi != geom_nodes.end();
00173        ++gi) {
00174     const NodeMap &nm = (*gi).first;
00175     GeomNode *geom_node = (*gi).second;
00176 
00177     PandaNode *node = nm._node;
00178     const string &name = nm._bucket->get_name();
00179 
00180     // Assign the name to the geom, if it doesn't have one already.
00181     if (!geom_node->has_name()) {
00182       if (!name.empty()) {
00183         geom_node->set_name(name);
00184 
00185       } else if (!default_name.empty()) {
00186         geom_node->set_name(default_name);
00187       }
00188     }
00189 
00190     // Only reparent the geom_node if it has no parent already.
00191     int num_parents = geom_node->get_num_parents();
00192     if (num_parents == 0) {
00193       if (geom_node->get_num_geoms() == 0) {
00194         // If there was nothing added, never mind.
00195         delete geom_node;
00196 
00197       } else if (node==NULL) {
00198         nassertr(base_geom_node == NULL, NULL);
00199         base_geom_node = geom_node;
00200 
00201       } else {
00202         node->add_child(geom_node);
00203       }
00204     }
00205   }
00206 
00207   return base_geom_node;
00208 }
00209 
00210 
00211 ////////////////////////////////////////////////////////////////////
00212 //     Function: Builder::add_bucket
00213 //       Access: Protected
00214 //  Description: Adds a new BuilderBucket just like the given one to
00215 //               the set of all used BuilderBuckets, and makes it the
00216 //               current bucket.  Future primitives will be added to
00217 //               this bucket.
00218 ////////////////////////////////////////////////////////////////////
00219 void Builder::
00220 add_bucket(const BuilderBucket &bucket) {
00221   // Optimization: maybe it's the same bucket we used last time.
00222   if (_bi != _buckets.end() &&
00223       (*_bi) == BuilderBucketNode((BuilderBucket *)&bucket)) {
00224     return;
00225   }
00226 
00227   // Nope.  Look again.
00228   _bi = _buckets.find((BuilderBucket *)&bucket);
00229   if (_bi == _buckets.end()) {
00230     BuilderBucket *new_bucket = bucket.make_copy();
00231     _bi = _buckets.insert(new_bucket).first;
00232   }
00233 }
00234 

Generated on Fri May 2 00:34:35 2003 for Panda by doxygen1.3