Panda3D

collisionVisualizer.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 collisionVisualizer.cxx
10 * @author drose
11 * @date 2003-04-16
12 */
13
14 #include "collisionVisualizer.h"
15 #include "collisionEntry.h"
16 #include "cullTraverser.h"
17 #include "cullTraverserData.h"
18 #include "cullableObject.h"
19 #include "cullHandler.h"
20 #include "renderState.h"
21 #include "renderModeAttrib.h"
22 #include "geomVertexData.h"
23 #include "geomVertexFormat.h"
24 #include "geomVertexArrayFormat.h"
25 #include "geom.h"
26 #include "geomPoints.h"
27 #include "geomLines.h"
28 #include "omniBoundingVolume.h"
29 #include "depthOffsetAttrib.h"
30 #include "colorScaleAttrib.h"
31 #include "transparencyAttrib.h"
32 #include "clipPlaneAttrib.h"
33 #include "geomVertexWriter.h"
34
35
36 #ifdef DO_COLLISION_RECORDING
37
38 TypeHandle CollisionVisualizer::_type_handle;
39
40 /**
41 *
42 */
43 CollisionVisualizer::
44 CollisionVisualizer(const std::string &name) : PandaNode(name), _lock("CollisionVisualizer") {
45 set_cull_callback();
46
47 // We always want to render the CollisionVisualizer node itself (even if it
48 // doesn't appear to have any geometry within it).
49 set_internal_bounds(new OmniBoundingVolume());
50 _point_scale = 1.0f;
51 _normal_scale = 1.0f;
52 }
53
54 /**
55 * Copy constructor.
56 */
57 CollisionVisualizer::
58 CollisionVisualizer(const CollisionVisualizer &copy) :
59 PandaNode(copy),
60 _lock("CollisionVisualizer"),
61 _point_scale(copy._point_scale),
62 _normal_scale(copy._normal_scale) {
63
64 set_cull_callback();
65
66 // We always want to render the CollisionVisualizer node itself (even if it
67 // doesn't appear to have any geometry within it).
68 set_internal_bounds(new OmniBoundingVolume());
69 }
70
71 /**
72 *
73 */
74 CollisionVisualizer::
75 ~CollisionVisualizer() {
76 }
77
78 /**
79 * Removes all the visualization data from a previous traversal and resets the
80 * visualizer to empty.
81 */
82 void CollisionVisualizer::
83 clear() {
84 LightMutexHolder holder(_lock);
85 _data.clear();
86 }
87
88 /**
89 * Returns a newly-allocated Node that is a shallow copy of this one. It will
90 * be a different Node pointer, but its internal data may or may not be shared
91 * with that of the original Node.
92 */
93 PandaNode *CollisionVisualizer::
94 make_copy() const {
95 return new CollisionVisualizer(*this);
96 }
97
98 /**
99 * This function will be called during the cull traversal to perform any
100 * additional operations that should be performed at cull time. This may
101 * include additional manipulation of render state or additional
102 * visible/invisible decisions, or any other arbitrary operation.
103 *
104 * Note that this function will *not* be called unless set_cull_callback() is
105 * called in the constructor of the derived class. It is necessary to call
106 * set_cull_callback() to indicated that we require cull_callback() to be
107 * called.
108 *
109 * By the time this function is called, the node has already passed the
110 * bounding-volume test for the viewing frustum, and the node's transform and
111 * state have already been applied to the indicated CullTraverserData object.
112 *
113 * The return value is true if this node should be visible, or false if it
114 * should be culled.
115 */
116 bool CollisionVisualizer::
117 cull_callback(CullTraverser *trav, CullTraverserData &data) {
118 // Now we go through and actually draw our visualized collision solids.
119
120 LightMutexHolder holder(_lock);
121
122 Data::const_iterator di;
123 for (di = _data.begin(); di != _data.end(); ++di) {
124 const TransformState *net_transform = (*di).first;
125 const VizInfo &viz_info = (*di).second;
126
127 CullTraverserData xform_data(data);
128
129 // We don't want to inherit the transform from above! We ignore whatever
130 // transforms were above the CollisionVisualizer node; it always renders
131 // its objects according to their appropriate net transform.
132 xform_data._net_transform = TransformState::make_identity();
133 xform_data._view_frustum = trav->get_view_frustum();
134 xform_data.apply_transform(net_transform);
135
136 // Draw all the collision solids.
137 Solids::const_iterator si;
138 for (si = viz_info._solids.begin(); si != viz_info._solids.end(); ++si) {
139 // Note that we don't preserve the clip plane attribute from the
140 // collision solid. We always draw the whole polygon (or whatever) in
141 // the CollisionVisualizer. This is a deliberate decision; clipping the
142 // polygons may obscure many collision tests that are being made.
143 const CollisionSolid *solid = (*si).first;
144 const SolidInfo &solid_info = (*si).second;
145 bool was_detected = (solid_info._detected_count > 0);
146 PT(PandaNode) node = solid->get_viz(trav, xform_data, !was_detected);
147 if (node != nullptr) {
148 CullTraverserData next_data(xform_data, node);
149
150 // We don't want to inherit the render state from above for these
151 // guys.
152 next_data._state = get_viz_state();
153 trav->traverse(next_data);
154 }
155 }
156
157 // Now draw all of the detected points.
158 if (!viz_info._points.empty()) {
159 CPT(RenderState) empty_state = RenderState::make_empty();
160 CPT(RenderState) point_state = RenderState::make(RenderModeAttrib::make(RenderModeAttrib::M_unchanged, 1.0f, false));
161
162 PT(GeomVertexArrayFormat) point_array_format =
163 new GeomVertexArrayFormat(InternalName::get_vertex(), 3,
164 Geom::NT_stdfloat, Geom::C_point,
165 InternalName::get_color(), 1,
166 Geom::NT_packed_dabc, Geom::C_color,
167 InternalName::get_size(), 1,
168 Geom::NT_stdfloat, Geom::C_other);
169 CPT(GeomVertexFormat) point_format =
170 GeomVertexFormat::register_format(point_array_format);
171
172 Points::const_iterator pi;
173 for (pi = viz_info._points.begin(); pi != viz_info._points.end(); ++pi) {
174 const CollisionPoint &point = (*pi);
175
176 // Draw a small red point at the surface point, and a smaller white
177 // point at the interior point.
178 {
179 PT(GeomVertexData) point_vdata =
180 new GeomVertexData("viz", point_format, Geom::UH_stream);
181
182 PT(GeomPoints) points = new GeomPoints(Geom::UH_stream);
183
184 GeomVertexWriter vertex(point_vdata, InternalName::get_vertex());
185 GeomVertexWriter color(point_vdata, InternalName::get_color());
186 GeomVertexWriter size(point_vdata, InternalName::get_size());
187
188 vertex.add_data3(point._surface_point);
189 color.add_data4(1.0f, 0.0f, 0.0f, 1.0f);
190 size.add_data1f(16.0f * _point_scale);
191 points->add_next_vertices(1);
192 points->close_primitive();
193
194 if (point._interior_point != point._surface_point) {
195 vertex.add_data3(point._interior_point);
196 color.add_data4(1.0f, 1.0f, 1.0f, 1.0f);
197 size.add_data1f(8.0f * _point_scale);
198 points->add_next_vertices(1);
199 points->close_primitive();
200 }
201
202 PT(Geom) geom = new Geom(point_vdata);
203 geom->add_primitive(points);
204
205 CullableObject *object =
206 new CullableObject(geom, point_state,
207 xform_data.get_internal_transform(trav));
208
209 trav->get_cull_handler()->record_object(object, trav);
210 }
211
212 // Draw the normal vector at the surface point.
213 if (!point._surface_normal.almost_equal(LVector3::zero())) {
214 PT(GeomVertexData) line_vdata =
215 new GeomVertexData("viz", GeomVertexFormat::get_v3cp(),
216 Geom::UH_stream);
217
218 PT(GeomLines) lines = new GeomLines(Geom::UH_stream);
219
220 GeomVertexWriter vertex(line_vdata, InternalName::get_vertex());
221 GeomVertexWriter color(line_vdata, InternalName::get_color());
222
223 vertex.add_data3(point._surface_point);
224 vertex.add_data3(point._surface_point +
225 point._surface_normal * _normal_scale);
226 color.add_data4(1.0f, 0.0f, 0.0f, 1.0f);
227 color.add_data4(1.0f, 1.0f, 1.0f, 1.0f);
228 lines->add_next_vertices(2);
229 lines->close_primitive();
230
231 PT(Geom) geom = new Geom(line_vdata);
232 geom->add_primitive(lines);
233
234 CullableObject *object =
235 new CullableObject(geom, empty_state,
236 xform_data.get_internal_transform(trav));
237
238 trav->get_cull_handler()->record_object(object, trav);
239 }
240 }
241 }
242 }
243
244 // Now carry on to render our child nodes.
245 return true;
246 }
247
248 /**
249 * Returns true if there is some value to visiting this particular node during
250 * the cull traversal for any camera, false otherwise. This will be used to
251 * optimize the result of get_net_draw_show_mask(), so that any subtrees that
252 * contain only nodes for which is_renderable() is false need not be visited.
253 */
254 bool CollisionVisualizer::
255 is_renderable() const {
256 return true;
257 }
258
259
260 /**
261 * Writes a brief description of the node to the indicated output stream.
262 * This is invoked by the << operator. It may be overridden in derived
263 * classes to include some information relevant to the class.
264 */
265 void CollisionVisualizer::
266 output(std::ostream &out) const {
267 PandaNode::output(out);
268 out << " ";
269 CollisionRecorder::output(out);
270 }
271
272 /**
273 * This method is called at the beginning of a CollisionTraverser::traverse()
274 * call. It is provided as a hook for the derived class to reset its state as
275 * appropriate.
276 */
277 void CollisionVisualizer::
278 begin_traversal() {
279 CollisionRecorder::begin_traversal();
280 LightMutexHolder holder(_lock);
281 _data.clear();
282 }
283
284 /**
285 * This method is called when a pair of collision solids have passed all
286 * bounding-volume tests and have been tested for a collision. The detected
287 * value is set true if a collision was detected, false otherwise.
288 */
289 void CollisionVisualizer::
290 collision_tested(const CollisionEntry &entry, bool detected) {
291 CollisionRecorder::collision_tested(entry, detected);
292
293 NodePath node_path = entry.get_into_node_path();
294 CPT(TransformState) net_transform = node_path.get_net_transform();
295 CPT(CollisionSolid) solid = entry.get_into();
296 nassertv(!solid.is_null());
297
298 LightMutexHolder holder(_lock);
299 VizInfo &viz_info = _data[std::move(net_transform)];
300 if (detected) {
301 viz_info._solids[std::move(solid)]._detected_count++;
302
303 if (entry.has_surface_point()) {
304 CollisionPoint p;
305 entry.get_all(entry.get_into_node_path(),
306 p._surface_point, p._surface_normal, p._interior_point);
307 viz_info._points.push_back(p);
308 }
309
310 } else {
311 viz_info._solids[std::move(solid)]._missed_count++;
312 }
313 }
314
315
316 /**
317 * Returns a RenderState suitable for rendering the collision solids with
318 * which a collision was detected.
319 */
320 CPT(RenderState) CollisionVisualizer::
321 get_viz_state() {
322 // Once someone asks for this pointer, we hold its reference count and never
323 // free it.
324 static CPT(RenderState) state = nullptr;
325 if (state == nullptr) {
326 state = RenderState::make
327 (DepthOffsetAttrib::make());
328 }
329
330 return state;
331 }
332
333 #endif // DO_COLLISION_RECORDING
CollisionEntry
Defines a single collision event.
Definition: collisionEntry.h:42
CollisionEntry::get_into
get_into
Returns the CollisionSolid pointer for the particular solid was collided into.
Definition: collisionEntry.h:98
CollisionEntry::has_surface_point
bool has_surface_point() const
Returns true if the surface point has been specified, false otherwise.
Definition: collisionEntry.I:192
CollisionEntry::get_into_node_path
get_into_node_path
Returns the NodePath that represents the specific CollisionNode or GeomNode instance that was collide...
Definition: collisionEntry.h:102
CollisionEntry::get_all
bool get_all(const NodePath &space, LPoint3 &surface_point, LVector3 &surface_normal, LPoint3 &interior_point) const
Simultaneously transforms the surface point, surface normal, and interior point of the collision into...
Definition: collisionEntry.cxx:120
CollisionSolid
The abstract base class for all things that can collide with other things in the world,...
Definition: collisionSolid.h:45
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
CullTraverserData
This collects together the pieces of data that are accumulated for each node while walking the scene ...
Definition: cullTraverserData.h:40
CullTraverser
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
CullTraverser::get_cull_handler
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
Definition: cullTraverser.I:152
CullTraverser::get_view_frustum
GeometricBoundingVolume * get_view_frustum() const
Returns the bounding volume that corresponds to the view frustum, or NULL if the view frustum is not ...
Definition: cullTraverser.I:135
CullTraverser::traverse
void traverse(const NodePath &root)
Begins the traversal from the indicated node.
Definition: cullTraverser.cxx:106
CullableObject
The smallest atom of cull.
Definition: cullableObject.h:41
GeomLines
Defines a series of disconnected line segments.
Definition: geomLines.h:23
GeomPoints
Defines a series of disconnected points.
Definition: geomPoints.h:23
GeomVertexArrayFormat
This describes the structure of a single array within a Geom data.
Definition: geomVertexArrayFormat.h:47
GeomVertexData
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
Definition: geomVertexData.h:68
GeomVertexFormat
This class defines the physical layout of the vertex data stored within a Geom.
Definition: geomVertexFormat.h:55
GeomVertexFormat::get_v3cp
static const GeomVertexFormat * get_v3cp()
Returns a standard vertex format with a packed color and a 3-component vertex position.
Definition: geomVertexFormat.I:287
GeomVertexWriter
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
Definition: geomVertexWriter.h:55
Geom
A container for geometry primitives.
Definition: geom.h:54
LightMutexHolder
Similar to MutexHolder, but for a light mutex.
Definition: lightMutexHolder.h:25
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
OmniBoundingVolume
This is a special kind of GeometricBoundingVolume that fills all of space.
Definition: omniBoundingVolume.h:24
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
TransformState
Indicates a coordinate-system transform on vertices.
Definition: transformState.h:54
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
clipPlaneAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
collisionEntry.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
collisionVisualizer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
colorScaleAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cullHandler.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cullTraverserData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cullTraverser.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cullableObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
depthOffsetAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomLines.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomPoints.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexArrayFormat.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexFormat.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geom.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
omniBoundingVolume.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
renderModeAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
renderState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
transparencyAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.