Panda3D
collisionNode.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file collisionNode.cxx
10  * @author drose
11  * @date 2002-03-16
12  */
13 
14 #include "collisionNode.h"
15 #include "config_collide.h"
16 
17 #include "geomNode.h"
18 #include "cullTraverserData.h"
19 #include "cullTraverser.h"
20 #include "renderState.h"
21 #include "transformState.h"
22 #include "colorScaleAttrib.h"
23 #include "transparencyAttrib.h"
24 #include "datagram.h"
25 #include "datagramIterator.h"
26 #include "bamReader.h"
27 #include "bamWriter.h"
28 #include "clockObject.h"
29 #include "boundingSphere.h"
30 #include "boundingBox.h"
31 #include "config_mathutil.h"
32 
33 TypeHandle CollisionNode::_type_handle;
34 
35 
36 /**
37  *
38  */
39 CollisionNode::
40 CollisionNode(const std::string &name) :
41  PandaNode(name),
42  _from_collide_mask(get_default_collide_mask()),
43  _collider_sort(0)
44 {
45  set_cull_callback();
46 
47  // CollisionNodes are hidden by default.
48  set_overall_hidden(true);
49 
50  // CollisionNodes have a certain set of bits on by default.
51  set_into_collide_mask(get_default_collide_mask());
52 }
53 
54 /**
55  *
56  */
57 CollisionNode::
58 CollisionNode(const CollisionNode &copy) :
59  PandaNode(copy),
60  _from_collide_mask(copy._from_collide_mask),
61  _collider_sort(copy._collider_sort),
62  _solids(copy._solids)
63 {
64 }
65 
66 /**
67  *
68  */
69 CollisionNode::
70 ~CollisionNode() {
71 }
72 
73 /**
74  * Returns a newly-allocated Node that is a shallow copy of this one. It will
75  * be a different Node pointer, but its internal data may or may not be shared
76  * with that of the original Node.
77  */
79 make_copy() const {
80  return new CollisionNode(*this);
81 }
82 
83 /**
84  * Returns true if the node's name has extrinsic meaning and must be preserved
85  * across a flatten operation, false otherwise.
86  */
88 preserve_name() const {
89  return true;
90 }
91 
92 /**
93  * Transforms the contents of this node by the indicated matrix, if it means
94  * anything to do so. For most kinds of nodes, this does nothing.
95  */
97 xform(const LMatrix4 &mat) {
98  nassertv(!mat.is_nan());
99 
100  if (mat.almost_equal(LMatrix4::ident_mat())) {
101  return;
102  }
103 
104  Solids::iterator si;
105  for (si = _solids.begin(); si != _solids.end(); ++si) {
106  PT(CollisionSolid) solid = (*si).get_write_pointer();
107  solid->xform(mat);
108  }
109  mark_internal_bounds_stale();
110 }
111 
112 /**
113  * Collapses this node with the other node, if possible, and returns a pointer
114  * to the combined node, or NULL if the two nodes cannot safely be combined.
115  *
116  * The return value may be this, other, or a new node altogether.
117  *
118  * This function is called from GraphReducer::flatten(), and need not deal
119  * with children; its job is just to decide whether to collapse the two nodes
120  * and what the collapsed node should look like.
121  */
123 combine_with(PandaNode *other) {
124  if (flatten_collision_nodes) {
125  if (is_exact_type(get_class_type()) &&
126  other->is_exact_type(get_class_type())) {
127  // Two CollisionNodes can combine, but only if they have the same name,
128  // because the name is often meaningful, and only if they have the same
129  // collide masks.
130  CollisionNode *cother = DCAST(CollisionNode, other);
131  if (get_name() == cother->get_name() &&
134  const COWPT(CollisionSolid) *solids_begin = &cother->_solids[0];
135  const COWPT(CollisionSolid) *solids_end = solids_begin + cother->_solids.size();
136  _solids.insert(_solids.end(), solids_begin, solids_end);
137  mark_internal_bounds_stale();
138  return this;
139  }
140 
141  // Two CollisionNodes with different names or different collide masks
142  // can't combine.
143  }
144  }
145 
146  return nullptr;
147 }
148 
149 /**
150  * Returns the subset of CollideMask bits that may be set for this particular
151  * type of PandaNode. For most nodes, this is 0; it doesn't make sense to set
152  * a CollideMask for most kinds of nodes.
153  *
154  * For nodes that can be collided with, such as GeomNode and CollisionNode,
155  * this returns all bits on.
156  */
158 get_legal_collide_mask() const {
159  return CollideMask::all_on();
160 }
161 
162 /**
163  * This function will be called during the cull traversal to perform any
164  * additional operations that should be performed at cull time. This may
165  * include additional manipulation of render state or additional
166  * visible/invisible decisions, or any other arbitrary operation.
167  *
168  * Note that this function will *not* be called unless set_cull_callback() is
169  * called in the constructor of the derived class. It is necessary to call
170  * set_cull_callback() to indicated that we require cull_callback() to be
171  * called.
172  *
173  * By the time this function is called, the node has already passed the
174  * bounding-volume test for the viewing frustum, and the node's transform and
175  * state have already been applied to the indicated CullTraverserData object.
176  *
177  * The return value is true if this node should be visible, or false if it
178  * should be culled.
179  */
182  // Append our collision vizzes to the drawing, even though they're not
183  // actually part of the scene graph.
184  Solids::const_iterator si;
185  for (si = _solids.begin(); si != _solids.end(); ++si) {
186  CPT(CollisionSolid) solid = (*si).get_read_pointer();
187  PT(PandaNode) node = solid->get_viz(trav, data, false);
188  if (node != nullptr) {
189  CullTraverserData next_data(data, node);
190 
191  // We don't want to inherit the render state from above for these guys.
192  next_data._state = RenderState::make_empty();
193  trav->traverse(next_data);
194  }
195  }
196 
197  if (respect_prev_transform) {
198  // Determine the previous frame's position, relative to the current
199  // position.
200  NodePath node_path = data.get_node_path();
201  CPT(TransformState) transform = node_path.get_net_transform()->invert_compose(node_path.get_net_prev_transform());
202 
203  if (!transform->is_identity()) {
204  // If we have a velocity, also draw the previous frame's position,
205  // ghosted.
206 
207  for (si = _solids.begin(); si != _solids.end(); ++si) {
208  CPT(CollisionSolid) solid = (*si).get_read_pointer();
209  PT(PandaNode) node = solid->get_viz(trav, data, false);
210  if (node != nullptr) {
211  CullTraverserData next_data(data, node);
212 
213  next_data._net_transform =
214  next_data._net_transform->compose(transform);
215  next_data._state = get_last_pos_state();
216  trav->traverse(next_data);
217  }
218  }
219  }
220  }
221 
222  // Now carry on to render our child nodes.
223  return true;
224 }
225 
226 /**
227  * Returns true if there is some value to visiting this particular node during
228  * the cull traversal for any camera, false otherwise. This will be used to
229  * optimize the result of get_net_draw_show_mask(), so that any subtrees that
230  * contain only nodes for which is_renderable() is false need not be visited.
231  */
233 is_renderable() const {
234  return true;
235 }
236 
237 /**
238  * A simple downcast check. Returns true if this kind of node happens to
239  * inherit from CollisionNode, false otherwise.
240  *
241  * This is provided as a a faster alternative to calling
242  * is_of_type(CollisionNode::get_class_type()).
243  */
245 is_collision_node() const {
246  return true;
247 }
248 
249 
250 /**
251  * Writes a brief description of the node to the indicated output stream.
252  * This is invoked by the << operator. It may be overridden in derived
253  * classes to include some information relevant to the class.
254  */
256 output(std::ostream &out) const {
257  PandaNode::output(out);
258  out << " (" << _solids.size() << " solids)";
259 }
260 
261 /**
262  * Sets the "from" CollideMask. In order for a collision to be detected from
263  * this object into another object, the intersection of this object's "from"
264  * mask and the other object's "into" mask must be nonzero.
265  */
266 void CollisionNode::
268  _from_collide_mask = mask;
269 }
270 
271 /**
272  * Called when needed to recompute the node's _internal_bound object. Nodes
273  * that contain anything of substance should redefine this to do the right
274  * thing.
275  */
276 void CollisionNode::
277 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
278  int &internal_vertices,
279  int pipeline_stage,
280  Thread *current_thread) const {
281  pvector<CPT(BoundingVolume) > child_volumes_ref;
282  pvector<const BoundingVolume *> child_volumes;
283  bool all_box = true;
284 
285  Solids::const_iterator gi;
286  for (gi = _solids.begin(); gi != _solids.end(); ++gi) {
287  CPT(CollisionSolid) solid = (*gi).get_read_pointer();
288  CPT(BoundingVolume) volume = solid->get_bounds();
289 
290  if (!volume->is_empty()) {
291  child_volumes_ref.push_back(volume);
292  child_volumes.push_back(volume);
293  if (!volume->is_exact_type(BoundingBox::get_class_type())) {
294  all_box = false;
295  }
296  }
297  }
298 
299  PT(GeometricBoundingVolume) gbv = new BoundingBox;
300 
301  BoundingVolume::BoundsType btype = get_bounds_type();
302  if (btype == BoundingVolume::BT_default) {
303  btype = bounds_type;
304  }
305 
306  if (btype == BoundingVolume::BT_box ||
307  (btype != BoundingVolume::BT_sphere && all_box)) {
308  // If all of the child volumes are a BoundingBox, then our volume is also
309  // a BoundingBox.
310  gbv = new BoundingBox;
311  } else {
312  // Otherwise, it's a sphere.
313  gbv = new BoundingSphere;
314  }
315 
316  if (child_volumes.size() > 0) {
317  const BoundingVolume **child_begin = &child_volumes[0];
318  const BoundingVolume **child_end = child_begin + child_volumes.size();
319  ((BoundingVolume *)gbv)->around(child_begin, child_end);
320  }
321 
322  internal_bounds = gbv;
323  internal_vertices = 0;
324 }
325 
326 /**
327  * Returns a RenderState for rendering the ghosted collision solid that
328  * represents the previous frame's position, for those collision nodes that
329  * indicate a velocity.
330  */
331 CPT(RenderState) CollisionNode::
332 get_last_pos_state() {
333  // Once someone asks for this pointer, we hold its reference count and never
334  // free it.
335  static CPT(RenderState) state = nullptr;
336  if (state == nullptr) {
337  state = RenderState::make
338  (ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 0.5f)),
339  TransparencyAttrib::make(TransparencyAttrib::M_alpha));
340  }
341 
342  return state;
343 }
344 
345 
346 /**
347  * Tells the BamReader how to create objects of type CollisionNode.
348  */
351  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
352 }
353 
354 /**
355  * Writes the contents of this object to the datagram for shipping out to a
356  * Bam file.
357  */
359 write_datagram(BamWriter *manager, Datagram &dg) {
360  PandaNode::write_datagram(manager, dg);
361 
362  int num_solids = _solids.size();
363  if (num_solids >= 0xffff) {
364  dg.add_uint16(0xffff);
365  dg.add_uint32(num_solids);
366  } else {
367  dg.add_uint16(num_solids);
368  }
369  for(int i = 0; i < num_solids; i++) {
370  manager->write_pointer(dg, _solids[i].get_read_pointer());
371  }
372 
373  dg.add_uint32(_from_collide_mask.get_word());
374 }
375 
376 /**
377  * Receives an array of pointers, one for each time manager->read_pointer()
378  * was called in fillin(). Returns the number of pointers processed.
379  */
381 complete_pointers(TypedWritable **p_list, BamReader *manager) {
382  int pi = PandaNode::complete_pointers(p_list, manager);
383 
384  int num_solids = _solids.size();
385  for (int i = 0; i < num_solids; i++) {
386  _solids[i] = DCAST(CollisionSolid, p_list[pi++]);
387  }
388 
389  return pi;
390 }
391 
392 /**
393  * This function is called by the BamReader's factory when a new object of
394  * type CollisionNode is encountered in the Bam file. It should create the
395  * CollisionNode and extract its information from the file.
396  */
397 TypedWritable *CollisionNode::
398 make_from_bam(const FactoryParams &params) {
399  CollisionNode *node = new CollisionNode("");
400  DatagramIterator scan;
401  BamReader *manager;
402 
403  parse_params(params, scan, manager);
404  node->fillin(scan, manager);
405 
406  return node;
407 }
408 
409 /**
410  * This internal function is called by make_from_bam to read in all of the
411  * relevant data from the BamFile for the new CollisionNode.
412  */
413 void CollisionNode::
414 fillin(DatagramIterator &scan, BamReader *manager) {
415  PandaNode::fillin(scan, manager);
416 
417  int num_solids = scan.get_uint16();
418  if (num_solids == 0xffff) {
419  num_solids = scan.get_uint32();
420  }
421  _solids.clear();
422  _solids.reserve(num_solids);
423  for(int i = 0; i < num_solids; i++) {
424  manager->read_pointer(scan);
425  // Push back a NULL for each solid, for now. We'll fill them in later.
426  _solids.push_back(nullptr);
427  }
428 
429  _from_collide_mask.set_word(scan.get_uint32());
430 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition: bamReader.I:275
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
Definition: bamWriter.cxx:317
static BitMask< uint32_t, nbits > all_on()
Returns a BitMask whose bits are all on.
Definition: bitMask.I:32
void set_word(WordType value)
Sets the entire BitMask to the value indicated by the given word.
Definition: bitMask.I:255
WordType get_word() const
Returns the entire BitMask as a single word.
Definition: bitMask.I:246
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition: boundingBox.h:29
This defines a bounding sphere, consisting of a center and a radius.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
A node in the scene graph that can hold any number of CollisionSolids.
Definition: collisionNode.h:30
get_into_collide_mask
Returns the current "into" CollideMask.
Definition: collisionNode.h:61
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
virtual bool preserve_name() const
Returns true if the node's name has extrinsic meaning and must be preserved across a flatten operatio...
static void register_with_read_factory()
Tells the BamReader how to create objects of type CollisionNode.
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
get_from_collide_mask
Returns the current "from" CollideMask.
Definition: collisionNode.h:59
virtual bool is_collision_node() const
A simple downcast check.
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this node by the indicated matrix, if it means anything to do so.
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
virtual CollideMask get_legal_collide_mask() const
Returns the subset of CollideMask bits that may be set for this particular type of PandaNode.
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
virtual PandaNode * combine_with(PandaNode *other)
Collapses this node with the other node, if possible, and returns a pointer to the combined node,...
virtual void output(std::ostream &out) const
Writes a brief description of the node to the indicated output stream.
set_from_collide_mask
Sets the "from" CollideMask.
Definition: collisionNode.h:59
The abstract base class for all things that can collide with other things in the world,...
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
void traverse(const NodePath &root)
Begins the traversal from the indicated node.
A class to retrieve the individual data elements previously stored in a Datagram.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
void add_uint32(uint32_t value)
Adds an unsigned 32-bit integer to the datagram.
Definition: datagram.I:94
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:73
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
get_bounds_type
Returns the bounding volume type set with set_bounds_type().
Definition: pandaNode.h:293
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:3583
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
A thread; that is, a lightweight process.
Definition: thread.h:46
Indicates a coordinate-system transform on vertices.
bool is_identity() const
Returns true if the transform represents the identity matrix, false otherwise.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:38
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
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 our own Panda specialization on the default STL vector.
Definition: pvector.h:42
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT(RenderState) CollisionNode
Returns a RenderState for rendering the ghosted collision solid that represents the previous frame's ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.