CSE 328 -- FUNDAMENTALS OF COMPUTER GRAPHICS

Professor Arie Kaufman

Assignment 5 solution

unsigned int* zDepth = NULL;
int width, height, size;

void EnableHiddenSurfaceRemoval(int widthIn, int heightIn)
{
  int i;
  height = heightIn;
  width = widthIn;
  size = width*height;
  if (zDepth) free(zDepth);
  zDepth =  (unsigned int*)malloc(sizeof(unsigned int)*size);
  for(i=0;i < size;i++) zDepth[i] = 999999;
}


void ComputePlaneAndDepths(vertex v1, vertex v2, vertex v3, float* dZx)
{
  float A,B,C;
  float vect12x,vect12y,vect12z;
  float vect13x,vect13y,vect13z;
  float length;
  float vect21x,vect21y,vect21z;
  float vect23x,vect23y,vect23z;
  float vect31x,vect31y,vect31z;
  float vect32x,vect32y,vect32z;

  // compute 2 vectors which lie in the plane of the
  // polygon. Specifically, vectors v1->v2 and v1->v3
  vect12x = v2.x-v1.x;
  vect12y = v2.y-v1.y;
  vect12z = v2.z-v1.z;
                     
  vect13x = v3.x-v1.x;
  vect13y = v3.y-v1.y;
  vect13z = v3.z-v1.z;

  // normalize the two vectors
  length = sqrtf(vect12x*vect12x+vect12y*vect12y+vect12z*vect12z);
  if (length !=0.0) {
    vect12x /= length;
    vect12y /= length;
    vect12z /= length;
  } else {
    vect12x = 0;
    vect12y = 0;
    vect12z = 0;
  }
  length = sqrtf(vect13x*vect13x+vect13y*vect13y+vect13z*vect13z);
  if (length !=0.0) {
    vect13x /= length;
    vect13y /= length;
    vect13z /= length;
  } else {
    vect13x = 0;
    vect13y = 0;
    vect13z = 0;
  }

  // compute the coefficients of the plane equation of the
  // polygon (Ax+By+Cz+d=0). A, B & C are coefficients of
  // the normal to the plane and they are computed using the
  // cross product of two vectors in the plane. Specifically
  // vect12 X vect13 since they must share their starting point.
  A = vect12y*vect13z - vect13y*vect12z;
  B = vect12z*vect13x - vect13z*vect12x;
  C = vect12x*vect13y - vect13x*vect12y;


  // compute dZx from the plane equation. 
  if (C!=0.0)
    *dZx = -(A/C);
  else
    *dZx = 0;

} // ComputePlaneAndDepths

// -------------------------------------------------------------
//  LoadLine
//    Draw a line into the Frame buffer using the current color
// -------------------------------------------------------------
void LoadLine(int startX, int stopX, int y,
              float currentZ, float dZx)
{
  unsigned int x;

  if (startX <= stopX) { // Left to right

    for(x=startX; x < stopX; x++) {
      if (!zDepth || currentZ < = zDepth[y*width+x]) {
        put_line(x,y,x,y);
        zDepth[y*width+x] = currentZ;
      } // endif this fragment is in front of the z-buffer stored here
      currentZ += dZx;
    } // endfor all pixels in this scanline

  } else {

    for(x=startX; x>=stopX; x--) {
      if (!zDepth || currentZ < = zDepth[y*width+x]) {
        put_line(x,y,x,y);
        zDepth[y*width+x] = currentZ;
      } // endif this fragment is in front of the z-buffer stored here
      currentZ += dZx;
    } // endfor all pixels in this scanline

  }
} // LoadLine


// -------------------------------------------------------------
//  DrawTriangle
//    Draw a triangle into the Frame buffer
// -------------------------------------------------------------
void DrawTriangle(int x1, int y1, int z1,
		       int x2, int y2, int z2,
		       int x3, int y3, int z3)
{
  vertex v1;
  vertex v2;
  vertex v3;
  unsigned int start = 0;
  unsigned int stop  = 1;
  unsigned int startX,stopX;
  unsigned int y;
  unsigned int yoff;
  tEdge edge[3];
  float currentZ;
  float this_dZx;
  float weight;

  v1.x = x1; v1.y = y1; v1.z = z1;
  v2.x = x2; v2.y = y2; v2.z = z2;
  v3.x = x3; v3.y = y3; v3.z = z3;

  Transform(&v1);
  Transform(&v2);
  Transform(&v3);

  //printf("(%d,%d,%d)  ", v1.x,v1.y,v1.z);
  //printf("(%d,%d,%d)  ", v2.x,v2.y,v2.z);
  //printf("(%d,%d,%d)\n", v3.x,v3.y,v2.z);
  Project(&v1);
  Project(&v2);
  Project(&v3);
  //printf("(%d,%d,%d)  ", v1.x,v1.y,v1.z);
  //printf("(%d,%d,%d)  ", v2.x,v2.y,v2.z);
  //printf("(%d,%d,%d)\n", v3.x,v3.y,v2.z);

  LoadEdges(v1,v2,v3,edge);

  ComputePlaneAndDepths(v1,v2,v3,&this_dZx);
  //printf("%f\n",this_dZx);

  //put_line(v1.x,v1.y,v2.x,v2.y);
  //put_line(v1.x,v1.y,v3.x,v3.y);
  //put_line(v2.x,v2.y,v3.x,v3.y);

  for (y = edge[start].bottomVertex.y; y<=edge[start].yMax && y<=edge[stop].yMax; y++) {

    if( y == edge[stop].yMax ) {
      stop=2;
    } else if( y == edge[start].yMax ) {
      start=2;
    } // endif change an edge

    // interpolate the starting zDepth for this scanline
    if (edge[start].topVertex.y != edge[start].bottomVertex.y)
      weight = (float)(                       y - edge[start].bottomVertex.y) /
                      ( edge[start].topVertex.y - edge[start].bottomVertex.y );
    else
      weight = 1.0;
    currentZ = weight *edge[start].topVertex.z +
            (1-weight)*edge[start].bottomVertex.z;

    startX = edge[start].currentX+0.5;
    stopX  = edge[stop].currentX+0.5;
    //put_line(startX, y, stopX, y);
    LoadLine(startX, stopX, y, currentZ, this_dZx);

    edge[start].currentX += edge[start].xInc;
    edge[stop ].currentX += edge[stop ].xInc;

  } // endfor still more polygon to rasterize


} // DrawTriangle