Saturday, February 05, 2011

Cuboid



/*
  * THIS PROGRAM DRAWS THE PERSPECTIVE PROJECTIONS OF A CUBOID AND ROTATES IT BY 60 DEGREES
  */
    
 #include<stdio.h>
 #include<stdlib.h>
 #include<conio.h>
 #include<graphics.h>
 #include<dos.h>
 #include<math.h>

 #define root_2 1.414
 #define uxy  100
 #define unitz 100
 #define adjust 1/root_2

 void drawAxis();
 void drawCube(double[][4]);
 void matrix_mult(double[][4],double[][4],double[][4]);
void convToOrdinaryCoordinate(double[][4]);
 int sign(double);

 void main(){

 int gdriver=DETECT,gmode,ecode;
 double f[8][4];            //matrix to hold cube vertices

 f[0][0]= 0; f[0][1]= 0; f[0][2]= 1; f[0][3]=1; //A
 f[1][0]= 1; f[1][1]= 0; f[1][2]= 1; f[1][3]=1; //B
 f[2][0]= 1; f[2][1]= 1; f[2][2]= 1; f[2][3]=1; //C
 f[3][0]= 0; f[3][1]= 1; f[3][2]= 1; f[3][3]=1; //D
 f[4][0]= 0; f[4][1]= 0; f[4][2]= 0; f[4][3]=1; //E
 f[5][0]= 1; f[5][1]= 0; f[5][2]= 0; f[5][3]=1; //F
 f[6][0]= 1; f[6][1]= 1; f[6][2]= 0; f[6][3]=1; //G
 f[7][0]= 0; f[7][1]= 1; f[7][2]= 0; f[7][3]=1; //H

 initgraph(&gdriver,&gmode,"C:\\TC\\bgi");
ecode = graphresult();
if (ecode != grOk){  /* an error occurred */
            printf("Graphics error: %s\n", grapherrormsg(ecode));
            printf("Press any key to halt:");
            getch();
            exit(1); /* terminate with an error code */
}

float z;
printf("\nEnter the center of projection(on z-axis): ");
scanf("%f",&z);

double r = -1.0/z;
//perspection matrix
double Pr[4][4] = {1,0,0,0,                                                       
                          0,1,0,0,
                         0,0,0,r,
                         0,0,0,1};

//orthographic matrix, for z=0
double Po[4][4] = {1,0,0,0,      
                          0,1,0,0,
                          0,0,0,0,
                          0,0,0,1};

clrscr();
drawAxis();       //render the axes
drawCube(f);    //draw the untransformed cube

clrscr();
double Temp[8][4],Temp2[8][4];

matrix_mult(f,Pr,Temp);          
convToOrdinaryCoordinate(Temp);    //apply perspective

matrix_mult(Temp,Po,Temp2);            //orthographic
convToOrdinaryCoordinate(Temp2);
clrscr();

drawAxis();
drawCube(Temp2);     //draw the final projection

//Rotate by 60 degree about x-axis using following rotation matrix
double Prot[][4]={1,0,0,0,                   
                          0,cos(M_PI/3),sin(M_PI/3),0,
                          0,-sin(M_PI/3),cos(M_PI/3),0,
                          0,0,0,1};

//translation matrix
double Pt[][4] = {        1,0,0,0,                                                              
                        0,1,0,0,
                        0,0,1,0,
                        -0.5,-0.5,-0.5,1};

//reverse translation matrix
double Pt_rev[][4] = {  1,0,0,0,
                                    0,1,0,0,
                                    0,0,1,0,
                                    0.5,0.5,0.5,1};

matrix_mult(f,Pt,Temp);                       //translate to origin
convToOrdinaryCoordinate(Temp);
matrix_mult(Temp,Prot,Temp2);                      //apply rotation
convToOrdinaryCoordinate(Temp2);                                                   
matrix_mult(Temp2,Pr,Temp);              //apply perspective
convToOrdinaryCoordinate(Temp);   
matrix_mult(Temp,Po,Temp2);                        //apply orthographic
convToOrdinaryCoordinate(Temp2);
matrix_mult(Temp2,Pt_rev,Temp);                   //translate back
convToOrdinaryCoordinate(Temp);
clrscr();
drawAxis();
drawCube(Temp);
                         
closegraph();
}

void drawAxis(){
int ox,oy;
int z_length;                 //10 unit squares along z-axis
char c[10];
 ox=getmaxx()/2;
 oy=getmaxy()/2;
 z_length=50*unitz;
cleardevice();
setcolor(BROWN);
line(0,oy,getmaxx(),oy);                       //x-axis
line(ox,0,ox,getmaxy());                       //y-axis
line(ox+z_length/root_2,oy-z_length/root_2,ox-z_length/root_2,oy+z_length/root_2);          //z-axis
}

void drawCube(double C[][4])          {
 int v[10],sa,sb,sc,sd;
 int ox=getmaxx()/2,oy=getmaxy()/2;
 setlinestyle(SOLID_LINE,1,3);
 sa=C[0][2]==0?0:sign(C[0][2]);
 sb=C[1][2]==0?0:sign(C[1][2]);
 sc=C[2][2]==0?0:sign(C[1][2]);
 sd=C[3][2]==0?0:sign(C[1][2]);

 v[0]=ox+uxy*(C[0][0]-adjust*sa);
 v[1]=oy-uxy*(C[0][1]-adjust*sa);
 v[2]=ox+uxy*(C[1][0]-adjust*sb);
 v[3]=oy-uxy*(C[1][1]-adjust*sb);
 v[4]=ox+uxy*(C[2][0]-adjust*sc);
 v[5]=oy-uxy*(C[2][1]-adjust*sc);
 v[6]=ox+uxy*(C[3][0]-adjust*sd);
 v[7]=oy-uxy*(C[3][1]-adjust*sd);
 v[8]=ox+uxy*(C[0][0]-adjust*sa);
 v[9]=oy-uxy*(C[0][1]-adjust*sa);

 setcolor(RED);
 drawpoly(5,v);
 getch();

 v[0]=ox+uxy*C[4][0];
 v[1]=oy-uxy*C[4][1];
 v[2]=ox+uxy*C[5][0];
 v[3]=oy-uxy*C[5][1];
 v[4]=ox+uxy*C[6][0];
 v[5]=oy-uxy*C[6][1];
 v[6]=ox+uxy*C[7][0];
 v[7]=oy-uxy*C[7][1];
 v[8]=ox+uxy*C[4][0];
 v[9]=oy-uxy*C[4][1];

 setcolor(MAGENTA);
 drawpoly(5,v);
 getch();

 setcolor(GREEN);
 line(ox+uxy*(C[0][0]-adjust*sa),oy-uxy*(C[0][1]-adjust*sa),ox+uxy*C[4][0],oy-uxy*C[4][1]);
 line(ox+uxy*(C[1][0]-adjust*sb),oy-uxy*(C[1][1]-adjust*sb),ox+uxy*C[5][0],oy-uxy*C[5][1]);
 line(ox+uxy*(C[2][0]-adjust*sc),oy-uxy*(C[2][1]-adjust*sc),ox+uxy*C[6][0],oy-uxy*C[6][1]);
 line(ox+uxy*(C[3][0]-adjust*sd),oy-uxy*(C[3][1]-adjust*sd),ox+uxy*C[7][0],oy-uxy*C[7][1]);
 getch();
 }

 //matrix multiplication of 8X4 and 4X4 matrices
 void matrix_mult(double A[][4],double B[][4],double C[][4]){
  int k,i,j;
  for(i=0;i<8;i++)
   for(j=0;j<4;j++){
    C[i][j] = 0;
    for(k=0;k<4;k++)
             C[i][j] = C[i][j] + A[i][k]*B[k][j];
   }
 }
  
 void convToOrdinaryCoordinate(double M[][4]){
 int i,j;

  for(i=0;i<8;i++)
   for(j=0;j<4;j++)
    M[i][j] /= M[i][3];
 }

 int sign(double x){

 if(x>0)
  return 1;
else
  return -1;
 }  
 
SAMPLE OUTPUT:

·         Original cuboid & its perspective projection onto z=0 plane from a point on the Z axis (0,0,5) –
 

·         Rotation by 60 degrees 


No comments:

Post a Comment

Do you think this information useful or was not up to the mark? Comment if you have any advices or suggestions about the post.