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

panda/src/pgraph/geomNode.cxx

Go to the documentation of this file.
00001 // Filename: geomNode.cxx
00002 // Created by:  drose (23Feb02)
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 "geomNode.h"
00020 #include "geomTransformer.h"
00021 #include "sceneGraphReducer.h"
00022 #include "accumulatedAttribs.h"
00023 #include "bamReader.h"
00024 #include "bamWriter.h"
00025 #include "datagram.h"
00026 #include "datagramIterator.h"
00027 #include "indent.h"
00028 
00029 TypeHandle GeomNode::_type_handle;
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: GeomNode::CData::Copy Constructor
00033 //       Access: Public
00034 //  Description:
00035 ////////////////////////////////////////////////////////////////////
00036 GeomNode::CData::
00037 CData(const GeomNode::CData &copy) :
00038   _geoms(copy._geoms)
00039 {
00040 }
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: GeomNode::CData::make_copy
00044 //       Access: Public, Virtual
00045 //  Description:
00046 ////////////////////////////////////////////////////////////////////
00047 CycleData *GeomNode::CData::
00048 make_copy() const {
00049   return new CData(*this);
00050 }
00051 
00052 ////////////////////////////////////////////////////////////////////
00053 //     Function: GeomNode::CData::write_datagram
00054 //       Access: Public, Virtual
00055 //  Description: Writes the contents of this object to the datagram
00056 //               for shipping out to a Bam file.
00057 ////////////////////////////////////////////////////////////////////
00058 void GeomNode::CData::
00059 write_datagram(BamWriter *manager, Datagram &dg) const {
00060   int num_geoms = _geoms.size();
00061   nassertv(num_geoms == (int)(PN_uint16)num_geoms);
00062   dg.add_uint16(num_geoms);
00063   
00064   Geoms::const_iterator gi;
00065   for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) {
00066     const GeomEntry &entry = (*gi);
00067     manager->write_pointer(dg, entry._geom);
00068     manager->write_pointer(dg, entry._state);
00069   }
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: GeomNode::CData::complete_pointers
00074 //       Access: Public, Virtual
00075 //  Description: Receives an array of pointers, one for each time
00076 //               manager->read_pointer() was called in fillin().
00077 //               Returns the number of pointers processed.
00078 ////////////////////////////////////////////////////////////////////
00079 int GeomNode::CData::
00080 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00081   int pi = CycleData::complete_pointers(p_list, manager);
00082 
00083   // Get the geom and state pointers.
00084   Geoms::iterator gi;
00085   for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) {
00086     GeomEntry &entry = (*gi);
00087     entry._geom = DCAST(Geom, p_list[pi++]);
00088     entry._state = DCAST(RenderState, p_list[pi++]);
00089   }
00090 
00091   return pi;
00092 }
00093 
00094 ////////////////////////////////////////////////////////////////////
00095 //     Function: GeomNode::CData::fillin
00096 //       Access: Public, Virtual
00097 //  Description: This internal function is called by make_from_bam to
00098 //               read in all of the relevant data from the BamFile for
00099 //               the new GeomNode.
00100 ////////////////////////////////////////////////////////////////////
00101 void GeomNode::CData::
00102 fillin(DatagramIterator &scan, BamReader *manager) {
00103   int num_geoms = scan.get_uint16();
00104   // Read the list of geoms and states.  Push back a NULL for each one.
00105   _geoms.reserve(num_geoms);
00106   for (int i = 0; i < num_geoms; i++) {
00107     manager->read_pointer(scan);
00108     manager->read_pointer(scan);
00109     _geoms.push_back(GeomEntry(NULL, NULL));
00110   }
00111 }
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 //     Function: GeomNode::Constructor
00115 //       Access: Published
00116 //  Description:
00117 ////////////////////////////////////////////////////////////////////
00118 GeomNode::
00119 GeomNode(const string &name) :
00120   PandaNode(name)
00121 {
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: GeomNode::Copy Constructor
00126 //       Access: Protected
00127 //  Description:
00128 ////////////////////////////////////////////////////////////////////
00129 GeomNode::
00130 GeomNode(const GeomNode &copy) :
00131   PandaNode(copy),
00132   _cycler(copy._cycler)
00133 {
00134 }
00135 
00136 ////////////////////////////////////////////////////////////////////
00137 //     Function: GeomNode::Destructor
00138 //       Access: Public, Virtual
00139 //  Description:
00140 ////////////////////////////////////////////////////////////////////
00141 GeomNode::
00142 ~GeomNode() {
00143 }
00144 
00145 ////////////////////////////////////////////////////////////////////
00146 //     Function: GeomNode::make_copy
00147 //       Access: Public, Virtual
00148 //  Description: Returns a newly-allocated PandaNode that is a shallow
00149 //               copy of this one.  It will be a different pointer,
00150 //               but its internal data may or may not be shared with
00151 //               that of the original PandaNode.  No children will be
00152 //               copied.
00153 ////////////////////////////////////////////////////////////////////
00154 PandaNode *GeomNode::
00155 make_copy() const {
00156   return new GeomNode(*this);
00157 }
00158 
00159 ////////////////////////////////////////////////////////////////////
00160 //     Function: GeomNode::apply_attribs_to_vertices
00161 //       Access: Public, Virtual
00162 //  Description: Applies whatever attributes are specified in the
00163 //               AccumulatedAttribs object (and by the attrib_types
00164 //               bitmask) to the vertices on this node, if
00165 //               appropriate.  If this node uses geom arrays like a
00166 //               GeomNode, the supplied GeomTransformer may be used to
00167 //               unify shared arrays across multiple different nodes.
00168 //
00169 //               This is a generalization of xform().
00170 ////////////////////////////////////////////////////////////////////
00171 void GeomNode::
00172 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
00173                           GeomTransformer &transformer) {
00174   if (pgraph_cat.is_debug()) {
00175     pgraph_cat.debug()
00176       << "Transforming geometry.\n";
00177   }
00178 
00179   if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
00180     if (!attribs._transform->is_identity()) {
00181       transformer.transform_vertices(this, attribs._transform->get_mat());
00182     }
00183   }
00184   if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
00185     if (attribs._color != (const RenderAttrib *)NULL) {
00186       const ColorAttrib *ca = DCAST(ColorAttrib, attribs._color);
00187       if (ca->get_color_type() == ColorAttrib::T_flat) {
00188         transformer.set_color(this, ca->get_color());
00189       }
00190     }
00191   }
00192   if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
00193     if (attribs._color_scale != (const RenderAttrib *)NULL) {
00194       const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attribs._color_scale);
00195       if (csa->get_scale() != LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)) {
00196         transformer.transform_colors(this, csa->get_scale());
00197       }
00198     }
00199   }
00200   if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
00201     if (attribs._tex_matrix != (const RenderAttrib *)NULL) {
00202       const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, attribs._tex_matrix);
00203       if (tma->get_mat() != LMatrix4f::ident_mat()) {
00204         transformer.transform_texcoords(this, tma->get_mat());
00205       }
00206     }
00207   }
00208   if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
00209     if (!attribs._other->is_empty()) {
00210       transformer.apply_state(this, attribs._other);
00211     }
00212   }
00213 }
00214 
00215 ////////////////////////////////////////////////////////////////////
00216 //     Function: GeomNode::xform
00217 //       Access: Public, Virtual
00218 //  Description: Transforms the contents of this node by the indicated
00219 //               matrix, if it means anything to do so.  For most
00220 //               kinds of nodes, this does nothing.
00221 //
00222 //               For a GeomNode, this does the right thing, but it is
00223 //               better to use a GeomTransformer instead, since it
00224 //               will share the new arrays properly between different
00225 //               GeomNodes.
00226 ////////////////////////////////////////////////////////////////////
00227 void GeomNode::
00228 xform(const LMatrix4f &mat) {
00229   GeomTransformer transformer;
00230   transformer.transform_vertices(this, mat);
00231 }
00232 
00233 ////////////////////////////////////////////////////////////////////
00234 //     Function: GeomNode::combine_with
00235 //       Access: Public, Virtual
00236 //  Description: Collapses this node with the other node, if possible,
00237 //               and returns a pointer to the combined node, or NULL
00238 //               if the two nodes cannot safely be combined.
00239 //
00240 //               The return value may be this, other, or a new node
00241 //               altogether.
00242 //
00243 //               This function is called from GraphReducer::flatten(),
00244 //               and need not deal with children; its job is just to
00245 //               decide whether to collapse the two nodes and what the
00246 //               collapsed node should look like.
00247 ////////////////////////////////////////////////////////////////////
00248 PandaNode *GeomNode::
00249 combine_with(PandaNode *other) {
00250   if (is_exact_type(get_class_type()) &&
00251       other->is_exact_type(get_class_type())) {
00252     // Two GeomNodes can combine by moving Geoms from one to the other.
00253     GeomNode *gother = DCAST(GeomNode, other);
00254     add_geoms_from(gother);
00255     return this;
00256   }
00257 
00258   return PandaNode::combine_with(other);
00259 }
00260 
00261 ////////////////////////////////////////////////////////////////////
00262 //     Function: GeomNode::calc_tight_bounds
00263 //       Access: Public, Virtual
00264 //  Description: This is used to support
00265 //               NodePath::calc_tight_bounds().  It is not intended to
00266 //               be called directly, and it has nothing to do with the
00267 //               normal Panda bounding-volume computation.
00268 //
00269 //               If the node contains any geometry, this updates
00270 //               min_point and max_point to enclose its bounding box.
00271 //               found_any is to be set true if the node has any
00272 //               geometry at all, or left alone if it has none.  This
00273 //               method may be called over several nodes, so it may
00274 //               enter with min_point, max_point, and found_any
00275 //               already set.
00276 ////////////////////////////////////////////////////////////////////
00277 CPT(TransformState) GeomNode::
00278 calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
00279                   const TransformState *transform) const {
00280   CPT(TransformState) next_transform = 
00281     PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform);
00282 
00283   const LMatrix4f &mat = next_transform->get_mat();
00284   int num_geoms = get_num_geoms();
00285   for (int i = 0; i < num_geoms; i++) {
00286     Geom *geom = get_geom(i);
00287     Geom::VertexIterator vi = geom->make_vertex_iterator();
00288     int num_prims = geom->get_num_prims();
00289     
00290     for (int p = 0; p < num_prims; p++) {
00291       int length = geom->get_length(p);
00292       for (int v = 0; v < length; v++) {
00293         Vertexf vertex = geom->get_next_vertex(vi) * mat;
00294         
00295         if (found_any) {
00296           min_point.set(min(min_point[0], vertex[0]),
00297                         min(min_point[1], vertex[1]),
00298                         min(min_point[2], vertex[2]));
00299           max_point.set(max(max_point[0], vertex[0]),
00300                         max(max_point[1], vertex[1]),
00301                         max(max_point[2], vertex[2]));
00302         } else {
00303           min_point = vertex;
00304           max_point = vertex;
00305           found_any = true;
00306         }
00307       }
00308     }
00309   }
00310 
00311   return next_transform;
00312 }
00313 
00314 ////////////////////////////////////////////////////////////////////
00315 //     Function: GeomNode::add_geoms_from
00316 //       Access: Published
00317 //  Description: Copies the Geoms (and their associated RenderStates)
00318 //               from the indicated GeomNode into this one.
00319 ////////////////////////////////////////////////////////////////////
00320 void GeomNode::
00321 add_geoms_from(const GeomNode *other) {
00322   CDReader cdata_other(other->_cycler);
00323   CDWriter cdata(_cycler);
00324 
00325   Geoms::const_iterator gi;
00326   for (gi = cdata_other->_geoms.begin(); 
00327        gi != cdata_other->_geoms.end(); 
00328        ++gi) {
00329     const GeomEntry &entry = (*gi);
00330     cdata->_geoms.push_back(entry);
00331   }
00332   mark_bound_stale();
00333 }
00334 
00335 ////////////////////////////////////////////////////////////////////
00336 //     Function: GeomNode::write_geoms
00337 //       Access: Published
00338 //  Description: Writes a short description of all the Geoms in the
00339 //               node.
00340 ////////////////////////////////////////////////////////////////////
00341 void GeomNode::
00342 write_geoms(ostream &out, int indent_level) const {
00343   CDReader cdata(_cycler);
00344   write(out, indent_level);
00345   Geoms::const_iterator gi;
00346   for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00347     const GeomEntry &entry = (*gi);
00348     indent(out, indent_level + 2) 
00349       << *entry._geom << " " << *entry._state << "\n";
00350   }
00351 }
00352 
00353 ////////////////////////////////////////////////////////////////////
00354 //     Function: GeomNode::write_verbose
00355 //       Access: Published
00356 //  Description: Writes a detailed description of all the Geoms in the
00357 //               node.
00358 ////////////////////////////////////////////////////////////////////
00359 void GeomNode::
00360 write_verbose(ostream &out, int indent_level) const {
00361   CDReader cdata(_cycler);
00362   write(out, indent_level);
00363   Geoms::const_iterator gi;
00364   for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00365     const GeomEntry &entry = (*gi);
00366     indent(out, indent_level + 2) 
00367       << *entry._geom << " " << *entry._state << "\n";
00368     entry._geom->write_verbose(out, indent_level + 4);
00369   }
00370 }
00371 
00372 ////////////////////////////////////////////////////////////////////
00373 //     Function: GeomNode::output
00374 //       Access: Public, Virtual
00375 //  Description: 
00376 ////////////////////////////////////////////////////////////////////
00377 void GeomNode::
00378 output(ostream &out) const {
00379   PandaNode::output(out);
00380   out << " (" << get_num_geoms() << " geoms)";
00381 }
00382 
00383 ////////////////////////////////////////////////////////////////////
00384 //     Function: GeomNode::is_geom_node
00385 //       Access: Public, Virtual
00386 //  Description: A simple downcast check.  Returns true if this kind
00387 //               of node happens to inherit from GeomNode, false
00388 //               otherwise.
00389 //
00390 //               This is provided as a a faster alternative to calling
00391 //               is_of_type(GeomNode::get_class_type()), since this
00392 //               test is so important to rendering.
00393 ////////////////////////////////////////////////////////////////////
00394 bool GeomNode::
00395 is_geom_node() const {
00396   return true;
00397 }
00398 
00399 ////////////////////////////////////////////////////////////////////
00400 //     Function: GeomNode::recompute_internal_bound
00401 //       Access: Protected, Virtual
00402 //  Description: Called when needed to recompute the node's
00403 //               _internal_bound object.  Nodes that contain anything
00404 //               of substance should redefine this to do the right
00405 //               thing.
00406 ////////////////////////////////////////////////////////////////////
00407 BoundingVolume *GeomNode::
00408 recompute_internal_bound() {
00409   // First, get ourselves a fresh, empty bounding volume.
00410   BoundingVolume *bound = PandaNode::recompute_internal_bound();
00411   nassertr(bound != (BoundingVolume *)NULL, bound);
00412 
00413   // Now actually compute the bounding volume by putting it around all
00414   // of our geoms' bounding volumes.
00415   pvector<const BoundingVolume *> child_volumes;
00416 
00417   CDReader cdata(_cycler);
00418   Geoms::const_iterator gi;
00419   for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
00420     const GeomEntry &entry = (*gi);
00421     child_volumes.push_back(&entry._geom->get_bound());
00422   }
00423 
00424   const BoundingVolume **child_begin = &child_volumes[0];
00425   const BoundingVolume **child_end = child_begin + child_volumes.size();
00426 
00427   bound->around(child_begin, child_end);
00428   return bound;
00429 }
00430 
00431 ////////////////////////////////////////////////////////////////////
00432 //     Function: GeomNode::register_with_read_factory
00433 //       Access: Public, Static
00434 //  Description: Tells the BamReader how to create objects of type
00435 //               GeomNode.
00436 ////////////////////////////////////////////////////////////////////
00437 void GeomNode::
00438 register_with_read_factory() {
00439   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00440 }
00441 
00442 ////////////////////////////////////////////////////////////////////
00443 //     Function: GeomNode::write_datagram
00444 //       Access: Public, Virtual
00445 //  Description: Writes the contents of this object to the datagram
00446 //               for shipping out to a Bam file.
00447 ////////////////////////////////////////////////////////////////////
00448 void GeomNode::
00449 write_datagram(BamWriter *manager, Datagram &dg) {
00450   PandaNode::write_datagram(manager, dg);
00451   manager->write_cdata(dg, _cycler);
00452 }
00453 
00454 ////////////////////////////////////////////////////////////////////
00455 //     Function: GeomNode::make_from_bam
00456 //       Access: Protected, Static
00457 //  Description: This function is called by the BamReader's factory
00458 //               when a new object of type GeomNode is encountered
00459 //               in the Bam file.  It should create the GeomNode
00460 //               and extract its information from the file.
00461 ////////////////////////////////////////////////////////////////////
00462 TypedWritable *GeomNode::
00463 make_from_bam(const FactoryParams &params) {
00464   GeomNode *node = new GeomNode("");
00465   DatagramIterator scan;
00466   BamReader *manager;
00467 
00468   parse_params(params, scan, manager);
00469   node->fillin(scan, manager);
00470 
00471   return node;
00472 }
00473 
00474 ////////////////////////////////////////////////////////////////////
00475 //     Function: GeomNode::fillin
00476 //       Access: Protected
00477 //  Description: This internal function is called by make_from_bam to
00478 //               read in all of the relevant data from the BamFile for
00479 //               the new GeomNode.
00480 ////////////////////////////////////////////////////////////////////
00481 void GeomNode::
00482 fillin(DatagramIterator &scan, BamReader *manager) {
00483   PandaNode::fillin(scan, manager);
00484   manager->read_cdata(scan, _cycler);
00485 }

Generated on Fri May 2 00:41:40 2003 for Panda by doxygen1.3