Jump to content
  • Advertisement
Sign in to follow this  
thyrgle

Why is this not working and causing lag?

This topic is 3007 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

So I have the following code:


#include <iostream>
#include <stdlib.h> //Needed for "exit" function

//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <math.h>
#define PI 3.14159265

bool keyPressed[4];
bool disableIdle;
bool disableEnemyGen = false;

float enemyX[1000];
float enemyY[1000];

int dir[1000];

float enemyRand, permanentRand;

float characterX, characterY;

using namespace std;

void moveEnemy(int x)
{
//determine direction
srand(time(NULL));
dir[x] = rand() % 2 + 1;

int i;

if (dir[x] == 1)
{
for(i = 0; i < 1000; i++)
{
enemyX = enemyX + 0.1;
}
if (x == 999)
{
disableEnemyGen = true;
glutPostRedisplay();
}
}
else if (dir[x] == 2)
{
for(i = 0; i < 1000; i++)
{
enemyY[x] = enemyY[x] + 0.1;
}
if (x == 999)
{
disableEnemyGen = true;
glutPostRedisplay();
}
}
}

void generateEnemies(float x, float y, int g)
{
enemyX[g] = x;
enemyY[g] = y;
glBegin(GL_TRIANGLE_FAN);
for(int i=0; i <= 360; i++)
glVertex3f(sin(i*PI/180)*0.1+enemyX[g], cos(i*PI/180)*0.1+enemyY[g], -10);
glEnd();
//glutTimerFunc(10, moveEnemy, g);
}
void moveCircleUp(int x)
{
disableIdle = true;
characterY = characterY + 0.1;
glutPostRedisplay();
x++;
if (x < 10)
{
glutTimerFunc(10, moveCircleUp, x);
}
else {
disableIdle = false;
}
}

void moveCircleLeft(int x)
{
disableIdle = true;
characterX = characterX - 0.1;
glutPostRedisplay();
x++;
if (x < 10)
{
glutTimerFunc(10, moveCircleLeft, x);
}
else {
disableIdle = false;
}
}

void moveCircleDown(int x)
{
disableIdle = true;
characterY = characterY - 0.1;
glutPostRedisplay();
x++;
if (x < 10)
{
glutTimerFunc(10, moveCircleDown, x);
}
else {
disableIdle = false;
}
}

void moveCircleRight(int x)
{
disableIdle = true;
characterX = characterX + 0.1;
glutPostRedisplay();
x++;
if (x < 10)
{
glutTimerFunc(10, moveCircleRight, x);
}
else {
disableIdle = false;
}
}

void initCharacter()
{
glBegin(GL_TRIANGLE_FAN);
for(int i=0; i <= 360; i++)
glVertex3f(sin(i*PI/180)*0.3+characterX, cos(i*PI/180)*0.3+characterY, -10);
glEnd();
}

void handleKeypress(unsigned char key, int x, int y) {
disableEnemyGen = true;
switch (key) {
case 27: //Escape key
exit(0); //Exit the program
}

if (key == 'a')
{
keyPressed[0] = true;
}
if (key == 'w')
{
keyPressed[1] = true;
}
if (key == 's')
{
keyPressed[2] = true;
}
if (key == 'd')
{
keyPressed[3] = true;
}
}

void handleKeyUp(unsigned char key, int x, int y)
{
if (key == 'a')
{
keyPressed[0] = false;
}
if (key == 'w')
{
keyPressed[1] = false;
}
if (key == 's')
{
keyPressed[2] = false;
}
if (key == 'd')
{
keyPressed[3] = false;
}
}
//Initializes 3D rendering
void initRendering() {
//Makes 3D drawing work when something is in front of something else
glEnable(GL_DEPTH_TEST);
}

//Called when the window is resized
void handleResize(int w, int h) {
//Tell OpenGL how to convert from coordinates to pixel values
glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective

//Set the camera perspective
glLoadIdentity(); //Reset the camera
gluPerspective(45.0, //The camera angle
(double)w / (double)h, //The width-to-height ratio
1.0, //The near z clipping coordinate
200.0); //The far z clipping coordinate
}

//Draws the 3D scene
void drawScene() {
//Clear information from last draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspectives'
initCharacter();
int i;
srand(time(NULL));
for (i = 0; i < 1000; i++)
{
if (disableEnemyGen == false)
{
enemyRand = rand() % 90;
generateEnemies(enemyRand, enemyRand, i);
}
else
{
generateEnemies(permanentRand, permanentRand, i);
}
}
glutSwapBuffers(); //Send the 3D scene to the screen
}

void move()
{
if(disableIdle == false)
{
if (keyPressed[0] == true)
{
moveCircleLeft(0);
}
if (keyPressed[1] == true)
{
moveCircleUp(0);
}
if (keyPressed[2] == true)
{
moveCircleDown(0);
}
if (keyPressed[3] == true)
{
moveCircleRight(0);
}
}
/*if ( sqrt( ( enemyX[]-characterX ) * ( enemyX-characterX ) + ( enemyY-characterY ) * ( enemyY-characterY ) ) < ( 0.2 + 0.3 ) )
{

}*/


}
int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1200, 600); //Set the window size

//Create the window
glutCreateWindow("Game");
initRendering(); //Initialize rendering

//Set handler functions for drawing, keypresses, and window resizes
glutDisplayFunc(drawScene);
glutKeyboardFunc(handleKeypress);
glutReshapeFunc(handleResize);
glutIdleFunc(move);
glutKeyboardUpFunc(handleKeyUp);

glutMainLoop(); //Start the main loop. glutMainLoop doesn't return.
return 0; //This line is never reached
}



Basically, I am trying to get a ball to move with the ASWD keys and then generate random dots to be placed on the screen. But, here is the problem: I am trying to make it so the multiple balls do not re display each time, only once. And also prevent so much lag in my program? Any suggestion would be appreciated.

[Edited by - thyrgle on June 30, 2010 9:36:19 PM]

Share this post


Link to post
Share on other sites
Advertisement
There is a lot of code and it's overly difficult to read it without any indentations. Please repost your code inside [ source ] and [ /source ] code tags (without any spaces inside the brackets). Also make sure you copy your code from your source files, otherwise there will still be no indentation.

Share this post


Link to post
Share on other sites
I haven't looked at OpenGL for a few years now but the fact that you are drawing 360,000 triangles using immediate mode in every frame is probably the cause for it being so slow.

Try display lists, vertex buffers, or textures to draw your balls. With textures you could draw as little as two triangles (one quad) to get the same effect, instead of 360 per ball.

Share this post


Link to post
Share on other sites
Yea the guy above me has it right, your going to be slow because you are sending 360,000 pieces of data to your GPU for each frame. Everyone runs into this problem, look up VBO(vertex buffer objects), which store the model on the GPU and you only send the triangles to the gpu 1 time.

Share this post


Link to post
Share on other sites

With optimization, and if you are running on some halfway decent hardware, I don't see any reason why your loop can't animate 1000 2D circles.

How many enemies can it render before it lags out? Is it 100, 200, or?

Your code could use some math optimization for sure. For example, there's no reason to keep recomputing PI/180. Either define a constant for magic numbers like that, or calulate them only once during setup. Also, no reason to draw each circle with so many vertexes. Cut that down to like 30 or 32 instead of 360. You still get a decent circle out of the deal, with much less overhead.

As others have said, you could use some graphics optimization as well. But get your loop working as fast as possible before you make any changes there.

Share this post


Link to post
Share on other sites
You are doing a lot of weird things here.
As for the "lag", as others have stated, drawing 360.000+ triangles in immediate mode each frame isn't the best idea. Another thing is that every time you press a key a delayed movement will start, moving your "character" 10 units in either direction with 10ms delay between each move and redraw. I don't know if this i intentional or not, but that may be the "lag" you are experiencing. While this movement is done your application effectively locks the input mechanism.

And one final thing, every time you press a key (to start the movement of the character, and this is also the only thing that ever causes the draw-method to be called) the boolean "disableEnemyGen" is set to true. when this is true you are drawing your enemies at a fixed position using the "permanentRand" variable. However, this variable is never initialized so it will be either 0 or some very large/small value depending on compiler and debug settings. In either case all your 1000 enemies will be drawn at the exact same location every time, or not at all.

Share this post


Link to post
Share on other sites
Hi,

Thanks for all the replies, but how do I make this:


glBegin(GL_TRIANGLE_FAN);
for(int i=0; i <= 360; i++)
glVertex3f(sin(i*PI/180)*0.3+characterX, cos(i*PI/180)*0.3+characterY, -10);
glEnd();




into a GL Vertex Buffer Object?

Share this post


Link to post
Share on other sites
Quote:
Original post by thyrgle
Hi,

Thanks for all the replies, but how do I make this:

*** Source Snippet Removed ***

into a GL Vertex Buffer Object?
Unfortunately, there's a lot of boilerplate code involved in setting up and rendering VBOs, so it's not something that's easily explained in a forum post (although I suppose it could be, with a little work).

I think your best bet would be to google/search for 'opengl vbo' and just start reading up on them - I'm sure you'll be able to find some tutorials with sample code.

Share this post


Link to post
Share on other sites
Quote:
Originally posted by Decrius
This site here explains very well how to use a VBO: http://www.songho.ca/opengl/gl_vbo.html

It's also got pages for VA and FBO.


Hmm... Well they use GLfloat vertices[] to store there information but what about using a for loop the way I made my circle? Is there a way to do that?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!