How do I specify a keyboard's directional keys in glut? - opengl

I wanna use up, down, left, right as part of the controls of an opengl + glut application. How do I refer to the keys inside my 'keyboard' function (the one that I pass to glutKeyboardFunc)?

You need glutSpecialFunc.
For example -
#include<GL/gl.h>
#include<GL/glut.h>
#include<stdio.h>
void
init(void)
{
/*initialize the x-y co-ordinate*/
glClearColor(0,0,0,0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-320, 319,-240, 239);
glClear (GL_COLOR_BUFFER_BIT);
glFlush();
}
void
catchKey(int key, int x, int y)
{
if(key == GLUT_KEY_LEFT)
printf("Left key is pressed\n");
else if(key == GLUT_KEY_RIGHT)
printf("Right key is pressed\n");
else if(key == GLUT_KEY_DOWN)
printf("Down key is pressed\n");
else if(key == GLUT_KEY_UP)
printf("Up key is pressed\n");
}
int
main(int argc, char *argv[])
{
double x_0, y_0, x_1, y_1;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(400, 400);
glutCreateWindow("Special key");
init();
glutSpecialFunc(catchKey);
glutMainLoop();
}

your functions should be something like these
void handleSpecialKeypress(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT:
isLeftKeyPressed = true;
if (!isRightKeyPressed) {
DO SOMETHING HERE;
}
break;
case GLUT_KEY_RIGHT:
isRightKeyPressed = true;
if (!isLeftKeyPressed) {
DO SOMETHING HERE;
}
break;
}
}
void handleSpecialKeyReleased(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT:
isLeftKeyPressed = false;
break;
case GLUT_KEY_RIGHT:
isRightKeyPressed = false;
break;
}
}
and you also need to invoke these in your main() method
glutSpecialFunc(handleSpecialKeypress);
glutSpecialUpFunc(handleSpecialKeyReleased);
The variables isRightKeyPressed and isLeftKeyPressed are global variables I defined.

Related

Finish drawing a polygon by right-clicking, but displaying a menu instead

I am writing a program that will continuously draw a polygon until the user right-clicks. The user can only draw if and only if the user makes a selection in the menu, if the user does not make a selection in the menu, the program will not draw. Up to now, my program has successfully drawn a polygon with the mouse, but the problem is that when I right-click to complete, the program pops up the menu instead of completing the polygon. Now how can I right-click to be able to complete the polygon, here's my program:
const int MAX = 100;
float mouseX, mouseY, ListX[MAX], ListY[MAX];
int numPoints = 0, closed = 0, shape = 0;
void mouse(int button, int state, int x, int y)
{
mouseX = x;
mouseY = y;
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
if (closed || numPoints >= MAX - 1)
numPoints = 0;
closed = 0;
ListX[numPoints] = mouseX;
ListY[numPoints] = mouseY;
numPoints++;
}
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
closed = 1;
}
void motion(int x, int y)
{
mouseX = x;
mouseY = y;
glutPostRedisplay();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
if (shape == 1)
{
if (numPoints)
{
glBegin(GL_LINE_STRIP);
for (int i = 0; i < numPoints; ++i)
glVertex2f(ListX[i], ListY[i]);
if (closed)
glVertex2f(ListX[0], ListY[0]);
else
glVertex2f(mouseX, mouseY);
glEnd();
}
}
glFlush();
}
void menu(int choice)
{
switch (choice)
{
case 1:
shape = 1;
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 100);
glutCreateWindow("");
gluOrtho2D(0, 640, 480, 0);
glutCreateMenu(menu);
glutAddMenuEntry("Polygon", 1);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutPassiveMotionFunc(motion);
glutMainLoop();
}
Edit: Thanks to genpfault, I finished the polygon by right-clicking but I don't know how to reattach it so I can re-open the menu.
...
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
if (shape == 1)
{
glutDetachMenu(GLUT_RIGHT_BUTTON); // Add this
...
}
glFlush();
}
void menu(int choice)
{
switch (choice)
{
case 1:
shape = 1;
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 100);
glutCreateWindow("");
gluOrtho2D(0, 640, 480, 0);
glutCreateMenu(menu);
glutAddMenuEntry("Polygon", 1);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutPassiveMotionFunc(mouse_move);
glutMainLoop();
}
Capture the return-value from glutCreateMenu(), that's the handle for the new menu.
Detach the menu in the menu callback via glutDetachMenu() and set a bool indicating you're in "add points" mode.
If you're in "add points" mode and detect a right-click, set the current menu to the menu handle from #1 via glutSetMenu(), then re-attach the menu with glutAttachMenu(). Reset the "add points" bool to false.
All together:
#include <GL/glut.h>
const int MAX = 100;
float mouseX, mouseY, ListX[MAX], ListY[MAX];
int numPoints = 0, closed = 0, shape = 0;
int hMenu = 0;
bool addingPoints = false;
void mouse(int button, int state, int x, int y)
{
mouseX = x;
mouseY = y;
if( addingPoints )
{
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
{
if (closed || numPoints >= MAX - 1)
numPoints = 0;
closed = 0;
ListX[numPoints] = mouseX;
ListY[numPoints] = mouseY;
numPoints++;
}
if( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
{
closed = 1;
addingPoints = false;
glutSetMenu(hMenu);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
}
}
void motion(int x, int y)
{
mouseX = x;
mouseY = y;
glutPostRedisplay();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 640, 480, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (shape == 1)
{
if (numPoints)
{
glBegin(GL_LINE_STRIP);
for (int i = 0; i < numPoints; ++i)
glVertex2f(ListX[i], ListY[i]);
if (closed)
glVertex2f(ListX[0], ListY[0]);
else
glVertex2f(mouseX, mouseY);
glEnd();
}
}
glutSwapBuffers();
}
void menu(int choice)
{
switch (choice)
{
case 1:
numPoints = 0;
shape = 1;
addingPoints = true;
glutDetachMenu(GLUT_RIGHT_BUTTON);
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutCreateWindow("");
hMenu = glutCreateMenu(menu);
glutSetMenu(hMenu);
glutAddMenuEntry("Polygon", 1);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutPassiveMotionFunc(motion);
glutMainLoop();
}

How to use glutSpecialFunc correctly?

I wanna make my square go up when UO is pressed.
void displayScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0,x,0);
glBegin(GL_QUADS);
glVertex3f(-0.4,-0.4, -5.0);
glVertex3f( 0.4,-0.4, -5.0);
glVertex3f( 0.4, 0.4, -5.0);
glVertex3f(-0.4, 0.4, -5.0);
glEnd();
//x = x + 0.1;
glutSwapBuffers();
}
I'm using gluSpecialFunc.
void ProcessSpecialKeys(unsigned char key, int x, int y)
{
if (key == GLUT_KEY_UP)
{
x = x + 0.1;
}
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(0,0);
glutCreateWindow("OpenGL Window");
init();
glutDisplayFunc(displayScene);
glutSpecialFunc(ProcessSpecialKeys);
//glutKeyboardFunc(ProcessKeys);
glutMainLoop();
return 0;
}
When I leave x+=0.1 in the displayScene, the square goes up when I press any key.
Am I using glutSpecialFunc incorrectly? Because I used it before and it worked normally. What am I missing?
glutSpecialFunc is not invoked continuously when a key is held down. The callback is called once when a key is pressed.
freeglut provides the glutSpecialUpFunc callback which is called when a key is released.
Set a state when UP is pressed and reset the state when UP is released:
int main(int argc, char** argv)
{
// [...]
glutSpecialFunc(ProcessSpecialKeys);
glutSpecialUpFunc(ReleaseSpecialKeys);
// [...]
}
int keyUpPressed = 0;
void ProcessSpecialKeys(unsigned char key, int x, int y)
{
if (key == GLUT_KEY_UP)
keyUpPressed = 1;
}
void ReleaseSpecialKeys(unsigned char key, int x, int y)
{
if (key == GLUT_KEY_UP)
keyUpPressed = 0;
}
Change the x dependent on the state of keyUpPressed. Continuously redraw the scene by calling glutPostRedisplay in displayScene
void displayScene(void)
{
if (keyUpPressed)
x += 0.1;
// [...]
glutSwapBuffers();
glutPostRedisplay();
}

How to declare function in other function?

So I'm making quiz in opengl with c++. The problem is that I don't know how to declare function inside other function, so I have an error.
void main_menu_display()
{
glClear(GL_COLOR_BUFFER_BIT);
// code to draw main menu
glutSwapBuffers();
}
void main_menu_key(unsigned char key, int x, int y)
{
I also tried this, to solve errors: //void first_screen_display();
//void first_screen_key();
switch(key)
{
case 27: //< escape -> quit
exit(0);
case 13: //< enter -> goto first display
glutDisplayFunc(first_screen_display);
glutKeyboardFunc(first_screen_key);
break;
and there's error: 'first_screen_display' was not declared in this scope
and same happens with first screen key.
}
glutPostRedisplay();
}
void first_screen_display()
{
glClear(GL_COLOR_BUFFER_BIT);
// code to draw first screen of game
glutSwapBuffers();
}
void first_screen_key(unsigned char key, int x, int y)
{
switch(key)
{
case 27: //< escape -> return to main menu
glutDisplayFunc(first_screen_display);
glutKeyboardFunc(first_screen_key);
break;
/* other stuff */
default:
break;
}
glutPostRedisplay();
}
int main(int argc, char* argv[]) //argument count, argument variables
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);
glutInitWindowSize(600,600);
glutInitWindowPosition(100,100);
glutCreateWindow("Quiz");
glutDisplayFunc(main_menu_display);
glutKeyboardFunc(main_menu_key);
//glutDisplayFunc(first_screen_display);
//glutKeyboardFunc(first_screen_key);
Init();
glutMainLoop();
return 0;
}

openGL/Glut drawn line not shown from mouse input

I am trying to draw a line based on the mouse input coordinates.
The following code compiles, however, a line is not displayed from mouse input.
int coord_1[2]; //(x,y) of first point for line
int coord_2[2]; //(x,y) of second point for line
bool ready_1=false;
bool ready_2=false;
void drawLine()
{
glBegin(GL_LINES);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(coord_1[0], coord_1[1]);
glVertex2f(coord_2[0], coord_2[1]);
glEnd();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1,1,-1,1,-1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(ready_1 && ready_2)
{
drawLine();
ready_1 = ready_2 = false;
}
glutSwapBuffers();
}
void mouse(int button, int state, int x, int y)
{
switch (button)
{
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN) //button pressed down
{
//only do something on release
}
if (state == GLUT_UP) //released button
{
cout << "right button up" << endl;
}
break;
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) //button pressed down
{
coord_1[0]=x;
coord_2[1]=y;
cout << "first pos" << endl;
ready_1=true;
}
if (state == GLUT_UP) //released button
{
coord_2[0]=x;
coord_2[1]=y;
cout << "second pos" << endl;
ready_2=true;
}
break;
default:
break;
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGBA|GLUT_MULTISAMPLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(512,512);
glutCreateWindow("Asn 1");
glutDisplayFunc(display);
glutIdleFunc(display);
glutMouseFunc(mouse);
glutKeyboardFunc(processNormalKeys);
// GLUT main loop
glutMainLoop();
return(0);
}
Any help or pointers in the right direction?
You probably draw the line, but since you reset your drawing condition afterwards, your line gets hidden in the next draw step (which might be VERY quick).
Remove the ready_1 = ready_2 = false; and the line should stay visible.
Instead you can set ready_2 = false when you receive a left button down event.

opengl tiny rendering glitch, need help & tips

here is my code:
#include <stdlib.h>
#include <iostream>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <SDL.h>
using namespace std;
typedef unsigned short us;
typedef unsigned char uc;
bool *keystates = new bool[256];
bool *skeystates= new bool[256];
uc dir_m[8][2]={
{ 0, 1 },
{ 0,-1 },
{ -1,0 },
{ 1,0 },
{ 1,1},
{ 1,-1 },
{ -1,-1 },
{ -1,1 }
};
us totalbots=15;
float zoomlvl=-70.f;
float camx=0.f,camy=0.f;
struct bot_data{
float x,y,z;
float r,g,b;
float size; // "radius" of the square
us coold;
us age;
us trans:5;
us dir:3,fac:2;
bot_data(void);
void move(void);
void deliver(us bot);
};
struct bool_data{
bool ch:1,ch2:1;
};
bot_data::bot_data(void){
size=0.25f;
fac=rand()%4;
switch(fac){
case 0:x=10.f,y=10.f,z=0.f;
r=1.0f,g=0.f,b=0.f;
break;
case 1:x=-10.f,y=-10.f,z=0.f;
r=0.0f,g=0.f,b=1.f;
break;
case 2:x=-10.f,y=10.f,z=0.f;
r=1.0f,g=1.f,b=0.f;
break;
case 3:x=10.f,y=-10.f,z=0.f;
r=0.0f,g=1.f,b=0.f;
break;
}
coold=0;
trans=0;
age=0;
dir=rand()%8;
}
bot_data *cubers=new bot_data[65536];
bool_data *bools=new bool_data;
void bot_data::move(void){
float move=size/10.f;
switch(dir){
case 0:y+=move;
break;
case 1:y-=move;
break;
case 2:x-=move;
break;
case 3:x+=move;
break;
case 4:x+=move;
y+=move;
break;
case 5:x+=move;
y-=move;
break;
case 6:y-=move;
x-=move;
break;
case 7:y+=move;
x-=move;
break;
}
}
void bot_data::deliver(us bot){
age=-10;
totalbots+=3;
float tmp=size-(size/4.f);
size=0.25f;
x-=size;
y+=size;
for(uc i=1;i<=3;i++){
cubers[totalbots-i].fac=fac;
switch(fac){
case 0:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=0.f;
break;
case 1:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=1.f;
break;
case 2:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
break;
case 3:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
break;
}
cubers[totalbots-i].coold=coold;
cubers[totalbots-i].size=size;
switch(i){
case 1:cubers[totalbots-i].x=x;
cubers[totalbots-i].y=y-size*2;
break;
case 2:cubers[totalbots-i].x=x+size*2;
cubers[totalbots-i].y=y;
break;
case 3:cubers[totalbots-i].x=x+size*2;
cubers[totalbots-i].y=y-size*2;
break;
}
}
}
void initkeys(void){
for(uc i=0;i<255;i++){
keystates[i]=false;
skeystates[i]=false;
}
}
void p_keys(unsigned char key, int x, int y){
keystates[key]=true;
}
void keyup(unsigned char key, int x, int y){
keystates[key]=false;
}
void sp_keys(int key, int x, int y){
skeystates[key]=true;
}
void skeyup(int key, int x, int y){
skeystates[key]=false;
}
void key_func(void){
if (keystates['z']){
if(skeystates[GLUT_KEY_UP])zoomlvl+=1.f;
else if (skeystates[GLUT_KEY_DOWN])zoomlvl-=1.f;
if(zoomlvl<-100.0f)zoomlvl=-100.f;
else if(zoomlvl>-5.f)zoomlvl=-5.f;
}
else{
if(skeystates[GLUT_KEY_UP])camy-=1.f;
else if(skeystates[GLUT_KEY_DOWN])camy+=1.f;
}
if(skeystates[GLUT_KEY_LEFT])camx+=1.f;
else if(skeystates[GLUT_KEY_RIGHT])camx-=1.f;
}
void render_p(us bot){
glColor3f(cubers[bot].r,cubers[bot].g,cubers[bot].b);
glBegin(GL_QUADS);
glVertex2f(cubers[bot].size,cubers[bot].size);
glVertex2f(cubers[bot].size,-cubers[bot].size);
glVertex2f(-cubers[bot].size,-cubers[bot].size);
glVertex2f(-cubers[bot].size,cubers[bot].size);
glEnd();
}
void process_cubers(void){
for(us i=0;i<totalbots;i++){
//glPushMatrix();
glLoadIdentity();
glTranslatef(cubers[i].x,cubers[i].y,cubers[i].z);
if(cubers[i].coold==0){
cubers[i].move();
cubers[i].trans++;
if(cubers[i].trans==20){
cubers[i].trans=0;
cubers[i].coold=50;
if(cubers[i].age<100){
cubers[i].size+=0.025f;
}
else if(cubers[i].age==150){
cubers[i].deliver(i);
}
cubers[i].dir=rand()%8;
cubers[i].age+=10;
}
}
else cubers[i].coold--;
render_p(i);
//glPopMatrix();
}
}
void display(void){
key_func();
glClearColor(0.6f,0.6f,0.6f,1.f);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef(camx,camy,zoomlvl);
process_cubers();
glutSwapBuffers();
SDL_Delay(1000/30);
glutPostRedisplay();
}
void resize(int width,int height){
glViewport(0,0,(GLsizei)width,(GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)width/(GLfloat)height,1.f,100.f);
glMatrixMode(GL_MODELVIEW);
}
int main (int argc, char **argv) {
initkeys();
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE);
glutInitWindowSize (640, 480);
glutInitWindowPosition (0, 0);
glutCreateWindow ("opengl 1");
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(resize);
glutKeyboardFunc(p_keys);
glutKeyboardUpFunc(keyup);
glutSpecialFunc(sp_keys);
glutSpecialUpFunc(skeyup);
glutMainLoop();
return 0;
}
it renders a certain amount of said squares that move each certain intervals. their move distance is their size. each time they move they grow in size until they reach the size limit (1.f in radius in this case) after a certain amount of moves (15 in this case) the square will split into 4 smaller squares and FILLING OUT THE EXACT SPACE its precursor occupied, that means it is supposed to look completely seamless..the problem is instead, i get this split second tear & glitch-looking rendering after the square splits, but other than that i found no other problems.
what i suspect is perhaps i missed some gl function i was supposed to call around the time i am rendering the new 3 squares (the splitting occurs by adding 3 new squares, and shrinking the current one to a quarter of its size, then adjusting all the squres.)
Try this:
#include <GL/glew.h>
#include <GL/glut.h>
typedef unsigned short us;
typedef unsigned char uc;
bool *keystates = new bool[256];
bool *skeystates= new bool[256];
uc dir_m[8][2]=
{
{ 0, 1 },
{ 0,-1 },
{ -1,0 },
{ 1,0 },
{ 1,1},
{ 1,-1 },
{ -1,-1 },
{ -1,1 }
};
us totalbots=15;
float zoomlvl=-70.f;
float camx=0.f,camy=0.f;
struct bot_data
{
float x,y,z;
float r,g,b;
float size; // "radius" of the square
us coold;
us age;
us trans:5;
us dir:3,fac:2;
bot_data(void);
void move(void);
void deliver(us bot);
};
struct bool_data
{
bool ch:1,ch2:1;
};
bot_data::bot_data(void)
{
size=0.25f;
fac=rand()%4;
switch(fac){
case 0:x=10.f,y=10.f,z=0.f;
r=1.0f,g=0.f,b=0.f;
break;
case 1:x=-10.f,y=-10.f,z=0.f;
r=0.0f,g=0.f,b=1.f;
break;
case 2:x=-10.f,y=10.f,z=0.f;
r=1.0f,g=1.f,b=0.f;
break;
case 3:x=10.f,y=-10.f,z=0.f;
r=0.0f,g=1.f,b=0.f;
break;
}
coold=0;
trans=0;
age=0;
dir=rand()%8;
}
bot_data *cubers=new bot_data[65536];
bool_data *bools=new bool_data;
void bot_data::move(void)
{
float move=size/10.f;
switch(dir){
case 0:y+=move;
break;
case 1:y-=move;
break;
case 2:x-=move;
break;
case 3:x+=move;
break;
case 4:x+=move;
y+=move;
break;
case 5:x+=move;
y-=move;
break;
case 6:y-=move;
x-=move;
break;
case 7:y+=move;
x-=move;
break;
}
}
void bot_data::deliver(us bot)
{
age=-10;
totalbots+=3;
float tmp=size-(size/4.f);
size=0.25f;
x-=size;
y+=size;
for(uc i=1;i<=3;i++){
cubers[totalbots-i].fac=fac;
switch(fac){
case 0:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=0.f;
break;
case 1:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=1.f;
break;
case 2:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
break;
case 3:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
break;
}
cubers[totalbots-i].coold=coold;
cubers[totalbots-i].size=size;
switch(i){
case 1:cubers[totalbots-i].x=x;
cubers[totalbots-i].y=y-size*2;
break;
case 2:cubers[totalbots-i].x=x+size*2;
cubers[totalbots-i].y=y;
break;
case 3:cubers[totalbots-i].x=x+size*2;
cubers[totalbots-i].y=y-size*2;
break;
}
}
}
void initkeys(void)
{
for(uc i=0;i<255;i++){
keystates[i]=false;
skeystates[i]=false;
}
}
void p_keys(unsigned char key, int x, int y)
{
keystates[key]=true;
}
void keyup(unsigned char key, int x, int y)
{
keystates[key]=false;
}
void sp_keys(int key, int x, int y)
{
skeystates[key]=true;
}
void skeyup(int key, int x, int y)
{
skeystates[key]=false;
}
void key_func(void)
{
if (keystates['z'])
{
if(skeystates[GLUT_KEY_UP])zoomlvl+=1.f;
if(skeystates[GLUT_KEY_DOWN])zoomlvl-=1.f;
if(zoomlvl<-100.0f)zoomlvl=-100.f;
if(zoomlvl>-5.f)zoomlvl=-5.f;
}
else
{
if(skeystates[GLUT_KEY_UP])camy-=1.f;
if(skeystates[GLUT_KEY_DOWN])camy+=1.f;
if(skeystates[GLUT_KEY_LEFT])camx+=1.f;
if(skeystates[GLUT_KEY_RIGHT])camx-=1.f;
}
}
void render_p(us bot)
{
glColor3f(cubers[bot].r,cubers[bot].g,cubers[bot].b);
glBegin(GL_QUADS);
glVertex2f(cubers[bot].size,cubers[bot].size);
glVertex2f(cubers[bot].size,-cubers[bot].size);
glVertex2f(-cubers[bot].size,-cubers[bot].size);
glVertex2f(-cubers[bot].size,cubers[bot].size);
glEnd();
}
void process_cubers(void)
{
for(us i=0;i<totalbots;i++){
if(cubers[i].coold==0){
cubers[i].move();
cubers[i].trans++;
if(cubers[i].trans==20){
cubers[i].trans=0;
cubers[i].coold=50;
if(cubers[i].age<100){
cubers[i].size+=0.025f;
}
else if(cubers[i].age==150){
cubers[i].deliver(i);
}
cubers[i].dir=rand()%8;
cubers[i].age+=10;
}
}
else cubers[i].coold--;
}
for(us i=0;i<totalbots;i++)
{
glPushMatrix();
glTranslatef(cubers[i].x,cubers[i].y,cubers[i].z);
render_p(i);
glPopMatrix();
}
}
void display(void)
{
key_func();
glClearColor(0.6f,0.6f,0.6f,1.f);
glClear (GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective(60, w / h,1.f,100.f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(camx,camy,zoomlvl);
process_cubers();
glutSwapBuffers();
}
void timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(33, timer, 0);
}
int main (int argc, char **argv)
{
initkeys();
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize (640, 480);
glutInitWindowPosition (0, 0);
glutCreateWindow ("opengl 1");
glutDisplayFunc(display);
glutKeyboardFunc(p_keys);
glutKeyboardUpFunc(keyup);
glutSpecialFunc(sp_keys);
glutSpecialUpFunc(skeyup);
glutTimerFunc(0, timer, 0);
glutMainLoop();
return 0;
}
You were drawing in your simulation loop. This splits that into two loops, sim then draw.
The way graphics rendering works (OpenGL or otherwise) is that it only guarantees a "nice" seam between two triangles that are "exactly" aligned along some edge if you render them as part of the same triangle strip, the same (vertex buffer, index buffer) model pair, or some other construct that groups triangles into a single render unit.
When you render a "quad," you are really rendering a 2-triangle triangle strip, so the seam between the two triangles looks nice.
When you render two seperate quads that are aligned along some edge, the edge can look bad. Anti-aliasing can help to fix the problem a little bit, but ultimately you need to use a single render unit if you want to get rid of the tearing along seams.
The figure shows four quads (eight triangles) being rendered in a grid. The diagonals are within quads so there isn't any tearing, but the since the quads are all rendered separately there is tearing along their seams.