- added debug line drawing in gameengine (handy for debugging physics problems)
authorErwin Coumans <blender@erwincoumans.com>
Wed, 27 Jul 2005 09:30:53 +0000 (09:30 +0000)
committerErwin Coumans <blender@erwincoumans.com>
Wed, 27 Jul 2005 09:30:53 +0000 (09:30 +0000)
- added #ifdef for a visual studio 8 crashing problems
- added scaling and tolerances to triangle meshes

23 files changed:
extern/bullet/Bullet/CollisionShapes/CollisionShape.h
extern/bullet/Bullet/CollisionShapes/StridingMeshInterface.h
extern/bullet/Bullet/CollisionShapes/TriangleMesh.h
extern/bullet/Bullet/CollisionShapes/TriangleMeshShape.cpp
extern/bullet/Bullet/CollisionShapes/TriangleMeshShape.h
extern/bullet/Bullet/NarrowPhaseCollision/ContinuousConvexCollision.cpp
extern/bullet/BulletDynamics/CollisionDispatch/ConvexConcaveCollisionAlgorithm.cpp
extern/bullet/BulletDynamics/CollisionDispatch/ConvexConcaveCollisionAlgorithm.h
extern/bullet/LinearMath/SimdQuadWord.h
intern/moto/include/MT_Scalar.h
source/gameengine/Converter/KX_BlenderSceneConverter.cpp
source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
source/gameengine/Ketsji/KX_MeshProxy.cpp
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_PythonInit.h
source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
source/gameengine/Rasterizer/RAS_IRasterizer.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h

index 6969075f38c3589e8d7c545b5267c19c47ca34af..2a2d0543bb271398619a3aca265a1a3ea48a98a4 100644 (file)
@@ -69,6 +69,8 @@ public:
        const char * m_tempDebug;
 //endif debugging support
 
+       virtual void    SetMargin(float margin) = 0;
+       virtual float   GetMargin() const = 0;
 
 };     
 
index 3bdcd7edb3848ccf45416dd2eacc2a5cf32d6a05..d212c6f890457df4b863216d1ccab803cb3bd890 100644 (file)
@@ -34,7 +34,7 @@ class  StridingMeshInterface
        public:
                StridingMeshInterface() :m_scaling(1.f,1.f,1.f)
                {
-                       
+
                }
 
                virtual ~StridingMeshInterface();
@@ -64,6 +64,8 @@ class  StridingMeshInterface
                {
                        m_scaling = scaling;
                }
+
+
 };
 
 #endif //STRIDING_MESHINTERFACE_H
index 6701ccbc3287df586ff2b56a9011d013d3b0e94b..37e29bf3b08702525a39fb1604298223b4b8f03d 100644 (file)
@@ -27,6 +27,7 @@ struct MyTriangle
 class TriangleMesh : public StridingMeshInterface
 {
        std::vector<MyTriangle> m_triangles;
+       
 
        public:
                TriangleMesh ();
@@ -56,8 +57,7 @@ class TriangleMesh : public StridingMeshInterface
                virtual void    preallocateVertices(int numverts){}
                virtual void    preallocateIndices(int numindices){}
 
-
-
+               
 };
 
 #endif //TRIANGLE_MESH_H
\ No newline at end of file
index 996c740acce4343b3a2258126a20528520c5a817..c9c7a73b9328f5e64097b6cf58a065987a371ce8 100644 (file)
@@ -17,7 +17,8 @@
 
 
 TriangleMeshShape::TriangleMeshShape(StridingMeshInterface* meshInterface)
-: m_meshInterface(meshInterface)
+: m_meshInterface(meshInterface),
+m_collisionMargin(0.1f)
 {
 }
 
@@ -31,16 +32,16 @@ TriangleMeshShape::~TriangleMeshShape()
 
 void TriangleMeshShape::GetAabb(const SimdTransform& trans,SimdVector3& aabbMin,SimdVector3& aabbMax) const
 {
-       SimdScalar margin = 0.5f;
+
        for (int i=0;i<3;i++)
        {
                SimdVector3 vec(0.f,0.f,0.f);
                vec[i] = 1.f;
                SimdVector3 tmp = trans(LocalGetSupportingVertex(vec*trans.getBasis()));
-               aabbMax[i] = tmp[i]+margin;
+               aabbMax[i] = tmp[i]+m_collisionMargin;
                vec[i] = -1.f;
                tmp = trans(LocalGetSupportingVertex(vec*trans.getBasis()));
-               aabbMin[i] = tmp[i]-margin;
+               aabbMin[i] = tmp[i]-m_collisionMargin;
        }
 }
 
index ecd9cc530fd8a39b654aa2c79c3f7273aadabb51..2083985e6ccd1e33759363e8425b0ad0d9b18708 100644 (file)
@@ -24,7 +24,8 @@ class TriangleMeshShape : public CollisionShape
 {
 
        StridingMeshInterface* m_meshInterface;
-       
+       float m_collisionMargin;
+
 public:
        TriangleMeshShape(StridingMeshInterface* meshInterface);
 
@@ -57,6 +58,16 @@ public:
        //debugging
        virtual char*   GetName()const {return "TRIANGLEMESH";}
 
+       
+       virtual float GetMargin() const {
+               return m_collisionMargin;
+       }
+       virtual void SetMargin(float collisionMargin)
+       {
+               m_collisionMargin = collisionMargin;
+       }
+
+
 
 };
 
index 21baabfb864b5fc256f52f63430b0cd6c9bcab4d..2369b02b1b9228baa9c500bc636c6b6ae211da66 100644 (file)
@@ -120,13 +120,18 @@ bool      ContinuousConvexCollision::calcTimeOfImpact(
 
                        lambda = lambda + dLambda;
 
+                       if (lambda > 1.f)
+                               return false;
+
+                       if (lambda < 0.f)
+                               return false;
+
                        //todo: next check with relative epsilon
                        if (lambda <= lastLambda)
                                break;
                        lastLambda = lambda;
 
-                       if (lambda > 1.f)
-                               return false;
+                       
 
                        //interpolate to next lambda
                        SimdTransform interpolatedTransA,interpolatedTransB,relativeTrans;
index 5dac60a9e06d5f22ffe0b3e50bdb351484c9020a..6a815cb3113215b6f193fff68c0380eafdd41d40 100644 (file)
@@ -83,6 +83,8 @@ void BoxTriangleCallback::ProcessTriangle(SimdVector3* triangle)
        if (m_boxProxy->IsConvexShape())
        {
                TriangleShape tm(triangle[0],triangle[1],triangle[2]);  
+               tm.SetMargin(m_collisionMarginTriangle);
+
                RigidBody* triangleBody = (RigidBody* )m_triangleProxy.m_clientObject;
                
                triangleBody->SetCollisionShape(&tm);
@@ -97,11 +99,12 @@ void BoxTriangleCallback::ProcessTriangle(SimdVector3* triangle)
 
 
 
-void   BoxTriangleCallback::SetTimeStepAndCounters(float timeStep,int stepCount,bool useContinuous)
+void   BoxTriangleCallback::SetTimeStepAndCounters(float timeStep,int stepCount,float collisionMarginTriangle,bool useContinuous)
 {
        m_timeStep = timeStep;
        m_stepCount = stepCount;
        m_useContinuous = useContinuous;
+       m_collisionMarginTriangle = collisionMarginTriangle;
 
        //recalc aabbs
        RigidBody* boxBody = (RigidBody* )m_boxProxy->m_clientObject;
@@ -141,8 +144,9 @@ void ConvexConcaveCollisionAlgorithm::ProcessCollision (BroadphaseProxy* ,Broadp
                
                if (m_convex.IsConvexShape())
                {
+                       float collisionMarginTriangle = triangleMesh->GetMargin();
                                        
-                       m_boxTriangleCallback.SetTimeStepAndCounters(timeStep,stepCount, useContinuous);
+                       m_boxTriangleCallback.SetTimeStepAndCounters(timeStep,stepCount, collisionMarginTriangle,useContinuous);
 #ifdef USE_BOX_TRIANGLE
                        m_boxTriangleCallback.m_manifoldPtr->ClearManifold();
 #endif
@@ -161,6 +165,8 @@ void ConvexConcaveCollisionAlgorithm::ProcessCollision (BroadphaseProxy* ,Broadp
 float ConvexConcaveCollisionAlgorithm::CalculateTimeOfImpact(BroadphaseProxy* ,BroadphaseProxy* ,float timeStep,int stepCount)
 {
 
+       return 1.f;
+
        //quick approximation using raycast, todo: use proper continuou collision detection
        RigidBody* convexbody = (RigidBody* )m_convex.m_clientObject;
        const SimdVector3& from = convexbody->getCenterOfMassPosition();
@@ -193,7 +199,7 @@ float ConvexConcaveCollisionAlgorithm::CalculateTimeOfImpact(BroadphaseProxy* ,B
                RigidBody* concavebody = (RigidBody* )m_concave.m_clientObject;
 
                TriangleMeshShape* triangleMesh = (TriangleMeshShape*) concavebody->GetCollisionShape();
-
+               
                if (triangleMesh)
                {
                        triangleMesh->ProcessAllTriangles(&raycastCallback,aabbMin,aabbMax);
index 35248c841c6b8c5753f91fa3bb0f31ac3ca4c370..10ff0718d923fe35dfcfe2f191229cc58f8533e6 100644 (file)
@@ -33,6 +33,7 @@ class BoxTriangleCallback : public TriangleCallback
        float   m_timeStep;
        int     m_stepCount;
        bool m_useContinuous;
+       float m_collisionMarginTriangle;
        
 public:
 
@@ -40,7 +41,7 @@ public:
 
        BoxTriangleCallback(Dispatcher* dispatcher,BroadphaseProxy* proxy0,BroadphaseProxy* proxy1);
 
-       void    SetTimeStepAndCounters(float timeStep,int stepCount, bool useContinuous);
+       void    SetTimeStepAndCounters(float timeStep,int stepCount, float collisionMarginTriangle,bool useContinuous);
 
        virtual ~BoxTriangleCallback();
 
index efce56617a61b10749b00ea506fcd111b3911bbb..f256a21555945fd30edaedeacc24c497647c52ec 100644 (file)
@@ -92,16 +92,14 @@ class       SimdQuadWord
                }
 
                SIMD_FORCE_INLINE SimdQuadWord() 
-               :m_x(0),m_y(0),m_z(0)
-               //todo, remove this in release/simd ?
-               ,m_unusedW(0)
+               :m_x(0.f),m_y(0.f),m_z(0.f),m_unusedW(0.f)
                {
                }
 
                SIMD_FORCE_INLINE SimdQuadWord(const SimdScalar& x, const SimdScalar& y, const SimdScalar& z) 
                :m_x(x),m_y(y),m_z(z)
                //todo, remove this in release/simd ?
-               ,m_unusedW(0)
+               ,m_unusedW(0.f)
                {
                }
 
index 6ee0948f24408ac855609406f885ed26345ed600..5cf9f76e592cca6b8d34ec9a03ceabd9c946b170 100755 (executable)
@@ -52,7 +52,8 @@
 #include "MT_random.h"
 #include "NM_Scalar.h"
 
-typedef double MT_Scalar;
+typedef double MT_Scalar; //this should be float !
+
 
 const MT_Scalar  MT_DEGS_PER_RAD(57.29577951308232286465);
 const MT_Scalar  MT_RADS_PER_DEG(0.01745329251994329547);
index f8a628bd0c7ecc579e0882b21de02b17b2426df4..298a909150f21b9b043c7ea969cd0ef105c0099d 100644 (file)
@@ -170,7 +170,22 @@ static struct Scene *GetSceneForName2(struct Main *maggie, const STR_String& sce
 
        return (Scene*) maggie->scene.first;
 }
+#include "KX_PythonInit.h"
 
+#ifdef USE_BULLET
+struct BlenderDebugDraw : public PHY_IPhysicsDebugDraw
+{
+       virtual void    DrawLine(const SimdVector3& from,const SimdVector3& to,const SimdVector3& color)
+       {
+               MT_Vector3 kxfrom(from[0],from[1],from[2]);
+               MT_Vector3 kxto(to[0],to[1],to[2]);
+               MT_Vector3 kxcolor(color[0],color[1],color[2]);
+
+               KX_RasterizerDrawDebugLine(kxfrom,kxto,kxcolor);
+       }
+};
+
+#endif
 
 void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
                                                                                        class KX_Scene* destinationscene,
@@ -226,7 +241,9 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
 #ifdef USE_BULLET
                case UseBullet:
                        {
-                               destinationscene->SetPhysicsEnvironment(new CcdPhysicsEnvironment());
+                               CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment();
+                               ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw());
+                               destinationscene->SetPhysicsEnvironment(ccdPhysEnv);
                                break;
                        }
 #endif
index 8c3a17f58f3dfafa1b90d004c3a74e90bce3fc05..3d81046e8e9ce770901ee77ceafa2cb96eb95c45 100644 (file)
@@ -173,6 +173,7 @@ void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode,
        int lines;
        char* s = tmpstr.Ptr();
        char* p;
+       
 
        // Save and change OpenGL settings
        int texture2D;
@@ -182,6 +183,11 @@ void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode,
        glGetIntegerv(GL_FOG, (GLint*)&fog);
        glDisable(GL_FOG);
        
+       int light;
+       glGetIntegerv(GL_LIGHTING, (GLint*)&light);
+       glDisable(GL_LIGHTING);
+
+       
        // Set up viewing settings
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
@@ -228,6 +234,10 @@ void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode,
                glEnable(GL_TEXTURE_2D);
        else
                glDisable(GL_TEXTURE_2D);
+       if (light)
+               glEnable(GL_LIGHTING);
+       else
+               glDisable(GL_LIGHTING);
 }
 
 /**
index 60a9d560a0617e2faa2baa8ccf0133be8077910a..b8cf5491d41896a6260379f4c3a410ee944dbe4a 100644 (file)
 /* These are defined by the build system... */
 //#define USE_SUMO_SOLID
 //#define USE_ODE
-//#define USE_BULLET
+
+//on visual studio 8, always enable BULLET. 
+//you can have multiple physics engines running anyway, and 
+//the build system doesn't really support this at the moment.
+#if 1400 > _MSC_VER
+#define USE_BULLET
+#endif
 
 class RAS_MeshObject;
 class KX_Scene;
index 38e55ee6723c4d852a96cbe1b5ed7d705f64436e..04b08575364804cc0f3393ebbbc413c30a80035f 100644 (file)
@@ -854,6 +854,7 @@ static CollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool p
 
 
 
+
 void   KX_ConvertBulletObject( class   KX_GameObject* gameobj,
        class   RAS_MeshObject* meshobj,
        class   KX_Scene* kxscene,
@@ -864,6 +865,8 @@ void        KX_ConvertBulletObject( class   KX_GameObject* gameobj,
 
                CcdPhysicsEnvironment* env = (CcdPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
        assert(env);
+
+
        
 
        bool dyna = false;
@@ -954,6 +957,7 @@ void        KX_ConvertBulletObject( class   KX_GameObject* gameobj,
                                if (bm)
                                {
                                        bm->CalculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
+                                       bm->SetMargin(0.f);
                                }
                                break;
                        }
index 37d8581631453ad8cda331f21658e0a460c9656e..b4b3cea8c8a3ddce9374d706756c3dcad9efcdbc 100644 (file)
@@ -213,5 +213,6 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* self,
 KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh,
 "Reinstance the physics mesh.")
 {
-       return Py_Success(KX_ReInstanceShapeFromMesh(m_meshobj));
+       //this needs to be reviewed, it is dependend on Sumo/Solid. Who is using this ?
+       return Py_None;//Py_Success(KX_ReInstanceShapeFromMesh(m_meshobj));
 }
index 6f2fced3bd1bcddf7408b9ae5dd2378df948cf24..fedd45c65e815725677051664d2e12280b78a33e 100644 (file)
@@ -78,6 +78,12 @@ static RAS_ICanvas* gp_Canvas = NULL;
 static KX_Scene*       gp_KetsjiScene = NULL;
 static RAS_IRasterizer* gp_Rasterizer = NULL;
 
+void   KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)
+{
+       if (gp_Rasterizer)
+               gp_Rasterizer->DrawDebugLine(from,to,color);
+}
+
 /* Macro for building the keyboard translation */
 //#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(SCA_IInputDevice::KX_##name))
 #define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(name))
index dc4bad05efb7e1d891d3e29278f91323afbfd6f5..85616e26b6c4a65faa6361d595844ab2cc30b9ac 100644 (file)
@@ -51,6 +51,9 @@ void          exitGamePlayerPythonScripting();
 PyObject*      initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level);
 void           exitGamePythonScripting();
 void PHY_SetActiveScene(class KX_Scene* scene);
+#include "MT_Vector3.h"
+
+void           KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color);
 
 #endif //__KX_PYTHON_INIT
 
index 609f0fc0e0b608979c8c143d0445baf493611777..a062a348b02281e4d86bd80c7b557b0ecc3da869 100644 (file)
@@ -1,3 +1,6 @@
+#include "KX_ConvertPhysicsObject.h"
+
+#ifdef USE_SUMO_SOLID
 
 #ifdef WIN32
 #pragma warning (disable : 4786)
@@ -216,3 +219,4 @@ KX_SumoPhysicsController::~KX_SumoPhysicsController()
 }
 
 
+#endif//USE_SUMO_SOLID
index 376a75f40d39d39a1de2f6399dce1f5487d8f810..8b423204bec5e51ed4d831d1df3ae86a28e35429 100644 (file)
@@ -7,7 +7,7 @@
 
 class BP_Proxy;
 
-bool gEnableSleeping = true;//false;//true;
+bool gEnableSleeping = false;//false;//true;
 #include "Dynamics/MassProps.h"
 
 SimdVector3 startVel(0,0,0);//-10000);
index 2a89cd0cf4a717db27c004907cc878035c67cb81..a4c9df51466368142758dcaa0a5693cb6c8ca249 100644 (file)
@@ -47,6 +47,43 @@ void DrawRasterizerLine(const float* from,const float* to,int color);
 
 
 
+
+static void DrawAabb(PHY_IPhysicsDebugDraw* debugDrawer,const SimdVector3& from,const SimdVector3& to,const SimdVector3& color)
+{
+       SimdVector3 halfExtents = (to-from)* 0.5f;
+       SimdVector3 center = (to+from) *0.5f;
+       int i,j;
+
+       SimdVector3 edgecoord(1.f,1.f,1.f),pa,pb;
+       for (i=0;i<4;i++)
+       {
+               for (j=0;j<3;j++)
+               {
+                       pa = SimdVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],              
+                               edgecoord[2]*halfExtents[2]);
+                       pa+=center;
+                       
+                       int othercoord = j%3;
+                       edgecoord[othercoord]*=-1.f;
+                       pb = SimdVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],      
+                               edgecoord[2]*halfExtents[2]);
+                       pb+=center;
+                       
+                       debugDrawer->DrawLine(pa,pb,color);
+               }
+               edgecoord = SimdVector3(-1.f,-1.f,-1.f);
+               if (i<3)
+                       edgecoord[i]*=-1.f;
+       }
+
+
+}
+
+
+
+
+
+
 CcdPhysicsEnvironment::CcdPhysicsEnvironment(ToiContactDispatcher* dispatcher,BroadphaseInterface* bp)
 :m_dispatcher(dispatcher),
 m_broadphase(bp),
@@ -402,10 +439,16 @@ bool      CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep)
                                
                                SimdPoint3 minAabb,maxAabb;
                                CollisionShape* shapeinterface = ctrl->GetCollisionShape();
+
+
+
                                shapeinterface->CalculateTemporalAabb(body->getCenterOfMassTransform(),
                                        body->getLinearVelocity(),body->getAngularVelocity(),
                                        timeStep,minAabb,maxAabb);
 
+                               shapeinterface->GetAabb(body->getCenterOfMassTransform(),
+                                       minAabb,maxAabb);
+
                                
                                BroadphaseProxy* bp = (BroadphaseProxy*) ctrl->m_broadphaseHandle;
                                if (bp)
@@ -414,7 +457,11 @@ bool       CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep)
 #ifdef WIN32
                                        SimdVector3 color (1,0,0);
                                        if (m_debugDrawer)
-                                               m_debugDrawer->DrawLine(minAabb,maxAabb,color);
+                                       {       
+                                               //draw aabb
+
+                                               DrawAabb(m_debugDrawer,minAabb,maxAabb,color);
+                                       }
 #endif
                                        scene->SetAabb(bp,minAabb,maxAabb);
                                }
index 48991566fa5466275e13aa4473cd71798782276a..03c7e1d5116834ab7e89f5ef5c31fea5460fb864 100644 (file)
@@ -333,6 +333,7 @@ public:
         */
        virtual void    SetPolygonOffset(float mult, float add) = 0;
        
+       virtual void    DrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)=0;
 };
 
 #endif //__RAS_IRASTERIZER
index 95688580fa3b51ff020d2ef305612a4dc8d71999..f9d70f1d23f6158a259990a65f4885da2e38ea4a 100644 (file)
@@ -401,6 +401,21 @@ void RAS_OpenGLRasterizer::ClearCachingInfo(void)
 
 void RAS_OpenGLRasterizer::EndFrame()
 {
+       //DrawDebugLines
+       glBegin(GL_LINES);
+       for (unsigned int i=0;i<m_debugLines.size();i++)
+       {
+               glColor4f(m_debugLines[i].m_color[0],m_debugLines[i].m_color[1],m_debugLines[i].m_color[2],1.f);
+               const MT_Scalar* fromPtr = &m_debugLines[i].m_from.x();
+               const MT_Scalar* toPtr= &m_debugLines[i].m_to.x();
+
+               glVertex3dv(fromPtr);
+               glVertex3dv(toPtr);
+       }
+       glEnd();
+
+       m_debugLines.clear();
+
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        m_2DCanvas->EndFrame();
 }      
index 2571cee13334e5f7d6a52d05bf1d7677bd3f4e43..ad6bdf8c1d17f708f770a8de3fff1776f7350fc1 100644 (file)
@@ -44,6 +44,13 @@ using namespace std;
 #include "RAS_MaterialBucket.h"
 #include "RAS_ICanvas.h"
 
+struct OglDebugLine
+{
+       MT_Vector3      m_from;
+       MT_Vector3      m_to;
+       MT_Vector3      m_color;
+};
+
 /**
  * 3D rendering device context.
  */
@@ -226,6 +233,17 @@ public:
                                        );
        virtual void    SetPolygonOffset(float mult, float add);
 
+       virtual void    DrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)
+       {
+               OglDebugLine line;
+               line.m_from = from;
+               line.m_to = to;
+               line.m_color = color;
+               m_debugLines.push_back(line);
+       }
+
+       std::vector <OglDebugLine>      m_debugLines;
+
 };
 
 #endif //__RAS_OPENGLRASTERIZER