4
\$\begingroup\$

Background

I am following on from this question, which isn't answered yet. Basically I have a cube and a UVSphere in my scene, with UVSphere on the top of the cube without touching the cube. Both exported from blender.

When I run the app The UVSphere does circle around the cube for 3 or 4 times and jump out of the scene. What I actually expect was the sphere to fall on top of the cube.

What this question about

From the comment to the linked question, I got to know about bullet debug drawing, which helps in debugging by drawing outline of physics bodies which are normally invisible. I did some research on that and came up with the code given below. From whatever I have read, below code should work, but it doesn't.

My Code

My bullet initialization code.

-(void) initializeScene {
    /*Setup physics world*/
    _physicsWorld = [[CC3PhysicsWorld alloc] init];
    [_physicsWorld setGravity:0 y:-9.8 z:0];

    /*Setting up debug draw*/
    MyDebugDraw *draw   =   new MyDebugDraw;
    draw->setDebugMode(draw->getDebugMode() 
                      | btIDebugDraw::DBG_DrawWireframe );
    _physicsWorld._discreteDynamicsWorld->setDebugDrawer(draw);

    /*Setup camera and lamb*/
    …………..

    //This simpleCube.pod contains the cube
    [self addContentFromPODFile: @"simpleCube.pod"];
    //This file contains sphere
    [self addContentFromPODFile: @"SimpleSphere.pod"];

    [self createGLBuffers];

    CC3MeshNode* cubeNode   = (CC3MeshNode*)[self getNodeNamed:@"Cube"];
    CC3MeshNode* sphereNode = (CC3MeshNode*)[self getNodeNamed:@"Sphere"]; 
    // both cubeNode and sphereNode are not nil from this point


    float *cVertexData  = (float*)((CC3VertexArrayMesh*)cubeNode.mesh)
                               .vertexLocations.vertices;
    int cVertexCount    = ((CC3VertexArrayMesh*)cubeNode.mesh)
                               .vertexLocations.vertexCount;

    btTriangleMesh* cTriangleMesh  = new btTriangleMesh();

    int offset = 0;
    for (int i = 0; i < (cVertexCount / 3); i++)
    {
        unsigned int index1 = offset;
        unsigned int index2 = offset+6;
        unsigned int index3 = offset+12;
        cTriangleMesh->addTriangle(
          btVector3(cVertexData[index1], cVertexData[index1+1], cVertexData[index1+2]),
          btVector3(cVertexData[index2], cVertexData[index2+1], cVertexData[index2+2]), 
          btVector3(cVertexData[index3], cVertexData[index3+1], cVertexData[index3+2]));
        offset += 18;
    }

    [self releaseRedundantData];

    /*Create a triangle mesh from the vertices*/
    btBvhTriangleMeshShape* cTriMeshShape 
                       = new btBvhTriangleMeshShape(cTriangleMesh,true);
    btCollisionShape *sphereShape = new btSphereShape(1);

    gTriMeshObject =   [_physicsWorld createPhysicsObjectTrimesh:cubeNode 
                            shape:cTriMeshShape 
                            mass:0 
                            restitution:1.0 
                            position:cubeNode.location];
    sphereObject   =   [_physicsWorld createPhysicsObject:sphereNode 
                            shape:sphereShape 
                            mass:1 
                            restitution:0.1 
                            position:sphereNode.location];
    sphereObject.rigidBody->setDamping(0.1,0.8);

    /*Enable debug drawing*/
    _physicsWorld._discreteDynamicsWorld->debugDrawWorld();
}

And My btIDebugDraw implementation (MyDebugDraw.h)

//MyDebugDraw.h
class MyDebugDraw: public btIDebugDraw{
    int m_debugMode;

public:

    virtual void drawLine(const btVector3& from,const btVector3& to
              ,const btVector3& color);

    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;
};

void MyDebugDraw::drawLine(const btVector3& from,const btVector3& to
                              ,const btVector3& color){
    LogInfo(@"Works!!");
    glPushMatrix();
    glColor4f(color.getX(), color.getY(), color.getZ(), 1.0);

    const GLfloat line[] = {
        from.getX()*1, from.getY()*1, from.getZ()*1, //point A
        to.getX()*1, to.getY()*1,to.getZ()*1 //point B
    };
    glVertexPointer( 3,
                    GL_FLOAT,
                    0,
                    &line );
    glPointSize( 5.0f );
    glDrawArrays( GL_POINTS, 0, 2 );
    glDrawArrays( GL_LINES, 0, 2 );
    glPopMatrix();
}

void MyDebugDraw::drawContactPoint(const btVector3 &PointOnB 
         ,const btVector3 &normalOnB, btScalar distance
         ,int lifeTime, const btVector3 &color){      
}

void MyDebugDraw::reportErrorWarning(const char *warningString){
}

void MyDebugDraw::draw3dText(const btVector3 &location
                                , const char *textString){
}

void MyDebugDraw::setDebugMode(int debugMode){
}

int MyDebugDraw::getDebugMode() const{
    return DBG_DrawWireframe;
}

My Problem

The drawLine method is getting called. I can see the cube and sphere in place. Sphere again does some circling around the cube before jumping off.

No debug lines are getting drawn.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Okay I got it working. For everyone who faces this in the future..

Note : I use Cocos3D (2D) functions to draw the line. So this is not a generic solution.

This is how I done it.

1) Create a RuleSet objective C class

RuleSet.h

#import "CC3Scene.h"

@interface RuleSet : NSObject{
}
@property(strong, nonatomic) CC3Scene *currentScene;
@property (strong, nonatomic) NSMutableArray *lines;
+(id)sharedRuleSet;
-(void) debugLineFromX:(float)fromX fromY:(float)fromY 
      fromZ:(float)fromZ toX:(float)toX toY:(float)toY toZ:(float)toZ;
@end

RuleSet.m

#import "RuleSet.h"
#import "CC3MeshNode.h"

@implementation RuleSet
+(id)sharedRuleSet{
    static RuleSet *sharedRuleSet = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedRuleSet = [[self alloc] init];
    });
    return sharedRuleSet;
}

-(void) debugLineFromX:(float)fromX fromY:(float)fromY fromZ:(float)fromZ 
           toX:(float)toX toY:(float)toY toZ:(float)toZ {
    if (!self.lines) {
        self.lines        =   [NSMutableArray array];
    }
    float arr_location[] = {fromX,fromY,fromZ, toX,toY, toZ };
    CC3LineNode* lineNode = [CC3LineNode nodeWithName: @"Line test"];
    [lineNode populateAsLineStripWith: 2
                             vertices: arr_location
                            andRetain: YES];
    lineNode.color = ccRED;

    [self.lines addObject:lineNode];
    [self.currentScene addChild:lineNode];
}
@end

2) Create a custom btDebugDraw implementation

MyDebugDraw.h

#include <iostream>
#include "btIDebugDraw.h"
#import "RuleSet.h"

class MyDebugDraw: public btIDebugDraw{
    int m_debugMode;

public:
    virtual void drawLine(const btVector3& from,const btVector3& to
                    ,const btVector3& color);
    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;
};

void MyDebugDraw::drawLine(const btVector3& from,const btVector3& to
                                ,const btVector3& color)
{
    RuleSet *rule = [RuleSet sharedToolSet];
    [rule debugLineFromX:from.x() fromY:from.y() fromZ:from.z() 
                    toX:to.x() toY:to.y() toZ:to.z()];
}

void MyDebugDraw::drawContactPoint(const btVector3 &PointOnB
            , const btVector3 &normalOnB, btScalar distance
            , int lifeTime, const btVector3 &color){}

void MyDebugDraw::reportErrorWarning(const char *warningString){}

void MyDebugDraw::draw3dText(const btVector3 &location
                , const char *textString){}

void MyDebugDraw::setDebugMode(int debugMode){}

int MyDebugDraw::getDebugMode() const{
    return DBG_DrawWireframe;
}

3) During physics world initialization

YourScene.m

......
#import "RuleSet.h"
#import "MyDebugDraw.h"
.......

-(void) initializeScene {
    RuleSet *rule       =   [RuleSet sharedToolSet];
    rule.currentScene   =   self;

    //Create physics world
    btBroadphaseInterface* broadphase = new btDbvtBroadphase();
    btDefaultCollisionConfiguration* collisionConfiguration 
                  = new btDefaultCollisionConfiguration();
    btCollisionDispatcher* dispatcher 
           = new btCollisionDispatcher(collisionConfiguration);
    btSequentialImpulseConstraintSolver* solver 
           = new btSequentialImpulseConstraintSolver();
    dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher
              ,broadphase,solver,collisionConfiguration);
    dynamicsWorld->setGravity(btVector3(0,-10.0,0));

    /*Create custom debug drawer*/
    MyDebugDraw *draw   =   new MyDebugDraw;
    draw->setDebugMode( draw->getDebugMode()
          | btIDebugDraw::DBG_DrawWireframe );
    dynamicsWorld->setDebugDrawer(draw);

    /*Add rigid bodies and collision objects to physics world*/    
    .....
    .....

    /*At the end of initializeScene function
        , after adding physics bodies*/    
    dynamicsWorld->debugDrawWorld();
}

And credit goes here. This is not my code.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .