btIDebugDraw problems

Post Reply
Anthony
Posts: 13
Joined: Sat Feb 11, 2012 8:44 pm

btIDebugDraw problems

Post by Anthony »

I've been attempting to work with Cocos3D and Bullet Physics for the past week or so. Things are progressing (slowly but surely) but I am having problems using btIDebugDraw.

here is a snippet of the code for the btBoxShape that I would like to show as a wireframe for debug purposes. I have created a "top down" view that will be used to simulate a dice roll.

-(void) initializeWorld

Code: Select all

btCollisionShape *dieShape = new btBoxShape(btVector3(1.0, 1.0, 1.0));
btDefaultMotionState *fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, 0, 0)));
btScalar mass = 1;
btVector3 fallInertia(0, 0, 0);
dieShape->calculateLocalInertia(mass, fallInertia);
	
btRigidBody::btRigidBodyConstructionInfo dieRigidBodyCI(mass,fallMotionState,dieShape,fallInertia);
dieRigidBodyCI.m_restitution = 0.1;
dieRigidBody = new btRigidBody(dieRigidBodyCI);
dieRigidBody->setDamping(0.3, 0.8);
dynamicsWorld->addRigidBody(dieRigidBody);
[[CCScheduler sharedScheduler] scheduleSelector:@selector(updatePhysics:) forTarget:self interval:0 paused:NO];
	reset = NO;
	left = true;

btIDebugDraw* debugDrawer;
-(void) updatePhysics:(ccTime)dt

Code: Select all

dynamicsWorld->stepSimulation(1/60.f, 10);
dynamicsWorld->setDebugDrawer(debugDrawer);
dynamicsWorld->debugDrawWorld();

btTransform trans;
dieRigidBody->getMotionState()->getWorldTransform(trans);
btVector3 dieRBPos = trans.getOrigin();
float velX = dieRigidBody->getLinearVelocity().x();
float velY = dieRigidBody->getLinearVelocity().y();
float velL = dieRigidBody->getLinearVelocity().length();
    
if (dieRigidBody->getLinearVelocity().length() > -0.1 && dieRigidBody->getLinearVelocity().length() < 0.1 && !reset) {
        
        LogInfo(@"Linear X is %f, linear Y is %f, linear length is %f", velX, velY, velL);
        
		if(left) {
            dieRigidBody->applyImpulse(btVector3(-3,0,4), btVector3(dieRBPos.getX(), dieRBPos.getY(), dieRBPos.getZ()));
			left = false;
			reset = true;
		} else {
            dieRigidBody->applyImpulse(btVector3(3,0,4), btVector3(dieRBPos.getX(), dieRBPos.getY(), dieRBPos.getZ()));
			left = true;
			reset = true;
		}
		
		
	} 
}
I plan on loading a die cube from a POD file and "attaching" it to the dieRigidBody, but for now I would just like to visualize the dieRigidBody with a wireframe and I can't get one to appear. What am I doing wrong?
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm
Contact:

Re: btIDebugDraw problems

Post by dphil »

Do you actually have an debug drawer implementation? I see you are declaring the debugDrawer variable, but not assigning anything to it (maybe you simply left the assignment part out, but it might be helpful to see). Keep in mind that btIDebugDraw is really just an interface that you need to subclass and provide actual rendering calls for to whatever you use for rendering, though I believe there is an OpenGL-based debug drawer provided in the demo code somewhere.

Also, dynamicsWorld->setDebugDrawer should go in the initialiazation, not the simulation update code. You only need to set it once.
Anthony
Posts: 13
Joined: Sat Feb 11, 2012 8:44 pm

Re: btIDebugDraw problems

Post by Anthony »

Thanks for you help. I don't have a debug drawer implementation - that must be my problem. How would I do that? I can't find many examples online, and I checked the API reference on btIDebugDraw but am still a bit confused. Although maybe the OpenGL-based debug drawer is more of what I'm after. I'll look into that. And good to know about the ->setDebugDrawer.

Thanks again!
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm
Contact:

Re: btIDebugDraw problems

Post by dphil »

Anthony wrote:Thanks for you help. I don't have a debug drawer implementation - that must be my problem. How would I do that?
Well, once you set the debug drawer for the world, Bullet will make calls to the functions listed in the btIDebugDraw interface. You just need to implement those functions so they actually make rendering calls. For example, in the drawLine function you could do "glBegin(GL_LINES)...." or whatever.
If you look at the code for btIDebugDraw, you'll notice a lot of the other methods just end up making calls to drawLine, so you get a lot of basic functionality just by implementing drawLine. Then you can get fancier by overriding some of the functions to draw more than just lines.
Anthony
Posts: 13
Joined: Sat Feb 11, 2012 8:44 pm

Re: btIDebugDraw problems

Post by Anthony »

Great, I'll give it a try. I really appreciate your help.
Anthony
Posts: 13
Joined: Sat Feb 11, 2012 8:44 pm

Re: btIDebugDraw problems

Post by Anthony »

dphil:

I hate to say it but I still can't get the debugger to work. I'm new to C++ (but not a newcomer to programming) so I'm probably making a simple mistake somewhere. This is my btIDebugDraw implementation (I named it myDebug.h)

Code: Select all

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

using std::cout;
using std::endl;

class myDebug : public btIDebugDraw
{
    
  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	
myDebug::drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
{
    cout << "WORKS!!!" << endl;
    LogInfo(@"Works!!");

    //what do I even put here once I actually get the LogInfo to output to the console??
}

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

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

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

void
myDebug::setDebugMode(int debugMode)
{
    
}

int
myDebug::getDebugMode() const
{
    return 0;
}
I put LogInfo in the drawLine function just to make sure it's working, but nothing outputs to the console. And I know you said I could simply implement drawLine only, but if I don't implement these other pure abstract functions my program won't compile (gives me error "Allocating an object of abstract class type 'myDebug' when trying to create an instance of myDebug) - and I'm sure I implemented them incorrectly because I just left them empty, but I don't even know what to put in them.

In my world implementation file, I use this to create the debugger and assign it to the world:

-(void) initializeWorld

Code: Select all

myDebug *debug;
debug = new myDebug;
dynamicsWorld->setDebugDrawer(debug);
-(void) updatePhysics:(ccTime)dt

Code: Select all

dynamicsWorld->debugDrawWorld();
I've been banging my head on the keyboard trying to figure this out on my own, but I can't seem to. The reason I want to debug in the first place is because I've created a rigidBody and "attached" a die cube (a CC3MeshNode - I'm using cocos3d) loaded from a POD file to it. I'm able to successfully set the location of the die cube by using:

Code: Select all

btTransform trans;
dieRigidBody->getMotionState()->getWorldTransform(trans);
btVector3 dieRBPos = trans.getOrigin();
dieMesh.location = cc3v(trans.getOrigin().getX(), trans.getOrigin().getY(), trans.getOrigin().getZ());
but when I try to update the rotation of the die cube to match the rotation of the rigidBody by using this:

Code: Select all

dieMesh.quaternion = CC3Vector4Make(trans.getRotation().getX(), trans.getRotation().getY(), trans.getRotation().getZ(), trans.getRotation().getW());
it doesn't always work - i.e., the die cube will sometimes land and stabilize on one of its edges. So the rotation is getting out of sync somewhere and I'm trying to figure out where. I would really, really appreciate your input!!

edit:

This is actually the problem I sometimes have in regards to rotation:
http://www.cocos2d-iphone.org/forum/topic/19802

and this is a post I made on the cocos3d forums asking for help (but the forum isn't as active as I'd hoped):
http://www.cocos2d-iphone.org/forum/topic/29226
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm
Contact:

Re: btIDebugDraw problems

Post by dphil »

For the drawing functions, implementing a rendering call in drawLine is sufficient to get something going, but yes for the sake of completing the abstract superclass you need those other function definitions in there, even if they are blank.

Ok, looking at your code I see another little detail that needs mentioning (it's been a little while since I implemented my own debug drawer, so forgive me if I don't remember all the details). When Bullet tries to make the debug draw calls, it first checks the debug mode (via getDebugMode()). If you look at the btIDebugDraw header, there is an enum called DebugDrawModes. The value you return from getDebugMode() will be checked against this enum to decide what to draw. Note that the value of 0 (which you are returning) corresponds to DBG_NoDebug :) . Try returning DBG_DrawWireframe (value of 1) instead, or some bitwise OR combination of various other of the enum options to suit your needs.

Typically, if you want to be able to modify what is drawn at runtime, you would be setting (via setDebugMode()) and storing the draw mode yourself as a member variable, and returning that variable (rather than a hard-coded value) in getDebugMode(), like this:

Code: Select all

void myDebug::setDebugMode( int debugMode ) {  mDebugModes = (DebugDrawModes) debugMode; }

int myDebug::getDebugMode() const { return mDebugModes; }
If you get stuck at all wondering how everything is working, I highly recommend taking a look at how Bullet actually uses the debug drawer, by checking out btCollisionWorld::debugDrawWorld and btCollisionWorld::debugDrawObject. A couple of the btCollisionWorld subclasses add a little extra drawing as well (for things like constraints and soft bodies), in case you're interested.

Hope that helps.
Anthony
Posts: 13
Joined: Sat Feb 11, 2012 8:44 pm

Re: btIDebugDraw problems

Post by Anthony »

Thanks, that did it! I set it to 1 and now drawLine() gets called. Now I'm just trying to figure out how to actually draw the lines, haha. You said glBegin(GL_LINES); but that seems to be throwing an error ("Conflicting types for 'gluLookAt' and 'gluPerspective' ?). I'll do some research on that, but I am truly grateful for your help dphil :)

edit: looks like I need to set up the vertices to be drawn from/to. That would make sense :lol: . I'll see if I can figure the rest out by myself. Thanks again dphil.
Last edited by Anthony on Mon Feb 13, 2012 11:39 pm, edited 1 time in total.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA
Contact:

Re: btIDebugDraw problems

Post by Erwin Coumans »

You could try re-using the existing Demos\OpenGL\GLDebugDrawer.cpp, just check the demos how to use it.

Thanks,
Erwin
Anthony
Posts: 13
Joined: Sat Feb 11, 2012 8:44 pm

Re: btIDebugDraw problems

Post by Anthony »

Thanks very much Erwin for pointing me in that direction. I'll check it out!
Anthony
Posts: 13
Joined: Sat Feb 11, 2012 8:44 pm

Re: btIDebugDraw problems

Post by Anthony »

Well, I'm very close...

I've put this in myDebug.cpp:

Code: Select all

#include <iostream>
#include "myDebug.h"
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>

using std::cout;
using std::endl;

#include <stdio.h>
myDebug::myDebug()
{
    
}

void myDebug::drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
{
//    cout << "test test" << endl;
    
    glBegin(GL_LINES);
            glColor3f(color.getX(), color.getY(), color.getZ());
            glVertex3d(from.getX(), from.getY(), from.getZ());
            glColor3f(color.getX(), color.getY(), color.getZ());
            glVertex3d(to.getX(), to.getY(), to.getZ());
    glEnd();
}

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

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

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

void myDebug::setDebugMode(int debugMode)
{
    
}
but when I attempt to add the OpenGL.framework and GLUT.framework in Xcode, my program will compile but will not run (it gives me a "dyld: Symbol not found: ___CFObjCIsCollectable" error - which I've read is just console noise and not the real reason why my program is crashing). When I remove these frameworks (and comment out the code above), everything compiles and runs fine. I think I'm very close to getting the debugging working but I can't figure out why adding these frameworks would cause my program to crash - and Google is not much help. dphil and Erwin, would either of you know why this is happening? And once again, thanks for your continuous help.
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm
Contact:

Re: btIDebugDraw problems

Post by dphil »

I made a new test project (Cocoa Application), to which I added the Bullet frameworks, OpenGL.framework, and GLUT.framework. I copied your myDebug implementation above (and I made up an appropriate header for it) and it built and ran fine. So I'm not sure what the problem is...

You could try the same thing on your end. Create a new bare bones Xcode project and add your Bullet, OpenGL, and GLUT frameworks and your btIDebugDrawer subclass, and see if it runs fine.

On a side note, I didn't actually need to add GLUT.framework to my project. It just finds it automatically in /System/Library/Frameworks. OpenGL seems to be required though.
Anthony
Posts: 13
Joined: Sat Feb 11, 2012 8:44 pm

Re: btIDebugDraw problems

Post by Anthony »

Thanks very much dphil. It seems to be a problem with my project file (likely because I am using a wrapper to integrate Bullet into Cocos3d). I appreciate all your help.
Post Reply