Translating an object

Okay, so first let me get it out of the way that this is not entirely my project. I have not done all the coding, so everything you will see in the code is not completely from my knowledge. I am rather new at OpenGL, and rather new at programming all together. That said, I am in the middle of a lengthy project with a group, and so far we have come up with an octahedron that bounces within a cube, translating after each wall hit. Complete with materials, lights and shadows. I am now at the task of having to add menu functionality for translating the octahedron (up, down, left, right, forward, backward). The easiest way I see this being done is relative to where the octahedron currently is when you do the translating. I am just not exactly sure how I should be going about this. Any helpful hints or tips will be GREATLY appreciated. Thanks for everything guys. Note; making the menu will not be the problem, I can do that easily, its the actual coding of the translations I am worried about.

That all said, here is the code. :slight_smile:

octahedron.h


#include <GL/glut.h>

/**********************************************************/
/* Material */
/**********************************************************/

struct Material {
  GLfloat ambient[4];
  GLfloat diffuse[4];
  GLfloat specular[4];
  GLfloat shiny;
};
typedef struct Material Material;

struct Point{
	GLfloat x;
	GLfloat y;
	GLfloat z;
};
typedef struct Point Point;

Material WhatIsBrass(void);
Material WhatIsWhiteShiny(void);
Material WhatIsRedPlastic(void);

#define Brass WhatIsBrass()
#define WhiteShiny WhatIsWhiteShiny()
#define RedPlastic WhatIsRedPlastic()

void SetMaterial(Material m);

octahedron.cpp


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <GL/glut.h>
#include <math.h>
#include "octahedron.h"

#define PI 3.14159265

GLsizei ww = 700, wh = 700;
GLdouble orthoX = 700, orthoY = 700, orthoZ = 700;
GLint wcx = 180, wcy = 180;
int xTrack, yTrack;					//tracks mouse movement
GLfloat moveX = 0.0, moveY = 0.0, moveZ = 0.0;
GLfloat rotX = 0, rotY = 0, rotZ = 0;
GLfloat delX = 0.16, delY = 0.05, delZ = 0.2;

float rotSpeed[2];					//to be possibly used later for automatic rotation

bool tracking = false;				//true when left mouse is held down
									//since the octahedron rotation is handled by bouncing,
									//should probably use this to move camera around

const GLfloat f[16] = {1, 0, 0, 0,
						0, 0, 0, 0,
						0, 0, 1, 0,
						0,-4, 0, 1};

double rotation[2] = {0,0};			//keeps track of current rotation

GLfloat vertices[6][3] =	{{0,1,0}, //0, 1, ... , 5
							{0,-1,0}, 
							{0,0,1}, 
							{1,0,0}, 
							{-1,0,0}, 
							{0,0,-1}};
GLubyte octaIndices[24] =	{0,2,3,     //face indices
							 0,2,4,
							 0,5,4,
							 0,5,3,
							 1,2,4,
							 1,2,3,
							 1,5,3,
							 1,5,4};



//calculate the norm from three points
//could be optimized a bit
Point norm(GLfloat a[3], GLfloat b[3], GLfloat c[3])
{
	GLfloat v1[3] = {a[0] - c[0], a[1] - c[1], a[2] - c[2]};
	GLfloat v2[3] = {b[0] - c[0], b[1] - c[1], b[2] - c[2]};
	//(a2b3 &#8722; a3b2, a3b1 &#8722; a1b3, a1b2 &#8722; a2b1)
	Point n = {(v1[1] * v2[2]) - (v1[2] * v2[1]),
		(v1[2] * v2[0]) - (v1[0] * v2[2]),
		(v1[0] * v2[1]) - (v1[1] * v2[0])};

	return n;
}

//calculate normal of each face, draw the face
//for some reason the normal of each odd face points inwards, so they are negated
void drawOcta(char shadow){
	GLfloat x, y;
	int i = 0;
	Point n;
	for(i; i < 8; i++){
		//glColor3ub(colors[i * 3],colors[i * 3 + 1],colors[i * 3 + 2]);
		
		if (shadow == 1){
		n = norm(vertices[octaIndices[i*3 + 1]], vertices[octaIndices[i*3 + 2]], vertices[octaIndices[i*3]]);

		if(i % 2 == 0)
			glNormal3f(n.x, n.y, n.z);

		else
			glNormal3f(- n.x, - n.y, - n.z);
		}
		
		glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, &octaIndices[i*3]);

	}


}


void ani() {


	int i, j, k;
	GLfloat pos[2];		//x,y,z
	GLfloat dir[2];		//dx,dy,dz
	GLint rot;			//degrees



	for (i = 0; i < 9000000; i++) 
		;
	// printf ("%f	%f	%f
", moveX, moveY, moveZ);
	if (moveX > 3.0){
		delX = -delX;
		if(delY > 0)
			rotY = rotY + 15;
		else
			rotY = rotY - 15;
		if(delZ > 0)
			rotZ = rotZ + 15;
		else
			rotZ = rotZ - 15;
	}

	if (moveY > 3.0){
		delY = -delY;
		if(delX > 0)
			rotX = rotX + 15;
		else
			rotX = rotX - 15;
		if(delX > 0)
			rotX = rotX + 15;
		else
			rotX = rotX - 15;
	}

	if (moveZ > 3.0){
		delZ = -delZ;
		if(delY > 0)
			rotY = rotY + 15;
		else
			rotY = rotY - 15;
		if(delX > 0)
			rotX = rotX + 15;
		else
			rotX = rotX - 15;
	}
	if (moveX < -3.0){
		delX = -delX;
		if(delY > 0)
			rotY = rotY + 15;
		else
			rotY = rotY - 15;
		if(delZ > 0)
			rotZ = rotZ + 15;
		else
			rotZ = rotZ - 15;
	}

	if (moveY < -3.0){
		delY = -delY;
		if(delX > 0)
			rotX = rotX + 15;
		else
			rotX = rotX - 15;
		if(delZ > 0)
			rotZ = rotZ + 15;
		else
			rotZ = rotZ - 15;
	}

	if (moveZ < -3.0){
		delZ = -delZ;
		if(delY > 0)
			rotY = rotY + 15;
		else
			rotY = rotY - 15;
		if(delX > 0)
			rotX = rotX + 15;
		else
			rotX = rotX - 15;
	}

	moveX += delX;
	moveY += delY;
	moveZ += delZ;


	glutPostRedisplay ( );
} 



/**********************************************************/
/* Material */
/**********************************************************/

Material WhatIsBrass(void)
     /* brass material */
{
  Material thisIsIt =
    {{0.33, 0.22, 0.03, 1.0},
     {0.78, 0.57, 0.11, 1.0},
     {0.99, 0.91, 0.81, 1.0},
     27.8};

  return thisIsIt;
}

Material WhatIsWhiteShiny(void)
{
  Material thisIsIt =
    {{1.0, 1.0, 1.0, 1.0},
     {1.0, 1.0, 1.0, 1.0},
     {1.0, 1.0, 1.0, 1.0},
     100.0};

  return thisIsIt;
}

Material WhatIsRedPlastic(void)
{
  Material thisIsIt =
    {{0.3, 0.0, 0.0, 1.0},
     {0.6, 0.0, 0.0, 1.0},
     {0.8, 0.6, 0.6, 1.0},
     32.0};

  return thisIsIt;
}


void SetMaterial(Material m)
     /* sets the current material */
{
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, m.ambient);
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m.diffuse);
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m.specular);
  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, m.shiny);
}

void display() {
	

	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	
	//store view matrix
	glPushMatrix();
	glMatrixMode (GL_MODELVIEW);
	glLoadIdentity();
	
	//lights off
	glDisable(GL_LIGHT0);
	//apply rotation

	//black lines for the cube
	glColor3ub(0, 0, 0);
	
	//these two represent camera rotation
	glRotated(30, 1.0, 0.0, 0.0);
	glRotated(30, 0.0, 1.0, 0.0);
	glBegin(GL_LINE_STRIP);
		glVertex3f(-4,-4,-4);
		glVertex3f(-4,4,-4);
		glVertex3f(-4,4,4);
		glVertex3f(-4,-4,4);
		glVertex3f(-4,-4,-4);
		glVertex3f(4,-4,-4);
		glVertex3f(4,4,-4);
		glVertex3f(4,4,4);
		glVertex3f(4,-4,4);
		glVertex3f(4,-4,-4);
	glEnd();
	glBegin(GL_LINES);
		glVertex3f(-4, 4, -4);
		glVertex3f(4, 4, -4);
		glVertex3f(-4, 4, 4);
		glVertex3f(4, 4, 4);
		glVertex3f(-4, -4, 4);
		glVertex3f(4, -4, 4);
	glEnd();
	

	//these four transformations apply only to the octahedron
	glTranslatef (moveX, moveY, moveZ);
	glRotatef(rotX, 1.0, 0.0, 0.0);
	glRotatef(rotY, 0.0, 1.0, 0.0);
	glRotatef(rotZ, 0.0, 0.0, 1.0);



	//lights on
	glEnable(GL_LIGHT0);

	//glEnable(GL_LIGHT1);    but not this light

	SetMaterial(Brass);
	drawOcta(1);
	glLoadIdentity();
	
	
	glDisable(GL_LIGHT0);
	
	
	//once again, camera rotations
	glRotated(30, 1.0, 0.0, 0.0);
	glRotated(30, 0.0, 1.0, 0.0);
	
	//these five transformations apply only to the shadow of the octahedron
	//later, should have a function for each light, can modify the mult matrix per light fairly easily, or have them be
	//part of the struct, which we haven't done yet
	glTranslatef (moveX, 0, moveZ);
	//mult matrix: basically, draw the octahedron again, but flatten it against the floor to achieve the shadow
	//only works if the light is considered to be far above the scene
	glMultMatrixf(f);
	glRotatef(rotX, 1.0, 0.0, 0.0);
	glRotatef(rotY, 0.0, 1.0, 0.0);
	glRotatef(rotZ, 0.0, 0.0, 1.0);
	drawOcta(0);
	
	//recover viewing matrix
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	
	glFlush();
	glutSwapBuffers();


}

//left mouse toggles tracking bool
void mouse(int button, int state, int x, int y) {

	if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		tracking = true;

	}
	if(button == GLUT_LEFT_BUTTON && state == GLUT_UP) {

		tracking = false;
	}
	
}

//tracks mouse position while mouse button is being held
void mouseTrackActive(int x, int y) {
	

		if(tracking == true){

			rotation[0] = rotation[0] + .7*(x - xTrack);
			if (rotation[0] >= 360) rotation[0]-=360;
			rotation[1] = rotation[1] + .7*(y - yTrack);
			if (rotation[1] >= 360) rotation[1]-=360;
		}

		xTrack = x;
		yTrack = y;
		glutPostRedisplay();
	}

//tracks mouse position while mouse button not being held
//essential to remain consistent with active mouse function
void mouseTrackPassive(int x, int y){

		xTrack = x;
		yTrack = y;
		glutPostRedisplay();
}

int main(int argc, char **argv) {
	GLfloat lightPos1[] = {0.0, 10.0, 0.0, 0.0};

    /* yellow light */
    GLfloat diffuse1[] = {1.0, 1.0, 0.75, 1.0};
    GLfloat specular1[] = {0.8, 0.8, 0.4, 1.0};
    GLfloat ambient1[] = {0.35, 0.35, 0.35, 1.0};

	//another light
	GLfloat lightPos2[] = {0.0, 1.0, -1.0, 0.0};
    GLfloat diffuse2[] = {0.4, 0.4, 0.4, 1.0};
    GLfloat specular2[] = {0.0, 0.0, 0.0, 1.0};
    GLfloat ambient2[] = {0.05, 0.05, 0.05, 0};

    /* background light */
    GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };

	glutInit (&argc, argv);
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB| GLUT_DEPTH);
	glutInitWindowSize (ww, wh);
	glutInitWindowPosition (wcx, wcy);
	glutCreateWindow ("Octahedron");
	glutDisplayFunc(display);


	glMatrixMode (GL_PROJECTION);
	glViewport (0,0, ww, wh);
	glLoadIdentity ( );
	glOrtho (-12.0, 12.0, -12.0, 12.0, -12.0, 12.0);
	glFrustum(-10.0, 10.0, -10.0, 10.0, -10.0, 10.0);

	//glMatrixMode (GL_MODELVIEW);
	glutIdleFunc(ani);
	glutMotionFunc(mouseTrackActive);
	glutPassiveMotionFunc(mouseTrackPassive);
	glutMouseFunc(mouse);
	glEnable(GL_DEPTH_TEST);
	glEnableClientState(GL_VERTEX_ARRAY);

	//color handled mostly by materials + light
	//glEnableClientState(GL_COLOR_ARRAY);
	//glColorPointer(3,GL_UNSIGNED_BYTE, 0, &colors);
	glVertexPointer(3, GL_FLOAT, 0, &vertices);
	glShadeModel(GL_FLAT);
    glEnable(GL_LIGHTING);
    glEnable(GL_NORMALIZE);
    
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
    /* set a low background light such that objects in the scene
       can be seen at all */
    
	glClearColor (1.0, 1.0, 1.0, 1.0);	   /*white background */

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glLightfv(GL_LIGHT0, GL_POSITION, lightPos1);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse1);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specular1);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient1);
	glLightfv(GL_LIGHT1, GL_POSITION, lightPos2);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse2);
    glLightfv(GL_LIGHT1, GL_SPECULAR, specular2);
    glLightfv(GL_LIGHT1, GL_AMBIENT, ambient2);
	glutMainLoop();
}

Again, thanks for all your time and consideration guys.

Just to add, my personal thoughts are to just make menu functions for rotX, rotY, and rotZ. But would that be enough? And would I have to push and pop the matrix to do this effect or would it truly be that simple to do?