• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Jesse Dager

[BULLET] Camera/object positions?

4 posts in this topic

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

0

Share this post


Link to post
Share on other sites

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

0

Share this post


Link to post
Share on other sites

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.

Edited by Steve_Segreto
2

Share this post


Link to post
Share on other sites

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

0

Share this post


Link to post
Share on other sites

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!  

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0