View previous topic :: View next topic |
Author |
Message |
Pishtaco
Joined: 21 Aug 2009 Posts: 3
|
Posted: Fri Aug 21, 2009 12:10 pm Post subject: DerelictODE - collision issue |
|
|
Hello,
First of all, thanks very much for Derelict.
I'm trying to get an ODE tutorial about blocks falling on a plane (here) working with D. I'm afraid I'm proceeding mostly by trial and error, since I have just started with D and know very little C++. My main experience is with Python, and in fact my goal is to port a game I'm working on from Python to D.
I'm having a problem with the dCollide function. The ODE documentation lists it like this:
Code: | int dCollide (dGeomID o1, dGeomID o2, int flags, dContactGeom *contact, int skip); |
where the fourth argument is more or less a pointer to an array of contactgeoms, and the fifth one is the space between adjacent contactgeoms in the array (sorry if I'm using the terminology wrong here).
But with derelict the compiler wants only four arguments, and looking in odefuncs.d I found this:
Code: | int function(dGeomID, dGeomID, int, dContactGeom*) dCollide; |
Here's my code:
Code: | void handle_collision_between(dGeomID obj_0, dGeomID obj_1)
{
const int MAX_CONTACTS = 10;
dContactGeom[MAX_CONTACTS] contact_geoms;
dContact[MAX_CONTACTS] contacts;
int numc = dCollide(obj_0, obj_1, MAX_CONTACTS, contact_geoms.ptr);
if (numc>0)
{
dBodyID body_1 = dGeomGetBody(obj_0);
dBodyID body_2 = dGeomGetBody(obj_1);
for (int i = 0; i < numc; i++)
{
contacts[i].geom = contact_geoms[i];
contacts[i].surface.mode = dContactBounce | dContactSoftCFM;
contacts[i].surface.mu = 5; //dInfinity;
contacts[i].surface.mu2 = 0;
contacts[i].surface.bounce = 0.5;
contacts[i].surface.bounce_vel = 0.1;
contacts[i].surface.soft_cfm = 0.01;
dJointID c = dJointCreateContact(world, contact_group, contacts.ptr+i);
dJointAttach(c, body_1, body_2);
}
}
}
} |
It compiles fine, but crashes at the first collision with "object.Exception: Access Violation - Write at address 0x24f998". If I change MAX_CONTACTS to 1, and so only use the first entry in the array, then it actually runs fine and the simulation looks reasonable; but I think that limiting contacts between geoms to one contact must be bad for the stability.
There's also one other thing I noticed, which is that the compiler doesn't recognize the ODE constant "dInfinity". |
|
Back to top |
|
|
aldacron
Joined: 05 May 2004 Posts: 1322 Location: Seoul, South Korea
|
Posted: Fri Aug 21, 2009 8:40 pm Post subject: |
|
|
I've fixed the function declaration in the trunk, so it should work for you now. However, a quick "Find in Files" on the ODE headers failed to produce a hit for dInfinity. If it's not in the headers, it won't be in the bindings. _________________ The One With D | The One With Aldacron | D Bits |
|
Back to top |
|
|
Pishtaco
Joined: 21 Aug 2009 Posts: 3
|
Posted: Sat Aug 22, 2009 5:19 am Post subject: |
|
|
Thanks! Now it's working nicely.
For anyone interested, here's the full collision example.
It's based on the ODE tutorial here: http://artis.imag.fr/Membres/Xavier.Decoret/resources/ode/tutorial1.html
and the SDL tutorial at: http://dmedia.dprogramming.com
Code: | import derelict.sdl.sdl;
import derelict.opengl.gl;
import derelict.opengl.glu;
import derelict.ode.ode;
import tango.time.StopWatch;
import tango.math.Math;
import tango.math.random.Kiss;
const int xResolution = 640;
const int yResolution = 480;
const int bitsPerPixel = 24;
const float dt_MAX = 0.005;
void init()
{
DerelictSDL.load();
DerelictGL.load();
DerelictGLU.load();
DerelictODE.load();
dInitODE(); // Maybe need this
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS,true);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES,4);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_SetVideoMode(xResolution, yResolution, bitsPerPixel, SDL_OPENGL); // | SDL_FULLSCREEN);
SDL_WM_SetCaption("ODE example", null);
}
void cleanup() {
SDL_Quit();
DerelictGLU.unload();
DerelictGL.unload();
DerelictSDL.unload();
DerelictODE.unload();
}
int main(char[][] args)
{
init();
scope(exit) cleanup();
// Create ODE world and space
dWorldID world = dWorldCreate();
dSpaceID space = dHashSpaceCreate(cast(dSpaceID) 0);
dWorldSetGravity(world, 0, -0.981, 0);
dJointGroupID contact_group = dJointGroupCreate(0);
Model model = new Model();
model.world = world;
model.space = space;
model.contact_group = contact_group;
// Create a floor
dGeomID plane = dCreatePlane(space,0,1,0,0);
// Create cubes
const int cube_count = 80;
Cube[cube_count] cubes;
for (int i = 0; i < cube_count; i++)
{
cubes[i] = new Cube(world,space,3,1,1,1.5);
cubes[i].set_position(cast(float)i/3-10,5+3*i,cast(float)i/10);
cubes[i].color[] = [Kiss.instance.toInt(256),Kiss.instance.toInt(256),Kiss.instance.toInt(256)];
//(random number generator)
}
GeometryRenderer geometry_renderer = new GeometryRenderer();
StopWatch stopwatch;
stopwatch.start();
ulong last_time, current_time; // measured in micro seconds
last_time = stopwatch.microsec();
float elapsed, dt;
int step_count;
mainLoop:
while (true)
{
SDL_Event event;
// handle all SDL events that we might have received in this loop iteration
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT: // user has clicked on the window's close button
break mainLoop;
case SDL_KEYDOWN:
break mainLoop;
default:
break;
}
}
// SIMULATION
current_time = stopwatch.microsec();
elapsed = cast(float)(current_time - last_time)/1000000; // microseconds to seconds
last_time = current_time;
step_count = cast(int)floor(elapsed/dt_MAX)+1;
dt = elapsed / step_count;
step_count = min(step_count, 10);
for (int i = 0; i<step_count; i++)
{
// Detect & deal with collisions
dSpaceCollide(space, &model, &near_callback);
// Step world
dWorldQuickStep(world, dt);
// Remove all temporary collision joints
dJointGroupEmpty(contact_group);
}
// draw stuff
setup_GL();
geometry_renderer.draw_plane();
for (int i = 0; i < cube_count; i++)
{
cubes[i].render(geometry_renderer);
}
SDL_GL_SwapBuffers();
SDL_Delay(10);
}
return 0;
}
class Model //hack to get a way of passing local world variables to callback function
{
dWorldID world;
dSpaceID space;
dJointGroupID contact_group;
void handle_collision_between(dGeomID obj_0, dGeomID obj_1)
{
const int MAX_CONTACTS = 10;
dContactGeom[MAX_CONTACTS] contact_geoms;
dContact[MAX_CONTACTS] contacts;
int numc = dCollide(obj_0, obj_1, MAX_CONTACTS, contact_geoms.ptr, dContactGeom.sizeof);
if (numc>0)
{
dBodyID body_1 = dGeomGetBody(obj_0);
dBodyID body_2 = dGeomGetBody(obj_1);
for (int i = 0; i < numc; i++)
{
contacts[i].geom = contact_geoms[i];
contacts[i].surface.mode = dContactBounce | dContactSoftCFM;
// friction parameter
contacts[i].surface.mu = 10;
contacts[i].surface.mu2 = 0;
// bounce is the amount of "bouncyness".
contacts[i].surface.bounce = 0.5;
// bounce_vel is the minimum incoming velocity to cause a bounce
contacts[i].surface.bounce_vel = 0.2;
// constraint force mixing parameter
contacts[i].surface.soft_cfm = 0.001;
dJointID c = dJointCreateContact(world, contact_group, contacts.ptr+i);
dJointAttach(c, body_1, body_2);
}
}
}
}
// "extern(C) below ... see
// http://www.dsource.org/forums/viewtopic.php?t=4625&sid=3b902645a7abfd5a3fc44ef85ca2918d
extern(C) void near_callback(void* data, dGeomID obj_0, dGeomID obj_1)
{
Model* model = cast(Model*) data;
model.handle_collision_between(obj_0, obj_1);
}
class Entity
{
dBodyID bbody;
dGeomID geom;
void render(GeometryRenderer gr)
{
glPushMatrix();
dReal* p = dBodyGetPosition(this.bbody);
dReal* r = dBodyGetRotation(this.bbody);
float[16] m;
m[ 0] = r[ 0];m[ 1] = r[ 4];m[ 2] = r[ 8];m[ 3] = 0;
m[ 4] = r[ 1];m[ 5] = r[ 5];m[ 6] = r[ 9];m[ 7] = 0;
m[ 8] = r[ 2];m[ 9] = r[ 6];m[10] = r[10];m[11] = 0;
m[12] = p[ 0];m[13] = p[ 1];m[14] = p[ 2];m[15] = 1;
glMultMatrixf(m.ptr);
render_in_local_frame(gr);
glPopMatrix();
}
void set_position(dReal x, dReal y, dReal z)
{
dBodySetPosition(bbody,x,y,z);
}
void render_in_local_frame(GeometryRenderer gr)
{
}
}
class Cube : Entity
{
ubyte[3] color;
this(dWorldID world, dSpaceID space, dReal width, dReal height, dReal depth, dReal mass)
{
bbody = dBodyCreate(world);
geom = dCreateBox(space,width,height,depth);
dMass m;
dMassSetBox(&m,1.0f,width,height,depth);
dMassAdjust(&m,mass);
dBodySetMass(bbody,&m);
dGeomSetBody(geom,bbody);
}
void render_in_local_frame(GeometryRenderer gr)
{
dVector3 lengths;
dGeomBoxGetLengths(geom,lengths);
glScalef(lengths[0]/2,lengths[1]/2,lengths[2]/2);
glColor3ubv(color.ptr);
gr.draw_cube();
}
}
class GeometryRenderer
{
GLfloat[] vertices = [-1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, // top face
-1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1]; // bottom face
GLfloat[] plane_vertices = [-1, 0, -1, -1, 0, 1, 1, 0, 1, 1, 0, -1];
void draw_faces()
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices.ptr);
glDrawArrays(GL_QUADS, 0, 8);
glDisableClientState(GL_VERTEX_ARRAY);
}
void draw_cube()
{
glPushMatrix();
draw_faces();
glRotatef(90, 1, 0,0 );
draw_faces();
glRotatef(90, 0, 0, 1 );
draw_faces();
glPopMatrix();
}
void draw_plane()
{
glPushMatrix();
glScalef(30,30,30);
glColor3ub(250,250,150);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, plane_vertices.ptr);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
}
}
void setup_GL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, cast(float)xResolution / yResolution, 0.5, 200);
gluLookAt(-2,10,-7, // eye location
0,1,0, // target
0,1,0); // up vector
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
}
|
|
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|