PDA

View Full Version : Plotting Points inside a function



damian89
05-01-2013, 12:40 PM
Hi,

I am doing my first steps with openGL. For a university course I have to implement the Bresenham algorithm, which fills in the appropriate pixels between two points to draw a line. In my example code I cannot see the points the function bresenham() should be drawing. Can anyone help me here?


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <GL/glut.h> // GLUT, include glu.h and gl.h

/* Handler for window-repaint event. Call back when the window first appears and
whenever the window needs to be re-painted. */

void bresenham(int x0, int y0,int x1, int y1){
int deltax = x1 - x0;
int deltay = y1 - y0;
double error = 0;
double deltaerror = abs(deltay/deltax);
int y = y0;
for(int i = 0; i < deltax; i++){ // POINT CREATION IN FOR-LOOP ALLOWED ?
glBegin(GL_POINTS); // HERE THE POINTS SHOULD BE CREATED
glPointSize(8);
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(x0+i,y,0);
glEnd();
error = error + deltaerror;
if (error >= 0.5){
y = y+1;
error = error - 1;
}
}
}

void display() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer (background)

bresenham(100,100,200,140); // HERE THE BRESENHAM FCN IS CALLED

glFlush(); // Render now
}

/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv) {
glutInit(&argc, argv); // Initialize GLUT
glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title
glutInitWindowSize(320, 320); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutDisplayFunc(display); // Register display callback handler for window re-paint
glutMainLoop(); // Enter the event-processing loop
return 0;
}

I think I messed with the order of functions. Thank you very much!

Damian

The Little Body
05-01-2013, 02:14 PM
You have forget a glutSwapBuffers() call at the end your display

And your bresenham implementation have a problem because you use int values instead floats in your division of deltay by deltax at this line


double deltaerror = abs(deltay/deltax);


has to be corrected by



double deltaerror = (double)fabs((float)(deltay)/(float)(deltax));


I have too added one gluOrtho2D(0, 320, 0, 200) call at the begin of the display func for that OpenGL know that vertices values are screen coordinates and not object's coordinates (cf. generally between -1.0f and +1.0f)

Here is your source corrected :


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <GL/glut.h> // GLUT, include glu.h and gl.h

/* Handler for window-repaint event. Call back when the window first appears and
whenever the window needs to be re-painted. */

void bresenham(int x0, int y0,int x1, int y1){

int deltax = x1 - x0;
int deltay = y1 - y0;

double error = 0.0;
double deltaerror = (double)fabs((float)(deltay)/(float)(deltax));

int y = y0;
int i;

int dy = (deltay > 0 ? 1 : -1);

if ( deltax > 0 )
{
for( i = 0; i < deltax; i++){ // POINT CREATION IN FOR-LOOP ALLOWED ?

glBegin(GL_POINTS); // HERE THE POINTS SHOULD BE CREATED
glPointSize(8);
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(x0 + i, y, 0);
printf("(%d,%d) \n", x0+i , y);
glEnd();

error += deltaerror;
if (error >= 0.5){
y += dy;
error -= 1.0f;
}
}
}
else
{
for( i = deltax; i < 0 ; i++){ // POINT CREATION IN FOR-LOOP ALLOWED ?

glBegin(GL_POINTS); // HERE THE POINTS SHOULD BE CREATED
glPointSize(8);
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(x0 + i, y, 0);
printf("(%d,%d) \n", x0+i , y);
glEnd();

error = error + deltaerror;
if (error >= 0.5){
y += dy;
error -= 1.0f;
}
}
}
}

void display() {

gluOrtho2D(0, 320, 0, 200);

glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer (background)

bresenham(0,0, 320,200); // HERE THE BRESENHAM FCN IS CALLED

glFlush(); // Render now
glutSwapBuffers();

}

/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv) {
glutInit(&argc, argv); // Initialize GLUT
glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title
glutInitWindowSize(320, 320); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutDisplayFunc(display); // Register display callback handler for window re-paint
glutMainLoop(); // Enter the event-processing loop
return 0;
}


Note that it print computed coordinates at the terminal output for that you can see generated coordinates
=> comment the two fprintf lines into the bresenham func if you don't want them

PS : you can too use only one glBegin() call at the begining and one glEnd() at the end in the bresenham function instead to make this for each computed point
(and only one call to glPointSize() and glColor3f() at the beginning since point sizes and colors are always the sames)

The Little Body
05-01-2013, 03:31 PM
There is a problem on the last bresenham function when the line is more vertical than horizontal :(

Here a corrected version where you can too :

- dynamically resize the window,
- change the color with the keyboard (r=red g=green b=blue w=white)
- change the point size (+ or -)
- quit using the ESC key



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <GL/glut.h> // GLUT, include glu.h and gl.h

int width = 320;
int height= 200;

int pointSize = 1;
float red = 1.0f;
float green = 1.0f;
float blue = 1.0f;

/* Draw a line between (x0,y0) and (x1, y1) using the Bresenham algorithm */
void bresenham(int x0, int y0,int x1, int y1){

int i, length;

int y = y0;
int x = x0;

int deltax = x1 - x0;
int deltay = y1 - y0;

float error = 0.0;
float deltaerror;

int incy = (deltay > 0 ? 1 : -1);
int incx = (deltax > 0 ? 1 : -1);

glBegin(GL_POINTS);

if ( abs(deltax) >= abs(deltay) )
{
length = abs(deltax);
deltaerror = fabs((float)(deltay)/(float)(deltax));

for( i = 0; i <= length; i++, x+= incx)
{
glVertex3f(x, y, 0);
// printf("point(%d,%d) \n", x , y);

error += deltaerror;
if (error >= 0.5)
{
y += incy;
error -= 1.0f;
}
}
}
else
{
length = abs(deltay);
deltaerror = fabs((float)(deltax)/(float)(deltay));

for( i = 0; i <= length ; i++, y += incy)
{
glVertex3f(x, y, 0);
// printf("point(%d,%d) \n", x , y);

error = error + deltaerror;
if (error >= 0.5)
{
x += incx;
error -= 1.0f;
}
}
}

glEnd();
}

/* Handler for window-repaint event. Call back when the window first appears and whenever the window needs to be re-painted. */
void display()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer (background)

bresenham(0,0, width,height);
bresenham(0,height, width, 0);
bresenham(width/2,0, width/2,height);
bresenham(0,height/2, width, height/2);

glFlush(); // Render now
glutSwapBuffers();
}

/* Handler for window event resize */
void reshape(GLsizei newwidth, GLsizei newheight)
{
width = newwidth;
height = newheight;

// printf("Reshape(%d,%d) \n", width, height);
glViewport(0, 0, width, height);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glutPostRedisplay();
}

/* Handler for keyboard events */
void keyboard(unsigned char key, int x, int y )
{
switch(key)
{
case '+' : pointSize++; break;

case '-' : if( pointSize > 0) pointSize--; break;

case 'r': red=1.0f; green=blue=0.0f; break;

case 'g': green=1.0f; red=blue=0.0f; break;

case 'b': blue=1.0f; red=green=0.0f; break;

case 'w' : red=green=blue=1.0f; break;

case 27 : exit(0); break;

break;
}

glPointSize(pointSize);
glColor3f(red, green, blue);

glutPostRedisplay();
}


/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv)
{
glutInit(&argc, argv); // Initialize GLUT
glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title
glutInitWindowSize(width, height); // Set the window's initial width & height
gluOrtho2D(0, width, 0, height); // Init screen coordinates use in the display func
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner

glutKeyboardFunc(keyboard); // Register keyboard handler for keyboard actions
glutReshapeFunc(reshape); // register resize callback handler for window resize
glutDisplayFunc(display); // Register display callback handler for window re-paint

glutMainLoop(); // Enter the event-processing loop

return 0;
}


Note, that you can make the glBegin(GL_POINTS)/glEnd() calls outside the bresenham() function if you want
(only call glBegin(GL_POINTS) before and glEnd() after the bloc of 4x bresenham()'s calls in the display() function)

Cf. minimize the use of glBegin()/glEnd() calls because they can to spend more time to execute than alls glVertex() calls used between them when you have only a small number of vertices to draw ...
(but in this precise case, I don't think that this can really make a big difference because lines traced here by the bresenham() function are relatively longs, so we don't have a relatively small number of points to display for each line as we don't use a too small window size :) )