Panda3D
Loading...
Searching...
No Matches
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
31TypeHandle BulletDebugNode::_type_handle;
32PStatCollector BulletDebugNode::_pstat_debug("App:Bullet:DoPhysics:Debug");
33
34/**
35 *
36 */
37BulletDebugNode::
38BulletDebugNode(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 */
60safe_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 */
71safe_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 */
97safe_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 */
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 */
118safe_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 */
161is_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 */
276void BulletDebugNode::
277do_sync_b2p(btDynamicsWorld *world) {
278
279 _debug_world = world;
280 _debug_stale = true;
281}
282
283/**
284 *
285 */
286void BulletDebugNode::DebugDraw::
287setDebugMode(int mode) {
288
289 _mode = mode;
290}
291
292/**
293 *
294 */
295int BulletDebugNode::DebugDraw::
296getDebugMode() const {
297
298 return _mode;
299}
300
301/**
302 *
303 */
304void BulletDebugNode::DebugDraw::
305reportErrorWarning(const char *warning) {
306
307 bullet_cat.error() << warning << std::endl;
308}
309
310/**
311 *
312 */
313void BulletDebugNode::DebugDraw::
314drawLine(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 */
342void BulletDebugNode::DebugDraw::
343drawTriangle(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 */
385void BulletDebugNode::DebugDraw::
386drawTriangle(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 */
395void BulletDebugNode::DebugDraw::
396drawContactPoint(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 */
407void BulletDebugNode::DebugDraw::
408draw3dText(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 */
417void BulletDebugNode::DebugDraw::
418drawSphere(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 */
444write_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 */
458TypedWritable *BulletDebugNode::
459make_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 */
474void BulletDebugNode::
475fillin(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}
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.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition bamReader.h:110
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
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
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,...
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 void draw_mask_changed()
Called after the node's DrawMask has been changed for any reason, this just provides a hook so derive...
static void register_with_read_factory()
Tells the BamReader how to create objects of type BulletDebugNode.
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 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_flatten_below() const
Returns true if a flatten operation may safely continue past this node, or false if nodes below this ...
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 safe_to_combine_children() const
Returns true if it is generally safe to combine the children of this PandaNode with each other.
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of Node by calling the xform()...
virtual bool safe_to_modify_transform() const
Returns true if it is safe to automatically adjust the transform on this kind of node.
virtual void record_object(CullableObject *object, const CullTraverser *traverser)
This callback function is intended to be overridden by a derived class.
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,...
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
SceneSetup * get_scene() const
Returns the SceneSetup object.
The smallest atom of cull.
A class to retrieve the individual data elements previously stored in a Datagram.
bool get_bool()
Extracts a boolean value.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition datagram.I:34
An instance of this class is passed to the Factory when requesting it to do its business and construc...
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
Defines a series of disconnected line segments.
Definition geomLines.h:23
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Defines a series of disconnected triangles.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
static const GeomVertexFormat * get_v3c4()
Returns a standard vertex format with a 4-component color and a 3-component vertex position.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
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.
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.
A container for geometry primitives.
Definition geom.h:54
Similar to MutexHolder, but for a light mutex.
This is a special kind of GeometricBoundingVolume that fills all of space.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition pStatTimer.h:30
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
is_overall_hidden
Returns true if the node has been hidden to all cameras by clearing its overall bit.
Definition pandaNode.h:248
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
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
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
Base class for objects that can be written to and read from Bam files.
This is our own Panda specialization on the default STL vector.
Definition pvector.h:42
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.