Program: 39140
Project: 39140
Buggy source:
/** 
 * Constructs BufferedImage from list of triangles based on the input Matrix3 specifications (positions of JSliders determining rotation of 3D image)
 * @param tris list of triangles
 * @param width width of image
 * @param height height of image
 * @param transform Matrix3 instance determining where JSlider rotation occurs for image construction
 * @return BufferedImage representing current view of 3D image
 */
private static BufferedImage imageFromTriangles(List<Triangle> tris,int width,int height,Matrix3 transform,Color color){
  BufferedImage img=new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
  if (color != null) {
    for (int i=0; i < width; i++) {
      for (int j=0; j < height; j++) {
        img.setRGB(i,j,color.getRGB());
      }
    }
  }
  double[] zBuffer=new double[img.getWidth() * img.getHeight()];
  for (int q=0; q < zBuffer.length; q++) {
    zBuffer[q]=Double.NEGATIVE_INFINITY;
  }
  for (  Triangle t : tris) {
    Vertex v1=transform.transform(t.v1);
    v1.x+=width / 2;
    v1.y+=height / 2;
    Vertex v2=transform.transform(t.v2);
    v2.x+=width / 2;
    v2.y+=height / 2;
    Vertex v3=transform.transform(t.v3);
    v3.x+=width / 2;
    v3.y+=height / 2;
    Vertex norm=getNorm(v1,v2,v3);
    double angleCos=Math.abs(norm.z);
    int minX=(int)Math.max(0,Math.ceil(Math.min(v1.x,Math.min(v2.x,v3.x))));
    int maxX=(int)Math.min(img.getWidth() - 1,Math.floor(Math.max(v1.x,Math.max(v2.x,v3.x))));
    int minY=(int)Math.max(0,Math.ceil(Math.min(v1.y,Math.min(v2.y,v3.y))));
    int maxY=(int)Math.min(img.getHeight() - 1,Math.floor(Math.max(v1.y,Math.max(v2.y,v3.y))));
    double triangleArea=(v1.y - v3.y) * (v2.x - v3.x) + (v2.y - v3.y) * (v3.x - v1.x);
    for (int y=minY; y <= maxY; y++) {
      for (int x=minX; x <= maxX; x++) {
        double b1=((y - v3.y) * (v2.x - v3.x) + (v2.y - v3.y) * (v3.x - x)) / triangleArea;
        double b2=((y - v1.y) * (v3.x - v1.x) + (v3.y - v1.y) * (v1.x - x)) / triangleArea;
        double b3=((y - v2.y) * (v1.x - v2.x) + (v1.y - v2.y) * (v2.x - x)) / triangleArea;
        if (b1 >= 0 && b1 <= 1 && b2 >= 0 && b2 <= 1 && b3 >= 0 && b3 <= 1) {
          double depth=b1 * v1.z + b2 * v2.z + b3 * v3.z;
          int zIndex=y * img.getWidth() + x;
          if (zBuffer[zIndex] < depth) {
            img.setRGB(x,y,getShade(t.color,angleCos).getRGB());
            zBuffer[zIndex]=depth;
          }
        }
      }
    }
  }
  return img;
}

Fixed version (ground truth):
/** 
 * Constructs BufferedImage from list of triangles based on the input Matrix3 specifications (positions of JSliders determining rotation of 3D image)
 * @param tris list of triangles
 * @param width width of image
 * @param height height of image
 * @param transform Matrix3 instance determining where JSlider rotation occurs for image construction
 * @param bgColor Color of the background in the image
 * @return BufferedImage representing current view of 3D image
 */
private static BufferedImage imageFromTriangles(List<Triangle> tris,int width,int height,Matrix3 transform,Color bgColor){
  BufferedImage img=new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
  if (bgColor != null) {
    for (int i=0; i < width; i++) {
      for (int j=0; j < height; j++) {
        img.setRGB(i,j,bgColor.getRGB());
      }
    }
  }
  double[] zBuffer=new double[img.getWidth() * img.getHeight()];
  for (int q=0; q < zBuffer.length; q++) {
    zBuffer[q]=Double.NEGATIVE_INFINITY;
  }
  for (  Triangle t : tris) {
    Vertex v1=transform.transform(t.v1);
    v1.x+=width / 2;
    v1.y+=height / 2;
    Vertex v2=transform.transform(t.v2);
    v2.x+=width / 2;
    v2.y+=height / 2;
    Vertex v3=transform.transform(t.v3);
    v3.x+=width / 2;
    v3.y+=height / 2;
    Vertex norm=getNorm(v1,v2,v3);
    double angleCos=Math.abs(norm.z);
    int minX=(int)Math.max(0,Math.ceil(Math.min(v1.x,Math.min(v2.x,v3.x))));
    int maxX=(int)Math.min(img.getWidth() - 1,Math.floor(Math.max(v1.x,Math.max(v2.x,v3.x))));
    int minY=(int)Math.max(0,Math.ceil(Math.min(v1.y,Math.min(v2.y,v3.y))));
    int maxY=(int)Math.min(img.getHeight() - 1,Math.floor(Math.max(v1.y,Math.max(v2.y,v3.y))));
    double triangleArea=(v1.y - v3.y) * (v2.x - v3.x) + (v2.y - v3.y) * (v3.x - v1.x);
    for (int y=minY; y <= maxY; y++) {
      for (int x=minX; x <= maxX; x++) {
        double b1=((y - v3.y) * (v2.x - v3.x) + (v2.y - v3.y) * (v3.x - x)) / triangleArea;
        double b2=((y - v1.y) * (v3.x - v1.x) + (v3.y - v1.y) * (v1.x - x)) / triangleArea;
        double b3=((y - v2.y) * (v1.x - v2.x) + (v1.y - v2.y) * (v2.x - x)) / triangleArea;
        if (b1 >= 0 && b1 <= 1 && b2 >= 0 && b2 <= 1 && b3 >= 0 && b3 <= 1) {
          double depth=b1 * v1.z + b2 * v2.z + b3 * v3.z;
          int zIndex=y * img.getWidth() + x;
          if (zBuffer[zIndex] < depth) {
            img.setRGB(x,y,getShade(t.color,angleCos).getRGB());
            zBuffer[zIndex]=depth;
          }
        }
      }
    }
  }
  return img;
}