OpenGL Keyboard Camera Controls - c++

I have been following this tutorial series for OpenGL: GLUT:
http://www.lighthouse3d.com/opengl/glut/
I have reached the stage of implementing camera controls using the keyboard:
http://www.lighthouse3d.com/opengl/glut/index.php?8
When doing the advanced tutorial it stops working. I've pretty much just copied and pasted it. When I run its version of the code it works. Mine just doesn't seem to work. It should rotate the camera view when moving left and right and move forward and backwards when using up and down keys.
My code is here broken down:
This part of my code renders components in the scene with init() which initilizes values etc.:
void display(void)
{
if (deltaMove)
moveMeFlat(deltaMove);
if (deltaAngle) {
angle += deltaAngle;
orientMe(angle);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texture[0]);
RenderSkyDome();
glBindTexture(GL_TEXTURE_2D, NULL);
glutSwapBuffers();
}
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0f);
glColor3f(0.0, 0.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
LoadTextures("clouds2.bmp", 0);
GenerateDome(600.0f, 5.0f, 5.0f, 1.0f, 1.0f);
snowman_display_list = createDL();
}
This is my main loop function:
int main ()
{
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(800, 600);
glutInitWindowPosition(0, 0);
glutCreateWindow("Captain Ed's Adventures: Great Wall of China");
init();
//Glut Input Commands
glutIgnoreKeyRepeat(1);
glutSpecialFunc(pressKey);
glutSpecialUpFunc(releaseKey);
glutKeyboardFunc(processNormalKeys);
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape); // This redraws everything on screen when window size is changed.
glutMainLoop();
return 0;
}
Here are my input functions which are called:
void pressKey(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT : deltaAngle = -0.10f;break;
case GLUT_KEY_RIGHT : deltaAngle = 0.10f;break;
case GLUT_KEY_UP : deltaMove = 50;break;
case GLUT_KEY_DOWN : deltaMove = -50;break;
}
}
void releaseKey(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT : if (deltaAngle < 0.0f)
deltaAngle = 0.0f;
break;
case GLUT_KEY_RIGHT : if (deltaAngle > 0.0f)
deltaAngle = 0.0f;
break;
case GLUT_KEY_UP : if (deltaMove > 0)
deltaMove = 0;
break;
case GLUT_KEY_DOWN : if (deltaMove < 0)
deltaMove = 0;
break;
}
}
void processNormalKeys(unsigned char key, int x, int y) {
if (key == 27)
exit(0);
}
Variables that get used by the camera and the functions that should change it:
static float angle=0.0,deltaAngle = 0.0,ratio;
static float x=0.0f,y=1.75f,z=5.0f;
static float lx=0.0f,ly=0.0f,lz=-1.0f;
static int deltaMove=0;
void orientMe(float ang) {
lx = sin(ang);
lz = -cos(ang);
glLoadIdentity();
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}
void moveMeFlat(int i) {
x = x + i*(lx)*0.1;
z = z + i*(lz)*0.1;
glLoadIdentity();
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}
I believe that's pretty much everything I am working with so basically what should happen is that when I press UP key deltaMove should = 50 and when this happens the if statement in void display(void) should do moveMeFlat(deltaMove); I don't know if I am doing this wrong or if there is a better result....
I can move "moveMeFlat(deltaMove)" within the relevant switch cases but this does not allow me to have the movement that I want. It seems to work using the source code from the tutorials above with the right functionality but not in my case so my assumption is that it's to do with the if statement in display.
The end result I am looking for is to be able to have forwards and backwards working with left and right rotating the camera. I would like to be able to press forward and left key and see the camera swerve left like in a racing game...

Try getting rid of static in front of all of your global variable declarations.
The last use of static is as a global variable inside a file of code. In this case, the use of static indicates that source code in other files that are part of the project cannot access the variable. Only code inside the single file can see the variable. (It's scope -- or visibility -- is limited to the file.) This technique can be used to simulate object oriented code because it limits visibility of a variable and thus helps avoid naming conflicts. This use of static is a holdover from C.
-http://www.cprogramming.com/tutorial/statickeyword.html
Also, instead of this:
if (deltaMove)
moveMeFlat(deltaMove);
if (deltaAngle) {
angle += deltaAngle;
orientMe(angle);
}
try this:
if (deltaMove != 0)
moveMeFlat(deltaMove);
if (deltaAngle != 0.0) {
angle += deltaAngle;
orientMe(angle);
}

Is GLUT idle when a key press is occurring? I think it is not idle. Your display() function is only called when the window is created and when GLUT is idle, which doesn't allow your position to be changed.
I suggest adding:
glutTimerFunc(40, display, 1);
to the end of your display function. This will cause display to be called every 40 milliseconds.
Also, don't register display as the idle function, or you'll have the idle function starting lots of series of timer functions.
P.S. I would call glFlush(); just before swapping the buffers in your display function.

Related

How to add delay between the movement of two disks

I'm currently doing an assignment in OpenGL and what I'm supposed to do is make two disks and then as I move the cursor on the screen and click the two disks should move to that position where I click on the window but the trick is that both the disks should not move together. The first disk should move and then after a small delay the second disk should move. Now I have been able to make both the disks move together at the point I click. What I want to know is how am I supposed to add a delay in the movement of both the disks. Please help!
This is my current code. Thanks!
EDIT:
Here's my updated code after implementing exactly what you said and now none of the disks are moving. If you understand the problem, fine otherwise thanks for all the help :)
#include <math.h>
#include <cstdlib>
#include <glut.h>
typedef struct _Vector
{
double x,y,z;
} Vector;
const int W_SCREEN = 1366;
const int H_SCREEN = 768;
const double PI = 3.14159265;
GLUquadric *qobja;
double speed = 10;
double radian;
double rot;
Vector pos2;
Vector pos;
Vector vel;
Vector dis;
Vector dir;
Vector mousecoords;
void mouse(int button, int state, int x , int y)
{
mousecoords.x = x - W_SCREEN/2;
mousecoords.y = -y + H_SCREEN/2;
}
void move()
{
dis.x = mousecoords.x - pos.x;
dis.y = mousecoords.y - pos.y;
if(sqrt(dis.x*dis.x + dis.y*dis.y) < speed)
{
pos.x = mousecoords.x;
pos.y = mousecoords.y;
pos2.x = mousecoords.x;
pos2.y = mousecoords.y;
}
else
{
radian = atan2(dis.y,dis.x);
pos.x += cos(radian)*speed;
pos.y += sin(radian)*speed;
pos2.x += cos(radian)*speed;
pos2.y += sin(radian)*speed;
}
}
void moveSecondDisk(int value)
{
// Code that moves (updates coordinates) of second disk
move();
glutPostRedisplay();
}
void moveFirstDisk(int value)
{
// Code that moves (updates coordinates) of first disk
move();
glutPostRedisplay();
unsigned int secondDiskDelay = 5000;
glutTimerFunc(secondDiskDelay, moveSecondDisk, 0);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glOrtho(-W_SCREEN/2,W_SCREEN/2,-H_SCREEN/2,H_SCREEN/2,-100,100);
qobja = gluNewQuadric();
gluQuadricNormals(qobja, GLU_SMOOTH);
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,25,50,0,100,100);
glPopMatrix();
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos2.x,pos2.y,0);
gluCylinder(qobja,50.5,65,0,100,100);
glPopMatrix();
/*glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,65.5,80,0,100,100);
glPopMatrix();
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,80.5,90,0,100,100);
glPopMatrix();
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,90.5,100,0,100,100);
glPopMatrix();
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,100.5,110,0,100,100);
glPopMatrix();
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,110.5,120,0,100,100);
glPopMatrix();
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,120.5,130,0,100,100);
glPopMatrix();
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,130.5,140,0,100,100);
glPopMatrix();
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,140.5,150,0,100,100);
glPopMatrix();
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,150.5,160,0,100,100);
glPopMatrix();
glPushMatrix();
glColor3f(0,0,0);
glTranslated(pos.x,pos.y,0);
gluCylinder(qobja,160.5,170,0,100,100);
glPopMatrix();*/
glFlush();
glutSwapBuffers();
glutPostRedisplay();
}
void init(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(W_SCREEN,H_SCREEN);
glutCreateWindow("ORCA WHALE SIMULATION");
glutDisplayFunc(display);
glutMouseFunc(mouse);
unsigned int firstDiskDelay = 2000;
glutTimerFunc(firstDiskDelay, moveFirstDisk, 0);
glClearColor(1,1,1,1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
init();
glutMainLoop();
return(0);
}
Use a timer to accomplish this. Create a function that moves the second disk with the following signature:
void moveSecondDisk(int value);
Then, execute the code that moves the first disk. Finally, call function glutTimerFunc, passing it the function moveSecondDisk as callback (second parameter). The first parameter will be delay between moving of two discs (expressed in miliseconds), and the third one will be value that is passed the callback function. Note that you can pass complex data to callback function by passing a pointer to a complex structure (or an object) as an integer, then casting it back to the desired type in the callback function. For more info, check the following links:
https://www.opengl.org/resources/libraries/glut/spec3/node64.html
https://www.opengl.org/discussion_boards/showthread.php/170990-glutTimerFunc
EDIT:
A more detailed explanation:
void movePos()
{
// Code that only modifies pos
...
}
void movePos2()
{
// Code that only modifies pos2
...
}
void moveSecondDisk(int value)
{
movePos2();
glutPostRedisplay();
}
void moveFirstDisk(int value)
{
movePos();
glutPostRedisplay();
unsigned int secondDiskDelay = 200;
glutTimerFunc(secondDiskDelay, moveSecondDisk, 0);
glutTimerFunc(300, moveFirstDisk, 0);
}
void init()
{
...
unsigned int firstDiskDelay = 50;
glutTimerFunc(firstDiskDelay, moveFirstDisk, 0);
...
}

I can't use user input to change z-coordinates of a triangle using GLUT?

I'm trying to use GLUT and OpenGL to draw a triangle that will change its z-coordinates based off a user input. I can't get it working though; no compiler errors, but the triangle doesn't change when I press those keys. Does anyone know why?
/////////////////////////////
/////OPENGL ASSIGNMENT 1/////
/////////////////////////////
#include <iostream>
#include <stdlib.h> //Needed for "exit" function
#include <GL/glut.h>
using namespace std;
/////GLOBAL VARIABLES/////
float zCoord = -10.0;
////Function Declarations/////
void initRendering();
void windowResize(int width, int height);
void keyBoardEvents(unsigned char key, int x, int y); ///this is the function that will use user input
void drawing(); /// Note: this is the function we will use to draw shapes using opengl functions
////Function Definitions/////
void initRendering()
{
glEnable(GL_DEPTH_TEST);
}
void windowResize(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double) width/ (double) height, 1.0, 200.0); ////Note: 45.0 is the camera angle, w/h is the aspect ratio///
}
void keyBoardEvents(unsigned char key, int x, int y)
{
switch (key)
{
case 27: exit(0);
break;
case 'w': zCoord = zCoord + 5.0f;
break;
case 's': zCoord = zCoord - 5.0f;
break;
case 'r': zCoord = -5.0f;
break;
}
if (zCoord < -30.0) ////// here we ensure -5.0 > zCoord > -30.0
{
zCoord = 30.0;
}
else if (zCoord > -5.0)
{
zCoord = -5.0;
}
}
void drawing()
{
//Standard OpenGL at the beginning of each drawing() function:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
///Specifically to this one, drawing the rectangle:
glBegin(GL_TRIANGLES); ////here we say start grouping the next 3 statements as 3 vertices of a triangle
glVertex3f(-0.5f, 0.5f, (float)zCoord);
glVertex3f(-1.0f, 1.5f, (float)zCoord);
glVertex3f(-1.5f, 0.5f, (float)zCoord);
glEnd;
glutSwapBuffers();
}
int main(int argc, char** argv) ////here we are passing some initial arguments to main, that the user does not have to input
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE ); ///initiates things like depth (DEPTH) and color (RGB)/////
glutInitWindowSize(400, 400); /////the initial window size
glutCreateWindow("MentorAssignment_1"); /////here we using an OpenGL function to make a window of title MentorAssignment_1
initRendering();
//////HANDLER FUNCTIONS///// ////These are functions that call other functions, like keyBoardEvents and drawing, every time glutMainLoop() runs
glutKeyboardFunc(keyBoardEvents);
glutDisplayFunc(drawing);
glutReshapeFunc(windowResize);
glutMainLoop(); ///The openGL function that ensures main runs infinitely! (until escape is pressed)
return 0;
}
You're missing parentheses after glEnd, which means you're not calling the function, just taking its address. Issuing a buffer swap after a glBegin() can likely put OpenGL in error state and cause it to ignore all further rendering commands. The net effect would be the triangle seems not to move, simply because it's no longer redrawn.
You need to call glutPostRedisplay() at the end of your keyBoardEvents function to indicate to GLUT that the frame should be redrawn.

Mouse movement accelerates code execution?

I'm teaching myself how to use OpenGL to create graphics, and I've got a basic spiral script+rotation. The Y-Axis rotation is automatic based on a timer function, but I noticed that when I move my mouse inside the window, it seems to rotate faster than intended. Could someone please look over my script and tell me what is causing the acceleration of the timer function?
#include <Windows.h>
#include <glut.h>
#include <stdio.h>
#include <math.h>
// Change viewing volume and viewport. Called when window is resized
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat nRange = 100.0f;
//Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Reset projection matrix stack
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Establish clipping volume (left, right, buttom, top, near, far)
if (w<= h)
glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
else
glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);
//Reset Model view matrix stack
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//Define a constant for pi
#define GL_PI 3.1415f
// This function does all the initialization
void SetupRC()
{
// Black background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
// Set drawing color to green
glColor3f(0.0f, 1.0f, 0.0f);
}
// Test declaration of rotation angle
GLfloat xRot = 0;
GLfloat yRot = 0;
// Modifiable variables for the eccentricity
GLfloat xMod = 50.0f;
GLfloat yMod = 50.0f;
// Called to draw scene
void RenderScene(void)
{
GLfloat x,y,z,angle; // Storage for coordinates and angles
GLfloat sizes[2]; // Store supported point size range
GLfloat step; // Store point size increments
GLfloat curSize; //Store current point size
// Get supported point size range and step size
glGetFloatv(GL_POINT_SIZE_RANGE, sizes);
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &step);
//Set the initial point size
curSize = sizes[0];
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT);
// Save matrix state and do the rotation
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
// specify point size before primitive is specified
glPointSize(curSize);
//Call only once for remaining points
glBegin(GL_LINE_STRIP);
//Set beginning z coordinate
z = -50.0f;
//Loop around in a circle three times
for (angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f)
{
// Calculate x and y values on the circle (the major and minor axis)
x = xMod*sin(angle);
y = yMod*cos(angle);
// Specify the point and move the z value up a little
glVertex3f(x, y, z);
z += 0.5f;
}
// Done drawing points
glEnd();
// Restore transformations
glPopMatrix();
//Flush drawing commands
glFlush();
}
// Modifier Code
void CircleController (int key, int x, int y)
{
switch (key)
{
case 27 : break;
case 100 :
(yRot -= 5.0f); ; break;
case 102 :
(yRot += 5.0f); ; break;
case 101 :
(xRot -= 5.0f); ; break;
case 103 :
(xRot += 5.0f); ; break;
glutDisplayFunc(RenderScene);
}
}
void MouseHandler (int button, int state, int x, int y)
{
// Holder variable assigned to overcome printf limitation and prevent double- printing due to MouseUp function call
GLfloat Holder = xMod;
// Increases size, and decreases timer speed by increasing the amount of time needed.
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
xMod+= 5.0f;
}
// Decreases size, and increases timer speed by decreasing the amount of time needed.
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
{
xMod-= 5.0f ;
}
if (Holder != xMod)
printf("%d \n", Holder);
}
void TimerFunction(int value)
{
//Call the arrow key function
glutSpecialFunc(CircleController);
//Call the Mouseclick Modifier function
glutMouseFunc(MouseHandler);
if (xRot < 360)
(xRot += 1.0f);
else
(xRot = 0.0f);
// Redraw the scene with new coordinates
glutPostRedisplay();
glutTimerFunc(1.6666f, TimerFunction, 1);
}
void main(void)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("Drawing Lines");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
glutTimerFunc(1.6666f, TimerFunction, 1);
SetupRC();
glutMainLoop();
}
Eric Palace gave me the start
My personal theory was always that it had something to do with the window focus and which program is given more CPU time, but that's just pure speculation.
That makes sense to me. But wait, don't you only paint on a timer? Wouldn't that prevent additional CPU time from modifying movement speed? Yes you do. Sortof.
glutTimerFunc(1.6666f, TimerFunction, 1);
The doc's for glutTimerFunc say that the first parameter is an unsigned int, representing the timer in milliseconds. So you're telling glut "call this function every 1 millsecond." (Approx 1000FPS) And since it takes longer than one millisecond to execute, you're effectively telling it "run this function over and over as fast as you possibly can". Which it does. And so additional CPU time is making a difference.
To avoid situtations like this (aside from correcting the 1.6666f parameter), it's usually suggested to
update the "world" in separate functions from painting the screen. In fact, I would imagine it to be common to have two or more world update functions. One for stuff that needs updating with the paint: arrows and running characters, one for stuff that only changes once a second or so: mana regen and npc decisions, and one for really slow stuff: respawns.
During an "update", check how much time has passed since the last update, (maxing out at half a second or so), and make the world update that much. Then if updates run twice as often or half as often for any reason, the game doesn't appear to speed up or slow down, you just just more/fewer frames instead.
Here's what such an update might look like
radians xrot = 0; //use a units class
radians rot_per_second = .01;
void updateFrame(double time_passed) {
assert(time_passed>=0 && time_passed <= 1.0);
radians rotate_thistime = rot_per_second * time_passed;
xrot += rotate_thistime;
}
void do_updates() {
static clock_t lastupdatetime = clock()-1; //use openGL functions instead of C
clock_t thisupdatetime = clock();
double seconds = double(thisupdatetime-lastupdatetime)/CLOCKS_PER_SEC;
if (seconds > 0.5) //if something happened and haven't update in a long time
seconds = 0.5; //pretend only half a second passed.
//this can happen if
// computer is overloaded
// computer hibernates
// the process is debugged
// the clock changes
if (seconds <= 0.0) //computer is REALLY fast or clock changed
return; //skip this update, we'll do it when we have sane numbers
updateFrame(seconds);
lastupdatetime = thisupdatetime;
}

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.

How to move triangle on plane in opengl

I want to move triangle on plane.How will i do it.I am using opengl "glut" and also i want to keep co-ordinate position of triangle.first time it will start at point (0,0,-6) and then when i will press "a" this will move left and when i will press "d" this will move "right".I know the keyoperation definition in opengl of "w" and "s".But my main concern is with movment and knwoing of co-ordinate points.
Thankie
Use global variables to store your programs state. One of these states is the triangle position. Modify this variable in the keyboard handler, then call glutPostRedisplay. In the display function draw the scene according to the program's state.
Important hints: OpenGL is "merely" a sophisticated rasterizer API, which means it "lives for the moment", i.e. you just draw triangles with it, and after you sent the rendering command and they've been processed OpenGL has no "persistency" about the sent geometry and the only trace left are the changes in the framebuffer.
If what you're looking for is more along the lines of "I want to describe a scene consisting of geometric objects and those shall interact through some black box mechanism" you're looking for a so called scene graph, which OpenGL is not (but many scene graphs use OpenGL as a backend).
EDIT: Full example source code
#include <GL/gl.h>
#include <GL/glut.h>
#define ORTHO_SCALE 10.
GLfloat triangle_vertices[] = {
-0.5, 0.0,
0.5, 0.0,
0.0, 1.0
};
struct {
struct {
struct {
GLfloat x, y;
} pos;
GLfloat rot;
} triangle;
} sceneinfo;
void display(void);
void keyboard(unsigned char key, int x, int y);
void special(int key, int x, int y);
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("simple triangle test");
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutSpecialFunc(special);
glutMainLoop();
return 0;
}
void display(void)
{
GLuint win_width, win_height;
GLfloat win_aspect;
win_width = glutGet(GLUT_WINDOW_WIDTH);
win_height = glutGet(GLUT_WINDOW_HEIGHT);
win_aspect = (float)win_width/(float)win_height;
glViewport(0, 0, win_width, win_height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-win_aspect * ORTHO_SCALE,
win_aspect * ORTHO_SCALE,
-ORTHO_SCALE,
ORTHO_SCALE,
-1., 1.);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(sceneinfo.triangle.pos.x, sceneinfo.triangle.pos.y, 0.);
glRotatef(sceneinfo.triangle.rot, 0, 0, 1.);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, triangle_vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glPopMatrix();
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y)
{
switch(key) {
case '+':
sceneinfo.triangle.rot += 2.;
break;
case '-':
sceneinfo.triangle.rot -= 2.;
break;
}
glutPostRedisplay();
}
void special(int key, int x, int y)
{
switch(key) {
case GLUT_KEY_LEFT:
sceneinfo.triangle.pos.x -= 0.2;
break;
case GLUT_KEY_RIGHT:
sceneinfo.triangle.pos.x += 0.2;
break;
case GLUT_KEY_UP:
sceneinfo.triangle.pos.y += 0.2;
break;
case GLUT_KEY_DOWN:
sceneinfo.triangle.pos.y -= 0.2;
break;
}
glutPostRedisplay();
}