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.
Answer
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
#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.
No comments:
Post a Comment