[BULLET] Camera/object positions?

Started by
3 comments, last by Jesse Dager 11 years ago

I am creating a new game engine (I have done it before) and I would like to integrate bullet physics. However, I ran into the problem that there isn't much documentation for the library, also, I use directX and have a very hard time converting from OpenGL to directX.

I would like to create a way for the camera to follow a terrain a set height above it (an FPS camera). I created (I think) a collision with the terrain mesh, but have no idea where to start with creating a camera follow. I know that there are other threads based on this, but I just don't understand enough about bullet to really follow them.

I finally would also like to create physics objects based on a .X file, but again, have no idea where to start. can anyone help???

Thanks,

Seth

I develop to expand the universe. "Live long and code strong!" - Delta_Echo (dream.in.code)
Advertisement

You might find what you are looking for in the demo code that comes with Bullet. I don't really use DirectX so I can't say for sure, but there is DirectX cloth demo, and you may be able to figure out how to manage the camera from that.

-Josh

--www.physicaluncertainty.com
--linkedin
--irc.freenode.net#gdnet

I have integrated Bullet Physics into a D3D9 class engine and it is not that difficult. Let me share an overview of Bullet, I may be glossing over many details, please refer to the Wiki page and other web resources as well.

You start by creating an object that derives from btCollisionWorld, like btDiscreteDynamicsWorld. You can tick this object using the stepSimulation member, which will basically identify all contacts between "collision" objects and update their positions based on physical properties like gravity, mass, etc.

Collision objects fall into two classes (well three if you consider the character controller), rigid bodies, soft bodies and kinematic objects. You can add immovable (static) collision objects by setting the mass to a special constant (0.0f). You add rigid bodies using the addRigidBody member of your collision world object. You can do ray testing against the objects in your world using the rayTest() member of the collision world object.

When first creating your collision world, you need to select and specify a collision dispatcher, a broadphase object, a constraint solver and some config data. Your program needs to allocate and de-allocate all objects and memory passed to Bullet, the library does not own any pointers provided to it.

The choice of broadphase object can determine how well the collision world responds to very dynamic rigid bodies changing position every frame. You can overload both broadphase and nearphase collision responses and filters (so you can make a player rigid body collide with nothing but the ground, but make every other rigid body bounce off the player, for instance).

You can also declare a debug drawer and provide a D3D9 implementation to help you visualize the collision world and the collision objects as you place them in the world.

Here's the debug drawer I use, maybe it would help you?


//-----------------------------------------------------------------------------
// File: CDebugDrawer.h
//
// Purpose: A debug drawer used by the physics library.
//
// Copyright (c) 2007-2011 Steve Segreto. All rights reserved.
//-----------------------------------------------------------------------------
#pragma once
#include "LinearMath/btIDebugDraw.h"
#include <vector>
struct VCol
{
    VCol(
        const D3DXVECTOR3& v,
        D3DCOLOR           c
        ) : pos(v),col(c)
    {
    }
    D3DXVECTOR3 pos;
    D3DCOLOR col;
};
void VisualizeRay (
    D3DXVECTOR3 rayStartW,
    D3DXVECTOR3 rayDirW,
    D3DXCOLOR   color
    );
void VisualizeLineSegment (
    D3DXVECTOR3 startW,
    D3DXVECTOR3 endW,
    D3DXCOLOR   color
    );
void VisualizeBox (
    struct AABB* box,
    D3DXCOLOR color = D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f )
    );
void VisualizeBox (
    struct OBB* box,
    D3DXCOLOR color = D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f )
    );
void VisualizeQuad (
    D3DXVECTOR3 topLeft,
    D3DXVECTOR3 bottomRight,
    D3DXCOLOR color = D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f )
    );
void VisualizeFrustum (
    D3DXVECTOR3* corners,
    D3DXCOLOR    color
    );
void VisualizeRotation (
    D3DXVECTOR3 posW,
    D3DXQUATERNION rot,
    D3DXCOLOR colorX = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f),
    D3DXCOLOR colorY = D3DXCOLOR(1.0f, 1.0f, 0.0f, 1.0f),
    D3DXCOLOR colorZ = D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)
    );
void VisualizeRotation (
    D3DXVECTOR3 posW,
    D3DXMATRIX rot,
    D3DXCOLOR colorX = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f),
    D3DXCOLOR colorY = D3DXCOLOR(1.0f, 1.0f, 0.0f, 1.0f),
    D3DXCOLOR colorZ = D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)
    );
class CDebugDrawer : public btIDebugDraw
{
public:
    int m_debugMode;
    std::vector< VCol > m_vertices;
    CDebugDrawer();
    void DebugPresent ();
    virtual void drawLine (
        const btVector3& from,
        const btVector3& to,
        const btVector3& fromColor,
        const btVector3& toColor
        );
    virtual void drawLine (
        const btVector3& from,
        const btVector3& to,
        const btVector3& color
        );
    virtual void drawSphere (
        const btVector3& p,
        btScalar         radius,
        const btVector3& color
        );
    virtual void drawBox (
        const btVector3& boxMin,
        const btVector3& boxMax,
        const btVector3& color,
        btScalar         alpha
        );
    virtual void drawTriangle (
        const btVector3& a,
        const btVector3& b,
        const btVector3& c,
        const btVector3& color,
        btScalar         alpha
        );
    virtual void drawContactPoint (
        const btVector3& PointOnB,
        const btVector3& normalOnB,
        btScalar         distance,
        int              lifeTime,
        const btVector3& color
        );
    virtual void reportErrorWarning (const char* warningString);
    virtual void draw3dText (
        const btVector3& location,
        const char*      textString
        );
    virtual void setDebugMode (int debugMode);
    virtual int getDebugMode () const
    {
        return m_debugMode;
    }
};

//-----------------------------------------------------------------------------
// File: CDebugDrawer.cpp
//
// Purpose: A debug drawer used by the physics library.
//
// Copyright (c) 2007-2011 Steve Segreto. All rights reserved.
//-----------------------------------------------------------------------------
#include "Global.h"
#include "CRenderable.h"
#include "CVertexManager.h"
#include "CDebugDrawer.h"
extern CPhysicsEngine* g_pPhysics;
void VisualizeFrustum (
    D3DXVECTOR3* corners,
    D3DXCOLOR    color
    )
{
    VisualizeLineSegment( corners[ 4 ], corners[ 5 ], color );
    VisualizeLineSegment( corners[ 7 ], corners[ 6 ], color );
    VisualizeLineSegment( corners[ 4 ], corners[ 7 ], color );
    VisualizeLineSegment( corners[ 5 ], corners[ 6 ], color );
    VisualizeLineSegment( corners[ 0 ], corners[ 1 ], color );
    VisualizeLineSegment( corners[ 3 ], corners[ 2 ], color );
    VisualizeLineSegment( corners[ 0 ], corners[ 3 ], color );
    VisualizeLineSegment( corners[ 1 ], corners[ 2 ], color );
    VisualizeLineSegment( corners[ 0 ], corners[ 4 ], color );
    VisualizeLineSegment( corners[ 1 ], corners[ 5 ], color );
    VisualizeLineSegment( corners[ 2 ], corners[ 6 ], color );
    VisualizeLineSegment( corners[ 3 ], corners[ 7 ], color );
}

void VisualizeRay (
    D3DXVECTOR3 rayStartW,
    D3DXVECTOR3 rayDirW,
    D3DXCOLOR   color
    )
{
    D3DXVECTOR3 rayToW = (rayDirW * 1000) + rayStartW;

    g_pPhysics->m_pDebugDrawer->m_vertices.clear();
    g_pPhysics->m_pDebugDrawer->drawLine( btVector3( rayStartW.x, rayStartW.y,
                                                     rayStartW.z ),
                                          btVector3( rayToW.x, rayToW.y,
                                                     rayToW.z ),
                                          btVector3( color.r, color.g, color.b ),
                                          btVector3( color.r, color.g, color.b ) );
    g_pPhysics->m_pDebugDrawer->DebugPresent();
}

void VisualizeBox (
    AABB*     box,
    D3DXCOLOR color
    )
{
    //
    // Draw a box using 4 quads
    //
    D3DXVECTOR3 c0 = D3DXVECTOR3( box->maxPt.x, box->maxPt.y, box->maxPt.z );
    D3DXVECTOR3 c1 = D3DXVECTOR3( box->maxPt.x, box->minPt.y, box->maxPt.z );
    D3DXVECTOR3 c2 = D3DXVECTOR3( box->maxPt.x, box->maxPt.y, box->minPt.z );
    D3DXVECTOR3 c3 = D3DXVECTOR3( box->minPt.x, box->maxPt.y, box->maxPt.z );
    D3DXVECTOR3 c4 = D3DXVECTOR3( box->maxPt.x, box->minPt.y, box->minPt.z );
    D3DXVECTOR3 c5 = D3DXVECTOR3( box->minPt.x, box->maxPt.y, box->minPt.z );
    D3DXVECTOR3 c6 = D3DXVECTOR3( box->minPt.x, box->minPt.y, box->maxPt.z );
    D3DXVECTOR3 c7 = D3DXVECTOR3( box->minPt.x, box->minPt.y, box->minPt.z );

    VisualizeLineSegment( c0, c3, color );
    VisualizeLineSegment( c0, c1, color );
    VisualizeLineSegment( c0, c2, color );
    VisualizeLineSegment( c3, c5, color );
    VisualizeLineSegment( c3, c6, color );
    VisualizeLineSegment( c1, c4, color );
    VisualizeLineSegment( c1, c6, color );
    VisualizeLineSegment( c2, c5, color );
    VisualizeLineSegment( c2, c4, color );
    VisualizeLineSegment( c4, c7, color );
    VisualizeLineSegment( c5, c7, color );
    VisualizeLineSegment( c6, c7, color );
}

void VisualizeBox (
    OBB*      box,
    D3DXCOLOR color
    )
{
    //
    // Draw a box using 4 quads
    //
    D3DXVECTOR3 c0 = box->m_objectBounds[ 7 ];
    D3DXVECTOR3 c1 = box->m_objectBounds[ 5 ];
    D3DXVECTOR3 c2 = box->m_objectBounds[ 3 ];
    D3DXVECTOR3 c3 = box->m_objectBounds[ 6 ];
    D3DXVECTOR3 c4 = box->m_objectBounds[ 1 ];
    D3DXVECTOR3 c5 = box->m_objectBounds[ 2 ];
    D3DXVECTOR3 c6 = box->m_objectBounds[ 4 ];
    D3DXVECTOR3 c7 = box->m_objectBounds[ 0 ];

    VisualizeLineSegment( c0, c3, color );
    VisualizeLineSegment( c0, c1, color );
    VisualizeLineSegment( c0, c2, color );
    VisualizeLineSegment( c3, c5, color );
    VisualizeLineSegment( c3, c6, color );
    VisualizeLineSegment( c1, c4, color );
    VisualizeLineSegment( c1, c6, color );
    VisualizeLineSegment( c2, c5, color );
    VisualizeLineSegment( c2, c4, color );
    VisualizeLineSegment( c4, c7, color );
    VisualizeLineSegment( c5, c7, color );
    VisualizeLineSegment( c6, c7, color );
}

void VisualizeQuad (
    D3DXVECTOR3 topLeft,
    D3DXVECTOR3 bottomRight,
    D3DXCOLOR   color
    )
{
    //
    // Draw a quad between topLeft and bottomRight.
    //
    VisualizeLineSegment( topLeft,
                          D3DXVECTOR3( topLeft.x,
                                       bottomRight.y,
                                       topLeft.z ), color );
    VisualizeLineSegment( D3DXVECTOR3( topLeft.x,
                                       bottomRight.y,
                                       topLeft.z ), bottomRight, color );
    VisualizeLineSegment( bottomRight,
                          D3DXVECTOR3( bottomRight.x,
                                       topLeft.y,
                                       bottomRight.z ), color );
    VisualizeLineSegment( D3DXVECTOR3( bottomRight.x,
                                       topLeft.y,
                                       bottomRight.z ), topLeft, color );
}

void VisualizeLineSegment (
    D3DXVECTOR3 startW,
    D3DXVECTOR3 endW,
    D3DXCOLOR   color
    )
{
    g_pPhysics->m_pDebugDrawer->m_vertices.clear();
    g_pPhysics->m_pDebugDrawer->drawLine( btVector3( startW.x, startW.y,
                                                     startW.z ),
                                          btVector3( endW.x, endW.y, endW.z ),
                                          btVector3( color.r, color.g, color.b ),
                                          btVector3( color.r, color.g, color.b ) );
    g_pPhysics->m_pDebugDrawer->DebugPresent();
}

void VisualizeRotation (
    D3DXVECTOR3    posW,
    D3DXQUATERNION rot,
    D3DXCOLOR      colorX,
    D3DXCOLOR      colorY,
    D3DXCOLOR      colorZ
    )
{
    D3DXMATRIX m;

    D3DXMatrixRotationQuaternion( &m, &rot );
    VisualizeRotation( posW, m, colorX, colorY, colorZ );
}

void VisualizeRotation (
    D3DXVECTOR3 posW,
    D3DXMATRIX  m,
    D3DXCOLOR   colorX,
    D3DXCOLOR   colorY,
    D3DXCOLOR   colorZ
    )
{
    D3DXVECTOR3 xAxis = (D3DXVECTOR3( m._11, m._12, m._13 ) * 1) + posW;
    D3DXVECTOR3 yAxis = (D3DXVECTOR3( m._21, m._22, m._23 ) * 1) + posW;
    D3DXVECTOR3 zAxis = (D3DXVECTOR3( m._31, m._32, m._33 ) * 1) + posW;

    g_pPhysics->m_pDebugDrawer->m_vertices.clear();
    g_pPhysics->m_pDebugDrawer->drawLine( btVector3( posW.x, posW.y, posW.z ),
                                          btVector3( xAxis.x, xAxis.y, xAxis.z ),
                                          btVector3( colorX.r, colorX.g,
                                                     colorX.b ),
                                          btVector3( colorX.r, colorX.g,
                                                     colorX.b ) );
    g_pPhysics->m_pDebugDrawer->drawLine( btVector3( posW.x, posW.y, posW.z ),
                                          btVector3( yAxis.x, yAxis.y, yAxis.z ),
                                          btVector3( colorY.r, colorY.g,
                                                     colorY.b ),
                                          btVector3( colorY.r, colorY.g,
                                                     colorY.b ) );
    g_pPhysics->m_pDebugDrawer->drawLine( btVector3( posW.x, posW.y, posW.z ),
                                          btVector3( zAxis.x, zAxis.y, zAxis.z ),
                                          btVector3( colorZ.r, colorZ.g,
                                                     colorZ.b ),
                                          btVector3( colorZ.r, colorZ.g,
                                                     colorZ.b ) );
    g_pPhysics->m_pDebugDrawer->DebugPresent();
}

CDebugDrawer::CDebugDrawer() : m_debugMode(0)
{
}

void CDebugDrawer::DebugPresent ()
{
    if ( !m_vertices.size() )
    {
        return;
    }

    D3DXMATRIX world;
    D3DXMatrixIdentity( &world );
    g_d3dDevice->SetTransform(D3DTS_WORLD, &world);
    HR( g_pRenderStateMgr->SetVertexShader( NULL ) );
    HR( g_pRenderStateMgr->SetPixelShader( NULL ) );
    DWORD m_renderStates[ 256 ];
    g_pRenderStateMgr->SetToDefaults( m_renderStates );
    g_pRenderStateMgr->PostStates( m_renderStates );
    g_pRenderStateMgr->SetRenderState( D3DRS_LIGHTING, FALSE );
    HR( g_pRenderStateMgr->SetVertexDeclaration( VertexCol::Decl ) );
    DWORD vertsToDraw = (DWORD)m_vertices.size();
    DWORD vertOffset = 0;
    DWORD vertChunk;
    while (vertsToDraw)
    {
        vertChunk = min( 16, vertsToDraw );
        g_d3dDevice->DrawPrimitiveUP( D3DPT_LINELIST, (UINT)vertChunk / 2,
                                      &m_vertices[vertOffset],
                                      sizeof(VCol) );
        vertsToDraw -= vertChunk;
        vertOffset += vertChunk;
    }

    m_vertices.clear();
}

void CDebugDrawer::drawLine (
    const btVector3& from,
    const btVector3& to,
    const btVector3& fromColor,
    const btVector3& toColor
    )
{
    D3DXVECTOR3 vFrom, vTo, vCFrom, vCTo;

    memcpy( &vFrom,  &from,      sizeof( D3DXVECTOR3 ) );
    memcpy( &vTo,    &to,        sizeof( D3DXVECTOR3 ) );
    memcpy( &vCFrom, &fromColor, sizeof( D3DXVECTOR3 ) );
    memcpy( &vCTo,   &toColor,   sizeof( D3DXVECTOR3 ) );
    D3DCOLOR cFrom, cTo;
    cFrom =
        D3DCOLOR_ARGB( 0xFF, (DWORD)(vCFrom.x * 255), (DWORD)(vCFrom.y * 255),
                       (DWORD)(vCFrom.z * 255) );
    cTo =
        D3DCOLOR_ARGB( 0xFF, (DWORD)(vCTo.x * 255), (DWORD)(vCTo.y * 255),
                       (DWORD)(vCTo.z * 255) );
    VCol vert[] = {VCol(vFrom, cFrom), VCol(vTo, cTo)};
    m_vertices.push_back( vert[0] );
    m_vertices.push_back( vert[1] );
}

void CDebugDrawer::drawLine (
    const btVector3& from,
    const btVector3& to,
    const btVector3& color
    )
{
    drawLine(from, to, color, color);
}

void CDebugDrawer::drawSphere (
    const btVector3& p,
    btScalar         radius,
    const btVector3& color
    )
{
#if 0
    glColor4f ( color.getX(), color.getY(), color.getZ(), btScalar(1.0f) );
    glPushMatrix ();
    glTranslatef ( p.getX(), p.getY(), p.getZ() );
    int lats = 5;
    int longs = 5;
    int i, j;
    for(i = 0; i <= lats; i++)
    {
        btScalar lat0 = SIMD_PI * (-btScalar(0.5) + (btScalar) (i - 1) / lats);
        btScalar z0 = radius * sin(lat0);
        btScalar zr0 = radius * cos(lat0);
        btScalar lat1 = SIMD_PI * (-btScalar(0.5) + (btScalar) i / lats);
        btScalar z1 = radius * sin(lat1);
        btScalar zr1 = radius * cos(lat1);
        glBegin(GL_QUAD_STRIP);
        for(j = 0; j <= longs; j++)
        {
            btScalar lng = 2 * SIMD_PI * (btScalar) (j - 1) / longs;
            btScalar x = cos(lng);
            btScalar y = sin(lng);
            glNormal3f(x * zr0, y * zr0, z0);
            glVertex3f(x * zr0, y * zr0, z0);
            glNormal3f(x * zr1, y * zr1, z1);
            glVertex3f(x * zr1, y * zr1, z1);
        }

        glEnd();
    }

    glPopMatrix();
#endif
}

void CDebugDrawer::drawBox (
    const btVector3& boxMin,
    const btVector3& boxMax,
    const btVector3& color,
    btScalar         alpha
    )
{
#if 0
    btVector3 halfExtent = (boxMax - boxMin) * btScalar(0.5f);
    btVector3 center = (boxMax + boxMin) * btScalar(0.5f);
    glColor4f (color.getX(), color.getY(), color.getZ(), alpha);
    glPushMatrix ();
    glTranslatef ( center.getX(), center.getY(), center.getZ() );
    glScaled(2 * halfExtent[0], 2 * halfExtent[1], 2 * halfExtent[2]);
    glPopMatrix ();
#endif
}

void CDebugDrawer::drawTriangle (
    const btVector3& a,
    const btVector3& b,
    const btVector3& c,
    const btVector3& color,
    btScalar         alpha
    )
{
#if 0
    const btVector3 n = btCross(b - a,c - a).normalized();
    glBegin(GL_TRIANGLES);
    glColor4f(color.getX(), color.getY(), color.getZ(),alpha);
    glNormal3d( n.getX(),n.getY(),n.getZ() );
    glVertex3d( a.getX(),a.getY(),a.getZ() );
    glVertex3d( b.getX(),b.getY(),b.getZ() );
    glVertex3d( c.getX(),c.getY(),c.getZ() );
    glEnd();
#endif
}

void CDebugDrawer::setDebugMode (int debugMode)
{
    m_debugMode = debugMode;
}

void CDebugDrawer::draw3dText (
    const btVector3& location,
    const char*      textString
    )
{
#if 0
    glRasterPos3f( location.x(),  location.y(),  location.z() );
#endif
}

void CDebugDrawer::reportErrorWarning (const char* warningString)
{
    OutputDebugStringA( warningString );
    OutputDebugStringA( "\n" );
}

void CDebugDrawer::drawContactPoint (
    const btVector3& pointOnB,
    const btVector3& normalOnB,
    btScalar         distance,
    int              lifeTime,
    const btVector3& color
    )
{
#if 0
    btVector3 to = pointOnB + normalOnB * distance;
    const btVector3&from = pointOnB;
    glColor4f(color.getX(), color.getY(), color.getZ(),1.f);
    glBegin(GL_LINES);
    glVertex3d( from.getX(), from.getY(), from.getZ() );
    glVertex3d( to.getX(), to.getY(), to.getZ() );
    glEnd();
    glRasterPos3f( from.x(),  from.y(),  from.z() );
    char buf[12];
    sprintf(buf," %d",lifeTime);
#endif
}

You can create collision objects from your own model data in many ways. One way to do it is to treat your models as indexed triangle lists and use the example shown below. Be aware that your indices must match the size given below (i.e. either 16 or 32-bit indices - the example below uses 16-bit).


pMesh->m_pTriMesh = new btTriangleIndexVertexArray();
btIndexedMesh iMesh;
iMesh.m_numTriangles = pMesh->m_numFaces;
iMesh.m_triangleIndexBase = (const unsigned char *)pMesh->m_pIndices;
iMesh.m_triangleIndexStride = 3 * sizeof(IndexFormat);
iMesh.m_numVertices = pMesh->m_numVertices;
iMesh.m_vertexBase = (const unsigned char *)pMesh->m_pVertices;
iMesh.m_vertexStride = sizeof(D3DXVECTOR3);
pMesh->m_pTriMesh->addIndexedMesh( iMesh, PHY_SHORT );
pMesh->m_pTriShape = new btBvhTriangleMeshShape( pMesh->m_pTriMesh, false, true );

The basic process is to create a CollisionShape and then insert that as a rigid body as mentioned above. Other possible collision shapes are:

btHeightfieldTerrainShape,

btScaledBvhTriangleMeshShape

and of course the primitive shapes, btSphereShape, btCylinderShape, btBoxShape, etc.

As a side note, I strongly suggest to make D3D9 right-handed rather than converting everything to D3D9 "suggested" coordinate system.

Previously "Krohm"

I have integrated Bullet Physics into a D3D9 class engine and it is not that difficult. Let me share an overview of Bullet, I may be glossing over many details, please refer to the Wiki page and other web resources as well.

You start by creating an object that derives from btCollisionWorld, like btDiscreteDynamicsWorld. You can tick this object using the stepSimulation member, which will basically identify all contacts between "collision" objects and update their positions based on physical properties like gravity, mass, etc.

Collision objects fall into two classes (well three if you consider the character controller), rigid bodies, soft bodies and kinematic objects. You can add immovable (static) collision objects by setting the mass to a special constant (0.0f). You add rigid bodies using the addRigidBody member of your collision world object. You can do ray testing against the objects in your world using the rayTest() member of the collision world object.

When first creating your collision world, you need to select and specify a collision dispatcher, a broadphase object, a constraint solver and some config data. Your program needs to allocate and de-allocate all objects and memory passed to Bullet, the library does not own any pointers provided to it.

The choice of broadphase object can determine how well the collision world responds to very dynamic rigid bodies changing position every frame. You can overload both broadphase and nearphase collision responses and filters (so you can make a player rigid body collide with nothing but the ground, but make every other rigid body bounce off the player, for instance).

You can also declare a debug drawer and provide a D3D9 implementation to help you visualize the collision world and the collision objects as you place them in the world.

Here's the debug drawer I use, maybe it would help you?


//-----------------------------------------------------------------------------
// File: CDebugDrawer.h
//
// Purpose: A debug drawer used by the physics library.
//
// Copyright (c) 2007-2011 Steve Segreto. All rights reserved.
//-----------------------------------------------------------------------------
#pragma once
#include "LinearMath/btIDebugDraw.h"
#include <vector>
struct VCol
{
    VCol(
        const D3DXVECTOR3& v,
        D3DCOLOR           c
        ) : pos(v),col(c)
    {
    }
    D3DXVECTOR3 pos;
    D3DCOLOR col;
};
void VisualizeRay (
    D3DXVECTOR3 rayStartW,
    D3DXVECTOR3 rayDirW,
    D3DXCOLOR   color
    );
void VisualizeLineSegment (
    D3DXVECTOR3 startW,
    D3DXVECTOR3 endW,
    D3DXCOLOR   color
    );
void VisualizeBox (
    struct AABB* box,
    D3DXCOLOR color = D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f )
    );
void VisualizeBox (
    struct OBB* box,
    D3DXCOLOR color = D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f )
    );
void VisualizeQuad (
    D3DXVECTOR3 topLeft,
    D3DXVECTOR3 bottomRight,
    D3DXCOLOR color = D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f )
    );
void VisualizeFrustum (
    D3DXVECTOR3* corners,
    D3DXCOLOR    color
    );
void VisualizeRotation (
    D3DXVECTOR3 posW,
    D3DXQUATERNION rot,
    D3DXCOLOR colorX = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f),
    D3DXCOLOR colorY = D3DXCOLOR(1.0f, 1.0f, 0.0f, 1.0f),
    D3DXCOLOR colorZ = D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)
    );
void VisualizeRotation (
    D3DXVECTOR3 posW,
    D3DXMATRIX rot,
    D3DXCOLOR colorX = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f),
    D3DXCOLOR colorY = D3DXCOLOR(1.0f, 1.0f, 0.0f, 1.0f),
    D3DXCOLOR colorZ = D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)
    );
class CDebugDrawer : public btIDebugDraw
{
public:
    int m_debugMode;
    std::vector< VCol > m_vertices;
    CDebugDrawer();
    void DebugPresent ();
    virtual void drawLine (
        const btVector3& from,
        const btVector3& to,
        const btVector3& fromColor,
        const btVector3& toColor
        );
    virtual void drawLine (
        const btVector3& from,
        const btVector3& to,
        const btVector3& color
        );
    virtual void drawSphere (
        const btVector3& p,
        btScalar         radius,
        const btVector3& color
        );
    virtual void drawBox (
        const btVector3& boxMin,
        const btVector3& boxMax,
        const btVector3& color,
        btScalar         alpha
        );
    virtual void drawTriangle (
        const btVector3& a,
        const btVector3& b,
        const btVector3& c,
        const btVector3& color,
        btScalar         alpha
        );
    virtual void drawContactPoint (
        const btVector3& PointOnB,
        const btVector3& normalOnB,
        btScalar         distance,
        int              lifeTime,
        const btVector3& color
        );
    virtual void reportErrorWarning (const char* warningString);
    virtual void draw3dText (
        const btVector3& location,
        const char*      textString
        );
    virtual void setDebugMode (int debugMode);
    virtual int getDebugMode () const
    {
        return m_debugMode;
    }
};

//-----------------------------------------------------------------------------
// File: CDebugDrawer.cpp
//
// Purpose: A debug drawer used by the physics library.
//
// Copyright (c) 2007-2011 Steve Segreto. All rights reserved.
//-----------------------------------------------------------------------------
#include "Global.h"
#include "CRenderable.h"
#include "CVertexManager.h"
#include "CDebugDrawer.h"
extern CPhysicsEngine* g_pPhysics;
void VisualizeFrustum (
    D3DXVECTOR3* corners,
    D3DXCOLOR    color
    )
{
    VisualizeLineSegment( corners[ 4 ], corners[ 5 ], color );
    VisualizeLineSegment( corners[ 7 ], corners[ 6 ], color );
    VisualizeLineSegment( corners[ 4 ], corners[ 7 ], color );
    VisualizeLineSegment( corners[ 5 ], corners[ 6 ], color );
    VisualizeLineSegment( corners[ 0 ], corners[ 1 ], color );
    VisualizeLineSegment( corners[ 3 ], corners[ 2 ], color );
    VisualizeLineSegment( corners[ 0 ], corners[ 3 ], color );
    VisualizeLineSegment( corners[ 1 ], corners[ 2 ], color );
    VisualizeLineSegment( corners[ 0 ], corners[ 4 ], color );
    VisualizeLineSegment( corners[ 1 ], corners[ 5 ], color );
    VisualizeLineSegment( corners[ 2 ], corners[ 6 ], color );
    VisualizeLineSegment( corners[ 3 ], corners[ 7 ], color );
}

void VisualizeRay (
    D3DXVECTOR3 rayStartW,
    D3DXVECTOR3 rayDirW,
    D3DXCOLOR   color
    )
{
    D3DXVECTOR3 rayToW = (rayDirW * 1000) + rayStartW;

    g_pPhysics->m_pDebugDrawer->m_vertices.clear();
    g_pPhysics->m_pDebugDrawer->drawLine( btVector3( rayStartW.x, rayStartW.y,
                                                     rayStartW.z ),
                                          btVector3( rayToW.x, rayToW.y,
                                                     rayToW.z ),
                                          btVector3( color.r, color.g, color.b ),
                                          btVector3( color.r, color.g, color.b ) );
    g_pPhysics->m_pDebugDrawer->DebugPresent();
}

void VisualizeBox (
    AABB*     box,
    D3DXCOLOR color
    )
{
    //
    // Draw a box using 4 quads
    //
    D3DXVECTOR3 c0 = D3DXVECTOR3( box->maxPt.x, box->maxPt.y, box->maxPt.z );
    D3DXVECTOR3 c1 = D3DXVECTOR3( box->maxPt.x, box->minPt.y, box->maxPt.z );
    D3DXVECTOR3 c2 = D3DXVECTOR3( box->maxPt.x, box->maxPt.y, box->minPt.z );
    D3DXVECTOR3 c3 = D3DXVECTOR3( box->minPt.x, box->maxPt.y, box->maxPt.z );
    D3DXVECTOR3 c4 = D3DXVECTOR3( box->maxPt.x, box->minPt.y, box->minPt.z );
    D3DXVECTOR3 c5 = D3DXVECTOR3( box->minPt.x, box->maxPt.y, box->minPt.z );
    D3DXVECTOR3 c6 = D3DXVECTOR3( box->minPt.x, box->minPt.y, box->maxPt.z );
    D3DXVECTOR3 c7 = D3DXVECTOR3( box->minPt.x, box->minPt.y, box->minPt.z );

    VisualizeLineSegment( c0, c3, color );
    VisualizeLineSegment( c0, c1, color );
    VisualizeLineSegment( c0, c2, color );
    VisualizeLineSegment( c3, c5, color );
    VisualizeLineSegment( c3, c6, color );
    VisualizeLineSegment( c1, c4, color );
    VisualizeLineSegment( c1, c6, color );
    VisualizeLineSegment( c2, c5, color );
    VisualizeLineSegment( c2, c4, color );
    VisualizeLineSegment( c4, c7, color );
    VisualizeLineSegment( c5, c7, color );
    VisualizeLineSegment( c6, c7, color );
}

void VisualizeBox (
    OBB*      box,
    D3DXCOLOR color
    )
{
    //
    // Draw a box using 4 quads
    //
    D3DXVECTOR3 c0 = box->m_objectBounds[ 7 ];
    D3DXVECTOR3 c1 = box->m_objectBounds[ 5 ];
    D3DXVECTOR3 c2 = box->m_objectBounds[ 3 ];
    D3DXVECTOR3 c3 = box->m_objectBounds[ 6 ];
    D3DXVECTOR3 c4 = box->m_objectBounds[ 1 ];
    D3DXVECTOR3 c5 = box->m_objectBounds[ 2 ];
    D3DXVECTOR3 c6 = box->m_objectBounds[ 4 ];
    D3DXVECTOR3 c7 = box->m_objectBounds[ 0 ];

    VisualizeLineSegment( c0, c3, color );
    VisualizeLineSegment( c0, c1, color );
    VisualizeLineSegment( c0, c2, color );
    VisualizeLineSegment( c3, c5, color );
    VisualizeLineSegment( c3, c6, color );
    VisualizeLineSegment( c1, c4, color );
    VisualizeLineSegment( c1, c6, color );
    VisualizeLineSegment( c2, c5, color );
    VisualizeLineSegment( c2, c4, color );
    VisualizeLineSegment( c4, c7, color );
    VisualizeLineSegment( c5, c7, color );
    VisualizeLineSegment( c6, c7, color );
}

void VisualizeQuad (
    D3DXVECTOR3 topLeft,
    D3DXVECTOR3 bottomRight,
    D3DXCOLOR   color
    )
{
    //
    // Draw a quad between topLeft and bottomRight.
    //
    VisualizeLineSegment( topLeft,
                          D3DXVECTOR3( topLeft.x,
                                       bottomRight.y,
                                       topLeft.z ), color );
    VisualizeLineSegment( D3DXVECTOR3( topLeft.x,
                                       bottomRight.y,
                                       topLeft.z ), bottomRight, color );
    VisualizeLineSegment( bottomRight,
                          D3DXVECTOR3( bottomRight.x,
                                       topLeft.y,
                                       bottomRight.z ), color );
    VisualizeLineSegment( D3DXVECTOR3( bottomRight.x,
                                       topLeft.y,
                                       bottomRight.z ), topLeft, color );
}

void VisualizeLineSegment (
    D3DXVECTOR3 startW,
    D3DXVECTOR3 endW,
    D3DXCOLOR   color
    )
{
    g_pPhysics->m_pDebugDrawer->m_vertices.clear();
    g_pPhysics->m_pDebugDrawer->drawLine( btVector3( startW.x, startW.y,
                                                     startW.z ),
                                          btVector3( endW.x, endW.y, endW.z ),
                                          btVector3( color.r, color.g, color.b ),
                                          btVector3( color.r, color.g, color.b ) );
    g_pPhysics->m_pDebugDrawer->DebugPresent();
}

void VisualizeRotation (
    D3DXVECTOR3    posW,
    D3DXQUATERNION rot,
    D3DXCOLOR      colorX,
    D3DXCOLOR      colorY,
    D3DXCOLOR      colorZ
    )
{
    D3DXMATRIX m;

    D3DXMatrixRotationQuaternion( &m, &rot );
    VisualizeRotation( posW, m, colorX, colorY, colorZ );
}

void VisualizeRotation (
    D3DXVECTOR3 posW,
    D3DXMATRIX  m,
    D3DXCOLOR   colorX,
    D3DXCOLOR   colorY,
    D3DXCOLOR   colorZ
    )
{
    D3DXVECTOR3 xAxis = (D3DXVECTOR3( m._11, m._12, m._13 ) * 1) + posW;
    D3DXVECTOR3 yAxis = (D3DXVECTOR3( m._21, m._22, m._23 ) * 1) + posW;
    D3DXVECTOR3 zAxis = (D3DXVECTOR3( m._31, m._32, m._33 ) * 1) + posW;

    g_pPhysics->m_pDebugDrawer->m_vertices.clear();
    g_pPhysics->m_pDebugDrawer->drawLine( btVector3( posW.x, posW.y, posW.z ),
                                          btVector3( xAxis.x, xAxis.y, xAxis.z ),
                                          btVector3( colorX.r, colorX.g,
                                                     colorX.b ),
                                          btVector3( colorX.r, colorX.g,
                                                     colorX.b ) );
    g_pPhysics->m_pDebugDrawer->drawLine( btVector3( posW.x, posW.y, posW.z ),
                                          btVector3( yAxis.x, yAxis.y, yAxis.z ),
                                          btVector3( colorY.r, colorY.g,
                                                     colorY.b ),
                                          btVector3( colorY.r, colorY.g,
                                                     colorY.b ) );
    g_pPhysics->m_pDebugDrawer->drawLine( btVector3( posW.x, posW.y, posW.z ),
                                          btVector3( zAxis.x, zAxis.y, zAxis.z ),
                                          btVector3( colorZ.r, colorZ.g,
                                                     colorZ.b ),
                                          btVector3( colorZ.r, colorZ.g,
                                                     colorZ.b ) );
    g_pPhysics->m_pDebugDrawer->DebugPresent();
}

CDebugDrawer::CDebugDrawer() : m_debugMode(0)
{
}

void CDebugDrawer::DebugPresent ()
{
    if ( !m_vertices.size() )
    {
        return;
    }

    D3DXMATRIX world;
    D3DXMatrixIdentity( &world );
    g_d3dDevice->SetTransform(D3DTS_WORLD, &world);
    HR( g_pRenderStateMgr->SetVertexShader( NULL ) );
    HR( g_pRenderStateMgr->SetPixelShader( NULL ) );
    DWORD m_renderStates[ 256 ];
    g_pRenderStateMgr->SetToDefaults( m_renderStates );
    g_pRenderStateMgr->PostStates( m_renderStates );
    g_pRenderStateMgr->SetRenderState( D3DRS_LIGHTING, FALSE );
    HR( g_pRenderStateMgr->SetVertexDeclaration( VertexCol::Decl ) );
    DWORD vertsToDraw = (DWORD)m_vertices.size();
    DWORD vertOffset = 0;
    DWORD vertChunk;
    while (vertsToDraw)
    {
        vertChunk = min( 16, vertsToDraw );
        g_d3dDevice->DrawPrimitiveUP( D3DPT_LINELIST, (UINT)vertChunk / 2,
                                      &m_vertices[vertOffset],
                                      sizeof(VCol) );
        vertsToDraw -= vertChunk;
        vertOffset += vertChunk;
    }

    m_vertices.clear();
}

void CDebugDrawer::drawLine (
    const btVector3& from,
    const btVector3& to,
    const btVector3& fromColor,
    const btVector3& toColor
    )
{
    D3DXVECTOR3 vFrom, vTo, vCFrom, vCTo;

    memcpy( &vFrom,  &from,      sizeof( D3DXVECTOR3 ) );
    memcpy( &vTo,    &to,        sizeof( D3DXVECTOR3 ) );
    memcpy( &vCFrom, &fromColor, sizeof( D3DXVECTOR3 ) );
    memcpy( &vCTo,   &toColor,   sizeof( D3DXVECTOR3 ) );
    D3DCOLOR cFrom, cTo;
    cFrom =
        D3DCOLOR_ARGB( 0xFF, (DWORD)(vCFrom.x * 255), (DWORD)(vCFrom.y * 255),
                       (DWORD)(vCFrom.z * 255) );
    cTo =
        D3DCOLOR_ARGB( 0xFF, (DWORD)(vCTo.x * 255), (DWORD)(vCTo.y * 255),
                       (DWORD)(vCTo.z * 255) );
    VCol vert[] = {VCol(vFrom, cFrom), VCol(vTo, cTo)};
    m_vertices.push_back( vert[0] );
    m_vertices.push_back( vert[1] );
}

void CDebugDrawer::drawLine (
    const btVector3& from,
    const btVector3& to,
    const btVector3& color
    )
{
    drawLine(from, to, color, color);
}

void CDebugDrawer::drawSphere (
    const btVector3& p,
    btScalar         radius,
    const btVector3& color
    )
{
#if 0
    glColor4f ( color.getX(), color.getY(), color.getZ(), btScalar(1.0f) );
    glPushMatrix ();
    glTranslatef ( p.getX(), p.getY(), p.getZ() );
    int lats = 5;
    int longs = 5;
    int i, j;
    for(i = 0; i <= lats; i++)
    {
        btScalar lat0 = SIMD_PI * (-btScalar(0.5) + (btScalar) (i - 1) / lats);
        btScalar z0 = radius * sin(lat0);
        btScalar zr0 = radius * cos(lat0);
        btScalar lat1 = SIMD_PI * (-btScalar(0.5) + (btScalar) i / lats);
        btScalar z1 = radius * sin(lat1);
        btScalar zr1 = radius * cos(lat1);
        glBegin(GL_QUAD_STRIP);
        for(j = 0; j <= longs; j++)
        {
            btScalar lng = 2 * SIMD_PI * (btScalar) (j - 1) / longs;
            btScalar x = cos(lng);
            btScalar y = sin(lng);
            glNormal3f(x * zr0, y * zr0, z0);
            glVertex3f(x * zr0, y * zr0, z0);
            glNormal3f(x * zr1, y * zr1, z1);
            glVertex3f(x * zr1, y * zr1, z1);
        }

        glEnd();
    }

    glPopMatrix();
#endif
}

void CDebugDrawer::drawBox (
    const btVector3& boxMin,
    const btVector3& boxMax,
    const btVector3& color,
    btScalar         alpha
    )
{
#if 0
    btVector3 halfExtent = (boxMax - boxMin) * btScalar(0.5f);
    btVector3 center = (boxMax + boxMin) * btScalar(0.5f);
    glColor4f (color.getX(), color.getY(), color.getZ(), alpha);
    glPushMatrix ();
    glTranslatef ( center.getX(), center.getY(), center.getZ() );
    glScaled(2 * halfExtent[0], 2 * halfExtent[1], 2 * halfExtent[2]);
    glPopMatrix ();
#endif
}

void CDebugDrawer::drawTriangle (
    const btVector3& a,
    const btVector3& b,
    const btVector3& c,
    const btVector3& color,
    btScalar         alpha
    )
{
#if 0
    const btVector3 n = btCross(b - a,c - a).normalized();
    glBegin(GL_TRIANGLES);
    glColor4f(color.getX(), color.getY(), color.getZ(),alpha);
    glNormal3d( n.getX(),n.getY(),n.getZ() );
    glVertex3d( a.getX(),a.getY(),a.getZ() );
    glVertex3d( b.getX(),b.getY(),b.getZ() );
    glVertex3d( c.getX(),c.getY(),c.getZ() );
    glEnd();
#endif
}

void CDebugDrawer::setDebugMode (int debugMode)
{
    m_debugMode = debugMode;
}

void CDebugDrawer::draw3dText (
    const btVector3& location,
    const char*      textString
    )
{
#if 0
    glRasterPos3f( location.x(),  location.y(),  location.z() );
#endif
}

void CDebugDrawer::reportErrorWarning (const char* warningString)
{
    OutputDebugStringA( warningString );
    OutputDebugStringA( "\n" );
}

void CDebugDrawer::drawContactPoint (
    const btVector3& pointOnB,
    const btVector3& normalOnB,
    btScalar         distance,
    int              lifeTime,
    const btVector3& color
    )
{
#if 0
    btVector3 to = pointOnB + normalOnB * distance;
    const btVector3&from = pointOnB;
    glColor4f(color.getX(), color.getY(), color.getZ(),1.f);
    glBegin(GL_LINES);
    glVertex3d( from.getX(), from.getY(), from.getZ() );
    glVertex3d( to.getX(), to.getY(), to.getZ() );
    glEnd();
    glRasterPos3f( from.x(),  from.y(),  from.z() );
    char buf[12];
    sprintf(buf," %d",lifeTime);
#endif
}

You can create collision objects from your own model data in many ways. One way to do it is to treat your models as indexed triangle lists and use the example shown below. Be aware that your indices must match the size given below (i.e. either 16 or 32-bit indices - the example below uses 16-bit).


pMesh->m_pTriMesh = new btTriangleIndexVertexArray();
btIndexedMesh iMesh;
iMesh.m_numTriangles = pMesh->m_numFaces;
iMesh.m_triangleIndexBase = (const unsigned char *)pMesh->m_pIndices;
iMesh.m_triangleIndexStride = 3 * sizeof(IndexFormat);
iMesh.m_numVertices = pMesh->m_numVertices;
iMesh.m_vertexBase = (const unsigned char *)pMesh->m_pVertices;
iMesh.m_vertexStride = sizeof(D3DXVECTOR3);
pMesh->m_pTriMesh->addIndexedMesh( iMesh, PHY_SHORT );
pMesh->m_pTriShape = new btBvhTriangleMeshShape( pMesh->m_pTriMesh, false, true );

The basic process is to create a CollisionShape and then insert that as a rigid body as mentioned above. Other possible collision shapes are:

btHeightfieldTerrainShape,

btScaledBvhTriangleMeshShape

and of course the primitive shapes, btSphereShape, btCylinderShape, btBoxShape, etc.

Wow! Thank you for the detailed response! This does help me quite a bit!

I develop to expand the universe. "Live long and code strong!" - Delta_Echo (dream.in.code)

This topic is closed to new replies.

Advertisement