Panda3D
|
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 }