I'm having trouble getting my yoyo program to work; I have a growing and shrinking string to go along with the yoyo moving and spinning, but I've got the string moving along with the yoyo. I need to have the string staying stationary while the yoyo spins up and down.I have to have the string and yoyo's movements allocated onto one button as well. Mind helping me with my code? (also please excuse the lackluster yoyo; I wanted to finish the programming before designing it)
#include "stdafx.h"
#include <GL/glut.h>
#include <GL/gl.h>
#include <math.h>
void firstDisplay();
void secondDisplay();
void movement();
void init();
void drawButton();
void handleButton(int button, int state, int x, int y);
const int Width=720;
const int Height = 480;
static float PI = 3.14159;
static float radius = 25;
static float INC= (PI/30);
static GLfloat spin = 0.0;
static GLfloat deltaz = .001;
static GLfloat deltax = 0.0;
static GLfloat deltay = 0.0;
//######################################################### Main #########################################################
void main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_MULTISAMPLE | GLUT_DEPTH);
glutInitWindowSize(Width,Height);
glutInitWindowPosition(0,0);
glutCreateWindow("Yoyo");
glutDisplayFunc(firstDisplay);
glutMouseFunc(handleButton);
init();
glutMainLoop();
return;
}
//######################################################### Draw Button #########################################################
void drawButton()
{
glBegin(GL_POLYGON);
float theta;
for (theta = 0.0; theta <= 2 * PI; theta += INC)
{
glColor3f(1,0,1);
glVertex2f(40 + radius * cos(theta), 40 + radius*sin(theta));
}
glEnd();
}
//######################################################### Second Display #########################################################
void secondDisplay()
{
float theta;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON); //Here is the yoyo
for (theta = 0.0; theta <= 2 * PI; theta += INC)
{
glColor3f(1,1,1);
float radius1 = 75;
glVertex2f(360 + radius1 * cos(theta), 80 + radius1*sin(theta));
}
glEnd();
glBegin(GL_POLYGON); //Here is the yoyo design
for (theta = 0.0; theta <= 2 * PI; theta += INC)
{
glColor3f(0,1,1);
float radius1 = 55;
glVertex2f(350 + radius1 * cos(theta), 90 + radius1*sin(theta));
}
glEnd();
glFlush();
return;
}
//######################################################### First Display #########################################################
void firstDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
float theta;
glBegin(GL_POLYGON); //Here is the yoyo
for (theta = 0.0; theta <= 2 * PI; theta += INC)
{
glColor3f(1,1,1);
float radius1 = 75;
glVertex2f(360 + radius1 * cos(theta), 80 + radius1*sin(theta));
}
glEnd();
glBegin(GL_POLYGON); //Here is the yoyo
for (theta = 0.0; theta <= 2 * PI; theta += INC)
{
glColor3f(0,1,1);
float radius1 = 55;
glVertex2f(350 + radius1 * cos(theta), 90 + radius1*sin(theta));
}
glEnd();
drawButton();
glutSwapBuffers();
glFlush();
return;
}
//######################################################### Draw String #########################################################
void draw_string()
{
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(363, 8.25 - deltay, 0.0);
glVertex3f(357, 8.25 - deltay, 0);
glVertex3f(357, 6, 0);
glVertex3f(363, 6, 0);
glEnd();
}
//######################################################### Button Controls #########################################################
void handleButton(int button, int state, int x, int y)
{
static int index =-1;
if(button == GLUT_LEFT_BUTTON)
{
if(y>= 10 && y<= 100)
{
if (state == GLUT_DOWN)
{
glutIdleFunc(movement);
}
if (state == GLUT_UP)
{
glutIdleFunc(NULL);
}
}
glutSwapBuffers();
}
}
//######################################################### Yoyo Movement #########################################################
void movement()
{
static int goingup = 0;
glClear(GL_COLOR_BUFFER_BIT);
if(goingup==1)
{
deltay -= 6;
if(deltay <= 0)
{
goingup = 0;
}
spin = spin -5;
if(spin < 360)
{
spin = spin + 360;
}
}
if(goingup == 0)
{
deltay += 6;
if (deltay >= 315)
{
goingup = 1;
}
spin = spin +5;
if(spin < 360)
{
spin = spin + 360;
}
}
glPushMatrix();
glTranslatef(360+deltax, 80+deltay, 0.0);
glRotatef(spin,0.0,0.0,1.0);
glTranslatef(-360,-80, 0.0);
secondDisplay();
draw_string();
glPopMatrix();
drawButton();
glutSwapBuffers();
}
//######################################################### Init #########################################################
void init()
{
glClearColor(0, 0, 0, 0.0);
glColor3f(1, 1, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,Width,Height,0);
return;
}
I solved my problem. I went separated the draw_string() and seconddisplay() functions within the movement function like so:
}
glPushMatrix();
glTranslatef(360+deltax, 80+deltay, 0.0);
glRotatef(spin,0.0,0.0,1.0);
glTranslatef(-360,-80, 0.0);
secondDisplay();
glPopMatrix();
glPushMatrix();
glTranslatef(360+deltax, 80+deltay, 0.0);
glRotatef(0,0.0,0.0,1.0);
glTranslatef(-360,-80, 0.0);
draw_string();
glPopMatrix();
drawButton();
glutSwapBuffers();
}
I removed the spin from draw_string()'s glRotatef.
Related
I am trying to draw a Bezier curve in OpenGL using floating point values. I have tried using many different code examples. My current code below, runs ,but does not show the curve on screen. The usual way to draw Bezier curves are with integer values, which means using the GLUORTHO2D() function for drawing the curve. But I want to draw a curve using floating point values. Such as x range(-1,1) and y range(-1,1).
like if x=(500) then consider it (-1 to 1) and if y=(800) then consider it (-1,1).
I have already tried using integer values and it worked for me. my code using integer values is below:
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
#define CTRL_COUNT 100
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
int X1[3]={20,25,20}, Y1[3]={5,24,38}; //first point(x1[0],y1[0]) second(x1[1],y1[1]) third(x1[2],y1[2])
void myInit()
{
glClearColor(0.0,0.0,0.0,0.0);
glColor3f(1.0,0.0,0.0);
glPointSize(8.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,128.0,0.0,96.0);
}
//p(t)=(1-t)^3*p0+3t(1-t)^2*p1+3t^2(1-t)p2+t^3p3
float getNextBezierPointX(float t)
{
float x=0.0;
for(int i=0; i<ctrlPointsCount; i++)
{
int c;
if(i==0 || i==ctrlPointsCount-1)
c = 1;
else
{
c = ctrlPointsCount-1;
}
x += c * pow(t, i) * pow(1-t, ctrlPointsCount-1-i) * ctrlPointsX[i];
}
return x;
}
float getNextBezierPointY(float t)
{
float y=0.0;
for(int i=0; i<ctrlPointsCount; i++)
{
int c;
if(i==0 || i==ctrlPointsCount-1)
c = 1;
else
{
c = ctrlPointsCount-1;
}
y += c * pow(t, i) * pow(1-t, ctrlPointsCount-1-i) * ctrlPointsY[i];
}
return y;
}
void drawline()
{
// draw control points using red color
for(int i=0; i < 3; i++)
{
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
// draw bezier curve using control poitns by calculating next points using cubic bezier curve formula
float oldX=ctrlPointsX[0], oldY=ctrlPointsY[0];
for(double t = 0.0;t <= 1.0; t += 0.01) {
float x = getNextBezierPointX(t);
float y = getNextBezierPointY(t);
//glColor3f(1.0,t,1.0);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
void myDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
ctrlPointsCount=3;
for(int i=0;i<3;i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glFlush();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(640,480);
glutInitWindowPosition(100,150);
glutCreateWindow("Bezier Curve");
glutDisplayFunc(myDisplay);
myInit();
glutMainLoop();
return 0;
}
But when i tried using floating point values , it does not work for me. It does not show the curved line on screen. My code using floating point values is below:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
using namespace std;
#define CTRL_COUNT 100
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = { 0.946875, 0.884375, 0.946875 };
//Initializes 3D rendering
void initRendering() {
glEnable(GL_DEPTH_TEST);
}
float getNextBezierPointX(float t)
{
float x = 0.0;
for (int i = 0; i<ctrlPointsCount; i++)
{
int c;
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
{
c = ctrlPointsCount - 1;
}
x += c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsX[i];
}
return x;
}
float getNextBezierPointY(float t)
{
float y = 0.0;
for (int i = 0; i<ctrlPointsCount; i++)
{
int c;
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
{
c = ctrlPointsCount - 1;
}
y += c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsY[i];
}
return y;
}
void drawline()
{
// draw control points using red color
for (int i = 0; i < 3; i++)
{
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
// draw bezier curve using control poitns by calculating next points using cubic bezier curve formula
float oldX = ctrlPointsX[0], oldY = ctrlPointsY[0];
for (double t = 0.0; t <= 1.0; t += 0.01)
{
float x = getNextBezierPointX(t);
float y = getNextBezierPointY(t);
//glColor3f(1.0,t,1.0);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
//Called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}
float _angle = 0.0;
float _cameraAngle = 0.0;
float _ang_tri = 0.0;
//Draws the 3D scene
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //Reset the drawing perspective
ctrlPointsCount = 3;
for (int i = 0; i<3; i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glutSwapBuffers();
}
void update(int value) {
_angle += 2.0f;
if (_angle > 360) {
_angle -= 360;
}
_ang_tri += 2.0f;
if (_ang_tri > 360) {
_ang_tri -= 360;
}
glutPostRedisplay(); //Tell GLUT that the display has changed
//Tell GLUT to call update again in 25 milliseconds
glutTimerFunc(25, update, 0);
}
int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1331, 641);
glutInitWindowPosition(0, 0);
//Create the window
glutCreateWindow("Our cg project");
initRendering();
//Set handler functions
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0); //Add a timer
glClearColor(0.0, 0.7, 1.5,0.0);
glutMainLoop();
return 0;
}
The problem is this here:
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {0.946875, 0.884375, 0.946875 };
for (int i = 0; i<3; i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
ctrlPointsX and ctrlPointsYcan only hold integer values. So when you do ctrlPointsX[i] = X1[i] and ctrlPointsY[i] = Y1[i] you are converting the floats to integers, which will round them down. So all your controlPoints will be 0.
You have to declare the controlPoints arrays as type double too:
double ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {0.946875, 0.884375, 0.946875 };
This should fix your problem.
I am new to opengl. I am doing a simple 2D shooting game and using AABB collision to do collision between objects and bullet. I do the collision for my plane and the square but it doesn't seems to work. Can help me check what's my problem?
#include <iostream>
#include <time.h>
#include <windows.h>
#include <string.h>
#include <math.h>
#include <GL/glut.h>
using namespace std;
#define SPACEBAR 32
class Plane {
public:
GLfloat x = 0.05f;
GLfloat y = 0.95f;
GLfloat width = 0.05f;
GLfloat height = 0.10f;
GLfloat moveX = 0.0f;
GLfloat moveY = 0.0f;
void drawPlane(GLfloat, GLfloat, GLfloat, GLfloat);
};
class Enemy {
public:
GLfloat x, y;
GLfloat width, height;
GLfloat sqrMoveX, sqrMoveY;
void drawEnemySqr(GLfloat, GLfloat, GLfloat, GLfloat);
};
Plane plane;
Enemy enemy;
GLfloat XMax, XMin, YMax, YMin;
GLdouble clipAreaXLeft, clipAreaXRight, clipAreaYBottom, clipAreaYTop;
int refreshMills = 30;
float RandomNumberX() {
float Min = -1.0f;
float Max = 1.0f;
return ((float(rand()) / float(RAND_MAX)) * (Max - Min)) + Min;
}
float RandomNumberY() {
float Min = 0.7f;
float Max = 1.0f;
return ((float(rand()) / float(RAND_MAX)) * (Max - Min)) + Min;
}
void Timer(int value) {
glutPostRedisplay();
glutTimerFunc(refreshMills, Timer, 0);
}
bool collision(GLfloat x1, GLfloat y1, GLfloat w1, GLfloat h1,
GLfloat x2, GLfloat y2, GLfloat w2, GLfloat h2) {
if ((x1 < (x2 + w2)) &&
((x1 + w1) > x2) &&
(y1 < (y2 + h2)) &&
((h1 + y1) > y2)) {
return true;
}
else {
return false;
}
}
void initGL() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
void Plane :: drawPlane(GLfloat planeX, GLfloat planeY, GLfloat planeWidth, GLfloat planeHeight) {
glTranslatef(moveX, moveY, 0.0f);
glBegin(GL_POLYGON);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(-(planeX), -(planeY));
glVertex2f(planeX, -(planeY));
glVertex2f(planeX + planeWidth, -(planeY - planeHeight));
glVertex2f(planeX - (planeWidth), -(planeY - (planeHeight + 0.20f)));
glVertex2f(-(planeX + planeWidth), -(planeY - planeHeight));
glEnd();
if (moveX > XMax) {
moveX = XMax;
}
else if (moveX < XMin) {
moveX = XMin;
}
if (moveY > YMax) {
moveY = YMax;
}
else if (moveY < YMin) {
moveY = YMin;
}
}
void Enemy :: drawEnemySqr(GLfloat enemyX, GLfloat enemyY, GLfloat enemyWidth, GLfloat enemyHeight) {
glTranslatef(sqrMoveX, sqrMoveY, 0.0f);
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex2f(enemyX, enemyY);
glVertex2f(enemyX + enemyWidth, enemyY);
glVertex2f(enemyX + enemyWidth, enemyY + enemyHeight);
glVertex2f(enemyX, enemyWidth + enemyY);
glEnd();
sqrMoveY -= 0.0005f;
if (sqrMoveY < -1.8f) {
sqrMoveX = RandomNumberX();
sqrMoveY = RandomNumberY();
}
glutPostRedisplay();
}
void display() {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glPushMatrix();
plane.drawPlane(plane.x, plane.y, plane.width, plane.height);
glPopMatrix();
glPushMatrix();
enemy.drawEnemySqr(0.0f, 0.0f, 0.3f, 0.3f);
glPopMatrix();
if (collision(plane.moveX, plane.moveY, plane.width, plane.height,
enemy.sqrMoveX, enemy.sqrMoveY, enemy.width, enemy.height) == true) {
enemy.sqrMoveY = -2.0f;
}
glutSwapBuffers();
}
void keyButton(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT:
plane.moveX += 0.05f;
break;
case GLUT_KEY_LEFT:
plane.moveX += -0.05f;
break;
case GLUT_KEY_UP:
plane.moveY += 0.05f;
break;
case GLUT_KEY_DOWN:
plane.moveY += -0.05f;
break;
default:
break;
}
glutPostRedisplay();
}
int main(int argc, char** argv) {
srand(time(NULL));
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(480, 640);
glutInitWindowPosition(50, 50);
glutCreateWindow("Plane Shooting Game");
glutDisplayFunc(display);
glutIdleFunc(idle);
glutReshapeFunc(reshape);
glutTimerFunc(25, Timer, 0);
glutSpecialFunc(keyButton);
initGL();
glutMainLoop();
return 0;
}
You have a problem in this line:
if (collision(plane.moveX, plane.moveY, plane.width, plane.height,
enemy.sqrMoveX, enemy.sqrMoveY, enemy.width, enemy.height) == true)
You must pass plane.x, plane.y, enemy.x, enemy.y to collision function instead of plane.moveX, plane.moveY, enemy.sqrMoveX, enemy.sqrMoveY.
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'm working in a little OpenGL - GLUT program (i'm totally noob), and i'm having many problems switching between gluPerspective and glOrtho pressing a key (for example 'p').
I've take some screenhots to illustrate the problem... using gluPerspective and glOrtho
And here's my code...
#if defined(__APPLE__)
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#else
#include <GL/gl.h>
#include <GL/greeglut.h>
#endif
#include <iostream>
#include <math.h>
#include "model.h"
using namespace std;
// actual vector representing the camera\'s direction
float lx = 0.0f,lz = -1.0f;
// XZ position of the camera
float x = 0.0f,z = 5.0f;
// angle for rotating triangle
float angle = 0.0f;
float fov = 45.0;
Model m;
Model m1;
Model m2;
Model m3;
double maxX, maxY, maxZ;
double minX, minY, minZ;
double centX, centY, centZ;
double maxTam;
bool persp = true;
double min(double x, double y) {
if(x < y) return x;
return y;
}
double max(double x, double y) {
if(x > y) return x;
return y;
}
void setMinMaxXYZ(void) {
maxX = minX = m.vertices()[0];
maxY = minY = m.vertices()[1];
maxZ = minZ = m.vertices()[2];
for(int i = 3; i < m.vertices().size(); i += 3) {
maxX = max(maxX,m.vertices()[i]);
minX = min(minX,m.vertices()[i]);
maxY = max(maxY,m.vertices()[i+1]);
minY = min(minY,m.vertices()[i+1]);
maxZ = max(maxZ,m.vertices()[i+2]);
minZ = min(minZ,m.vertices()[i+2]);
}
centX = ((maxX - minX)/2) + minX;
centY = ((maxY - minY)/2) + minY;
centZ = ((maxZ - minZ)/2) + minZ;
}
void changeView(void) {
int w = glutGet(GLUT_WINDOW_WIDTH);
int h = glutGet(GLUT_WINDOW_HEIGHT);
float ratio = w * 1.0 / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(persp) gluPerspective(fov, ratio, 0.1f, 100.0f);
else glOrtho(-1,1,-1,1,-0.5,100.0);
glMatrixMode(GL_MODELVIEW);
}
void changeSize(int w, int h) {
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0) h = 1;
if(w == 0) w = 1;
float ratio = w * 1.0 / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(persp) gluPerspective(fov, ratio, 0.1f, 100.0f);
else glOrtho(-1,1,-1,1,0.1,100.0);
glViewport(0,0,w,h);
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glLoadIdentity();
// Posicionament de la càmera
gluLookAt( x, 1.0f, z,
x+lx, 1.0f, z+lz,
0.0f, 1.0f, 0.0f);
glClearColor(0.5,0.5,1.0,1.0);
// dibuix terra
glColor3f(0.0f, 255.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-5.0f, 0.0f, -5.0f);
glVertex3f(-5.0f, 0.0f, 5.0f);
glVertex3f( 5.0f, 0.0f, 5.0f);
glVertex3f( 5.0f, 0.0f, -5.0f);
glEnd();
// Models .obj
for (int i = 0; i < 3; ++i) {
float transX, transY, transZ;
if(i == 0) {
m = m1;
transX = -1.25; transY = 0.5; transZ = -2.0;
} else if(i == 1) {
m = m2;
transX = -0.5; transY = 0.5; transZ = 2.5;
} else {
m = m3;
transX = 2.5; transY = 0.25; transZ = -0.5;
}
setMinMaxXYZ();
maxTam = max(max(maxX - minX, maxY - minY), maxZ - minZ);
glPushMatrix();
glTranslated(-(centX / maxTam), -(centY / maxTam), -(centZ / maxTam));
glTranslated(transX,transY,transZ);
glScaled(1.0/maxTam,1.0/maxTam,1.0/maxTam);
glBegin(GL_TRIANGLES);
for(int i = 0; i < m.faces().size(); i++){
const Face &f = m.faces()[i];
glColor3f(Materials[f.mat].diffuse[0],Materials[f.mat].diffuse[1],Materials[f.mat].diffuse[2]);
for(int j = 0; j < 3; j++)
glVertex3dv(&m.vertices()[f.v[j]]);
}
glEnd();
glPopMatrix();
}
glutSwapBuffers();
}
void processKeys(unsigned char key, int x, int y) {
if (key == 27)
exit(0);
else if(key == 'p'){
persp = not persp;
changeView();
}
}
void processSpecialKeys(int key, int xx, int yy) {
float fraction = 0.1f;
switch (key) {
case GLUT_KEY_LEFT :
angle -= 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
case GLUT_KEY_RIGHT :
angle += 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
case GLUT_KEY_UP :
x += lx * fraction;
z += lz * fraction;
break;
case GLUT_KEY_DOWN :
x -= lx * fraction;
z -= lz * fraction;
break;
}
}
void idle(void) {
glutPostRedisplay();
}
void iniView(void) {
int w = glutGet(GLUT_WINDOW_WIDTH);
int h = glutGet(GLUT_WINDOW_HEIGHT);
float ratio = w * 1.0 / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
//glOrtho(-1,1,-1,1,0.01,1000);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
// init GLUT i creació finestra
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,800);
glutCreateWindow("IDI: Bloc 3 - Càmeres i perspectives");
// Carregar models .obj
m1.load("model/legoman-assegut.obj");
m2.load("model/Shaun_Hastings.obj");
m3.load("model/porsche.obj");
// crides
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(idle);
glutKeyboardFunc(processKeys);
glutSpecialFunc(processSpecialKeys);
iniView();
// OpenGL init
glEnable(GL_DEPTH_TEST);
// loop
glutMainLoop();
return 1;
}
It's supposed that i should see the green "floor" in the glOrtho view... what i'm doing wrong??
ps. Model objects are .obj files delivered by the teacher.
edit:
Finally, the glOrtho works properly. But now... i've got another question, how can i do to maximize the window and (in glOrtho mode) the image does not deform??
In changeSize() function... when i'm using gluPerspective it works fine, but not with glOrtho!!
the fact that you don't see the floor with orthographic projection is actually expected given the way you set up your modelview matrix:
it happens because your floor is parallel to the XZ plane - and your view vector is, too.
// Posicionament de la càmera
gluLookAt( x, 1.0f, z,
x+lx, 1.0f, z+lz,
0.0f, 1.0f, 0.0f);
the first 3 arguments of gluLookAt are the xyz-components of the camera position, the next 3 arguments are the xyz of the 'center of interest'. the vector between those 2 points is the view vector, and its y-component is 0, meaning it is parallel to XZ and thus your floor.
if you want to see the floor + orthographic projection, you'll have to tilt the camera so that it looks down.
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.