Panda3D
 All Classes Functions Variables Enumerations
bulletBodyNode.cxx
1 // Filename: bulletBodyNode.cxx
2 // Created by: enn0x (19Nov10)
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 "bulletBodyNode.h"
16 #include "bulletShape.h"
17 #include "bulletWorld.h"
18 #include "bulletTriangleMesh.h"
19 
20 #include "collisionBox.h"
21 #include "collisionPlane.h"
22 #include "collisionSphere.h"
23 #include "collisionPolygon.h"
24 
25 TypeHandle BulletBodyNode::_type_handle;
26 
27 ////////////////////////////////////////////////////////////////////
28 // Function: BulletBodyNode::Constructor
29 // Access: Published
30 // Description:
31 ////////////////////////////////////////////////////////////////////
32 BulletBodyNode::
33 BulletBodyNode(const char *name) : PandaNode(name) {
34 
35  // Shape
36  _shape = new btEmptyShape();
37 
38  // Default collide mask
40 }
41 
42 ////////////////////////////////////////////////////////////////////
43 // Function: BulletBodyNode::get_legal_collide_mask
44 // Access: Public, virtual
45 // Description: Returns the subset of CollideMask bits that may be
46 // set for this particular type of PandaNode. For
47 // BodyNodes this returns all bits on.
48 ////////////////////////////////////////////////////////////////////
51 
52  return CollideMask::all_on();
53 }
54 
55 ////////////////////////////////////////////////////////////////////
56 // Function: BulletBodyNode::safe_to_flatten
57 // Access: Public, Virtual
58 // Description: Returns true if it is generally safe to flatten out
59 // this particular kind of Node by duplicating
60 // instances, false otherwise (for instance, a Camera
61 // cannot be safely flattened, because the Camera
62 // pointer itself is meaningful).
63 ////////////////////////////////////////////////////////////////////
65 safe_to_flatten() const {
66 
67  return false;
68 }
69 
70 ////////////////////////////////////////////////////////////////////
71 // Function: BulletBodyNode::safe_to_transform
72 // Access: Public, Virtual
73 // Description: Returns true if it is generally safe to transform
74 // this particular kind of Node by calling the xform()
75 // method, false otherwise. For instance, it's usually
76 // a bad idea to attempt to xform a Character.
77 ////////////////////////////////////////////////////////////////////
80 
81  return false;
82 }
83 
84 ////////////////////////////////////////////////////////////////////
85 // Function: BulletBodyNode::safe_to_modify_transform
86 // Access: Public, Virtual
87 // Description: Returns true if it is safe to automatically adjust
88 // the transform on this kind of node. Usually, this is
89 // only a bad idea if the user expects to find a
90 // particular transform on the node.
91 //
92 // ModelNodes with the preserve_transform flag set are
93 // presently the only kinds of nodes that should not
94 // have their transform even adjusted.
95 ////////////////////////////////////////////////////////////////////
98 
99  return false;
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function: BulletBodyNode::safe_to_combine
104 // Access: Public, Virtual
105 // Description: Returns true if it is generally safe to combine this
106 // particular kind of PandaNode with other kinds of
107 // PandaNodes of compatible type, adding children or
108 // whatever. For instance, an LODNode should not be
109 // combined with any other PandaNode, because its set of
110 // children is meaningful.
111 ////////////////////////////////////////////////////////////////////
112 bool BulletBodyNode::
114 
115  return false;
116 }
117 
118 ////////////////////////////////////////////////////////////////////
119 // Function: BulletBodyNode::safe_to_combine_children
120 // Access: Public, Virtual
121 // Description: Returns true if it is generally safe to combine the
122 // children of this PandaNode with each other. For
123 // instance, an LODNode's children should not be
124 // combined with each other, because the set of children
125 // is meaningful.
126 ////////////////////////////////////////////////////////////////////
127 bool BulletBodyNode::
129 
130  return false;
131 }
132 
133 ////////////////////////////////////////////////////////////////////
134 // Function: BulletBodyNode::safe_to_flatten_below
135 // Access: Public, Virtual
136 // Description: Returns true if a flatten operation may safely
137 // continue past this node, or false if nodes below this
138 // node may not be molested.
139 ////////////////////////////////////////////////////////////////////
140 bool BulletBodyNode::
142 
143  return false;
144 }
145 
146 ////////////////////////////////////////////////////////////////////
147 // Function: BulletBodyNode::output
148 // Access: Public, Virtual
149 // Description:
150 ////////////////////////////////////////////////////////////////////
151 void BulletBodyNode::
152 output(ostream &out) const {
153 
154  PandaNode::output(out);
155 
156  out << " (" << get_num_shapes() << " shapes)";
157 
158  if (is_static()) out << " static";
159  if (is_kinematic()) out << " kinematic";
160 }
161 
162 ////////////////////////////////////////////////////////////////////
163 // Function: BulletBodyNode::add_shape
164 // Access: Published
165 // Description:
166 ////////////////////////////////////////////////////////////////////
167 void BulletBodyNode::
168 add_shape(BulletShape *shape, const TransformState *ts) {
169 
170  nassertv(get_object());
171  nassertv(ts);
172 
173  nassertv(!(shape->ptr()->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE
174  && ((btConvexHullShape *)shape->ptr())->getNumVertices() == 0));
175 
176  // Transform
177  btTransform trans = TransformState_to_btTrans(ts);
178 
179  // Reset the shape scaling before we add a shape, and remember the current
180  // Scale so we can restore it later...
181  NodePath np = NodePath::any_path((PandaNode *)this);
182  LVector3 scale = np.get_scale();
183  np.set_scale(1.0);
184 
185  // Root shape
186  btCollisionShape *previous = get_object()->getCollisionShape();
187  btCollisionShape *next;
188 
189  if (_shapes.size() == 0) {
190  nassertv(previous->getShapeType() == EMPTY_SHAPE_PROXYTYPE);
191 
192  if (ts->is_identity()) {
193  // After adding the shape we will have one shape, but with transform.
194  // We need to wrap the shape within a compound shape, in oder to
195  // be able to set the local transform.
196  next = shape->ptr();
197  }
198  else {
199  // After adding the shape we will have a total of one shape, without
200  // local transform. We can set the shape directly.
201  next = new btCompoundShape();
202  ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
203  }
204 
205  get_object()->setCollisionShape(next);
206  _shape = next;
207 
208  delete previous;
209  }
210  else if (_shapes.size() == 1) {
211  if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
212  // We have one shape, and add another shape. The previous shape is
213  // already a compound shape. So we just need to add the second shape
214  // to the compound shape.
215  next = previous;
216 
217  ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
218  }
219  else {
220  // We have one shape which is NOT a compound shape, and want to add
221  // a second shape. We need to wrap both shapes within a compound shape.
222  next = new btCompoundShape();
223 
224  btTransform previous_trans = btTransform::getIdentity();
225  ((btCompoundShape *)next)->addChildShape(previous_trans, previous);
226  ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
227 
228  get_object()->setCollisionShape(next);
229  _shape = next;
230  }
231  }
232  else {
233  // We already have two or more shapes, and want to add another. So we
234  // already have a compound shape as wrapper, and just need to add the
235  // new shape to the compound.
236  nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
237 
238  next = previous;
239  ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
240  }
241 
242  _shapes.push_back(shape);
243 
244  // Restore the local scaling again
245  np.set_scale(scale);
246 
247  shape_changed();
248 }
249 
250 ////////////////////////////////////////////////////////////////////
251 // Function: BulletBodyNode::remove_shape
252 // Access: Published
253 // Description:
254 ////////////////////////////////////////////////////////////////////
255 void BulletBodyNode::
256 remove_shape(BulletShape *shape) {
257 
258  nassertv(get_object());
259 
260  BulletShapes::iterator found;
261  PT(BulletShape) ptshape = shape;
262  found = find(_shapes.begin(), _shapes.end(), ptshape);
263 
264  if (found == _shapes.end()) {
265  bullet_cat.warning() << "shape not attached" << endl;
266  }
267  else {
268  _shapes.erase(found);
269 
270  // Determine the new root shape
271  btCollisionShape *previous = get_object()->getCollisionShape();
272  btCollisionShape *next;
273 
274  if (_shapes.size() == 0) {
275  // No more shapes remaining
276  next = new btEmptyShape();
277 
278  get_object()->setCollisionShape(next);
279  _shape = next;
280 
281  // The previous shape might be a compound. Then delete it.
282  if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
283  delete previous;
284  }
285  }
286  else if (_shapes.size() == 1) {
287  // Only one shape remaining
288  nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
289 
290  btCompoundShape *compound = (btCompoundShape *)previous;
291  compound->removeChildShape(shape->ptr());
292 
293  nassertv(compound->getNumChildShapes() == 1);
294 
295  // The compound is no longer required if the remaining shape
296  // has no transform
297  btTransform trans = compound->getChildTransform(0);
298  if (is_identity(trans)) {
299  next = compound->getChildShape(0);
300 
301  get_object()->setCollisionShape(next);
302  _shape = next;
303 
304  delete compound;
305  }
306  }
307  else {
308  // More than one shape are remaining
309  nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
310 
311  btCompoundShape *compound = (btCompoundShape *)previous;
312  compound->removeChildShape(shape->ptr());
313  }
314 
315  shape_changed();
316  }
317 }
318 
319 ////////////////////////////////////////////////////////////////////
320 // Function: BulletBodyNode::is_identity
321 // Access: Private
322 // Description: Returns TRUE if the transform is an identity
323 // transform, otherwise FALSE.
324 ////////////////////////////////////////////////////////////////////
325 bool BulletBodyNode::
326 is_identity(btTransform &trans) {
327 
328  btVector3 null(0, 0, 0);
329 
330  return (trans.getOrigin() == null
331  && trans.getRotation().getAxis() == null);
332 }
333 
334 ////////////////////////////////////////////////////////////////////
335 // Function: BulletBodyNode::get_shape_pos
336 // Access: Published
337 // Description:
338 ////////////////////////////////////////////////////////////////////
339 LPoint3 BulletBodyNode::
340 get_shape_pos(int idx) const {
341 
342  nassertr(idx >= 0 && idx < (int)_shapes.size(), LPoint3::zero());
343  return get_shape_mat(idx).get_row3(3);
344 }
345 
346 ////////////////////////////////////////////////////////////////////
347 // Function: BulletBodyNode::get_shape_mat
348 // Access: Published
349 // Description:
350 ////////////////////////////////////////////////////////////////////
351 LMatrix4 BulletBodyNode::
352 get_shape_mat(int idx) const {
353 
354  nassertr(idx >= 0 && idx < (int)_shapes.size(), LMatrix4::ident_mat());
355 
356  btCollisionShape *root = get_object()->getCollisionShape();
357  if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
358  btCompoundShape *compound = (btCompoundShape *)root;
359 
360  btTransform trans = compound->getChildTransform(idx);
361  return btTrans_to_LMatrix4(trans);
362 
363  // The above code assumes that shape's index in _shapes member
364  // is the same as the shapes index within the compound. If it
365  // turns out that this is not always true we could use the
366  // following code:
367  /*
368  btCollisionShape *shape = get_shape(idx)->ptr();
369  for (int i=0; i<compound->getNumChildShapes(); i++) {
370  if (compound->getChildShape(i) == shape) {
371  btTransform trans = compound->getChildTransform(idx);
372  return btTrans_to_LMatrix4(trans);
373  }
374  }
375  */
376  }
377 
378  return LMatrix4::ident_mat();
379 }
380 
381 ////////////////////////////////////////////////////////////////////
382 // Function: BulletBodyNode::shape_changed
383 // Access: Published
384 // Description: Hook which will be called whenever the total shape
385 // of a body changed. Used for example to update
386 // the mass properties (inertia) of a rigid body.
387 // The default implementation does nothing.
388 ////////////////////////////////////////////////////////////////////
389 void BulletBodyNode::
390 shape_changed() {
391 
392 }
393 
394 ////////////////////////////////////////////////////////////////////
395 // Function: BulletBodyNode::set_deactivation_time
396 // Access: Published
397 // Description:
398 ////////////////////////////////////////////////////////////////////
399 void BulletBodyNode::
400 set_deactivation_time(PN_stdfloat dt) {
401 
402  get_object()->setDeactivationTime(dt);
403 }
404 
405 ////////////////////////////////////////////////////////////////////
406 // Function: BulletBodyNode::get_deactivation_time
407 // Access: Published
408 // Description:
409 ////////////////////////////////////////////////////////////////////
410 PN_stdfloat BulletBodyNode::
411 get_deactivation_time() const {
412 
413  return get_object()->getDeactivationTime();
414 }
415 
416 ////////////////////////////////////////////////////////////////////
417 // Function: BulletBodyNode::is_active
418 // Access: Published
419 // Description:
420 ////////////////////////////////////////////////////////////////////
421 bool BulletBodyNode::
422 is_active() const {
423 
424  return get_object()->isActive();
425 }
426 
427 ////////////////////////////////////////////////////////////////////
428 // Function: BulletBodyNode::set_active
429 // Access: Published
430 // Description:
431 ////////////////////////////////////////////////////////////////////
432 void BulletBodyNode::
433 set_active(bool active, bool force) {
434 
435  if (active) {
436  get_object()->activate(force);
437  }
438  else {
439  if (force) {
440  get_object()->forceActivationState(ISLAND_SLEEPING);
441  }
442  else {
443  get_object()->setActivationState(ISLAND_SLEEPING);
444  }
445  }
446 }
447 
448 ////////////////////////////////////////////////////////////////////
449 // Function: BulletBodyNode::set_deactivation_enabled
450 // Access: Published
451 // Description:
452 ////////////////////////////////////////////////////////////////////
453 void BulletBodyNode::
454 set_deactivation_enabled(const bool enabled, const bool force) {
455 
456  int state = (enabled) ? WANTS_DEACTIVATION : DISABLE_DEACTIVATION;
457 
458  if (force) {
459  get_object()->forceActivationState(state);
460  }
461  else {
462  get_object()->setActivationState(state);
463  }
464 }
465 
466 ////////////////////////////////////////////////////////////////////
467 // Function: BulletBodyNode::is_deactivation_enabled
468 // Access: Published
469 // Description:
470 ////////////////////////////////////////////////////////////////////
471 bool BulletBodyNode::
472 is_deactivation_enabled() const {
473 
474  return (get_object()->getActivationState() & DISABLE_DEACTIVATION) == 0;
475 }
476 
477 ////////////////////////////////////////////////////////////////////
478 // Function: BulletBodyNode::check_collision_with
479 // Access: Published
480 // Description:
481 ////////////////////////////////////////////////////////////////////
482 bool BulletBodyNode::
483 check_collision_with(PandaNode *node) {
484 
485  btCollisionObject *obj = BulletWorld::get_collision_object(node);
486 
487  if (obj) {
488  return get_object()->checkCollideWith(obj);
489  }
490  else {
491  return false;
492  }
493 }
494 
495 ////////////////////////////////////////////////////////////////////
496 // Function: BulletBodyNode::get_anisotropic_friction
497 // Access: Published
498 // Description:
499 ////////////////////////////////////////////////////////////////////
500 LVecBase3 BulletBodyNode::
501 get_anisotropic_friction() const {
502 
503  return btVector3_to_LVecBase3(get_object()->getAnisotropicFriction());
504 }
505 
506 ////////////////////////////////////////////////////////////////////
507 // Function: BulletBodyNode::set_anisotropic_friction
508 // Access: Published
509 // Description:
510 ////////////////////////////////////////////////////////////////////
511 void BulletBodyNode::
512 set_anisotropic_friction(const LVecBase3 &friction) {
513 
514  nassertv(!friction.is_nan());
515  get_object()->setAnisotropicFriction(LVecBase3_to_btVector3(friction));
516 }
517 
518 ////////////////////////////////////////////////////////////////////
519 // Function: BulletBodyNode::has_contact_response
520 // Access: Published
521 // Description:
522 ////////////////////////////////////////////////////////////////////
523 bool BulletBodyNode::
524 has_contact_response() const {
525 
526  return get_object()->hasContactResponse();
527 }
528 
529 ////////////////////////////////////////////////////////////////////
530 // Function: BulletBodyNode::get_contact_processing_threshold
531 // Access: Published
532 // Description:
533 ////////////////////////////////////////////////////////////////////
534 PN_stdfloat BulletBodyNode::
535 get_contact_processing_threshold() const {
536 
537  return get_object()->getContactProcessingThreshold();
538 }
539 
540 ////////////////////////////////////////////////////////////////////
541 // Function: BulletBodyNode::set_contact_processing_threshold
542 // Access: Published
543 // Description: The constraint solver can discard solving
544 // contacts, if the distance is above this threshold.
545 ////////////////////////////////////////////////////////////////////
546 void BulletBodyNode::
547 set_contact_processing_threshold(PN_stdfloat threshold) {
548 
549  get_object()->setContactProcessingThreshold(threshold);
550 }
551 
552 ////////////////////////////////////////////////////////////////////
553 // Function: BulletBodyNode::get_ccd_swept_sphere_radius
554 // Access: Published
555 // Description:
556 ////////////////////////////////////////////////////////////////////
557 PN_stdfloat BulletBodyNode::
558 get_ccd_swept_sphere_radius() const {
559 
560  return get_object()->getCcdSweptSphereRadius();
561 }
562 
563 ////////////////////////////////////////////////////////////////////
564 // Function: BulletBodyNode::set_ccd_swept_sphere_radius
565 // Access: Published
566 // Description:
567 ////////////////////////////////////////////////////////////////////
568 void BulletBodyNode::
569 set_ccd_swept_sphere_radius(PN_stdfloat radius) {
570 
571  return get_object()->setCcdSweptSphereRadius(radius);
572 }
573 
574 ////////////////////////////////////////////////////////////////////
575 // Function: BulletBodyNode::get_ccd_motion_threshold
576 // Access: Published
577 // Description:
578 ////////////////////////////////////////////////////////////////////
579 PN_stdfloat BulletBodyNode::
580 get_ccd_motion_threshold() const {
581 
582  return get_object()->getCcdMotionThreshold();
583 }
584 
585 ////////////////////////////////////////////////////////////////////
586 // Function: BulletBodyNode::set_ccd_motion_threshold
587 // Access: Published
588 // Description:
589 ////////////////////////////////////////////////////////////////////
590 void BulletBodyNode::
591 set_ccd_motion_threshold(PN_stdfloat threshold) {
592 
593  return get_object()->setCcdMotionThreshold(threshold);
594 }
595 
596 ////////////////////////////////////////////////////////////////////
597 // Function: BulletBodyNode::add_shapes_from_collision_solids
598 // Access: Published
599 // Description:
600 ////////////////////////////////////////////////////////////////////
601 void BulletBodyNode::
602 add_shapes_from_collision_solids(CollisionNode *cnode) {
603 
604  PT(BulletTriangleMesh) mesh = NULL;
605 
606  for (int j=0; j<cnode->get_num_solids(); j++) {
607  CPT(CollisionSolid) solid = cnode->get_solid(j);
608  TypeHandle type = solid->get_type();
609 
610  // CollisionSphere
611  if (CollisionSphere::get_class_type() == type) {
612  CPT(CollisionSphere) sphere = DCAST(CollisionSphere, solid);
613  CPT(TransformState) ts = TransformState::make_pos(sphere->get_center());
614 
615  add_shape(BulletSphereShape::make_from_solid(sphere), ts);
616  }
617 
618  // CollisionBox
619  else if (CollisionBox::get_class_type() == type) {
620  CPT(CollisionBox) box = DCAST(CollisionBox, solid);
621  CPT(TransformState) ts = TransformState::make_pos(box->get_approx_center());
622 
623  add_shape(BulletBoxShape::make_from_solid(box), ts);
624  }
625 
626  // CollisionPlane
627  else if (CollisionPlane::get_class_type() == type) {
628  CPT(CollisionPlane) plane = DCAST(CollisionPlane, solid);
629 
630  add_shape(BulletPlaneShape::make_from_solid(plane));
631  }
632 
633  // CollisionGeom
634  else if (CollisionPolygon::get_class_type() == type) {
635  CPT(CollisionPolygon) polygon = DCAST(CollisionPolygon, solid);
636 
637  if (!mesh) {
638  mesh = new BulletTriangleMesh();
639  }
640 
641  for (int i=2; i < polygon->get_num_points(); i++ ) {
642  LPoint3 p1 = polygon->get_point(0);
643  LPoint3 p2 = polygon->get_point(i-1);
644  LPoint3 p3 = polygon->get_point(i);
645 
646  mesh->add_triangle(p1, p2, p3, true);
647  }
648  }
649  }
650 
651  if (mesh && mesh->get_num_triangles() > 0) {
652  add_shape(new BulletTriangleMeshShape(mesh, true));
653  }
654 }
655 
656 ////////////////////////////////////////////////////////////////////
657 // Function: BulletBodyNode::set_transform_dirty
658 // Access: Published
659 // Description: This method enforces an update of the Bullet
660 // transform, that is copies the scene graph transform
661 // to the Bullet transform.
662 // This is achieved by alling the protected PandaNode
663 // hook 'transform_changed'.
664 ////////////////////////////////////////////////////////////////////
665 void BulletBodyNode::
667 
668  transform_changed();
669 }
670 
671 ////////////////////////////////////////////////////////////////////
672 // Function: BulletBodyNode::get_shape_bounds
673 // Access: Published
674 // Description: Returns the current bounds of all collision shapes
675 // owned by this body.
676 ////////////////////////////////////////////////////////////////////
679 
680 /*
681  btTransform tr;
682  tr.setIdentity();
683  btVector3 aabbMin,aabbMax;
684  ptr()->getAabb(tr,aabbMin,aabbMax);
685  btVector3 o = tr.getOrigin();
686 cout << "aabbMin " << aabbMin.x() << " " << aabbMin.y() << " " << aabbMin.z() << endl;
687 cout << "aabbMax " << aabbMax.x() << " " << aabbMax.y() << " " << aabbMax.z() << endl;
688 cout << "origin " << aabbMin.x() << " " << aabbMin.y() << " " << aabbMin.z() << endl;
689 */
690 
691  btVector3 center;
692  btScalar radius;
693 
694  if (_shape) {
695  _shape->getBoundingSphere(center, radius);
696  }
697 
698  BoundingSphere bounds(btVector3_to_LPoint3(center), (PN_stdfloat)radius);
699 
700  return bounds;
701 }
702 
static const LMatrix4f & ident_mat()
Returns an identity matrix.
Definition: lmatrix.h:903
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
This is the base class for all three-component vectors and points.
Definition: lvecBase3.h:105
virtual CollideMask get_legal_collide_mask() const
Returns the subset of CollideMask bits that may be set for this particular type of PandaNode...
void set_transform_dirty()
This method enforces an update of the Bullet transform, that is copies the scene graph transform to t...
BoundingSphere get_shape_bounds() const
Returns the current bounds of all collision shapes owned by this body.
static BitMask< WType, nbits > all_on()
Returns a BitMask whose bits are all on.
Definition: bitMask.I:73
The abstract base class for all things that can collide with other things in the world, and all the things they can collide with (except geometry).
This defines a bounding sphere, consisting of a center and a radius.
static const LPoint3f & zero()
Returns a zero-length point.
Definition: lpoint3.h:258
A cuboid collision volume or object.
Definition: collisionBox.h:30
void set_scale(PN_stdfloat scale)
Sets the scale component of the transform, leaving translation and rotation untouched.
Definition: nodePath.I:848
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:100
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
A spherical collision volume or object.
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
Definition: lvecBase3.h:463
virtual bool safe_to_combine() const
Returns true if it is generally safe to combine this particular kind of PandaNode with other kinds of...
virtual bool safe_to_modify_transform() const
Returns true if it is safe to automatically adjust the transform on this kind of node.
virtual bool safe_to_flatten_below() const
Returns true if a flatten operation may safely continue past this node, or false if nodes below this ...
static NodePath any_path(PandaNode *node, Thread *current_thread=Thread::get_current_thread())
Returns a new NodePath that represents any arbitrary path from the root to the indicated node...
Definition: nodePath.I:77
void set_contact_processing_threshold(PN_stdfloat threshold)
The constraint solver can discard solving contacts, if the distance is above this threshold...
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of Node by calling the xform()...
LVecBase3 get_scale() const
Retrieves the scale component of the transform.
Definition: nodePath.cxx:1331
void set_into_collide_mask(CollideMask mask)
Sets the &quot;into&quot; CollideMask.
Definition: pandaNode.cxx:2037
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of Node by duplicating insta...
virtual bool safe_to_combine_children() const
Returns true if it is generally safe to combine the children of this PandaNode with each other...
A node in the scene graph that can hold any number of CollisionSolids.
Definition: collisionNode.h:33
LVecBase3f get_row3(int row) const
Retrieves the row column of the matrix as a 3-component vector, ignoring the last column...
Definition: lmatrix.h:1312
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
A general bitmask class.
Definition: bitMask.h:35
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165