diff --git a/config.json b/config.json index b4f5cd2..28dae13 100644 --- a/config.json +++ b/config.json @@ -4,14 +4,15 @@ "screenHeight":600, "maxFPS":60, "FOV":100, -"playerSpeed":5.0, +"playerSpeed":2.0, "playerSprintModifier":2.0, "debug":{ "__comment":"values are: enabled/disabled", "masterDebugToggle":"enabled", "drawDebugHud":"disabled", - "drawLines":"enabled", + "drawLines":"disabled", "overrideBackFaceCulling":"disabled", - "frustumCullingOverridePercent":0 + "frustumCullingOverridePercent":0, + "drawZBuffer":"enabled" } } diff --git a/src/main/java/uk/org/floop/epq3d/App.java b/src/main/java/uk/org/floop/epq3d/App.java index f26bc1c..e0d8ef4 100644 --- a/src/main/java/uk/org/floop/epq3d/App.java +++ b/src/main/java/uk/org/floop/epq3d/App.java @@ -37,7 +37,7 @@ } public static void initObjects(){ - JsonReader Jason = new JsonReader("testingJSON.json"); + JsonReader Jason = new JsonReader(); Jason.getObjects(); mainCollection = Jason.mainCollection; mainCollection.initialiseAll(); diff --git a/src/main/java/uk/org/floop/epq3d/Face.java b/src/main/java/uk/org/floop/epq3d/Face.java index 5d66ebb..e9f1a3a 100644 --- a/src/main/java/uk/org/floop/epq3d/Face.java +++ b/src/main/java/uk/org/floop/epq3d/Face.java @@ -1,5 +1,7 @@ package uk.org.floop.epq3d; +import java.util.ArrayList; + public class Face { public PointComp[] points; public Point2D[] UVPoints; @@ -53,11 +55,10 @@ boundingSphereR = Math.max(boundingSphereR, distance); } - calculateNormal(); perspectiveMappingMatrices = new Matrix[points.length - 2][2]; separateTris(); - generateUVMatrices(); + //generateUVMatrices(); // fixedFace is a constant object which is used temporarily when the face intersects with the camera, // and thus needs to be sliced. fixedFace = new Face(); @@ -78,7 +79,7 @@ } } - public void draw(drawData drawData) { + public void draw(drawData drawData, ArrayList frustumInfo) { double ang = normal.angleTo(new Vector3D(0.2, 0.5, 1)); if (!isInitialised) { throw new RuntimeException("Face not initialised"); @@ -120,24 +121,29 @@ if (invalidIndex == -1) { throw new RuntimeException("How did this happen?!"); } - Point3D oldPoint1 = points[trisFaceList[tri_i][Math.floorMod(invalidIndex + 1, 3)]].getRotatedPoint(); - Point3D oldPoint2 = points[trisFaceList[tri_i][Math.floorMod(invalidIndex + 2, 3)]].getRotatedPoint(); - Point3D invalidPoint = points[trisFaceList[tri_i][invalidIndex]].getRotatedPoint(); - Point3D newPoint1; - Point3D newPoint2; + PointComp oldPoint1 = points[trisFaceList[tri_i][Math.floorMod(invalidIndex + 1, 3)]]; + PointComp oldPoint2 = points[trisFaceList[tri_i][Math.floorMod(invalidIndex + 2, 3)]]; + PointComp invalidPoint = points[trisFaceList[tri_i][invalidIndex]]; + PointComp newPoint1 = new PointComp(); + PointComp newPoint2 = new PointComp(); // assign old points 1 and 2 based on the index of the invalid point // interpolate between oldPoint1 and invalidPoint - newPoint1 = interpolate(oldPoint1, invalidPoint); + newPoint1 = interpolate(drawData, frustumInfo, oldPoint1, invalidPoint); + newPoint1.setProjectedPoint(drawData); + if (newPoint1.getProjectedPoint().x == 0){ + int p = 0; + } // interpolate between oldPoint2 and invalid point - newPoint2 = interpolate(oldPoint2, invalidPoint); + newPoint2 = interpolate(drawData, frustumInfo, oldPoint2, invalidPoint); + newPoint2.setProjectedPoint(drawData); Triangle newTri; - newTri = new Triangle(oldPoint1.project(drawData), newPoint2.project(drawData), newPoint1.project(drawData), + newTri = new Triangle(oldPoint1, newPoint2, newPoint1, new boolean[]{false, false, false}, tris[tri_i].texture, tris[tri_i].perspectiveMappingMatrix); newTri.draw(drawData, ang); - newTri = new Triangle(oldPoint1.project(drawData), oldPoint2.project(drawData), newPoint2.project(drawData), + newTri = new Triangle(oldPoint1, oldPoint2, newPoint2, new boolean[]{false, false, false}, tris[tri_i].texture, tris[tri_i].perspectiveMappingMatrix); @@ -153,44 +159,65 @@ if (validIndex == -1) { throw new RuntimeException("How did this happen?!"); } - Point3D invalidPoint1 = points[trisFaceList[tri_i][Math.floorMod(validIndex + 1, 3)]].getRotatedPoint(); - Point3D invalidPoint2 = points[trisFaceList[tri_i][Math.floorMod(validIndex + 2, 3)]].getRotatedPoint(); - Point3D oldPoint = points[trisFaceList[tri_i][validIndex]].getRotatedPoint(); - Point3D newPoint1; - Point3D newPoint2; + PointComp invalidPoint1 = points[trisFaceList[tri_i][Math.floorMod(validIndex + 1, 3)]]; + PointComp invalidPoint2 = points[trisFaceList[tri_i][Math.floorMod(validIndex + 2, 3)]]; + PointComp oldPoint = points[trisFaceList[tri_i][validIndex]]; + PointComp newPoint1; + PointComp newPoint2; // interpolate for z = 0.001 between invalid1 and oldPoint - newPoint1 = interpolate(oldPoint, invalidPoint1); - + newPoint1 = interpolate(drawData, frustumInfo, oldPoint, invalidPoint1); + newPoint1.setProjectedPoint(drawData); // interpolate for z = 0.001 between invalid2 and oldPoint - newPoint2 = interpolate(oldPoint, invalidPoint2); + newPoint2 = interpolate(drawData, frustumInfo, oldPoint, invalidPoint2); + newPoint2.setProjectedPoint(drawData); - // create and draw new triangle - Triangle newTri; - newTri = new Triangle(newPoint1.project(drawData), newPoint2.project(drawData), oldPoint.project(drawData), - new boolean[]{false, false, false}, - tris[tri_i].texture, - tris[tri_i].perspectiveMappingMatrix); - newTri.draw(drawData, ang); + // project points, set their z values, and then draw triangles + { + // create and draw new triangle + Triangle newTri; + newTri = new Triangle(newPoint1, newPoint2, oldPoint, + new boolean[]{false, false, false}, + tris[tri_i].texture, + tris[tri_i].perspectiveMappingMatrix); + newTri.draw(drawData, ang); + } } // if all points are invalid, do nothing } } } - private Point3D interpolate(Point3D oldPoint, Point3D invalidPoint){ - double gradX = (oldPoint.z - invalidPoint.z) / - (oldPoint.x - invalidPoint.x); - double gradY = (oldPoint.z - invalidPoint.z) / - (oldPoint.y - invalidPoint.y); + private PointComp interpolate(drawData drawData, ArrayList frustumInfo, PointComp oldPoint, PointComp invalidPoint){ + // calculate distance to each of the frustum planes. Then store the minimum distance from each of +// double minDis = 0; +// int planeMin = 0; +// for (int planeId: +// frustumInfo) { +// // don't check the near plane +// if(planeId != 0) { +// double dist = drawData.frustumPlanes[planeId].getDistance(invalidPoint.getRotatedPoint()); +// if (minDis > dist) { +// minDis = dist; +// planeMin = planeId; +// } +// } +// } + double interpolateZval = 0.001; + double gradX = (oldPoint.getRotatedPoint().z - invalidPoint.getRotatedPoint().z) / + (oldPoint.getRotatedPoint().x - invalidPoint.getRotatedPoint().x); + double gradY = (oldPoint.getRotatedPoint().z - invalidPoint.getRotatedPoint().z) / + (oldPoint.getRotatedPoint().y - invalidPoint.getRotatedPoint().y); - Point3D newPoint = new Point3D( - (0.001 + gradX * oldPoint.x - oldPoint.z) / gradX, - (0.001 + gradY * oldPoint.y - oldPoint.z) / gradY, - 0.001); + Point3D newPointRotated = new Point3D( + (interpolateZval + gradX * oldPoint.getRotatedPoint().x - oldPoint.getRotatedPoint().z) / gradX, + (interpolateZval + gradY * oldPoint.getRotatedPoint().y - oldPoint.getRotatedPoint().z) / gradY, + interpolateZval); if (!Double.isFinite(gradX)) { - newPoint.x = oldPoint.x; + newPointRotated.x = oldPoint.getRotatedPoint().x; } if (!Double.isFinite(gradY)) { - newPoint.y = oldPoint.y; + newPointRotated.y = oldPoint.getRotatedPoint().y; } + PointComp newPoint = new PointComp(); newPoint.invalidate(); + newPoint.setRotatedPoint(newPointRotated); return newPoint; } /* @@ -288,9 +315,9 @@ newTrisFaceList[i][2] = i + 2; newTris[i] = new Triangle( - points[0].getProjectedPoint(), - points[i + 1].getProjectedPoint(), - points[i + 2].getProjectedPoint(), + points[0], + points[i + 1], + points[i + 2], new boolean[]{hasEdges, hasEdges, hasEdges}, texture, perspectiveMappingMatrices[i]); } @@ -452,7 +479,7 @@ pointUV.set(uvTo00.multiplyPoint3raw(UVPoints[tri[2]].x, UVPoints[tri[2]].y, 0)); double xScale = pointUV.x / pointFace.x; - System.out.println("Scale: " + xScale); + //System.out.println("Scale: " + xScale); MultMat.setItems(new double[][]{ {xScale, 0, 0, 0}, {0, 1, 0, 0}, diff --git a/src/main/java/uk/org/floop/epq3d/JsonReader.java b/src/main/java/uk/org/floop/epq3d/JsonReader.java index 3a34e8e..18082ec 100644 --- a/src/main/java/uk/org/floop/epq3d/JsonReader.java +++ b/src/main/java/uk/org/floop/epq3d/JsonReader.java @@ -12,23 +12,31 @@ // Program for print data in JSON format. public class JsonReader { - JSONObject file; + JSONObject fileCollections; + JSONObject fileTextures; + Texture[] textures; ObjectCollection mainCollection; - public JsonReader(String filePath) { + public JsonReader() { JSONParser parser = new JSONParser(); Object obj; try { - obj = parser.parse(new FileReader(filePath)); + obj = parser.parse(new FileReader("jsonCollections.json")); } catch (IOException | ParseException e) { throw new RuntimeException(e); } - file = (JSONObject)obj; + fileCollections = (JSONObject)obj; + try { + obj = parser.parse(new FileReader("jsonTextures.json")); + } catch (IOException | ParseException e) { + throw new RuntimeException(e); + } + fileTextures = (JSONObject)obj; } public void getObjects(){ - textures = getTextures((JSONArray) file.get("textures")); - mainCollection = separateCollection((JSONObject) ((JSONArray)file.get("collections")).get(0), textures); - file.get("collection"); + textures = getTextures((JSONArray) fileTextures.get("textures")); + mainCollection = separateCollection((JSONObject) ((JSONArray) fileCollections.get("collections")).get(0), textures); + fileCollections.get("collection"); } private ObjectCollection separateCollection(JSONObject json, Texture[] textures){ ObjectCollection result = new ObjectCollection(); @@ -57,7 +65,6 @@ ); } - // make faceList, UV list and texture lists // (the indices should match up, if they don't something went wrong) JSONArray faceListJson = (JSONArray) object.get("faceList"); @@ -70,29 +77,26 @@ for (int i = 0; i < faceListJson.size(); i+=1) { JSONArray jsonFace = (JSONArray) faceListJson.get(i); - JSONArray jsonUV = (JSONArray) uvPointsListJson.get(i); String jsonTextureName = (String) texturesNamesJson.get(i); faceList[i] = new int[jsonFace.size()]; uvPointsList[i] = new Point2D[jsonFace.size()]; - - for (int j = 0; j < jsonFace.size(); j += 1){ - faceList[i][j] = Integer.parseInt(String.valueOf(jsonFace.get(j))); - uvPointsList[i][j] = new Point2D( -0,0 - ); -// Integer.parseInt(String.valueOf(((JSONArray)jsonUV.get(j)).get(0))), -// Integer.parseInt(String.valueOf(((JSONArray)jsonUV.get(j)).get(1))) -// ); - } - - // terrible linear search but idc because this code only runs once + // probably inefficient linear search but idc because this code only runs once for (Texture texture : textures) { if (Objects.equals(texture.name, jsonTextureName)) { texturesList[i] = texture; break; } } + for (int j = 0; j < jsonFace.size(); j += 1){ + faceList[i][j] = (int)(long)jsonFace.get(j); + if(!texturesList[i].isSolid()){ + uvPointsList[i][j] = new Point2D( + (int)(double)((JSONArray)uvPointsListJson.get(faceList[i][j])).get(0), + (int)(double)((JSONArray)uvPointsListJson.get(faceList[i][j])).get(1)); + } + } + } result.addObject(new Object3d(points, faceList, uvPointsList, false, texturesList, true)); } @@ -104,6 +108,7 @@ JSONObject JsonTexture = (JSONObject) textures.get(i); if(Objects.equals(JsonTexture.get("type"), "solid")){ result[i] = new Texture(JsonTexture.get("name").toString(), Color.decode('#' + (String) JsonTexture.get("color"))); + //result[i] = new Texture(JsonTexture.get("name").toString(), Color.decode('#' + "0000ff")); } } return result; diff --git a/src/main/java/uk/org/floop/epq3d/Line2d.java b/src/main/java/uk/org/floop/epq3d/Line2d.java index 8ec6f3d..1e027ae 100644 --- a/src/main/java/uk/org/floop/epq3d/Line2d.java +++ b/src/main/java/uk/org/floop/epq3d/Line2d.java @@ -5,8 +5,8 @@ // handles line and line drawing public class Line2d { - public Point2D point1; - public Point2D point2; + public PointComp point1; + public PointComp point2; public boolean isDrawn; @@ -23,7 +23,7 @@ // drawing progress variables private int iteratorVal; private int D; - public Line2d(Point2D _point1, Point2D _point2, boolean _isDrawn){ + public Line2d(PointComp _point1, PointComp _point2, boolean _isDrawn){ point1 = _point1; point2 = _point2; isDrawn = _isDrawn; @@ -63,12 +63,12 @@ */ public void initialise(){ // initialise brensenham algorithm - if (point2.x > point1.x) { - realPoint1 = point1; - realPoint2 = point2; + if (point2.getProjectedPoint().x > point1.getProjectedPoint().x) { + realPoint1 = point1.getProjectedPoint(); + realPoint2 = point2.getProjectedPoint(); } else { // if dx is less than zero, swap the points around - realPoint1 = point2; - realPoint2 = point1; + realPoint1 = point2.getProjectedPoint(); + realPoint2 = point1.getProjectedPoint(); } dx = realPoint2.x - realPoint1.x; dy = realPoint2.y - realPoint1.y; diff --git a/src/main/java/uk/org/floop/epq3d/Object3d.java b/src/main/java/uk/org/floop/epq3d/Object3d.java index c6327b3..bc3fc5d 100644 --- a/src/main/java/uk/org/floop/epq3d/Object3d.java +++ b/src/main/java/uk/org/floop/epq3d/Object3d.java @@ -43,6 +43,7 @@ // check for frustum culling of faces // works the same as for collections. // see explanation within ObjectCollection + ArrayList newFrustumInfo = new ArrayList(); boolean draw = true; for (int planeId: frustumInfo) { @@ -50,9 +51,11 @@ if (dist < -face.boundingSphereR + face.boundingSphereR * drawData.frustumCullingOverridePercent){ draw = false; break; + } else if(dist < face.boundingSphereR) { + newFrustumInfo.add(planeId); } } - if(draw){face.draw(drawData);} + if(draw){face.draw(drawData, newFrustumInfo);} } } } diff --git a/src/main/java/uk/org/floop/epq3d/ObjectCollection.java b/src/main/java/uk/org/floop/epq3d/ObjectCollection.java index 999ddf1..21b8e7c 100644 --- a/src/main/java/uk/org/floop/epq3d/ObjectCollection.java +++ b/src/main/java/uk/org/floop/epq3d/ObjectCollection.java @@ -129,7 +129,6 @@ newFrustumInfo.add(planeId); } // else if not technically required because of break but it makes me happy - } if(draw){collection.draw(drawData, newFrustumInfo);} } diff --git a/src/main/java/uk/org/floop/epq3d/Point2D.java b/src/main/java/uk/org/floop/epq3d/Point2D.java index 46cc457..a415ff3 100644 --- a/src/main/java/uk/org/floop/epq3d/Point2D.java +++ b/src/main/java/uk/org/floop/epq3d/Point2D.java @@ -16,5 +16,4 @@ public int[] get(){ return new int[]{x, y}; } - } diff --git a/src/main/java/uk/org/floop/epq3d/Point3D.java b/src/main/java/uk/org/floop/epq3d/Point3D.java index d8fe766..16eae53 100644 --- a/src/main/java/uk/org/floop/epq3d/Point3D.java +++ b/src/main/java/uk/org/floop/epq3d/Point3D.java @@ -51,12 +51,7 @@ // (int)(drawData.scrX*0.5*((drawData.FPDis*x)/(z) + ((double)drawData.scrY/(double)drawData.scrX))) point.x = drawData.scrX - (int)(drawData.scrX*0.5*((drawData.FPDis*y)/(z) + 1)); point.y = (int)(drawData.scrX*0.5*((drawData.FPDis*x)/(z) + ((double)drawData.scrY/(double)drawData.scrX))); - /* link: - https://en.wikipedia.org/wiki/3D_projection - Mathematical formula - */ -// point.x = (int)((point.y * drawData.scrX) / (point.z * 1)*drawData.FPDis); -// point.y = (int)((point.x * drawData.scrX) / (point.z * 1)*drawData.FPDis); + point.z = z; if(Math.abs(point.x) > 5000 || Math.abs(point.y) > 5000){ int debug = 12; @@ -68,12 +63,7 @@ // sorry point.x = drawData.scrX - (int)(drawData.scrX*0.5*((drawData.FPDis*y)/(z) + 1)); point.y = (int)(drawData.scrX*0.5*((drawData.FPDis*x)/(z) + ((double)drawData.scrY/(double)drawData.scrX))); - /* link: - https://en.wikipedia.org/wiki/3D_projection - Mathematical formula - */ -// point.x = (int)((-y * drawData.scrX) / (z * 2)*drawData.FPDis) + drawData.scrX / 2; -// point.y = (int)((x * drawData.scrX) / (z * 2)*drawData.FPDis) + drawData.scrX / 2; + point.z = z; } public double[] get(){ return new double[]{x, y, z}; diff --git a/src/main/java/uk/org/floop/epq3d/PointComp.java b/src/main/java/uk/org/floop/epq3d/PointComp.java index c82a1e3..bc08fe1 100644 --- a/src/main/java/uk/org/floop/epq3d/PointComp.java +++ b/src/main/java/uk/org/floop/epq3d/PointComp.java @@ -11,6 +11,9 @@ point.y = _y; point.z = _z; } + + public PointComp() { + } public void invalidate(){ isProjectedPointValid = false; isRotatedPointValid = false; } @@ -32,6 +35,12 @@ isRotatedPointValid = true; } } + public void setRotatedPoint(Point3D newRotatedPoint){ + rotatedPoint.x = newRotatedPoint.x; + rotatedPoint.y = newRotatedPoint.y; + rotatedPoint.z = newRotatedPoint.z; + isRotatedPointValid = true; + } public void setProjectedPoint(drawData drawData){ if(!isProjectedPointValid) { rotatedPoint.projectOn(drawData, projectedPoint); diff --git a/src/main/java/uk/org/floop/epq3d/Screen.java b/src/main/java/uk/org/floop/epq3d/Screen.java index f0b7841..373a5f6 100644 --- a/src/main/java/uk/org/floop/epq3d/Screen.java +++ b/src/main/java/uk/org/floop/epq3d/Screen.java @@ -183,15 +183,18 @@ } } // write debug overlay - BufferedImage bufImg = new BufferedImage(drawData.scrX, drawData.scrY, BufferedImage.TYPE_INT_ARGB); for(int x = 0; x < drawData.scrX; x +=1){ for(int y = 0; y < drawData.scrY; y += 1){ - bufImg.setRGB(x, y, drawData.drawImg[x][y]); + if(drawData.drawZBuffer){ + drawData.bufImg.setRGB(x, y, Color.getHSBColor(0, 0, (float)drawData.zBuf[x][y]/2147483648f).getRGB()); + } else { + drawData.bufImg.setRGB(x, y, drawData.drawImg[x][y]); + } drawData.drawImg[x][y] = 0; drawData.zBuf[x][y] = 0; } } - g.drawImage(bufImg, 0, 0, this); + g.drawImage(drawData.bufImg, 0, 0, this); g.drawImage(drawData.debugImg, 0, 0, this); for(int x = 0; x < drawData.scrX; x +=1){ for(int y = 0; y < drawData.scrY; y += 1){ diff --git a/src/main/java/uk/org/floop/epq3d/Texture.java b/src/main/java/uk/org/floop/epq3d/Texture.java index 1a35076..40b3ded 100644 --- a/src/main/java/uk/org/floop/epq3d/Texture.java +++ b/src/main/java/uk/org/floop/epq3d/Texture.java @@ -46,11 +46,14 @@ } public Color getColor(double ang) { - double multiplier = 1 - ang/(2*Math.PI); + double multiplier = 1.5 - ang/(Math.PI); int rgb = color.getRGB(); - int r = rgb & 0xff; + int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; - int b = (rgb >> 16) & 0xff; - return new Color((int) (r*multiplier), (int) (g*multiplier), (int) (b*multiplier)); + int b = rgb & 0xff; + return new Color( + (int) (Math.min(255, (r + 255*(multiplier-1)) * multiplier - 255*(multiplier-1))), + (int) (Math.min(255, (g + 255*(multiplier-1)) * multiplier - 255*(multiplier-1))), + (int) (Math.min(255, (b + 255*(multiplier-1)) * multiplier - 255*(multiplier-1)))); } } diff --git a/src/main/java/uk/org/floop/epq3d/Triangle.java b/src/main/java/uk/org/floop/epq3d/Triangle.java index 3bc0e14..a47b43e 100644 --- a/src/main/java/uk/org/floop/epq3d/Triangle.java +++ b/src/main/java/uk/org/floop/epq3d/Triangle.java @@ -3,9 +3,9 @@ import java.awt.*; public class Triangle{ - public Point2D point1; - public Point2D point2; - public Point2D point3; + public PointComp point1; + public PointComp point2; + public PointComp point3; public Matrix[] perspectiveMappingMatrix; @@ -27,7 +27,7 @@ public void invalidate() { is_initialised = false; } - public Triangle(Point2D _pA, Point2D _pB, Point2D _pC, boolean[] _edgeList, Texture _texture, Matrix[] mapMatrix){ + public Triangle(PointComp _pA, PointComp _pB, PointComp _pC, boolean[] _edgeList, Texture _texture, Matrix[] mapMatrix){ point1 = _pA; point2 = _pB; point3 = _pC; @@ -73,7 +73,6 @@ } catch (RuntimeException e){ currentLine = 'B'; - // point2 = LineB.nextPix(); } } else { @@ -87,41 +86,63 @@ // cancel drawing if the x value of the triangle is out of bounds if (x >= drawData.scrX) {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]) { + double z1 = LineLong.getZVal(x); double z2; + if(currentLine=='A'){ + z2=LineA.getZVal(x); + } else{ + z2=LineB.getZVal(x); + } + double gradient = -(z2 - z1) / (point2[1]-point1[1]); for (int y = Math.max(point1[1], 0); y <= Math.min(point2[1], drawData.scrY - 1); y += 1) { // function only exists so I don't have to copy paste code everywhere. - drawPix(drawData, currentLine, x, y, point1[1], point2[1], ang); + double zVal = z1 + gradient*(point1[1]-y); + drawPix(drawData, x, y, zVal, ang); } } else { + double z2 = LineLong.getZVal(x); double z1; + if(currentLine=='A'){ + z1=LineA.getZVal(x); + } else{ + z1=LineB.getZVal(x); + } + double gradient = -(z2 - z1) / (point1[1]-point2[1]); for (int y = Math.max(point2[1], 0); y <= Math.min(point1[1], drawData.scrY - 1); y += 1) { - drawPix(drawData, currentLine, x,y, point1[1], point2[1], ang); + double zVal = z1 + gradient*(point2[1]-y); + drawPix(drawData, x, y, zVal, ang); } } } } lastMillis = (System.currentTimeMillis() - lastMillis); return (int)lastMillis; - - } - } + } + } return 0; } public boolean initialise(drawData drawData){ + 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))); + min = new Point2D( + Math.min(point1.getProjectedPoint().x, + Math.min(point2.getProjectedPoint().x, point3.getProjectedPoint().x)), + Math.min(point1.getProjectedPoint().y, + Math.min(point2.getProjectedPoint().y, point3.getProjectedPoint().y))); + max = new Point2D( + Math.max(point1.getProjectedPoint().x, + Math.max(point2.getProjectedPoint().x, point3.getProjectedPoint().x)), + Math.max(point1.getProjectedPoint().y, + Math.max(point2.getProjectedPoint().y, point3.getProjectedPoint().y))); if(max.x < 0 || min.x > drawData.scrX || max.y < 0 || min.y > drawData.scrY){ return false; } // 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){ + if (point1.getProjectedPoint().x == min.x) { + if (point2.getProjectedPoint().x == max.x){ LineLong = new Line2d(point1, point2, edgeList[0]); LineA = new Line2d(point1, point3, edgeList[2]); LineB = new Line2d(point3, point2, edgeList[1]); @@ -131,8 +152,8 @@ LineB = new Line2d(point2, point3, edgeList[1]); } } - else if (point2.x == min.x) { - if (point1.x == max.x) { + else if (point2.getProjectedPoint().x == min.x) { + if (point1.getProjectedPoint().x == max.x) { LineLong = new Line2d(point2, point1, edgeList[0]); LineA = new Line2d(point2, point3, edgeList[1]); LineB = new Line2d(point3, point1, edgeList[2]); @@ -142,8 +163,8 @@ LineB = new Line2d(point1, point3, edgeList[2]); } } - else if (point3.x == min.x){ - if (point1.x == max.x) { + else if (point3.getProjectedPoint().x == min.x){ + if (point1.getProjectedPoint().x == max.x) { LineLong = new Line2d(point3, point1, edgeList[2]); LineA = new Line2d(point3, point2, edgeList[1]); LineB = new Line2d(point2, point1, edgeList[0]); @@ -153,19 +174,15 @@ LineB = new Line2d(point1, point2, edgeList[0]); } } + // find z calculation constants + // they are always relative to lineLong point1 + PointComp refPoint = LineLong.point1; + Vector3D vec1 = new Vector3D(refPoint.getRotatedPoint(), LineLong.point2.getRotatedPoint()); // assign points to lines is_initialised = true; return true; } - private void drawPix(drawData drawData, char currentLine, int x, int y, int y1, int y2, double ang){ - // 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)); + private void drawPix(drawData drawData, int x, int y, double ZVal, double ang){ // 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+1))); diff --git a/src/main/java/uk/org/floop/epq3d/Vector3D.java b/src/main/java/uk/org/floop/epq3d/Vector3D.java index ecfa94a..bd21f26 100644 --- a/src/main/java/uk/org/floop/epq3d/Vector3D.java +++ b/src/main/java/uk/org/floop/epq3d/Vector3D.java @@ -15,6 +15,13 @@ y = 0; z = 0; } + + public Vector3D(Point3D start, Point3D end) { + x = end.x - start.x; + y = end.y - start.y; + z = end.z - start.z; + } + public void createFrom2Points(Point3D start, Point3D end){ x = end.x - start.x; y = end.y - start.y; diff --git a/src/main/java/uk/org/floop/epq3d/drawData.java b/src/main/java/uk/org/floop/epq3d/drawData.java index ea51778..c53e16a 100644 --- a/src/main/java/uk/org/floop/epq3d/drawData.java +++ b/src/main/java/uk/org/floop/epq3d/drawData.java @@ -25,12 +25,15 @@ // debug public boolean debugHud; public boolean backfaceCullingDisabled; + public boolean drawZBuffer; public int frustumCullingOverridePercent; + // player public double playerSpeed; public double playerSprintModifier; // draw onto + BufferedImage bufImg; public int[][] drawImg; public int[][] zBuf; public BufferedImage debugImg; @@ -67,8 +70,10 @@ debugHud = toBoolean(debugFile.get("drawDebugHud")); backfaceCullingDisabled = toBoolean(debugFile.get("overrideBackFaceCulling")); frustumCullingOverridePercent = (int)(long)debugFile.get("frustumCullingOverridePercent"); - } + drawZBuffer = toBoolean(debugFile.get("drawZBuffer")); + } + bufImg = new BufferedImage(scrX, scrY, BufferedImage.TYPE_INT_ARGB); drawImg = new int[scrX][scrY]; zBuf = new int[scrX][scrY]; debugImg = new BufferedImage(scrX, scrY, BufferedImage.TYPE_INT_ARGB); diff --git a/src/main/java/uk/org/floop/epq3d/testing.java b/src/main/java/uk/org/floop/epq3d/testing.java index ff24384..a439d60 100644 --- a/src/main/java/uk/org/floop/epq3d/testing.java +++ b/src/main/java/uk/org/floop/epq3d/testing.java @@ -2,7 +2,7 @@ class testing { public static void main(String[] args) { - JsonReader Jason = new JsonReader("cube.json"); + JsonReader Jason = new JsonReader(); Jason.getObjects(); ObjectCollection main = Jason.mainCollection; Texture[] textures = Jason.textures;