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.
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 − a3b2, a3b1 − a1b3, a1b2 − 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.