import org.omg.CORBA.PolicyTypeHelper; import java.awt.*; import java.awt.image.BufferedImage; public class Triangle{ public Point2D point1; public Point2D point2; public Point2D point3; public Matrix perspectiveMappingMatrix; public boolean[] edgeList; //edge 1-2 , 2-3, 3-1 private Line2d LineLong; private Line2d LineA; private Line2d LineB; public BufferedImage texture; // initialisation variables private boolean is_initialised = false; private Point2D min; private Point2D max; // progress variables private Point3D result = new Point3D(0,0,0); private Point2D result2 = new Point2D(0,0); public void invalidate() { is_initialised = false; } public Triangle(Point2D _pA, Point2D _pB, Point2D _pC, boolean[] _edgeList, BufferedImage _texture, Matrix mapMatrix){ point1 = _pA; point2 = _pB; point3 = _pC; edgeList = _edgeList; texture = _texture; perspectiveMappingMatrix = mapMatrix; } // returns int for debug public int draw(BufferedImage img, BufferedImage zBuf, double FPDis, int scrX, int scrY){ // long lastMillis; if (!is_initialised){initialise();} int[] point1; int[] point2; char currentLine = 'A'; lastMillis = System.currentTimeMillis(); point1 = LineLong.nextPix(); point2 = LineA.nextPix(); for(int x = min.x+1; x <= max.x; x += 1) { while(x-1 == point1[0]) { if(LineLong.isDrawn && // draw line pixels if needed, and on screen point1[0] > 0 && point1[1] > 0 && point1[0] < img.getWidth() && point1[1] < img.getHeight()){ img.setRGB(point1[0], point1[1], Color.HSBtoRGB(0, 1, 1)); } try { // this error seems to be thrown randomly, for various reasons // todo fix point1 = LineLong.nextPix(); } catch (Exception e){ throw new RuntimeException("accessed too many line pixels"); } } while(x-1 == point2[0]) { if (currentLine == 'A') { try{ if(LineA.isDrawn && // draw line pixels if needed, and on screen point2[0] > 0 && point2[1] > 0 && point2[0] < img.getWidth() && point2[1] < img.getHeight()){ img.setRGB(point2[0], point2[1], Color.HSBtoRGB(0f, 1, 1)); } point2 = LineA.nextPix(); } catch (RuntimeException e){ currentLine = 'B'; // point2 = LineB.nextPix(); } } else { if(LineB.isDrawn && // draw line pixels if needed, and on screen point2[0] > 0 && point2[1] > 0 && point2[0] < img.getWidth() && point2[1] < img.getHeight()){ img.setRGB(point2[0], point2[1], Color.HSBtoRGB(0f, 1, 1)); } point2 = LineB.nextPix(); } } // cancel drawing if the x value of the triangle is out of bounds if (x >= img.getWidth()) {break;} if (x > 0) { // check which way to loop // TODO - work out a way of not needing to test for this every time if (point1[1] < point2[1]) { for (int y = Math.max(point1[1], 0); y <= Math.min(point2[1], img.getHeight() - 1); y += 1) { // function only exists so I don't have to copy paste code everywhere. drawPix(img, zBuf, FPDis, scrX, scrY, currentLine, x, y, point1[1], point2[1]); } } else { for (int y = Math.max(point2[1], 0); y <= Math.min(point1[1], img.getHeight() - 1); y += 1) { drawPix(img, zBuf, FPDis, scrX, scrY, currentLine, x,y, point1[1], point2[1]); } } } } lastMillis = (System.currentTimeMillis() - lastMillis); return (int)lastMillis; } public void initialise(){ if (point1 == null || point2 == null || point3 == null){ throw new NullPointerException(); } min = new Point2D(Math.min(point1.x, Math.min(point2.x, point3.x)), Math.min(point1.y, Math.min(point2.y, point3.y))); max = new Point2D(Math.max(point1.x, Math.max(point2.x, point3.x)), Math.max(point1.y, Math.max(point2.y, point3.y))); // woo horrible IFs mess. // we need to figure out which points touch the edges in order to find which line is the 'full length' edge, // and then assign line A and line B in order if (point1.x == min.x) { if (point2.x == max.x){ LineLong = new Line2d(point1, point2, edgeList[0]); LineA = new Line2d(point1, point3, edgeList[2]); LineB = new Line2d(point3, point2, edgeList[1]); } else { LineLong = new Line2d(point1, point3, edgeList[2]); LineA = new Line2d(point1, point2, edgeList[0]); LineB = new Line2d(point2, point3, edgeList[1]); } } else if (point2.x == min.x) { if (point1.x == max.x) { LineLong = new Line2d(point2, point1, edgeList[0]); LineA = new Line2d(point2, point3, edgeList[1]); LineB = new Line2d(point3, point1, edgeList[2]); } else { LineLong = new Line2d(point2, point3, edgeList[1]); LineA = new Line2d(point2, point1, edgeList[0]); LineB = new Line2d(point1, point3, edgeList[2]); } } else if (point3.x == min.x){ if (point1.x == max.x) { LineLong = new Line2d(point3, point1, edgeList[2]); LineA = new Line2d(point3, point2, edgeList[1]); LineB = new Line2d(point2, point1, edgeList[0]); } else { LineLong = new Line2d(point3, point2, edgeList[2]); LineA = new Line2d(point3, point1, edgeList[1]); LineB = new Line2d(point1, point2, edgeList[0]); } } // assign points to lines is_initialised = true; } private void drawPix(BufferedImage img, BufferedImage zBuf, double FPDis, int scrX, int scrY, char currentLine, int x, int y, int y1, int y2){ // find Z coordinate of pixel double z1 = LineLong.getZVal(x); double z2; if(currentLine=='A'){z2=LineA.getZVal(x);} else{z2=LineB.getZVal(x);} double ZVal = z1 + ((z1-z2)/ (y1-y2) * (y - y1)); // a value of 0 represents a value which is on the camera, at z=0. // not the best mapping but it's probably good enough int newZ = (int)((2147483648L/ZVal)); // if the new Z value is greater than the existing Z value on the buffer, the new pixel is calculated and drawn if(zBuf.getRGB(x, y) == Color.HSBtoRGB(0, 0, 0) || newZ > zBuf.getRGB(x, y)){ //newZ > zBuf.getRGB(x, y) || zBuf.setRGB(x, y, newZ); result = new Point3D(0,0,0); //perspectiveMappingMatrix.multiplyPoint3to(new Point3D(x, y, 0), result); // project result result.projectOn(FPDis, scrX, scrY, result2); int colour = texture.getRGB( Math.floorMod((int)(result2.x), texture.getWidth()), Math.floorMod((int)(result2.y), texture.getHeight())); img.setRGB(x, y, (int) (colour - 10*(result2.x/ texture.getWidth()) - 10*(result2.y/ texture.getHeight()))); } } }