0

I'm currently working on a program, that will be able to visualize the evolution of point on the plane that are flowing along a vectorfield. I've finished the first version which I've pasted below. When running the program with a large number of points it seems that only the last say 30000 points gets drawn into the window. I'd like to be able to draw about 1000000 points, so I'm way off.

I've tried lovering the number if iterations (the Iteration variable - controlling the number of points), and here it acts just fine. However when increasing it substantially the first part is no longer drawn.

#include <iostream>
#include <stdio.h>
#include <math.h>
//#include <gsl/gsl_math.h>
//#include <gsl/gsl_sf.h>
#include <GL/freeglut.h>
#include <GL/gl.h>

using namespace std;

//Initial iterations to make the system settle:
int initIter=0;
//Iterations once system has settled:
int Iterations = 100000;
/**Starting point in time-phase-space (t,x,y,vx,vy).
For mathematical reasons the last two components should
always be 0**/
float TPS[5]={0,0.00,0.100,0.00,0.000};
//Timestep:
float dt=0.001;




/**The Step function make one Picard
iteration **/
float * Step(float * Arr){
static float NewTPS[5];
NewTPS[0] = Arr[0]+dt;
NewTPS[1] = Arr[1]+Arr[3]*dt;
NewTPS[2] = Arr[2]+Arr[4]*dt;
//This is the dynamical functions:
NewTPS[3] = -Arr[2];
NewTPS[4] = Arr[1];
return NewTPS;
}




/** This function sets up GLUT plotting
window: **/
void myInit(){
 // set the background color
 glClearColor(0.0f, 0.0f, 0.0f, 1.00f);

 // set the foreground (pen) color
  glColor4f(1.0f, 1.0f, 1.0f, 0.04f);

 // set up the viewport
  glViewport(0, 0, 800, 800);

 // set up the projection matrix (the camera)
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluOrtho2D(-2.0f, 2.0f, -2.0f, 2.0f);

 // set up the modelview matrix (the objects)
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

 //Computing initial iterations:
  for (int i=0;i<initIter;i++){
   //cout << TPS[1]<<" " << TPS[2] << endl;
   float * newTPS2;
   newTPS2 = Step(TPS);
   //Assigning the values of newTPS2 to TPS:
    for (int j=0; j<5;j++){
     TPS[j]=*(newTPS2+j);
 }
  }

 // enable blending
  //glEnable(GL_BLEND);
  //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

 // enable point smoothing
  //glEnable(GL_POINT_SMOOTH);  
  //glPointSize(1.0f);
 }





/** This function draws a the point that
is passed to it: **/
 void Draw(){
 // clear the screen
  glClear(GL_COLOR_BUFFER_BIT);

 // draw some points
  glBegin(GL_POINTS);
  for (int i = 0; i <Iterations ; i++) {
   float * newTPS2;
   //cout << TPS[0]<< " " << TPS[1] << " " << TPS[2]<< endl;
    newTPS2 = Step(TPS);
    //Assigning the values of newTPS to TPS:
    for (int j=0; j<5;j++){
     TPS[j]=*(newTPS2+j);
}   
  // draw the new point
   glVertex2f(TPS[1], TPS[2]);
   }    
  glEnd();

  // swap the buffers
  glutSwapBuffers();
  //glFlush();
  }



  int main(int argc, char** argv){
  // initialize GLUT
  glutInit(&argc, argv);

  // set up our display mode for color with alpha and double buffering
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);


  glutInitWindowSize(800, 800);
  glutCreateWindow("Trace of 2D-dynamics");
  myInit();
  // register our callback functions
  glutDisplayFunc(Draw);
  //  glutKeyboardFunc(mykey);

  // start the program
  glutMainLoop();
  return 0;
  }
genpfault
  • 51,148
  • 11
  • 85
  • 139
Martin
  • 103
  • 3
  • 2
    `glVertex2f` is deprecated. You probably want to be learning modern OpenGL, not 1990s OpenGL: http://www.arcsynthesis.org/gltut/. Particularly if you want things to scale well. – Flexo Feb 24 '13 at 12:20
  • Thank you for the link - will have a look at it. – Martin Feb 24 '13 at 12:28
  • All of your OpenGL is reasonably correct; I suspect the problem lies elsewhere. In particular, your call to `gluOrtho2D` restricts all of your particles to the range [-2,2] in x and y. Are you sure all of your numerical integrations (and hence particular positions) stay within that range? – radical7 Feb 24 '13 at 14:27
  • My particles will leave that window for sure. I'm okay with that - however it seems that the early plotted points vanish, for some reason. I've tried bypassing the Step-routine and generating some float values just before plotting. Here all particles seem to be plotted - even in the millions. So can bad things happen when i leave my window? Also at some point Step returns inf, -inf or nan - but the "missing point"-problem seems to set in much earlier. – Martin Feb 24 '13 at 15:05
  • Heres an update: I've tried to plot as little as 9000 points - the spiral shape, that gets drawn isn't starting from the right place - hinting that points have been lost. However using cout to view the datapoints directly nothing is missing. – Martin Feb 24 '13 at 15:27

2 Answers2

5

If you want to just color specific pixels on the screen, you should't be using glVertex at all. Put them all in a contiguos memory block, create a texture from it and render a quad covering the whole screen. That might be faster than calculating their positions inside OpenGL.

Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135
  • Actually, I don't see a problem using `glVertex` in this instance (except perhaps for one's distaste in using older-style OpenGL). What the OP wants to do is merely plot a collection of 2D points (ignoring the speed characteristics, of which there are ways around [e.g., VBOs]), this is the way to go. It simply solves the problem without the programmer needing to effectively write a rasterizer. It's a "style" (use modern OpenGL because it's the cool way) vs. a "productivity" thing (get your job done). – radical7 Feb 24 '13 at 14:32
-2

Probably in your implementation the size of a primitive is limited to a signed short, that is 32768 points. If that is the case you have to do glEnd/glBegin for each group of 32768 points or so:

for (int i = 0, x = 0; i <Iterations ; i++, x++) {
    //...
    if (x >= 32768)
    {
        x = 0;
        glEnd();
        glBegin(GL_POINTS);
    }
    //...
}

BTW, you may consider using vertex buffer objects (VBO). This limitation is likely the same, but are quite faster to draw.

rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • Seems your right about the limitation to 32768 pixels. Thanks - and I'll take a look at VBO. – Martin Feb 24 '13 at 12:53
  • @rodrigo No, that's not correct. There's no such limit in OpenGL for the number of vertices you can sent between a `glBegin`/`glEnd` pair, and particularly for `GL_POINTS`. Depending on the primitive type (e.g., `GL_POINTS`), and when OpenGL receives that many vertices, it will rasterize that geometric primitive. Have a look at (provoking vertex)[https://www.opengl.org/wiki/Primitive#Provoking_vertex]. BTW, this holds true regardless if you're using begin/end semantics, or VBOs and `glDrawArrays` or `glDrawElements`. – radical7 Feb 24 '13 at 14:24