Monday 9 July 2012

Bullet Physics, Cocos3d, Debug Drawer - setDebugDrawer

I have recently managed to get the Bullet Physics debug drawer working within cocos3d.

To implement this I have created a C++ class that has access to singleton class which in turn can draw on my 3d scene.

My class inherits btIDebugDraw

class debugDrawer : public btIDebugDraw

Within


debugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
{
  
   RuleSet *rule = [General SharedGeneral].RuleSet;
   [rule debugLine:from.x() y:from.y() z:from.z() :to.x() dy:to.y() dz:to.z()];

}

Within my shared class I have my line drawing code

-(void) debugLine :(float)x y:(float)y z:(float) z:(float)dx dy:(float)dy dz:(float) dz {
    
    float arr_location[] = {x,y,z, dx,dy, dz };
    CC3LineNode* lineNode = [CC3LineNode nodeWithName: @"Line test"];
    [lineNode populateAsLineStripWith: 2
                             vertices: arr_location
                            andRetain: YES];
    lineNode.color = ccGREEN;
    
    [_lines addObject:lineNode];
    [_activeWorld addChild:lineNode];   
  //Thanks Bill :-)  
}

I referenced my shared object which allows me to draw lines in my 3d world.

When I initialise my 3d world I attach my debugDrawer

 debugDrawer *debug;
 debug = new  debugDrawer;
 dynamicsWorld->setDebugDrawer(debug);

At the end of every synchronisation of my physics world I call my debugDrawer

 _discreteDynamicsWorld->debugDrawWorld();  // This is the internal name of the class

Before calling each synchronisation on my physics world I call a debugStart session,
this removes all my previous lines from the scene, if you want pretty patterns don't bother with the following :-)

[general.RuleSet debugStart];

Within my shared class I have

-(void) debugStart {
   
    for (CC3LineNode* lineNode in _lines) {
        [_activeWorld removeChild:lineNode];
    }
    
    [_lines removeAllObjects];
    
}


Now I can see if my physics objects are being rendered correctly.
This only implements line drawing there are other methods within btIDebugDraw 
that you could implement for further functionality.



All the best.

Duncan.

15 comments:

  1. Hi!
    Could you post your full code for the debugDrawer class?
    I'm getting lots of errors in NSObjCRuntime, because I cannot figure out how to include (and call methods of) objc classes within c++ code.
    Thanks in advance.

    ReplyDelete
  2. Thanks for sharing all these pieces about Cocos3d and Bullet, by the way.
    Couldn't find any information about btIDebugDraw and Cocos3d anywhere else.

    ReplyDelete
  3. Hi!
    I finally found a thread in the cocos3d forum about using box2d with cocos3d and realized that I had to write extern "C" {} around my cocos3d imports. After fixing that, everything worked fine.

    By the way:
    I managed to do without the singleton. I just had a pointer to the cocos3d scene in my debug drawer class which I directly used to draw. I just considered it handier to have to write only one class.

    Thanks again for your tutorial!

    ReplyDelete
  4. Sorry for not posting a reply I've only just noticed your messages.

    I'm glad it was of some help :-)

    ReplyDelete
  5. I couldn't understand what the ruleset actually mean. Please help..

    Thanks

    ReplyDelete
  6. Hi Raj,

    The rule set is my own internal class,
    I base every level of my games on a set of rules, so each level I derive from a RuleSet class.
    This class has a method that is can draw a line in my active cocos3d scene.

    I hope that helps

    Duncan.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Ok, I'll have a try implementing it, since i'm not familiar with bullet physics and still new to cocos2d/3d, I find it a bit difficult. It could be very helpful if we have a very simple sample code of cube whose debug draw is enabled. Please do post an example if you find time in your busy schedule.
    Anyway thanks for your quick reply. I would try implementing it on my own.

    ReplyDelete
  9. Another error I get is "allocating object of an abstract class type" for the code below
    debugDrawer *debug;
    debug = new debugDrawer; // I get error here
    dynamicsWorld->setDebugDrawer(debug);

    In stack overflow i found we can only have reference for abstract classes.
    This stops me from proceeding further. Please give your valid inputs on how it works for you

    ReplyDelete
    Replies
    1. Got solutions for above issue of abstract class using stackoverflow http://stackoverflow.com/questions/11929319/allocating-an-object-for-abstact-class-type-if-not-implemented-and-missing-vtabl
      Trying to implement now.

      Delete
  10. What is the error that you get?
    Have you changed the name of your file to have an extension of .mm?

    When you enable the debug drawer it does it for all objects all you have to do if you have written the debug drawer is

    myDebug *debug;
    debug = new myDebug;
    dynamicsWorld->setDebugDrawer(debug);

    after you have initialised your dynamics world.

    and a call to your debug instance to draw the world, I put this in my updateAfterTransform.

    It sounds like your having more of a problem with creating a class and initialising it.

    ReplyDelete
  11. I finally got the debug drawer working. Thanks for the excellant post.
    Actually the error I got was due to improper implementation of virtual function in the debug class I created. Finally it worked. Thanks again.

    ReplyDelete
  12. No problem,
    Out of curiosity what are you planning on using it for?

    ReplyDelete
  13. This comment has been removed by the author.

    ReplyDelete
  14. This comment has been removed by the author.

    ReplyDelete