I have a few questions based on the code below. It was compiled using freeglut on win32 with mingw32 but it should compile with glut and gcc under linux.
I suspect from the code below that the position vectors are incorrect since the force sphere doesn't only rotate about the y-axis as you'll see if you run it. I've varied the friction coefficients but can't get the spheres to rotate. Any suggestions? Lastly, how difficult would it be to model a cylindrical container instead of using four walls as shown.
Thanks
- Code: Select all
// compile using:
//gcc -o isaac.exe isaac.c -lopengl32 -lglu32 -lfreeglut -lNewton
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <gl/glut.h>
#include <Newton/Newton.h>
#define NUMSPHERES 5
static NewtonWorld* nWorld;
static NewtonBody* sphBody[NUMSPHERES];
static NewtonBody* floorBody;
static NewtonBody* wall1Body;
static NewtonBody* wall2Body;
static NewtonBody* wall3Body;
static NewtonBody* wall4Body;
int showaxis=1;
int showcont=1;
int fullscreen=0;
int showfps=1;
int w=640, h=480;
float fps = 10.0;
float timeStep=0.010; //fps/1000
// sphere
float sphRadius = 0.5f;
float sphMass = 1.0f;
// floor
float fwidth = 500.0f;
float fheight = 2.0f;
float fypos = -1.0;
// walls
float width = 1.0f; // 2*sphRadius
float cwidth = 2.0f; //2.0f*width
float cheight = 6.0f;
float wypos = 0.0;
float gravity = -9.81f;
GLuint axis;
GLuint cont;
GLUquadric *sphere;
void initTex(void)
{
GLuint i;
GLboolean flag;
GLubyte data[256]; /* texture map data */
flag = GL_FALSE;
/* generate chessboard image */
for (i = 0; i < 64; i++)
{
if (!(i % 8))
flag = !flag;
if (flag) /* square is red */
{
data[4 * i ] = 255;
data[4 * i+ 1] = 0;
data[4 * i + 2] = 0;
data[4 * i + 3] = 255;
}
else /* square is white */
{
data[4 * i ] = 255;
data[4 * i+ 1] = 255;
data[4 * i + 2] = 255;
data[4 * i + 3] = 255;
}
flag = !flag;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps (GL_TEXTURE_2D, GL_RGBA, 8, 8, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
void FPS(void)
{
static int frame,tb;
int ttime;
char s[30];
frame++;
ttime=glutGet(GLUT_ELAPSED_TIME);
if (ttime - tb > 1000)
{
sprintf(s,"FPS: %4.2f",frame*1000.0/(ttime-tb));
if (showfps) printf("%s\n",s);
tb = ttime;
frame = 0;
}
}
void reshape(w, h)
{
if (h<=0) h=1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)w/h, 1,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5,5,4,0,1,0,0,1,0);
}
void clrDisplay(void)
{
glClearColor(0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void drawContainer()
{
glColor3f(1, 1, 0);
glPushMatrix();
//base
glBegin(GL_LINE_LOOP);
glVertex3f(-width,0,width);
glVertex3f( width,0,width);
glVertex3f( width,0,-width);
glVertex3f(-width,0,-width);
glEnd();
//top
glBegin(GL_LINE_LOOP);
glVertex3f(-width,cheight*width,width);
glVertex3f( width,cheight*width,width);
glVertex3f( width,cheight*width,-width);
glVertex3f(-width,cheight*width,-width);
glEnd();
//corner 1
glBegin(GL_LINES);
glVertex3f(-width,0,width);
glVertex3f(-width,cheight*width,width);
glEnd();
//corner 2
glBegin(GL_LINES);
glVertex3f(width,0,width);
glVertex3f(width,cheight*width,width);
glEnd();
//corner 3
glBegin(GL_LINES);
glVertex3f(-width,0,-width);
glVertex3f(-width,cheight*width,-width);
glEnd();
//corner 4
glBegin(GL_LINES);
glVertex3f(width,0,-width);
glVertex3f(width,cheight*width,-width);
glEnd();
glPopMatrix();
}
void drawAxis(void)
{
glPushMatrix();
glColor3f(1, 0, 0);
glBegin(GL_LINES);
glVertex3f(0, 0, 0);
glVertex3f(10, 0, 0);
glEnd();
glColor3f(0, 1, 0);
glBegin(GL_LINES);
glVertex3f(0, 0, 0);
glVertex3f(0, 10, 0);
glEnd();
glColor3f(0, 0, 1);
glBegin(GL_LINES);
glVertex3f(0, 0, 0);
glVertex3f(0, 0, 10);
glEnd();
glPopMatrix();
}
void showSpheres(void)
{
int i,j;
dFloat location[4][4];
glColor3f(1.0f,1.0f,1.0f);
glEnable(GL_TEXTURE_2D);
for (i=0;i<NUMSPHERES;i++)
{
glPushMatrix();
NewtonBodyGetMatrix(sphBody[i], &location[0][0]);
glMultMatrixf(&location[0][0]);
gluSphere(sphere,sphRadius,12,12);
glPopMatrix();
}
glDisable(GL_TEXTURE_2D);
}
void display(void)
{
clrDisplay();
if (!glIsList(axis))
{
axis = glGenLists(1);
glNewList(axis, GL_COMPILE);
drawAxis();
glEndList();
}
if (!glIsList(cont))
{
cont = glGenLists(1);
glNewList(cont, GL_COMPILE);
drawContainer();
glEndList();
}
showSpheres();
if (showfps) FPS();
if (showaxis) glCallList(axis);
if (showcont) glCallList(cont);
glutSwapBuffers();
}
void idleFunc(void)
{
glutPostRedisplay();
}
void timerFunc(int val)
{
if (val)
{
NewtonUpdate(nWorld, timeStep);
idleFunc();
glutTimerFunc(fps,timerFunc,1);
}
}
void keyboard(unsigned char key, int x, int y)
{
if (key == 27)
{
glutLeaveMainLoop();
}
else if (key == 'a')
{
showaxis=!showaxis;
}
else if (key == 'c')
{
showcont=!showcont;
}
else if (key == 'p')
{
showfps=!showfps;
}
else if (key == 'f')
{
fullscreen=!fullscreen;
if (fullscreen)
{
glutFullScreen();
}
else
{
glutReshapeWindow(w,h);
glutPositionWindow(0,0);
}
printf("fullscreen %d\n",fullscreen);
}
}
void* PhysicsAlloc (int sizeInBytes)
{
return malloc (sizeInBytes);
}
void PhysicsFree (void *ptr, int sizeInBytes)
{
free (ptr);
}
void cleanUp (void)
{
NewtonDestroy (nWorld);
}
void sphPhysicsApplyForceAndTorque (const NewtonBody* body)
{
dFloat mass;
dFloat Ixx;
dFloat Iyy;
dFloat Izz;
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
dFloat force[3]={0.0f, mass*gravity, 0.0f};
//dFloat torque[3]={1.0f, 0.0f, 0.0f};
NewtonBodySetForce (body, &force[0]);
//NewtonBodySetTorque (body, &torque[0]);
}
void driverPhysicsApplyForceAndTorque (const NewtonBody* body)
{
dFloat mass;
dFloat Ixx;
dFloat Iyy;
dFloat Izz;
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
dFloat force[3]={0.0f, 100.0*mass*gravity, 0.0f};
dFloat torque[3]={0.0f, 100.0f, 0.0f};
NewtonBodySetForce (body, &force[0]);
NewtonBodySetTorque (body, &torque[0]);
}
void setLoc(dFloat a[4][4],dFloat b[4][4])
{
int i,j;
for (i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
b[i][j]=a[i][j];
}
}
}
void initNewton(void)
{
int i=0;
float sphI = (2.0/5.0)*sphMass*sphRadius*sphRadius;
dFloat sphForce[3]={0.0f,sphMass*gravity,0.0f};
//dFloat sphTorque[3]={1.0f,0.0f,0.0f};
dFloat x=0,y=0,z=0;
dFloat sx[5] = {-0.5, 0.5, 0.5,-0.5, 0.0};
dFloat sy[5] = { 1.5, 1.5, 1.5, 1.5, 2.0};
dFloat sz[5] = { 0.5, 0.5,-0.5,-0.5, 0.0};
dFloat location0[4][4] = {{1.0,0.0,0.0,0.0},
{0.0,1.0,0.0,0.0},
{0.0,0.0,1.0,0.0},
{0.0,0.0,0.0,1.0}};
dFloat location[4][4];
printf("NPE Version: %d\n",NewtonWorldGetVersion(nWorld));
NewtonCollision *collision;
nWorld = NewtonCreate (PhysicsAlloc, PhysicsFree);
///////////////////////////////////////////////////// spheres
// create spheres
for (i = 0;i<NUMSPHERES;i++)
{
collision = NewtonCreateSphere (nWorld, sphRadius, sphRadius, sphRadius, NULL);
sphBody[i] = NewtonCreateBody (nWorld, collision);
if (i<4)
{
NewtonBodySetForceAndTorqueCallback (sphBody[i], sphPhysicsApplyForceAndTorque);
}
else
{
NewtonBodySetForceAndTorqueCallback (sphBody[i], driverPhysicsApplyForceAndTorque);
}
NewtonBodySetMassMatrix (sphBody[i], sphMass, sphI, sphI, sphI);
NewtonBodySetForce (sphBody[i], &sphForce[0]);
setLoc(location0,location);
x=sx[i];
y=sy[i];
z=sz[i];
location[3][0]=x;
location[3][1]=y;
location[3][2]=z;
NewtonBodySetMatrix (sphBody[i], &location[0][0]);
}
///////////////////////////////////////////////////// floor
// create the floor
collision = NewtonCreateBox (nWorld, fwidth, fheight, fwidth, NULL);
floorBody = NewtonCreateBody (nWorld, collision);
setLoc(location0,location);
x = 0.0f;
y = fypos;
z = 0.0f;
location[3][0]=x;
location[3][1]=y;
location[3][2]=z;
NewtonBodySetMatrix (floorBody, &location[0][0]);
///////////////////////////////////////////////////// wall 1
// create wall 1
collision = NewtonCreateBox (nWorld, cwidth, cheight, cwidth, NULL);
wall1Body = NewtonCreateBody (nWorld, collision);
setLoc(location0,location);
x = 2.0f;
y = wypos;
z = 0.0f;
location[3][0]=x;
location[3][1]=y;
location[3][2]=z;
NewtonBodySetMatrix (wall1Body, &location[0][0]);
///////////////////////////////////////////////////// wall 2
// create wall 2
collision = NewtonCreateBox (nWorld, cwidth, cheight, cwidth, NULL);
wall2Body = NewtonCreateBody (nWorld, collision);
setLoc(location0,location);
x = 0.0f;
y = wypos;
z = -2.0f;
location[3][0]=x;
location[3][1]=y;
location[3][2]=z;
NewtonBodySetMatrix (wall2Body, &location[0][0]);
///////////////////////////////////////////////////// wall 3
// create wall 3
collision = NewtonCreateBox (nWorld, cwidth, cheight, cwidth, NULL);
wall3Body = NewtonCreateBody (nWorld, collision);
setLoc(location0,location);
x = -2.0f;
y = wypos;
z = 0.0f;
location[3][0]=x;
location[3][1]=y;
location[3][2]=z;
NewtonBodySetMatrix (wall3Body, &location[0][0]);
///////////////////////////////////////////////////// wall 4
// create wall 4
collision = NewtonCreateBox (nWorld, cwidth, cheight, cwidth, NULL);
wall4Body = NewtonCreateBody (nWorld, collision);
setLoc(location0,location);
x = 0.0f;
y = wypos;
z = 2.0f;
location[3][0]=x;
location[3][1]=y;
location[3][2]=z;
NewtonBodySetMatrix (wall4Body, &location[0][0]);
// Release collision
NewtonReleaseCollision (nWorld, collision);
// get the default material ID
int defaultID = NewtonMaterialGetDefaultGroupID (nWorld);
// Set default material properties
//NewtonMaterialSetDefaultSoftness (nWorld, defaultID, defaultID, 0.05f);
//NewtonMaterialSetDefaultElasticity (nWorld, defaultID, defaultID, 0.4f);
//NewtonMaterialSetDefaultCollidable (nWorld, defaultID, defaultID, 1);
NewtonMaterialSetDefaultFriction (nWorld, defaultID, defaultID, 1.9f, 1.09f);
}
void initGL(void)
{
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(w,h);
glutInitWindowPosition(0,0);
glutCreateWindow("Amit's demo - Press ESC to exit");
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutIdleFunc(idleFunc);
glutTimerFunc(0, timerFunc, 1);
sphere=gluNewQuadric();
gluQuadricTexture(sphere,1);
initTex();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
initNewton();
initGL();
glutMainLoop();
cleanUp();
return 0;
}