CG Lab Programs

 Note: Blue Lines Indicate Comment Lines

Programs Covered

1) Sierpinski Gasket in a Tetrahedron      (Explained)
2) House Rotation                                    (Not Explained)
3) Liang-Barsky Parametric Line Clipping(Explained

* 4)Cohen-Sutherland Line Clipping   (Yet to Prepare)
5)Scanline-Area Filling Algorithm (next Lab program)

 

1) Sierpinski Gasket in a Tetrahedron 

 1) Write an OpenGL Program to recursively subdivide a tetrahedron to from 3D Sierpinski gasket. The number of recursive steps is to be specified by the user.
#include<stdlib.h>
#include<stdio.h>
#include<GL/glut.h>
GLfloat v[4][3]={{0.0,0.0,1.0},{0.0,1.0,0.0},
                     {-1.0,-0.5,0.0}, {1.0,-0.5,0.0}};
GLfloat colors[4][3]={{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0},{0.0,0.0,0.0}};
int n;
void triangle(GLfloat *va,GLfloat *vb,GLfloat *vc)
{
        glVertex3fv(va);
        glVertex3fv(vb);
        glVertex3fv(vc);
}
void tetra(GLfloat *a,GLfloat *b,GLfloat *c,GLfloat *d)
{
    glColor3fv(colors[0]);
    triangle( a, b, c);
    glColor3fv(colors[1]);
    triangle( a, c, d);
    glColor3fv(colors[2]);
    triangle( a, d, b);
    glColor3fv(colors[3]);
    triangle( b, d, c);
}

void divide_tetra(GLfloat *a,GLfloat *b,GLfloat *c,GLfloat *d,int m)
{
    GLfloat mid[6][3];
    int j;
    if(m>0)
    {    /*compute six midpoints*/
        for(j=0;j<3;j++) mid[0][j]=(a[j]+b[j])/2;
        for(j=0;j<3;j++) mid[1][j]=(a[j]+c[j])/2;
        for(j=0;j<3;j++) mid[2][j]=(a[j]+d[j])/2;
        for(j=0;j<3;j++) mid[3][j]=(b[j]+c[j])/2;
        for(j=0;j<3;j++) mid[4][j]=(c[j]+d[j])/2;
        for(j=0;j<3;j++) mid[5][j]=(b[j]+d[j])/2;
        divide_tetra(a,mid[0],mid[1],mid[2],m-1);
        divide_tetra(mid[0],b,mid[3],mid[5],m-1);
        divide_tetra(mid[1],mid[3],c,mid[4],m-1);
        divide_tetra(mid[2],mid[5],mid[4],d,m-1);
    }
    else
        tetra( a, b, c, d);      //draw triangle at end of recursion//
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glBegin(GL_TRIANGLES);      // This glBegin is to draw triangles taking three
    divide_tetra(v[0],v[1],v[2],v[3],n); // vertices at a time. divide_tetra calls itself
    glEnd();                                 //  and finally tetra which calls triangle four times
                                                         // which in-turn calls vertex function.

    glFlush();                                 // Call flush at the end to send output to screen
                                                                // making the gasket visible

}

void myReshape(int w,int h)
{
    glViewport(0,0,w,h);                 // Set the viewport to span the entire window
glMatrixMode(GL_PROJECTION);//Change the matrix mode to GL_PROJECTION
    glLoadIdentity();                       // Load the identity matrix to GL_PROJECTION
    glOrtho(-2.0,2.0,-2.0,2.0 ,-10.0,10.0);//Multiply orthographic projection matrix
                             // to this GL_PROJECTION matrix to change projection type to
                                                                  // Orthographic

glMatrixMode(GL_MODELVIEW);//Change the matrix mode to GL_MODELVIEW
    glutPostRedisplay();     //Arrange or fix or appoint or schedule a call to display
                                                          // function  as soon as possible
.
}

int main(int argc,char **argv)//Comments for main included only in this program
{
printf("enter the no of division ");
scanf("%d",&n);
glutInit(&argc,argv);                                  // Initialize the graphics system
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
                                                   // Initialize the display mode
                             // to use a single buffer in the frame buffer and not DOUBLE                                       // and to use RGB color system(and not CMYK)
                                             // and to make use of DEPTH buffer since this
                                                      // is a 3D program

glutInitWindowSize(500,500);       // Initialize window size
glutCreateWindow("3d gasket");   // Create a window
glutReshapeFunc(myReshape);//Register the reshape function for call back when
                                                       // current window size changes.

glutDisplayFunc(display);       // Register the display function for call back.
                                       // Display function is called when ever the contents of
                            // the window changes as in an animation or any overlapping
                       //window gets closed and our window needs to be redrawn or our
                    // window changes shape or our window gets maximized and hence
                                     // visible from invisible

glEnable(GL_DEPTH_TEST);
                        // Enable hidden surface removal or visible surface determination
                            // this test is usually enabled in conjunction with use of
                            // GLUT_DEPTH in glutInitDisplayMode and hence only in 3D
                                         // programs

glClearColor(1.0,1.0,1.0,1.0);        // Set the background color to white
glutMainLoop();     // most important line of every program. This calls the event
                               // loop which is an infinite loop. It terminates when program
                          // is terminated. It is responsible for calling the display function, 
                           // the mouse function, the reshape function the idle function, the
                     // keyboard function, the special keyboard  function at appropriate
                         // times during the running of the program.

return 0;
}

 

 

Out Put:

enter the no of division : 2

 

2) House Rotation

  Write an OpenGL Program to create a house like figure and rotate it about  a given fixed point using OpenGL functions.

#include<stdio.h>
#include<math.h>
#include<GL/glut.h>
GLfloat house[2][9]={{100.0,100.0,175.0,250.0,250.0,150.0,150.0,200.0,200.0},        {100.0,300.0,400.0,300.0,100.0,100.0,150.0,150.0,100.0}};
GLfloat theta;
GLfloat h=100.0;
GLfloat k=100.0;
void drawhouse()
{
    glColor3f(1.0,0.0,0.0);
    glBegin(GL_LINE_LOOP);
    glVertex2f(house[0][0],house[1][0]);
    glVertex2f(house[0][1],house[1][1]);
    glVertex2f(house[0][3],house[1][3]);
    glVertex2f(house[0][4],house[1][4]);
    glEnd();
    glColor3f(1.0,0.0,1.0);
    glBegin(GL_LINE_LOOP);
    glVertex2f(house[0][5],house[1][5]);
    glVertex2f(house[0][6],house[1][6]);
    glVertex2f(house[0][7],house[1][7]);
    glVertex2f(house[0][8],house[1][8]);
    glEnd();
    glColor3f(1.0,0.0,0.0);
    glBegin(GL_LINE_LOOP);
    glVertex2f(house[0][1],house[1][1]);
    glVertex2f(house[0][2],house[1][2]);
    glVertex2f(house[0][3],house[1][3]);
    glEnd();
}
void display()
{
    int i;
    GLfloat m[16],p,q;
    p=-h*(cos(theta)-1)+k*(sin(theta));
    q=-k*(cos(theta)-1)-h*(sin(theta));
    for(i=0;i<15;i++)
        m[i]=0.0;
    m[0]=cos(theta);
    m[1]=sin(theta);
    m[4]=-sin(theta);
    m[5]=cos(theta);
    m[12]=p;
    m[13]=q;
    m[10]=1;
    m[15]=1;
    glMatrixMode(GL_MODELVIEW);
    glClear(GL_COLOR_BUFFER_BIT);
    drawhouse();
    glPushMatrix();
    glMultMatrixf(m);
    drawhouse();
    glPopMatrix();
    glFlush();
}
void myinit()
{
    glClearColor(1.0,1.0,1.0,1.0);
    glColor3f(1.0,1.0,0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0,499.0,0.0,499.0);
    glMatrixMode(GL_MODELVIEW);
}
int main(int argc,char **argv)
{

    printf("enter the rotation angle\n");
    scanf("%f",&theta);
    theta=theta*3.141/180;
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowSize(500,500);
    glutInitWindowPosition(0,0);
    glutCreateWindow("rotated house");
    glutDisplayFunc(display);
    myinit();
    glutMainLoop();
    return 0;
}


Input:
enter  the rotation angle
-30

 

3) Liang-Barsky Parametric Line Clipping

  Write an OpenGL Program to implement Liang-Barsky line clipping algorithm.
/* Hi There this program is difficult to understand and its my goal to make you understand. This is a parametric line clipping algorithm. The parameter t is a fraction between 0 and 1. So your lessons in ratios in school are useful in this program. The thing is if we know the parameter t on a line from (x1,y1) to (x2,y2) we can find any point(x,y) on the line by:
x=x1+t*dx;
y=y1+t*dy;
where dx and dy are x2-x1 and y2-y1 respectively. So starting from (x1,y1) t gives an idea of how much far have we gone towards (x2,y2).
For clipping we find t value of intersection points. There are four intersection points of a line with four edges of the window. If at an intersection point if line is going into the window it means it is a potentially entering point. If intersection point is such that line is leaving the window then it is potentially leaving. We consider lines going from left to right and bottom to top. Argument holds if line is in any other direction.

In this figure Line number 1 looks proper and its part is inside the window. It starts with line entering bottom edge then entering left edge then leaving top edge and then leaving right edge.
Something wrong with Line Number 2. It enters bottom edge then leaves top edge and then enters left edge and then leaves right edge(not shown). So since entering intersection point has crossed over after the leaving intersection point. Hence the line is rejected.
Lines no. 3 are horizontal and dy=0 so they go to third condition in cliptest function and are rejected.
Ditto with lines no 4. where dx=0;
*/
#include<stdio.h>
#include<GL/glut.h>

double xmin=50, ymin=50, xmax=100,ymax=100; //window boundaries
double xvmin=200,yvmin=200,xvmax=300, yvmax=300; //viewport boundaries
int x1,y1,x2,y2;
int cliptest(double p,double q,double *t1,double *t2)
{      // p is denominator in division and q is numerator                 
// t1 is t entering and t2 is t leaving
    double t=q/p;
    if(p<0.0)        //potentially entry point ,update te
    {    if(t>*t1) *t1=t;
        if(t>*t2) return(0); //line portion is outside as in line no 2 where t(entering)
                                       // has become more than t(leaving)
    }
    else if(p>0.0) //potentially leaving point ,update tl
        {
        if(t<*t2) *t2=t;
            if(t<*t1) return(0); //line portion is outside
        }
        else if(p==0.0)
            { if(q<0.0)
                 return(0);//line parallel to edge but outside
            }
            return(1);
}
void liangbaraskylineclipanddraw(double x0,double y0,double x1,double y1)
{
    double dx= x1-x0,dy=y1-y0, te=0.0,tl=1.0;

    if(cliptest(-dx,x0-xmin,&te,&tl))// inside test wrt left edge
// t for the left edge is t=(xmin-x0) /dx .... order of numerator is reversed and you get -dx
    if(cliptest(dx,xmax-x0,&te,&tl))// inside test wrt right edge
// t for the right edge is t=(xmax-x0)/dx.... first parameter becomes q and second p then t=q/p
    if(cliptest(-dy,y0-ymin,&te,&tl))// inside test wrt bottom edge
// same story numerator by demoninator to find t
    if(cliptest(dy,ymax-y0,&te,&tl))// inside test wrt top edge
// in one way cohen sutherland and liang barasky are similar
    {
        if(tl<1.0)
        {
            x1=x0+tl*dx;
            y1=y0+tl*dy;
        }
        if(te>0.0)
        {
            x0=x0+te*dx;
            y0=y0+te*dy;
        }
    }
    //window to viewport mappings
    double sx= (xvmax-xvmin)/(xmax-xmin);// scale parameters
            double sy= (yvmax-yvmin)/(ymax-ymin);
            double vx0= xvmin+(x0-xmin)*sx;
            double vy0= yvmin+(y0-ymin)*sy;
            double vx1= xvmin+(x1-xmin)*sx;
            double vy1= yvmin+(y1-ymin)*sy;
// draw a red colored viewport
        glColor3f(1.0,0.0,0.0);
        glBegin(GL_LINE_LOOP);
        glVertex2f(xvmin,yvmin);
        glVertex2f(xvmax,yvmin);
        glVertex2f(xvmax,yvmax);
        glVertex2f(xvmin,yvmax);
        glEnd();
        glColor3f(0.0,0.0,1.0); //draw blue colored clip line
        glBegin(GL_LINES);
        glVertex2d(vx0,vy0);
        glVertex2f(vx1,vy1);
        glEnd();

}
void display()
{
    double x0=60,y0=20,x1=80,y1=120;
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0,0.0,0.0);          //draw a line with red color
    glBegin(GL_LINES);
    glVertex2d(x0,y0);
    glVertex2d(x1,y1);
    glEnd();
    glColor3f(0.0,0.0,1.0);     //draw a blue color window
    glBegin(GL_LINE_LOOP);
    glVertex2f(xmin,ymin);
    glVertex2f(xmax,ymin);
    glVertex2f(xmax,ymax);
    glVertex2f(xmin,ymax);
    glEnd();
    liangbaraskylineclipanddraw(x0,y0,x1,y1);
    glFlush();
}
void myinit()
{    glClearColor(1.0,1.0,1.0,1.0);
    glColor3f(1.0,0.0,0.0);
    glPointSize(1.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0,499.0,0.0,499.0);
}
int main(int argc, char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowSize(500,500);
    glutInitWindowPosition(0,0);
    glutCreateWindow("liang barsky line clipping algorithm");
    glutDisplayFunc(display);
    myinit();
    glutMainLoop();
    return 0;
}

5)Scanline-Area Filling Algorithm (next Lab program)

Scan-line area filling uses the property of coherence to color the polygon. Scanline coherence means if a point lies inside a polygon then other points lying on the same scanline near to it are also likely to be inside the polygon.

There are various ways to check if a point is inside the polygon or not. If somehow all pixels lying inside are found out then it is just a matter of changing their pixel value to color the polygon.

In this program it uses two arrays le and re denoting left edge and right edge. They span the entire window height(500-array size) and store the position(x value) of the intersection point of the scan line with one of the edges of polygon(either left or right).

Initial values in le array is 500. That of re array is 0. We scan convert individual edges of the polygon and each point on the edge, its x value goes to the correct le or re array.

Finally once le and re arrays are populated we draw a line from the left edge to the right edge in a loop and iterate over the entire window region(all 500 scanlines).

#include<stdio.h>
#include<GL/glut.h>
GLfloat x1,y1,x2,y2,x3,y3,x4,y4;
void edgedetect(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2,int *le,int *re)
{
            float mx,x,temp;
            int i;
            if((y2-y1)<0)    // if second point is below first point interchange them
            {
              temp=x1;x1=x2;x2=temp;
              temp=y1;y1=y2;y2=temp;
            }
              if((y2-y1)!=0)      // if denominator is zero we can't find slope
                        mx=(x2-x1)/(y2-y1);
            else
                        mx=x2-x1;    // y2-y1=0 implies line is horizontal
            x=x1;
            for(i=y1;i<y2;i++)        // starting from x1,y1 add slope mx to x
            {                                  // and round it to find the next point on the
                                                // line. For that particular scan line i

                        if(x<le[i])         // insert the x value into either le or re.
                                    le[i]=x; // Initially both le and re will contain same
                                                // value...
                        if(x>re[i])         // in the next time for the other edge
                                    re[i]=x; // either le or re will change
                        x+=mx;            // NOTE: le and re are integer arrays and x
            }                                  // is float so automatic type conversion.
}
void drawpixel(int x,int y)
{
            glColor3f(0.0,1.0,1.0);
            glBegin(GL_POINTS);
            glVertex2i(x,y);
            glEnd();
}
void scanfill(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4)
{
            int le[500],re[500];
            int i,y;
            for(i=0;i<500;i++)   // initialize le and re array values
            {
                        le[i]=500;
                        re[i]=0;
            }
            edgedetect(x1,y1,x2,y2,le,re);    // call edge detect four times
            edgedetect(x2,y2,x3,y3,le,re);    // once for each edge.
            edgedetect(x3,y3,x4,y4,le,re);
            edgedetect(x4,y4,x1,y1,le,re);
for(y=0;y<500;y++)        // for every scan line with value y
{
           if(le[y]<=re[y])            // refer to le and re arrays to see if a part
                        for(i=le[y]+1;i<re[y];i++) // of the scanline is inside polygon
                                    drawpixel(i,y);       // if so draw a horizontal line from
}                                                              // left edge to right edge

}
void display()
{
            glClear(GL_COLOR_BUFFER_BIT);
            x1=200,y1=200,x2=100,y2=300,x3=200,y3=400,x4=300,y4=300;
            glBegin(GL_LINE_LOOP);       // draw the boundary of the polygon
            glVertex2f(x1,y1);                   // to be filled.
             glVertex2f(x2,y2);
            glVertex2f(x3,y3);
            glVertex2f(x4,y4);
    glEnd();
   scanfill(x1,y1,x2,y2,x3,y3,x4,y4);       // call scanfill to fill the polygon
   glFlush();   // Usually students fail the lab because they forget glFlush.
}
void myinit()
{
            glClearColor(1.0,1.0,1.0,1.0);
            glColor3f(0.0,0.0,1.0);
            glPointSize(1.0);
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            gluOrtho2D(0.0,499.0,0.0,499.0);
}
int main(int argc,char **argv)
{          glutInit(&argc,argv);
            glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
            glutInitWindowSize(500,500);// 500 height is hardcoded
            glutInitWindowPosition(0,0);
            glutCreateWindow("scanfill");
            glutDisplayFunc(display);
            myinit();
            glutMainLoop();
            return 0;
  

Output:

Available soon !



Previous
Next Post »

Please Leave ur Valuable comments Here ConversionConversion EmoticonEmoticon

Facebook

HTML Comment Box is loading comments...

Our Partners

Our Partners