Hello, I am very fresh and new to OpenGL, and programming overall for the most part. I have had some assistance with classmates in this project I am doing, and I feel I have made some great headway, but there is something I am missing, or not seeing, or just forgetting about… that is making my idle animation function not work. Before I show you the code, I know I only have it set for the x and y and not z yet, but I figure I mine as well get those two going before I even need to delve into the z space. The idea behind the project was to make an octahedron in 3d space, and have it move around the box, adjusting angle as it came in contact with the boundaries. All with having materials and lighting around it. The materials and lighting are for the most part completed, but this animation has me in a snag. So please, tips, hints and helpful advice is greatly appreciated. Thanks.
octahedron.h
#include <GL/glut.h>
GLfloat pos[2]; //x,y
GLfloat dir[2]; //dx,dy
GLint rot; //degrees
/**********************************************************/
/* 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;
GLint wcx = 180, wcy = 180;
int xTrack, yTrack; //tracks mouse movement
int moveX, moveY; //possibly used later for animation
float rotSpeed[2]; //to be possibly used later for automatic rotation
bool tracking = false; //true when left mouse is held down
double rotation[2] = {0,0}; //keeps track of current rotation
GLfloat vertices[6][3] = {{0,1,0},
{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(void){
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]);
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() {
GLfloat x,y;
int i, j, k;
GLfloat pos[2]; //x,y,z
GLfloat dir[2]; //dx,dy,dz
GLint rot; //degrees
int neg;
pos[0] = (GLfloat) x - (ww/2 - orthoX/2);
pos[1] = (GLfloat) y - (wh/2 - orthoX/2);
//randomly set x direction (rand between -2.2 and 2.2, abs value >= .2)
if(rand()%2 == 1) neg = 1;
else neg = -1;
dir[0] = .2 * neg + (float)(rand() % 100) *.02 * neg;
//randomly set y direction (rand between -2.2 and 2.2, abs value >= .2)
if(rand()%2 == 1) neg = 1;
else neg = -1;
dir[1] = .2 * neg + (float)(rand() % 100) *.02 * neg;
rot = (GLint)(rand()%180);
//randomly set rotation if hits a boundary
for(k=0; k < 20; k++){
if (pos[0] + (ww/2 - orthoX/2) > ww/2 + 149) {
if(dir[0] > 0) dir[0] = - dir[0];
rot = (GLint)(rand()%180);
}
if (pos[0] + (ww/2 - orthoX/2) < ww/2 - 149) {
if(dir[0] < 0) dir[0] = - dir[0];
rot = (GLint)(rand()%180);
}
if (pos[1] + (wh/2 - orthoY/2) > wh/2 + 149) {
if(dir[1] > 0) dir[1] = - dir[1];
rot = (GLint)(rand()%180);
}
if (pos[1] + (wh/2 - orthoY/2) < wh/2 - 149) {
if(dir[1] < 0) dir[1] = - dir[1];
rot = (GLint)(rand()%180);
}
}
//displaceX += dirX * 5.0; displaceY += dirY * 3.0;
for (i = 0; i < 20000; i++)
for (j = 0; j < 200; j++) ;
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
glRotated(rotation[1], 1.0, 0.0, 0.0);
glRotated(rotation[0], 0.0, 1.0, 0.0);
//black lines
//use the commented out code below to make a box around the octahedron
glColor3ub(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();
//lights on
glEnable(GL_LIGHT0);
//glEnable(GL_LIGHT1); but not this light
SetMaterial(RedPlastic);
drawOcta();
//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.6, 0.6, 0.6, 1.0};
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 (-8.0, 8.0, -8.0, 8.0, -8.0, 8.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();
}