Panda3D

partBundleNode.cxx

00001 // Filename: partBundleNode.cxx
00002 // Created by:  drose (06Mar02)
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 #include "partBundleNode.h"
00016 #include "datagram.h"
00017 #include "datagramIterator.h"
00018 #include "bamReader.h"
00019 #include "bamWriter.h"
00020 #include "sceneGraphReducer.h"
00021 
00022 TypeHandle PartBundleNode::_type_handle;
00023 
00024 ////////////////////////////////////////////////////////////////////
00025 //     Function: PartBundleNode::Destructor
00026 //       Access: Public, Virtual
00027 //  Description: 
00028 ////////////////////////////////////////////////////////////////////
00029 PartBundleNode::
00030 ~PartBundleNode() {
00031   Bundles::iterator bi;
00032   for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
00033     (*bi)->get_bundle()->remove_node(this);
00034   }
00035 }
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: PartBundleNode::apply_attribs_to_vertices
00039 //       Access: Public, Virtual
00040 //  Description: Applies whatever attributes are specified in the
00041 //               AccumulatedAttribs object (and by the attrib_types
00042 //               bitmask) to the vertices on this node, if
00043 //               appropriate.  If this node uses geom arrays like a
00044 //               GeomNode, the supplied GeomTransformer may be used to
00045 //               unify shared arrays across multiple different nodes.
00046 //
00047 //               This is a generalization of xform().
00048 ////////////////////////////////////////////////////////////////////
00049 void PartBundleNode::
00050 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
00051                           GeomTransformer &transformer) {
00052   if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
00053     Bundles::iterator bi;
00054     for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
00055       PT(PartBundleHandle) handle = (*bi);
00056       PartBundle *bundle = handle->get_bundle();
00057       PT(PartBundle) new_bundle = bundle->apply_transform(attribs._transform);
00058       update_bundle(handle, new_bundle);
00059     }
00060 
00061     // Make sure the Geom bounding volumes get recomputed due to this
00062     // update.
00063     r_mark_geom_bounds_stale(Thread::get_current_thread());
00064   }
00065 }
00066 
00067 ////////////////////////////////////////////////////////////////////
00068 //     Function: PartBundleNode::xform
00069 //       Access: Public, Virtual
00070 //  Description: Transforms the contents of this PandaNode by the
00071 //               indicated matrix, if it means anything to do so.  For
00072 //               most kinds of PandaNodes, this does nothing.
00073 ////////////////////////////////////////////////////////////////////
00074 void PartBundleNode::
00075 xform(const LMatrix4 &mat) {
00076   // With plain xform(), we can't attempt to share bundles across
00077   // different nodes.  Better to use apply_attribs_to_vertices(),
00078   // instead.
00079 
00080   if (mat.almost_equal(LMatrix4::ident_mat())) {
00081     // Don't bother.
00082     return;
00083   }
00084 
00085   Bundles::iterator bi;
00086   for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
00087     PT(PartBundleHandle) handle = (*bi);
00088     PartBundle *bundle = handle->get_bundle();
00089     if (bundle->get_num_nodes() > 1) {
00090       PT(PartBundle) new_bundle = DCAST(PartBundle, bundle->copy_subgraph());
00091       update_bundle(handle, new_bundle);
00092       bundle = new_bundle;
00093     }
00094     bundle->xform(mat);
00095   }
00096 }
00097 
00098 ////////////////////////////////////////////////////////////////////
00099 //     Function: PartBundleNode::add_bundle
00100 //       Access: Protected
00101 //  Description: 
00102 ////////////////////////////////////////////////////////////////////
00103 void PartBundleNode::
00104 add_bundle(PartBundle *bundle) {
00105   PT(PartBundleHandle) handle = new PartBundleHandle(bundle);
00106   add_bundle_handle(handle);
00107 }
00108 
00109 ////////////////////////////////////////////////////////////////////
00110 //     Function: PartBundleNode::add_bundle_handle
00111 //       Access: Protected
00112 //  Description: 
00113 ////////////////////////////////////////////////////////////////////
00114 void PartBundleNode::
00115 add_bundle_handle(PartBundleHandle *handle) {
00116   Bundles::iterator bi = find(_bundles.begin(), _bundles.end(), handle);
00117   if (bi != _bundles.end()) {
00118     // This handle is already within the node.
00119     return;
00120   }
00121 
00122   _bundles.push_back(handle);
00123   handle->get_bundle()->add_node(this);
00124 }
00125 
00126 ////////////////////////////////////////////////////////////////////
00127 //     Function: PartBundleNode::steal_bundles
00128 //       Access: Protected
00129 //  Description: Moves the PartBundles from the other node onto this
00130 //               one.
00131 ////////////////////////////////////////////////////////////////////
00132 void PartBundleNode::
00133 steal_bundles(PartBundleNode *other) {
00134   if (other == this) {
00135     return;
00136   }
00137 
00138   Bundles::iterator bi;
00139   for (bi = other->_bundles.begin(); bi != other->_bundles.end(); ++bi) {
00140     PartBundleHandle *handle = (*bi);
00141     handle->get_bundle()->remove_node(other);
00142     add_bundle_handle(handle);
00143   }
00144   other->_bundles.clear();
00145 }
00146 
00147 ////////////////////////////////////////////////////////////////////
00148 //     Function: PartBundleNode::update_bundle
00149 //       Access: Protected, Virtual
00150 //  Description: Replaces the contents of the indicated
00151 //               PartBundleHandle (presumably stored within this node)
00152 //               with new_bundle.
00153 ////////////////////////////////////////////////////////////////////
00154 void PartBundleNode::
00155 update_bundle(PartBundleHandle *old_bundle_handle, PartBundle *new_bundle) {
00156   PartBundle *old_bundle = old_bundle_handle->get_bundle();
00157   old_bundle->remove_node(this);
00158   old_bundle_handle->set_bundle(new_bundle);
00159   new_bundle->add_node(this);
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: PartBundleNode::write_datagram
00164 //       Access: Public, Virtual
00165 //  Description: Writes the contents of this object to the datagram
00166 //               for shipping out to a Bam file.
00167 ////////////////////////////////////////////////////////////////////
00168 void PartBundleNode::
00169 write_datagram(BamWriter *manager, Datagram &dg) {
00170   PandaNode::write_datagram(manager, dg);
00171 
00172   dg.add_uint16(_bundles.size());
00173   Bundles::iterator bi;
00174   for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
00175     manager->write_pointer(dg, (*bi)->get_bundle());
00176   }
00177 }
00178 
00179 ////////////////////////////////////////////////////////////////////
00180 //     Function: PartBundleNode::complete_pointers
00181 //       Access: Public, Virtual
00182 //  Description: Receives an array of pointers, one for each time
00183 //               manager->read_pointer() was called in fillin().
00184 //               Returns the number of pointers processed.
00185 ////////////////////////////////////////////////////////////////////
00186 int PartBundleNode::
00187 complete_pointers(TypedWritable **p_list, BamReader* manager) {
00188   int pi = PandaNode::complete_pointers(p_list, manager);
00189 
00190   Bundles::iterator bi;
00191   for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
00192     PT(PartBundle) bundle = DCAST(PartBundle, p_list[pi++]);
00193     bundle->add_node(this);
00194     (*bi) = new PartBundleHandle(bundle);
00195   }
00196 
00197   return pi;
00198 }
00199 
00200 ////////////////////////////////////////////////////////////////////
00201 //     Function: PartBundleNode::fillin
00202 //       Access: Protected
00203 //  Description: This internal function is called by make_from_bam to
00204 //               read in all of the relevant data from the BamFile for
00205 //               the new PandaNode.
00206 ////////////////////////////////////////////////////////////////////
00207 void PartBundleNode::
00208 fillin(DatagramIterator &scan, BamReader* manager) {
00209   PandaNode::fillin(scan, manager);
00210 
00211   int num_bundles = 1;
00212   if (manager->get_file_minor_ver() >= 5) {
00213     num_bundles = scan.get_uint16();
00214   }
00215 
00216   nassertv(num_bundles >= 1);
00217 
00218   // Bundle 0.  We already have a slot for this one.
00219   manager->read_pointer(scan);
00220 
00221   // Remaining bundles.  Push a new slot for each one.
00222   for (int i = 1; i < num_bundles; ++i) {
00223     manager->read_pointer(scan);
00224     _bundles.push_back(NULL);
00225   }
00226 }
 All Classes Functions Variables Enumerations