SO3Engine
OgreNewt_Debugger.cpp
Go to the documentation of this file.
7#include <CustomJoint.h>
8
9#include <sstream>
10
11#include <OgreSceneNode.h>
12#include <OgreSceneManager.h>
13#include <OgreManualObject.h>
14
15namespace OgreNewt
16{
17
19 // DEUBBER FUNCTIONS
21 Debugger::Debugger(const OgreNewt::World* world)
22 {
23 m_world = world;
24 m_debugnode = NULL;
25 m_raycastsnode = NULL;
26 m_defaultcolor = Ogre::ColourValue::White;
27
28 m_recordraycasts = false;
29 m_markhitbodies = false;
30 m_raycol = Ogre::ColourValue::Green;
31 m_convexcol = Ogre::ColourValue::Blue;
32 m_hitbodycol = Ogre::ColourValue::Red;
33 m_prefilterdiscardedcol = Ogre::ColourValue::Black;
34 }
35
37 {
38 deInit();
39 }
40
41 void Debugger::init(Ogre::SceneManager* smgr)
42 {
43 if (!m_debugnode)
44 {
45 m_debugnode = smgr->getRootSceneNode()->createChildSceneNode("__OgreNewt__Debugger__Node__");
46 m_debugnode->setListener(this);
47 }
48
49 if (!m_raycastsnode)
50 {
51 m_raycastsnode = smgr->getRootSceneNode()->createChildSceneNode("__OgreNewt__Raycasts_Debugger__Node__");
52 m_raycastsnode->setListener(this);
53 }
54
55 m_sceneManager = smgr;
56 }
57
59 {
61 if (m_debugnode)
62 {
63 m_debugnode->setListener(NULL);
64 m_debugnode->removeAndDestroyAllChildren();
65 m_debugnode->getParentSceneNode()->removeAndDestroyChild(m_debugnode->getName());
66 m_debugnode = NULL;
67 }
68
69
72 {
73 m_raycastsnode->setListener(NULL);
74 m_raycastsnode->removeAndDestroyAllChildren();
75 m_raycastsnode->getParentSceneNode()->removeAndDestroyChild(m_raycastsnode->getName());
76 m_raycastsnode = NULL;
77 }
78 }
79
80 void Debugger::nodeDestroyed(const Ogre::Node *node)
81 {
82 if (node == m_debugnode)
83 {
84 m_debugnode = NULL;
86 }
87
88 if (node == m_raycastsnode)
89 {
90 m_raycastsnode = NULL;
92 }
93 }
94
95
97 {
98 for (BodyDebugDataMap::iterator it = m_cachemap.begin(); it != m_cachemap.end(); it++)
99 {
100 Ogre::ManualObject* mo = it->second.m_lines;
101 if (mo)
102 delete mo;
103 OgreNewt::OgreAddons::MovableText *text = it->second.m_text;
104 if (text)
105 delete text;
106 }
107 m_cachemap.clear();
108 }
109
110
111
113 {
114 if (!m_debugnode)
115 return;
116
117 m_debugnode->removeAllChildren();
118
119 // make the new lines.
120 for (Body* body = m_world->getFirstBody(); body; body = body->getNext())
121 {
122 processBody(body);
123 }
124
125 // display any joint debug information
126 NewtonWorldForEachJointDo(m_world->getNewtonWorld(), newtonprocessJoints, this);
127
128 // delete old entries
129 BodyDebugDataMap newbodymap;
130 for (BodyDebugDataMap::iterator it = m_cachemap.begin(); it != m_cachemap.end(); it++)
131 {
132 if (it->second.m_updated)
133 newbodymap.insert(*it);
134 else
135 {
136 Ogre::ManualObject* mo = it->second.m_lines;
137 if (mo)
138 delete mo;
139 OgreNewt::OgreAddons::MovableText *text = it->second.m_text;
140 if (text)
141 delete text;
142 }
143 }
144 m_cachemap.swap(newbodymap);
145 }
146
148 {
149 // erase any existing lines!
150 if (m_debugnode)
151 m_debugnode->removeAllChildren();
152 }
153
154 void Debugger::setMaterialColor(const MaterialID* mat, Ogre::ColourValue col)
155 {
156 m_materialcolors[mat->getID()] = col;
157 }
158
159 void Debugger::setDefaultColor(Ogre::ColourValue col)
160 {
161 m_defaultcolor = col;
162 }
163
164
165 void _CDECL Debugger::newtonprocessJoints(const NewtonJoint* newtonJoint, void* userData)
166 {
167 Debugger* me = (Debugger*)userData;
168 CustomJoint* customJoint = (CustomJoint*)NewtonJointGetUserData(newtonJoint);
169 if (customJoint->GetUserData())
170 me->processJoint((Joint*)customJoint->GetUserData());
171 }
172
173
175 {
176 // show joint info
178 }
179
180
181 void Debugger::buildDebugObjectFromCollision(Ogre::ManualObject* object, Ogre::ColourValue colour, const NewtonCollision* shape) const
182 {
183 object->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
184
185 // set color
186 // if( it != m_materialcolors.end() )
187 // object->colour(it->second);
188 // else
189 // object->colour(m_defaultcolor);
190
191 object->colour(colour);
192
193 dFloat matrix[16];
194 Converters::QuatPosToMatrix(Ogre::Quaternion::IDENTITY, Ogre::Vector3::ZERO, &matrix[0]);
195
196 NewtonCollisionForEachPolygonDo(shape, &matrix[0], newtonPerPoly, object);
197 object->setCastShadows(false);
198 object->end();
199 }
200
201
203 {
204 NewtonBody* newtonBody = bod->getNewtonBody();
205 MaterialIdColorMap::iterator it = m_materialcolors.find(NewtonBodyGetMaterialGroupID(newtonBody));
206
207 Ogre::Vector3 pos, vel, omega;
208 Ogre::Quaternion ori;
209 bod->getVisualPositionOrientation(pos, ori);
210
211 vel = bod->getVelocity();
212 omega = bod->getOmega();
213
214 // ----------- create debug-text ------------
215 std::ostringstream oss_name;
216 oss_name << "__OgreNewt__Debugger__Body__" << bod << "__";
217 std::ostringstream oss_info;
218 oss_info.precision(2);
219 oss_info.setf(std::ios::fixed, std::ios::floatfield);
220 Ogre::Vector3 inertia;
221 Ogre::Real mass;
222 bod->getMassMatrix(mass, inertia);
223
224 oss_info << "[" << bod->getOgreNode()->getName() << "]" << std::endl;
225 oss_info << "Mass: " << mass << std::endl;
226 oss_info << "Position: " << pos[0] << " x " << pos[1] << " x " << pos[2] << std::endl;
227 oss_info << "Velocity: " << vel[0] << " x " << vel[1] << " x " << vel[2] << std::endl;
228 oss_info << "Omega: " << omega[0] << " x " << omega[1] << " x " << omega[2] << std::endl;
229 oss_info << "Inertia: " << inertia[0] << " x " << inertia[1] << " x " << inertia[2] << std::endl;
230
231 // ----------- ------------------ ------------
232
233 // look for cached data
234 BodyDebugData* data = &m_cachemap[bod];
235
236 if (data->m_lastcol == bod->getCollision() && (data->m_scale == bod->getOgreNode()->_getDerivedScale())) // use cached data
237 {
238 // set new position...
239 data->m_node->setPosition(pos);
240 data->m_node->setOrientation(ori);
241 data->m_updated = 1;
242 m_debugnode->addChild(data->m_node);
243 data->m_text->setCaption(oss_info.str());
244 data->m_text->setLocalTranslation(bod->getAABB().getSize().y * 1.01f * Ogre::Vector3::UNIT_Y);
245 }
246 else
247 {
248 data->m_lastcol = bod->getCollision();
249 data->m_updated = 1;
250 data->m_scale = bod->getOgreNode()->_getDerivedScale();
251 if (data->m_node)
252 {
253 data->m_node->detachAllObjects();
254 data->m_node->setPosition(pos);
255 data->m_node->setOrientation(ori);
256 }
257 else
258 data->m_node = m_debugnode->createChildSceneNode(pos, ori);
259
260 if (data->m_lines)
261 {
262 data->m_lines->clear();
263 }
264 else
265 {
266 std::ostringstream oss;
267 oss << "__OgreNewt__Debugger__Lines__" << bod << "__";
268 data->m_lines = new Ogre::ManualObject(oss.str());
269 }
270
271 if (data->m_text)
272 {
273 data->m_text->setCaption(oss_info.str());
274 data->m_text->setLocalTranslation(bod->getAABB().getMaximum().y * 1.01f * Ogre::Vector3::UNIT_Y);
275 }
276 else
277 {
278 data->m_text = new OgreNewt::OgreAddons::MovableText(oss_name.str(), oss_info.str(), "BlueHighway-10", bod->getAABB().getSize().y * 0.1f);
279 data->m_text->setLocalTranslation(bod->getAABB().getMaximum().y * 1.01f * Ogre::Vector3::UNIT_Y);
281 }
282
283 data->m_node->attachObject(data->m_text);
284
285 buildDebugObjectFromCollision(data->m_lines, m_defaultcolor, NewtonBodyGetCollision(bod->getNewtonBody()));
286 data->m_lines->setCastShadows(false);
287 data->m_text->setCastShadows(false);
288 data->m_node->attachObject(data->m_lines);
289 }
290 }
291
292
293
294 void _CDECL Debugger::newtonPerPoly(void* userData, int vertexCount, const dFloat* faceVertec, int id)
295 {
296 Ogre::ManualObject* lines = (Ogre::ManualObject*)userData;
297 Ogre::Vector3 p0, p1;
298
299 if (vertexCount < 2)
300 return;
301
302 int i = vertexCount - 1;
303 p0 = Ogre::Vector3(faceVertec[(i * 3) + 0], faceVertec[(i * 3) + 1], faceVertec[(i * 3) + 2]);
304
305
306 for (i = 0; i < vertexCount; i++)
307 {
308 p1 = Ogre::Vector3(faceVertec[(i * 3) + 0], faceVertec[(i * 3) + 1], faceVertec[(i * 3) + 2]);
309
310 lines->position(p0);
311 lines->position(p1);
312
313 p0 = p1;
314 }
315 }
316
317 // ----------------- raycast-debugging -----------------------
318 void Debugger::startRaycastRecording(bool markhitbodies)
319 {
320 m_recordraycasts = true;
321 m_markhitbodies = markhitbodies;
322 }
323
325 {
326 return m_recordraycasts;
327 }
328
333
335 {
336 if (m_raycastsnode)
337 {
338 /*
339 while( m_raycastsnode->numAttachedObjects() > 0 )
340 {
341 delete m_raycastsnode->detachObject((unsigned short)0);
342 }
343 */
344 m_raycastsnode->removeAndDestroyAllChildren();
345 }
346
347 for (ManualObjectList::iterator it = mRecordedRaycastObjects.begin(); it != mRecordedRaycastObjects.end(); it++)
348 {
349 delete (*it);
350 }
352 }
353
355 {
356 m_recordraycasts = false;
357 }
358
359 void Debugger::setRaycastRecordingColor(Ogre::ColourValue rayCol, Ogre::ColourValue convexCol, Ogre::ColourValue hitBodyCol, Ogre::ColourValue prefilterDiscardedBodyCol)
360 {
361 m_raycol = rayCol;
362 m_convexcol = convexCol;
363 m_hitbodycol = hitBodyCol;
364 m_prefilterdiscardedcol = prefilterDiscardedBodyCol;
365 }
366
367 void Debugger::addRay(const Ogre::Vector3 &startpt, const Ogre::Vector3 &endpt)
368 {
369 if (!m_raycastsnode)
370 return;
371
372 static int i = 0;
373 std::ostringstream oss;
374 oss << "__OgreNewt__Raycast_Debugger__Lines__Raycastline__" << i++ << "__";
375 Ogre::ManualObject *line = new Ogre::ManualObject(oss.str());
376
377 line->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
378 line->colour(m_raycol);
379 line->position(startpt);
380 line->position(endpt);
381 line->setCastShadows(false);
382 line->end();
383
384 mRecordedRaycastObjects.push_back(line);
385 m_raycastsnode->attachObject(line);
386 }
387
388 void Debugger::addConvexRay(const OgreNewt::ConvexCollisionPtr& col, const Ogre::Vector3 &startpt, const Ogre::Quaternion &colori, const Ogre::Vector3 &endpt)
389 {
390 if (!m_raycastsnode)
391 return;
392
393 static int i = 0;
394 // lines from aab
395 std::ostringstream oss;
396 oss << "__OgreNewt__Raycast_Debugger__Lines__Convexcastlines__" << i++ << "__";
397 Ogre::ManualObject *line = new Ogre::ManualObject(oss.str());
398
399 line->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
400 line->colour(m_convexcol);
401
402 /*
403 // aab1
404 Ogre::AxisAlignedBox aab1 = col->getAABB(colori, startpt);
405 const Ogre::Vector3* corners1 = aab1.getAllCorners();
406 Ogre::AxisAlignedBox aab2 = col->getAABB(colori, endpt);
407 const Ogre::Vector3* corners2 = aab2.getAllCorners();
408 for(int i = 0; i < 4; i++)
409 {
410 line->position(corners1[i]); line->position(corners1[(i+1)%4]);
411 line->position(corners1[i+4]); line->position(corners1[(i+1)%4+4]);
412 line->position(corners2[i]); line->position(corners2[(i+1)%4]);
413 line->position(corners2[i+4]); line->position(corners2[(i+1)%4+4]);
414 line->position(corners1[i]); line->position(corners2[i]);
415 line->position(corners1[i+4]); line->position(corners2[i+4]);
416 }
417 line->position(corners1[0]); line->position(corners1[6]);
418 line->position(corners1[1]); line->position(corners1[5]);
419 line->position(corners1[2]); line->position(corners1[4]);
420 line->position(corners1[3]); line->position(corners1[7]);
421 line->position(corners2[0]); line->position(corners2[6]);
422 line->position(corners2[1]); line->position(corners2[5]);
423 line->position(corners2[2]); line->position(corners2[4]);
424 line->position(corners2[3]); line->position(corners2[7]);
425 */
426
427 // bodies
428 float matrix[16];
429
430 Converters::QuatPosToMatrix(colori, startpt, &matrix[0]);
431 NewtonCollisionForEachPolygonDo(col->getNewtonCollision(), &matrix[0], newtonPerPoly, line);
432
433 if (endpt != startpt)
434 {
435 Converters::QuatPosToMatrix(colori, endpt, &matrix[0]);
436 NewtonCollisionForEachPolygonDo(col->getNewtonCollision(), &matrix[0], newtonPerPoly, line);
437 }
438 line->setCastShadows(false);
439
440 line->end();
441
442 mRecordedRaycastObjects.push_back(line);
443 m_raycastsnode->attachObject(line);
444 }
445
447 {
448 if (!m_raycastsnode)
449 return;
450
451 static int i = 0;
452 float matrix[16];
453 Ogre::Vector3 pos;
454 Ogre::Quaternion ori;
455
456 std::ostringstream oss;
457 oss << "__OgreNewt__Raycast_Debugger__Lines__DiscardedBody__" << i++ << "__";
458 Ogre::ManualObject *line = new Ogre::ManualObject(oss.str());
459
460 line->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
461 line->colour(m_prefilterdiscardedcol);
462
463 body->getVisualPositionOrientation(pos, ori);
464 Converters::QuatPosToMatrix(ori, pos, &matrix[0]);
465 NewtonCollisionForEachPolygonDo(body->getCollision()->getNewtonCollision(), &matrix[0], newtonPerPoly, line);
466
467 line->setCastShadows(false);
468 line->end();
469
470 mRecordedRaycastObjects.push_back(line);
471 m_raycastsnode->attachObject(line);
472 }
473
475 {
476 if (!m_raycastsnode)
477 return;
478
479 static int i = 0;
480 float matrix[16];
481 Ogre::Vector3 pos;
482 Ogre::Quaternion ori;
483
484 std::ostringstream oss;
485 oss << "__OgreNewt__Raycast_Debugger__Lines__HitBody__" << i++ << "__";
486 Ogre::ManualObject *line = new Ogre::ManualObject(oss.str());
487
488 line->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
489 line->colour(m_hitbodycol);
490
491 body->getVisualPositionOrientation(pos, ori);
492 Converters::QuatPosToMatrix(ori, pos, &matrix[0]);
493 NewtonCollisionForEachPolygonDo(body->getCollision()->getNewtonCollision(), &matrix[0], newtonPerPoly, line);
494
495 line->setCastShadows(false);
496 line->end();
497
498 mRecordedRaycastObjects.push_back(line);
499 m_raycastsnode->attachObject(line);
500 }
501
502} // end namespace OgreNewt
503
main class for all Rigid Bodies in the system.
void getMassMatrix(Ogre::Real &mass, Ogre::Vector3 &inertia) const
get Ogre::Real(mass) and Ogre::Vector3(inertia) of the body.
const OgreNewt::CollisionPtr & getCollision() const
set the factors that cause a body to "freeze" when equilibrium reached.
Ogre::Vector3 getVelocity() const
get velocity of the body. in global coordinates.
Ogre::Vector3 getOmega() const
get omega of the body. in global space.
NewtonBody * getNewtonBody() const
get a pointer to the NewtonBody object
Ogre::AxisAlignedBox getAABB() const
get the axis-aligned bounding box for this body.
Ogre::Node * getOgreNode() const
get a pointer to the attached Node.
void getVisualPositionOrientation(Ogre::Vector3 &pos, Ogre::Quaternion &orient) const
get the node position and orientation in form of an Ogre::Vector(position) and Ogre::Quaternion(orien...
NewtonCollision *const getNewtonCollision() const
retrieve the Newton pointer
represents a collision shape that is explicitly convex.
For viewing the Newton rigid bodies visually.
virtual void nodeDestroyed(const Ogre::Node *)
called when one of the nodes used in this class are destroyed
bool isRaycastRecording()
returns true, if currently recording raycasts
void showDebugInformation()
show the newton world
void setRaycastRecordingColor(Ogre::ColourValue rayCol, Ogre::ColourValue convexCol, Ogre::ColourValue hitBodyCol, Ogre::ColourValue prefilterDiscardedBodyCol)
set the color of the raycast-debug-lines
Ogre::ColourValue m_raycol
MaterialIdColorMap m_materialcolors
void buildDebugObjectFromCollision(Ogre::ManualObject *object, Ogre::ColourValue colour, const NewtonCollision *shape) const
bool isRaycastRecordingHitBodies()
returns true, if hit bodies are currently recording
void setDefaultColor(Ogre::ColourValue col)
set default color
void addHitBody(const OgreNewt::Body *body)
this function is used internally
Ogre::SceneNode * m_debugnode
BodyDebugDataMap m_cachemap
Ogre::ColourValue m_defaultcolor
Ogre::SceneNode * m_raycastsnode
Ogre::ColourValue m_hitbodycol
void clearBodyDebugDataCache()
clear debug data cache for bodies (m_cachemap)
void init(Ogre::SceneManager *smgr)
init the debugger.
void clearRaycastsRecorded()
clears all raycasts, that are currently shown, should probably be done once per frame!
void processJoint(Joint *joint)
call the function to show debug information for this joint
void hideDebugInformation()
remove lines and text drawn
Ogre::ColourValue m_prefilterdiscardedcol
void setMaterialColor(const MaterialID *mat, Ogre::ColourValue col)
set Material color
const OgreNewt::World * m_world
ManualObjectList mRecordedRaycastObjects
std::map< OgreNewt::Body *, BodyDebugData > BodyDebugDataMap
void addDiscardedBody(const OgreNewt::Body *body)
this function is used internally
void deInit()
de-init the debugger (cleantup)
Ogre::ColourValue m_convexcol
void addConvexRay(const OgreNewt::ConvexCollisionPtr &col, const Ogre::Vector3 &startpt, const Ogre::Quaternion &colori, const Ogre::Vector3 &endpt)
this function is used internally
void stopRaycastRecording()
disables raycast-debugging
Ogre::SceneManager * m_sceneManager
void processBody(Body *body)
create debug information for one body
void startRaycastRecording(bool markhitbodies=false)
enable additional raycast-debugging (this also enables displaying of recorded raycasts!...
void addRay(const Ogre::Vector3 &startpt, const Ogre::Vector3 &endpt)
this function is used internally
base class for all joints.
virtual void showDebugData(Ogre::SceneNode *debugRootNode)
show joint visual debugging data
represents a material
int getID() const
get Newton-assigned material ID.
void setCaption(const Ogre::String &caption)
void setLocalTranslation(Ogre::Vector3 trans)
void setTextAlignment(const HorizontalAlignment &horizontalAlignment, const VerticalAlignment &verticalAlignment)
represents a physics world.
NewtonWorld * getNewtonWorld() const
retrieves a pointer to the NewtonWorld
Body * getFirstBody() const
to iterate through all bodies call this function and then use body->getNext()
_OgreNewtExport void QuatPosToMatrix(const Ogre::Quaternion &quat, const Ogre::Vector3 &pos, dFloat *matrix)
Take a Quaternion and Position Matrix and create a Newton-happy float matrix!
OgreNewt::OgreAddons::MovableText * m_text