diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/BmMap.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/BmMap.java index 3b277e87..49c15b83 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/BmMap.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/BmMap.java @@ -53,6 +53,9 @@ public class BmMap { private Predicate tileFilter; + private long renderTimeSumNanos; + private long tilesRendered; + public BmMap(String id, String name, World world, Path fileRoot, ResourcePack resourcePack, MapSettings settings) throws IOException { this.id = Objects.requireNonNull(id); this.name = Objects.requireNonNull(name); @@ -84,13 +87,24 @@ public BmMap(String id, String name, World world, Path fileRoot, ResourcePack re ); this.tileFilter = t -> true; + + this.renderTimeSumNanos = 0; + this.tilesRendered = 0; } public void renderTile(Vector2i tile) { if (!tileFilter.test(tile)) return; + long start = System.nanoTime(); + HiresModel hiresModel = hiresModelManager.render(world, tile); lowresModelManager.render(hiresModel); + + long end = System.nanoTime(); + long delta = end - start; + + renderTimeSumNanos += delta; + tilesRendered ++; } public synchronized void save() { @@ -143,6 +157,10 @@ public void setTileFilter(Predicate tileFilter) { this.tileFilter = tileFilter; } + public long getAverageNanosPerTile() { + return renderTimeSumNanos / tilesRendered; + } + @Override public int hashCode() { return id.hashCode(); diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Face.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Face.java index 7366e357..3d2f2001 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Face.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Face.java @@ -28,22 +28,21 @@ import com.flowpowered.math.matrix.Matrix3f; import com.flowpowered.math.vector.Vector2f; import com.flowpowered.math.vector.Vector3f; - import de.bluecolored.bluemap.core.util.MathUtils; public class Face { - private Vector3f p1, p2, p3; // points - private Vector3f n1, n2, n3; // normals + private final VectorM3f p1, p2, p3; // points + private final VectorM3f n1, n2, n3; // normals private Vector3f c1, c2, c3; // vertex-colors private Vector2f uv1, uv2, uv3; // texture UV private int materialIndex; private boolean normalizedNormals; public Face(Vector3f p1, Vector3f p2, Vector3f p3, Vector2f uv1, Vector2f uv2, Vector2f uv3, int materialIndex) { - this.p1 = p1; - this.p2 = p2; - this.p3 = p3; + this.p1 = new VectorM3f(p1); + this.p2 = new VectorM3f(p2); + this.p3 = new VectorM3f(p3); this.uv1 = uv1; this.uv2 = uv2; @@ -51,10 +50,9 @@ public Face(Vector3f p1, Vector3f p2, Vector3f p3, Vector2f uv1, Vector2f uv2, V this.materialIndex = materialIndex; - Vector3f faceNormal = getFaceNormal(); - this.n1 = faceNormal; - this.n2 = faceNormal; - this.n3 = faceNormal; + this.n1 = getFaceNormal(); + this.n2 = new VectorM3f(n1); + this.n3 = new VectorM3f(n1); this.normalizedNormals = true; Vector3f color = Vector3f.ONE; @@ -64,84 +62,86 @@ public Face(Vector3f p1, Vector3f p2, Vector3f p3, Vector2f uv1, Vector2f uv2, V } public void rotate(Quaternionf rotation) { - p1 = rotation.rotate(p1); - p2 = rotation.rotate(p2); - p3 = rotation.rotate(p3); + p1.rotate(rotation); + p2.rotate(rotation); + p3.rotate(rotation); - n1 = rotation.rotate(n1); - n2 = rotation.rotate(n2); - n3 = rotation.rotate(n3); + n1.rotate(rotation); + n2.rotate(rotation); + n3.rotate(rotation); } public void transform(Matrix3f transformation) { - p1 = transformation.transform(p1); - p2 = transformation.transform(p2); - p3 = transformation.transform(p3); + MatrixM3f mtransform = new MatrixM3f(transformation); - n1 = transformation.transform(n1); - n2 = transformation.transform(n2); - n3 = transformation.transform(n3); + p1.transform(mtransform); + p2.transform(mtransform); + p3.transform(mtransform); + + n1.transform(mtransform); + n2.transform(mtransform); + n3.transform(mtransform); normalizedNormals = false; } public void translate(Vector3f translation) { - p1 = translation.add(p1); - p2 = translation.add(p2); - p3 = translation.add(p3); + p1.add(translation); + p2.add(translation); + p3.add(translation); } public Vector3f getP1() { - return p1; + return p1.toVector3f(); } public void setP1(Vector3f p1) { - this.p1 = p1; + this.p1.set(p1); } public Vector3f getP2() { - return p2; + return p2.toVector3f(); } public void setP2(Vector3f p2) { - this.p2 = p2; + this.p2.set(p2); } public Vector3f getP3() { - return p3; + return p3.toVector3f(); } public void setP3(Vector3f p3) { - this.p3 = p3; + this.p3.set(p3); } public Vector3f getN1() { - normlizeNormals(); - return n1; + normalizeNormals(); + return n1.toVector3f(); } public void setN1(Vector3f n1) { - this.n1 = n1; + this.n1.set(n1); normalizedNormals = false; } public Vector3f getN2() { - normlizeNormals(); - return n2; + normalizeNormals(); + return n2.toVector3f(); } public void setN2(Vector3f n2) { - this.n2 = n2; + this.n2.set(n2); normalizedNormals = false; } public Vector3f getN3() { - normlizeNormals(); - return n3; + normalizeNormals(); + return n3.toVector3f(); } public void setN3(Vector3f n3) { - this.n3 = n3; + this.n3.set(n3); normalizedNormals = false; } @@ -201,16 +201,16 @@ public void setMaterialIndex(int materialIndex) { this.materialIndex = materialIndex; } - public Vector3f getFaceNormal() { + private VectorM3f getFaceNormal() { return MathUtils.getSurfaceNormal(p1, p2, p3); } - private void normlizeNormals() { + private void normalizeNormals() { if (normalizedNormals) return; - n1 = n1.normalize(); - n2 = n2.normalize(); - n3 = n3.normalize(); + n1.normalize(); + n2.normalize(); + n3.normalize(); normalizedNormals = true; } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/MatrixM3f.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/MatrixM3f.java new file mode 100644 index 00000000..41b91f17 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/MatrixM3f.java @@ -0,0 +1,47 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.core.model; + +import com.flowpowered.math.matrix.Matrix3f; + +public class MatrixM3f { + + public float m00, m01, m02; + public float m10, m11, m12; + public float m20, m21, m22; + + public MatrixM3f(Matrix3f v) { + this.m00 = v.get(0, 0); + this.m01 = v.get(0, 1); + this.m02 = v.get(0, 2); + this.m10 = v.get(1, 0); + this.m11 = v.get(1, 1); + this.m12 = v.get(1, 2); + this.m20 = v.get(2, 0); + this.m21 = v.get(2, 1); + this.m22 = v.get(2, 2); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/VectorM3f.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/VectorM3f.java new file mode 100644 index 00000000..aa53f93f --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/VectorM3f.java @@ -0,0 +1,120 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.core.model; + +import com.flowpowered.math.GenericMath; +import com.flowpowered.math.imaginary.Quaternionf; +import com.flowpowered.math.vector.Vector3f; + +public class VectorM3f { + + public float x, y, z; + + public VectorM3f(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + + public VectorM3f(VectorM3f v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + } + + public VectorM3f(Vector3f v) { + this.x = v.getX(); + this.y = v.getY(); + this.z = v.getZ(); + } + + public void set(Vector3f v) { + this.x = v.getX(); + this.y = v.getY(); + this.z = v.getZ(); + } + + public void add(VectorM3f translation) { + this.x += translation.x; + this.y += translation.y; + this.z += translation.z; + } + + public void add(Vector3f translation) { + this.x += translation.getX(); + this.y += translation.getX(); + this.z += translation.getX(); + } + + public void rotate(Quaternionf rotation) { + final float length = rotation.length(); + if (Math.abs(length) < GenericMath.FLT_EPSILON) { + throw new ArithmeticException("Cannot rotate by the zero quaternion"); + } + final float nx = rotation.getX() / length; + final float ny = rotation.getY() / length; + final float nz = rotation.getZ() / length; + final float nw = rotation.getW() / length; + final float px = nw * x + ny * z - nz * y; + final float py = nw * y + nz * x - nx * z; + final float pz = nw * z + nx * y - ny * x; + final float pw = -nx * x - ny * y - nz * z; + + this.x = pw * -nx + px * nw - py * nz + pz * ny; + this.y = pw * -ny + py * nw - pz * nx + px * nz; + this.z = pw * -nz + pz * nw - px * ny + py * nx; + } + + public void transform(MatrixM3f t) { + float lx = x, ly = y; + this.x = t.m00 * lx + t.m01 * ly + t.m02 * z; + this.y = t.m10 * lx + t.m11 * ly + t.m12 * z; + this.z = t.m20 * lx + t.m21 * ly + t.m22 * z; + } + + public void normalize() { + final float length = length(); + if (Math.abs(length) < GenericMath.FLT_EPSILON) { + throw new ArithmeticException("Cannot normalize the zero vector"); + } + + x /= length; + y /= length; + z /= length; + } + + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + public float lengthSquared() { + return x * x + y * y + z * z; + } + + public Vector3f toVector3f() { + return new Vector3f(this.x, this.y, this.z); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/MathUtils.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/MathUtils.java index db9ff38b..979b240d 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/MathUtils.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/MathUtils.java @@ -28,6 +28,7 @@ import com.flowpowered.math.vector.Vector3f; import com.flowpowered.math.vector.Vector3i; import com.flowpowered.math.vector.Vector4f; +import de.bluecolored.bluemap.core.model.VectorM3f; public class MathUtils { @@ -72,6 +73,27 @@ public static Vector3f getSurfaceNormal(Vector3f p1, Vector3f p2, Vector3f p3) { return n; } + /** + * Calculates the surface-normal of a plane spanned between three vectors. + * @param p1 The first vector + * @param p2 The second vector + * @param p3 The third vector + * @return The calculated normal + */ + public static VectorM3f getSurfaceNormal(VectorM3f p1, VectorM3f p2, VectorM3f p3) { + float ux = p2.x - p1.x, uy = p2.y - p1.y, uz = p2.z - p1.z; + float vx = p3.x - p1.x, vy = p3.y - p1.y, vz = p3.z - p1.z; + + float nX = uy * vz - uz * vy; + float nY = uz * vx - ux * vz; + float nZ = ux * vy - uy * vx; + + VectorM3f n = new VectorM3f(nX, nY, nZ); + n.normalize(); + + return n; + } + /** * Hashes the provided position to a random float between 0 and 1.