Calculating gluLookAt, glOrtho and glFrustum - c++

I am working on an assignment to draw wire frame GLUT standard objects. This seems simple but we are told we cannot use gluAtLook(), glOrtho(), glFrustrum but we must use glTranslate(), glScale() and glRotate. How to you project the object without using these functions in glMatrixMode(GL_PROJECTION)?
This is what I have so far:
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <math.h> // for sqrt()
#include <glut.h>
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glLoadIdentity(); /* clear the matrix */
/* viewing transformation */
glTranslatef(0.0, 0.0, -5.0);
glScalef(1.0, 2.0, 1.0); /* modeling transformation */
glutWireCube(1.0);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
//glTranslatef(0.0, 0.0, -5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Can someone please help with this?

we are told we cannot use gluAtLook(), glOrtho(), glFrustrum but we must use glTranslate(), glScale() and glRotate
gluLookAt sets up the world to view space transformation, glOrtho does view to orthographic projection space transformation and glFrustum does view to perspective projection space transformation. When you say your tutor hasn't allowed to use it, it clearly means that the intention is to understand how these functions work in the first place.
There're many resources on the internet which teach you that. Here's one by a renowned UC Berkeley professor Dr. Ravi Ramamoorthi. SongHo has good articles which will help you do the same thing.
I can demonstrate a simple case in 2D. Say we've a world defined with objects (for simplicity we take a point P); we want the camera to be at (3, 3) with its X and Y axes pointing in directions opposite to world's X and Y axes. For simplicity we'll assume both frames have the same scaling factor i.e. 1 unit in both X and Y directions measure the same distance (magnitude) for both systems. So the two frames differ only by orientation and origin location (W0 and V0 are the symbols denoting them).
We need to derive Mworld->view i.e. the matrix which maps points in world space to view space. This is what the now-deprecated gluLookAt function calculates and multiplies with GL_MODELVIEW matrix stack. This matrix will be used to get a view of the world from the camera's viewpoint.
We know that Mworld->view = Tview->world. The matrix which maps points of frame A to frame B will also be the matrix which transforms B's frame into A's frame. The derivation goes like this
The point P in world has (1, 2) = Pw as coordinates, we're effectively finding a matrix, which when multiplied with Pw will give Pv i.e. the same point's coordinates in view frame. The point is written as a 3D point since homogeneous extension of a 2D point would be a 3D point; the homogeneous coordinate would be 1 since it's a point; had it been a vector, it'd be 0.
Step one is rotation; rotating view's frame by -180° (right-handed system where +ve rotation is counter-clockwise); now the axes are along the same direction for both frames. We've to tackle the origin difference, this is done by translation, which is step 2. Multiplying both will give the required matrix. Note that each step transforms the view's frame more closer into world's frame by post-multiplying. Also each transformation is based on that current local frame we're in and not based on the starting global (world) frame.
The same idea can be extended to 3D too, with some more effort. In the above derivation all I needed were just rotation matrix, translation matrix and matrix multiplication; no gluLookat.The links I gave you should help in calculating the same for 3D. The projection matrix derivation is a bit more involved. However, you can still achieve the result without using glOrtho; the links I gave above has the formula for the final matrix; you can compose a matrix using that and multiply that to the GL_PROJECTION matrix stack.
Note: The above derivation assumes column vectors and thus transformation matrices (like rotation) and multiplication order are done based on that. If you assume row vector convention then transpose all the matrices and reverse the order of multplication since
(AB)^T = B^T A^T

What you need to do is compute your own projection matrix and model-view matrix. After that you can load them using glLoadMatrix right after you call glLoadIdentity.

#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <math.h> // for sqrt()
#include <glut.h>
static GLfloat Xvalue = 0.0f;
static GLfloat Yvalue = 0.0f;
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
static GLfloat zRot = 0.0f;
static GLfloat xScale = 1.0f;
static GLfloat yScale = 1.0f;
static GLfloat zScale = 1.0f;
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glShadeModel(GL_FLAT);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glLoadIdentity(); //clear the matrix
glTranslatef(Xvalue, Yvalue, -3.0); // viewing transformation
glScalef(xScale, yScale, zScale); // modeling transformation
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glRotatef(zRot, 0.0f, 0.0f, 1.0f);
glutWireCube(1.0);
glFlush();
}
void reshape(int w, int h)
{
GLfloat identity[16] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 };
if (h == 0) // don't want a divide by zero
{
h = 1;
}
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(identity);
GLfloat fovy = 52.0f; // in degrees
GLfloat c = 1.0 / (GLfloat)tan(fovy / 4.0), a = (GLfloat)w / (GLfloat)h, n = 1.0f, f = 1000.0f;
GLfloat projection[16] = { c / a, 0.0, 0.0, 0.0,
0.0, c, 0.0, 0.0,
0.0, 0.0, -(f + n) / (f - n), -1.0,
0.0, 0.0, -2.0*f*n / (f - n), 0.0 };
glMultMatrixf(projection);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyInput(unsigned char key, int x, int y)
{ // Keyboard input processing routine.
switch (key)
{
case 'b': // move left
Xvalue -= 0.1;
glutPostRedisplay();
break;
case 'B': // move right
Xvalue += 0.1;
glutPostRedisplay();
break;
case 'c': // move down
Yvalue -= 0.1;
glutPostRedisplay();
break;
case 'C': // move up
Yvalue += 0.1;
glutPostRedisplay();
break;
case 'e': // scale down
zScale -= 0.1;
xScale -= 0.1;
yScale -= 0.1;
glutPostRedisplay();
break;
case 'E': // scale up
zScale += 0.1;
xScale += 0.1;
yScale += 0.1;
glutPostRedisplay();
break;
case 'f': // rotate x axis CW
xRot -= 5.0f;
glutPostRedisplay();
break;
case 'F': // rotate x axis CCW
xRot += 5.0f;
glutPostRedisplay();
break;
case 'g': // rotate y axis CW
yRot -= 5.0f;
glutPostRedisplay();
break;
case 'G': // rotate y axis CCW
yRot += 5.0f;
glutPostRedisplay();
break;
case 'h': // rotate z axis CW
zRot -= 5.0f;
glutPostRedisplay();
break;
case 'H': // rotate z axis CCW
zRot += 5.0f;
glutPostRedisplay();
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyInput);
glutMainLoop();
return 0;
}

Related

New Coordinates of the vertices after appliying glTranslatef and glRotatef (OpenGL, C++)

First of all, let me tell i am quite new using OpenGL and C++. However, i want to get involved with this two topics.
So let me explain my case, ive been searching how to get the new coordinates of an object after glTrasnlatef and glRotatef were applied. However, i did not find the find info, actually i found some info about java but i am not getting it, as i told you i am working with C++.
I read there is something to deal with the glPushMatrix(); function but idont know how to handle it.
I know that after applying some trnaslation and rotation i am doing changes into the actual matrix.
Finally, the main purpose of this is because ill use those vertices from the rombohedrom and do a lot of translations and rotations, those are going to be needed as well.
So far this is my code (BTW i am working with lines and the vertices of course because i only need those).
i will really appreciate if someone can address me through the right path.
Thanks in advance
Alberto
#include <GL/glut.h>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
// Global variables
double rotate_y=0;
double rotate_x=0;
int width = 640;
int height = 640;
#define PI 3.14159265
float theta = 60;
float edgeLength = 1;
float sinThetaOverHypotenuse = (sin((theta*PI)/180))/edgeLength;
vector<vector<float>> coordinates{{0.0, 0.0, 0.0},
{1.0, 0.0, 0.0},
{1.0, 0.0, 0.0},
{1.5, sinThetaOverHypotenuse, 0.0},
{1.5, sinThetaOverHypotenuse, 0.0},
{0.5, sinThetaOverHypotenuse, 0},
{0.5, sinThetaOverHypotenuse, 0},
{0.0, 0.0, 0.0}};
void rhombohedrom()
{
vector<vector<float>> rotated {};
// glClearColor(1,1,0,0)
// Clear screen and Z-buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH ) / 300.0;
double h = glutGet( GLUT_WINDOW_HEIGHT ) / 300.0;
glOrtho( -1 * w, 1 * w, -1 * h, 1 * h, 10, -10);
glMatrixMode( GL_MODELVIEW );
// Reset transformations
glLoadIdentity();
// Rotate when user changes rotate_x and rotate_y
glRotatef( rotate_x, 1.0, 0.0, 0.0 );
glRotatef( rotate_y, 0.0, 1.0, 0.0 );
/*
FACE 0
FACE 0
FACE 0
FACE 0
*/
// random color side - front
glBegin(GL_LINE_LOOP);
glColor3f( 0.7, 0.3, 0.8 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
/*
FACE 1
FACE 1
FACE 1
FACE 1
*/
glPushMatrix();
glTranslatef(0.0,0.0,0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
glColor3f( 1.0, 1.0, 1.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
/*
FACE 2
FACE 2
FACE 2
FACE 2
*/
glPushMatrix();
glTranslatef(0.5,0.0,sinThetaOverHypotenuse);
glBegin(GL_LINE_LOOP);
glColor3f( 0.5, 0.5, 0.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
/*
FACE 3
FACE 3
FACE 3
FACE 3
*/
glPushMatrix();
glTranslatef(0.5,sinThetaOverHypotenuse,0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
glColor3f( 0.5, 0.0, 0.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void specialKeys(int key, int x, int y)
{
// Right arrow - increase rotation by 5 degree
if (key == GLUT_KEY_RIGHT)
rotate_y += 5;
// Left arrow - decrease rotation by 5 degree
else if (key == GLUT_KEY_LEFT)
rotate_y -= 5;
else if (key == GLUT_KEY_UP)
rotate_x += 5;
else if (key == GLUT_KEY_DOWN)
rotate_x -= 5;
// Request display update
glutPostRedisplay();
}
int main(int argc, char *argv[])
{
// Initialize GLUT and process user parameters
glutInit(&argc,argv);
glutInitWindowSize(width,height);
// Position of the window
glutInitWindowPosition(10,10);
// Request double buffered true color window with Z-buffer
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
// Create window
glutCreateWindow("rhombohedrom");
// Enable Z-buffer depth test
glEnable(GL_DEPTH_TEST);
// Callback functions
glutDisplayFunc(rhombohedrom);
glutSpecialFunc(specialKeys);
//
glutMainLoop();
return 0;
}
First, I want to address some remarks such as:
glPushMatrix() is an old way, try to use the MVP technique which will help you solving your problem. So, you have to write your Vertex Shader and pass the Matrices through what called uniform in OpenGL. Obviously, you have to use new Routines.
glPopMatrix() is also an old routine.
I'm happy to answer your further questions if you want to know more about those remarks.
Use Vertex Shader instead of simple calculus using the CPU!
you can change glTranslatef() and glRotatef() by lookAt so you can change the scale, rotation and translation.
Use Vertex Shader instead of using or stressing the CPU by graphic calculus. Even if you have an Intel integrated GPU

make GLUT application to rotate on keyboard press

guys i try to make an GLUT application that could rotate object on key pressed, but it seems not worked.
#include <stdio.h>
#include <gl/glut.h>
GLfloat rotation = 90.0;
float posX = 0, posY = 0, posZ = 0;
void reshape(int width, int heigth){
/* window ro reshape when made it bigger or smaller*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//clip the windows so its shortest side is 2.0
if (width < heigth) {
glOrtho(-2.0, 2.0, -2.0 * (GLfloat)heigth / (GLfloat)width, 2.0 * (GLfloat)heigth / (GLfloat)width, 2.0, 2.0);
}
else{
glOrtho(-2.0, 2.0, -2.0 * (GLfloat)width / (GLfloat)heigth, 2.0 * (GLfloat)width / (GLfloat)heigth,2.0 , 2.0);
}
// set viewport to use the entire new window
glViewport(0, 0, width, heigth);
}
void rect(){
glBegin(GL_POLYGON);
glVertex2f(-0.2, -0.2);
glColor3f(1.0, 1.0, 0.0);
glVertex2f(-0.2, 0.2);
glColor3f(1.0, 0.0, 1.0);
glVertex2f(0.2, 0.2);
glColor3f(0.0, 1.0, 1.0);
glVertex2f(1.2, -0.2);
glColor3f(1.0, 1.0, 1.0);
glEnd();
}
void display(){
//Clear Window
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(posX,posY,posZ);
rect();
glPopMatrix();
glFlush();
}
void init(){
// set clear color to black
glClearColor(0.0, 0.0, 0.0, 0.0);
// set fill color to white
glColor3f(1.0, 1.0, 1.0);
//set up standard orthogonal view with clipping
//box as cube of side 2 centered at origin
//This is the default view and these statements could be removed
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
}
float move_unit = 10;
int deg = 0;
void keyboardown(int key, int x, int y)
{
switch (key){
case GLUT_KEY_RIGHT:
glRotatef((deg+=move_unit), posX, posY, posZ);;
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
glRotatef(deg-=move_unit, posX, posY, posZ);;
break;
case GLUT_KEY_UP:
glRotatef(deg-=move_unit, posX, posY, posZ);;
break;
case GLUT_KEY_DOWN:
glRotatef(deg+=move_unit, posX, posY, posZ);;
break;
default:
break;
}
glutPostRedisplay();
}
int main(int argc, char** argv){
//initialize mode and open a windows in upper left corner of screen
//Windows tittle is name of program
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Move Test");
glutDisplayFunc(display);
init();
glutSpecialFunc(keyboardown);
glutMainLoop();
}
is there is something i did it wrong?
before, i tried to use the GLUT_KEY_ for moving 2d object and it worked, but when i change the command to glrotatef, it doesn't work.
have any suggestion?
The problem here is, that you override the matrix before it is used. In keyboardown the matrix is set, but at the begin of display the glLoadIdentity(); function is called, which resets the matrix and removes the rotation.
To solve this, you can, e.g., store the rotation angle in a variable. In keyboardown you increase/decrease the angle. When rendering in the display function, you reset the matrix as already done and then add the rotation by calling glRotatef with the previously stored angle.

Keep world within viewport bounds

I am currently trying to create a 2D side scroller and i currently have my "world" drawing (a large white box for the time being), but i cannot figure out any relationship between the edge of the world map and the edge of the viewport to ensure that the viewport is always fully covered by the map.
My basic world drawing code is:
void drawTiles(void)
{
for (int i = 0; i < 50; i++)
{
for (int j = 0; j < 500; j++)
{
glPushMatrix();
glTranslatef(j, -i, 0);
glBegin (GL_QUADS);
glTexCoord2d(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glTexCoord2d(1.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glTexCoord2d(1.0, 1.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2d(0.0, 1.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glPopMatrix();
}
}
}
void display(void)
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(camX, camY, -20); //translate back a bit to view the map correctly (our camera)
drawTiles(); //draw our tiles
glPopMatrix();
glutSwapBuffers();
}
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, 100.0);
glMatrixMode(GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 'w':
camY -= 0.25;
break;
case 's':
camY += 0.25;
break;
case 'a':
camX += 0.25;
break;
case 'd':
camX -= 0.25;
break;
}
}
How would i go about ensuring that when I use WASD and on viewport resize, that i do not translate beyond the bounds of the map (currently 500x50 tiles)?
If you have a planar scene (2D only), it should be sufficient to use an orthographic projection transformation. The projection transformation determines the camera's parameters. In the current state (with the perspective projection) you have a usual pin hole camera with a vertical opening angle of 60°.
An orthographic projection is defined by its edges. Let's say you want your camera to "see" two units to the left, 3 units to the right, 1 unit up and 4 units down. This would be possible, although it might not be reasonable in your case.
The current perspective camera "sees" about 11.5 units up and down. The according width can be calculated from the window dimensions (we do not want to stretch the image). So instead of gluPerspective, use the following:
float halfHeight = 11.5f;
float halfWidth = halfHeight * (GLfloat)w / (GLfloat)h; //based on window aspect ratio
glOrtho(-halfWidth, halfWidth, halfHeight, -halfHeight, -1, 1);
If you want to change the visible area, you just need to adjust the halfHeight. The -1 and 1 are the znear and zfar plane. Everything that is between these planes is visible. Everything else will be cut off. But since you have only 2D content, this should not be relevant.
In your call to glTranslatef(camX, camY, -20);, set the z-coordinate to 0. This is not needed any more, because we have an orthographic view.
Now if you want to check if the map is still visible, do the following. I'll just show the exmple of checking the left/right boundary. The vertical case is similar:
//The camera can see from camX-halfWidth to camX+halfWidth
//You might want to make halfWidth and halfHeight class variables
float leftMapBoundary = 0;
float rightMapBoundary = 500;
//the camera must be
// * at least halfWidth right of the left boundary and
// * at least halfWidth left of the right one:
if(camX < leftMapBoundary + halfWidth)
camX = leftMapBoundary + halfWidth;
if(camX > rightMapBoundary - halfWidth)
camX = rightMapBoundary - halfWidth;
Add the code after the switch in your keyboard function or whenever you move the camera.

Drawing a ball and two cones in OpenGL C++

I have a code where I want to draw a bowl and two cones at a time.
But, it is showing only those cones, not showing the ball.
#include <GL/glut.h>
#include <stdlib.h>
#include <Math.h> // Needed for sin, cos
#define PI 3.14159265f
GLfloat ballRadius = 0.5f; // Radius of the bouncing ball
GLfloat ballX = 0.0f; // Ball's center (x, y) position
GLfloat ballY = 0.0f;
GLfloat ballXMax, ballXMin, ballYMax, ballYMin; // Ball's center (x, y) bounds
GLfloat xSpeed = 0.02f; // Ball's speed in x and y directions
GLfloat ySpeed = 0.007f;
int refreshMillis = 30; // Refresh period in milliseconds
static void resize(int width, int height)
{
const float ar = (float) width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
}
static void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// This is ball's code that is not being drawn.
***glTranslatef(ballX, ballY, 0.0f); // Translate to (xPos, yPos)
// Use triangular segments to form a circle
glBegin(GL_TRIANGLE_FAN);
glColor3f(1.0f, 0.0f, 0.0f); // Blue
glVertex2f(0.0f, 0.0f); // Center of circle
int numSegments = 100;
GLfloat angle;
for (int i = 0; i <= numSegments; i++) { // Last vertex same as first vertex
angle = i * 2.0f * PI / numSegments; // 360 deg for all segments
glVertex2f(cos(angle) * ballRadius, sin(angle) * ballRadius);
}
glEnd();***
//End of ball code
glColor3d(0,1,0);
glPushMatrix();
glTranslated(-1.0,0.5,-6);
glRotated(65, -1.0, 0.0, 0.0);
glutSolidCone(1, 2, 70, 50);
glPopMatrix();
glPushMatrix();
glTranslated(0.0,-1.5,-6);
glRotated(65, -1.0, 3.0, 0.0);
glutWireCone(1,2, 16, 16);
glPopMatrix();
glutSwapBuffers();
}
/* Program entry point */
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(740,580);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Programming Techniques - 3D Cones");
glutReshapeFunc(resize);
glutDisplayFunc(display);
glClearColor(1,1,1,1);
glutMainLoop();
return EXIT_SUCCESS;
}
The reason you don't see the circle is that it's clipped against the near plane. With glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0); you specify that the near plane is at z = -2, and the far plane at z = -100. Anything outside these values are clipped. But by using glVertex2, your z values for the circle vertices are 0, so all of them are clipped. You can fix it by calling glTranslatef(ballX, ballY, -10.0f); instead.
A couple more pointers:
Always reset the matrix mode to GL_MODELVIEW (e.g. in your resize() function). You don't have to, but it's a good convention.
Always glPush/PopMatrix() before modifying the matrix stack (e.g. when translating the circle).
glColor3f(1.0f, 0.0f, 0.0f); // Blue? ;)

Need help in Bowling Game in OpenGL C++

I am creating a bowling game in openGL C++.
What I have done so far that I have drawn a bowl and three points(obstacles).
The bowl is moved upon key-pressed.
I want to make illusion that when the bowl hits those obstacles, they should be dropped. To do this, I have code like when the X and Y co-ordinates of the ball and of those obstacles are same, then the obstacle's X and Y co-ordinates are incremented to make illusion that they are dropped.
Suggest some logic.
This is my code: -
#include <GL/glut.h>
#include <cmath>
#include <stdio.h>
float posX = 0.01, posY = -0.1, posZ = 0,
bx1 = 0.01, by1 = 0.1,
bx2 = 0.06, by2 = 0.1,
bx3 = 0.10, by3 = 0.1;
GLfloat rotation = 90.0;
double x, y, angle;
#define PI 3.1415926535898
GLint circle_points = 50;
void bottle() {
glColor3f(0.0, 0.0, 1.0);
glPointSize(9.0);
glBegin(GL_POINTS);
glVertex3f(bx1, by1, 0.0);
glEnd();
glBegin(GL_POINTS);
glVertex3f(bx2, by2, 0.0);
glEnd();
glBegin(GL_POINTS);
glVertex3f(bx3, by3, 0.0);
glEnd();
glFlush();
}
void circ() {
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_TRIANGLE_FAN);
for (int i = 0; i <= 300; i++) {
angle = 2 * PI * i / 300;
x = cos(angle) / 20;
y = sin(angle) / 20;
glVertex2d(x, y);
}
glEnd();
}
void display() {
glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
bottle();
glPopMatrix();
glPushMatrix();
glTranslatef(posX, posY, posZ);
circ();
glPopMatrix();
glutSwapBuffers();
}
float move_unit = 0.02f;
void keyboardown(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT:
posX += move_unit;
break;
case GLUT_KEY_LEFT:
posX -= move_unit;
break;
case GLUT_KEY_UP:
posY += move_unit;
break;
case GLUT_KEY_DOWN:
posY -= move_unit;
break;
default:
break;
}
if ( posX == bx1 || posX == bx2 ) {
bx1 -= 0.02,by1 += 0.06;
bx2 = 0.02,
by2 += 0.08;
bx3 = 0.04,
by3 += 0.04;
}
glutPostRedisplay();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Practice 1");
glutDisplayFunc(display);
glutSpecialFunc(keyboardown);
glutMainLoop();
}
Instead of calling circ() function inside display you could call
glutIdleFunc(nameOfYourChoice);
in your main function after keyboard function. So that function is calling again and again.
In the above function (nameOfYourChoice) you can manipulate any variables you want for x's and y's. So in that function you can check if there was a collision between objects and if appear collisions you can "drop" things, in this example boxes, via x's and y's in that function.
At the end of that function you have to call
glutPostRedisplay();
Now if you want to get those boxes up again you can use timers(also with your time-step) and then after a certain amount of time you can put those boxes up again via x's and y's obviously.For that you also will need bool variables to know if there was a collision.
So collision happens:
bool flagBox1 = true;
time passed:
bool flagBox1 = false;
//code to put back the dropped object
code in (nameOfYourChoice) function:
if(flagBox1){
//proceed to your actions...
}
All those changes you will pass them in your display function as you did for the circ with
glTranslatef(box1posX, box1posY, box1posZ);
glTranslatef(box2posX, box2posY, box2posZ);
glTranslatef(box3posX, box3posY, box3posZ);
Then render them.
A good practice is to change all your "changeable" variables with a step like a time-step.
In that way the hole movement will be depending on that time-step.
First, moving objects in discrete intervals (something like 'posX += move_unit;') just isn't the way animation is done these days. Instead you should measure the time that passed since the last update/frame and move the object according to that. So if you want to move your ball 50 units per second you would write 'posX += 50.0 * passedTime;'. This guarantees that the movement does not get any faster or slower if fps changes.
Second, what you are asking about is rotating a vector. The most general way of doing this is creating a rotation-matrix and multiplying it with the vector, just google rotation-matrix. In your simple case it should be sufficient to calculate the pole's coordinates using sin() and cos(). You also could use the Matrix-Stack of OpenGL, have look into glRotate(), glPushMatrix() etc.
Third, your question is very general, and the code snippet cant be called snippet anymore. Keep your questions precise and the snippets short.