Related
After the camera rotation on the Y axis and X and the subsequent move, is a strange camera rotation along the axis Z. For example, here is the normal state but I was randomly moved around the stage, all twisted I do not know what to do and how to fix the problem, I hope for your help. I saw this question, it does not help me, because I do not even use glm, do not mark as a duplicate.
Code:
#include <iostream>
#include <chrono>
#include <GL/glut.h>
#include "Camera.h"
using namespace std;
constexpr auto FPS_RATE = 120;
int windowHeight = 600, windowWidth = 600, windowDepth = 600;
float angle = 0, speedRatio = 0.25;
struct MyPoint3f
{
float x;
float y;
float z;
};
MyPoint3f lastMousePos = { };
bool mouseButtonWasPressed = false;
float mouseSensitivity = 0.1;
float camMoveSpeed = 3;
float camPitchAngle = 0, camYawAngle = 0;
Camera cam;
void init();
void displayFunction();
void idleFunction();
void reshapeFunction(int, int);
void keyboardFunction(unsigned char, int, int);
void specialKeysFunction(int, int, int);
void mouseFunc(int, int, int, int);
void motionFunction(int, int);
double getTime();
double getTime()
{
using Duration = std::chrono::duration<double>;
return std::chrono::duration_cast<Duration>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count();
}
const double frame_delay = 1.0 / FPS_RATE;
double last_render = 0;
void init()
{
glutDisplayFunc(displayFunction);
glutIdleFunc(idleFunction);
glutReshapeFunc(reshapeFunction);
glutKeyboardFunc(keyboardFunction);
glutMouseFunc(mouseFunc);
glutMotionFunc(motionFunction);
glViewport(0, 0, windowWidth, windowHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, -windowDepth / 2, windowDepth / 2);
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
cam.setShape(45, (double)windowWidth / windowHeight, 0.1, 1000);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
cam.set(Point3(0, 0, 350), Point3(0, 0, 349), Vector3(0, 1, 0));
}
void displayFunction()
{
angle += speedRatio;
if (angle >= 360 || angle <= -360) angle = 0;
if (camPitchAngle <= -360) camPitchAngle = 0;
if (camPitchAngle >= 360) camPitchAngle = 0;
if (camYawAngle <= -360) camYawAngle = 0;
if (camYawAngle >= 360) camYawAngle = 0;
cout << camPitchAngle << " " << camYawAngle << endl;
cam.pitch(-(camPitchAngle *= mouseSensitivity));
cam.yaw(-(camYawAngle *= mouseSensitivity));
camPitchAngle = 0; camYawAngle = 0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glRotatef(angle, 1, 0, 0);
glRotatef(angle, 0, 1, 0);
glColor3f(0, 1, 0);
glutWireCube(150.0);
glBegin(GL_LINES);
glColor3f(1, 0, 0);
for (int i = 0; i <= 75; i += 5)
{
glVertex3i(i, 0, 0);
glVertex3i(-i, 0, 0);
glVertex3i(0, i, 0);
glVertex3i(0, -i, 0);
glVertex3i(0, 0, i);
glVertex3i(0, 0, -i);
}
glEnd();
glPopMatrix();
//RSHIFT and CTRL
if (GetAsyncKeyState(VK_LSHIFT))
{
cam.slide(0, 1.0 * camMoveSpeed, 0);
}
if (GetAsyncKeyState(VK_LCONTROL))
{
cam.slide(0, -1.0 * camMoveSpeed, 0);
}
glutSwapBuffers();
}
void idleFunction()
{
const double current_time = getTime();
if ((current_time - last_render) > frame_delay)
{
last_render = current_time;
glutPostRedisplay();
}
}
void reshapeFunction(int w, int h)
{
}
void keyboardFunction(unsigned char key, int w, int h)
{
switch (key)
{
case '+': case '=':
speedRatio += 0.125;
break;
case '-': case '_':
speedRatio -= 0.125;
break;
case 'A': case 'a':
cam.slide(-1.0 * camMoveSpeed, 0, 0);
break;
case 'D': case 'd':
cam.slide(1.0 * camMoveSpeed, 0, 0);
break;
case 'W': case 'w':
cam.slide(0, 0, -1.0 * camMoveSpeed);
break;
case 'S': case 's':
cam.slide(0, 0, 1.0 * camMoveSpeed);
break;
case 'Z': case 'z':
cam.yaw(-1);
break;
case 'X': case 'x':
cam.yaw(1);
break;
case 27:
angle = 0;
speedRatio = 0;
cam.set(Point3(0, 0, 350), Point3(0, 0, 349), Vector3(0, 1, 0));
break;
default:
cout << key << endl;
break;
}
}
void specialKeysFunction(int key, int x, int y)
{
cout << key << endl;
}
void mouseFunc(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
mouseButtonWasPressed = true;
lastMousePos.x = x;
lastMousePos.y = y;
}
}
void motionFunction(int mousePosX, int mousePosY)
{
if (mousePosX >= 0 && mousePosX < windowWidth && mousePosY >= 0 && mousePosY < windowHeight)
{
if (mouseButtonWasPressed)
{
camPitchAngle += -mousePosY + lastMousePos.y;
camYawAngle += mousePosX - lastMousePos.x;
lastMousePos.x = mousePosX;
lastMousePos.y = mousePosY;
}
}
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(windowWidth, windowHeight);
glutInitWindowPosition((GetSystemMetrics(SM_CXSCREEN) - windowWidth) / 2, (GetSystemMetrics(SM_CYSCREEN) - windowHeight) / 2);
glutCreateWindow("Window");
init();
glutMainLoop();
return 0;
}
Camera.h
Camera.cpp
When you do
glRotatef(angle, 1, 0, 0);
glRotatef(angle, 0, 1, 0);
Then the model is rotated around the y-axis and then the rotated model is rotated around the x-axis, because glRotatef sets a rotation matrix and multiplies it to the current matrix.
Because the model is rotated around the y-axis before it is rotated around the x-axis, the (view space) y-axis is kept it the yz-plane of the view space.
If you want to keep the x-axis in the xz-plane of the view space, you've to do the rotation around the x-axis first:
glRotatef(angle, 0, 1, 0);
glRotatef(angle, 1, 0, 0);
The same issue occurs when you apply pich() and yaw() to the camera object. If you switch it (first yaw() then pitch()), then that won't solve the issue, because pitch and yaw are applied incrementally by each mouse move (pich(), yaw(), pich(), yaw(), pich(), yaw() ...). So there is always a yaw() after a pitch() and the model gets tilted.
To solve the issue you've to sum up camPitchAngle and camYawAngle. Take into account the mouse intensity:
void motionFunction(int mousePosX, int mousePosY)
{
if (mousePosX >= 0 && mousePosX < windowWidth && mousePosY >= 0 && mousePosY < windowHeight)
{
if (mouseButtonWasPressed)
{
camPitchAngle += (-mousePosY + lastMousePos.y) * mouseSensitivity;
camYawAngle += (mousePosX - lastMousePos.x) * mouseSensitivity;
lastMousePos.x = mousePosX;
lastMousePos.y = mousePosY;
}
}
}
Copy the camera object (cam / curr_cam) in displayFunction and apply camPitchAngle and camYawAngle to the copy. Use the copy to set the view and projection matrix:
void displayFunction()
{
// [...]
// cam.pitch(-(camPitchAngle *= mouseSensitivity)); <--- delete
// cam.yaw(-(camYawAngle *= mouseSensitivity)); <--- delete
// [...]
Camera curr_cam = cam;
curr_cam.yaw( -camYawAngle );
curr_cam.pitch( -camPitchAngle );
// [...]
if (GetAsyncKeyState(VK_LSHIFT))
{
curr_cam.slide(0, 1.0 * camMoveSpeed, 0);
}
if (GetAsyncKeyState(VK_LCONTROL))
{
curr_cam.slide(0, -1.0 * camMoveSpeed, 0);
}
// [...]
}
Of course you've to set camYawAngle = 0 respectively camPitchAngle = 0; when z, x or ESC is pressed.
so I got an image as a texture for a square, but the problem is that whenever I run the code I get this:
But when I take this line out:
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
Then I get this output (the white space is where I want to put the image as a texture):
Or if I change the third parameter to 5, then I get this output. But I know that the texture does display correctly when I run the code below, but the output is still like the first image at the top. How would I go about fixing the output so that it looks like the second image with the texture showing? Note that the texture DOES display fine with my code, you just cant see it becuase it's hidden becuase the whole output wont display properly.
#include <GL/glut.h>
#include <iostream>
#include <unistd.h>
#include <math.h>
#include <GL/gl.h>
#include <opencv2/opencv.hpp> //for OpenCV 3.x
#include <opencv/highgui.h> //for OpenCV 3.x
#include <cstdio>
#include <stdlib.h>
#include <string.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdio.h>
#include <math.h>
#define UpperBD 80
#define PI 3.1415926
#define Num_pts 10
using namespace std;
float Xe = 200.0f;//100
float Ye = 300.0f;
float Ze = 450.0f;
float Rho = sqrt(pow(Xe,2) + pow(Ye,2) + pow(Ze,2));
float D_focal = 100.0f;
GLuint texture[2];
struct Image {
unsigned long sizeX;
unsigned long sizeY;
char *data;
};
typedef struct Image Image;
#define checkImageWidth 64
#define checkImageHeight 64
GLubyte checkImage[checkImageWidth][checkImageHeight][3];
void makeCheckImage(void){
int i, j, c;
for (i = 0; i < checkImageWidth; i++) {
for (j = 0; j < checkImageHeight; 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;
}
}
}
int ImageLoad(char *filename, Image *image) {
FILE *file;
unsigned long size; // size of the image in bytes.
unsigned long i; // standard counter.
unsigned short int planes; // number of planes in image (must be 1)
unsigned short int bpp; // number of bits per pixel (must be 24)
char temp; // temporary color storage for bgr-rgb conversion.
// make sure the file is there.
if ((file = fopen(filename, "rb"))==NULL){
printf("File Not Found : %s\n",filename);
return 0;
}
// seek through the bmp header, up to the width/height:
fseek(file, 18, SEEK_CUR);
// read the width
if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
printf("Error reading width from %s.\n", filename);
return 0;
}
if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
printf("Error reading height from %s.\n", filename);
return 0;
}
size = image->sizeX * image->sizeY * 3;
// read the planes
if ((fread(&planes, 2, 1, file)) != 1) {
printf("Error reading planes from %s.\n", filename);
return 0;
}
if (planes != 1) {
printf("Planes from %s is not 1: %u\n", filename, planes);
return 0;
}
// read the bitsperpixel
if ((i = fread(&bpp, 2, 1, file)) != 1) {
printf("Error reading bpp from %s.\n", filename);
return 0;
}
if (bpp != 24) {
printf("Bpp from %s is not 24: %u\n", filename, bpp);
return 0;
}
// seek past the rest of the bitmap header.
fseek(file, 24, SEEK_CUR);
// read the data.
image->data = (char *) malloc(size);
if (image->data == NULL) {
printf("Error allocating memory for color-corrected image data");
return 0;
}
if ((i = fread(image->data, size, 1, file)) != 1) {
printf("Error reading image data from %s.\n", filename);
return 0;
}
for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}
// we're done.
return 1;
}
Image * loadTexture(){
Image *image1;
// allocate space for texture
image1 = (Image *) malloc(sizeof(Image));
if (image1 == NULL) {
printf("Error allocating space for image");
exit(0);
}
if (!ImageLoad("g.bmp", image1)) {
exit(1);
}
return image1;
}
void myinit(void)
//something in this function is making it not appear properly
{
// glClearColor (0.5, 0.5, 0.5, 0.0);
// glEnable(GL_DEPTH_TEST);
// glDepthFunc(GL_LESS);
Image *image1 = loadTexture();
// makeCheckImage();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Create Texture
glGenTextures(2, texture);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //scale linearly when image smalled than texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
//above line causing problem
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, texture[1]);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
// glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,&checkImage[0][0][0]);
glEnable(GL_TEXTURE_2D);
// glShadeModel(GL_FLAT);
}
typedef struct {
float X[UpperBD];
float Y[UpperBD];
float Z[UpperBD];
} pworld;
typedef struct {
float X[UpperBD];
float Y[UpperBD];
float Z[UpperBD];
} pviewer;
typedef struct{
float X[UpperBD];
float Y[UpperBD];
} pperspective;
typedef struct{
float X[UpperBD];
float Y[UpperBD];
} pattern2DL;
typedef struct{
float X[UpperBD];
float Y[UpperBD];
} arrowpoint;
typedef struct {
float r[UpperBD], g[UpperBD], b[UpperBD];
} pt_diffuse;
void mydisplay()
{
// define x-y coordinate
float p1x=-1.0f, p1y= 0.0f;
float p2x= 1.0f, p2y= 0.0f;
float p3x= 0.0f, p3y= 1.0f;
float p4x= 0.0f, p4y=-1.0f;
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
pworld world;
pviewer viewer;
pperspective perspective;
pattern2DL letterL;
arrowpoint arrow;
//define the x-y-z world coordinate
world.X[0] = 0.0; world.Y[0] = 0.0; world.Z[0] = 0.0; // origin
world.X[1] = 50.0; world.Y[1] = 0.0; world.Z[1] = 0.0; // x-axis
world.X[2] = 0.0; world.Y[2] = 50.0; world.Z[2] = 0.0; // y-axis
world.X[3] = 0.0; world.Y[3] = 0.0; world.Z[3] = 50.0; // y-axis
//define projection plane world coordinate , THIS IS THE SQUARE AROUND THE LETTERS
world.X[4] = 60.0; world.Y[4] = -50.0; world.Z[4] = 0.0;
world.X[5] = 60.0; world.Y[5] = 50.0; world.Z[5] = 0.0; // base line
world.X[7] = 60.0; world.Y[7] = -50.0; world.Z[7] = 100.0; // side bar
world.X[6] = 60.0; world.Y[6] = 50.0; world.Z[6] = 100.0; // side bar
//define 2D pattern letter A
letterL.X[0] = -10.0; letterL.Y[0] = 10.0;
letterL.X[1] = -15.0; letterL.Y[1] = 10.0;
letterL.X[2] = -20.0; letterL.Y[2] = 30.0;
letterL.X[3] = -40.0; letterL.Y[3] = 30.0;
letterL.X[4] = -45.0; letterL.Y[4] = 10.0;
letterL.X[5] = -50.0; letterL.Y[5] = 10.0;
letterL.X[6] = -37.0; letterL.Y[6] = 70.0;
letterL.X[7] = -23.0; letterL.Y[7] = 70.0;
letterL.X[8] = -25.0; letterL.Y[8] = 40.0;
letterL.X[9] = -35.0; letterL.Y[9] = 40.0;
letterL.X[10] = -30.0; letterL.Y[10] = 60.0;
//letter B
letterL.X[11] = 10.0; letterL.Y[11] = 10.0;
letterL.X[12] = 10.0; letterL.Y[12] = 70.0;
letterL.X[13] = 20.0; letterL.Y[13] = 10.0;
letterL.X[14] = 20.0; letterL.Y[14] = 70.0;
letterL.X[15] = 20.0; letterL.Y[15] = 60.0;
letterL.X[16] = 20.0; letterL.Y[16] = 45.0;
letterL.X[17] = 20.0; letterL.Y[17] = 35.0;
letterL.X[18] = 20.0; letterL.Y[18] = 20.0;
letterL.X[19] = 25.0; letterL.Y[19] = 58.0;
letterL.X[20] = 27.0; letterL.Y[20] = 56.0;
letterL.X[21] = 28.0; letterL.Y[21] = 52.0;
letterL.X[22] = 27.0; letterL.Y[22] = 49.0;
letterL.X[23] = 25.0; letterL.Y[23] = 47.0;
letterL.X[24] = 25.0; letterL.Y[24] = 33.0;
letterL.X[25] = 27.0; letterL.Y[25] = 31.0;
letterL.X[26] = 28.0; letterL.Y[26] = 27.0;
letterL.X[27] = 27.0; letterL.Y[27] = 24.0;
letterL.X[28] = 25.0; letterL.Y[28] = 22.0;
letterL.X[29] = 30.0; letterL.Y[29] = 65.0;
letterL.X[30] = 34.0; letterL.Y[30] = 60.0;
letterL.X[31] = 34.0; letterL.Y[31] = 50.0;
letterL.X[32] = 30.0; letterL.Y[32] = 45.0;
letterL.X[33] = 25.0; letterL.Y[33] = 40.0;
letterL.X[34] = 30.0; letterL.Y[34] = 38.0;
letterL.X[35] = 34.0; letterL.Y[35] = 30.0;
letterL.X[36] = 34.0; letterL.Y[36] = 20.0;
letterL.X[37] = 30.0; letterL.Y[37] = 15.0;
arrow.X[0] = 0.0; arrow.Y[0] = 25.0;
arrow.X[1] = 0.0; arrow.Y[1] = 75.0;
arrow.X[2] = 60.0; arrow.Y[2] = 75.0;
arrow.X[3] = 60.0; arrow.Y[3] = 85.0;
arrow.X[4] = 90.0; arrow.Y[4] = 50.0;
arrow.X[5] = 60.0; arrow.Y[5] = 15.0;
arrow.X[6] = 60.0; arrow.Y[6] = 25.0;
arrow.X[7] = 0.0; arrow.Y[7] = 25.0;
arrow.X[8] = 0.0; arrow.Y[8] = 75.0;
arrow.X[9] = 60.0; arrow.Y[9] = 75.0;
arrow.X[10] = 60.0; arrow.Y[10] = 85.0;
arrow.X[11] = 90.0; arrow.Y[11] = 50.0;
arrow.X[12] = 60.0; arrow.Y[12] = 15.0;
arrow.X[13] = 60.0; arrow.Y[13] = 25.0;
//decoration
for(int i = 0; i <= 37; i++)
{
world.X[8+i] = 60.0;
world.Y[8+i] = letterL.X[i];
world.Z[8+i] = letterL.Y[i];
}
//arrow
for(int j = 0; j <= 6; j++)
{
world.X[46+j] = arrow.X[j]-50;//-50
world.Y[46+j] = arrow.Y[j];
world.Z[46+j] = 100.0;//CHANGE TO 150?
}
for(int k = 0; k <= 6; k++)
{
world.X[53+k] = arrow.X[k]-50;
world.Y[53+k] = arrow.Y[k];
world.Z[53+k] = 110.0;//CHANGE TO 150?
}
float sPheta = Ye / sqrt(pow(Xe,2) + pow(Ye,2));
float cPheta = Xe / sqrt(pow(Xe,2) + pow(Ye,2));
float sPhi = sqrt(pow(Xe,2) + pow(Ye,2)) / Rho;
float cPhi = Ze / Rho;
float xMin = 1000.0, xMax = -1000.0;
float yMin = 1000.0, yMax = -1000.0;
//47 is normal vector 46 is a, 45 is ps, 7 is top left box vertex
//COMUTER SHADE OF FLOATING ARROW DUE NEXT WEEK
world.X[60] = -200.0; world.Y[60]=50.0; world.Z[60]=200.0;//ps
world.X[61] = 0.0; world.Y[61]=0.0; world.Z[61]=0.0;//vector a
world.X[62] = 0.0; world.Y[62]=0.0; world.Z[62]=1.0;//VECTOR N
float tmp = (world.X[62]*(world.X[61]-world.X[60]))
+(world.Y[62]*(world.Y[61]-world.Y[60]))
+(world.Z[62]*(world.Z[61]-world.Z[60]));
cout << tmp;
float lambda = tmp/((world.X[62]*(world.X[60]-world.X[7]))
+(world.Y[62]*(world.Y[60]-world.Y[7]))
+(world.Z[62]*(world.Z[60]-world.Z[7])));
cout << lambda;
float lambda_2 = tmp/((world.X[62]*(world.X[60]-world.X[6]))//MAKE ARROW HIGHER, ABOVE PROJECTION PLANE SQUARE
+(world.Y[62]*(world.Y[60]-world.Y[6]))
+(world.Z[62]*(world.Z[60]-world.Z[6])));
cout << lambda_2;
world.X[63] = world.X[60]+lambda*(world.X[60]-world.X[7]);//interseciton point for p7, X COMP
world.Y[63] = world.Y[60]+lambda*(world.Y[60]-world.Y[7]);//Y COMP
world.Z[63] = 0.0;
world.X[64] = world.X[60]+lambda_2*(world.X[60]-world.X[6]);//interseciton point for p7, X COMP
world.Y[64] = world.Y[60]+lambda_2*(world.Y[60]-world.Y[6]);//Y COMP
world.Z[64] = 0.0;
//for arrow's shade, 46-52
float lambda_arrow1 = tmp/((world.X[62]*(world.X[60]-world.X[46]))
+(world.Y[62]*(world.Y[60]-world.Y[46]))
+(world.Z[62]*(world.Z[60]-world.Z[46])));
float lambda_arrow2 = tmp/((world.X[62]*(world.X[60]-world.X[47]))//MAKE ARROW HIGHER, ABOVE PROJECTION PLANE SQUARE
+(world.Y[62]*(world.Y[60]-world.Y[47]))
+(world.Z[62]*(world.Z[60]-world.Z[47])));
float lambda_arrow3 = tmp/((world.X[62]*(world.X[60]-world.X[48]))
+(world.Y[62]*(world.Y[60]-world.Y[48]))
+(world.Z[62]*(world.Z[60]-world.Z[48])));
float lambda_arrow4 = tmp/((world.X[62]*(world.X[60]-world.X[49]))
+(world.Y[62]*(world.Y[60]-world.Y[49]))
+(world.Z[62]*(world.Z[60]-world.Z[49])));
float lambda_arrow5 = tmp/((world.X[62]*(world.X[60]-world.X[50]))
+(world.Y[62]*(world.Y[60]-world.Y[50]))
+(world.Z[62]*(world.Z[60]-world.Z[50])));
float lambda_arrow6 = tmp/((world.X[62]*(world.X[60]-world.X[51]))
+(world.Y[62]*(world.Y[60]-world.Y[51]))
+(world.Z[62]*(world.Z[60]-world.Z[51])));
float lambda_arrow7 = tmp/((world.X[62]*(world.X[60]-world.X[52]))
+(world.Y[62]*(world.Y[60]-world.Y[52]))
+(world.Z[62]*(world.Z[60]-world.Z[52])));
world.X[65] = world.X[60]+lambda_arrow1*(world.X[60]-world.X[46]);//interseciton point for p7, X COMP
world.Y[65] = world.Y[60]+lambda_arrow1*(world.Y[60]-world.Y[46]);//Y COMP
world.Z[65] = 0.0;
world.X[66] = world.X[60]+lambda_arrow2*(world.X[60]-world.X[47]);//interseciton point for p7, X COMP
world.Y[66] = world.Y[60]+lambda_arrow2*(world.Y[60]-world.Y[47]);//Y COMP
world.Z[66] = 0.0;
world.X[67] = world.X[60]+lambda_arrow3*(world.X[60]-world.X[48]);//interseciton point for p7, X COMP
world.Y[67] = world.Y[60]+lambda_arrow3*(world.Y[60]-world.Y[48]);//Y COMP
world.Z[67] = 0.0;
world.X[68] = world.X[60]+lambda_arrow4*(world.X[60]-world.X[49]);//interseciton point for p7, X COMP
world.Y[68] = world.Y[60]+lambda_arrow4*(world.Y[60]-world.Y[49]);//Y COMP
world.Z[68] = 0.0;
world.X[69] = world.X[60]+lambda_arrow5*(world.X[60]-world.X[50]);//interseciton point for p7, X COMP
world.Y[69] = world.Y[60]+lambda_arrow5*(world.Y[60]-world.Y[50]);//Y COMP
world.Z[69] = 0.0;
world.X[70] = world.X[60]+lambda_arrow6*(world.X[60]-world.X[51]);//interseciton point for p7, X COMP
world.Y[70] = world.Y[60]+lambda_arrow6*(world.Y[60]-world.Y[51]);//Y COMP
world.Z[70] = 0.0;
world.X[71] = world.X[60]+lambda_arrow7*(world.X[60]-world.X[52]);//interseciton point for p7, X COMP
world.Y[71] = world.Y[60]+lambda_arrow7*(world.Y[60]-world.Y[52]);//Y COMP
world.Z[71] = 0.0;
// -----------diffuse reflection-----------*
pt_diffuse diffuse; //diffuse.r[3]
//-------reflectivity coefficient-----------*
#define Kdr 0.8
#define Kdg 0.0
#define Kdb 0.0
// define additional pts to find diffuse reflection
//world.X[49] = world.X[45] + lambda_2*(world.X[45] - world.X[6]);
//--------compute distance------------------*//change 45 to 60!!!!!!
float distance[UpperBD];
for (int i=63; i<=71; i++) {
distance[i] = sqrt(pow((world.X[i]-world.X[60]),2)+ //intersect pt p7
pow((world.Y[i]-world.Y[60]),2)+
pow((world.X[i]-world.X[60]),2) );
//std::cout << "distance[i] " << distance[i] << std::endl;
}
// for (int i=4; i<=5; i++){
// distance[i] = sqrt(pow((world.X[i]-world.X[60]),2)+ //pt p4 of projection plane
// pow((world.Y[i]-world.Y[60]),2)+
// pow((world.X[i]-world.X[60]),2) );
// //std::cout << "distance[i] " << distance[i] << std::endl;
// }
//--------compute angle---------------------*
float angle[UpperBD], tmp_dotProd[UpperBD], tmp_mag_dotProd[UpperBD];
for (int i=63; i<=71; i++){
tmp_dotProd[i] = world.Z[i]-world.X[60];
std::cout << " tmp_dotProd[i] " << tmp_dotProd[i] << std::endl;
tmp_mag_dotProd[i] = sqrt(pow((world.X[i]-world.X[60]),2)+ //[45] pt light source
pow((world.Y[i]-world.Y[60]),2)+
pow((world.Z[i]-world.Z[60]),2) );
std::cout << " tmp_mag_dotProd[i] 1 " << tmp_mag_dotProd[i] << std::endl;
angle[i] = tmp_dotProd[i]/ tmp_mag_dotProd[i];
std::cout << "angle[i] " << angle[i] << std::endl;
//compute color intensity
diffuse.r[i] = Kdr * angle[i] / pow(distance[i],2) ;
diffuse.g[i] = Kdg * angle[i] / pow(distance[i],2) ;
diffuse.b[i] = Kdb * angle[i] / pow(distance[i],2) ;
}
// for (int i=4; i<=5; i++){
//
// tmp_dotProd[i] = world.Z[i]-world.X[45];
// std::cout << " tmp_dotProd[i] " << tmp_dotProd[i] << std::endl;
//
// tmp_mag_dotProd[i] = sqrt(pow((world.X[i]-world.X[45]),2)+ //[45] pt light source
// pow((world.Y[i]-world.Y[45]),2)+
// pow((world.Z[i]-world.Z[45]),2) );
// std::cout << " tmp_mag_dotProd[i] 1 " << tmp_mag_dotProd[i] << std::endl;
//
// angle[i] = tmp_dotProd[i]/ tmp_mag_dotProd[i];
// std::cout << "angle[i] " << angle[i] << std::endl;
//
// //compute color intensity
// diffuse.r[i] = Kdr * angle[i] / pow(distance[i],2) ;
// diffuse.g[i] = Kdg * angle[i] / pow(distance[i],2) ;
// diffuse.b[i] = Kdb * angle[i] / pow(distance[i],2) ;
//
// //std::cout << "diffuse.r[i] " << diffuse.r[i] << std::endl;
// //std::cout << "diffuse.g[i] " << diffuse.g[i] << std::endl;
// }
//
for(int i = 0; i < UpperBD; i++)
{
viewer.X[i] = -sPheta * world.X[i] + cPheta * world.Y[i];
viewer.Y[i] = -cPheta * cPhi * world.X[i]
- cPhi * sPheta * world.Y[i]
+ sPhi * world.Z[i];
viewer.Z[i] = -sPhi * cPheta * world.X[i]
- sPhi * cPheta * world.Y[i]
-cPheta * world.Z[i] + Rho;
// cout << i;
}
for(int i = 0; i <= UpperBD; i++)
{
perspective.X[i] = D_focal * viewer.X[i] / viewer.Z[i] ;
perspective.Y[i] = D_focal * viewer.Y[i] / viewer.Z[i] ;
if (perspective.X[i] > xMax) xMax = perspective.X[i];
if (perspective.X[i] < xMin) xMin = perspective.X[i];
if (perspective.Y[i] > yMax) yMax = perspective.Y[i];
if (perspective.Y[i] < yMin) yMin = perspective.Y[i];
/////*
//std::cout << "xMin " << xMin << std::endl;
// std::cout << "xMax " << xMax << std::endl;
// std::cout << "yMin " << yMin << std::endl;
// std::cout << "yMax " << yMax << std::endl;
//*/
}
for(int i = 0; i <= UpperBD; i++)
{
if ((xMax-xMin) != 0) perspective.X[i] = perspective.X[i]/(xMax-xMin);
if ((yMax-yMin) != 0) perspective.Y[i] = perspective.Y[i]/(yMax-yMin);
std::cout << i << perspective.X[i] << perspective.Y[i] << std::endl;
}
glViewport(0,0,1550,1250);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glBegin(GL_LINES);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(perspective.X[0],perspective.Y[0]);
glVertex2f(perspective.X[1],perspective.Y[1]);
glColor3f(0.0, 1.0, 0.0);
glVertex2f(perspective.X[0],perspective.Y[0]);
glVertex2f(perspective.X[2],perspective.Y[2]);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(perspective.X[0],perspective.Y[0]);
glVertex2f(perspective.X[3],perspective.Y[3]);
glColor3f(1.0, 1.0, 0.0); // projection plane , square
glVertex2f(perspective.X[4],perspective.Y[4]);
glVertex2f(perspective.X[5],perspective.Y[5]);
glVertex2f(perspective.X[4],perspective.Y[4]);
glVertex2f(perspective.X[7],perspective.Y[7]);
glVertex2f(perspective.X[5],perspective.Y[5]);
glVertex2f(perspective.X[6],perspective.Y[6]);
glVertex2f(perspective.X[6],perspective.Y[6]);
glVertex2f(perspective.X[7],perspective.Y[7]);
glEnd();
glColor3f(0.0, 1.0, 0.0); // LETTER A STARTS HERE
glBegin(GL_POLYGON);
glVertex2f(perspective.X[13],perspective.Y[13]);
glVertex2f(perspective.X[12],perspective.Y[12]);
glVertex2f(perspective.X[11],perspective.Y[11]);
glVertex2f(perspective.X[12],perspective.Y[12]);
glVertex2f(perspective.X[14],perspective.Y[14]);
glVertex2f(perspective.X[13],perspective.Y[13]);
glVertex2f(perspective.X[18],perspective.Y[18]);
glVertex2f(perspective.X[17],perspective.Y[17]);
glVertex2f(perspective.X[11],perspective.Y[11]);
glVertex2f(perspective.X[17],perspective.Y[17]);
glVertex2f(perspective.X[18],perspective.Y[18]);
glVertex2f(perspective.X[14],perspective.Y[14]);
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(perspective.X[8],perspective.Y[8]);
glVertex2f(perspective.X[15],perspective.Y[15]);
glVertex2f(perspective.X[14],perspective.Y[14]);
glVertex2f(perspective.X[15],perspective.Y[15]);
glVertex2f(perspective.X[14],perspective.Y[14]);
glVertex2f(perspective.X[18],perspective.Y[18]);
glVertex2f(perspective.X[16],perspective.Y[16]);
glVertex2f(perspective.X[18],perspective.Y[18]);
glVertex2f(perspective.X[16],perspective.Y[16]);
glVertex2f(perspective.X[10],perspective.Y[10]);
glVertex2f(perspective.X[9],perspective.Y[9]);
glVertex2f(perspective.X[10],perspective.Y[10]);
glVertex2f(perspective.X[8],perspective.Y[8]);
glVertex2f(perspective.X[9],perspective.Y[9]);
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(perspective.X[16],perspective.Y[16]);
glVertex2f(perspective.X[17],perspective.Y[17]);
//etc...
glEnd();
glColor3f(0.0, 1.0, 0.0); //LETTER B STARTS HERE
glBegin(GL_POLYGON);
glVertex2f(perspective.X[19],perspective.Y[19]);
glVertex2f(perspective.X[20],perspective.Y[20]);
//etc...
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINES);
//
glVertex2f(perspective.X[23],perspective.Y[23]);
glVertex2f(perspective.X[24],perspective.Y[24]);
glVertex2f(perspective.X[25],perspective.Y[25]);
glVertex2f(perspective.X[26],perspective.Y[26]);
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(perspective.X[27],perspective.Y[27]);
glVertex2f(perspective.X[28],perspective.Y[28]);
//etc...
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(perspective.X[29],perspective.Y[29]);
glVertex2f(perspective.X[30],perspective.Y[30]);
//etc...
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(perspective.X[24],perspective.Y[24]);
glVertex2f(perspective.X[41],perspective.Y[41]);
//etc...
glEnd();
glColor3f(0.0, 1.0, 0.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);//3D arrow starts here
glVertex2f(perspective.X[46],perspective.Y[46]);
glVertex2f(perspective.X[47],perspective.Y[47]);
//etc...
glEnd(); //end arrow
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_LINES);
glVertex2f(perspective.X[63],perspective.Y[63]);
glVertex2f(perspective.X[64],perspective.Y[64]);
//etc...
glEnd(); //end arrow
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);
//arrow shadow
glVertex2f(perspective.X[65],perspective.Y[65]);
glVertex2f(perspective.X[66],perspective.Y[66]);
//etc...
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[1]);
// glutSolidTeapot(0.1);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glEnable( GL_TEXTURE_2D );
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
glBegin(GL_QUADS);
glVertex2f(perspective.X[4],perspective.Y[4]);
glTexCoord2f(0.0, 0.0);
glVertex2f(perspective.X[5],perspective.Y[5]);
glTexCoord2f(0.1, 0.0);
glVertex2f(perspective.X[4],perspective.Y[4]);
glTexCoord2f(0.1, 0.1);
glVertex2f(perspective.X[7],perspective.Y[7]);
glTexCoord2f(0.0, 0.1);
glVertex2f(perspective.X[5],perspective.Y[5]);
glVertex2f(perspective.X[6],perspective.Y[6]);
glVertex2f(perspective.X[6],perspective.Y[6]);
glVertex2f(perspective.X[7],perspective.Y[7]);
glEnd();
glDisable( GL_TEXTURE_2D );
//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
#define display_scaling 200000.0
#define display_shifting 0.2
for (int i=63; i<=71; i++) {
float r, g, b;
r = display_scaling*diffuse.r[i]+display_shifting;
//r = display_scaling*diffuse.r[i];
g = diffuse.g[i]; b = diffuse.b[i] ;
glColor3f(r, g, b);
std::cout << "display_scaling*diffuse.r[i] " << r << std::endl;
glBegin(GL_POLYGON);
glVertex2f(perspective.X[i],perspective.Y[i]);
glVertex2f(perspective.X[i]+0.1,perspective.Y[i]);
glVertex2f(perspective.X[i]+0.1,perspective.Y[i]+0.1);
glVertex2f(perspective.X[i],perspective.Y[i]+0.1);
glEnd();
}
gluPerspective(45.0,0.5,1.0,60.0);
gluOrtho2D(5, 10, 0.0, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutSwapBuffers();
glFlush();
//sleep(5);
}
int main(int argc, char** argv)
{
cv::Mat image = cv::imread("b.jpg", CV_LOAD_IMAGE_COLOR);
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB );
glutInitWindowSize(900, 1000);
glutCreateWindow("lab");
//imshow( "lab", image );
glutDisplayFunc(mydisplay);
myinit();
glutMainLoop();
}
glEnable(GL_TEXTURE_2D) has to be removed from myinit, because it is done immediately before the object with the texture is drawn.
Further use the STB library, which can be found at GitHub - nothings/stb to load the bitmap:
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
void myinit(void)
{
glGenTextures(2, texture);
int cx, cy, ch;
stbi_uc *img = stbi_load("g.bmp", &cx, &cy, &ch, 3);
if (!img)
return;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, cx, cy, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
stbi_image_free( img );
// ....
}
The number of vertex coordinates is UpperBD, so the maximum index is UpperBD-1 or < UpperBD, but not <= UpperBD.
Change (2 times):
for(int i = 0; i <= UpperBD; i++)
for(int i = 0; i < UpperBD; i++)
gluPerspective and gluOrtho2D at once makes no sense at all.
Init the projection matrix and the model view matrix at the begin of each frame in mydisplay:
void mydisplay()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,0.5,1.0,60.0);
//gluOrtho2D(5, 10, 0.0, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
.....
}
When the vertex coordinate is set by glVertex the current texture coordinates, and is associated with the vertex coordinate. This means glTexCoord has to be dine before glVertex. A GL_QUAD primitive consitis of 4 vertices and each vertex coordinate needs its own texture coordinate:
glBindTexture(GL_TEXTURE_2D, texture[0]);
glEnable( GL_TEXTURE_2D );
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex2f(perspective.X[4],perspective.Y[4]);
glTexCoord2f(1.0, 0.0);
glVertex2f(perspective.X[5],perspective.Y[5]);
glTexCoord2f(1.0, 1.0);
glVertex2f(perspective.X[6],perspective.Y[6]);
glTexCoord2f(0.0, 1.0);
glVertex2f(perspective.X[7],perspective.Y[7]);
glEnd();
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 got some code but the matrix orientation does not appeal to my purposes, can someone teach me how to convert it's orientation, it's currently set up as X Z Y, but i would like it to reflect X Y Z, can someone please highlight what must be done?
when i do vertex3f(100, 100, 10); forexample, the 10 value should reflect the Z value on my grid.
Here is my code:
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <Windows.h>
#include <glut.h>
#include <iostream>
using namespace std;
const float sensitivity = 0.005;
const float walk_speed = 0.5;
float cam_pos[3] = { 100.5, 10.0f, 50 };
float cam_view[3] = { -1.0f, 0.0f, 1.0f };
static int old_x, old_y, half_width, half_height;
int width = 1024, height = 768;
void updateKeys()
{
if (GetAsyncKeyState('W')){
cam_pos[0] += cam_view[0] * walk_speed;
cam_pos[1] += cam_view[1] * walk_speed;
cam_pos[2] += cam_view[2] * walk_speed;
}
if (GetAsyncKeyState('S')){
cam_pos[0] -= cam_view[0] * walk_speed;
cam_pos[1] -= cam_view[1] * walk_speed;
cam_pos[2] -= cam_view[2] * walk_speed;
}
if (GetAsyncKeyState('A')){
cam_pos[0] += cam_view[2] * walk_speed;
cam_pos[2] -= cam_view[0] * walk_speed;
}
if (GetAsyncKeyState('D')){
cam_pos[0] -= cam_view[2] * walk_speed;
cam_pos[2] += cam_view[0] * walk_speed;
}
if (GetAsyncKeyState(VK_SPACE)){
cam_pos[1] += walk_speed;
}
}
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//3d camera
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
cam_pos[0], cam_pos[1], cam_pos[2],
cam_pos[0] + cam_view[0], cam_pos[1] + cam_view[1], cam_pos[2] + cam_view[2],
0.0f, 1.0f, 0.0f);
//render grid
glBegin(GL_LINES);
for (int i = 0; i <= 100; i++) {
if (i == 0) { glColor3f(.6, .3, .3); }
else { glColor3f(.25, .25, .25); };
glVertex3f(i, 0, 0);
glVertex3f(i, 0, 100);
if (i == 0) { glColor3f(.3, .3, .6); }
else { glColor3f(.25, .25, .25); };
glVertex3f(0, 0, i);
glVertex3f(100, 0, i);
};
glEnd();
glEnable(GL_POINT_SMOOTH);
glPointSize(50.0f);
glColor3f(1, 0, 0);
glBegin(GL_POINTS);
glVertex3f(0, 0, 0);
//X, Z, Y
glVertex3f(10, -10, 10);
glEnd();
updateKeys();
glutSwapBuffers();
}
void normalize(float *v)
{
float magnitude = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] /= magnitude;
v[1] /= magnitude;
v[2] /= magnitude;
}
void rotate_view(float *view, float angle, float x, float y, float z)
{
float new_x;
float new_y;
float new_z;
float c = cos(angle);
float s = sin(angle);
new_x = (x*x*(1 - c) + c) * view[0];
new_x += (x*y*(1 - c) - z*s) * view[1];
new_x += (x*z*(1 - c) + y*s) * view[2];
new_y = (y*x*(1 - c) + z*s) * view[0];
new_y += (y*y*(1 - c) + c) * view[1];
new_y += (y*z*(1 - c) - x*s) * view[2];
new_z = (x*z*(1 - c) - y*s) * view[0];
new_z += (y*z*(1 - c) + x*s) * view[1];
new_z += (z*z*(1 - c) + c) * view[2];
view[0] = new_x;
view[1] = new_y;
view[2] = new_z;
normalize(view);
}
void motion(int x, int y)
{
float rot_x, rot_y;
float rot_axis[3];
x -= half_width;
y -= half_height;
rot_x = -(float)(x - old_x) * sensitivity;
rot_y = -(float)(y - old_y) * sensitivity;
old_x = x;
old_y = y;
rotate_view(cam_view, rot_x, 0.0f, 1.0f, 0.0f);
rot_axis[0] = -cam_view[2];
rot_axis[1] = 0.0f;
rot_axis[2] = cam_view[0];
normalize(rot_axis);
rotate_view(cam_view, rot_y, rot_axis[0], rot_axis[1], rot_axis[2]);
}
void mouse(int button, int state, int x, int y)
{
old_x = x - half_width;
old_y = y - half_height;
glutPostRedisplay();
}
void idle()
{
glutPostRedisplay();
}
void keys(unsigned char c, int x, int y)
{
glutPostRedisplay();
cout << "camera view: :" << cam_view[0] << "," << cam_view[1] << "," << cam_view[2] << endl;
}
void reshape(int w, int h)
{
width = w;
height = h;
half_height = w / 2;
half_width = h / 2;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 10000.0);
glViewport(0, 0, w, h);
}
//----------------------------------------------------------------------
// Main program
//----------------------------------------------------------------------
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(width, height);
glutCreateWindow("OpenGL");
glutDisplayFunc(renderScene);
glutKeyboardFunc(keys);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutIdleFunc(idle);
// OpenGL init
glEnable(GL_DEPTH_TEST);
// enter GLUT event processing cycle
glutMainLoop();
return 0; // this is just to keep the compiler happy
}
Use a transformation matrix that "remaps" the values. You can push that matrix on your modelview as usual.
The identity matrix is:
(1, 0, 0; 0, 1, 0; 0, 0, 1)
Your matrix would be:
(1, 0, 0; 0, 0, 1; 0, 1, 0)
I guess you can spot the difference. You can extend to a 4D matrix for homogeneous coordinates accordingly.
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.