debugDraw.cpp
Engine/source/gfx/sim/debugDraw.cpp
Public Variables
Public Functions
ConsoleDocClass(DebugDrawer , "@brief A debug helper <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> rendering debug primitives <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">scene.\n\n</a>" "The <a href="/coding/class/classdebugdrawer/">DebugDrawer</a> is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> debug primitives <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the scene <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> testing. It is " "often useful when debugging collision code or complex 3d algorithms <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> have " "them draw debug information, like culling hulls or bounding volumes, normals , " "simple lines, and so <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">forth.\n\n</a>" "A key feature of the <a href="/coding/class/classdebugdrawer/">DebugDrawer</a> is that each primitive gets <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> \"time <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> live\" (TTL) " "which allows them <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> continue <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the scene <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> fixed period of time. You " "can freeze or resume the system at any time <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow you <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> examine the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">output.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "DebugDraw.drawLine( %player.getMuzzlePoint( 0 ), %hitPoint );\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "DebugDraw.setLastTTL( 5000 ); // 5 <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">seconds.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" "The <a href="/coding/class/classdebugdrawer/">DebugDrawer</a> renders solely in world space and all primitives are rendered with the " "cull <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disabled.\n</a>" "@note This feature can easily be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> cheat in online games, so you should be sure " "it is disabled in your shipping game. By default the <a href="/coding/class/classdebugdrawer/">DebugDrawer</a> is disabled in all " "TORQUE_SHIPPING <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">builds.\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GFX\n</a>" )
DefineEngineMethod(DebugDrawer , drawBox , void , (Point3F a, Point3F b, LinearColorF color) , (LinearColorF::WHITE) , "Draws an axis aligned box primitive within the two 3d points." )
DefineEngineMethod(DebugDrawer , drawLine , void , (Point3F a, Point3F b, LinearColorF color) , (LinearColorF::WHITE) , "Draws <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> line primitive between two 3d points." )
DefineEngineMethod(DebugDrawer , setLastTTL , void , (U32 ms) , "Sets the \"time <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> live\" (TTL) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the last rendered primitive." )
DefineEngineMethod(DebugDrawer , setLastZTest , void , (bool enabled) , "Sets the z buffer reading state <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the last rendered primitive." )
DefineEngineMethod(DebugDrawer , toggleDrawing , void , () , "Toggles the rendering of <a href="/coding/class/classdebugdrawer/">DebugDrawer</a> primitives." )
DefineEngineMethod(DebugDrawer , toggleFreeze , void , () , "Toggles freeze <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> which keeps the currently rendered primitives from expiring." )
Detailed Description
Public Variables
MODULE_END
MODULE_INIT
Public Functions
ConsoleDocClass(DebugDrawer , "@brief A debug helper <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> rendering debug primitives <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">scene.\n\n</a>" "The <a href="/coding/class/classdebugdrawer/">DebugDrawer</a> is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> debug primitives <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the scene <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> testing. It is " "often useful when debugging collision code or complex 3d algorithms <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> have " "them draw debug information, like culling hulls or bounding volumes, normals , " "simple lines, and so <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">forth.\n\n</a>" "A key feature of the <a href="/coding/class/classdebugdrawer/">DebugDrawer</a> is that each primitive gets <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> \"time <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> live\" (TTL) " "which allows them <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> continue <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the scene <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> fixed period of time. You " "can freeze or resume the system at any time <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow you <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> examine the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">output.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "DebugDraw.drawLine( %player.getMuzzlePoint( 0 ), %hitPoint );\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "DebugDraw.setLastTTL( 5000 ); // 5 <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">seconds.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" "The <a href="/coding/class/classdebugdrawer/">DebugDrawer</a> renders solely in world space and all primitives are rendered with the " "cull <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disabled.\n</a>" "@note This feature can easily be used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> cheat in online games, so you should be sure " "it is disabled in your shipping game. By default the <a href="/coding/class/classdebugdrawer/">DebugDrawer</a> is disabled in all " "TORQUE_SHIPPING <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">builds.\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GFX\n</a>" )
DefineEngineMethod(DebugDrawer , drawBox , void , (Point3F a, Point3F b, LinearColorF color) , (LinearColorF::WHITE) , "Draws an axis aligned box primitive within the two 3d points." )
DefineEngineMethod(DebugDrawer , drawLine , void , (Point3F a, Point3F b, LinearColorF color) , (LinearColorF::WHITE) , "Draws <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> line primitive between two 3d points." )
DefineEngineMethod(DebugDrawer , setLastTTL , void , (U32 ms) , "Sets the \"time <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> live\" (TTL) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the last rendered primitive." )
DefineEngineMethod(DebugDrawer , setLastZTest , void , (bool enabled) , "Sets the z buffer reading state <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the last rendered primitive." )
DefineEngineMethod(DebugDrawer , toggleDrawing , void , () , "Toggles the rendering of <a href="/coding/class/classdebugdrawer/">DebugDrawer</a> primitives." )
DefineEngineMethod(DebugDrawer , toggleFreeze , void , () , "Toggles freeze <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> which keeps the currently rendered primitives from expiring." )
IMPLEMENT_CONOBJECT(DebugDrawer )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "gfx/sim/debugDraw.h" 26 27#include "gfx/gFont.h" 28#include "gfx/gfxDrawUtil.h" 29#include "gfx/gfxTransformSaver.h" 30#include "gfx/gfxDebugEvent.h" 31#include "math/mathUtils.h" 32#include "math/util/frustum.h" 33#include "console/console.h" 34#include "scene/sceneManager.h" 35#include "core/module.h" 36#include "console/engineAPI.h" 37 38#include "math/mPolyhedron.impl.h" 39 40 41MODULE_BEGIN( DebugDrawer ) 42 43 MODULE_INIT_AFTER( Sim ) 44 MODULE_INIT_AFTER( GFX ) 45 46 // DebugDrawer will register itself as a SimObject and 47 // thus get automatically shut down with Sim. 48 49 MODULE_INIT 50 { 51 DebugDrawer::init(); 52 } 53 54MODULE_END; 55 56 57DebugDrawer* DebugDrawer::sgDebugDrawer = NULL; 58 59IMPLEMENT_CONOBJECT(DebugDrawer); 60 61ConsoleDocClass( DebugDrawer, 62 "@brief A debug helper for rendering debug primitives to the scene.\n\n" 63 64 "The DebugDrawer is used to render debug primitives to the scene for testing. It is " 65 "often useful when debugging collision code or complex 3d algorithms to have " 66 "them draw debug information, like culling hulls or bounding volumes, normals, " 67 "simple lines, and so forth.\n\n" 68 69 "A key feature of the DebugDrawer is that each primitive gets a \"time to live\" (TTL) " 70 "which allows them to continue to render to the scene for a fixed period of time. You " 71 "can freeze or resume the system at any time to allow you to examine the output.\n" 72 73 "@tsexample\n" 74 "DebugDraw.drawLine( %player.getMuzzlePoint( 0 ), %hitPoint );\n" 75 "DebugDraw.setLastTTL( 5000 ); // 5 seconds.\n" 76 "@endtsexample\n" 77 78 "The DebugDrawer renders solely in world space and all primitives are rendered with the " 79 "cull mode disabled.\n" 80 81 "@note This feature can easily be used to cheat in online games, so you should be sure " 82 "it is disabled in your shipping game. By default the DebugDrawer is disabled in all " 83 "TORQUE_SHIPPING builds.\n" 84 85 "@ingroup GFX\n" ); 86 87DebugDrawer::DebugDrawer() 88{ 89 mHead = NULL; 90 isFrozen = false; 91 shouldToggleFreeze = false; 92 93#ifdef ENABLE_DEBUGDRAW 94 isDrawing = true; 95#else 96 isDrawing = false; 97#endif 98} 99 100DebugDrawer::~DebugDrawer() 101{ 102 if( sgDebugDrawer == this ) 103 sgDebugDrawer = NULL; 104} 105 106DebugDrawer* DebugDrawer::get() 107{ 108 if (sgDebugDrawer) 109 { 110 return sgDebugDrawer; 111 } else { 112 DebugDrawer::init(); 113 return sgDebugDrawer; 114 } 115} 116 117void DebugDrawer::init() 118{ 119#ifdef ENABLE_DEBUGDRAW 120 sgDebugDrawer = new DebugDrawer(); 121 sgDebugDrawer->registerObject("DebugDraw"); 122 Sim::getRootGroup()->addObject( sgDebugDrawer ); 123 Con::warnf( "DebugDrawer Enabled!" ); 124#endif 125} 126 127void DebugDrawer::setupStateBlocks() 128{ 129 GFXStateBlockDesc d; 130 131 d.setCullMode(GFXCullNone); 132 mRenderZOnSB = GFX->createStateBlock(d); 133 134 d.setZReadWrite(false); 135 mRenderZOffSB = GFX->createStateBlock(d); 136 137 d.setCullMode(GFXCullCCW); 138 d.setZReadWrite(true, false); 139 d.setBlend(true); 140 mRenderAlpha = GFX->createStateBlock(d); 141} 142 143void DebugDrawer::drawBoxOutline(const Point3F &a, const Point3F &b, const LinearColorF &color) 144{ 145 Point3F point0(a.x, a.y, a.z); 146 Point3F point1(a.x, b.y, a.z); 147 Point3F point2(b.x, b.y, a.z); 148 Point3F point3(b.x, a.y, a.z); 149 150 Point3F point4(a.x, a.y, b.z); 151 Point3F point5(a.x, b.y, b.z); 152 Point3F point6(b.x, b.y, b.z); 153 Point3F point7(b.x, a.y, b.z); 154 155 // Draw one plane 156 drawLine(point0, point1, color); 157 drawLine(point1, point2, color); 158 drawLine(point2, point3, color); 159 drawLine(point3, point0, color); 160 161 // Draw the other plane 162 drawLine(point4, point5, color); 163 drawLine(point5, point6, color); 164 drawLine(point6, point7, color); 165 drawLine(point7, point4, color); 166 167 // Draw the connecting corners 168 drawLine(point0, point4, color); 169 drawLine(point1, point5, color); 170 drawLine(point2, point6, color); 171 drawLine(point3, point7, color); 172} 173 174void DebugDrawer::drawTransformedBoxOutline(const Point3F &a, const Point3F &b, const LinearColorF &color, const MatrixF& transform) 175{ 176 Point3F point0(a.x, a.y, a.z); 177 Point3F point1(a.x, b.y, a.z); 178 Point3F point2(b.x, b.y, a.z); 179 Point3F point3(b.x, a.y, a.z); 180 181 Point3F point4(a.x, a.y, b.z); 182 Point3F point5(a.x, b.y, b.z); 183 Point3F point6(b.x, b.y, b.z); 184 Point3F point7(b.x, a.y, b.z); 185 186 transform.mulP(point0); 187 transform.mulP(point1); 188 transform.mulP(point2); 189 transform.mulP(point3); 190 transform.mulP(point4); 191 transform.mulP(point5); 192 transform.mulP(point6); 193 transform.mulP(point7); 194 195 // Draw one plane 196 drawLine(point0, point1, color); 197 drawLine(point1, point2, color); 198 drawLine(point2, point3, color); 199 drawLine(point3, point0, color); 200 201 // Draw the other plane 202 drawLine(point4, point5, color); 203 drawLine(point5, point6, color); 204 drawLine(point6, point7, color); 205 drawLine(point7, point4, color); 206 207 // Draw the connecting corners 208 drawLine(point0, point4, color); 209 drawLine(point1, point5, color); 210 drawLine(point2, point6, color); 211 drawLine(point3, point7, color); 212} 213 214void DebugDrawer::render(bool clear) 215{ 216#ifdef ENABLE_DEBUGDRAW 217 if(!isDrawing) 218 return; 219 220 GFXDEBUGEVENT_SCOPE( DebugDrawer, ColorI::GREEN ); 221 222 if (!mRenderZOnSB) 223 { 224 setupStateBlocks(); 225 String fontCacheDir = Con::getVariable("$GUI::fontCacheDirectory"); 226 mFont = GFont::create("Arial", 12, fontCacheDir); 227 } 228 229 SimTime curTime = Sim::getCurrentTime(); 230 231 for(DebugPrim **walk = &mHead; *walk; ) 232 { 233 GFX->setupGenericShaders(); 234 DebugPrim *p = *walk; 235 236 // Set up the state block... 237 GFXStateBlockRef currSB; 238 if(p->type==DebugPrim::Capsule) 239 { 240 currSB = mRenderAlpha; 241 } 242 else if(p->useZ) 243 { 244 currSB = mRenderZOnSB; 245 } 246 else 247 { 248 currSB = mRenderZOffSB; 249 } 250 251 GFX->setStateBlock( currSB ); 252 253 Point3F d; 254 const ColorI color = p->color.toColorI(); 255 256 switch(p->type) 257 { 258 case DebugPrim::Tri: 259 PrimBuild::begin( GFXLineStrip, 4); 260 261 PrimBuild::color(p->color); 262 263 PrimBuild::vertex3fv(p->a); 264 PrimBuild::vertex3fv(p->b); 265 PrimBuild::vertex3fv(p->c); 266 PrimBuild::vertex3fv(p->a); 267 268 PrimBuild::end(); 269 break; 270 case DebugPrim::DirectionLine: 271 { 272 const static F32 ARROW_LENGTH = 0.2f, ARROW_RADIUS = 0.035f, CYLINDER_RADIUS = 0.008f; 273 Point3F &start = p->a, &end = p->b; 274 Point3F direction = end - start; 275 F32 length = direction.len(); 276 if( length>ARROW_LENGTH ) 277 { 278 //cylinder with arrow on end 279 direction *= (1.0f/length); 280 Point3F baseArrow = end - (direction*ARROW_LENGTH); 281 GFX->getDrawUtil()->drawCone(currSB->getDesc(), baseArrow, end, ARROW_RADIUS, color); 282 GFX->getDrawUtil()->drawCylinder(currSB->getDesc(), start, baseArrow, CYLINDER_RADIUS, color); 283 } 284 else if( length>0 ) 285 { 286 //short, so just draw arrow 287 GFX->getDrawUtil()->drawCone(currSB->getDesc(), start, end, ARROW_RADIUS, color); 288 } 289 } 290 break; 291 case DebugPrim::Capsule: 292 GFX->getDrawUtil()->drawCapsule(currSB->getDesc(), p->a, p->b.x, p->b.y, color); 293 break; 294 case DebugPrim::OutlinedText: 295 { 296 GFXTransformSaver saver; 297 Point3F result; 298 if (MathUtils::mProjectWorldToScreen(p->a, &result, GFX->getViewport(), GFX->getWorldMatrix(), GFX->getProjectionMatrix())) 299 { 300 GFX->setClipRect(GFX->getViewport()); 301 Point2I where = Point2I(result.x, result.y); 302 //only switch statement that uses p->color2 303 GFX->getDrawUtil()->setBitmapModulation(p->color2.toColorI()); 304 GFX->getDrawUtil()->drawText(mFont, Point2I(where.x-1, where.y), p->mText); 305 GFX->getDrawUtil()->drawText(mFont, Point2I(where.x+1, where.y), p->mText); 306 GFX->getDrawUtil()->drawText(mFont, Point2I(where.x, where.y-1), p->mText); 307 GFX->getDrawUtil()->drawText(mFont, Point2I(where.x, where.y+1), p->mText); 308 309 GFX->getDrawUtil()->setBitmapModulation(color); 310 GFX->getDrawUtil()->drawText(mFont, where, p->mText); 311 } 312 } 313 break; 314 case DebugPrim::Box: 315 d = p->a - p->b; 316 GFX->getDrawUtil()->drawCube(currSB->getDesc(), d * 0.5, (p->a + p->b) * 0.5, color); 317 break; 318 case DebugPrim::Line: 319 PrimBuild::begin( GFXLineStrip, 2); 320 321 PrimBuild::color(color); 322 323 PrimBuild::vertex3fv(p->a); 324 PrimBuild::vertex3fv(p->b); 325 326 PrimBuild::end(); 327 break; 328 case DebugPrim::Text: 329 { 330 GFXTransformSaver saver; 331 Point3F result; 332 if (MathUtils::mProjectWorldToScreen(p->a, &result, GFX->getViewport(), GFX->getWorldMatrix(), GFX->getProjectionMatrix())) 333 { 334 GFX->setClipRect(GFX->getViewport()); 335 GFX->getDrawUtil()->setBitmapModulation(color); 336 GFX->getDrawUtil()->drawText(mFont, Point2I(result.x, result.y), p->mText); 337 } 338 } 339 break; 340 } 341 342 // Ok, we've got data, now freeze here if needed. 343 if (shouldToggleFreeze) 344 { 345 isFrozen = !isFrozen; 346 shouldToggleFreeze = false; 347 } 348 349 if(clear && p->dieTime <= curTime && !isFrozen && p->dieTime != U32_MAX) 350 { 351 *walk = p->next; 352 mPrimChunker.free(p); 353 } 354 else 355 walk = &((*walk)->next); 356 } 357#endif 358} 359 360void DebugDrawer::drawBox(const Point3F &a, const Point3F &b, const LinearColorF &color) 361{ 362 if(isFrozen || !isDrawing) 363 return; 364 365 DebugPrim *n = mPrimChunker.alloc(); 366 367 n->useZ = true; 368 n->dieTime = 0; 369 n->a = a; 370 n->b = b; 371 n->color = color; 372 n->type = DebugPrim::Box; 373 374 n->next = mHead; 375 mHead = n; 376} 377 378void DebugDrawer::drawLine(const Point3F &a, const Point3F &b, const LinearColorF &color) 379{ 380 if(isFrozen || !isDrawing) 381 return; 382 383 DebugPrim *n = mPrimChunker.alloc(); 384 385 n->useZ = true; 386 n->dieTime = 0; 387 n->a = a; 388 n->b = b; 389 n->color = color; 390 n->type = DebugPrim::Line; 391 392 n->next = mHead; 393 mHead = n; 394} 395 396void DebugDrawer::drawCapsule(const Point3F &a, const F32 &radius, const F32 &height, const LinearColorF &color) 397{ 398 if(isFrozen || !isDrawing) 399 return; 400 401 DebugPrim *n = mPrimChunker.alloc(); 402 403 n->useZ = true; 404 n->dieTime = 0; 405 n->a = a; 406 n->b.x = radius; 407 n->b.y = height; 408 n->color = color; 409 n->type = DebugPrim::Capsule; 410 411 n->next = mHead; 412 mHead = n; 413 414} 415 416void DebugDrawer::drawDirectionLine(const Point3F &a, const Point3F &b, const LinearColorF &color) 417{ 418 if(isFrozen || !isDrawing) 419 return; 420 421 DebugPrim *n = mPrimChunker.alloc(); 422 423 n->useZ = true; 424 n->dieTime = 0; 425 n->a = a; 426 n->b = b; 427 n->color = color; 428 n->type = DebugPrim::DirectionLine; 429 430 n->next = mHead; 431 mHead = n; 432} 433 434void DebugDrawer::drawOutlinedText(const Point3F& pos, const String& text, const LinearColorF &color, const LinearColorF &colorOutline) 435{ 436 if(isFrozen || !isDrawing) 437 return; 438 439 DebugPrim *n = mPrimChunker.alloc(); 440 441 n->useZ = false; 442 n->dieTime = 0; 443 n->a = pos; 444 n->color = color; 445 n->color2 = colorOutline; 446 dStrncpy(n->mText, text.c_str(), 256); 447 n->type = DebugPrim::OutlinedText; 448 449 n->next = mHead; 450 mHead = n; 451} 452 453void DebugDrawer::drawTri(const Point3F &a, const Point3F &b, const Point3F &c, const LinearColorF &color) 454{ 455 if(isFrozen || !isDrawing) 456 return; 457 458 DebugPrim *n = mPrimChunker.alloc(); 459 460 n->useZ = true; 461 n->dieTime = 0; 462 n->a = a; 463 n->b = b; 464 n->c = c; 465 n->color = color; 466 n->type = DebugPrim::Tri; 467 468 n->next = mHead; 469 mHead = n; 470} 471 472void DebugDrawer::drawPolyhedron( const AnyPolyhedron& polyhedron, const LinearColorF& color ) 473{ 474 const PolyhedronData::Edge* edges = polyhedron.getEdges(); 475 const Point3F* points = polyhedron.getPoints(); 476 const U32 numEdges = polyhedron.getNumEdges(); 477 478 for( U32 i = 0; i < numEdges; ++ i ) 479 { 480 const PolyhedronData::Edge& edge = edges[ i ]; 481 drawLine( points[ edge.vertex[ 0 ] ], points[ edge.vertex[ 1 ] ], color ); 482 } 483} 484 485void DebugDrawer::drawPolyhedronDebugInfo( const AnyPolyhedron& polyhedron, const MatrixF& transform, const Point3F& scale ) 486{ 487 Point3F center = polyhedron.getCenterPoint(); 488 center.convolve( scale ); 489 transform.mulP( center ); 490 491 // Render plane indices and normals. 492 493 const U32 numPlanes = polyhedron.getNumPlanes(); 494 for( U32 i = 0; i < numPlanes; ++ i ) 495 { 496 const AnyPolyhedron::PlaneType& plane = polyhedron.getPlanes()[ i ]; 497 498 Point3F planePos = plane.getPosition(); 499 planePos.convolve( scale ); 500 transform.mulP( planePos ); 501 502 Point3F normal = plane.getNormal(); 503 transform.mulV( normal ); 504 505 drawText( planePos, String::ToString( i ), ColorI::BLACK ); 506 drawLine( planePos, planePos + normal, ColorI::GREEN ); 507 } 508 509 // Render edge indices and direction indicators. 510 511 const U32 numEdges = polyhedron.getNumEdges(); 512 for( U32 i = 0; i < numEdges; ++ i ) 513 { 514 const AnyPolyhedron::EdgeType& edge = polyhedron.getEdges()[ i ]; 515 516 Point3F v1 = polyhedron.getPoints()[ edge.vertex[ 0 ] ]; 517 Point3F v2 = polyhedron.getPoints()[ edge.vertex[ 1 ] ]; 518 519 v1.convolve( scale ); 520 v2.convolve( scale ); 521 transform.mulP( v1 ); 522 transform.mulP( v2 ); 523 524 const Point3F midPoint = v1 + ( v2 - v1 ) / 2.f; 525 526 drawText( midPoint, String::ToString( "%i (%i, %i)", i, edge.face[ 0 ], edge.face[ 1 ] ), ColorI::WHITE ); 527 528 // Push out the midpoint away from the center to place the direction indicator. 529 530 Point3F pushDir = midPoint - center; 531 pushDir.normalize(); 532 const Point3F dirPoint = midPoint + pushDir; 533 const Point3F lineDir = ( v2 - v1 ) / 2.f; 534 535 drawLine( dirPoint, dirPoint + lineDir, ColorI::RED ); 536 } 537 538 // Render point indices and coordinates. 539 540 const U32 numPoints = polyhedron.getNumPoints(); 541 for( U32 i = 0; i < numPoints; ++ i ) 542 { 543 Point3F p = polyhedron.getPoints()[ i ]; 544 545 p.convolve( scale ); 546 transform.mulP( p ); 547 548 drawText( p, String::ToString( "%i: (%.2f, %.2f, %.2f)", i, p.x, p.y, p.z ), LinearColorF::WHITE ); 549 } 550} 551 552void DebugDrawer::drawText(const Point3F& pos, const String& text, const LinearColorF &color) 553{ 554 if(isFrozen || !isDrawing) 555 return; 556 557 DebugPrim *n = mPrimChunker.alloc(); 558 559 n->useZ = false; 560 n->dieTime = 0; 561 n->a = pos; 562 n->color = color; 563 dStrncpy(n->mText, text.c_str(), 256); 564 n->type = DebugPrim::Text; 565 566 n->next = mHead; 567 mHead = n; 568} 569 570void DebugDrawer::setLastTTL(U32 ms) 571{ 572 AssertFatal(mHead, "Tried to set last with nothing in the list!"); 573 if (ms != U32_MAX) 574 mHead->dieTime = Sim::getCurrentTime() + ms; 575 else 576 mHead->dieTime = U32_MAX; 577} 578 579void DebugDrawer::setLastZTest(bool enabled) 580{ 581 AssertFatal(mHead, "Tried to set last with nothing in the list!"); 582 mHead->useZ = enabled; 583} 584 585DefineEngineMethod( DebugDrawer, drawLine, void, ( Point3F a, Point3F b, LinearColorF color ), ( LinearColorF::WHITE ), 586 "Draws a line primitive between two 3d points." ) 587{ 588 object->drawLine( a, b, color ); 589} 590 591DefineEngineMethod( DebugDrawer, drawBox, void, ( Point3F a, Point3F b, LinearColorF color ), ( LinearColorF::WHITE ), 592 "Draws an axis aligned box primitive within the two 3d points." ) 593{ 594 object->drawBox( a, b, color ); 595} 596 597DefineEngineMethod( DebugDrawer, setLastTTL, void, ( U32 ms ),, 598 "Sets the \"time to live\" (TTL) for the last rendered primitive." ) 599{ 600 object->setLastTTL( ms ); 601} 602 603DefineEngineMethod( DebugDrawer, setLastZTest, void, ( bool enabled ),, 604 "Sets the z buffer reading state for the last rendered primitive." ) 605{ 606 object->setLastZTest( enabled ); 607} 608 609DefineEngineMethod( DebugDrawer, toggleFreeze, void, (),, 610 "Toggles freeze mode which keeps the currently rendered primitives from expiring." ) 611{ 612 object->toggleFreeze(); 613} 614 615DefineEngineMethod( DebugDrawer, toggleDrawing, void, (),, 616 "Toggles the rendering of DebugDrawer primitives." ) 617{ 618 object->toggleDrawing(); 619} 620 621