Firstly thanks for giving your time.This is one of question which has a lot of answers but it does not work, here I am trying to take an example and let's see if we can solve this and maybe someone will get benefited again in future.
So the problem is we have glreadpixel() calling on a point on a circle, which is drawn by bresenham function.
But the thing is its not even giving any value than 0,0,0 for RGB on changing the background colour of the window.
Here is the big code, enjoy experimenting. I have tried everything. By the way, I am developing n macOS (OpenGL is hardware independent )
using namespace std;
#include <GLUT/glut.h>
#include <iostream>
#include <vector>
#include <CoreGraphics/CoreGraphics.h>
int r = 40;
int flag = 0;
int cordinates [50][3]=
{
{50, 50} , //0 station
{400, 450} , //1 station
{750, 250} //2 station
};
int matrix[50][50] = {
{0,1,1},
{1,0,1},
{1,1,0}
};
int trains[50][50] = {
{3,4,0,1,999},
{11,1,1,2,999},
{0,0,0,999}
};
int x,y;
int *x1, *y3, x2, y2;
int xx,yy,xxx,yyy,p,q,vertexcount,counter;
int xinc,xinc3,i,j,system_time,flag1,time_chekcer_cnt,dda =0;
char buf3[12],buf[12];
float tempx0,tempy0,tempx1,tempy1;
int train0 = 999 ;int start0,speed0,next0,nextx0,nexty0,final0 = 999 ;//999 signifies invalid
int train1 ,start1, speed1,next1,nextx1,nexty1,final1 = 999 ;//999 signifies invalid
int train2 ,start2, speed2,next2,final2 = 999 ;//999 signifies invalid
void init2D()
{
glClearColor(0,0,0,0.0);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (0.0, 900.0, 0.0, 900.0);
}
;
void bresenham_circle(const int h, const int k,const int r)
{
int x=0,y=r,p=(3-(2*r));
do{
//Read pixel
unsigned char pixelub[3];
// glReadPixels(<#GLint x#>, <#GLint y#>, <#GLsizei width#>, <#GLsizei height#>, <#GLenum format#>, <#GLenum type#>, <#GLvoid *pixels#>)
glPointSize(1);
//draw two points
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
glVertex2i((h+x),(k+y));
glEnd();
//color detection start
glReadPixels
(
(h+x),(k+y),
1, 1,
GLUT_RGB, GL_UNSIGNED_BYTE, &pixelub
);
//print
cout <<"reading pixel : "<<(h+x)<<" "<<(k+y);
printf("r: %u g: %u b: %u\n", pixelub[0], pixelub[1], pixelub[2]);
cout << endl;
//end
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
glVertex2i((h+y),(k+x));
glEnd();
glBegin(GL_POINTS);
glVertex2i((h+y),(k-x));
glEnd();
glBegin(GL_POINTS);
glVertex2i((h+x),(k-y));
glEnd();
glBegin(GL_POINTS);
glVertex2i((h-x),(k-y));
glEnd();
glBegin(GL_POINTS);
glVertex2i((h-y),(k-x));
glEnd();
glBegin(GL_POINTS);
glVertex2i((h-y),(k+x));
glEnd();
glBegin(GL_POINTS);
glVertex2i((h-x),(k+y));
glEnd();
x++;
if(p<0){
p+= ((4*x)+6);
}else {
y--;
p+=(4*(x-y)+10);
}
}
while (x<=y);
}
void drawBitmapText(char *string,float x,float y,float z)
{
char *c;
glRasterPos3f(x, y,z);
for (c=string; *c != NULL; c++)
{
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *c);
}
}
void systemtime(){
sprintf(buf, "%d", system_time); // puts string into buffer
printf("%s\n", buf);
sprintf(buf3, "%d", system_time-1); // puts string into buffer
if(system_time >1){
glColor3f(1.0, 1.0, 1.0);
drawBitmapText(buf3,200,200,0);
glColor3f(0.0, 1.0, 0.0);
drawBitmapText(buf,200,200,0);
system_time =system_time+1;
}else {
drawBitmapText(buf,200,200,0);
system_time =system_time+1;
}
};
void draw_pixel(int x, int y){
glPointSize(5);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
cout << "\n THIS IS PRINTING X and Y :"<<x<<" & "<<y<<endl;
glVertex2i(x, y);
glEnd();
glFlush();
}
//bresenham ..... i vant DDA
void draw_dda( float *x0, float *y0, int x1, int y1,int speed) {
//cout << "\n LOOPING FOR START CORDIANTES : X0 and Y0 "<<*x0<<*y0<<endl;
int dx = x1 - *x0;
int dy = y1 - *y0;
//GLfloat x1 = p1.x; GLfloat y1 = p1.y;
GLfloat step = 0;
if(abs(dx) > abs(dy)) {
step = abs(dx);
} else {
step = abs(dy);
}
GLfloat xInc = dx/step;
GLfloat yInc = dy/step;
for (int speed_count = 0 ; speed_count < speed ; speed_count++){
glPointSize(5);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
//cout << "\n THIS IS PRINTING X and Y :"<<xInc<<" & "<<yInc<<endl;
glVertex2i(*x0, *y0);
glEnd();
int cy1 = *y0;
int cx1 = *x0;
//cout << "\n calling bresenham";
glColor3f(1.0, 1.0, 1.0);
bresenham_circle(cx1, cy1, r);
//cout << " \n" <<cx1<<" "<<cy1<<" "<<r;
while (flag != 1){
r--;
//cout <<"\n r is "<<r<<endl;
if (r == 0){
flag = 1;
}
}
r =40;flag= 0;
*x0 = *x0+xInc;
*y0 = *y0+yInc;
glColor3f(1.0, 0.0, 0.0);
int cy = *y0;
int cx = *x0;
//cout << "\n calling bresenham";
bresenham_circle(cx, cy, r);
//cout << " \n" <<cx<<" "<<cy<<" "<<r;
while (flag != 1){
r--;
//cout <<"\n r is "<<r<<endl;
if (r == 0){
flag = 1;
}
}
r =40;flag= 0;
//cout << "\n THIS IS PRINTING X and Y :"<<xInc<<" & "<<yInc<<endl;
}
}
void drawline(float *x0, float *y0, int x1, int y1)
{ cout << "\n LOOPING FOR START CORDIANTES : ("<<*x0<<","<<*y0<<") To ("<<x1<<","<<y1<<")"<<endl;
int dx, dy, p, x, y;
dx=x1-*x0;
dy=y1-*y0;
x=*x0;
y=*y0;
p=2*dy-dx;
//cout << "X and X1 "<<x<<x1<<endl;
if (x<x1)
{
if(p>=0)
{
draw_pixel(x,y);
//cout << ">>>>>. Y INCREMENTED >>>>> "<<y<<endl;
y=y+1;
p=p+2*dy-2*dx;
}
else
{ //cout << "\n >>>>>NOT Y INCREMENTED >>>>> "<<y<<endl;
draw_pixel(x,y);
//cout << "X and Y "<<x<<y<<endl;
p=p+2*dy;
}
x=x+1;
}
*x0=x;
*y0=y;
//cout << "\n X "<<x<<" and Y "<<y<<endl;
//cout << "\n X0 "<<*x0<<" and Y0 "<<*y0<<endl;
}
void display_ndots()
{glClear(GL_COLOR_BUFFER_BIT);
glPointSize(5);
glColor3f(1.0, 0.0, 0.0);
//draw two points
glBegin(GL_POINTS);
for(int i = 0; i < 10; i++)
{ xx = cordinates[i][0];
yy = cordinates[i][1];
glVertex2i(xx,yy);
//printf("%i",xx);
}
glEnd();
glColor3f(0.0, 1.0, 0.0);
//draw a line
glLineWidth(3);
glBegin(GL_LINES);
for(counter = 0 ; counter < 3 ; counter ++){
for (p = 0 ; p < 3 ; p ++){
for (q = 0 ; q < 3 ; q ++){
if( matrix[p][q] == 1){
xx = cordinates[p][0];
yy = cordinates[p][1];
xxx = cordinates[q][0];
yyy = cordinates[q][1];
glVertex2i(xx,yy);
glVertex2i(xxx,yyy);
}
}
}
}
glEnd();
systemtime();
time_chekcer_cnt = 0;
for(time_chekcer_cnt = 0 ; time_chekcer_cnt <10 ; time_chekcer_cnt ++){
if (system_time == trains[time_chekcer_cnt][0]){
switch (time_chekcer_cnt)
{
case 0: printf("Trian number %i have been started server time is %i \n",time_chekcer_cnt,system_time);
/*Initializing Train Data*/
train0 = time_chekcer_cnt;
speed0 = trains[time_chekcer_cnt][1];
start0 = trains[time_chekcer_cnt][2];
cout<<"\n >>>>>>>>>>>>>"<<start0<<endl;
tempx0 = cordinates[start0][0];
tempy0 = cordinates[start0][1];
next0 = trains[time_chekcer_cnt][3];
nextx0 = cordinates[next0][0];
nexty0 = cordinates[next0][1];
;
i=0;
while (trains[time_chekcer_cnt][i] != 999) {
i = i+1;
}
final0 = trains[time_chekcer_cnt][i-1];//999 signifies invalid
printf("\nfinal station is %i \n",final0);
//tempx01 = cordinates[start0][0]+10;
//tempy01 = cordinates[start0][1];
break;
case 1:
printf("Trian number %i have been started server time is %i \n",time_chekcer_cnt,system_time);
/*Initializing Train Data*/
train1 = time_chekcer_cnt;
speed1 = trains[time_chekcer_cnt][1];
start1 = trains[time_chekcer_cnt][2];
cout<<"\n >>>>>>>>>>>>>"<<start0<<endl;
tempx1 = cordinates[start0][0];
tempy1 = cordinates[start0][1];
next1 = trains[time_chekcer_cnt][3];
nextx1 = cordinates[next0][0];
nexty1 = cordinates[next0][1];
;
i=0;
while (trains[time_chekcer_cnt][i] != 999) {
i = i+1;
}
final1 = trains[time_chekcer_cnt][i-1];//999 signifies invalid
printf("\nfinal station is %i \n",final0);
break;
//default: // code to be executed if n doesn't match any cases
}
}
}
if (train0 != 999){
glColor3f(1.0, 1.0, 0.0);
draw_dda( &tempx0, &tempy0 ,nextx0, nexty0,speed0);
cout << "Draving from corinates ("<<tempx0<<","<<tempy0<<") To ("<<nextx0<<","<<nexty0<<")"<<endl;
}
if (train1 != 999){
glColor3f(1.0, 1.0, 0.0);
/// cout << "original x and y are "<<nextx0<<" & "<<nexty0;
draw_dda( &tempx1, &tempy1 ,nextx1, nexty1,speed1);
cout << "Draving from corinates ("<<tempx0<<","<<tempy0<<") To ("<<nextx0<<","<<nexty0<<")"<<endl;
// drawline( &tempx0, &tempy0 ,nextx0, nexty0);
//draw_dda( &tempx01, &tempy01 ,nextx0+10, nexty0);
// cout<<"After call by reference it is :"<<nextx0<<" & "<<nexty0;
}
/*bresenham_circle(100, 100, r);
while (flag != 1){
r--;
cout <<"\n r is "<<r<<endl;
if (r == 0){
flag = 1;
}
}*/
glFlush();
glGetError();
}
void timlycall (int unused) {
glutPostRedisplay();
glutTimerFunc(1000, timlycall, 0);
}
int main(int argc,char *argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (900, 900);
glutInitWindowPosition (0, 0);
glutCreateWindow ("points and lines");
init2D();
glutDisplayFunc(display_ndots);
//glutDisplayFunc(init2D);
glutTimerFunc(0, timlycall, 0);
glutMainLoop();
return 0;
}
Please not macos have library GLUT but windows have GL
Update 1.0
OK folks we have made some progress :
Using GLUT_RGB in glreadpixel() gives error code 1280 i.e. detected
by method BDL have provided. Which stands for incorrect enumeration ,
so use GL_RGB inside glreadpixel()
Now one more interesting thing we have to tackle, i.e now GlReadPixel
is giving r:255 g: 255 b: 255 as output , i.e background color
instead of color that must be yellow , because we are calling the
function on point which lies on the circle that too after its
painted.
You are passing a wrong enumeration to glReadPixels. GLUT_RGB is not the same as GL_RGB and may thus not be used for this function.
This would have been reported as a GL_INVALID_ENUM error by glGetError(), but the error code is never checked. You should use something like:
GLenum error = glGetError();
if (error != GL_NO_ERROR)
std::cout << "OpenGL error: " << error << std::endl;
Related
In this code, I'm trying to shade a surface properly based on the position of a light which can be moved. So when you move the light, the surface updates. In addition, I'm looking to have two lights of different colors both shading the same surface. Unfortunately, the surface color remains static.
What I'd like:
1) Have the surface update when the light is moved, and a vector that will use both colors(I'm not 100% on how to do this).
2) Have the lights and normals remain a static color regardless of shading/light.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#ifdef MAC
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
//Camera variables
int xangle = -270;
int yangle = 0;
//Control Modes (Rotate mode by default)
int mode = 0;
int lightmode = 0;
//Player Position (Y offset so it would not be straddling the grid)
float cubeX = 0;
float cubeY = 0.5;
float cubeZ = 0;
//Vertex arrays for surface
float surfaceX [12][12];
float surfaceY [12][12];
float surfaceZ [12][12];
//Surface Normal arrays
float Nx[11][11];
float Ny[11][11];
float Nz[11][11];
//Color arrays
float R[11][11];
float G[11][11];
float B[11][11];
//Material properties
float Ka = 0.2;
float Kd = 0.4;
float Ks = 0.4;
float Kp = 0.5;
//Light position and color variables
float Light1x = 0;
float Light1y = 5;
float Light1z = 0;
float Light1r = 1;
float Light1g = 0;
float Light1b = 0;
float Light2x = -5;
float Light2y = 5;
float Light2z = -5;
float Light2r = 0;
float Light2g = 1;
float Light2b = 0;
//Random number generator
float RandomNumber(float Min, float Max)
{
return ((float(rand()) / float(RAND_MAX)) * (Max - Min)) + Min;
}
//---------------------------------------
// Initialize material properties
//---------------------------------------
void init_material(float Ka, float Kd, float Ks, float Kp,
float Mr, float Mg, float Mb)
{
// Material variables
float ambient[] = { Ka * Mr, Ka * Mg, Ka * Mb, 1.0 };
float diffuse[] = { Kd * Mr, Kd * Mg, Kd * Mb, 1.0 };
float specular[] = { Ks * Mr, Ks * Mg, Ks * Mb, 1.0 };
// Initialize material
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, Kp);
}
//---------------------------------------
// Initialize light source
//---------------------------------------
void init_light(int light_source, float Lx, float Ly, float Lz,
float Lr, float Lg, float Lb)
{
// Light variables
float light_position[] = { Lx, Ly, Lz, 0.0 };
float light_color[] = { Lr, Lg, Lb, 1.0 };
// Initialize light source
glEnable(GL_LIGHTING);
glEnable(light_source);
glLightfv(light_source, GL_POSITION, light_position);
glLightfv(light_source, GL_AMBIENT, light_color);
glLightfv(light_source, GL_DIFFUSE, light_color);
glLightfv(light_source, GL_SPECULAR, light_color);
glLightf(light_source, GL_CONSTANT_ATTENUATION, 1.0);
glLightf(light_source, GL_LINEAR_ATTENUATION, 0.0);
glLightf(light_source, GL_QUADRATIC_ATTENUATION, 0.0);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
}
//---------------------------------------
// Initialize surface
//---------------------------------------
void init_surface()
{
//Initialize X, select column
for (int i = 0; i < 12; i++)
{
//Select row
//Surface is +1 so the far right normal will be generated correctly
for (int j = 0; j < 12; j++)
{
//-5 to compensate for negative coordinate values
surfaceX[i][j] = i-5;
//Generate random surface height
surfaceY[i][j] = RandomNumber(5, 7) - 5;
//surfaceY[i][j] = 0;
surfaceZ[i][j] = j-5;
}
}
}
void define_normals()
{
//Define surface normals
for (int i = 0; i < 11; i++)
{
for (int j = 0; j < 11; j++)
{
//Get two tangent vectors
float Ix = surfaceX[i+1][j] - surfaceX[i][j];
float Iy = surfaceY[i+1][j] - surfaceY[i][j];
float Iz = surfaceZ[i+1][j] - surfaceZ[i][j];
float Jx = surfaceX[i][j+1] - surfaceX[i][j];
float Jy = surfaceY[i][j+1] - surfaceY[i][j];
float Jz = surfaceZ[i][j+1] - surfaceZ[i][j];
//Do cross product, inverted for upward normals
Nx[i][j] = - Iy * Jz + Iz * Jy;
Ny[i][j] = - Iz * Jx + Ix * Jz;
Nz[i][j] = - Ix * Jy + Iy * Jx;
//Original vectors
//Nx[i][j] = Iy * Jz - Iz * Jy;
//Ny[i][j] = Iz * Jx - Ix * Jz;
//Nz[i][j] = Ix * Jy - Iy * Jx;
float length = sqrt(
Nx[i][j] * Nx[i][j] +
Ny[i][j] * Ny[i][j] +
Nz[i][j] * Nz[i][j]);
if (length > 0)
{
Nx[i][j] /= length;
Ny[j][j] /= length;
Nz[i][j] /= length;
}
}
}
}
void calc_color()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
//Calculate light vector
//Light position, hardcoded for now 0,1,1
float Lx = Light1x - surfaceX[i][j];
float Ly = Light1y - surfaceY[i][j];
float Lz = Light1z - surfaceZ[i][j];
//std::cout << "Lx: " << Lx << std::endl;
//std::cout << "Ly: " << Ly << std::endl;
//std::cout << "Lz: " << Lz << std::endl;
//Grab surface normals
//These are Nx,Ny,Nz due to compiler issues
float Na = Nx[i][j];
float Nb = Ny[i][j];
float Nc = Nz[i][j];
//std::cout << "Na: " << Na << std::endl;
//std::cout << "Nb: " << Nb << std::endl;
//std::cout << "Nc: " << Nc << std::endl;
//Do cross product
float Color = (Na * Lx) + (Nb * Ly) + (Nc * Lz);
//std::cout << "Color: " << Color << std::endl;
R[i][j] = Color;
G[i][j] = Color;
B[i][j] = Color;
}
}
}
//---------------------------------------
// Init function for OpenGL
//---------------------------------------
void init()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//Viewing Window Modified
glOrtho(-7.0, 7.0, -7.0, 7.0, -7.0, 7.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Rotates camera
//glRotatef(30.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
//Project 3 code
init_surface();
define_normals();
//Shading code
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
//X,Y,Z - R,G,B
init_light(GL_LIGHT1, Light1x, Light1y, Light1z, Light1r, Light1g, Light1b);
//init_light(GL_LIGHT2, Light2x, Light2y, Light2z, Light2r, Light2g, Light2b);
//init_light(GL_LIGHT2, 0, 1, 0, 0.5, 0.5, 0.5);
}
void keyboard(unsigned char key, int x, int y)
{
///TODO: allow user to change color of light
//Controls
//Toggle Mode
if (key == 'q')
{
if(mode == 0)
{
mode = 1;
std::cout << "Switched to Light mode (" << mode << ")" << std::endl;
}
else if(mode == 1)
{
mode = 0;
std::cout << "Switched to Rotate mode (" << mode << ")" << std::endl;
}
}
//Toggle light control
else if (key == 'e')
{
if(lightmode == 0)
{
lightmode = 1;
std::cout << "Switched to controlling light 2 (" << lightmode << ")" << std::endl;
}
else if(lightmode == 1)
{
lightmode = 0;
std::cout << "Switched to controlling light 1 (" << lightmode << ")" << std::endl;
}
}
////Rotate Camera (mode 0)
//Up & Down
else if (key == 's' && mode == 0)
xangle += 5;
else if (key == 'w' && mode == 0)
xangle -= 5;
//Left & Right
else if (key == 'a' && mode == 0)
yangle -= 5;
else if (key == 'd' && mode == 0)
yangle += 5;
////Move Light (mode 1)
//Forward & Back
else if (key == 'w' && mode == 1)
{
if (lightmode == 0)
{
Light1z = Light1z - 1;
//init_surface();
//define_normals();
calc_color();
glutPostRedisplay();
}
else if (lightmode == 1)
Light2z = Light2z - 1;
//init_surface();
}
else if (key == 's' && mode == 1)
{
if (lightmode == 0)
Light1z = Light1z + 1;
else if (lightmode == 1)
Light2z = Light2z + 1;
}
//Strafe
else if (key == 'd' && mode == 1)
{
if (lightmode == 0)
Light1x = Light1x + 1;
else if (lightmode == 1)
Light2x = Light2x + 1;
}
else if (key == 'a' && mode == 1)
{
if (lightmode == 0)
Light1x = Light1x - 1;
else if (lightmode == 1)
Light2x = Light2x - 1;
}
//Up & Down (Cube offset by +0.5 in Y)
else if (key == 'z' && mode == 1)
{
if (lightmode == 0)
Light1y = Light1y + 1;
else if (lightmode == 1)
Light2y = Light2y + 1;
}
else if (key == 'x' && mode == 1)
{
if (lightmode == 0)
Light1y = Light1y - 1;
else if (lightmode == 1)
Light2y = Light2y - 1;
}
//Redraw objects
glutPostRedisplay();
}
//---------------------------------------
// Display callback for OpenGL
//---------------------------------------
void display()
{
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Rotation Code
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(xangle, 1.0, 0.0, 0.0);
glRotatef(yangle, 0.0, 1.0, 0.0);
//Light Code
init_material(Ka, Kd, Ks, 100 * Kp, 0.8, 0.6, 0.4);
//Color Code
calc_color();
//Draw the squares, select column
for (int i = 0; i <= 9; i++)
{
//Select row
for (int j = 0; j <= 9; j++)
{
glBegin(GL_POLYGON);
//Surface starts at top left
//Counter clockwise
glColor3f(R[i][j], G[i][j], B[i][j]);
glNormal3f(Nx[i][j], Ny[i][j], Nz[i][j]);
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glColor3f(R[i][j+1], G[i][j+1], B[i][j+1]);
glNormal3f(Nx[i][j+1], Ny[i][j+1], Nz[i][j+1]);
glVertex3f(surfaceX[i][j+1], surfaceY[i][j+1], surfaceZ[i][j+1]);
glColor3f(R[i+1][j+1], G[i+1][j+1], B[i+1][j+1]);
glNormal3f(Nx[i+1][j+1], Ny[i+1][j+1], Nz[i+1][j+1]);
glVertex3f(surfaceX[i+1][j+1], surfaceY[i+1][j+1], surfaceZ[i+1][j+1]);
glColor3f(R[i+1][j], G[i+1][j], B[i+1][j]);
glNormal3f(Nx[i+1][j], Ny[i+1][j], Nz[i+1][j]);
glVertex3f(surfaceX[i+1][j], surfaceY[i+1][j], surfaceZ[i+1][j]);
glEnd();
}
}
//Draw the normals
for (int i = 0; i <= 10; i++)
{
for (int j = 0; j <= 10; j++)
{
glBegin(GL_LINES);
//glColor3f(0.0, 1.0, 1.0);
float length = 1;
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glVertex3f(surfaceX[i][j]+length*Nx[i][j],
surfaceY[i][j]+length*Ny[i][j],
surfaceZ[i][j]+length*Nz[i][j]);
glEnd();
}
}
//Marking location of lights
glPointSize(10);
glBegin(GL_POINTS);
glColor3f(Light1r, Light1g, Light1b);
glVertex3f(Light1x, Light1y, Light1z);
glEnd();
glPointSize(10);
glBegin(GL_POINTS);
glColor3f(Light2r, Light2g, Light2b);
glVertex3f(Light2x, Light2y, Light2z);
glEnd();
//+Z = Moving TOWARD camera in opengl
//Origin point for reference
glPointSize(10);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
glVertex3f(0, 0, 0);
glEnd();
//Assign Color of Lines
float R = 1;
float G = 1;
float B = 1;
glBegin(GL_LINES);
glColor3f(R, G, B);
////Drawing the grid
//Vertical lines
for (int i = 0; i < 11; i++)
{
int b = -5 + i;
glVertex3f(b, 0, -5);
glVertex3f(b, 0, 5);
}
//Horizontal lines
for (int i = 0; i < 11; i++)
{
int b = -5 + i;
glVertex3f(-5,0,b);
glVertex3f(5,0,b);
}
glEnd();
glFlush();
}
//---------------------------------------
// Main program
//---------------------------------------
int main(int argc, char *argv[])
{
srand(time(NULL));
//Print Instructions
std::cout << "Project 3 Controls: " << std::endl;
std::cout << "q switches control mode" << std::endl;
std::cout << "w,a,s,d for camera rotation" << std::endl;
//Required
glutInit(&argc, argv);
//Window will default to a different size without
glutInitWindowSize(500, 500);
//Window will default to a different position without
glutInitWindowPosition(250, 250);
//
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
//Required
glutCreateWindow("Project 3");
//Required, calls display function
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
//Required
init();
glutMainLoop();
return 0;
}
1) Have the surface update when the light is moved
You missed to update the position of the light, when the light was moved. Set the light position at the begin of the function display.
Note, when the light position is set by glLightfv(GL_LIGHT0, GL_POSITION, pos), then
pos is multiplied by the current model view matrix.
So the light has to be set after the model view matrix was "cleared" by glLoadIdentity:
void display()
{
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Rotation Code
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// init light
init_light(GL_LIGHT1, Light1x, Light1y, Light1z, Light1r, Light1g, Light1b);
init_light(GL_LIGHT2, Light2x, Light2y, Light2z, Light2r, Light2g, Light2b);
glRotatef(xangle, 1.0, 0.0, 0.0);
glRotatef(yangle, 0.0, 1.0, 0.0);
// [...]
}
2) Have the lights and normals remain a static color regardless of shading/light.
Enable lighting before drawing the surface, but disable lighting before drawing the lines and points:
void display()
{
// [...]
// switch on lighting
glEnable(GL_LIGHTING);
//Draw the squares, select column
for (int i = 0; i <= 9; i++)
{
// [...]
}
// switch off lighting
glDisable(GL_LIGHTING);
//Draw the normals
for (int i = 0; i <= 10; i++)
{
// [...]
}
// [...]
}
The purpose of this code is to generate a 'surface' with random Y variation, and then have a light source shine on it and generate areas of brightness and perform shading on darker areas. The problem is, this isn't really happening. The light either illuminates one side or the other, and those sides are all uniformly bright or dark. What am I missing with this? Keep in mind there is a good bit of code that has yet to be removed, but it is not my priority, I'm just trying to get shading functional at this point.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#ifdef MAC
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
//Camera variables
int xangle = -270;
int yangle = 0;
//Control Mode (Rotate mode by default)
int mode = 0;
//Player Position (Y offset so it would not be straddling the grid)
float cubeX = 0;
float cubeY = 0.5;
float cubeZ = 0;
//Vertex arrays for surface
float surfaceX [11][11];
float surfaceY [11][11];
float surfaceZ [11][11];
//Surface Normal arrays
float Nx[11][11];
float Ny[11][11];
float Nz[11][11];
//Color arrays
float R[11][11];
float G[11][11];
float B[11][11];
// Material properties
float Ka = 0.2;
float Kd = 0.4;
float Ks = 0.4;
float Kp = 0.5;
//Random number generator
float RandomNumber(float Min, float Max)
{
return ((float(rand()) / float(RAND_MAX)) * (Max - Min)) + Min;
}
//---------------------------------------
// Initialize material properties
//---------------------------------------
void init_material(float Ka, float Kd, float Ks, float Kp,
float Mr, float Mg, float Mb)
{
// Material variables
float ambient[] = { Ka * Mr, Ka * Mg, Ka * Mb, 1.0 };
float diffuse[] = { Kd * Mr, Kd * Mg, Kd * Mb, 1.0 };
float specular[] = { Ks * Mr, Ks * Mg, Ks * Mb, 1.0 };
// Initialize material
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, Kp);
}
//---------------------------------------
// Initialize light source
//---------------------------------------
void init_light(int light_source, float Lx, float Ly, float Lz,
float Lr, float Lg, float Lb)
{
// Light variables
float light_position[] = { Lx, Ly, Lz, 0.0 };
float light_color[] = { Lr, Lg, Lb, 1.0 };
// Initialize light source
glEnable(GL_LIGHTING);
glEnable(light_source);
glLightfv(light_source, GL_POSITION, light_position);
glLightfv(light_source, GL_AMBIENT, light_color);
glLightfv(light_source, GL_DIFFUSE, light_color);
glLightfv(light_source, GL_SPECULAR, light_color);
glLightf(light_source, GL_CONSTANT_ATTENUATION, 1.0);
glLightf(light_source, GL_LINEAR_ATTENUATION, 0.0);
glLightf(light_source, GL_QUADRATIC_ATTENUATION, 0.0);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
}
//---------------------------------------
// Initialize surface
//---------------------------------------
void init_surface()
{
//Initialize X, select column
for (int i = 0; i < 11; i++)
{
//Select row
for (int j = 0; j < 11; j++)
{
surfaceX[i][j] = i-5;
surfaceY[i][j] = RandomNumber(5, 7) - 5;
surfaceZ[i][j] = j-5;
//std::cout << "Coordinate "<< i << "," << j << std::endl;
}
//std::cout << "Hello world "<< std::endl;
}
//std::cout << "Coordinate -5,-5" << surfaceX[-5][-5] << std::endl;
}
void define_normals()
{
//Define surface normals
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
//Get two tangent vectors
float Ix = surfaceX[i+1][j] - surfaceX[i][j];
float Iy = surfaceY[i+1][j] - surfaceY[i][j];
float Iz = surfaceZ[i+1][j] - surfaceZ[i][j];
float Jx = surfaceX[i][j+1] - surfaceX[i][j];
float Jy = surfaceY[i][j+1] - surfaceY[i][j];
float Jz = surfaceZ[i][j+1] - surfaceZ[i][j];
//Get two tangent vectors
//float Ix = Px[i+1][j] - Px[i][j];
//float Iy = Py[i+1][j] - Py[i][j];
//float Iz = Pz[i+1][j] - Pz[i][j];
//float Jx = Px[i][j+1] - Px[i][j];
//float Jy = Py[i][j+1] - Py[i][j];
//float Jz = Pz[i][j+1] - Pz[i][j];
//Do cross product
Nx[i][j] = Iy * Jz - Iz * Jy;
Ny[i][j] = Iz * Jx - Ix * Jz;
Nz[i][j] = Ix * Jy - Iy * Jx;
//Nx[i][j] = Nx[i][j] * -1;
//Ny[i][j] = Ny[i][j] * -1;
//Nz[i][j] = Nz[i][j] * -1;
float length = sqrt(
Nx[i][j] * Nx[i][j] +
Ny[i][j] * Ny[i][j] +
Nz[i][j] * Nz[i][j]);
if (length > 0)
{
Nx[i][j] /= length;
Ny[j][j] /= length;
Nz[i][j] /= length;
}
}
}
//std::cout << "Surface normal for 0,0: "<< Nx[0][0] << "," << Ny[0][0] << "," << Nz[0][0] << std::endl;
}
void calc_color()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
//Calculate light vector
//Light position, hardcoded for now 0,1,1
float Lx = -1 - surfaceX[i][j];
float Ly = -1 - surfaceY[i][j];
float Lz = -1 - surfaceZ[i][j];
std::cout << "Lx: " << Lx << std::endl;
std::cout << "Ly: " << Ly << std::endl;
std::cout << "Lz: " << Lz << std::endl;
//Grab surface normals
//These are Nx,Ny,Nz due to compiler issues
float Na = Nx[i][j];
float Nb = Ny[i][j];
float Nc = Nz[i][j];
std::cout << "Na: " << Na << std::endl;
std::cout << "Nb: " << Nb << std::endl;
std::cout << "Nc: " << Nc << std::endl;
//Do cross product
float Color = (Na * Lx) + (Nb * Ly) + (Nc * Lz);
std::cout << "Color: " << Color << std::endl;
//Color = Color * -1;
R[i][j] = Color;
G[i][j] = Color;
B[i][j] = Color;
//std::cout << "Color Value: " << std::endl;
////std::cout << "R: " << R[i][j] << std::endl;
//std::cout << "G: " << G[i][j] << std::endl;
//std::cout << "B: " << B[i][j] << std::endl;
}
}
}
//---------------------------------------
// Init function for OpenGL
//---------------------------------------
void init()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//Viewing Window Modified
glOrtho(-7.0, 7.0, -7.0, 7.0, -7.0, 7.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Rotates camera
//glRotatef(30.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
//Project 3 code
init_surface();
define_normals();
//Shading code
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
init_light(GL_LIGHT0, 0, 1, 1, 0.5, 0.5, 0.5);
//init_light(GL_LIGHT1, 0, 0, 1, 0.5, 0.5, 0.5);
//init_light(GL_LIGHT2, 0, 1, 0, 0.5, 0.5, 0.5);
}
void keyboard(unsigned char key, int x, int y)
{
//Controls
//Toggle Mode
if (key == 'q')
{
if(mode == 0)
{
mode = 1;
std::cout << "Switched to Move mode (" << mode << ")" << std::endl;
}
else if(mode == 1)
{
mode = 0;
std::cout << "Switched to Rotate mode (" << mode << ")" << std::endl;
}
}
////Rotate Camera (mode 0)
//Up & Down
else if (key == 's' && mode == 0)
xangle += 5;
else if (key == 'w' && mode == 0)
xangle -= 5;
//Left & Right
else if (key == 'a' && mode == 0)
yangle -= 5;
else if (key == 'd' && mode == 0)
yangle += 5;
////Move Cube (mode 1)
//Forward & Back
else if (key == 'w' && mode == 1)
{
if (cubeZ > -5)
cubeZ = cubeZ - 1;
else
std::cout << "You have struck an invisible wall! (Min Z bounds)" << std::endl;
}
else if (key == 's' && mode == 1)
{
if (cubeZ < 5)
cubeZ = cubeZ + 1;
else
std::cout << "You have struck an invisible wall! (Max Z bounds)" << std::endl;
}
//Strafe
else if (key == 'd' && mode == 1)
{
if (cubeX < 5)
cubeX = cubeX + 1;
else
std::cout << "You have struck an invisible wall! (Max X bounds)" << std::endl;
}
else if (key == 'a' && mode == 1)
{
if (cubeX > -5)
cubeX = cubeX - 1;
else
std::cout << "You have struck an invisible wall! (Min X bounds)" << std::endl;
}
//Up & Down (Cube offset by +0.5 in Y)
else if (key == 'z' && mode == 1)
{
if (cubeY < 5)
cubeY = cubeY + 1;
else
std::cout << "You've gone too high! Come back! (Max Y bounds)" << std::endl;
}
else if (key == 'x' && mode == 1)
{
if (cubeY > 0.5)
cubeY = cubeY - 1;
else
std::cout << "You've reached bedrock! (Min Y bounds)" << std::endl;
}
//Place/Remove block
else if (key == 'e' && mode == 1)
{
//Occupied(cubeX,cubeY,cubeZ);
}
//Redraw objects
glutPostRedisplay();
}
//---------------------------------------
// Display callback for OpenGL
//---------------------------------------
void display()
{
// Clear the screen
//std::cout << "xangle: " << xangle << std::endl;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Rotation Code
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(xangle, 1.0, 0.0, 0.0);
glRotatef(yangle, 0.0, 1.0, 0.0);
//Light Code
init_material(Ka, Kd, Ks, 100 * Kp, 0.8, 0.6, 0.4);
calc_color();
//Draw the squares, select column
for (int i = 0; i <= 9; i++)
{
//Select row
for (int j = 0; j <= 9; j++)
{
glBegin(GL_POLYGON);
//Surface starts at top left
//Counter clockwise
// CALCULATE COLOR HERE
// - calculate direction from surface to light
// - calculate dot product of normal and light direction vector
// - call glColor function
//Calculate light vector
//Light position, hardcoded for now 0,1,1
///float Lx = 0 - surfaceX[i][j];
//float Ly = 1 - surfaceY[i][j];
//float Lz = 1 - surfaceZ[i][j];
//Grab surface normals
//These are Nx,Ny,Nz due to compiler issues
//float Na = Nx[i][j];
//float Nb = Ny[i][j];
//float Nc = Nz[i][j];
//Do cross product
//float Color = (Na * Lx) + (Nb * Ly) + (Nc * Lz);
//???
//glColor3fv(Color);
//glColor3f(0.5*Color,0.5*Color,0.5*Color);
glColor3f(R[i][j], G[i][j], B[i][j]);
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glColor3f(R[i][j+1], G[i][j+1], B[i][j+1]);
glVertex3f(surfaceX[i][j+1], surfaceY[i][j+1], surfaceZ[i][j+1]);
glColor3f(R[i+1][j+1], G[i+1][j+1], B[i+1][j+1]);
glVertex3f(surfaceX[i+1][j+1], surfaceY[i+1][j+1], surfaceZ[i+1][j+1]);
glColor3f(R[i+1][j], G[i+1][j], B[i+1][j]);
glVertex3f(surfaceX[i+1][j], surfaceY[i+1][j], surfaceZ[i+1][j]);
glEnd();
}
}
//Draw the normals
for (int i = 0; i <= 10; i++)
{
for (int j = 0; j <= 10; j++)
{
glBegin(GL_LINES);
//glColor3f(0.0, 1.0, 1.0);
float length = 1;
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glVertex3f(surfaceX[i][j]+length*Nx[i][j],
surfaceY[i][j]+length*Ny[i][j],
surfaceZ[i][j]+length*Nz[i][j]);
glEnd();
}
}
glEnd();
glFlush();
//Player Cube
//Cube: midx, midy, midz, size
//+Z = Moving TOWARD camera in opengl
//Origin point for reference
glPointSize(10);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
glVertex3f(0, 0, 0);
glEnd();
//Assign Color of Lines
float R = 1;
float G = 1;
float B = 1;
glBegin(GL_LINES);
glColor3f(R, G, B);
////Drawing the grid
//Vertical lines
for (int i = 0; i < 11; i++)
{
int b = -5 + i;
glVertex3f(b, 0, -5);
glVertex3f(b, 0, 5);
}
//Horizontal lines
for (int i = 0; i < 11; i++)
{
int b = -5 + i;
glVertex3f(-5,0,b);
glVertex3f(5,0,b);
}
glEnd();
glEnd();
glFlush();
}
//---------------------------------------
// Main program
//---------------------------------------
int main(int argc, char *argv[])
{
srand(time(NULL));
//Print Instructions
std::cout << "Project 3 Controls: " << std::endl;
std::cout << "q switches control mode" << std::endl;
std::cout << "w,a,s,d for camera rotation" << std::endl;
//Required
glutInit(&argc, argv);
//Window will default to a different size without
glutInitWindowSize(500, 500);
//Window will default to a different position without
glutInitWindowPosition(250, 250);
//
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
//Required
glutCreateWindow("Project 3");
//Required, calls display function
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
//Required
init();
glutMainLoop();
return 0;
}
Both the surface and normals are being generated as well as the color for the given vertex, I'm just not understanding why it isn't working.
The light or brightness of the surface is a function of the incident light vector the view direction and the normal vector of the surface.
You missed to set the normal vector attributes when you render the plane. Set the normal vector attribute by glNormal, before the vertex coordinate is specified:
for (int i = 0; i <= 9; i++)
{
for (int j = 0; j <= 9; j++)
{
glBegin(GL_POLYGON);
glColor3f(R[i][j], G[i][j], B[i][j]);
glNormal3f(Nx[i][j], Ny[i][j], Nz[i][j]);
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glColor3f(R[i][j+1], G[i][j+1], B[i][j+1]);
glNormal3f(Nx[i][j+1], Ny[i][j+1], Nz[i][j+1]);
glVertex3f(surfaceX[i][j+1], surfaceY[i][j+1], surfaceZ[i][j+1]);
glColor3f(R[i+1][j+1], G[i+1][j+1], B[i+1][j+1]);
glNormal3f(Nx[i+1][j+1], Ny[i+1][j+1], Nz[i+1][j+1]);
glVertex3f(surfaceX[i+1][j+1], surfaceY[i+1][j+1], surfaceZ[i+1][j+1]);
glColor3f(R[i+1][j], G[i+1][j], B[i+1][j]);
glNormal3f(Nx[i+1][j], Ny[i+1][j], Nz[i+1][j]);
glVertex3f(surfaceX[i+1][j], surfaceY[i+1][j], surfaceZ[i+1][j]);
glEnd();
}
}
But note, that the quality of the light will be low, because of the Gouraud shading of the Legacy OpenGL standard light model.
See also OpenGL Lighting on texture plane is not working.
Further, the normal vectors are inverted. You can change the direction by swapping the vectors in the cross product:
Nx[i][j] = Iz * Jy - Iy * Jz;
Ny[i][j] = Ix * Jz - Iz * Jx;
Nz[i][j] = Iy * Jx - Ix * Jy;
Side note:
Note, that drawing by glBegin/glEnd sequences, the fixed function matrix stack and fixed function, per vertex light model, is deprecated since decades. See Fixed Function Pipeline and Legacy OpenGL.
Read about Vertex Specification and Shader for a state of the art way of rendering.
I am using gl and glut on Windows platform
my problem is that glReadPixels returns all 0s. I guess it has something to do with the way I initialize the window so it cannot get the correct pixel value.
This is how I initialize the window:
glutInit(&argc, argv);
glutInitWindowSize(800,600);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 800, 600, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glTranslatef(0.375, 0.375, 0);
glClearColor(0, 0, 0, 1.0);
And with this, I get all 0s:
Edit:
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_QUADS);
glVertex2i(x-20, y-20);
glVertex2i(x-20, y+20);
glVertex2i(x+20, y+20);
glVertex2i(x+20, y-20);
glEnd();
unsigned char pixel[4];
glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
After I glClear, I did render some shapes, at (x, y) then I used glReadPixels to get the color at (x, y) but it returns 0s. I tried to glReadPixels the whole screen and it returns 0s too.
Edit 2:
So, to be more clear about my problem, here is the code:
I just don't know where the source of the problem could be so I pasted all of the code here. This is the tanks program from the book "Game Programming All in One" by Jonathan S. Habour. The book uses Allegro library, I try to convert to openGL. At the "look for a hit" in the updatebullet procedure, I printed out the coordinates of the enemy tank and the color at that pixel but all I get is 0s.
#include <GL/glut.h>
#include <stdlib.h>
#include <iostream.h>
#include <windows.h>
//define tank structure
struct tagTank
{
int x,y;
int dir,speed;
} tanks[2];
struct tagBullet
{
int x,y;
int alive;
int xspd,yspd;
} bullets[2];
void setuptanks()
{
tanks[0].x = 30;
tanks[0].y = 40;
tanks[0].dir = 1;
tanks[0].speed = 5;
tanks[1].x = 800 - 30;
tanks[1].y = 600 - 30;
tanks[1].dir = 3;
tanks[1].speed = 5;
}
void drawtank(int num)
{
int x = tanks[num].x;
int y = tanks[num].y;
int dir = tanks[num].dir;
//draw tank body
glColor3f(1.0, 0.0, 0.0);
if (num) glColor3f(0.0, 0.0, 1.0);
glBegin(GL_QUADS);
glVertex2i(x-20, y-20);
glVertex2i(x-20, y+20);
glVertex2i(x+20, y+20);
glVertex2i(x+20, y-20);
glEnd();
glColor3f(0.5, 0.0, 0.0);
if (num) glColor3f(0.0, 0.0, 0.5);
glBegin(GL_QUADS);
glVertex2i(x-10, y-10);
glVertex2i(x-10, y+10);
glVertex2i(x+10, y+10);
glVertex2i(x+10, y-10);
glEnd();
//draw the turret based on direction
glColor3f(1.0, 1.0, 1.0);
switch (dir)
{
case 0:
glBegin(GL_QUADS);
glVertex2i(x-2, y-30);
glVertex2i(x-2, y);
glVertex2i(x+2, y);
glVertex2i(x+2, y-30);
glEnd();
break;
case 1:
glBegin(GL_QUADS);
glVertex2i(x, y-2);
glVertex2i(x, y+2);
glVertex2i(x+30, y+2);
glVertex2i(x+30, y-2);
glEnd();
break;
case 2:
glBegin(GL_QUADS);
glVertex2i(x-2, y);
glVertex2i(x-2, y+30);
glVertex2i(x+2, y+30);
glVertex2i(x+2, y);
glEnd();
break;
case 3:
glBegin(GL_QUADS);
glVertex2i(x-30, y-2);
glVertex2i(x-30, y+2);
glVertex2i(x, y+2);
glVertex2i(x, y-2);
glEnd();
break;
}
}
void erasetank(int num)
{
//calculate box to encompass the tank
int left = tanks[num].x - 30;
int top = tanks[num].y - 30;
int right = tanks[num].x + 30;
int bottom = tanks[num].y + 30;
//erase the tank
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_QUADS);
glVertex2i(left, top);
glVertex2i(left, bottom);
glVertex2i(right, bottom);
glVertex2i(right, top);
glEnd();
}
void movetank(int num)
{
int dir = tanks[num].dir;
int speed = tanks[num].speed;
//update tank position based on direction
switch(dir)
{
case 0:
tanks[num].y -= speed;
break;
case 1:
tanks[num].x += speed;
break;
case 2:
tanks[num].y += speed;
break;
case 3:
tanks[num].x -= speed;
break;
}
//keep tank inside the screen
if (tanks[num].x > 800-30)
{
tanks[num].x = 800-30;
tanks[num].speed = 0;
}
else if (tanks[num].x < 30)
{
tanks[num].x = 30;
tanks[num].speed = 0;
}
else if (tanks[num].y > 600-30)
{
tanks[num].y = 600-30;
tanks[num].speed = 0;
}
else if (tanks[num].y < 30)
{
tanks[num].y = 30;
tanks[num].speed = 0;
}
else tanks[num].speed = 5;
}
void explode(int num, int x, int y)
{
int n;
//retrieve location of enemy tank
int tx = tanks[!num].x;
int ty = tanks[!num].y;
//is bullet inside the boundary of the enemy tank?
if (x > tx-30 && x < tx+30 && y > ty-30 && y < ty+30)
setuptanks();
//draw some random circles for the "explosion"
for (n = 0; n < 10; n++)
{
glColor3f((rand() % 101)/100.0, (rand() % 101)/100.0, (rand() % 101)/100.0);
glBegin(GL_QUADS);
glVertex2i(x-16, y-16);
glVertex2i(x-16, y+16);
glVertex2i(x+16, y+16);
glVertex2i(x+16, y-16);
glEnd();
//Sleep(10);
}
//clear the area of debris
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_QUADS);
glVertex2i(x-16, y-16);
glVertex2i(x-16, y+16);
glVertex2i(x+16, y+16);
glVertex2i(x+16, y-16);
glEnd();
}
void updatebullet(int num)
{
int x = bullets[num].x;
int y = bullets[num].y;
if (bullets[num].alive)
{
//erase bullet
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_QUADS);
glVertex2i(x-2, y-2);
glVertex2i(x-2, y+2);
glVertex2i(x+2, y+2);
glVertex2i(x+2, y-2);
glEnd();
//move bullet
bullets[num].x += bullets[num].xspd;
bullets[num].y += bullets[num].yspd;
x = bullets[num].x;
y = bullets[num].y;
//stay within the screen
if (x < 5 || x > 800 || y < 20 || y > 600)
{
bullets[num].alive = 0;
return;
}
//look for a hit
unsigned char pixel[4];
glReadPixels(tanks[!num].x, tanks[!num].y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
cout << tanks[!num].x << ", " << tanks[!num].y << " | " << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << endl;
if ((int)pixel[0] || (int)pixel[1] || (int)pixel[2])
{
bullets[num].alive = 0;
explode(num, x, y);
return;
}
//draw bullet
x = bullets[num].x;
y = bullets[num].y;
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex2i(x-2, y-2);
glVertex2i(x-2, y+2);
glVertex2i(x+2, y+2);
glVertex2i(x+2, y-2);
glEnd();
}
}
void fireweapon(int num)
{
int x = tanks[num].x;
int y = tanks[num].y;
//ready to fire again?
if (!bullets[num].alive)
{
bullets[num].alive = 1;
//fire bullet in direction tank is facing
switch (tanks[num].dir)
{
//north
case 0:
bullets[num].x = x;
bullets[num].y = y-30;
bullets[num].xspd = 0;
bullets[num].yspd = -20;
break;
//east
case 1:
bullets[num].x = x+30;
bullets[num].y = y;
bullets[num].xspd = 20;
bullets[num].yspd = 0;
break;
//south
case 2:
bullets[num].x = x;
bullets[num].y = y+30;
bullets[num].xspd = 0;
bullets[num].yspd = 20;
break;
//west
case 3:
bullets[num].x = x-30;
bullets[num].y = y;
bullets[num].xspd = -20;
bullets[num].yspd = 0;
break;
}
}
}
void up(int num)
{
tanks[num].dir = 0;
}
void down(int num)
{
tanks[num].dir = 2;
}
void left(int num)
{
tanks[num].dir = 3;
}
void right(int num)
{
tanks[num].dir = 1;
}
static void display(void)
{
erasetank(0);
erasetank(1);
movetank(0);
movetank(1);
drawtank(0);
drawtank(1);
updatebullet(0);
updatebullet(1);
glFlush();
Sleep(50);
}
static void key(unsigned char key, int x, int y)
{
switch (key)
{
case 27 :
exit(0);
break;
case 'a':
left(1);
break;
case 'd':
right(1);
break;
case 'w':
up(1);
break;
case 's':
down(1);
break;
case 32:
fireweapon(1);
break;
case 13:
fireweapon(0);
break;
}
glutPostRedisplay();
}
static void specialkey(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_LEFT:
left(0);
break;
case GLUT_KEY_RIGHT:
right(0);
break;
case GLUT_KEY_UP:
up(0);
break;
case GLUT_KEY_DOWN:
down(0);
break;
}
glutPostRedisplay();
}
static void idle(void)
{
glutPostRedisplay();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(800,600);
glutInitWindowPosition(10,10);
glutCreateWindow("Tanks");
glClear(GL_COLOR_BUFFER_BIT);
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutSpecialFunc(specialkey);
glutIdleFunc(idle);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 800, 600, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glTranslatef(0.375, 0.375, 0);
glClearColor(0, 0, 0, 1.0);
setuptanks();
glutMainLoop();
return EXIT_SUCCESS;
}
As Roger Rowland pointed out you are reading from the wrong part of the screen. You need to flip your y-coordinate before you pass it into glReadPixels()
Other things:
You don't need erasetank() or erasebullet(), just clear the screen each frame
It's a good idea to put glClear() and your matrix stuff in the display callback
An explicit glutInitDisplayMode() is a good idea
There's no real reason not to use GLUT_DOUBLE
Use a glutTimerFunc() instead of sleep()
All together:
#include <GL/glut.h>
#include <iostream>
using namespace std;
//define tank structure
struct tagTank
{
int x,y;
int dir,speed;
} tanks[2];
struct tagBullet
{
int x,y;
int alive;
int xspd,yspd;
} bullets[2];
void setuptanks()
{
tanks[0].x = 30;
tanks[0].y = 40;
tanks[0].dir = 1;
tanks[0].speed = 5;
tanks[1].x = 800 - 30;
tanks[1].y = 600 - 30;
tanks[1].dir = 3;
tanks[1].speed = 5;
}
void drawtank(int num)
{
int x = tanks[num].x;
int y = tanks[num].y;
int dir = tanks[num].dir;
//draw tank body
glColor3f(1.0, 0.0, 0.0);
if (num) glColor3f(0.0, 0.0, 1.0);
glBegin(GL_QUADS);
glVertex2i(x-20, y-20);
glVertex2i(x-20, y+20);
glVertex2i(x+20, y+20);
glVertex2i(x+20, y-20);
glEnd();
glColor3f(0.5, 0.0, 0.0);
if (num) glColor3f(0.0, 0.0, 0.5);
glBegin(GL_QUADS);
glVertex2i(x-10, y-10);
glVertex2i(x-10, y+10);
glVertex2i(x+10, y+10);
glVertex2i(x+10, y-10);
glEnd();
//draw the turret based on direction
glColor3f(1.0, 1.0, 1.0);
switch (dir)
{
case 0:
glBegin(GL_QUADS);
glVertex2i(x-2, y-30);
glVertex2i(x-2, y);
glVertex2i(x+2, y);
glVertex2i(x+2, y-30);
glEnd();
break;
case 1:
glBegin(GL_QUADS);
glVertex2i(x, y-2);
glVertex2i(x, y+2);
glVertex2i(x+30, y+2);
glVertex2i(x+30, y-2);
glEnd();
break;
case 2:
glBegin(GL_QUADS);
glVertex2i(x-2, y);
glVertex2i(x-2, y+30);
glVertex2i(x+2, y+30);
glVertex2i(x+2, y);
glEnd();
break;
case 3:
glBegin(GL_QUADS);
glVertex2i(x-30, y-2);
glVertex2i(x-30, y+2);
glVertex2i(x, y+2);
glVertex2i(x, y-2);
glEnd();
break;
}
}
void movetank(int num)
{
int dir = tanks[num].dir;
int speed = tanks[num].speed;
//update tank position based on direction
switch(dir)
{
case 0:
tanks[num].y -= speed;
break;
case 1:
tanks[num].x += speed;
break;
case 2:
tanks[num].y += speed;
break;
case 3:
tanks[num].x -= speed;
break;
}
//keep tank inside the screen
if (tanks[num].x > 800-30)
{
tanks[num].x = 800-30;
tanks[num].speed = 0;
}
else if (tanks[num].x < 30)
{
tanks[num].x = 30;
tanks[num].speed = 0;
}
else if (tanks[num].y > 600-30)
{
tanks[num].y = 600-30;
tanks[num].speed = 0;
}
else if (tanks[num].y < 30)
{
tanks[num].y = 30;
tanks[num].speed = 0;
}
else tanks[num].speed = 5;
}
void explode(int num, int x, int y)
{
int n;
//retrieve location of enemy tank
int tx = tanks[!num].x;
int ty = tanks[!num].y;
//is bullet inside the boundary of the enemy tank?
if (x > tx-30 && x < tx+30 && y > ty-30 && y < ty+30)
setuptanks();
//draw some random circles for the "explosion"
for (n = 0; n < 10; n++)
{
glColor3f((rand() % 101)/100.0, (rand() % 101)/100.0, (rand() % 101)/100.0);
glBegin(GL_QUADS);
glVertex2i(x-16, y-16);
glVertex2i(x-16, y+16);
glVertex2i(x+16, y+16);
glVertex2i(x+16, y-16);
glEnd();
}
}
void updatebullet(int num)
{
if (bullets[num].alive)
{
//move bullet
bullets[num].x += bullets[num].xspd;
bullets[num].y += bullets[num].yspd;
int x = bullets[num].x;
int y = bullets[num].y;
//stay within the screen
if (x < 5 || x > 800 || y < 20 || y > 600)
{
bullets[num].alive = 0;
return;
}
//look for a hit
unsigned char pixel[4];
int h = glutGet( GLUT_WINDOW_HEIGHT );
glReadPixels(x, h - y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
cout << x << ", " << y << " | " << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << endl;
if ((int)pixel[0] || (int)pixel[1] || (int)pixel[2])
{
bullets[num].alive = 0;
explode(num, x, y);
return;
}
//draw bullet
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex2i(x-2, y-2);
glVertex2i(x-2, y+2);
glVertex2i(x+2, y+2);
glVertex2i(x+2, y-2);
glEnd();
}
}
void fireweapon(int num)
{
int x = tanks[num].x;
int y = tanks[num].y;
//ready to fire again?
if (!bullets[num].alive)
{
bullets[num].alive = 1;
//fire bullet in direction tank is facing
switch (tanks[num].dir)
{
//north
case 0:
bullets[num].x = x;
bullets[num].y = y-30;
bullets[num].xspd = 0;
bullets[num].yspd = -20;
break;
//east
case 1:
bullets[num].x = x+30;
bullets[num].y = y;
bullets[num].xspd = 20;
bullets[num].yspd = 0;
break;
//south
case 2:
bullets[num].x = x;
bullets[num].y = y+30;
bullets[num].xspd = 0;
bullets[num].yspd = 20;
break;
//west
case 3:
bullets[num].x = x-30;
bullets[num].y = y;
bullets[num].xspd = -20;
bullets[num].yspd = 0;
break;
}
}
}
void up(int num)
{
tanks[num].dir = 0;
}
void down(int num)
{
tanks[num].dir = 2;
}
void left(int num)
{
tanks[num].dir = 3;
}
void right(int num)
{
tanks[num].dir = 1;
}
static void display(void)
{
glClearColor(0, 0, 0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
int w = glutGet( GLUT_WINDOW_WIDTH );
int h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho( 0, w, h, 0, -1, 1 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375, 0.375, 0);
movetank(0);
movetank(1);
drawtank(0);
drawtank(1);
glFlush();
updatebullet(0);
updatebullet(1);
glutSwapBuffers();
}
static void key(unsigned char key, int x, int y)
{
switch (key)
{
case 27 : exit(0); break;
case 'a': left(1); break;
case 'd': right(1); break;
case 'w': up(1); break;
case 's': down(1); break;
case 32: fireweapon(1); break;
case 13: fireweapon(0); break;
}
}
static void specialkey(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_LEFT: left(0); break;
case GLUT_KEY_RIGHT: right(0); break;
case GLUT_KEY_UP: up(0); break;
case GLUT_KEY_DOWN: down(0); break;
}
}
void timer( int value )
{
glutTimerFunc( 50, timer, 0 );
glutPostRedisplay();
}
int main(int argc, char *argv[])
{
glutInitWindowSize(800,600);
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutCreateWindow("Tanks");
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutSpecialFunc(specialkey);
glutTimerFunc( 0, timer, 0 );
setuptanks();
glutMainLoop();
return EXIT_SUCCESS;
}
I've just began learning OpenGL and this program is a mixture of stuff I've put together myself and some stuff straight copied from tutorials to speed up the process (like the whole OBJ loader you will see soon).
I'm having an error on
glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z);
//draw the faces
glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
glVertex3f(vertex[faces[i]->faces[3]-1]->x,vertex[faces[i]->faces[3]-1]->y,vertex[faces[i]->faces[3]-1]->z);
and that error is EXC_BAD_ACCESS code = 1. I'm completely lost for answers to this issue and I've searched around but couldn't find anything unfortunately. I also know for a fact that it is loading the file as well because that was the first issue I faced but resolved. Below is all my code (which is in one file. I'll be making a whole new project from scratch soon).
Main.cpp
#include <GLUT/GLUT.h>
#include <math.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <cmath>
void init();
void keyboard(unsigned char key, int x, int y);
void reshape(int w, int h);
void display();
void camera();
void cubePositions();
void drawCube();
void enable();
void plane();
// Roation angles.
float xPos = 0;
float yPos = 0;
float zPos = 0;
float xRot = 0;
float yRot = 0;
float angle = 0.0;
float lastx, lasty;
// Cubes position arrays.
float cubePosZ[10];
float cubePozX[10];
// Fog variables.
GLfloat fogAngle = 0.0;
GLfloat density = 0.1;
GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1.0};
#define checkImageWidth 64
#define checkImageHeight 64
static GLubyte checkImage[checkImageHeight][checkImageWidth][4];
static GLuint texName;
void makeCheckImage(void)
{
int i, j, c;
for (i = 0; i < checkImageHeight; i++) {
for (j = 0; j < checkImageWidth; j++) {
c = ((((i&0x8)==0)^((j&0x8))==0))*255;
checkImage[i][j][0] = (GLubyte) c;
checkImage[i][j][1] = (GLubyte) c;
checkImage[i][j][2] = (GLubyte) c;
checkImage[i][j][3] = (GLubyte) 255;
}
}
}
struct coordinate{
float x,y,z;
coordinate(float a,float b,float c) : x(a),y(b),z(c) {};
};
//for faces, it can contain triangles and quads as well, the four variable contain which is that
struct face{
int facenum;
bool four;
int faces[4];
face(int facen,int f1,int f2,int f3) : facenum(facen){ //constructor for triangle
faces[0]=f1;
faces[1]=f2;
faces[2]=f3;
four=false;
}
face(int facen,int f1,int f2,int f3,int f4) : facenum(facen){ //overloaded constructor for quad
faces[0]=f1;
faces[1]=f2;
faces[2]=f3;
faces[3]=f4;
four=true;
}
};
//we rotate or object with angle degrees
int loadObject(const char* filename)
{
std::vector<std::string*> coord; //read every single line of the obj file as a string
std::vector<coordinate*> vertex;
std::vector<face*> faces;
std::vector<coordinate*> normals; //normal vectors for every face
std::ifstream in(filename); //open the .obj file
if(!in.is_open()) //if not opened, exit with -1
{
std::cout << "Nor oepened" << std::endl;
return -1;
}
char buf[256];
//read in every line to coord
while(!in.eof())
{
in.getline(buf,256);
coord.push_back(new std::string(buf));
}
//go through all of the elements of coord, and decide what kind of element is that
for(int i=0;i<coord.size();i++)
{
if(coord[i]->c_str()[0]=='#') //if it is a comment (the first character is #)
continue; //we don't care about that
else if(coord[i]->c_str()[0]=='v' && coord[i]->c_str()[1]==' ') //if vector
{
float tmpx,tmpy,tmpz;
sscanf(coord[i]->c_str(),"v %f %f %f",&tmpx,&tmpy,&tmpz); //read in the 3 float coordinate to tmpx,tmpy,tmpz
vertex.push_back(new coordinate(tmpx,tmpy,tmpz)); //and then add it to the end of our vertex list
}else if(coord[i]->c_str()[0]=='v' && coord[i]->c_str()[1]=='n') //if normal vector
{
float tmpx,tmpy,tmpz; //do the same thing
sscanf(coord[i]->c_str(),"vn %f %f %f",&tmpx,&tmpy,&tmpz);
normals.push_back(new coordinate(tmpx,tmpy,tmpz));
}else if(coord[i]->c_str()[0]=='f') //if face
{
int a,b,c,d,e;
if(count(coord[i]->begin(),coord[i]->end(),' ')==3) //if it is a triangle (it has 3 space in it)
{
sscanf(coord[i]->c_str(),"f %d//%d %d//%d %d//%d",&a,&b,&c,&b,&d,&b);
faces.push_back(new face(b,a,c,d)); //read in, and add to the end of the face list
}else{
sscanf(coord[i]->c_str(),"f %d//%d %d//%d %d//%d %d//%d",&a,&b,&c,&b,&d,&b,&e,&b);
faces.push_back(new face(b,a,c,d,e)); //do the same, except we call another constructor, and we use different pattern
}
}
}
//raw
int num; //the id for the list
num=glGenLists(1); //generate a uniqe
glNewList(num,GL_COMPILE); //and create it
for(int i=0;i<faces.size();i++)
{
if(faces[i]->four) //if it's a quad draw a quad
{
glBegin(GL_QUADS);
//basically all I do here, is use the facenum (so the number of the face) as an index for the normal, so the 1st normal owe to the first face
//I subtract 1 because the index start from 0 in C++
glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z);
//draw the faces
glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
glVertex3f(vertex[faces[i]->faces[3]-1]->x,vertex[faces[i]->faces[3]-1]->y,vertex[faces[i]->faces[3]-1]->z);
glEnd();
}else{
glBegin(GL_TRIANGLES);
glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z);
glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
glEnd();
}
}
glEndList();
//delete everything to avoid memory leaks
for(int i=0;i<coord.size();i++)
delete coord[i];
for(int i=0;i<faces.size();i++)
delete faces[i];
for(int i=0;i<normals.size();i++)
delete normals[i];
for(int i=0;i<vertex.size();i++)
delete vertex[i];
return num; //return with the id
}
// Sets the position of the cubes randomly. Can later be used for more purposeful placements.
void cubePositions()
{
for (int i = 0; i < 10; i++)
{
cubePosZ[i] = rand() % 5 + 5;
cubePozX[i] = rand() % 5 + 5;
}
}
void drawCube()
{
for (int i = 0; i < 10; i++)
{
glPushMatrix();
//glTranslated(-cubePozX[i + 1] * 10, -1, -cubePosZ[i + 1] * 10);
glTranslated((i + 4), 0, (i - 5));
glTranslatef(i, 0, 5 * i);
glScalef(2, 2, 2);
glBegin(GL_QUADS);
glTexCoord2f(1, 0);
glVertex3f(-1, -1, 0);
glNormal3f(1, 1, 1);
glTexCoord2f(1, 1);
glVertex3f(-1, 1, 0);
glTexCoord2f(0, 1);
glVertex3f(1, 1, 0);
glTexCoord2f(0, 0);
glVertex3f(1, -1, 0);
glVertex3f(-1, -1, -1);
glVertex3f(-1, 1, -1);
glEnd();
glPopMatrix();
}
}
void plane()
{
glPushMatrix();
glColor4f(1.0, 0.0, 1.0, 1.0);
glTranslatef(0, -2.5, 0.0);
glScalef(100, 2, 100);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(-1, 0, 1);
glTexCoord2f(1.0, 0.0);
glVertex3f(-1, 0, -0.5);
glTexCoord2f(1.0, 1.0);
glVertex3f(1, 0, -0.5);
glTexCoord2f(0.0, 1.0);
glVertex3f(1, 0, 1);
glEnd();
glPopMatrix();
}
int cube;
void init()
{
cubePositions();
cube = loadObject("/Users/Admin/test.obj");
}
void enable()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_TEXTURE_2D);
float col[] = {1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT0, GL_DIFFUSE, col);
}
void camera()
{
glRotatef(xRot, 1.0, 0.0, 0.0);
glRotatef(yRot, 0.0, 1.0, 0.0);
glTranslated(-xPos, -yPos, -zPos);
}
void display()
{
glClearColor(0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
camera();
enable();
drawCube();
plane();
glCallList(cube);
glTranslated(-2, 0, 0);
glutSwapBuffers();
angle++;
}
void reshape(int w, int h)
{
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 1000.0);
glMatrixMode (GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
if (key == 27)
{
exit(0);
}
if (key == 'q')
{
xRot += 0.5;
if (xRot > 360)
{
xRot -= 360;
}
}
if (key == 'z')
{
xRot -= 0.5;
if (xRot < - 360)
{
xRot += 360;
}
}
if (key == 'w')
{
float xRotRad;
float yRotRad;
xRotRad = (xRot / 180 * 3.14159f);
yRotRad = (yRot / 180 * 3.14159f);
xPos += float(sin(yRotRad));
zPos -= float(cos(yRotRad));
yPos -= float(sin(xRotRad));
}
if (key == 's')
{
float xRotRad;
float yRotRad;
xRotRad = (xRot / 180 * 3.14159f);
yRotRad = (yRot / 180 * 3.14159f);
xPos -= float(sin(yRotRad));
zPos += float(cos(yRotRad));
yPos += float(sin(xRotRad));
}
if (key == 'd')
{
yRot += 1;
if (yRot > 360)
{
yRot -= 360;
}
}
if (key == 'a')
{
yRot -= 1;
if (yRot < -360)
{
yRot += 360;
}
}
if (key == 'x')
{
yPos -= 1;
}
if (key == 'c')
{
yPos += 1;
}
}
void mouseMovement(int x, int y)
{
int diffX = x - lastx;
int diffY = y - lasty;
lastx = x;
lasty = y;
xRot += (float)diffY;
yRot += (float)diffX;
}
int main(int argc, char * argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(1000, 1000);
glutInitWindowPosition(100, 100);
glutCreateWindow("OpenGL GLUT Computing - Taylor Moore");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutPassiveMotionFunc(mouseMovement);
glutMainLoop();
return 0;
}
EXC_BAD_ACCESS usually means you are trying to access a chunk of memory that has been released or dealloc'ed. Here's the first response to a Google search on the term EXC_BAD_ACCESS that explains two strategies for tracking down the cause.
I'm not new to C++ but I am used to running a g++ compiler vs Microsoft's VS C++. I understand what this error should mean. It should mean that I'm missing a ';' on the line before or in the class Polygon. I can't seem to find anything wrong. g++ compiles the code without error. It seems like the Polygon Class isn't being loaded. Can anyone please show me what I'm missing please.I have the Application.cpp, Polygon.h, and Polygon.cpp below.
Application.cpp throwing errors but if I can fix the first others will follow:
application.cpp(121) : error C2143: syntax error : missing ';' before '*'
application.cpp(121) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
application.cpp(121) : error C2365: 'Polygon' : redefinition; previous definition was 'function'
c:\program files\microsoft sdks\windows\v6.0a\include\wingdi.h(4203) : see declaration of 'Polygon'
#include <sstream>
#include <numeric>
#include <math.h>
#include "Polygon.h"
#define PI 3.14159265
//use standard namespace
using namespace std;
/**************************** Window Variables ****************************/
double _window_height = 500;
double _window_width = 500;
double _window_position_x = 0;
double _window_position_y = 0;
string _window_title ("Assignment 5");
/**************************** Object Variables ****************************/
int _my_shape = 0;
GLint _object_shine = 40;
double _object_y_rotation = 0;
GLfloat ambient_reflection[3] = {1.0, 1.0, 1.0};
GLfloat diffuse_reflection[3] = {1.0, 1.0, 1.0};
GLfloat specular_reflection[3] = {1.0, 1.0, 1.0};
GLfloat emissive_color[3] = {0.0, 0.0, 0.0};
int specular_exponent = 0;
/*************************** Lighting Variables ***************************/
//Global Light settings
GLfloat _global_ambient_light[] = {0.5, 0.5, 0.5, 1.0};
GLfloat _global_diffuse_light[] = {0.7, 0.7, 0.7, 1.0};
int rotation_int = 0;
int rotation_angle = 90;
int _CAMERA_DISTANCE = 2;
//Light 0 Settings
GLfloat _z_axis_rotations[8][4] = {{(_CAMERA_DISTANCE*cos((90)*PI/180)), (_CAMERA_DISTANCE*sin((90)*PI/180)), 0.0, 1.0},
{(_CAMERA_DISTANCE*cos((45)*PI/180)), (_CAMERA_DISTANCE*sin((45)*PI/180)), 0.0, 1.0},
{(_CAMERA_DISTANCE*cos((0)*PI/180)), (_CAMERA_DISTANCE*sin((0)*PI/180)), 0.0, 1.0},
{(_CAMERA_DISTANCE*cos((315)*PI/180)), (_CAMERA_DISTANCE*sin((315)*PI/180)), 0.0, 1.0},
{(_CAMERA_DISTANCE*cos((270)*PI/180)), (_CAMERA_DISTANCE*sin((270)*PI/180)), 0.0, 1.0},
{(_CAMERA_DISTANCE*cos((225)*PI/180)), (_CAMERA_DISTANCE*sin((225)*PI/180)), 0.0, 1.0},
{(_CAMERA_DISTANCE*cos((180)*PI/180)), (_CAMERA_DISTANCE*sin((180)*PI/180)), 0.0, 1.0},
{(_CAMERA_DISTANCE*cos((135)*PI/180)), (_CAMERA_DISTANCE*sin((135)*PI/180)), 0.0, 1.0}};
GLfloat _ambient_0_light[] = {0.3f, 0.3f, 0.3f, 1.0f};
GLfloat _diffuse_0_light[] = {0.6f, 0.6f, 0.6f, 1.0f};
GLfloat _specular_0_light[] = {0.6f, 0.6f, 0.6f, 1.0f};
GLfloat _specular_0_property[] = {0.6f, 0.6f, 0.6f, 1.0f};
//Light 1 Settings
// Green Spotlight with narrow angle
GLfloat _light_1_position[] = {2.0, 0.0, -0.5, 1.0};
GLfloat _diffuse_1_light[] = {0.2, 0.4, 0.9, 1.0};
GLfloat _spot_1_direction[] = {-0.3, -2.0, -0.3};
//Light 2 Settings
// Red Spotlight with wide angle
GLfloat _light_2_position[] = {0.3, -0.5, 4.0, 1.0};
GLfloat _diffuse_2_light[] = {1.0, 0.2, 0.6, 1.0};
GLfloat _spot_2_direction[] = {0.3, -0.5, -2.0};
GLfloat _cutoff = 90.0;
GLfloat _AMBIENT_CONSTANT = 0.1;
GLfloat _DIFFUSE_CONSTANT = 0.1;
GLfloat _EMISSION_CONSTANT = 0.05;
GLfloat _SPECULAR_CONSTANT = 0.1;
int _SPECULAR_EXPONENT_CONSTANT = 1;
int _CUTOFF_CONSTANT = 1;
/*************************** Shading Variables ***************************/
bool _shade_model_smooth = true;
/**************************** File Variables *****************************/
//Error String printed if the file is not found
string _FILE_OPEN_ERROR = "Error: File could not be found or opened.";
//Error String printed if the file is not formed correctly
string _CHOICE_INVALID_ERROR = "Error: The choice you made was not one that is defined.";
/** for file reading **/
//The Array for holding all the Polygons
Polygon** _Polygons;
//the current size of the Polygon Array
int _polygons_max = 10;
//the current element for processing in the Polygon Array
int _polygons_current = 0;
/* ReadFromFile
*
* This method will ask a filename from the user and either return to
* the user a file not found error or will read in from the file the
* coordinates and place them in the coordinate array, while also setting
* the number of lines that make up a shape.
*/
void ReadFromFile(){
ifstream input; // input file stream
string filename = ""; // used to store filename
string line = ""; // temporary storage for reading lines at a time
// cout << "Type a filename and press Enter: ";
// cin >> filename;
//cout << "Type a filename and press Enter: dodecahedron.dat" << endl;
filename = "dodec.dat";//"dodecahedron.dat"; //should be 36 polygons
input.open (filename.c_str(), ifstream::in);//try to open the file
if(input.is_open()){ //check if file is open
_Polygons = new Polygon*[_polygons_max];
double _light_settings[12] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
int SH = 0;
double _normals[3] = {0.0, 0.0, 0.0};
int _coordinate_count = 0;
int _coordinate_max = 4;
double** _coordinates = new double*[_coordinate_max];
while (input.good()){ //not eof or failbit
/* Ensure space is available */
if(_polygons_current >= _polygons_max){
_polygons_max = _polygons_max * 2; //double max size
Polygon** temp = new Polygon*[_polygons_max]; //create bigger array
for (int j = 0; j <_polygons_current; j++) {
temp[j] = _Polygons[j]; // copy values to new array.
}
delete [] _Polygons; //free old array memory
_Polygons = temp; //transfer polygons
}
getline(input, line); //get the line from input
string::size_type _last_pos = line.find_first_not_of(" ", 0);
string::size_type _pos = line.find_first_of(" ", _last_pos);
if((line.substr(_last_pos, _pos - _last_pos)).c_str()[0] == '#'){ //comment
//do nothing for this line
}else if((line.substr(_last_pos, _pos - _last_pos)).c_str()[0] == 'J' ||
(line.substr(_last_pos, _pos - _last_pos)).c_str()[0] == 'j'){ //polygon start
if(_coordinate_count != 0){
//cout << "Polygon #" << _polygons_current << endl;
_Polygons[_polygons_current] = new Polygon(_coordinate_count, _coordinates);
_Polygons[_polygons_current]->setAmbientReflection(_light_settings[0], _light_settings[1], _light_settings[2]);
_Polygons[_polygons_current]->setDiffuseReflection(_light_settings[3], _light_settings[4], _light_settings[5]);
_Polygons[_polygons_current]->setSpecularReflection(_light_settings[6], _light_settings[7], _light_settings[8]);
_Polygons[_polygons_current]->setEmissiveColor(_light_settings[9], _light_settings[10], _light_settings[11]);
_Polygons[_polygons_current]->setSurfaceNormals(_normals[0], _normals[1], _normals[2]);
_Polygons[_polygons_current]->setSpecularExponent(SH);
for(int i=0; i<_coordinate_count; i++){
delete _coordinates[i];
}
_coordinate_count = 0;
_polygons_current++;
}
if(line.find_first_not_of(" ", _pos) != string::npos){
for(int i=0; i<12; i++){
_last_pos = line.find_first_not_of(" ", _pos);
_pos = line.find_first_of(" ", _last_pos);
_light_settings[i] = atof(line.substr(_last_pos, _pos - _last_pos).c_str());
}
_last_pos = line.find_first_not_of(" ", _pos);
_pos = line.find_first_of(" ", _last_pos);
SH = atoi(line.substr(_last_pos, _pos - _last_pos).c_str());
for(int i=0; i<3; i++){
_last_pos = line.find_first_not_of(" ", _pos);
_pos = line.find_first_of(" ", _last_pos);
_normals[i] = atof(line.substr(_last_pos, _pos - _last_pos).c_str());
}
}
}else{
/* Ensure space is available */
if(_coordinate_count >= _coordinate_max){
_coordinate_max = _coordinate_max * 2; //double max size
double** temp = new double*[_coordinate_max]; //create bigger array
for (int i = 0; i < _coordinate_count; i++) {
temp[i] = new double[3];
temp[i][0] = _coordinates[i][0]; // copy values to new array.
temp[i][1] = _coordinates[i][1];
temp[i][2] = _coordinates[i][3];
}
delete [] _coordinates; //free old array memory
_coordinates = temp; //transfer polygons
}
_coordinates[_coordinate_count] = new double[3];
for(int i=0; i<3; i++){
_coordinates[_coordinate_count][i] = atof(line.substr(_last_pos, _pos - _last_pos).c_str());
_last_pos = line.find_first_not_of(" ", _pos);
_pos = line.find_first_of(" ", _last_pos);
}
_coordinate_count++;
}
}
input.close();
}else{
//if the file could not be opened output to the screen the error
cout << _FILE_OPEN_ERROR;
exit(0);
}
}
/* InitializeWindow
*
* Initializes the GLUT Library settings and creates a window for the
* program to be displayed in.
*
*/
void InitializeWindow(int argc, char** argv){
glutInit(&argc,argv); /* Initialize GLUT */
glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH );/* Specify display mode */
glutInitWindowSize(_window_width, _window_height); /* Set window size */
glutInitWindowPosition(_window_position_x, _window_position_y); /* Set window position */
glutCreateWindow(_window_title.c_str()); /* Create Window */
}
/* InitializeEnvironment
*
* Initializes the Glut environment in which the drawing is to be done.
*/
void InitializeEnvironment(){
glClearColor (0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, _global_ambient_light);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, _global_diffuse_light);
glLoadIdentity();
glLightfv(GL_LIGHT0, GL_POSITION, _z_axis_rotations[0]);
glLightfv(GL_LIGHT0, GL_SPECULAR, _specular_0_light);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, _cutoff);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0);
glLoadIdentity();
glLightfv(GL_LIGHT1, GL_POSITION, _light_1_position);
glLightfv(GL_LIGHT1, GL_DIFFUSE, _diffuse_1_light);
//
// glLoadIdentity();
// glLightfv(GL_LIGHT2, GL_POSITION, light3_position);
// glLightfv(GL_LIGHT2, GL_DIFFUSE, light3_diffuse_light);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
if(_my_shape == 1){
glFrontFace(GL_CW);
}else{
glFrontFace(GL_CCW);
}
glEnable(GL_CULL_FACE);
}
// In the main method we registered this method as the callback function for
// Keyboard input. Anytime a key is pressed the ascii value of the key and
// the x and y positions of the mouse cursor within the window are passed to
// this function.
void Keyboard(unsigned char key, int x, int y) {
switch (key) {
case '1':
glEnable(GL_LIGHT0);
break;
case '2':
glEnable(GL_LIGHT1);
break;
case '+': /* Increase the cutoff angle of the positional light. */
if(_cutoff == 90){
_cutoff = 180;
}else if((_cutoff-_CUTOFF_CONSTANT) > 180){
_cutoff = 180;
}else{
_cutoff += _CUTOFF_CONSTANT;
}
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, _cutoff);
break;
case '-': /* Decrease the cutoff angle of the positional light. */
if(_cutoff == 180){
_cutoff = 90;
}else if((_cutoff-_CUTOFF_CONSTANT) < 0){
_cutoff = 0;
}else{
_cutoff -= _CUTOFF_CONSTANT;
}
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, _cutoff);
break;
case '0': /* Turn off the directional and positional light. */
glDisable(GL_LIGHT0);
glDisable(GL_LIGHT1);
break;
case 'a': /* Decrease the ambient light. */
if(_global_ambient_light[0]>0){
_global_ambient_light[0] = _global_ambient_light[1] = _global_ambient_light[2] -= _AMBIENT_CONSTANT;
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, _global_ambient_light);
}
break;
case 'A': /* Increase the ambient light. */
if(_global_ambient_light[0]<1){
_global_ambient_light[0] = _global_ambient_light[1] = _global_ambient_light[2] += _AMBIENT_CONSTANT;
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, _global_ambient_light);
}
break;
case 'd': /* Decrease the diffuse light. */
if(_global_diffuse_light[0]>0){
_global_diffuse_light[0] = _global_diffuse_light[1] = _global_diffuse_light[2] -= _DIFFUSE_CONSTANT;
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, _global_diffuse_light);
}
break;
case 'D': /* Increase the diffuse light. */
if(_global_diffuse_light[0]<1){
_global_diffuse_light[0] = _global_diffuse_light[1] = _global_diffuse_light[2] += _DIFFUSE_CONSTANT;
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, _global_diffuse_light);
}
break;
case 's': /* Decrease the specular component of the positional light. */
if(_my_shape != 1){
for(int i=0; i<3; i++){
if((specular_reflection[i]-_SPECULAR_CONSTANT) < -1.0){
specular_reflection[i] = -1.0;
}else{
specular_reflection[i] -= _SPECULAR_CONSTANT;
}
}
}else{
for(int i=0; i < _polygons_current; i++){ //Over all Polygons
double* sr = _Polygons[i]->getSpecularReflection();
for(int j=0; j<3; j++){
if((sr[j]-_SPECULAR_CONSTANT) < -1.0){
sr[j] = -1.0;
}else{
sr[j] -= _SPECULAR_CONSTANT;
}
}
}
}
break;
case 'S': /* Increase the specular component of the positional light. */
if(_my_shape != 1){
for(int i=0; i<3; i++){
if((specular_reflection[i]+_SPECULAR_CONSTANT) > 1.0){
specular_reflection[i] = 1.0;
}else{
specular_reflection[i] += _SPECULAR_CONSTANT;
}
}
}else{
for(int i=0; i < _polygons_current; i++){ //Over all Polygons
double* sr = _Polygons[i]->getSpecularReflection();
for(int j=0; j<3; j++){
if((sr[j]+_SPECULAR_CONSTANT) > 1.0){
sr[j] = 1.0;
}else{
sr[j] += _SPECULAR_CONSTANT;
}
}
}
}
break;
case 'h': /* Decrease the shininess of the object. */
if(_my_shape != 1){
if((specular_exponent-_SPECULAR_EXPONENT_CONSTANT) < 0){
specular_exponent = 0;
}else{
specular_exponent-=_SPECULAR_EXPONENT_CONSTANT;
}
}else{
for(int i=0; i < _polygons_current; i++){ //Over all Polygons
int sh = _Polygons[i]->getSpecularExponent();
if((sh-_SPECULAR_EXPONENT_CONSTANT) < 0){
_Polygons[i]->setSpecularExponent(0);
}else{
_Polygons[i]->setSpecularExponent(sh-_SPECULAR_EXPONENT_CONSTANT);
}
}
}
break;
case 'H': /* Increase the shininess of the object. */
if(_my_shape != 1){
if((specular_exponent+_SPECULAR_EXPONENT_CONSTANT) > 128){
specular_exponent = 128;
}else{
specular_exponent+=_SPECULAR_EXPONENT_CONSTANT;
}
}else{
for(int i=0; i < _polygons_current; i++){ //Over all Polygons
int sh = _Polygons[i]->getSpecularExponent();
if((sh+_SPECULAR_EXPONENT_CONSTANT) > 128){
_Polygons[i]->setSpecularExponent(128);
}else{
_Polygons[i]->setSpecularExponent(sh+_SPECULAR_EXPONENT_CONSTANT);
}
}
}
break;
case 'e': /* Decrease the emissive light of the object. */
if(_my_shape != 1){
if((emissive_color[0]-_EMISSION_CONSTANT) < 0){
emissive_color[0] = 0;
}else{
emissive_color[0] -= _EMISSION_CONSTANT;
}
if((emissive_color[1]-_EMISSION_CONSTANT) < 0){
emissive_color[1] = 0;
}else{
emissive_color[1] -= _EMISSION_CONSTANT;
}
if((emissive_color[2]-_EMISSION_CONSTANT) < 0){
emissive_color[2] = 0;
}else{
emissive_color[2] -= _EMISSION_CONSTANT;
}
}else{
for(int i=0; i < _polygons_current; i++){ //Over all Polygons
double* ep = _Polygons[i]->getEmissiveColor();
if((ep[0]-_EMISSION_CONSTANT) < 0){
ep[0] = 0;
}else{
ep[0] -= _EMISSION_CONSTANT;
}
if((ep[1]-_EMISSION_CONSTANT) < 0){
ep[1] = 0;
}else{
ep[1] -= _EMISSION_CONSTANT;
}
if((ep[2]-_EMISSION_CONSTANT) < 0){
ep[2] = 0;
}else{
ep[2] -= _EMISSION_CONSTANT;
}
}
}
break;
case 'E': /* Increase the emissive light of the object. */
if(_my_shape != 1){
if((emissive_color[0]+_EMISSION_CONSTANT) > 1){
emissive_color[0] = 1;
}else{
emissive_color[0] += _EMISSION_CONSTANT;
}
if((emissive_color[1]+_EMISSION_CONSTANT) > 1){
emissive_color[1] = 1;
}else{
emissive_color[1] += _EMISSION_CONSTANT;
}
if((emissive_color[2]+_EMISSION_CONSTANT) > 1){
emissive_color[2] = 1;
}else{
emissive_color[2] += _EMISSION_CONSTANT;
}
}else{
for(int i=0; i < _polygons_current; i++){ //Over all Polygons
double* ep = _Polygons[i]->getEmissiveColor();
if((ep[0]+_EMISSION_CONSTANT) > 1){
ep[0] = 1;
}else{
ep[0] += _EMISSION_CONSTANT;
}
if((ep[1]+_EMISSION_CONSTANT) > 1){
ep[1] = 1;
}else{
ep[1] += _EMISSION_CONSTANT;
}
if((ep[2]+_EMISSION_CONSTANT) > 1){
ep[2] = 1;
}else{
ep[2] += _EMISSION_CONSTANT;
}
}
}
break;
case 'p': /* Rotate the positional light about the Z-axis */
glLoadIdentity();
if(rotation_int == 7){
rotation_int = 0;
}else{
rotation_int++;
}
glLightfv(GL_LIGHT0, GL_POSITION, _z_axis_rotations[rotation_int]);
break;
case 'P': /* Rotate the positional light about the Z-axis */
glLoadIdentity();
if(rotation_int == 0){
rotation_int = 7;
}else{
rotation_int--;
}
glLightfv(GL_LIGHT0, GL_POSITION, _z_axis_rotations[rotation_int]);
break;
case 'o': /* Rotate the objects around the Y-axis : negative */
_object_y_rotation -= 15.0;
break;
case 'O': /* Rotate the objects around the Y-axis : positive */
_object_y_rotation += 15.0;
break;
case 'q': case 'Q': /* Quit the program */
exit(0);
}
//Call redisplay to draw changes
glutPostRedisplay();
}
void DrawFromFile(){
glPushMatrix();
for(int i=0; i < _polygons_current; i++){ //Over all Polygons
double* ap = _Polygons[i]->getAmbientReflection();
double* dp = _Polygons[i]->getDiffuseReflection();
double* ep = _Polygons[i]->getEmissiveColor();
double* sp = _Polygons[i]->getSpecularReflection();
GLfloat amt[] = {ap[0], ap[1], ap[2], 1};
GLfloat dif[] = {dp[0], dp[1], dp[2], 1};
GLfloat emc[] = {ep[0], ep[1], ep[2], 1};
GLfloat spc[] = {sp[0], sp[1], sp[2], 1};
int _p_sides = _Polygons[i]->getSides();
glMaterialfv(GL_FRONT, GL_AMBIENT, amt);
glMaterialfv(GL_FRONT, GL_DIFFUSE, dif);
glMaterialfv(GL_FRONT, GL_EMISSION, emc);
glMaterialfv(GL_FRONT, GL_SPECULAR, spc);
glMateriali(GL_FRONT, GL_SHININESS, _Polygons[i]->getSpecularExponent());
glBegin(GL_POLYGON);
for(int j=0; j < _p_sides; j++){
glNormal3dv(_Polygons[i]->getSurfaceNormals());
glVertex3dv(_Polygons[i]->getVertex(j));
}
glEnd();
}
glPopMatrix();
}
void Display(void){
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glShadeModel (GL_SMOOTH);
//Perspective data here
glMatrixMode(GL_PROJECTION);
gluPerspective(45, 1, 0, 2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
switch(_my_shape){
case 1:
glTranslated(0, 0, -1);
glRotated(_object_y_rotation, 0, 1, 0);
DrawFromFile();
break;
case 2:
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_reflection);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_reflection);
glMaterialfv(GL_FRONT, GL_EMISSION, emissive_color);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflection);
glMateriali(GL_FRONT, GL_SHININESS, specular_exponent);
glRotated(_object_y_rotation, 0, 1, 0);
glutSolidTeapot(0.8);
break;
case 3:
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_reflection);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_reflection);
glMaterialfv(GL_FRONT, GL_EMISSION, emissive_color);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflection);
glMateriali(GL_FRONT, GL_SHININESS, specular_exponent);
glRotated(_object_y_rotation, 0, 1, 0);
glutSolidIcosahedron();
break;
case 4:
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_reflection);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_reflection);
glMaterialfv(GL_FRONT, GL_EMISSION, emissive_color);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflection);
glMateriali(GL_FRONT, GL_SHININESS, specular_exponent);
glRotated(_object_y_rotation, 0, 1, 0);
glutSolidTorus(0.3, 0.8, 10, 30);
break;
default:
cout << _CHOICE_INVALID_ERROR << endl;
exit(1);
break;
}
glPopMatrix();
glFlush();
}
int PollUser(){
int choice = 0;
cout << "Use the menu below to pick a shape to draw:" << endl << endl;
cout << "1: Dodecahedron (Drawn from file)" << endl;
cout << "2: Teapot (GLUT drawn)" << endl;
cout << "3: Icosahedron (GLUT drawn)" << endl;
cout << "4: Torus (GLUT drawn)" << endl;
cout << endl << "Enter choice: ";
cin >> choice;
return choice;
}
int main(int argc, char** argv){
_my_shape = PollUser();
InitializeWindow(argc, argv); /* Initialize window */
InitializeEnvironment(); /* Initialize other parameter */
glutDisplayFunc(Display); /* Redisplay callback event handling */
glutKeyboardFunc(Keyboard); /* Keyboard callback function */
ReadFromFile(); /* Read from file */
glutMainLoop(); /* Start glut functions */
return 0;
}
Polygon.h
#ifndef POLYGON_H_
#define POLYGON_H_
#include <iostream>
#include <cstdlib>
#include <new>
class Polygon {
public:
Polygon();
Polygon(int, double**);
virtual ~Polygon();
void *operator new(size_t size);
void operator delete(void *p);
void *operator new[](size_t size);
void operator delete[](void *p);
double* getVertex(int);
void setSpecularExponent(int);
void setSurfaceNormals(double,double,double);
void setAmbientReflection(double,double,double);
void setDiffuseReflection(double,double,double);
void setSpecularReflection(double,double,double);
void setEmissiveColor(double,double,double);
int getSides(void);
int getSpecularExponent(void);
double* getSurfaceNormals(void);
double* getAmbientReflection(void);
double* getDiffuseReflection(void);
double* getSpecularReflection(void);
double* getEmissiveColor(void);
private:
double** verticies;
double surface_normals[3];
double ambient_reflection[3];
double diffuse_reflection[3];
double specular_reflection[3];
double emissive_color[3];
int sides;
int spec_ex;
};
#endif /* POLYGON_H_ */
Polygon.cpp
#include "Polygon.h"
using namespace std;
Polygon::Polygon(){
sides = 0;
}
Polygon::Polygon(int numberOfSides, double** polyVerticies){
sides = numberOfSides;
verticies = new double*[numberOfSides];
for(int n=0; n<numberOfSides; n++){
verticies[n] = new double[3];
verticies[n][0] = polyVerticies[n][0];
verticies[n][1] = polyVerticies[n][1];
verticies[n][2] = polyVerticies[n][2];
}
}
void *Polygon::operator new(size_t size){
void *p;
p = malloc(size);
if(!p) {
bad_alloc ba;
throw ba;
}
return p;
}
void Polygon::operator delete(void *p){
free(p);
}
// new overloaded for loc arrays.
void *Polygon::operator new[](size_t size){
void *p;
p = malloc(size);
if(!p) {
bad_alloc ba;
throw ba;
}
return p;
}
void Polygon::operator delete[](void *p){
free(p);
}
void Polygon::setSpecularExponent(int exponent){
spec_ex = exponent;
}
void Polygon::setSurfaceNormals(double x, double y, double z){
surface_normals[0] = x;
surface_normals[1] = y;
surface_normals[2] = z;
}
void Polygon::setAmbientReflection(double r, double g, double b){
ambient_reflection[0] = r;
ambient_reflection[1] = g;
ambient_reflection[2] = b;
}
void Polygon::setDiffuseReflection(double r, double g, double b){
diffuse_reflection[0] = r;
diffuse_reflection[1] = g;
diffuse_reflection[2] = b;
}
void Polygon::setSpecularReflection(double r, double g, double b){
specular_reflection[0] = r;
specular_reflection[1] = g;
specular_reflection[2] = b;
}
void Polygon::setEmissiveColor(double r, double g, double b){
emissive_color[0] = r;
emissive_color[1] = g;
emissive_color[2] = b;
}
double* Polygon::getVertex(int index){
if(index < sides){
double* _temp = new double[3];
_temp[0] = verticies[index][0];
_temp[1] = verticies[index][1];
_temp[2] = verticies[index][2];
return _temp;
}
return new double;
}
int Polygon::getSides(){
return sides;
}
int Polygon::getSpecularExponent(){
return spec_ex;
}
double* Polygon::getSurfaceNormals(){
return surface_normals;
}
double* Polygon::getAmbientReflection(){
return ambient_reflection;
}
double* Polygon::getDiffuseReflection(){
return diffuse_reflection;
}
double* Polygon::getSpecularReflection(){
return specular_reflection;
}
double* Polygon::getEmissiveColor(){
return emissive_color;
}
Polygon::~Polygon() {
delete[] verticies;
}
Thanks for any help anyone can offer.
Your Polygon class conflicts with a Polygon function defined in wingdi.h :
WINGDIAPI BOOL WINAPI Polygon(HDC,const POINT*,int);
You could fix this error by putting the Polygon class in a namespace of yours.
Your Error is caused by there being a polygon type already defined in a windows system file. Put your Polygon type in a namespace and fully qualifie it.
From the third error, it looks like there could be a conflicting declaration for "Polygon" in your code. Try enclosing Polygon in a namespace?
I have a feeling the issue at hand here is the last of the errors you listed. Namely:
application.cpp(121) : error C2365: 'Polygon' : redefinition; previous definition was 'function' c:\program files\microsoft sdks\windows\v6.0a\include\wingdi.h(4203) : see declaration of 'Polygon'
Try putting your Polygon class in a separate namespace to prevent the name clash. That should clear it up. And reference it by the fully scoped name in application.cpp.
You are naming that class "Polygon" inside a namespace where a class with that name is already present (in wingdi.h). Do you read error message?
This is far too much code. Cut out as much as you can and see whether the error persists, before you post a bolus like this.
I don't have access to VS, so I can't test, but this looks like a namespace problem; your `Polygon` is in conflict with a Microsoft `Polygon`. So use your own namespace and don't say `using namespace std`, it's a scattergun.
You are getting an ambiguous name call of Polygon perhaps?
Would be better if you at least indicated which line is 121
By the way, why do you use arrays rather than vector and why are you overloading operator new?
I also encountered the same error, the reason for the error is that i have declaration and definition a B class in my A.cpp file and use B as
Member variables of A in A.h file. finally i solved this error by declaring class B in my A.h file.