Search code examples
c++openglglutbgicg

Boundary fill algorithm in opengl c++


How can i implement the boundary fill algorithm using opengl and c++ i search online and found this code

  #include <iostream.h>
#include <conio.h>
#include <graphics.h>
#include <dos.h> void bfill(int x,int y,int fill,int border)
{
    if((getpixel(x,y)!=border)&&(getpixel(x,y)!=fill))
    {
        delay(8);
        putpixel(x,y,fill);

        bfill(x+1, y,fill,border);
            bfill(x, y+1,fill,border);
            bfill(x-1, y,fill,border);
            bfill(x, y-1,fill,border);          
    }
}
void main()
{
    int gd=DETECT,gm;
    initgraph(&gd,&gm,"C:\\Tc\\BGI");
    rectangle(10,50,50,10);
    bfill(11,12,MAGENTA,WHITE);
    getch();

but it's using BGI can anyone help?

This is my code:

#include <windows.h> // Header file for Windows
#include <gl/gl.h> // Header file for the OpenGL Library
#include <gl/glu.h> // Header file for the GLu32 Library
#include <gl/glut.h>

#include<iostream>
#include<cmath>



using namespace std;

void draw_XOY(){
glBegin(GL_LINES);
//xox'
glVertex2d(-1000, 0);
glVertex2d(1000, 0);
//yoy'
glVertex2d(0, -1000);
glVertex2d(0, 1000);
glEnd();
}


void dda_line(int x1, int y1, int x2, int y2){
cout<<"Draw Line from "<<"("<<x1<<" , "<<y1<<")"<< " To "<<"("<<x2<<" , "<<y2<<")"<<endl;
float x,y,dx,dy,step;
int i;

glBegin(GL_LINE_STRIP);

dx=x2-x1;
dy=y2-y1;

if(dx>=dy)
step=dx;
else
step=dy;

dx=dx/step;
dy=dy/step;

x=x1;
y=y1;

i=1;
while(i<=step)
{
glVertex2d(x,y);
x=x+dx;
y=y+dy;
i=i+1;
}

glEnd();

cout<<endl<<endl;
}


void draw_up_ellipse(int a, int b, int k, int h){
int x = 0;
int y = 0;

float pi = 3.14121324;

glBegin(GL_POINTS);
for(float i = 0; i <= pi; i+=0.01){
x = a * cos(i) ;
y = b * sin(i) ;
cout<<x<<", "<<y<<endl;
glVertex2d(x+k, y+h);
}
glEnd();
}


void draw_down_ellipse(int a, int b, int k, int h){
int x = 0;
int y = 0;

float pi = 3.14121324;

glBegin(GL_POINTS);
for(float i = pi; i <= 2*pi; i+=0.01){
x = a * cos(i) ;
y = b * sin(i) ;
cout<<x<<", "<<y<<endl;
glVertex2d(x+k, y+h);
}
glEnd();
}


// draw function
static void redraw(void);

//main function
int main(int argc, char **argv)
{
glutInit(&argc,argv); // init the window with args
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); //determine display MODE
glutInitWindowPosition(0,0); //the position of window
glutInitWindowSize(1200,1200); // size w X h
glutCreateWindow("First Example"); // create the window with this title
glutDisplayFunc(redraw); // draw function (contains al drawing stmts.)

glMatrixMode(GL_PROJECTION); // eye = camera look position and 'theta'
gluPerspective(45,1.0,0.1,1000.0); // theta, w/h , near, far
glMatrixMode(GL_MODELVIEW); //return to model view matrix

glutMainLoop(); // re-run
return 0; //return 0
}

// implementation of draw function
static void redraw(void)
{
glClearColor(0.0, 0.0, 0.0, 1.0); // determine clear color
glClearDepth(1.0); // depth clearaty
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // real clear
glLoadIdentity(); // load all init of I (eye to (0,0,0) )

glColor3f(0.0, 0.0, 1.0); // color of drawing geometries
glTranslatef(0.0f,0.0f,-200.0f); // all to back (( to see result))
glColor3f(1.0, 1.0, 1.0); // ???

//pixel size
glPointSize(3);
glLineWidth(2);

draw_XOY();

glColor3f(0.0, 1.0, 0.0);

dda_line(20, 10, 30, 20);
dda_line(30, 20, 40, 10);
dda_line(35, 0, 40, 10);
dda_line(25, 0, 35, 0);
dda_line(25, 0, 20, 10);
dda_line(20, 10, 35, 0);
dda_line(20, 10, 40, 10);
dda_line(35, 0, 30, 20);
dda_line(25, 0, 30, 20);
dda_line(25, 0, 40, 10);



glTranslated(-30,40,0);

glColor3f(1.0, 0.0, 0.0);
dda_line(-40, 0, -30, 0);
dda_line(-30, 0, -20, 0);
dda_line(-20, 0, -10, 0);
dda_line(-10, 0, 0, 0);

glColor3f(1.0, 1.0, 0.0);

draw_up_ellipse(10,8,-10,0);
draw_up_ellipse(15,13,-15,0);
draw_down_ellipse(15,8,-5,0);
draw_down_ellipse(20,13,0,0);

draw_up_ellipse(20,18,-10,0);
draw_up_ellipse(15,13,-15,0);
draw_down_ellipse(30,23,0,0);

draw_up_ellipse(30,23,-10,0);
draw_up_ellipse(35,28,-5,0);

glutSwapBuffers(); // to show frame in back buffer( no noise)
}

And I need to fill this (shape on the left):

screenshot


Solution

  • You got 2 options:

    1. Implement boundary fill

      but that is not how OpenGL works so it would be SLOOOOOW (using glReadPixels for reading individual pixels) unless you copy your screen into CPU side memory (with single glReadPixels call) fill on CPU side (SW rendering) there and then copy back to screen (single textured QUAD covering screen). For more info see:

      just ignore the VCL stuff (the filling does not use it anyway) and convert the pixel array DWORD **pixel=NULL; to your pixel format. Btw using linear 1D array behind will ease up the texture stuff later on. This is how to read entire screen and write it back:

      to read individual pixels you can do:

      BYTE color[3];
      glReadPixels(x,y,1,1,GL_RGB,GL_UNSIGNED_BYTE,color);
      

      in case you do not know what BYTE/DWORD is (and call your self a programmer) BYTE is 8 bit unsigned int and DWORD is 32 bit unsigned int ... some compilers and languages does not have it anymore so if the case use what you have or create it by typedef ...

      You can even port your BGI code (due to your lack of formatting I overlooked the bfill implementation at first look) just write putpixel and getpixel functions with GL counterparts. AND REMOVE THE delay !!! for example:

    2. convert your shape into convex polygons and render as such

      OpenGL can render such shapes with filling natively and fast. Just render as glBegin(GL_POLYGON)/glEnd() or triangulate and use GL_TRIANGLE instead (like ear clipping).

      So instead of rendering your elliptic arces pixel by pixel store them into list of points in CPU side memory. Triangulate or reorder into convex polygons and then render with for loop inside glBegin/glEnd (or use VBO and glDraw)...

      So you would also need to add direction of the arces into your function and some target list of points.