Plotting Points inside a function

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

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) 
", 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) 
", 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)

There is a problem on the last bresenham function when the line is more vertical than horizontal :frowning:

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) 
", 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) 
", 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) 
", 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 :slight_smile: )