Tuesday, 10 June 2014

Gourad shading algorithm


/* This routine performs shading of a triangular surface using
/* Gourad algorithm. Here, vertex co-ordinates, vertex intensities
/* are needed as inputs. Number of vertices is 3 by default.  
/* Display window is set to wsize by wsize pixels in size.  
/******************************************************************/

#include<stdio.h>
#include<math.h>                                                                                         
#define wsize 300
                                                                      
typedef struct {int x, y, I;} point;
point vertex[10];
int buffer[wsize][wsize], left[wsize], right[wsize];
int ymin = 999, ymax = -999;
FILE *fp;

float compute_distance(int, int, int, int);

main()
{
 int i, j, n;

 fp = fopen("shadeT.txt", "w");
 printf("\nHow many vertices in polygon: ");
 scanf("%d", &n);
 for(i = 0; i < n; i++)
   {
    printf("\nGive vertex[%d]: ",i);
    scanf("%d %d", &vertex[i].x, &vertex[i].y);
   }

 for(i = 0; i < n; i++)
   {
    if(vertex[i].y < ymin)
       ymin = vertex[i].y;
    if(vertex[i].y > ymax)
       ymax = vertex[i].y;
   }
 printf("\nymin = %d, ymax = %d", ymin, ymax);

 for(i = 0; i < n; i++)
   {
    printf("\nGive intensity at vertex[%d]: ",i);
    scanf("%d", &vertex[i].I);
   }
                                                                                         
 for(i = 0; i < wsize; i++)
   for(j = 0; j < wsize; j++)
      buffer[i][j] = 10;
                                                                                         
 drawpolygon(n);

 printf("\n");
 for(i = 0; i < wsize; i++)
   {
    for(j = 0; j < wsize; j++)
      printf("%d ",buffer[i][j]);
    printf("\n");
   }
 getboundaries();                                                                              
 //uniformfill();          
 //printf("\n\n\n");
 //for(i = 0; i < wsize; i++)
 //  {
 //   for(j = 0; j < wsize; j++)
 //     fprintf(fp2, "%d ",buffer[i][j]);
 //   fprintf(fp2, "\n");
 //  }

 gouradfill();
                                                                                         
 printf("\n\n\n");
 for(i = 0; i < wsize; i++)
   {
    for(j = 0; j < wsize; j++)
      fprintf(fp, "%d ",buffer[i][j]);
    fprintf(fp, "\n");
   }
   
 for(i = 0; i < wsize; i++)
   {
    for(j = 0; j < wsize; j++)
      printf("%d ",buffer[i][j]);
    printf("\n");
   }


 fclose(fp);
}

getboundaries()
{
 int i, j, rmark;
 for(j = 0; j < wsize; j++)
   {
    i = 0;
    while((buffer[i][j] == 10) && (i < wsize)) i++;
    if(buffer[i][j] == 11)
       {left[j] = i; while(buffer[i][j] == 11) i++; rmark = i-1;}
    while((buffer[i][j] == 10) && (i < wsize))
       {i++; if(buffer[i][j] == 11) right[j] = i;else right[j] = rmark;}
   }

 for(i = 0; i < 3; i++)
   buffer[vertex[i].x][vertex[i].y] = vertex[i].I;
}

uniformfill()
{
 int i, j;

 for(i = ymin; i < ymax; i++)
   for(j = left[i]; j <= right[i]; j++)
     buffer[j][i] = 50;
}

gouradfill()
{
 int i, j, k;

 for(i = ymin; i < ymax; i++)
  {
   buffer[left[i]][i] = (int)(-(compute_distance(vertex[0].x, vertex[0].y, left[i], i)/compute_distance(vertex[0].x, vertex[0].y, vertex[1].x, vertex[1].y)*(vertex[0].I - vertex[1].I)) + vertex[0].I);

   buffer[right[i]][i] = (int)(-(compute_distance(vertex[0].x, vertex[0].y, right[i], i)/compute_distance(vertex[0].x, vertex[0].y, vertex[2].x, vertex[2].y)*(vertex[0].I - vertex[2].I)) + vertex[0].I);

   //printf("\n\ni = %d) l=%d, r=%d, bl=%d, br=%d :: ", i, left[i], right[i], buffer[left[i]][i], buffer[right[i]][i]);
   for(j = left[i]; j < right[i]; j++)
    {
     buffer[j][i] = (int)(-((float)(j-left[i])/(float)(right[i]-left[i]))* (buffer[left[i]][i] - buffer[right[i]][i]) + buffer[left[i]][i]);
     //printf("%d ", buffer[j][i]);
    }
  }
}


float compute_distance(int x1, int y1, int x2, int y2)
{
 return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));  
}

drawpolygon(int k)
{
 int i;
 for(i = 0;i < k-1;i++)
  {
   BresLine(i, vertex[i].x, vertex[i].y, vertex[i+1].x, vertex[i+1].y);
  }
 BresLine(k-1, vertex[k-1].x, vertex[k-1].y, vertex[0].x, vertex[0].y);
}


BresLine(int j, int x1, int y1, int x2, int y2)
{
 int x, y, dx, dy, p, temp, k;
 float slope;
                                                                                         
                                                                                          
 dx = abs(x2 - x1); dy = abs(y2 - y1);

 if(dx == 0) verline(j, x1, y1, x2, y2);
 else if(dy == 0) horline(j, x1, y1, x2, y2);
 else if(dx == dy) digline(j, x1, y1, x2, y2);
 else
 {
  x = x1; y = y1;
  slope = (float)dy/(float)dx;
  if(slope > 1)
    {
     swap(&x1, &y1); swap(&x2, &y2);
     temp = dx; dx = dy; dy = temp;
     temp = x; x = y; y = temp;
    }
  p = 2 * dy - dx;
  if(slope > 1) buffer[y][x] = 11; else buffer[x][y] = 11;
                                                                                         
                                                                                         
  for(k=0; k < dx; k++)
    {
     if(p < 0)
       {
        if(x < x2) x++; else x--;
        p = p + 2 * dy;
       }
     else
       {
        if(y < y2) y++; else y--;
        if(x < x2) x++; else x--;
        p = p + 2 * (dy - dx);
       }
     if(slope > 1) buffer[y][x] = 11; else buffer[x][y] = 11;  
    }
  }
}

swap(int *a,Gourad shading algorithm  int *b)
{
 int tmp;
 tmp = *a; *a = *b; *b = tmp;
}
                                                                                         
horline(int l, int x1, int y1, int x2, int y2)
{
 int i,j;
 if(x1 < x2)
  for(i = x1; i <= x2; i++)
     buffer[i][y1] = 11;
 else
  for(i = x2; i <= x1; i++)
     buffer[i][y1] = 11;
}
                                                                                         
verline(int l, int x1, int y1, int x2, int y2)
{
 int i,j;
 if(y1 < y2)
  for(j = y1; j <= y2; j++)
     buffer[x1][j] = 11;
 else
  for(j = y2; j <= y1; j++)
     buffer[x1][j] = 11;
}
                                                                                         
                                                                                         
digline(int l, int x1, int y1, int x2, int y2)
{
 int i,j;
 if(x1 < x2)
  for(i = x1; i <= x2; i++)
    buffer[i][i] = 11;
 else
  for(i = x2; i <= x1; i++)
    buffer[i][i] = 11;
}

/***************************************************************
This Program is may be tested with the following example inputs.
Example 1:
No. of vertices: 3
Vertices: 15 28; 2 2; 28 2
Vertex intensities: 9 5 1

Example 2:
No. of vertices: 3
Vertices: 5 15; 28 2; 25 25
Vertex intensities: 9 5 1
***************************************************************/

No comments:

Post a Comment