Panda3D
bulletDebugNode.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 bulletDebugNode.cxx
10  * @author enn0x
11  * @date 2010-01-23
12  */
13 
14 #include "bulletDebugNode.h"
15 
16 #include "config_bullet.h"
17 
18 #include "bulletWorld.h"
19 
20 #include "cullHandler.h"
21 #include "cullTraverser.h"
22 #include "cullableObject.h"
23 #include "geomLines.h"
24 #include "geomVertexData.h"
25 #include "geomTriangles.h"
26 #include "geomVertexFormat.h"
27 #include "geomVertexWriter.h"
28 #include "omniBoundingVolume.h"
29 #include "pStatTimer.h"
30 
31 TypeHandle BulletDebugNode::_type_handle;
32 PStatCollector BulletDebugNode::_pstat_debug("App:Bullet:DoPhysics:Debug");
33 
34 /**
35  *
36  */
37 BulletDebugNode::
38 BulletDebugNode(const char *name) : PandaNode(name) {
39 
40  _debug_stale = false;
41  _debug_world = nullptr;
42  _wireframe = true;
43  _constraints = true;
44  _bounds = false;
45  _drawer._normals = true;
46 
47  CPT (BoundingVolume) bounds = new OmniBoundingVolume();
48  set_bounds(bounds);
49  set_final(true);
50  set_overall_hidden(true);
51 }
52 
53 /**
54  * Returns true if it is generally safe to flatten out this particular kind of
55  * Node by duplicating instances, false otherwise (for instance, a Camera
56  * cannot be safely flattened, because the Camera pointer itself is
57  * meaningful).
58  */
60 safe_to_flatten() const {
61 
62  return false;
63 }
64 
65 /**
66  * Returns true if it is generally safe to transform this particular kind of
67  * Node by calling the xform() method, false otherwise. For instance, it's
68  * usually a bad idea to attempt to xform a Character.
69  */
71 safe_to_transform() const {
72 
73  return false;
74 }
75 
76 /**
77  * Returns true if it is safe to automatically adjust the transform on this
78  * kind of node. Usually, this is only a bad idea if the user expects to find
79  * a particular transform on the node.
80  *
81  * ModelNodes with the preserve_transform flag set are presently the only
82  * kinds of nodes that should not have their transform even adjusted.
83  */
86 
87  return false;
88 }
89 
90 /**
91  * Returns true if it is generally safe to combine this particular kind of
92  * PandaNode with other kinds of PandaNodes of compatible type, adding
93  * children or whatever. For instance, an LODNode should not be combined with
94  * any other PandaNode, because its set of children is meaningful.
95  */
97 safe_to_combine() const {
98 
99  return false;
100 }
101 
102 /**
103  * Returns true if it is generally safe to combine the children of this
104  * PandaNode with each other. For instance, an LODNode's children should not
105  * be combined with each other, because the set of children is meaningful.
106  */
108 safe_to_combine_children() const {
109 
110  return false;
111 }
112 
113 /**
114  * Returns true if a flatten operation may safely continue past this node, or
115  * false if nodes below this node may not be molested.
116  */
118 safe_to_flatten_below() const {
119 
120  return false;
121 }
122 
123 /**
124  *
125  */
128 
129  if (is_overall_hidden()) {
130  _drawer.setDebugMode(DebugDraw::DBG_NoDebug);
131  }
132  else {
133  int mode = DebugDraw::DBG_DrawText |
134  DebugDraw::DBG_DrawFeaturesText |
135  DebugDraw::DBG_DrawContactPoints;
136 
137  if (_wireframe) {
138  mode |= DebugDraw::DBG_DrawWireframe;
139  }
140 
141  if (_constraints) {
142  mode |= DebugDraw::DBG_DrawConstraints;
143  mode |= DebugDraw::DBG_DrawConstraintLimits;
144  }
145 
146  if (_bounds) {
147  mode |= DebugDraw::DBG_DrawAabb;
148  }
149 
150  _drawer.setDebugMode(mode);
151  }
152 }
153 
154 /**
155  * Returns true if there is some value to visiting this particular node during
156  * the cull traversal for any camera, false otherwise. This will be used to
157  * optimize the result of get_net_draw_show_mask(), so that any subtrees that
158  * contain only nodes for which is_renderable() is false need not be visited.
159  */
161 is_renderable() const {
162  return true;
163 }
164 
165 /**
166  * Adds the node's contents to the CullResult we are building up during the
167  * cull traversal, so that it will be drawn at render time. For most nodes
168  * other than GeomNodes, this is a do-nothing operation.
169  */
172  PT(Geom) debug_lines;
173  PT(Geom) debug_triangles;
174 
175  {
176  LightMutexHolder holder(BulletWorld::get_global_lock());
177  if (_debug_world == nullptr) {
178  return;
179  }
180  if (_debug_stale) {
181  nassertv(_debug_world != nullptr);
182  PStatTimer timer(_pstat_debug);
183 
184  // Collect debug geometry data
185  _drawer._lines.clear();
186  _drawer._triangles.clear();
187 
188  _debug_world->debugDrawWorld();
189 
190  // Render lines
191  {
192  PT(GeomVertexData) vdata =
193  new GeomVertexData("", GeomVertexFormat::get_v3c4(), Geom::UH_stream);
194  vdata->unclean_set_num_rows(_drawer._lines.size() * 2);
195 
196  GeomVertexWriter vwriter(vdata, InternalName::get_vertex());
197  GeomVertexWriter cwriter(vdata, InternalName::get_color());
198 
200  for (lit = _drawer._lines.begin(); lit != _drawer._lines.end(); lit++) {
201  const Line &line = *lit;
202 
203  vwriter.set_data3(line._p0);
204  vwriter.set_data3(line._p1);
205  cwriter.set_data4(LVecBase4(line._color));
206  cwriter.set_data4(LVecBase4(line._color));
207  }
208 
209  PT(GeomPrimitive) prim = new GeomLines(Geom::UH_stream);
210  prim->set_shade_model(Geom::SM_uniform);
211  prim->add_next_vertices(_drawer._lines.size() * 2);
212 
213  debug_lines = new Geom(vdata);
214  debug_lines->add_primitive(prim);
215  _debug_lines = debug_lines;
216  }
217 
218  // Render triangles
219  {
220  PT(GeomVertexData) vdata =
221  new GeomVertexData("", GeomVertexFormat::get_v3c4(), Geom::UH_stream);
222  vdata->unclean_set_num_rows(_drawer._triangles.size() * 3);
223 
224  GeomVertexWriter vwriter(vdata, InternalName::get_vertex());
225  GeomVertexWriter cwriter(vdata, InternalName::get_color());
226 
228  for (tit = _drawer._triangles.begin(); tit != _drawer._triangles.end(); tit++) {
229  const Triangle &tri = *tit;
230 
231  vwriter.set_data3(tri._p0);
232  vwriter.set_data3(tri._p1);
233  vwriter.set_data3(tri._p2);
234  cwriter.set_data4(LVecBase4(tri._color));
235  cwriter.set_data4(LVecBase4(tri._color));
236  cwriter.set_data4(LVecBase4(tri._color));
237  }
238 
239  PT(GeomPrimitive) prim = new GeomTriangles(Geom::UH_stream);
240  prim->set_shade_model(Geom::SM_uniform);
241  prim->add_next_vertices(_drawer._triangles.size() * 3);
242 
243  debug_triangles = new Geom(vdata);
244  debug_triangles->add_primitive(prim);
245  _debug_triangles = debug_triangles;
246  }
247 
248  // Clear collected data.
249  _drawer._lines.clear();
250  _drawer._triangles.clear();
251 
252  _debug_stale = false;
253  } else {
254  debug_lines = _debug_lines;
255  debug_triangles = _debug_triangles;
256  }
257  }
258 
259  // Record them without any state or transform.
260  trav->_geoms_pcollector.add_level(2);
261  {
262  CullableObject *object =
263  new CullableObject(std::move(debug_lines), RenderState::make_empty(), trav->get_scene()->get_cs_world_transform());
264  trav->get_cull_handler()->record_object(object, trav);
265  }
266  {
267  CullableObject *object =
268  new CullableObject(std::move(debug_triangles), RenderState::make_empty(), trav->get_scene()->get_cs_world_transform());
269  trav->get_cull_handler()->record_object(object, trav);
270  }
271 }
272 
273 /**
274  *
275  */
276 void BulletDebugNode::
277 do_sync_b2p(btDynamicsWorld *world) {
278 
279  _debug_world = world;
280  _debug_stale = true;
281 }
282 
283 /**
284  *
285  */
286 void BulletDebugNode::DebugDraw::
287 setDebugMode(int mode) {
288 
289  _mode = mode;
290 }
291 
292 /**
293  *
294  */
295 int BulletDebugNode::DebugDraw::
296 getDebugMode() const {
297 
298  return _mode;
299 }
300 
301 /**
302  *
303  */
304 void BulletDebugNode::DebugDraw::
305 reportErrorWarning(const char *warning) {
306 
307  bullet_cat.error() << warning << std::endl;
308 }
309 
310 /**
311  *
312  */
313 void BulletDebugNode::DebugDraw::
314 drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color) {
315 
316  PN_stdfloat r = color.getX();
317  PN_stdfloat g = color.getY();
318  PN_stdfloat b = color.getZ();
319 
320  // Hack to get rid of triangle normals. The hack is based on the assumption
321  // that only normals are drawn in yellow.
322  if (_normals==false && r==1.0f && g==1.0f && b==0.0f) return;
323 
324  Line line;
325 
326  line._p0 = LVecBase3((PN_stdfloat)from.getX(),
327  (PN_stdfloat)from.getY(),
328  (PN_stdfloat)from.getZ());
329  line._p1 = LVecBase3((PN_stdfloat)to.getX(),
330  (PN_stdfloat)to.getY(),
331  (PN_stdfloat)to.getZ());
332  line._color = UnalignedLVecBase4((PN_stdfloat)r,
333  (PN_stdfloat)g,
334  (PN_stdfloat)b, 1.0f);
335 
336  _lines.push_back(line);
337 }
338 
339 /**
340  *
341  */
342 void BulletDebugNode::DebugDraw::
343 drawTriangle(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, const btVector3 &color, btScalar) {
344 
345  btScalar r = color.getX();
346  btScalar g = color.getY();
347  btScalar b = color.getZ();
348 
349  Triangle tri;
350 
351  tri._p0 = LVecBase3((PN_stdfloat)v0.getX(),
352  (PN_stdfloat)v0.getY(),
353  (PN_stdfloat)v0.getZ());
354 
355  tri._p1 = LVecBase3((PN_stdfloat)v1.getX(),
356  (PN_stdfloat)v1.getY(),
357  (PN_stdfloat)v1.getZ());
358 
359  tri._p2 = LVecBase3((PN_stdfloat)v2.getX(),
360  (PN_stdfloat)v2.getY(),
361  (PN_stdfloat)v2.getZ());
362 
363  tri._color = UnalignedLVecBase4((PN_stdfloat)r,
364  (PN_stdfloat)g,
365  (PN_stdfloat)b, 1.0f);
366 
367  _triangles.push_back(tri);
368 
369 
370  // Draw the triangle's normal
371 /*
372  btVector3 x1 = v1 - v0;
373  btVector3 x2 = v2 - v0;
374  btVector3 normal = v1.cross(v2).normalize();
375 
376  btVector3 from = (v0 + v1 + v2) * 0.3333;
377  btVector3 to = from + normal;
378  drawLine(from, to, color);
379 */
380 }
381 
382 /**
383  *
384  */
385 void BulletDebugNode::DebugDraw::
386 drawTriangle(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, const btVector3 &n0, const btVector3 &n1, const btVector3 &n2, const btVector3 &color, btScalar alpha) {
387  if (bullet_cat.is_debug()) {
388  bullet_cat.debug() << "drawTriangle(2) - not yet implemented!" << std::endl;
389  }
390 }
391 
392 /**
393  *
394  */
395 void BulletDebugNode::DebugDraw::
396 drawContactPoint(const btVector3 &point, const btVector3 &normal, btScalar distance, int lifetime, const btVector3 &color) {
397 
398  const btVector3 to = point + normal * distance;
399  const btVector3 &from = point;
400 
401  drawLine(from, to, color);
402 }
403 
404 /**
405  *
406  */
407 void BulletDebugNode::DebugDraw::
408 draw3dText(const btVector3 &location, const char *text) {
409  if (bullet_cat.is_debug()) {
410  bullet_cat.debug() << "draw3dText - not yet implemented!" << std::endl;
411  }
412 }
413 
414 /**
415  *
416  */
417 void BulletDebugNode::DebugDraw::
418 drawSphere(btScalar radius, const btTransform &transform, const btVector3 &color) {
419 
420  btVector3 center = transform.getOrigin();
421 
422  const btVector3 xoffs = transform.getBasis() * btVector3(1, 0, 0);
423  const btVector3 yoffs = transform.getBasis() * btVector3(0, 1, 0);
424  const btVector3 zoffs = transform.getBasis() * btVector3(0, 0, 1);
425 
426  drawArc(center, xoffs, yoffs, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
427  drawArc(center, yoffs, zoffs, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
428  drawArc(center, zoffs, xoffs, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
429 }
430 
431 /**
432  * Tells the BamReader how to create objects of type BulletDebugNode.
433  */
436  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
437 }
438 
439 /**
440  * Writes the contents of this object to the datagram for shipping out to a
441  * Bam file.
442  */
444 write_datagram(BamWriter *manager, Datagram &dg) {
445  PandaNode::write_datagram(manager, dg);
446 
447  dg.add_bool(_wireframe);
448  dg.add_bool(_constraints);
449  dg.add_bool(_bounds);
450  dg.add_bool(_drawer._normals);
451 }
452 
453 /**
454  * This function is called by the BamReader's factory when a new object of
455  * this type is encountered in the Bam file. It should create the rigid body
456  * and extract its information from the file.
457  */
458 TypedWritable *BulletDebugNode::
459 make_from_bam(const FactoryParams &params) {
460  BulletDebugNode *param = new BulletDebugNode;
461  DatagramIterator scan;
462  BamReader *manager;
463 
464  parse_params(params, scan, manager);
465  param->fillin(scan, manager);
466 
467  return param;
468 }
469 
470 /**
471  * This internal function is called by make_from_bam to read in all of the
472  * relevant data from the BamFile for the new BulletDebugNode.
473  */
474 void BulletDebugNode::
475 fillin(DatagramIterator &scan, BamReader *manager) {
476  PandaNode::fillin(scan, manager);
477 
478  _wireframe = scan.get_bool();
479  _constraints = scan.get_bool();
480  _bounds = scan.get_bool();
481  _drawer._normals = scan.get_bool();
482 }
Geom
A container for geometry primitives.
Definition: geom.h:54
geomVertexData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LightMutexHolder
Similar to MutexHolder, but for a light mutex.
Definition: lightMutexHolder.h:25
GeomVertexWriter::set_data4
void set_data4(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat w)
Sets the write row to a particular 4-component value, and advances the write row.
Definition: geomVertexWriter.I:670
cullTraverser.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
CullableObject
The smallest atom of cull.
Definition: cullableObject.h:41
BulletDebugNode::register_with_read_factory
static void register_with_read_factory()
Tells the BamReader how to create objects of type BulletDebugNode.
Definition: bulletDebugNode.cxx:435
GeomVertexData
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
Definition: geomVertexData.h:68
BulletDebugNode::safe_to_transform
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of Node by calling the xform()...
Definition: bulletDebugNode.cxx:71
BulletDebugNode::is_renderable
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
Definition: bulletDebugNode.cxx:161
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
cullableObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
CullTraverser::get_scene
SceneSetup * get_scene() const
Returns the SceneSetup object.
Definition: cullTraverser.I:35
BulletDebugNode::safe_to_flatten_below
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 ...
Definition: bulletDebugNode.cxx:118
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
GeomVertexWriter
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
Definition: geomVertexWriter.h:55
CullTraverser
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
BulletDebugNode::write_datagram
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: bulletDebugNode.cxx:444
BamReader::get_factory
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
geomLines.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
PStatTimer
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
BulletDebugNode::safe_to_combine_children
virtual bool safe_to_combine_children() const
Returns true if it is generally safe to combine the children of this PandaNode with each other.
Definition: bulletDebugNode.cxx:108
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PandaNode::write_datagram
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
DatagramIterator::get_bool
bool get_bool()
Extracts a boolean value.
Definition: datagramIterator.I:48
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
CullHandler::record_object
virtual void record_object(CullableObject *object, const CullTraverser *traverser)
This callback function is intended to be overridden by a derived class.
Definition: cullHandler.cxx:43
PStatCollector
A lightweight class that represents a single element that may be timed and/or counted via stats.
Definition: pStatCollector.h:43
CullTraverserData
This collects together the pieces of data that are accumulated for each node while walking the scene ...
Definition: cullTraverserData.h:40
OmniBoundingVolume
This is a special kind of GeometricBoundingVolume that fills all of space.
Definition: omniBoundingVolume.h:24
geomTriangles.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BulletDebugNode::add_for_draw
virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data)
Adds the node's contents to the CullResult we are building up during the cull traversal,...
Definition: bulletDebugNode.cxx:171
BulletDebugNode::safe_to_modify_transform
virtual bool safe_to_modify_transform() const
Returns true if it is safe to automatically adjust the transform on this kind of node.
Definition: bulletDebugNode.cxx:85
Factory::register_factory
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
GeomTriangles
Defines a series of disconnected triangles.
Definition: geomTriangles.h:23
SceneSetup::get_cs_world_transform
const TransformState * get_cs_world_transform() const
Returns the position from the starting node relative to the camera, in the GSG's internal coordinate ...
Definition: sceneSetup.I:268
omniBoundingVolume.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomLines
Defines a series of disconnected line segments.
Definition: geomLines.h:23
BulletDebugNode
Definition: bulletDebugNode.h:29
BulletDebugNode::safe_to_combine
virtual bool safe_to_combine() const
Returns true if it is generally safe to combine this particular kind of PandaNode with other kinds of...
Definition: bulletDebugNode.cxx:97
Datagram::add_bool
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:34
GeomVertexWriter::set_data3
void set_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row.
Definition: geomVertexWriter.I:640
bulletWorld.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BulletDebugNode::draw_mask_changed
virtual void draw_mask_changed()
Called after the node's DrawMask has been changed for any reason, this just provides a hook so derive...
Definition: bulletDebugNode.cxx:127
geomVertexFormat.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BoundingVolume
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
Definition: boundingVolume.h:41
config_bullet.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
PandaNode::is_overall_hidden
is_overall_hidden
Returns true if the node has been hidden to all cameras by clearing its overall bit.
Definition: pandaNode.h:248
CullTraverser::get_cull_handler
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
Definition: cullTraverser.I:152
cullHandler.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bulletDebugNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
parse_params
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
GeomVertexFormat::get_v3c4
static const GeomVertexFormat * get_v3c4()
Returns a standard vertex format with a 4-component color and a 3-component vertex position.
Definition: geomVertexFormat.I:324
BulletDebugNode::safe_to_flatten
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of Node by duplicating insta...
Definition: bulletDebugNode.cxx:60
GeomPrimitive
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56