Saturday 21 March 2015

Bezier Curve Algorithm in C | OpenGL for n control points

 

Bezier Curve Algorithm in C | OpenGL


#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<GL/freeglut.h>
#include<GL/gl.h>
#define STEP 0.0001
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
int numpoints=0,q=0;
typedef struct{
    float x,y;
}POINT;
POINT *ctrlPoint,*auxPoint;

int i,j,f;
float t;
long double factorial(int x){
    long double fact=1;
    int p=1;
    if(x==0 || x==1)
        return 1;
    else{
        while(p<=x){
            fact*=p;
            p++;}
        }
    return fact;
}
long double binomial( int f, int n){
    double com=factorial(n)/(factorial(f)*factorial(n-f));
    return com;
}

POINT bernstein(POINT *ctrlPoint,float t,int n){
POINT N;N.x=N.y=0;

for(i=0;i<=n;i++){
    N.x+=ctrlPoint[i].x*binomial(i,n)*pow(t,i)*pow((1-t),(n-i));
    N.y+=ctrlPoint[i].y*binomial(i,n)*pow(t,i)*pow((1-t),(n-i));
    }
    return N;

}
void init(){
    glClearColor(0.0,0.0,0.0,0.0);
    glPointSize(10.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0,(float)SCREEN_WIDTH,0.0,(float)SCREEN_HEIGHT);

}



void drawPoint(int x,int y){
    glColor3f(0.0,0.0,1.0);   
    glBegin(GL_POINTS);
        glVertex2i(x,y);
    glEnd();
    glFlush();
}

void drawLine(POINT p1,POINT p2){
    glColor3f(1.0,0.0,0.0);   
    glLineWidth(1.0);   
    glBegin(GL_LINES);
        glVertex2f(p1.x,p1.y);
        glVertex2f(p2.x,p2.y);
    glEnd();
    glFlush();
}
void drawCurve(POINT p1,POINT p2,float color){
    glColor3f(1,0.0,0.0);   
    glLineWidth(1);   
    glBegin(GL_LINES);
        glVertex2f(p1.x,p1.y);
        glVertex2f(p2.x,p2.y);
    glEnd();
    glFlush();
}

void MouseEvent(int button,int state,int x,int y){
    POINT M,P=ctrlPoint[0];
    if(button==GLUT_LEFT_BUTTON && state==GLUT_DOWN){
        ctrlPoint[numpoints].x=(float)x;
        ctrlPoint[numpoints].y=(float)SCREEN_HEIGHT-y;
        numpoints++;
        drawPoint(x,SCREEN_HEIGHT-y);
        }
    else
        if(button==GLUT_MIDDLE_BUTTON && state==GLUT_DOWN){
            for(t = 0;t <= 1.0; t += STEP) {
                    M=bernstein(ctrlPoint,t,numpoints-1);   
                    drawCurve(P,M,t);
                    P=M;
                }
            }
        else
            if(button==GLUT_RIGHT_BUTTON && state==GLUT_DOWN){
                for(i=0;i<numpoints-1;i++)
                    drawLine(ctrlPoint[i],ctrlPoint[i+1]);
            }
}
void keyboardEvent(unsigned char key,int x, int y){
    if(key==27)
        exit(0);
    else
        if(key=='C'){
            glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                         glFlush();
            numpoints=0;
            }
}

void display() {
    glClear(GL_COLOR_BUFFER_BIT);
    glFlush();
}

int main(int argc, char *argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowSize(800,600);
    glutInitWindowPosition(100,100);
    glutCreateWindow("Bezier Curve Application in OpenGL | Developed BY Shaharyar Shaukat");
    ctrlPoint=(POINT *)malloc(q*sizeof(POINT));
    if(!ctrlPoint){
        exit(EXIT_FAILURE);
        }
    else{
    q++;
    auxPoint=(POINT *)realloc(ctrlPoint,q*sizeof(POINT));
    if(!auxPoint){
        exit(EXIT_FAILURE);
        }
    else{   
        ctrlPoint=auxPoint;
            glutMouseFunc(MouseEvent);
        }
    }
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboardEvent);
    init();
    glutMainLoop();
    free(ctrlPoint);
    free(auxPoint);
    return 0;
}