PDA

View Full Version : Rotating cube, sphere and collision.

UnIcron
02-23-2003, 11:57 PM
Could anyone help me? I v worked on this for about two days, and it is just not what it is supposed to be.
This is the file here. You can rotate the cube by pressing 'x', 'y' or 'z' keys.
I wanna the collisions to be detected and the sphere reflects narturally. Any idea?

I have to finish this by tomorrow. Could anyone who wants to help me rply asap or, email to me at jjnn5@hotmail.com.
Thanks a lot.

//#include <GL/gl.h>
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>

#define COS(X) cos( (X) * 3.14159/180.0 )
#define SIN(X) sin( (X) * 3.14159/180.0 )
#define FALSE 0
#define TRUE 1

#define rw 5.0 /* Room width.*/
#define G -0.5 /* vertical acceleration */

// Objects
GLuint Ball;
GLuint Room;

GLenum Mode;
GLboolean FIRST_RENDER = GL_TRUE;

// Rotation variables.
GLfloat Zrot = 0.0;
GLfloat Zstep = 0.50; /* increment for the ball rotation */
GLfloat Xang = 0.0, Yang = 0.0, Zang = 0.0;

// Position variables.
GLfloat pos[3] = {0.0, 1.0, 0.0};
GLfloat vel[3] = {0.0005, 0.0, 0.0};

// Environment variables
GLfloat g = 0.0;
GLfloat E = 0.5; /* Energy lost */

GLfloat viewZ = 15.0;

// Collision detection variables.
GLfloat Xmin, Xmax;
GLfloat Zmin, Zmax;
GLfloat Ymin, Ymax;

//const GLfloat a = 5.0;
//Vertices; from front to back, CCW.
GLfloat vertices[8][3] = {
{-rw,-rw,rw},
{-rw,rw,rw},
{rw,rw,rw},
{rw,-rw,rw},
{-rw,-rw,-rw},
{rw,-rw,-rw},
{rw,rw,-rw},
{-rw,rw,-rw}};
GLfloat verTrans[8][3] = {
{-rw,-rw,rw},
{-rw,rw,rw},
{rw,rw,rw},
{rw,-rw,rw},
{-rw,-rw,-rw},
{rw,-rw,-rw},
{rw,rw,-rw},
{-rw,rw,-rw}};
GLfloat edges[3][3];

/* normals
0: left; 1: right; 2: top; 3: bottom; 4: front; 5: back.
*/
GLfloat normals[6][3];

GLfloat trans[16] = {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 };

/* Math functions */
// oprA and oprB are 1x3 vectors; this method returns the result vector.
void crossMult3x3v( GLfloat *oprA, GLfloat *oprB, GLfloat *result ) {
result[0] = oprA[1]*oprB[2] - oprA[2]*oprB[1];
result[1] = oprA[2]*oprB[0] - oprA[0]*oprB[2];
result[2] = oprA[0]*oprB[1] - oprA[1]*oprB[0];
}

void minus3x3v( GLfloat *oprA, GLfloat *oprB, GLfloat *result ) {
result[0] = oprA[0] - oprB[0];
result[1] = oprA[1] - oprB[1];
result[2] = oprA[2] - oprB[2];

}

void plus3x3v( GLfloat *oprA, GLfloat *oprB, GLfloat *result) {
result[0] = oprA[0] + oprB[0];
result[1] = oprA[1] + oprB[1];
result[2] = oprA[2] + oprB[2];
}

// Dot multiplication of two 3D vectors.
GLfloat dotMult3x3v( GLfloat *oprA, GLfloat *oprB ) {
return (oprA[0]*oprB[0] + oprA[1]*oprB[1] + oprA[2]*oprB[2]);
}

// For transformation to a vertex. Row vector used.
void mult4x16v( GLfloat *oprA, GLfloat *oprB, GLfloat *result ) {
result[0] = oprA[0]*oprB[0]+oprA[1]*oprB[1] + oprA[2]*oprB[2] + oprA[3]*oprB[3];
result[1] = oprA[0]*oprB[4]+oprA[1]*oprB[5] + oprA[2]*oprB[6] + oprA[3]*oprB[7];
result[2] = oprA[0]*oprB[8]+oprA[1]*oprB[9] + oprA[2]*oprB[10] + oprA[3]*oprB[11];
result[3] = oprA[0]*oprB[12]+oprA[1]*oprB[13] + oprA[2]*oprB[14] + oprA[3]*oprB[15];
}

void toHomogeneous( GLfloat *vertex, GLfloat h ) {
GLfloat result[4];
if( h == 0 ) h = 1.0;

result[0] = vertex[0]*h;
result[1] = vertex[1]*h;
result[2] = vertex[2]*h;
result[3] = h;

vertex = result;
}

void toThreeDimen( GLfloat *vertex ) {
GLfloat result[3];

if( vertex[3] != 0 ) {
result[0] = vertex[0]/vertex[3];
result[1] = vertex[1]/vertex[3];
result[2] = vertex[2]/vertex[3];

vertex = result;
}
}

GLfloat getValue( GLfloat *v ) {
return sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
}

void linearMult( GLfloat *v, GLfloat factor, GLfloat *r ) {
r[0] = v[0]*factor;
r[1] = v[1]*factor;
r[2] = v[2]*factor;
}
/*end of math functions*/

/* help functions */
void transVertices() {
int i;

for( i=0; i<8; i++ ) {
toHomogeneous( vertices[i], 1.0 );
mult4x16v( vertices[i], trans, verTrans[i] );
toThreeDimen( vertices[i] );
toThreeDimen( verTrans[i] );
}
}

void calEdges() {
minus3x3v( verTrans[1], verTrans[0], edges[0] );
minus3x3v( verTrans[3], verTrans[0], edges[1] );
minus3x3v( verTrans[4], verTrans[0], edges[2] );
}

void calNormals() {
crossMult3x3v( edges[2], edges[0], normals[0] );
crossMult3x3v( edges[0], edges[2], normals[1] );
crossMult3x3v( edges[2], edges[1], normals[2] );
crossMult3x3v( edges[1], edges[2], normals[3] );
crossMult3x3v( edges[0], edges[1], normals[4] );
crossMult3x3v( edges[1], edges[0], normals[5] );
}

GLboolean hitWall( GLfloat *vertex, GLfloat *normal, GLfloat *curP ) {
GLfloat pToPlane[3];
GLfloat dotM, nValue;

minus3x3v( curP, vertex, pToPlane );
dotM = dotMult3x3v( pToPlane, normal );
nValue = getValue( normal );

return GL_TRUE;
return GL_FALSE;
}

void reflect( GLfloat *normal, GLfloat *v ) {
//int i;
GLfloat normalCP[3];

GLfloat nValue = getValue(normal);
GLfloat dotM = dotMult3x3v( v, normal );
dotM = abs(dotM);
g = 0;
//printf("nValue:%f\tdotM:%f\t%f\n\n", nValue,dotM, 2*dotM/(nValue*nValue));
/*
printf("before");
for( i = 0; i<3; i++ ) printf( "%f\t", v[i] );
printf("\n\n");
*/
linearMult( normal, 2*dotM/(nValue*nValue), normalCP );
/*
printf("normal");
for( i = 0; i<3; i++ ) printf( "%f\t", normal[i] );
printf("\n\n");
*/
plus3x3v( normalCP, v, v );
/*
printf("after");
for( i = 0; i<3; i++ ) printf( "%f\t", v[i] );
printf("\n\n");
*/}

void testCollisions(GLfloat *curP, GLfloat *curV ) {
GLfloat tem[3];

if( hitWall( verTrans[0], normals[0], pos ) ) {
minus3x3v( pos, tem, pos );
reflect( normals[0], vel );
//linearMult(vel, -1, vel);
linearMult( vel, E, vel );
printf( "hello 0\n" );
}
if( hitWall( verTrans[6], normals[1], pos ) ) {
minus3x3v( pos, tem, pos );
reflect( normals[1], vel );
//linearMult(vel, -1, vel);
linearMult( vel, E, vel );
printf( "hello 1\n" );
}
if( hitWall( verTrans[6], normals[2], pos ) ) {
minus3x3v( pos, tem, pos );
reflect( normals[2], vel );
//linearMult(vel, -1, vel);
linearMult( vel, E, vel );
printf( "hello 2\n" );
}
if( hitWall( verTrans[0], normals[3], pos ) ) {
minus3x3v( pos, tem, pos );
reflect( normals[3], vel );
//linearMult(vel, -1, vel);
linearMult( vel, E, vel );
printf( "hello 3\n" );
}
if( hitWall( verTrans[0], normals[4], pos ) ) {
minus3x3v( pos, tem, pos );
reflect( normals[4], vel );
//linearMult(vel, -1, vel);
linearMult( vel, E, vel );
printf( "hello 4\n" );
}
if( hitWall( verTrans[6], normals[5], pos ) ) {
minus3x3v( pos, tem, pos );
reflect( normals[5], vel );
//linearMult(vel, -1, vel);
linearMult( vel, E, vel );
printf( "hello 5\n" );
}

}

void move() {
g += (0.5*G*0.02*0.02);

vel[1] += g;

pos[0] += vel[0];
pos[1] += vel[1];
pos[2] += vel[2];
}
/*End of help functions*/

void init (void ) {
GLfloat ambientLight[] = {0.4f, 0.4f, 0.4f, 1.0f};
GLfloat diffuseLight[] = {0.7f, 0.7f, 0.7f, 1.0f};
GLfloat specular[] = { 0.9f, 0.9f, 0.9f, 1.0f };
GLfloat lightPos[] = { -50.0f, 200.0f, 200.0f, 1.0f };
GLfloat specref[] = {0.6f, 0.6f, 0.6f, 1.0f };

// glEnable( GL_BLEND );
// glBlendFunc( GL_SRC_ALPHA, GL_SRC_ALPHA );
glEnable( GL_LIGHTING );

glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambientLight );
glLightfv( GL_LIGHT0, GL_AMBIENT, ambientLight );
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuseLight );
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );

glLightfv( GL_LIGHT0, GL_POSITION, lightPos );
glEnable( GL_LIGHT0 );

glEnable( GL_COLOR_MATERIAL);
glEnable( GL_DEPTH_TEST );
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
glMaterialfv( GL_FRONT, GL_SPECULAR, specref);
glMateriali( GL_FRONT, GL_SHININESS, 64 );
glClearColor( 0.0, 0.0, 0.0, 1.0 );
}

static GLuint make_ball( void )
{
GLuint list;
GLfloat a, b;
GLfloat da = 18.0, db = 18.0;
GLuint color;
GLfloat x, y, z;
GLuint aIndex, bIndex;

// All vertices are stored in this table to enhance performance.
static GLfloat BallTable[10][20][2][3];

list = glGenLists( 1 );

glNewList( list, GL_COMPILE );

color = 0;

for (a=-90.0, aIndex = 0;a+da<=90.0;a+=da, aIndex++) {

for (b=0.0,bIndex = 0 ;b<=360.0 ;b+=db, bIndex++) {

if( FIRST_RENDER ) {
x = Brad * COS(b) * COS(a);
y = Brad * SIN(b) * COS(a);

BallTable[aIndex][bIndex][0][0] = x;
BallTable[aIndex][bIndex][0][1] = y;
BallTable[aIndex][bIndex][0][2] = z;
}

glVertex3fv(BallTable[aIndex][bIndex][0]);
color?glColor4f(0.0,0.0,1.0, 1.0):glColor4f(1.0,0.0,0.0,1.0);

if( FIRST_RENDER ) {
x = Brad * COS(b) * COS(a+da);
y = Brad * SIN(b) * COS(a+da);

BallTable[aIndex][bIndex][1][0] = x;
BallTable[aIndex][bIndex][1][1] = y;
BallTable[aIndex][bIndex][1][2] = z;
}

color?glColor4f(0.0,0.0,1.0,1.0):glColor4f(1.0,0.0 ,0.0,1.0);
glVertex3fv(BallTable[aIndex][bIndex][1]);

color = 1-color;
}
glEnd();
}

glEndList();

FIRST_RENDER = GL_FALSE;

return list;
}

static GLuint build_room( void )
{
GLuint list;

list = glGenLists( 1 );

glNewList( list, GL_COMPILE );

glColor4f( 1.0, 1.0, 1.0 , 1.0 );

glutWireCube(rw*2);
/*
glBegin( GL_LINES );

//Left
glNormal3fv( Leftn );
glVertex3i(-a,-a,a);
glVertex3i(-a,-a,-a);
glVertex3i(-a,a,-a);
glVertex3i(-a,a,a);
glGetFloatv(GL_CURRENT_NORMAL, Leftn );
printf("< %f, %f, %f>\n", Leftn[0], Leftn[1], Leftn[2]);

//Top
glVertex3i(-a,a,a);
glVertex3i(-a,a,-a);
glVertex3i(a,a,-a);
glVertex3i(a,a,a);

//Right
glVertex3i(a,a,a);
glVertex3i(a,a,-a);
glVertex3i(a,-a,-a);
glVertex3i(a,-a,a);

//Bottom
glVertex3i(-a,-a,a);
glVertex3i(a,-a,a);
glVertex3i(a,-a,-a);
glVertex3i(-a,-a,-a);

//Front
glVertex3i(-a,-a,a);
glVertex3i(-a,a,a);
glVertex3i(a,a,a);
glVertex3i(a,-a,a);

//Back
glVertex3i(-a,-a,-a);
glVertex3i(-a,a,-a);
glVertex3i(a,a,-a);
glVertex3i(a,-a,-a);

glEnd();
*/
glEndList();

return list;
}

static void reshape( int width, int height )
{
GLfloat nRange = 50.0;

glViewport(0, 0, (GLint)width, (GLint)height);

// Reset projection matrix stack
glMatrixMode(GL_PROJECTION);

if( height <= 0 ) height = 1;

gluPerspective( 45.0f, width/height, 5.0, -30.0 );
// glFrustum( -5.0, 5.0, -5.0, 5.0, 5.0, 20.0 );
// glOrtho( -1*nRange, nRange, -1*nRange, nRange, -1*nRange, nRange );

// Reset Model view mateix stack
glMatrixMode(GL_MODELVIEW);

}

static void draw( void )
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();
gluLookAt( 0.0, 0.0, viewZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );

glPushMatrix();
glRotatef(Xang, 1.0, 0.0, 0.0);
glRotatef(Yang, 0.0, 1.0, 0.0);
glRotatef(Zang, 0.0, 0.0, 1.0);

glGetFloatv( GL_MODELVIEW_MATRIX, trans );

glCallList( Room );

glBegin(GL_LINES);
glColor3f( 0.0, 0.0, 1.0 );
glVertex3f( 0.0, 0.0, 0.0 );
glVertex3f( 3.0, 0.0, 0.0 );
glColor3f( 1.0, 0.0, 0.0 );
glVertex3f( 0.0, 0.0, 0.0 );
glVertex3f( 0.0, 3.0, 0.0 );
glColor3f( 0.0, 1.0, 0.0 );
glVertex3f( 0.0, 0.0, 0.0 );
glVertex3f( 0.0, 0.0, 3.0 );
glEnd();
glPopMatrix();

glTranslatef( pos[0], pos[1], pos[2] );
glScalef( 2.0, 2.0, 2.0 );
glRotatef( 8.0, 0.0, 0.0, 1.0 );
glRotatef( 90.0, 1.0, 0.0, 0.0 );
glRotatef( Zrot, 0.0, 0.0, 1.0 );
glCallList( Ball );

glPopMatrix();

/* animation */
glFlush();
glutSwapBuffers();

}

static void idle( void ) {
int i, j;
transVertices();
calEdges();
calNormals();
testCollisions( pos, vel );
move();

/*
for( i=0; i< 6; i++ ){
for( j =0; j <3; j++ ) printf("%f\t", normals[i][j] );
printf("\n");}
printf("\n"); */
printf( "%f\n\n", getValue( vel ));
draw();
}

/*
static void idle( void )
{
static float vel0 = -100.0;

g+=0.5*G*0.02*0.02;

Zrot += Zstep;

pos[0] += vel[0];
if (pos[0]>=Xmax) {
pos[0] = Xmax;
vel[0] = -vel[0];

if( vel[0] >= 0 ) vel[0]+= E;
else vel[0] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;

Zstep = -Zstep;
}
if (pos[0]<=Xmin) {
pos[0] = Xmin;
vel[0] = -vel[0];

if( vel[0] >= 0 ) vel[0]+= E;
else vel[0] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;

Zstep = -Zstep;
}

vel[1] += g;
pos[1] += vel[1];
if (pos[1]<Ymin) {
pos[1] = Ymin;
vel[1] = -vel[1];

if( vel[0] >= 0 ) vel[0]+= E;
else vel[0] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;
}
if (pos[1]> Ymax) {
pos[1] = Ymax;
vel[1] = -vel[1];

if( vel[0] >= 0 ) vel[0]+= E;
else vel[0] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;
}

pos[2] += vel[2];

if ( pos[2] < Zmin ) {
pos[2] = Zmin;
vel[2] = -vel[2];

if( vel[0] >= 0 ) vel[0]+= E;
else vel[0] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;

}
if ( pos[2] > Zmax ) {
pos[2] = Zmax;
vel[2] = -vel[2];

if( vel[0] >= 0 ) vel[0]+= E;
else vel[0] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;
if( vel[1] >= 0 ) vel[1]+= E;
else vel[1] -= E;
}

draw();
}
*/

static void key(unsigned char k, int x, int y)
{
switch (k) {
case 27:
exit (0);
break;
case 'b':
viewZ += 1.0;
draw();
break;
case 'x':
Xang++;
break;
case 'y':
Yang++;
break;
case 'z':
Zang++;
break;
}

}

void main( int argc, char *argv[] )
{

glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Bouncing ball 1. By Jin Jun SA2");

init();

Ball = make_ball();
Room = build_room();

glCullFace( GL_BACK );
glEnable( GL_CULL_FACE );
glDisable( GL_DITHER );