diff --git a/DepthBuffer.java b/DepthBuffer.java index c533e38..62c6f46 100644 --- a/DepthBuffer.java +++ b/DepthBuffer.java @@ -1,10 +1,9 @@ - import java.lang.Double; /** * The DepthBuffer class implements a DepthBuffer and its pass test. - */ + */ public class DepthBuffer { private double[] buffer; int width; @@ -14,17 +13,17 @@ public class DepthBuffer { * Constructs a DepthBuffer of size width x height. * The buffer is initially cleared. */ - public DepthBuffer (int width, int height) { + public DepthBuffer(int width, int height) { buffer = new double[width * height]; this.width = width; this.height = height; - clear (); + clear(); } /** * Clears the buffer to infinite depth for all fragments. */ - public void clear () { + public void clear() { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { buffer[i * width + j] = Double.POSITIVE_INFINITY; @@ -37,10 +36,13 @@ public class DepthBuffer { * Test if a fragment passes the DepthBuffer test, i.e. is the fragment the * closest at its position. */ - public boolean testFragment (Fragment fragment) { - if ((fragment.getX () >= 0) && (fragment.getX () < width) && (fragment.getY () >= 0) && (fragment.getY () < height)) { + public boolean testFragment(Fragment fragment) { + if ((fragment.getX() >= 0) && (fragment.getX() < width) && (fragment.getY() >= 0) + && (fragment.getY() < height)) { - /* COMPLETER */ + if (fragment.getDepth() < this.buffer[fragment.getY() * height + fragment.getX()]) { + return true; + } return false; } else { @@ -49,17 +51,12 @@ public class DepthBuffer { } /** - * Writes the fragment depth to the buffer + * Writes the fragment depth to the buffer */ - public void writeFragment (Fragment fragment) { - if ((fragment.getX () >= 0) && (fragment.getX () < width) && (fragment.getY () >= 0) && (fragment.getY () < height)) { - - /* COMPLETER */ - + public void writeFragment(Fragment fragment) { + if (testFragment(fragment)) { + this.buffer[fragment.getY() * height + fragment.getX()] = fragment.getDepth(); } } - } - - diff --git a/Rasterizer.java b/Rasterizer.java index 39da099..7b19083 100644 --- a/Rasterizer.java +++ b/Rasterizer.java @@ -71,77 +71,84 @@ public class Rasterizer { int x2 = v2.getX(); int y2 = v2.getY(); - /* For now : just display the vertices */ - Fragment f = new Fragment(0, 0); - int size = 2; - for (int i = 0; i < v1.getNumAttributes(); i++) { - f.setAttribute(i, v1.getAttribute(i)); + // /* For now : just display the vertices */ + // Fragment f = new Fragment(0, 0); + // int size = 2; + // for (int i = 0; i < v1.getNumAttributes(); i++) { + // f.setAttribute(i, v1.getAttribute(i)); + // } + // for (int i = -size; i <= size; i++) { + // for (int j = -size; j <= size; j++) { + // f.setPosition(x1 + i, y1 + j); + // shader.shade(f); + // } + // } + + // tracé d'un segment avec l'algo de Bresenham + int numAttributes = v1.getNumAttributes(); + Fragment fragment = new Fragment(0, 0); // , numAttributes); + + boolean sym = (Math.abs(y2 - y1) > Math.abs(x2 - x1)); + if (sym) { + int temp; + temp = x1; + x1 = y1; + y1 = temp; + temp = x2; + x2 = y2; + y2 = temp; } - for (int i = -size; i <= size; i++) { - for (int j = -size; j <= size; j++) { - f.setPosition(x1 + i, y1 + j); - shader.shade(f); - } + if (x1 > x2) { + Fragment ftemp; + int temp; + temp = x1; + x1 = x2; + x2 = temp; + temp = y1; + y1 = y2; + y2 = temp; + ftemp = v1; + v1 = v2; + v2 = ftemp; } - /* - * tracé d'un segment avec l'algo de Bresenham - * int numAttributes = v1.getNumAttributes (); - * Fragment fragment = new Fragment (0, 0); //, numAttributes); - * - * boolean sym = (Math.abs (y2 - y1) > Math.abs (x2 - x1)); - * if (sym) { - * int temp; - * temp = x1; x1 = y1 ; y1 = temp; - * temp = x2; x2 = y2 ; y2 = temp; - * } - * if (x1 > x2) { - * Fragment ftemp; - * int temp; - * temp = x1; x1 = x2; x2 = temp; - * temp = y1; y1 = y2; y2 = temp; - * ftemp = v1; v1 = v2; v2 = ftemp; - * } - * - * int ystep; - * if (y1 < y2) { - * ystep = 1; - * } else { - * ystep = -1; - * } - * - * int x = x1; - * float y_courant = y1; - * int y=y1; - * float delta_y = y2-y1; - * float delta_x = x2-x1; - * float m = delta_y/delta_x; - * - * - * for (int i=1;i<=delta_x;i++) { - * x = x+1; - * y_courant = y_courant + m; - * if ((ystep == 1)&&(y_courant < y+0.5)||((ystep == -1) && (y_courant > y - * -0.5))) { - * y = y; - * } else { - * y = y + ystep; - * } - * - * //envoi du fragment au shader - * fragment.setPosition (x, y); - * - * if (!shader.isClipped (fragment)) { - * - * //interpolation des attributs - * interpolate2 (v1, v2, fragment); - * if (sym) { - * swapXAndY (fragment); - * } - * shader.shade (fragment); - * } - * } - */ + int ystep; + if (y1 < y2) { + ystep = 1; + } else { + ystep = -1; + } + + int x = x1; + float y_courant = y1; + int y = y1; + float delta_y = y2 - y1; + float delta_x = x2 - x1; + float m = delta_y / delta_x; + + for (int i = 1; i <= delta_x; i++) { + x = x + 1; + y_courant = y_courant + m; + if ((ystep == 1) && (y_courant < y + 0.5) || ((ystep == -1) && (y_courant > y + - 0.5))) { + y = y; + } else { + y = y + ystep; + } + + // envoi du fragment au shader + fragment.setPosition(x, y); + + if (!shader.isClipped(fragment)) { + + // interpolation des attributs + interpolate2(v1, v2, fragment); + if (sym) { + swapXAndY(fragment); + } + shader.shade(fragment); + } + } } @@ -179,6 +186,14 @@ public class Rasterizer { return C; } + private int min3(int a, int b, int c) { + return Math.min(a, Math.min(b, c)); + } + + private int max3(int a, int b, int c) { + return Math.max(a, Math.max(b, c)); + } + /** * Rasterizes the triangular face made of the Fragment v1, v2 and v3 */ @@ -188,7 +203,53 @@ public class Rasterizer { /* iterate over the triangle's bounding box */ - /* A COMPLETER */ + int x_hg = min3(v1.getX(), v2.getX(), v3.getX()); + int y_hg = min3(v1.getY(), v2.getY(), v3.getY()); + + int x_bd = max3(v1.getX(), v2.getX(), v3.getX()); + int y_bd = max3(v1.getY(), v2.getY(), v3.getY()); + + for (int px = x_hg; px < x_bd; px++) { + boucle: for (int py = y_hg; py < y_bd; py++) { + + // System.out.println(px); + // System.out.println(py); + // System.out.println(); + + Vector3 point = new Vector3(1, px, py); + Vector barycentre = null; + try { + barycentre = C.multiply(point); + } catch (SizeMismatchException e) { + e.printStackTrace(); + } + + for (int i = 0; i < 3; i++) { + // si une des coordonnées barycentrique est négative, + // le pixel n'est pas dans le triangle + if (barycentre.get(i) < 0) { + // on passe au pixel suivant + continue boucle; + } + } + + // System.out.println(barycentre); + + // Le pixel est dans le triangle + // On créé un fragment + Fragment couleur = new Fragment(px, py); + + // on interpole la couleur + for (int i = 0; i < couleur.getNumAttributes(); i++) { + double pondere = v1.getAttribute(i) * barycentre.get(0) + v2.getAttribute(i) * barycentre.get(1) + + v3.getAttribute(i) * barycentre.get(2); + couleur.setAttribute(i, pondere); + } + + // on affiche le pixel + shader.shade(couleur); + } + } } } diff --git a/Renderer.java b/Renderer.java index 166a995..b165901 100644 --- a/Renderer.java +++ b/Renderer.java @@ -23,9 +23,9 @@ public class Renderer { mesh = new Mesh(scene.getMeshFileName()); screen = new GraphicsWrapper(scene.getScreenW(), scene.getScreenH()); screen.clearBuffer(); - shader = new SimpleShader(screen); - // shader = new PainterShader (screen); - // rasterizer = new PerspectiveCorrectRasterizer (shader); + // shader = new SimpleShader(screen); + shader = new PainterShader(screen); + rasterizer = new PerspectiveCorrectRasterizer(shader); rasterizer = new Rasterizer(shader); xform = new Transformation(); @@ -146,16 +146,17 @@ public class Renderer { /* wireframe rendering */ renderWireframe(); screen.swapBuffers(); - wait(10); + wait(1); /* solid rendering, no lighting */ - /* - * screen.clearBuffer (); - * shader.reset (); - * renderSolid (); - * screen.swapBuffers (); - * wait (3); - */ + + screen.clearBuffer(); + shader.reset(); + renderSolid(); + screen.swapBuffers(); + wait(1); + + wait(10); /* solid rendering, with lighting */ /*