Opengl,C++ : Large number of points - c++

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;
}

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.

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.

Related

how do i calculate glFrustum parameters?

I have this code:
/*
* This is a simple program that computes FPS
* by means of a circular buffer
*/
#include <GL/glut.h>
//#include <numeric>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
// Number of elements in the circular buffer
#define NELS 10
// Number of lines
#define NLINES 10000
// circular buffer used to compute frame rate
float circularBuffer[NELS];
int firstInd = 0, nEls = 0;
// function to get the number of elapsed ticks
uint32_t getTick()
{
struct timespec ts;
unsigned theTick = 0U;
clock_gettime( CLOCK_REALTIME, &ts );
theTick = ts.tv_nsec / 1000000;
theTick += ts.tv_sec * 1000;
return theTick;
}
// Function to compute real modulus and NOT remained as % does
inline int modulo(int a, int b) {
const int result = a % b;
return result >= 0 ? result : result + b;
}
// Compute sum of the elements in the circular buffer
float sumCircularBuffer()
{
int ind;
float sum = 0;
if (nEls > 0) {
for (ind=1; ind<=nEls; ind++) {
sum = sum + circularBuffer[modulo(firstInd-ind, NELS)];
}
}
return sum;
}
// accumulate buffer and update window title
void computeAndShowFrameRate(void)
{
static float lastTime = 0.0f;
static unsigned int frameCount = 0;
char windowTitle[100];
float sumFPS;
float currentTime = (float)getTick() * 0.001f;
// Initialize lastTime to the current time
if (lastTime == 0) {
lastTime = currentTime;
}
// increase frame count
frameCount++;
if (currentTime - lastTime > 1.0f) {
// insert the current fps in the circular buffer
circularBuffer[firstInd] = ((float)frameCount) / (currentTime - lastTime);
// update variable lastTime
lastTime = currentTime;
//circularBuffer[firstInd] = (float)frameCount;
firstInd = ((firstInd+1)%NELS);
if (nEls < NELS) {
nEls++;
}
frameCount = 0;
// sum elements in circular buffer
sumFPS = sumCircularBuffer();
snprintf(windowTitle, 100, "FPS = %6.2f", sumFPS/nEls);
// update window title
glutSetWindowTitle(windowTitle);
}
}
// display function
void display(void)
{
int currLineInd;
// get current frame rate
computeAndShowFrameRate();
// clear buffer
glClear (GL_COLOR_BUFFER_BIT);
for (currLineInd = 0; currLineInd<NLINES; currLineInd++) {
// draw line
glBegin(GL_LINES);
// random color
glColor3f((float)rand()/RAND_MAX, (float)rand()/RAND_MAX, (float)rand()/RAND_MAX);
// random first point
glVertex2f((float)rand()/RAND_MAX, (float)rand()/RAND_MAX);
// random color
glColor3f((float)rand()/RAND_MAX, (float)rand()/RAND_MAX, (float)rand()/RAND_MAX);
// random second point
glVertex2f((float)rand()/RAND_MAX, (float)rand()/RAND_MAX);
glEnd();
}
glFinish();
glutPostRedisplay();
}
// initialization function
void init (void)
{
// Use current time as seed for random generator
srand(time(0));
// select clearing color
glClearColor (0.0, 0.0, 0.0, 0.0);
// Orthographic projection
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}
// Window size and mode
int main(int argc, char** argv)
{
// pass potential input arguments to glutInit
glutInit(&argc, argv);
// set display mode
// GLUT_SINGLE = single buffer window
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (400, 400);
glutInitWindowPosition (100, 100);
glutCreateWindow ("OpenGL Window");
// Call initialization routinesx
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
I have to replace the glOrtho function with glFrustum and get the same result.
I read the opengl guide on khronos and understood the differences between glOrtho and glFrustum but i can't figure out how to calculate the parameters.
How do I calculate the parameters to pass to the glFrustum function?
glFrustum() require 6 parameters to specify 6 clipping planes: left, right, bottom, top, near and far planes. A visual representation would be like this:
The values that will come up with depend on your implementation and the scale of the models you are working with. As mentioned above, if the projected geometry is in front of the near plane or behind the far plane it will be clipped thus it won't be visible.
To solve this you either have to recompute the parameters for the glFrustum() function(bad idea) or move the camera/scene along the z-axis.
References:
http://www.songho.ca/opengl/gl_transform.html
https://learnopengl.com/Getting-started/Coordinate-Systems
With Perspective projection the distnace to the near and far plane have to be grater than 0,
0 < near < far
because you want to define a Viewing frustum:
If the distance to the near plane is less than 0, the result is undefined (Usually the instruction has no effect at all).
See glFrustum:
void glFrustum( GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top,
GLdouble nearVal,
GLdouble farVal);
The distances left, right, bottom and top, are the distances from the center of the view to the side faces of the frustum, on the near plane. near and far specify the distances to the near and far plane of the frustum.
The geometry has to be between the near and the far plane, else it is clipped. Therefore, you have to move the shift along the z-axis in the negative direction (in negativ direction, because the view space z-axis points out of the view):
// initialization function
void init (void)
{
// [...]
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-0.1, 0.1, -0.1, 0.1, 0.1, 50.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -5.0f);
}

Cutting the bottom side of a circle

// #include loads up library files, the order can matter
// generally load glut.h last
#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>
// this is the initialisation function, called once only
void init() {
glClearColor(0.0, 0.0, 1.0, 0.0); // set what colour you want the background to be
glMatrixMode(GL_PROJECTION); // set the matrix mode, we will look at this later
// set the projection window size in x an y.
gluOrtho2D(0.0, 500, 0.0, 500.0);
}
// this is the display function it is called when ever you want to draw something
// all drawing should be called form here
void circle() {
// draw circle
float theta;
glClear(GL_COLOR_BUFFER_BIT); // clear the screen using the background colour
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0); // set colour to red
for (int i = 0; i < 320; i++) {
theta = i * 3.142 / 180;
glVertex2f(190 + 50 * cos(theta), 250 + 70 * sin(theta));
}
glEnd();
glFlush(); // force all drawing to finish
}
// this has the effect of repeatedly calling the display function
void display() {
circle();
}
// as with many programming languages the main() function is the entry point for execution of the program
int main(int argc, char** argv) {
glutInit(&argc, argv); //perform the GLUT initialization
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // more initialisation
glutInitWindowSize(800, 600); // set window position
glutInitWindowPosition(0, 0); // set window size
glutCreateWindow("Circle"); // create a display with a given caption for the title bar
init(); // call init function defined above
glutDisplayFunc(display); // define what function to call to draw
// the last function in the program puts the program into infinite loop
glutMainLoop();
// this line exits the program
return 0;
}
I've added comments so you can understand my code. The code creates a big red circle, and cuts the bottom right side of the circle, but I want to the cut only the bottom side. How can I achieve this? I would really appreciate the help.
Like this:
If you want to cut a circle by a Secant line, then you have to define an start angle and an end angle and to specify the vertex coordinates form the point on the circle with the start angle to the point with the end angle.
A Full angle has 360 degrees (2*PI radians). The bottom (south) has an angle of -90 degrees.
If you want to cut a part at the bottom of the circle, then the start and the end angle can be calculated like this:
int cutsegment = 45;
int start = -90 + cutsegment / 2;
int end = 270 - cutsegment / 2;
for (int i = start; i <= end; i++) {
theta = i * 3.142 / 180;
glVertex2f(190 + 50 * cos(theta), 250 + 70 * sin(theta));
}

OpenGl glutIdleFunc Animation

My problem
I am still learning opengl and I was working on a game similar to chicken invaders. What I am trying to do is to have a background similar to that of chicken invaders with some stars and galaxy. I did that using a quad with the size of the screen that I added texture to. Up until now all is good but I am now trying to translate this galaxy background downward so that the spaceship and the chicken seem as if they are moving forward through space. My idea is to used glutIdleFunc() function and on every iteration, I should sleep first for 30 milliseconds then update the galaxy background so that every row of pixels is moved downward by 1 row and the last row is copied to the first row. The problem is that this approach works fine for the about 15 seconds then the program stops completely and my computer hangs and freezes to the extent that I need to restart my pc. I think my approach requires ridiculously many operations every time glutIdleFunc() is called. I searched for people who faced similar situations online but I found no similar post.
code:
main function
int main(int argc, char** argr) {
glutInit(&argc, argr);
glutInitWindowSize(SCREEN_WIDTH, SCREEN_WIDTH);
// background is a global variable that contains the bitmap array
int err = load_image("Art/background.bmp", &background);
if(err)
{
fprintf(stderr, "%d\n", err);
exit(1);
}
glutCreateWindow("OpenGL - 2D Template");
glutDisplayFunc(Display);
glutMotionFunc(mo);
glutMouseFunc(mou);
glutIdleFunc(Animate);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
gluOrtho2D(0.0, 1000, 0.0, 600);
glutMainLoop();
}
Animation
void Animate(void)
{
msleep(300);
translate_image(&background, 30);
glutPostRedisplay();
}
void translate_image(image_t* img, const int c)
{
uint32_t copy[img->height][img->width];
for(int i = 0; i < img->height; i++)
{
for(int j = 0; j < img->width; j++)
{
copy[i][j] = img->data[i * img->width + j];
}
}
for(int i = 0; i < img->height; i++)
{
for(int j = 0; j < img->width; j++)
{
int index = (i + c) % img->height;
img->data[index * img->width + j] = copy[i][j];
}
}
}
Display Function
void Display() {
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
texture = glInitTexture(background);
drawImage(texture, 0.0f, 0.0f, background.width, background.height);
glDisable(GL_TEXTURE_2D);
drawSpaceShip();
glFlush();
}
Main question
is There a more efficient way to do the same thing I am trying to do with freezing my computer every time I run it ?
You don't have to copy around the picture contents. It suffices to animate the texture coordinates, which you use to map the picture to the quad.
Also you must call glutInitDisplayMode before glutCreateWindow for it to have an effect. Also you don't want a single buffered framebuffer, but a double buffered one GLUT_DOUBLE instead of GLUT_SINGLE and call glutSwapBuffers instead of glFinish.

GLUT individual pixel manipulation produces unexpected result

For the sake of learning, I'm accessing individual pixel data using GLUT and manually setting pixel color by going through all pixels in the window, like this (some non-related code omitted):
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, WIDTH, 0.0, HEIGHT);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
glPointSize(1.0f);
glColor3f(255, 0, 0);
glBegin(GL_POINTS);
glVertex2i(i, j);
glEnd();
}
}
glutSwapBuffers();
}
void timer(int obsolete) {
glutPostRedisplay();
glutTimerFunc(16, timer, 0);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition(100, 100);
glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow("GLUT Test");
init();
glutDisplayFunc(display);
timer(0);
glutMainLoop();
return 0;
}
I'm expecting to get a fully red pixels window, but I'm getting something different - a window with black vertical stripes, as if horizontal for loop suddenly skipped some lines.
Any ideas what am I doing wrong here? I have a suspicion it might be related to float to int conversion somewhere "inside", but I'm not sure what to search for.
Edit: I've found out that if I resize the window in runtime to be one pixel less in width, then these black stripe tears disappear.
You set up the projection such that the left edge is at 0, and the right one at WIDTH. Note that your pixels are small squares with an area, and this means that 0.0 maps to the left edge ot the left-most pixel, and WIDTH maps to the right edge of the right-most pixel. Integer coordinates will lie exactly in the middle between two pixels. And with some numerical precision loss during transformation, you might end up with two neighboring points beeing rounded to the same pixel.
You can either add 0.5 to x and y when drawing your points, or just shift your orth projection by half a pixel so that integers are mapped to pixel centers:
Ortho(-0.5f, WIDTH-0.5f, -0.5f, HEIGHT-0.5f, ...);

How to make 2d Chess Board in OpenGl

I have to make a 2d Chess Board of 8 * 8 blocks in OpenGL with VisualC++. I have the following code that i tried .
But I have a problem in this code .
I can't reduce the board size. e.g. 5*5.
When i click on the window it redraws the board.
I want to make this code to just work with loops. Except If , Else.
#include<GL\glut.h>
int black=0,white=1,color=0;
GLint a1=10,b1=10,a2=30,b2=30;
void init (void)
{
glClearColor (0.0, 0.0,1.0,0.0);
glMatrixMode (GL_PROJECTION);
glClear (GL_COLOR_BUFFER_BIT);
gluOrtho2D (0.0,120.0,0.0,140.0);
}
void lineSegment ()
{
for(int i=0;i<3;i++)
{
if(b2<120)
{
a1=10;b1=b2;
a2=30;b2=b2+20;
}
for(int j=0;j<5;j++)
{
if(a2<120)
{
if(color==black)
{
glColor3f(0,0,0);
glRecti(a1,b1,a2,b2);
color=1;
a1=a2;
a2=a2+20;
}
else
{
glColor3f(1,1,1);
glRecti(a1,b1,a2,b2);
color=0;
a1=a2;
a2=a2+20;
}
}
}
//GLint a1=10,b1=10,a2=30,b2=30;
}
glFlush();
}
void main (int argc, char** argv)
{
glutInit(&argc,argv); //Initialize GLUT.
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); // Set display mode.
glutInitWindowPosition (50,100); //Set top-left display-window position.
glutInitWindowSize (400,300); //Set display-window width and height.
glutCreateWindow ("An Example OpenGL Program"); //Create display window.
init(); // Execute initialization procedure.
glutDisplayFunc(lineSegment); //send graphics to display window.
glutMainLoop(); //display everything and wait.
}
Im going to suggest you significantly reduce the code you are working with. Define a width and height for the board and the number of divisions per side of the board.
Lets define width and height as w and h respectively and the number of divisions n and m respectively. w.l.o.g. assume n and m divide w and h evenly.
void DrawBoard(int w, int h, int n, int m) {
bool color = true;
int sw = w/n, sh = h/m; //square width and height respectively
//for each width and height draw a rectangle with a specific color
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j) {
//oscillate the color per square of the board
if(color)
glColor3f(1, 1, 1);
else
glColor3f(0, 0, 0);
color = !color;
//draw a rectangle in the ith row and jth column
glRecti(i*sw, j*sh, (i+1)*sw, (j+1)*sh);
}
if(m % 2 == 0) color = !color; //switch color order at end of row if necessary
}
}
This should give the basic idea, though I might have hessed up an index or two. But essentially, iterate over the grid cells and draw a rectangle per board square.
This code will also draw the board starting at coordinate (0, 0) and finishing at (w, h). However if you would like it in an arbitrary position you can either add an (x, y) to eaxh corresponding coordinate in the glRecti call, or learn about transforms in openGL and use glTranslatef.