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);
...
}
Related
I've checked every other related question on this site but none of the solutions have worked for me. I'm simply trying to follow my rectangle, which moves left and right with key presses in OpenGL. Here's my very simple program:
/*Begin useful backend functions/vars*/
/*************************************/
//Window size and refresh rate (60 fps)
int width = 500;
int height = 500;
int interval = 1000 / 60;
//Used to draw rectangles
void drawRect(float x, float y, float width, float height) {
glBegin(GL_QUADS);
glVertex2f(x, y);
glVertex2f(x + width, y);
glVertex2f(x + width, y + height);
glVertex2f(x, y + height);
glEnd();
}
/***********************************/
/*End useful backend functions/vars*/
/*Game vars*/
/***********/
//keycodes
#define keyA 0x41
#define keyD 0x44
//player
int playerWidth = 30;
int playerHeight = 50;
int playerSpeed = 3;
//player starting position
float playerX = width / 2;
float playerY = 25.0f;
/***************/
/*End game vars*/
/*Game specific functions*/
/*************************/
void keyboard() {
//Move player (and camera) on key presses
if (GetAsyncKeyState(keyA)) {
playerX -= playerSpeed;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-playerSpeed,0,0);
}
if (GetAsyncKeyState(keyD)) {
playerX += playerSpeed;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(playerSpeed, 0, 0);
}
}
/********************/
/*End game functions*/
/*Draw and update for window*/
/****************************/
void draw() {
//Initialliy clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//Draw player
drawRect(playerX, playerY, playerWidth, playerHeight);
//Swap buffers to end
glutSwapBuffers();
}
void update(int value) {
// input handling
keyboard();
// Call update() again in 'interval' milliseconds
glutTimerFunc(interval, update, 0);
// Redisplay frame
glutPostRedisplay();
}
/*****************/
/*End draw/update*/
/*Main function*/
/***************/
int main(int argc, char** argv) {
// initialize opengl (via glut)
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(width, height);
glutCreateWindow("My Game");
// Register callback functions
glutDisplayFunc(draw);
glutTimerFunc(interval, update, 0);
// setup scene to be 2d
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//set draw color to white
glColor3f(1.0f, 1.0f, 1.0f);
//start the whole thing
glutMainLoop();
return 0;
}
/*************/
/*End of main*/
The keyboard movement works perfectly, however:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-playerSpeed,0,0);
inside my keyboard() function, does nothing. And if I try it with GL_PROJECTION, it turns my screen black.
First of all note, that drawing by glBegin/glEnd sequences and the fixed function matrix stack is deprecated since decades. See Fixed Function Pipeline and Legacy OpenGL.
Simplify things.
Add a the keyboard events for key up and down (glutKeyboardFunc / glutKeyboardUpFunc). This functions only modifies the speed of the player. The speed is set when a button is pressed and is set 0, when a button is release:
int playerSpeed = 0;
void keyboardDown(unsigned char key, int x, int y)
{
if (key == 'a')
playerSpeed -= 3;
else if (key == 'd')
playerSpeed = 3;
}
void keyboardUp( unsigned char key, int x, int y )
{
playerSpeed = 0;
}
The timer event just modifies the position of the player:
void update(int value)
{
playerX += playerSpeed;
glutTimerFunc(interval, update, 0);
glutPostRedisplay();
}
In draw the model matrix is set and the rectangle is drawn:
void draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(playerX, playerY, 0);
//Draw player
drawRect(0, 0, playerWidth, playerHeight);
//Swap buffers to end
glutSwapBuffers();
}
Set the callback functions in main:
int main(int argc, char** argv)
{
// ...
glutDisplayFunc(draw);
glutTimerFunc(interval, update, 0);
glutKeyboardFunc( keyboardDown );
glutKeyboardUpFunc( keyboardUp );
// ...
}
#include <stdio.h> // this library is for standard input and output
#include "glut.h"// this library is for glut the OpenGL Utility Toolkit
#include <math.h>
float squareX = 0.0f;
float squareY = -0.3f;
float squareZ = 0.0f;
static int flag = 1;
void drawShape(void) {
glTranslatef(squareX, squareY, squareZ);
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(162, 50);
glVertex2f(162, 10);
glVertex2f(220, 10);
glVertex2f(220, 50);
glVertex2f(162, 50);
glEnd();
}
void initRendering() {
glEnable(GL_DEPTH_TEST);
}
// called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, (float)w, 0.0f, (float)h, -1.0f, 1.0f);
}
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawShape();
glutSwapBuffers();
}
// make the square go up
void update(int value) {
if (flag) {
squareY += 1.0f;
if (squareY > 400.0) {
flag = 0;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
// make the square go right
/* void update(int value) {
if (flag) {
squareX += 1.0f;
if (squareX > 400.0) {
flag = 0;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
} */
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutCreateWindow("Moving Square");
initRendering();
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0);
glutMainLoop();
return(0);
}
I have uploaded this code before but this time I made the square go all the way up. The code just moves the square up, but I don't know how to position it on the left once it reaches the top, so then I can make it move to the right. I have uploaded a demonstration on how I want it to look below.
Preview:
What I want it to do next:
I recommend to initialize the variables squareX, squareY and squareZ with the start position of the rectangle:
float squareX = 162.0f;
float squareY = 0.0f;
float squareZ = 0.0f;
Do not draw a rectangle specific position, but draw a rectangle on the position (0,0) with a length (width, height). Let the model matrix (set by glTranslatef), do the job of the positioning:
void drawShape(void)
{
float width = 58.0f;
float height = 40.0f;
glTranslatef(squareX, squareY, squareZ);
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(0, 0);
glVertex2f(width, 0);
glVertex2f(width, height);
glVertex2f(0, height);
glVertex2f(0, 0);
glEnd();
}
Use a variable state, which has stated the direction of the current movement:
int state = 1; // 0: stop; 1: move up; 2: move right
If the rectangle a certain position has reached, then the state has to be changed and a the new start position can be set. At the final position, the rectangle can stop or the process can even be restarted:
void update(int value)
{
if (state == 1) // 1 : move up
{
squareY += 1.0f;
if (squareY > 400.0)
{
state = 2;
squareX = 0.0f;
squareY = 180.0f;
}
}
else if (state == 2) // 2 : move right
{
squareX += 1.0f;
if (squareX > 400.0)
{
state = 0;
// restart
//state = 1;
//squareX = 162.0f;
//squareY = 0.0f;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
i've a problem with drawing firework effect in animated scene when i clicked on mouse button. Why it don't drawing?
My Code:
#include<GL/glut.h>
struct Point {
GLint x;
GLint y;
};
Point p1, p2;
int ww=600,wh=400;
int xi,yi,xf,yf,y1b,x1b,y2b,x2b;
float px, py, t;
float x=0.,y=0.,x1=5.;
void update()
{
x+=0.01;
x1 -= 0.02;
if (x>6)
{
x -= 6;
x1 = 4;
}
}
There I create a function that draw firework effect on the basis of bezier curves. It will Okey if I draw on the static window.
// Bezier curve firework
void bezier(int xi, int yi, int xf, int yf)
{
// Coordinates for additional points of bezier curve
x1b = xi + rand()%15;
y1b = yi + rand()%5;
x2b = xf + rand()%15;
y2b = xf + rand()%5;
calculate and draw the curves
for (t=0.;t<=1.;t+=0.001)
{
px=(1-t)*(1-t)*(1-t)*xi+3*t*(1-t)*(1-t)*x1b+3*t*t*(1-t)*x2b+t*t*t*xf;
py=(1-t)*(1-t)*(1-t)*yi+3*t*(1-t)*(1-t)*y1b+3*t*t*(1-t)*y2b+t*t*t*yf;
glPointSize(2);
glBegin(GL_POINTS);
//glColor3f(1,0,0);
glVertex2d(px,py);
glEnd();
glFlush();
}
}
void initRendering()
{
glEnable(GL_DEPTH_TEST);
}
void reshaped(int w , int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (double)w/(double)h,1,200);
}
// If pressed ESC -> exit
void keyPressed(unsigned char k, int x, int y)
{
if(k==27)
{
exit(0);
}
}
Then, if I pressed mouse button it should call the function above and draw what I need. But nothing(
// If pressed mouse button -> draw firework effect
void mousePressed(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
{
xi=x;
yi=wh-y;
xf=x + 5.;
p1.x = xi; p1.y = yi;
p2.x = xf; p2.y = yi;
//drawLine(xi,yi,xf,yi);
bezier(xi, yi,xf, yi);
}
glutPostRedisplay();
}
There I create animated window. Two clouds move in gorizontal waves.
// Display a two moving clouds and the earth
void display()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(x1,y,-5.0);
glBegin(GL_POLYGON);
glColor3f(1.,0.,0.5);
glVertex3f(-1.,1.,-5.);
glVertex3f(0.,2.,-5.);
glVertex3f(-2.,2.,-5.);
glVertex3f(1.,1.,-5.);
glEnd();
glPopMatrix();
glPushMatrix();
glTranslatef(x,y,-5.);
glBegin(GL_POLYGON);
glColor3f(0.,0.5,0.5);
glVertex3f(1.,0.7,-5.);
glVertex3f(1.5,1.0,-5.0);
glVertex3f(0.7,1.5,-5.0);
glVertex3f(0.0,2.0,-5.0);
glVertex3f(-0.7,1.5,-5.0);
glVertex3f(-1.4,1.6,-5.0);
glVertex3f(-1.7,1.0,-5.0);
glVertex3f(-1.5,0.7,-5.0);
glVertex3f(-1.0,0.5,-5.0);
glEnd();
glPopMatrix();
glBegin(GL_POLYGON);
glColor3f(1.,1.,1.5);
glVertex3f(-2.,-2.,-5.);
glVertex3f(-2.0,-2.0,-5.0);
glVertex3f(-1.0,-1.5,-5.0);
//glVertex3f(0.0,0.0,-5.0);
glVertex3f(2.0,-2.0,-5.0);
glVertex3f(1.2,-1.5,-5.0);
glEnd();
update();
glutSwapBuffers();
glFlush();
}
void myinit()
{
glViewport(0,0,ww,wh);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble)ww,0.0,(GLdouble)wh);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc,char **argv)
{
// Initialization
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("Salute | Clouds");
initRendering();
// Registration
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshaped);
// Handler of
myinit();
glutKeyboardFunc(keyPressed);
glutMouseFunc(mousePressed);
// Main Loop
glutMainLoop();
return(0);
}
I think the problem is as follows:
I'm trying to draw my firework in an updated animated window. And every time I clicked on the screen, it is updated. And in the end, nothing is visible.
Actually the question:
How to make so that function glutMoseFunk would draw my salute in updated window?
While your scene is draw in perspective projection, the function bezier works with orthographic projection. This means you have to change the projection matrix befor you call bezier.
Further, do all the rendering in the main loop (display function). The event mousePressed should only be used to change parameters (set xi, yi, ...).
The display function may look like this:
int ww=400, wh=400;
void display()
{
// clear the frame buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// setup perspective projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (double)ww/(double)wh,1,200);
// set model view matrix (identity matrix)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw scene
.....
// setup ortihgraphic projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble)ww,0.0,(GLdouble)wh);
bezier(xi, yi,xf, yi);
update();
glutSwapBuffers();
glutPostRedisplay();
}
The reshaped function should set the viewport and notice the window size only:
void reshaped(int w , int h)
{
ww = w;
wh = h;
glViewport(0, 0, ww, wh);
}
So i'm making a game(something similar to a pong)using openGl in cpp , and when i try running the program , the image rendering is too slow ,i feel something is taking a huge toll on my GPU memory ,
(So far i have competed the drawing and movement of the paddle which works fine and the problem arises when the ball is set to motion on the press of a button , Everything slows down after this )
Here i have attached a portion of my code
Point out any deficiencies in my code
#include<stdlib.h>
#include<GL/glut.h>
#include<windows.h>
#include<iostream>
//#include<sstream>
#include<stdio.h>
#include<ctime>
#include<string.h>
typedef double point[3];
point a,b,c,d;
static float xmove=0.0;
static int release=0;
static float ii=0.00;
static int reac_top;
using namespace std;
//GLvoid player1_box();
GLfloat xangle=0.0;
float changeDir=1;// positive direction
double vv[4][3]={ {0.5,0.2,0.0},{ 0.5,0.25,0.0},{0.7,0.25,0.0},{0.7,0.2,0.0}};
void renderoutline()
{
glBegin(GL_LINE_LOOP);
glColor3f(1,0,0);
glVertex2f(0.0,0.0);
glColor3f(1,0,0);
glVertex2f(0,1.2);
glColor3f(1,0,0);
glVertex2f(1.2,1.2);
glColor3f(1,0,0);
glVertex2f(1.2,0);
glEnd();
}
void ball()
{
glBegin(GL_POLYGON);
glColor3f(0,0,1);
glVertex3f(0.6,0.25,0.0);
glColor3f(0,0,1);
glVertex3f(0.6,0.28,0.0);
glColor3f(0,0,1);
glVertex3f(0.62,0.28,0.0);
glColor3f(0,0,1);
glVertex3f(0.62,0.25,0.0);
glEnd();
}
void renderbox1( point a , point b , point c, point d)
{
glBegin(GL_POLYGON);
glColor3f(0,0,0);
glVertex3dv(a);
glColor3f(0,0,0);
glVertex3dv(b);
glColor3f(0,0,0);
glVertex3dv(c);
glColor3f(0,0,0);
glVertex3dv(d);
glEnd();
}
void keyboard(unsigned char key,int x,int y)
{
switch(key){
case 'a':xangle-=0.1;
++xmove;
while(xmove>5)
{
xmove=-5;
xangle=0.5;
continue;
}
break;
case 'd':xangle+=0.1;
--xmove;
while(xmove<-5)
{
xmove=5;
xangle =-0.5;
continue;
}
break;
case 'r':
release=1;
//printf("Inside switch r");
break;
}
glutPostRedisplay();
}
void display()
{
Sleep(2);
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glLineWidth(3.0);
glLoadIdentity();
glTranslatef(xangle,0,0);
renderbox1(vv[0],vv[1],vv[2],vv[3]); // To draw the paddle
glPopMatrix();
//printf("x move in disp:%1f \n",xmove);
renderoutline();
glPushMatrix();
glTranslatef(0,ii,0);
ball(); //To draw the ball
glPopMatrix();
glFlush();
}
void moveBall(){ //glutidlefunction
if(release==1)
{ //Release becomes one when the key 'r' is pressed (glutkeyboardfunc)
Sleep(500);
if(ii>=0&&ii<=0.9 )
{
reac_top=false;
ii=ii+0.05;printf("1\n");//The ball which was intially on the paddle starts moving till it reaches the top edge of thescreen
}
else if(ii>=0.9)
{
//when the boll reaches top
ii=ii-0.05;
reac_top=3;
printf("2\n");
}
else if( (ii<0.9)&& (reac_top==3)&&(ii>0.05)) //The balls journey back to the paddle
{
printf("3\n");
ii=ii-0.05;
}
release=1;
}
}
void reshape(int w, int h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1.2, 0, 1.2,-10.0,10.0);
glMatrixMode(GL_MODELVIEW);
glViewport(0,0,w,h);
//glutPostRedisplay();
//Use the whole window for rendering
}
int main(int argc ,char **argv)
{
//clock_t begin= clock();
char n1,n2;
int ack;
/*printf("The object of Tic Tac Toe is to get three in a row. \n . Players alternate placing Xs and Os(Traingles and Boxes in this version) \n on the game board until either opponent has three \n in a row or all nine squares are filled(Which would be a drawObviously). \n");
printf("\n Press 1 if acknowledged \n");
scanf("%d",&ack);*/
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(1000,500);
glutInitWindowPosition(200,0);
glutCreateWindow("3d Gasket");
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutReshapeFunc(reshape);
glutIdleFunc(moveBall);
glClearColor(1,1,1,1);
glutMainLoop();
//clock_t end=clock();
}
You're using c++, use C++-style (stdlib.h -> cstdlib) headers.
Apply your projection/modelview matrices each time through display() instead of a reshape callback, helps prevent annoying matrix stack issues.
Don't Sleep(), use a timer/idle callback to glutPostRedisplay(). Bonus points for framerate-independent movement (you can use glutGet(GLUT_ELAPSED_TIME) to calculate delta-t).
Without Sleep() there's no reason to drag windows.h into things.
All together:
#include <GL/glut.h>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <cstring>
typedef double point[3];
point a,b,c,d;
static float xmove=0.0;
static int release=0;
static float ii=0.00;
static int reac_top;
using namespace std;
GLfloat xangle=0.0;
float changeDir=1;// positive direction
double vv[4][3]={ {0.5,0.2,0.0},{ 0.5,0.25,0.0},{0.7,0.25,0.0},{0.7,0.2,0.0}};
void renderoutline()
{
glBegin(GL_LINE_LOOP);
glColor3f(1,0,0);
glVertex2f(0.0,0.0);
glColor3f(1,0,0);
glVertex2f(0,1.2);
glColor3f(1,0,0);
glVertex2f(1.2,1.2);
glColor3f(1,0,0);
glVertex2f(1.2,0);
glEnd();
}
void ball()
{
glBegin(GL_POLYGON);
glColor3f(0,0,1);
glVertex3f(0.6,0.25,0.0);
glColor3f(0,0,1);
glVertex3f(0.6,0.28,0.0);
glColor3f(0,0,1);
glVertex3f(0.62,0.28,0.0);
glColor3f(0,0,1);
glVertex3f(0.62,0.25,0.0);
glEnd();
}
void renderbox1( point a , point b , point c, point d)
{
glBegin(GL_POLYGON);
glColor3f(0,0,0);
glVertex3dv(a);
glColor3f(0,0,0);
glVertex3dv(b);
glColor3f(0,0,0);
glVertex3dv(c);
glColor3f(0,0,0);
glVertex3dv(d);
glEnd();
}
void keyboard(unsigned char key,int x,int y)
{
switch(key)
{
case 'a':xangle-=0.1;
++xmove;
while(xmove>5)
{
xmove=-5;
xangle=0.5;
continue;
}
break;
case 'd':xangle+=0.1;
--xmove;
while(xmove<-5)
{
xmove=5;
xangle =-0.5;
continue;
}
break;
case 'r':
release=1;
break;
}
}
void display()
{
glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1.2, 0, 1.2,-10.0,10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glLineWidth(3.0);
glLoadIdentity();
glTranslatef(xangle,0,0);
renderbox1(vv[0],vv[1],vv[2],vv[3]); // To draw the paddle
glPopMatrix();
renderoutline();
glPushMatrix();
glTranslatef(0,ii,0);
ball();
glPopMatrix();
glFlush();
}
void moveBall()
{
if(release==1)
{
//Release becomes one when the key 'r' is pressed (glutkeyboardfunc)
if(ii>=0&&ii<=0.9 )
{
reac_top=false;
ii=ii+0.05;printf("1\n");//The ball which was intially on the paddle starts moving till it reaches the top edge of thescreen
}
else if(ii>=0.9)
{
//when the boll reaches top
ii=ii-0.05;
reac_top=3;
printf("2\n");
}
else if( (ii<0.9)&& (reac_top==3)&&(ii>0.05)) //The balls journey back to the paddle
{
printf("3\n");
ii=ii-0.05;
}
release=1;
}
}
void timer( int value )
{
moveBall();
glutTimerFunc( 16, timer, 0 );
glutPostRedisplay();
}
int main(int argc ,char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(1000,500);
glutInitWindowPosition(200,0);
glutCreateWindow("3d Gasket");
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
}
this is my cube. Once created, it has a random x position on either -2, -1, 0, 1, or 2.
void cube(void)
{
srand (time(0));
int cube_posX;
int lowv = -2;
int highv = 2;
cube_posX = rand() % (highv - lowv + 1) + lowv;
glTranslatef(cube_posX, 0.0, cube_angle);
glRotatef(cube_angle, 90.0, 0.0, 1.0);
glutSolidCube(0.25);
}
and this is how I move the cube slowly forward
void MOVE_CUBE(int value)
{
cube_posZ = cube_posZ - 0.01;
glutPostRedisplay();
glutTimerFunc(25, MOVE_CUBE, 0);
}
and finally putting them in display:
void init(void)
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
float cam_eyeX = 0.0, cam_eyeY = 1.5, cam_eyeZ = 5.0;
float cam_centerX = 0.0, cam_centerY = 0.0, cam_centerZ = 0.0;
void display(void)
{
glClearColor(1.0,1.0,1.0,1.0); //to add background color (white)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(cam_eyeX, cam_eyeY, cam_eyeZ, cam_centerX, cam_centerY, cam_centerZ, 0.0, 1.0, 0.0); //camera! (cam position X, cam position Y, cam position Z, cam target X, cam target Y, cam target Z, up position X, up position Y, up position Z)
cube();
glutSwapBuffers();
angle += 0.05; //to affect the glRotate function
glFlush();
}
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);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); // Set up display buffer
glutInitWindowSize(750, 500); //window's size
glutInitWindowPosition(100, 100); //window's position
glutCreateWindow("Hendra Ganteng!"); //window's title
init();
glutDisplayFunc(display);
glutIdleFunc (display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard_Handler);
MOVE_CUBE(0);
glutMainLoop();
return 0;
}
But when I see it in action, the cube moves forward flawlessly, but keeps changing x position onto those 5 possibilities (-2,-1,0,1,2) every 0.5 to 1 second. If I disable the srand(time(0)), the cube changes its x position rapidly. I just want to make it stay in 1 x position so then I can call more cubes in different x position. Could someone please kindly what's wrong in my code?
How is that behaviour not expected? You are generating a random X position every time you display your cube. If you re-seed the random number generator using the time, then it will be start a different sequence whenever the time changes (once per second).
Instead, you should pre-generate your cube(s). How about this:
// Global cube data
struct Cube {
int x;
double angle;
};
vector<Cube> cubes;
const int num_cubes = 1;
// Example initialisation...
void InitCubes()
{
cubes.reserve(num_cubes);
for( int i = 0; i < num_cubes; i++ )
{
Cube cube;
cube.x = rand() % (highv - lowv + 1) + lowv;
cube.angle = 0.0;
cubes.push_back(cube);
}
}
Now the update/display cycles simply need to modify the angle, but not the x-position.
void UpdateCube( Cube & cube )
{
cube.angle += 0.05;
}
void DisplayCube( Cube & cube )
{
glTranslatef((double)cube.x, 0.0, cube.angle);
glRotatef(cube.angle, 90.0, 0.0, 1.0);
glutSolidCube(0.25);
}
In your main function, call InitCubes() during startup.
In your display function, do this:
void display(void)
{
glClearColor(1.0,1.0,1.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(cam_eyeX, cam_eyeY, cam_eyeZ, cam_centerX, cam_centerY, cam_centerZ, 0.0, 1.0, 0.0);
// Display cubes
for( int i = 0; i < cubes.size(); i++ ) DisplayCube( cubes[i] );
glutSwapBuffers();
glFlush();
// Update cubes for next render cycle.
for( int i = 0; i < cubes.size(); i++ ) UpdateCube( cubes[i] );
}