Panda3D
partBundleNode.cxx
1 // Filename: partBundleNode.cxx
2 // Created by: drose (06Mar02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "partBundleNode.h"
16 #include "datagram.h"
17 #include "datagramIterator.h"
18 #include "bamReader.h"
19 #include "bamWriter.h"
20 #include "sceneGraphReducer.h"
21 
22 TypeHandle PartBundleNode::_type_handle;
23 
24 ////////////////////////////////////////////////////////////////////
25 // Function: PartBundleNode::Destructor
26 // Access: Public, Virtual
27 // Description:
28 ////////////////////////////////////////////////////////////////////
29 PartBundleNode::
30 ~PartBundleNode() {
31  Bundles::iterator bi;
32  for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
33  (*bi)->get_bundle()->remove_node(this);
34  }
35 }
36 
37 ////////////////////////////////////////////////////////////////////
38 // Function: PartBundleNode::apply_attribs_to_vertices
39 // Access: Public, Virtual
40 // Description: Applies whatever attributes are specified in the
41 // AccumulatedAttribs object (and by the attrib_types
42 // bitmask) to the vertices on this node, if
43 // appropriate. If this node uses geom arrays like a
44 // GeomNode, the supplied GeomTransformer may be used to
45 // unify shared arrays across multiple different nodes.
46 //
47 // This is a generalization of xform().
48 ////////////////////////////////////////////////////////////////////
50 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
51  GeomTransformer &transformer) {
52  if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
53  Bundles::iterator bi;
54  for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
55  PT(PartBundleHandle) handle = (*bi);
56  PartBundle *bundle = handle->get_bundle();
57  PT(PartBundle) new_bundle = bundle->apply_transform(attribs._transform);
58  update_bundle(handle, new_bundle);
59  }
60 
61  // Make sure the Geom bounding volumes get recomputed due to this
62  // update.
63  r_mark_geom_bounds_stale(Thread::get_current_thread());
64  }
65 }
66 
67 ////////////////////////////////////////////////////////////////////
68 // Function: PartBundleNode::xform
69 // Access: Public, Virtual
70 // Description: Transforms the contents of this PandaNode by the
71 // indicated matrix, if it means anything to do so. For
72 // most kinds of PandaNodes, this does nothing.
73 ////////////////////////////////////////////////////////////////////
75 xform(const LMatrix4 &mat) {
76  // With plain xform(), we can't attempt to share bundles across
77  // different nodes. Better to use apply_attribs_to_vertices(),
78  // instead.
79 
80  if (mat.almost_equal(LMatrix4::ident_mat())) {
81  // Don't bother.
82  return;
83  }
84 
85  Bundles::iterator bi;
86  for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
87  PT(PartBundleHandle) handle = (*bi);
88  PartBundle *bundle = handle->get_bundle();
89  if (bundle->get_num_nodes() > 1) {
90  PT(PartBundle) new_bundle = DCAST(PartBundle, bundle->copy_subgraph());
91  update_bundle(handle, new_bundle);
92  bundle = new_bundle;
93  }
94  bundle->xform(mat);
95  }
96 }
97 
98 ////////////////////////////////////////////////////////////////////
99 // Function: PartBundleNode::add_bundle
100 // Access: Protected
101 // Description:
102 ////////////////////////////////////////////////////////////////////
103 void PartBundleNode::
104 add_bundle(PartBundle *bundle) {
105  PT(PartBundleHandle) handle = new PartBundleHandle(bundle);
106  add_bundle_handle(handle);
107 }
108 
109 ////////////////////////////////////////////////////////////////////
110 // Function: PartBundleNode::add_bundle_handle
111 // Access: Protected
112 // Description:
113 ////////////////////////////////////////////////////////////////////
114 void PartBundleNode::
115 add_bundle_handle(PartBundleHandle *handle) {
116  Bundles::iterator bi = find(_bundles.begin(), _bundles.end(), handle);
117  if (bi != _bundles.end()) {
118  // This handle is already within the node.
119  return;
120  }
121 
122  _bundles.push_back(handle);
123  handle->get_bundle()->add_node(this);
124 }
125 
126 ////////////////////////////////////////////////////////////////////
127 // Function: PartBundleNode::steal_bundles
128 // Access: Protected
129 // Description: Moves the PartBundles from the other node onto this
130 // one.
131 ////////////////////////////////////////////////////////////////////
132 void PartBundleNode::
133 steal_bundles(PartBundleNode *other) {
134  if (other == this) {
135  return;
136  }
137 
138  Bundles::iterator bi;
139  for (bi = other->_bundles.begin(); bi != other->_bundles.end(); ++bi) {
140  PartBundleHandle *handle = (*bi);
141  handle->get_bundle()->remove_node(other);
142  add_bundle_handle(handle);
143  }
144  other->_bundles.clear();
145 }
146 
147 ////////////////////////////////////////////////////////////////////
148 // Function: PartBundleNode::update_bundle
149 // Access: Protected, Virtual
150 // Description: Replaces the contents of the indicated
151 // PartBundleHandle (presumably stored within this node)
152 // with new_bundle.
153 ////////////////////////////////////////////////////////////////////
154 void PartBundleNode::
155 update_bundle(PartBundleHandle *old_bundle_handle, PartBundle *new_bundle) {
156  PartBundle *old_bundle = old_bundle_handle->get_bundle();
157  old_bundle->remove_node(this);
158  old_bundle_handle->set_bundle(new_bundle);
159  new_bundle->add_node(this);
160 }
161 
162 ////////////////////////////////////////////////////////////////////
163 // Function: PartBundleNode::write_datagram
164 // Access: Public, Virtual
165 // Description: Writes the contents of this object to the datagram
166 // for shipping out to a Bam file.
167 ////////////////////////////////////////////////////////////////////
168 void PartBundleNode::
170  PandaNode::write_datagram(manager, dg);
171 
172  dg.add_uint16(_bundles.size());
173  Bundles::iterator bi;
174  for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
175  manager->write_pointer(dg, (*bi)->get_bundle());
176  }
177 }
178 
179 ////////////////////////////////////////////////////////////////////
180 // Function: PartBundleNode::complete_pointers
181 // Access: Public, Virtual
182 // Description: Receives an array of pointers, one for each time
183 // manager->read_pointer() was called in fillin().
184 // Returns the number of pointers processed.
185 ////////////////////////////////////////////////////////////////////
188  int pi = PandaNode::complete_pointers(p_list, manager);
189 
190  Bundles::iterator bi;
191  for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
192  PT(PartBundle) bundle = DCAST(PartBundle, p_list[pi++]);
193  bundle->add_node(this);
194  (*bi) = new PartBundleHandle(bundle);
195  }
196 
197  return pi;
198 }
199 
200 ////////////////////////////////////////////////////////////////////
201 // Function: PartBundleNode::fillin
202 // Access: Protected
203 // Description: This internal function is called by make_from_bam to
204 // read in all of the relevant data from the BamFile for
205 // the new PandaNode.
206 ////////////////////////////////////////////////////////////////////
207 void PartBundleNode::
208 fillin(DatagramIterator &scan, BamReader* manager) {
209  PandaNode::fillin(scan, manager);
210 
211  int num_bundles = 1;
212  if (manager->get_file_minor_ver() >= 5) {
213  num_bundles = scan.get_uint16();
214  }
215 
216  nassertv(num_bundles >= 1);
217 
218  // Bundle 0. We already have a slot for this one.
219  manager->read_pointer(scan);
220 
221  // Remaining bundles. Push a new slot for each one.
222  for (int i = 1; i < num_bundles; ++i) {
223  manager->read_pointer(scan);
224  _bundles.push_back(NULL);
225  }
226 }
static const LMatrix4f & ident_mat()
Returns an identity matrix.
Definition: lmatrix.h:903
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: pandaNode.cxx:4164
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
bool almost_equal(const LMatrix4f &other, float threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
Definition: lmatrix.cxx:879
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
void xform(const LMatrix4 &mat)
Applies the indicated transform to the root of the animated hierarchy.
Definition: partBundle.I:171
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
This is a trivial class returned by PartBundleNode::get_bundle().
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:105
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
This class is used by the SceneGraphReducer to maintain and accumulate the set of attributes we have ...
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
This is a node that contains a pointer to an PartBundle.
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, GeomTransformer &transformer)
Applies whatever attributes are specified in the AccumulatedAttribs object (and by the attrib_types b...
int get_num_nodes() const
Returns the number of PartBundleNodes that contain a pointer to this PartBundle.
Definition: partBundle.I:198
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this PandaNode by the indicated matrix, if it means anything to do so...
virtual void write_datagram(BamWriter *manager, Datagram &me)
Writes the contents of this object to the datagram for shipping out to a Bam file.
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:181
This is the root of a MovingPart hierarchy.
Definition: partBundle.h:49
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
PartGroup * copy_subgraph() const
Allocates and returns a new copy of this node and of all of its children.
Definition: partGroup.cxx:87
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
void set_bundle(PartBundle *bundle)
Changes the actual PartBundle embedded within the handle.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
PartBundle * get_bundle()
Returns the actual PartBundle embedded within the handle.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
Definition: bamWriter.cxx:279
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:658
An object specifically designed to transform the vertices of a Geom without disturbing indexing or af...