0

I want to draw 100 points on the screen using openGL. This means there will be 100 GL_POINTS randomly located on the screen each time I run the program. Currently there is only one point that remains on the screen and its position was previously given. However, my random points only appeared for a short period of time and then they disappear. I don't know what did I miss to make it work. Below is my code

#include <stdlib.h>
#include <GL/freeglut.h>
#include <math.h>

GLfloat cameraPosition[] = { 0.0, 0.2, 1.0 };

/* Random Star position */
GLfloat starX, starY, starZ;
GLint starNum = 0;

void myIdle(void){
   starNum += 1;

   /* Generate random number between 1 and 4. */
   starX = 1.0 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 3.0));
   starY = 1.0 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 3.0));
   starZ = 1.0 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 3.0));

   /* Now force OpenGL to redraw the change */
   glutPostRedisplay();
}

// Draw a single point
void stars(GLfloat x, GLfloat y, GLfloat z){
   glBegin(GL_POINTS);
   glColor3f(1.0, 0.0, 0.0);
   glVertex3f(x, y, z);
   glEnd();
}

// Draw random points.
void myDisplay(void){
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glEnable(GL_LINE_SMOOTH);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glLoadIdentity();
   gluLookAt(cameraPosition[0], cameraPosition[1], cameraPosition[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

   /* They show up on the screen randomly but they disappear after starNum greater than 100 */
   if (starNum < 100){
      glPushMatrix();
      stars(starX, starY, starZ);
      glPopMatrix();
   }

   /* This point will remain on the screen. */
   glPushMatrix();
   stars(2.0, 2.0, 2.0);
   glPopMatrix();

   /* swap the drawing buffers */
   glutSwapBuffers();
}

void initializeGL(void){
   glEnable(GL_DEPTH_TEST);
   glClearColor(0, 0, 0, 1.0);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glPointSize(2.0);
   glOrtho(-4.0, 4.0, -4.0, 4.0, 0.1, 10.0);
   glMatrixMode(GL_MODELVIEW);
}

void main(int argc, char** argv){
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
   glutInitWindowSize(1800, 1000);
   glutInitWindowPosition(100, 150);
   glutCreateWindow("Random points");

   /* Register display function */
   glutDisplayFunc(myDisplay);

   /* Register the animation function */
   glutIdleFunc(myIdle);

   initializeGL();
   glutMainLoop();
}

Any idea what do I miss?

zihaow
  • 312
  • 2
  • 9
  • 23
  • 3
    What do you expect? You are drawing the stars if `starNum < 100` and wonder why they disappear when this condition is not met any more? I don't understand your surprise. – Nico Schertler Nov 06 '16 at 02:34
  • I want to draw 100 points on the screen and the position of them are random. Basically, I want all the stars remain on the screen. – zihaow Nov 06 '16 at 02:59
  • 4
    OpenGL is not a scene graph API. You need to draw all the stars every time your display function is called. – Reto Koradi Nov 06 '16 at 04:27

2 Answers2

1

To build on what @Reto_Koradi said in his comment, each time your display function is called, you are drawing 2 stars. You're drawing 1 random star (as long as starnum is less than 100), and then you're drawing a star at location (2,2,2). The constant star you see is the one at (2,2,2).

What you probably want to do is something like this:

// Draw random points.
void myDisplay(void){
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glEnable(GL_LINE_SMOOTH);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glLoadIdentity();
   gluLookAt(cameraPosition[0], cameraPosition[1], cameraPosition[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

   /* They show up on the screen randomly but they disappear after starNum greater than 100 */
   for (starnum = 0; starnum < 100; starnum++) {
      glPushMatrix();

      starX = 1.0 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 3.0));
      starY = 1.0 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 3.0));
      starZ = 1.0 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 3.0));

      stars(starX, starY, starZ);
      glPopMatrix();
   }

   /* This point will remain on the screen. */
   glPushMatrix();
   stars(2.0, 2.0, 2.0);
   glPopMatrix();

   /* swap the drawing buffers */
   glutSwapBuffers();
}

And then remove the code that changes the value of starnum and starX, starY and starZ from your myIdle() function.

user1118321
  • 25,567
  • 4
  • 55
  • 86
  • 1. I would not use stars call instead get the whole loop inside `glBegin` `glEnd` ... 2. where are you setting the seed so the random stars are the same all the frames (or the flicker is desired?)? 3. why push pop matrix if it is not used? – Spektre Nov 06 '16 at 08:39
  • My point was not to write the most correct, most efficient answer. It was to help someone who's new at this to understand where the code they wrote went wrong. As such my reply made as much use of the existing code as possible. Once the poster knows its correct, then they can worry about making it efficient. – user1118321 Nov 06 '16 at 15:50
  • I did not mean it as criticism but as additional hints to move forward ... sorry if that was not clear – Spektre Nov 07 '16 at 08:44
  • Sorry, I was raised by wolves. I tend to overreact. In any event, it's all good. Thanks for the clarification. – user1118321 Nov 07 '16 at 17:18
0

As @Reto Koradi mentioned, I need to draw all 100 stars on every time my display function is called. To do that, I need a GLfloat data structure that stores the x, y, z random value at the beginning and then accesses the data array to draw the stars and this will make all of them remain on the screen. Here is the solution to achieve it without the 'myIdle' function, everything is done within the 'myDisplay' function.

/* Data structure for generating stars at random location */
typedef GLfloat star2[100];
star2 randomX = {};
star2 randomY = {};
star2 randomZ = {};

// Draw random points.
void myDisplay(void){
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glEnable(GL_LINE_SMOOTH);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glLoadIdentity();
   gluLookAt(cameraPosition[0], cameraPosition[1], cameraPosition[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

   /* Generate random number of stars */
   if (starNum < 100){
        /* This will store 100 stars' location to a data array. */
        for (starNum = 0; starNum < 100; starNum++) {


        starX = -4.0 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 8.0));
        starY = -4.0 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 8.0));
        starZ = -4.0 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 8.0));

        randomX[starNum] = { starX };
        randomY[starNum] = { starY };
        randomZ[starNum] = { starZ };
        }
    }
    else{
        /* This will draw 100 stars on the screen */
        for (int i = 0; i < starNum; i++){
            glPushMatrix();
            stars(randomX[i],randomY[i], randomZ[i]);
            glPopMatrix();
        }
    }

   /* swap the drawing buffers */
   glutSwapBuffers();
}
zihaow
  • 312
  • 2
  • 9
  • 23