[ODE] ODE / Mac OS X Crash
Kevin Reid
kpreid at attglobal.net
Fri Apr 5 09:54:02 2002
/* ODE/Mac OS X Crash Test
When compiled and executed on my computer, this program often crashes.
I believe that this is caused by ODE (specifically running on Mac OS
X), as most of the code was copied (after careful examination) from
ODE and GLUT demo programs.
Reducing the global CFM seems to make it survive longer, as does
reducing the number of bodies.
The simulation consists of NUMBODIES unit cubes or spheres dropped
onto a fixed xz plane, with gravity in the -y direction and damping to
produce a terminal velocity effect. The x and z location of the bodies
does not noticeably affect the crashing behavior.
Graphics display is done using OpenGL/GLUT. The original program which
exhibited this problem used Cocoa instead of GLUT.
Operating systems:
Mac OS X 10.1.x: crashes
x86 SuSE Linux: stable
My results with different numbers of boxes:
<= 40: stable
41-59: depends on how long you let it run
>= 60: SIGSEGV before all the objects fall
Crash log contains:
Thread 0 Crashed:
#0 0x0001a028 in dSolveLCP(int, double *, double *, double *, double *, int, double *, double *, int *)
#1 0x000047b4 in processIslands(dxWorld *, double)
#2 0x00003bd8 in myGlutIdle
#3 0x71679f1c in -[GLUTAppDelegate idleFuncDrawHack]
#4 0x71670dfc in -[GLUTApplication sendEvent:]
#5 0x70c23488 in -[NSApplication run]
#6 0x71676aec in glutMainLoop
#7 0x000044e8 in main
#8 0x00003608 in _start
#9 0x00003438 in start
- Kevin Reid, Jan 25 - Mar 28, 2002
*/
#include <stdio.h>
#include <GLUT/glut.h>
#include "ode/ode.h"
#define NUMBODIES 80
#define USE_SPHERE 0
#define USE_HELIX 1
#define USE_TORQUE 1
#define USE_WEIRD_MATRIX_OPS 0
#define CONTACTS 3
dWorldID aWorld;
dSpaceID aSpace;
float cycle = 0, fade;
dJointGroupID aContactGroup;
dBodyID bodies[NUMBODIES];
dGeomID geoms[NUMBODIES];
GLfloat colors[NUMBODIES][4];
unsigned int contactsThisFrame;
void kglTransformByODEGeom(dGeomID geom) {
const dReal *p = dGeomGetPosition(geom);
const dReal *R = dGeomGetRotation(geom);
GLdouble glm[16];
glm[0] = R[0]; glm[1] = R[4]; glm[2] = R[8]; glm[3] = 0;
glm[4] = R[1]; glm[5] = R[5]; glm[6] = R[9]; glm[7] = 0;
glm[8] = R[2]; glm[9] = R[6]; glm[10] = R[10];glm[11] = 0;
glm[12] = p[0]; glm[13] = p[1]; glm[14] = p[2]; glm[15] = 1;
glMultMatrixd(glm);
}
static void odeNearCallback(void *data, dGeomID g1, dGeomID g2) {
dBodyID b1 = dGeomGetBody(g1),
b2 = dGeomGetBody(g2);
dContact contact[CONTACTS];
int contactsUsed, i;
if (b1 && b2 && dAreConnected(b1, b2)) return;
contactsUsed = dCollide(g1, g2, CONTACTS, &contact[0].geom,
sizeof(dContact));
if (contactsUsed > CONTACTS) contactsUsed = CONTACTS;
for (i = 0; i < contactsUsed; i++) {
contact[i].surface.mode = 0;
contact[i].surface.mu = 20.0;
dJointAttach(dJointCreateContact(aWorld, aContactGroup,
&(contact[i])), b1, b2);
contactsThisFrame++;
}
}
void myGlutResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLfloat)w / h, 1.0, 120.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, -6, -20);
}
void myGlutIdle(void) {
const float step = 1.0/40;
int i;
cycle = fmod(cycle + step / 4, 1);
fade = fabs(cycle * 2 - 1);
contactsThisFrame = 0;
dSpaceCollide(aSpace, NULL, &odeNearCallback);
//printf("%u\n", contactsThisFrame);
dWorldStep(aWorld, step);
dJointGroupEmpty(aContactGroup);
for (i = 0; i < NUMBODIES; i++) {
const dReal *cvel = dBodyGetLinearVel(bodies[i]);
dBodyAddForce(bodies[i],
-cvel[0] * 1.25,
-cvel[1] * 1.25,
-cvel[2] * 1.25
);
}
glutPostRedisplay();
}
void myGlutDisplay(void) {
int i;
glClearColor(fade * 0.15, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (USE_WEIRD_MATRIX_OPS) glPushMatrix();
for (i = 0; i < NUMBODIES; i++) {
if (!USE_WEIRD_MATRIX_OPS) glPushMatrix();
kglTransformByODEGeom(geoms[i]);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colors[i]);
glColor3f(fade * 1.5, 0, 0);
#if USE_SPHERE
glRotatef(90, 1, 0, 0);
glutSolidSphere(0.5, 9, 6);
glDisable(GL_LIGHTING);
glutWireSphere(0.5, 9, 6);
#else
glutSolidCube(1);
glDisable(GL_LIGHTING);
glutWireCube(1);
#endif
glEnable(GL_LIGHTING);
if (!USE_WEIRD_MATRIX_OPS) glPopMatrix();
}
if (USE_WEIRD_MATRIX_OPS) glPopMatrix();
glutSwapBuffers();
}
int main(int argc, char **argv) {
printf("Initializing GLUT\n");
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 300);
glutInitWindowPosition(100, 100);
glutCreateWindow("ODE Crash Test");
glutDisplayFunc(myGlutDisplay);
glutReshapeFunc(myGlutResize);
glutIdleFunc(myGlutIdle);
glPolygonOffset(1, 1);
glDepthFunc(GL_LEQUAL);
glEnable(GL_POLYGON_OFFSET_FILL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
myGlutResize(400, 300);
printf("Creating ODE world\n");
aWorld = dWorldCreate();
aSpace = dHashSpaceCreate();
aContactGroup = dJointGroupCreate(0);
dCreatePlane(aSpace, 0, 1, 0, 0);
dWorldSetGravity(aWorld, 0, -9.81, 0);
dWorldSetERP(aWorld, 0.5);
dWorldSetCFM(aWorld, 1e-10);
printf("Creating objects\n");
{
int i;
dMass mass;
dMassSetBox(&mass, 1.0, 1, 1, 1);
for (i = 0; i < NUMBODIES; i++) {
float fraction = (float)i / NUMBODIES;
bodies[i] = dBodyCreate(aWorld);
dBodySetMass(bodies[i], &mass);
#if USE_SPHERE
geoms[i] = dCreateSphere(aSpace, 0.5);
#else
geoms[i] = dCreateBox(aSpace, 1, 1, 1);
#endif
dGeomSetBody(geoms[i], bodies[i]);
if (USE_HELIX) {
float r = (i % 3 - 1) * (1.5+4*(1 - fraction)),
theta = (float)i / 4;
dBodySetPosition(bodies[i],
sin(theta) * r,
(float)i + 1,
cos(theta) * r
);
} else {
dBodySetPosition(bodies[i], 0, (float)i * 2 + 1, 0);
}
if (USE_TORQUE) dBodyAddTorque(bodies[i], fraction*10, fraction*20, fraction*30);
colors[i][0] = fraction;
colors[i][1] = 1 - fraction;
colors[i][2] = 1 - fabs(fraction * 2 - 1);
colors[i][3] = 1;
}
}
printf("Starting simulation\n");
glutMainLoop();
return 0;
}