diff --git a/src/org/joml/AABBd.java b/src/org/joml/AABBd.java deleted file mode 100644 index 06cd6da2b..000000000 --- a/src/org/joml/AABBd.java +++ /dev/null @@ -1,714 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents an axis-aligned box defined via the minimum and maximum corner coordinates as double-precision floats. - * - * @author Kai Burjack - */ -public class AABBd implements Externalizable, AABBdc { - - /** - * The x coordinate of the minimum corner. - */ - public double minX = Double.POSITIVE_INFINITY; - /** - * The y coordinate of the minimum corner. - */ - public double minY = Double.POSITIVE_INFINITY; - /** - * The z coordinate of the minimum corner. - */ - public double minZ = Double.POSITIVE_INFINITY; - /** - * The x coordinate of the maximum corner. - */ - public double maxX = Double.NEGATIVE_INFINITY; - /** - * The y coordinate of the maximum corner. - */ - public double maxY = Double.NEGATIVE_INFINITY; - /** - * The z coordinate of the maximum corner. - */ - public double maxZ = Double.NEGATIVE_INFINITY; - - /** - * Create a new {@link AABBd} representing the box with - * (minX, minY, minZ)=(+inf, +inf, +inf) and (maxX, maxY, maxZ)=(-inf, -inf, -inf). - */ - public AABBd() { - } - - /** - * Create a new {@link AABBd} as a copy of the given source. - * - * @param source - * the {@link AABBd} to copy from - */ - public AABBd(AABBdc source) { - this.minX = source.minX(); - this.minY = source.minY(); - this.minZ = source.minZ(); - this.maxX = source.maxX(); - this.maxY = source.maxY(); - this.maxZ = source.maxZ(); - } - - /** - * Create a new {@link AABBd} with the given minimum and maximum corner coordinates. - * - * @param min - * the minimum coordinates - * @param max - * the maximum coordinates - */ - public AABBd(Vector3fc min, Vector3fc max) { - this.minX = min.x(); - this.minY = min.y(); - this.minZ = min.z(); - this.maxX = max.x(); - this.maxY = max.y(); - this.maxZ = max.z(); - } - - /** - * Create a new {@link AABBd} with the given minimum and maximum corner coordinates. - * - * @param min - * the minimum coordinates - * @param max - * the maximum coordinates - */ - public AABBd(Vector3dc min, Vector3dc max) { - this.minX = min.x(); - this.minY = min.y(); - this.minZ = min.z(); - this.maxX = max.x(); - this.maxY = max.y(); - this.maxZ = max.z(); - } - - /** - * Create a new {@link AABBd} with the given minimum and maximum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @param minZ - * the z coordinate of the minimum corner - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - * @param maxZ - * the z coordinate of the maximum corner - */ - public AABBd(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { - this.minX = minX; - this.minY = minY; - this.minZ = minZ; - this.maxX = maxX; - this.maxY = maxY; - this.maxZ = maxZ; - } - - public double minX() { - return minX; - } - - public double minY() { - return minY; - } - - public double minZ() { - return minZ; - } - - public double maxX() { - return maxX; - } - - public double maxY() { - return maxY; - } - - public double maxZ() { - return maxZ; - } - - /** - * Set this {@link AABBd} to be a clone of source. - * - * @param source - * the {@link AABBd} to copy from - * @return this - */ - public AABBd set(AABBdc source){ - this.minX = source.minX(); - this.minY = source.minY(); - this.minZ = source.minZ(); - this.maxX = source.maxX(); - this.maxY = source.maxY(); - this.maxZ = source.maxZ(); - return this; - } - - private AABBd validate() { - if (!isValid()) { - minX = Double.POSITIVE_INFINITY; - minY = Double.POSITIVE_INFINITY; - minZ = Double.POSITIVE_INFINITY; - - maxX = Double.NEGATIVE_INFINITY; - maxY = Double.NEGATIVE_INFINITY; - maxZ = Double.NEGATIVE_INFINITY; - } - return this; - } - - public boolean isValid() { - return minX < maxX && minY < maxY && minZ < maxZ; - } - - - /** - * Set the minimum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @param minZ - * the z coordinate of the minimum corner - * @return this - */ - public AABBd setMin(double minX, double minY, double minZ) { - this.minX = minX; - this.minY = minY; - this.minZ = minZ; - return this; - } - - /** - * Set the maximum corner coordinates. - * - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - * @param maxZ - * the z coordinate of the maximum corner - * @return this - */ - public AABBd setMax(double maxX, double maxY, double maxZ) { - this.maxX = maxX; - this.maxY = maxY; - this.maxZ = maxZ; - return this; - } - - /** - * Set the minimum corner coordinates. - * - * @param min - * the minimum coordinates - * @return this - */ - public AABBd setMin(Vector3dc min) { - return this.setMin(min.x(), min.y(), min.z()); - } - - /** - * Set the maximum corner coordinates. - * - * @param max - * the maximum coordinates - * @return this - */ - public AABBd setMax(Vector3dc max) { - return this.setMax(max.x(), max.y(), max.z()); - } - - public double getMax(int component) throws IllegalArgumentException { - switch (component) { - case 0: - return maxX; - case 1: - return maxY; - case 2: - return maxZ; - default: - throw new IllegalArgumentException(); - } - } - - public double getMin(int component) throws IllegalArgumentException { - switch (component) { - case 0: - return minX; - case 1: - return minY; - case 2: - return minZ; - default: - throw new IllegalArgumentException(); - } - } - - public Vector3d center(Vector3d dest) { - return dest.set(minX + ((maxX - minX) / 2.0), minY + ((maxY - minY) / 2.0), minZ + ((maxZ - minZ) / 2.0)); - } - - public Vector3f center(Vector3f dest) { - return dest.set(minX + ((maxX - minX) / 2.0f), minY + ((maxY - minY) / 2.0f), minZ + ((maxZ - minZ) / 2.0f)); - } - - public Vector3d extent(Vector3d dest) { - return dest.set((maxX - minX) / 2.0, (maxY - minY) / 2.0, (maxZ - minZ) / 2.0); - } - - public Vector3f extent(Vector3f dest) { - return dest.set((maxX - minX) / 2.0f, (maxY - minY) / 2.0f, (maxZ - minZ) / 2.0f); - } - - /** - * Return the length along the x component - * - * @return length in the x dimension - */ - public double lengthX(){ - return maxX - minX; - } - - /** - * Return the length along the y component - * - * @return length in the y dimension - */ - public double lengthY(){ - return maxY - minY; - } - - /** - * Return the length along the z component - * - * @return length in the z dimension - */ - public double lengthZ(){ - return maxZ - minZ; - } - - /** - * Get the size of the aabb. - * - * @param dest - * will hold the result - * @return dest - */ - public Vector3f getSize(Vector3f dest) { - return dest.set(lengthX(), lengthY(), lengthZ()); - } - - /** - * Get the size of the aabb. - * - * @param dest - * will hold the result - * @return dest - */ - public Vector3d getSize(Vector3d dest) { - return dest.set(lengthX(), lengthY(), lengthZ()); - } - - /** - * Set this to the union of this and the given point (x, y, z). - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @return this - */ - public AABBd union(double x, double y, double z) { - return union(x, y, z, this); - } - - /** - * Set this to the union of this and the given point p. - * - * @param p - * the point - * @return this - */ - public AABBd union(Vector3dc p) { - return union(p.x(), p.y(), p.z(), this); - } - - public AABBd union(double x, double y, double z, AABBd dest) { - dest.minX = this.minX < x ? this.minX : x; - dest.minY = this.minY < y ? this.minY : y; - dest.minZ = this.minZ < z ? this.minZ : z; - dest.maxX = this.maxX > x ? this.maxX : x; - dest.maxY = this.maxY > y ? this.maxY : y; - dest.maxZ = this.maxZ > z ? this.maxZ : z; - return dest; - } - - public AABBd union(Vector3dc p, AABBd dest) { - return union(p.x(), p.y(), p.z(), dest); - } - - /** - * Set this to the union of this and other. - * - * @param other - * the other {@link AABBd} - * @return this - */ - public AABBd union(AABBdc other) { - return this.union(other, this); - } - - public AABBd union(AABBdc other, AABBd dest) { - dest.minX = this.minX < other.minX() ? this.minX : other.minX(); - dest.minY = this.minY < other.minY() ? this.minY : other.minY(); - dest.minZ = this.minZ < other.minZ() ? this.minZ : other.minZ(); - dest.maxX = this.maxX > other.maxX() ? this.maxX : other.maxX(); - dest.maxY = this.maxY > other.maxY() ? this.maxY : other.maxY(); - dest.maxZ = this.maxZ > other.maxZ() ? this.maxZ : other.maxZ(); - return dest; - } - - /** - * Ensure that the minimum coordinates are strictly less than or equal to the maximum coordinates by swapping - * them if necessary. - * - * @return this - */ - public AABBd correctBounds() { - double tmp; - if (this.minX > this.maxX) { - tmp = this.minX; - this.minX = this.maxX; - this.maxX = tmp; - } - if (this.minY > this.maxY) { - tmp = this.minY; - this.minY = this.maxY; - this.maxY = tmp; - } - if (this.minZ > this.maxZ) { - tmp = this.minZ; - this.minZ = this.maxZ; - this.maxZ = tmp; - } - return this; - } - - /** - * Translate this by the given vector xyz. - * - * @param xyz - * the vector to translate by - * @return this - */ - public AABBd translate(Vector3dc xyz) { - return translate(xyz.x(), xyz.y(), xyz.z(), this); - } - - public AABBd translate(Vector3dc xyz, AABBd dest) { - return translate(xyz.x(), xyz.y(), xyz.z(), dest); - } - - /** - * Translate this by the given vector xyz. - * - * @param xyz - * the vector to translate by - * @return this - */ - public AABBd translate(Vector3fc xyz) { - return translate(xyz.x(), xyz.y(), xyz.z(), this); - } - - public AABBd translate(Vector3fc xyz, AABBd dest) { - return translate(xyz.x(), xyz.y(), xyz.z(), dest); - } - - /** - * Translate this by the vector (x, y, z). - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param z - * the z coordinate to translate by - * @return this - */ - public AABBd translate(double x, double y, double z) { - return translate(x, y, z, this); - } - - public AABBd translate(double x, double y, double z, AABBd dest) { - dest.minX = minX + x; - dest.minY = minY + y; - dest.minZ = minZ + z; - dest.maxX = maxX + x; - dest.maxY = maxY + y; - dest.maxZ = maxZ + z; - return dest; - } - - public AABBd intersection(AABBdc other, AABBd dest) { - dest.minX = Math.max(minX, other.minX()); - dest.minY = Math.max(minY, other.minY()); - dest.minZ = Math.max(minZ, other.minZ()); - - dest.maxX = Math.min(maxX, other.maxX()); - dest.maxY = Math.min(maxY, other.maxY()); - dest.maxZ = Math.min(maxZ, other.maxZ()); - return dest.validate(); - } - - /** - * Compute the AABB of intersection between this and the given AABB. - *

- * If the two AABBs do not intersect, then the minimum coordinates of this - * will have a value of {@link Double#POSITIVE_INFINITY} and the maximum coordinates will have a value of - * {@link Double#NEGATIVE_INFINITY}. - * - * @param other - * the other AABB - * @return this - */ - public AABBd intersection(AABBdc other) { - return intersection(other, this); - } - - public boolean containsAABB(AABBdc aabb) { - return aabb.minX() >= minX && aabb.maxX() <= maxX && - aabb.minY() >= minY && aabb.maxY() <= maxY && - aabb.minZ() >= minZ && aabb.maxZ() <= maxZ; - } - - public boolean containsAABB(AABBfc aabb) { - return aabb.minX() >= minX && aabb.maxX() <= maxX && - aabb.minY() >= minY && aabb.maxY() <= maxY && - aabb.minZ() >= minZ && aabb.maxZ() <= maxZ; - } - - public boolean containsAABB(AABBic aabb) { - return aabb.minX() >= minX && aabb.maxX() <= maxX && - aabb.minY() >= minY && aabb.maxY() <= maxY && - aabb.minZ() >= minZ && aabb.maxZ() <= maxZ; - } - - public boolean containsPoint(double x, double y, double z) { - return x > minX && y > minY && z > minZ && x < maxX && y < maxY && z < maxZ; - } - - public boolean containsPoint(Vector3dc point) { - return containsPoint(point.x(), point.y(), point.z()); - } - - public boolean intersectsPlane(double a, double b, double c, double d) { - return Intersectiond.testAabPlane(minX, minY, minZ, maxX, maxY, maxZ, a, b, c, d); - } - - public boolean intersectsPlane(Planed plane) { - return Intersectiond.testAabPlane(this, plane); - } - - public boolean intersectsAABB(AABBd other) { - return this.maxX > other.minX && this.maxY > other.minY && this.maxZ > other.minZ && - this.minX < other.maxX && this.minY < other.maxY && this.minZ < other.maxZ; - } - - public boolean intersectsSphere(double centerX, double centerY, double centerZ, double radiusSquared) { - return Intersectiond.testAabSphere(minX, minY, minZ, maxX, maxY, maxZ, centerX, centerY, centerZ, radiusSquared); - } - - public boolean intersectsSphere(Spheref sphere) { - return Intersectiond.testAabSphere(this, sphere); - } - - public boolean intersectsRay(double originX, double originY, double originZ, double dirX, double dirY, double dirZ) { - return Intersectiond.testRayAab(originX, originY, originZ, dirX, dirY, dirZ, minX, minY, minZ, maxX, maxY, maxZ); - } - - public boolean intersectsRay(Rayd ray) { - return Intersectiond.testRayAab(ray, this); - } - - public boolean intersectsRay(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, Vector2d result) { - return Intersectiond.intersectRayAab(originX, originY, originZ, dirX, dirY, dirZ, minX, minY, minZ, maxX, maxY, maxZ, result); - } - - public boolean intersectsRay(Rayd ray, Vector2d result) { - return Intersectiond.intersectRayAab(ray, this, result); - } - - public int intersectsLineSegment(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z, Vector2d result) { - return Intersectiond.intersectLineSegmentAab(p0X, p0Y, p0Z, p1X, p1Y, p1Z, minX, minY, minZ, maxX, maxY, maxZ, result); - } - - public int intersectsLineSegment(LineSegmentf lineSegment, Vector2d result) { - return Intersectiond.intersectLineSegmentAab(lineSegment, this, result); - } - - /** - * Apply the given {@link Matrix4dc#isAffine() affine} transformation to this {@link AABBd}. - *

- * The matrix in m must be {@link Matrix4dc#isAffine() affine}. - * - * @param m - * the affine transformation matrix - * @return this - */ - public AABBd transform(Matrix4dc m) { - return transform(m, this); - } - - public AABBd transform(Matrix4dc m, AABBd dest) { - double dx = maxX - minX, dy = maxY - minY, dz = maxZ - minZ; - double minx = Double.POSITIVE_INFINITY, miny = Double.POSITIVE_INFINITY, minz = Double.POSITIVE_INFINITY; - double maxx = Double.NEGATIVE_INFINITY, maxy = Double.NEGATIVE_INFINITY, maxz = Double.NEGATIVE_INFINITY; - for (int i = 0; i < 8; i++) { - double x = minX + (i & 1) * dx, y = minY + (i >> 1 & 1) * dy, z = minZ + (i >> 2 & 1) * dz; - double tx = m.m00() * x + m.m10() * y + m.m20() * z + m.m30(); - double ty = m.m01() * x + m.m11() * y + m.m21() * z + m.m31(); - double tz = m.m02() * x + m.m12() * y + m.m22() * z + m.m32(); - minx = Math.min(tx, minx); - miny = Math.min(ty, miny); - minz = Math.min(tz, minz); - maxx = Math.max(tx, maxx); - maxy = Math.max(ty, maxy); - maxz = Math.max(tz, maxz); - } - dest.minX = minx; - dest.minY = miny; - dest.minZ = minz; - dest.maxX = maxx; - dest.maxY = maxy; - dest.maxZ = maxz; - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(maxX); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(maxY); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(maxZ); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(minX); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(minY); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(minZ); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - AABBd other = (AABBd) obj; - if (Double.doubleToLongBits(maxX) != Double.doubleToLongBits(other.maxX)) - return false; - if (Double.doubleToLongBits(maxY) != Double.doubleToLongBits(other.maxY)) - return false; - if (Double.doubleToLongBits(maxZ) != Double.doubleToLongBits(other.maxZ)) - return false; - if (Double.doubleToLongBits(minX) != Double.doubleToLongBits(other.minX)) - return false; - if (Double.doubleToLongBits(minY) != Double.doubleToLongBits(other.minY)) - return false; - if (Double.doubleToLongBits(minZ) != Double.doubleToLongBits(other.minZ)) - return false; - return true; - } - - /** - * Return a string representation of this AABB. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this AABB by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(minX, formatter) + " " + Runtime.format(minY, formatter) + " " + Runtime.format(minZ, formatter) + ") < " - + "(" + Runtime.format(maxX, formatter) + " " + Runtime.format(maxY, formatter) + " " + Runtime.format(maxZ, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeDouble(minX); - out.writeDouble(minY); - out.writeDouble(minZ); - out.writeDouble(maxX); - out.writeDouble(maxY); - out.writeDouble(maxZ); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - minX = in.readDouble(); - minY = in.readDouble(); - minZ = in.readDouble(); - maxX = in.readDouble(); - maxY = in.readDouble(); - maxZ = in.readDouble(); - } - -} diff --git a/src/org/joml/AABBdc.java b/src/org/joml/AABBdc.java deleted file mode 100644 index ac07cb442..000000000 --- a/src/org/joml/AABBdc.java +++ /dev/null @@ -1,489 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML - * - * 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 org.joml; - -/** - * Interface to a read-only view of axis-aligned box defined via the minimum - * and maximum corner coordinates as double-precision floats. - */ -public interface AABBdc { - - /** - * @return The x coordinate of the minimum corner. - */ - double minX(); - - /** - * @return The y coordinate of the minimum corner. - */ - double minY(); - - /** - * @return The z coordinate of the minimum corner. - */ - double minZ(); - - /** - * @return The x coordinate of the maximum corner. - */ - double maxX(); - - /** - * @return The y coordinate of the maximum corner. - */ - double maxY(); - - /** - * @return The z coordinate of the maximum corner. - */ - double maxZ(); - - /** - * Check whether this AABB represents a valid AABB. - * - * @return true iff this AABB is valid; false otherwise - */ - boolean isValid(); - - /** - * Get the maximum corner coordinate of the given component. - * - * @param component - * the component, within [0..2] - * @return the maximum coordinate - * @throws IllegalArgumentException if component is not within [0..2] - */ - double getMax(int component); - - /** - * Get the minimum corner coordinate of the given component. - * - * @param component - * the component, within [0..2] - * @return the maximum coordinate - * @throws IllegalArgumentException if component is not within [0..2] - */ - double getMin(int component); - - /** - * Return the center of the aabb - * - * @param dest will hold the result - * @return dest - */ - Vector3d center(Vector3d dest); - - /** - * Return the center of the aabb - * - * @param dest will hold the result - * @return dest - */ - Vector3f center(Vector3f dest); - - /** - * Extent of the aabb (max - min) / 2.0. - * - * @param dest will hold the result - * @return dest - */ - Vector3d extent(Vector3d dest); - - /** - * Extent of the aabb (max - min) / 2.0. - * - * @param dest will hold the result - * @return dest - */ - Vector3f extent(Vector3f dest); - - /** - * Compute the union of this and the given point (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @param dest - * will hold the result - * @return dest - */ - AABBd union(double x, double y, double z, AABBd dest); - - - /** - * Compute the union of this and the given point p and store the result in dest. - * - * @param p - * the point - * @param dest - * will hold the result - * @return dest - */ - AABBd union(Vector3dc p, AABBd dest); - - - /** - * Compute the union of this and other and store the result in dest. - * - * @param other - * the other {@link AABBd} - * @param dest - * will hold the result - * @return dest - */ - AABBd union(AABBdc other, AABBd dest); - - /** - * Translate this by the given vector xyz and store the result in dest. - * - * @param xyz - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - AABBd translate(Vector3dc xyz, AABBd dest); - - - /** - * Translate this by the given vector xyz and store the result in dest. - * - * @param xyz - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - AABBd translate(Vector3fc xyz, AABBd dest); - - /** - * Translate this by the vector (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param z - * the z coordinate to translate by - * @param dest - * will hold the result - * @return dest - */ - AABBd translate(double x, double y, double z, AABBd dest); - - - /** - * Compute the AABB of intersection between this and the given AABB. - *

- * If the two AABBs do not intersect, then the minimum coordinates of this - * will have a value of {@link Double#POSITIVE_INFINITY} and the maximum coordinates will have a value of - * {@link Double#NEGATIVE_INFINITY}. - * - * @param other - * the other AABB - * @param dest - * will hold the result - * @return dest - */ - AABBd intersection(AABBdc other, AABBd dest); - - - /** - * Check if this AABB contains the given AABB. - * - * @param aabb - * the AABB to test - * @return true iff this AABB contains the AABB; false otherwise - */ - boolean containsAABB(AABBdc aabb); - - /** - * Check if this AABB contains the given AABB. - * - * @param aabb - * the AABB to test - * @return true iff this AABB contains the AABB; false otherwise - */ - boolean containsAABB(AABBfc aabb); - - - /** - * Check if this AABB contains the given AABB. - * - * @param aabb - * the AABB to test - * @return true iff this AABB contains the AABB; false otherwise - */ - boolean containsAABB(AABBic aabb); - - - /** - * Test whether the point (x, y, z) lies inside this AABB. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @return true iff the given point lies inside this AABB; false otherwise - */ - boolean containsPoint(double x, double y, double z); - - - /** - * Test whether the given point lies inside this AABB. - * - * @param point - * the coordinates of the point - * @return true iff the given point lies inside this AABB; false otherwise - */ - boolean containsPoint(Vector3dc point); - - /** - * Test whether the plane given via its plane equation a*x + b*y + c*z + d = 0 intersects this AABB. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return true iff the plane intersects this AABB; false otherwise - */ - boolean intersectsPlane(double a, double b, double c, double d); - - - /** - * Test whether the given plane intersects this AABB. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param plane - * the plane - * @return true iff the plane intersects this AABB; false otherwise - */ - boolean intersectsPlane(Planed plane); - - - /** - * Test whether this and other intersect. - * - * @param other - * the other AABB - * @return true iff both AABBs intersect; false otherwise - */ - boolean intersectsAABB(AABBd other); - - /** - * Test whether this AABB intersects the given sphere with equation - * (x - centerX)^2 + (y - centerY)^2 + (z - centerZ)^2 - radiusSquared = 0. - *

- * Reference: http://stackoverflow.com - * - * @param centerX - * the x coordinate of the center of the sphere - * @param centerY - * the y coordinate of the center of the sphere - * @param centerZ - * the z coordinate of the center of the sphere - * @param radiusSquared - * the square radius of the sphere - * @return true iff this AABB and the sphere intersect; false otherwise - */ - boolean intersectsSphere(double centerX, double centerY, double centerZ, double radiusSquared) ; - - /** - * Test whether this AABB intersects the given sphere. - *

- * Reference: http://stackoverflow.com - * - * @param sphere - * the sphere - * @return true iff this AABB and the sphere intersect; false otherwise - */ - boolean intersectsSphere(Spheref sphere); - - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects this AABB. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @return true if this AABB and the ray intersect; false otherwise - */ - boolean intersectsRay(double originX, double originY, double originZ, double dirX, double dirY, double dirZ) ; - - - - /** - * Test whether the given ray intersects this AABB. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param ray - * the ray - * @return true if this AABB and the ray intersect; false otherwise - */ - boolean intersectsRay(Rayd ray); - /** - * Determine whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + t * dir of the near and far point of intersection. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects this AABB - * @return true if the given ray intersects this AABB; false otherwise - */ - boolean intersectsRay(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, Vector2d result); - - - /** - * Determine whether the given ray intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + t * dir of the near and far point of intersection. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param ray - * the ray - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects this AABB - * @return true if the given ray intersects this AABB; false otherwise - */ - boolean intersectsRay(Rayd ray, Vector2d result); - - /** - * Determine whether the undirected line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects this AABB - * @return {@link Intersectiond#INSIDE} if the line segment lies completely inside of this AABB; or - * {@link Intersectiond#OUTSIDE} if the line segment lies completely outside of this AABB; or - * {@link Intersectiond#ONE_INTERSECTION} if one of the end points of the line segment lies inside of this AABB; or - * {@link Intersectiond#TWO_INTERSECTION} if the line segment intersects two sides of this AABB or lies on an edge or a side of this AABB - */ - int intersectsLineSegment(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z, Vector2d result) ; - - /** - * Determine whether the given undirected line segment intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param lineSegment - * the line segment - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects this AABB - * @return {@link Intersectiond#INSIDE} if the line segment lies completely inside of this AABB; or - * {@link Intersectiond#OUTSIDE} if the line segment lies completely outside of this AABB; or - * {@link Intersectiond#ONE_INTERSECTION} if one of the end points of the line segment lies inside of this AABB; or - * {@link Intersectiond#TWO_INTERSECTION} if the line segment intersects two sides of this AABB or lies on an edge or a side of this AABB - */ - int intersectsLineSegment(LineSegmentf lineSegment, Vector2d result); - - /** - * Apply the given {@link Matrix4dc#isAffine() affine} transformation to this {@link AABBd} - * and store the resulting AABB into dest. - *

- * The matrix in m must be {@link Matrix4dc#isAffine() affine}. - * - * @param m - * the affine transformation matrix - * @param dest - * will hold the result - * @return dest - */ - AABBd transform(Matrix4dc m, AABBd dest); - -} diff --git a/src/org/joml/AABBf.java b/src/org/joml/AABBf.java deleted file mode 100644 index 8d37c36e7..000000000 --- a/src/org/joml/AABBf.java +++ /dev/null @@ -1,667 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents an axis-aligned box defined via the minimum and maximum corner coordinates as single-precision floats. - * - * @author Kai Burjack - */ -public class AABBf implements Externalizable, AABBfc { - - /** - * The x coordinate of the minimum corner. - */ - public float minX = Float.POSITIVE_INFINITY; - /** - * The y coordinate of the minimum corner. - */ - public float minY = Float.POSITIVE_INFINITY; - /** - * The z coordinate of the minimum corner. - */ - public float minZ = Float.POSITIVE_INFINITY; - /** - * The x coordinate of the maximum corner. - */ - public float maxX = Float.NEGATIVE_INFINITY; - /** - * The y coordinate of the maximum corner. - */ - public float maxY = Float.NEGATIVE_INFINITY; - /** - * The z coordinate of the maximum corner. - */ - public float maxZ = Float.NEGATIVE_INFINITY; - - /** - * Create a new {@link AABBf} representing the box with - * (minX, minY, minZ)=(+inf, +inf, +inf) and (maxX, maxY, maxZ)=(-inf, -inf, -inf). - */ - public AABBf() { - } - - /** - * Create a new {@link AABBf} as a copy of the given source. - * - * @param source - * the {@link AABBf} to copy from - */ - public AABBf(AABBf source) { - this.minX = source.minX; - this.minY = source.minY; - this.minZ = source.minZ; - this.maxX = source.maxX; - this.maxY = source.maxY; - this.maxZ = source.maxZ; - } - - /** - * Create a new {@link AABBf} with the given minimum and maximum corner coordinates. - * - * @param min - * the minimum coordinates - * @param max - * the maximum coordinates - */ - public AABBf(Vector3fc min, Vector3fc max) { - this.minX = min.x(); - this.minY = min.y(); - this.minZ = min.z(); - this.maxX = max.x(); - this.maxY = max.y(); - this.maxZ = max.z(); - } - - /** - * Create a new {@link AABBf} with the given minimum and maximum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @param minZ - * the z coordinate of the minimum corner - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - * @param maxZ - * the z coordinate of the maximum corner - */ - public AABBf(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - this.minX = minX; - this.minY = minY; - this.minZ = minZ; - this.maxX = maxX; - this.maxY = maxY; - this.maxZ = maxZ; - } - - /** - * Set this {@link AABBf} to be a clone of source. - * - * @param source - * the {@link AABBf} to copy from - * @return this - */ - public AABBf set(AABBfc source){ - this.minX = source.minX(); - this.minY = source.minY(); - this.minZ = source.minZ(); - this.maxX = source.maxX(); - this.maxY = source.maxY(); - this.maxZ = source.maxZ(); - return this; - } - - private AABBf validate() { - if (!isValid()) { - minX = Float.POSITIVE_INFINITY; - minY = Float.POSITIVE_INFINITY; - minZ = Float.POSITIVE_INFINITY; - - maxX = Float.NEGATIVE_INFINITY; - maxY = Float.NEGATIVE_INFINITY; - maxZ = Float.NEGATIVE_INFINITY; - } - return this; - } - - public float minX() { - return minX; - } - - public float minY() { - return minY; - } - - public float minZ() { - return minZ; - } - - public float maxX() { - return maxX; - } - - public float maxY() { - return maxY; - } - - public float maxZ() { - return maxZ; - } - - public boolean isValid() { - return minX < maxX && minY < maxY && minZ < maxZ; - } - - /** - * Set the minimum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @param minZ - * the z coordinate of the minimum corner - * @return this - */ - public AABBf setMin(float minX, float minY, float minZ) { - this.minX = minX; - this.minY = minY; - this.minZ = minZ; - return this; - } - - /** - * Set the maximum corner coordinates. - * - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - * @param maxZ - * the z coordinate of the maximum corner - * @return this - */ - public AABBf setMax(float maxX, float maxY, float maxZ) { - this.maxX = maxX; - this.maxY = maxY; - this.maxZ = maxZ; - return this; - } - - /** - * Set the minimum corner coordinates. - * - * @param min - * the minimum coordinates - * @return this - */ - public AABBf setMin(Vector3fc min) { - return this.setMin(min.x(), min.y(), min.z()); - } - - /** - * Set the maximum corner coordinates. - * - * @param max - * the maximum coordinates - * @return this - */ - public AABBf setMax(Vector3fc max) { - return this.setMax(max.x(), max.y(), max.z()); - } - - public float getMax(int component) throws IllegalArgumentException { - switch (component) { - case 0: - return maxX; - case 1: - return maxY; - case 2: - return maxZ; - default: - throw new IllegalArgumentException(); - } - } - - public float getMin(int component) throws IllegalArgumentException { - switch (component) { - case 0: - return minX; - case 1: - return minY; - case 2: - return minZ; - default: - throw new IllegalArgumentException(); - } - } - - public Vector3f center(Vector3f dest) { - return dest.set(minX + ((maxX - minX) / 2.0f), minY + ((maxY - minY) / 2.0f), minZ + ((maxZ - minZ) / 2.0f)); - } - - public Vector3d center(Vector3d dest) { - return dest.set(minX + ((maxX - minX) / 2.0), minY + ((maxY - minY) / 2.0), minZ + ((maxZ - minZ) / 2.0)); - } - - public Vector3d extent(Vector3d dest) { - return dest.set((maxX - minX) / 2.0, (maxY - minY) / 2.0, (maxZ - minZ) / 2.0); - } - - public Vector3f extent(Vector3f dest) { - return dest.set((maxX - minX) / 2.0f, (maxY - minY) / 2.0f, (maxZ - minZ) / 2.0f); - } - - /** - * Return the length along the x component - * - * @return length in the x dimension - */ - public float lengthX(){ - return maxX - minX; - } - - /** - * Return the length along the y component - * - * @return length in the y dimension - */ - public float lengthY(){ - return maxY - minY; - } - - /** - * Return the length along the z component - * - * @return length in the z dimension - */ - public float lengthZ(){ - return maxZ - minZ; - } - - /** - * Get the size of the aabb. - * - * @param dest - * will hold the result - * @return dest - */ - public Vector3f getSize(Vector3f dest) { - return dest.set(lengthX(), lengthY(), lengthZ()); - } - - /** - * Get the size of the aabb. - * - * @param dest - * will hold the result - * @return dest - */ - public Vector3d getSize(Vector3d dest) { - return dest.set(lengthX(), lengthY(), lengthZ()); - } - - /** - * Set this to the union of this and the given point (x, y, z). - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @return this - */ - public AABBf union(float x, float y, float z) { - return union(x, y, z, this); - } - - /** - * Set this to the union of this and the given point p. - * - * @param p - * the point - * @return this - */ - public AABBf union(Vector3fc p) { - return union(p.x(), p.y(), p.z(), this); - } - - public AABBf union(float x, float y, float z, AABBf dest) { - dest.minX = this.minX < x ? this.minX : x; - dest.minY = this.minY < y ? this.minY : y; - dest.minZ = this.minZ < z ? this.minZ : z; - dest.maxX = this.maxX > x ? this.maxX : x; - dest.maxY = this.maxY > y ? this.maxY : y; - dest.maxZ = this.maxZ > z ? this.maxZ : z; - return dest; - } - - public AABBf union(Vector3fc p, AABBf dest) { - return union(p.x(), p.y(), p.z(), dest); - } - - /** - * Set this to the union of this and other. - * - * @param other - * the other {@link AABBf} - * @return this - */ - public AABBf union(AABBf other) { - return this.union(other, this); - } - - public AABBf union(AABBf other, AABBf dest) { - dest.minX = this.minX < other.minX ? this.minX : other.minX; - dest.minY = this.minY < other.minY ? this.minY : other.minY; - dest.minZ = this.minZ < other.minZ ? this.minZ : other.minZ; - dest.maxX = this.maxX > other.maxX ? this.maxX : other.maxX; - dest.maxY = this.maxY > other.maxY ? this.maxY : other.maxY; - dest.maxZ = this.maxZ > other.maxZ ? this.maxZ : other.maxZ; - return dest; - } - - /** - * Ensure that the minimum coordinates are strictly less than or equal to the maximum coordinates by swapping - * them if necessary. - * - * @return this - */ - public AABBf correctBounds() { - float tmp; - if (this.minX > this.maxX) { - tmp = this.minX; - this.minX = this.maxX; - this.maxX = tmp; - } - if (this.minY > this.maxY) { - tmp = this.minY; - this.minY = this.maxY; - this.maxY = tmp; - } - if (this.minZ > this.maxZ) { - tmp = this.minZ; - this.minZ = this.maxZ; - this.maxZ = tmp; - } - return this; - } - - /** - * Translate this by the given vector xyz. - * - * @param xyz - * the vector to translate by - * @return this - */ - public AABBf translate(Vector3fc xyz) { - return translate(xyz.x(), xyz.y(), xyz.z(), this); - } - - public AABBf translate(Vector3fc xyz, AABBf dest) { - return translate(xyz.x(), xyz.y(), xyz.z(), dest); - } - - /** - * Translate this by the vector (x, y, z). - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param z - * the z coordinate to translate by - * @return this - */ - public AABBf translate(float x, float y, float z) { - return translate(x, y, z, this); - } - - public AABBf translate(float x, float y, float z, AABBf dest) { - dest.minX = minX + x; - dest.minY = minY + y; - dest.minZ = minZ + z; - dest.maxX = maxX + x; - dest.maxY = maxY + y; - dest.maxZ = maxZ + z; - return dest; - } - - public AABBf intersection(AABBfc other, AABBf dest) { - dest.minX = Math.max(minX, other.minX()); - dest.minY = Math.max(minY, other.minY()); - dest.minZ = Math.max(minZ, other.minZ()); - - dest.maxX = Math.min(maxX, other.maxX()); - dest.maxY = Math.min(maxY, other.maxY()); - dest.maxZ = Math.min(maxZ, other.maxZ()); - return dest.validate(); - } - - /** - * Compute the AABB of intersection between this and the given AABB. - *

- * If the two AABBs do not intersect, then the minimum coordinates of this - * will have a value of {@link Float#POSITIVE_INFINITY} and the maximum coordinates will have a value of - * {@link Float#NEGATIVE_INFINITY}. - * - * @param other - * the other AABB - * @return this - */ - public AABBf intersection(AABBfc other) { - return intersection(other, this); - } - - public boolean containsAABB(AABBdc aabb) { - return aabb.minX() >= minX && aabb.maxX() <= maxX && - aabb.minY() >= minY && aabb.maxY() <= maxY && - aabb.minZ() >= minZ && aabb.maxZ() <= maxZ; - } - - public boolean containsAABB(AABBfc aabb) { - return aabb.minX() >= minX && aabb.maxX() <= maxX && - aabb.minY() >= minY && aabb.maxY() <= maxY && - aabb.minZ() >= minZ && aabb.maxZ() <= maxZ; - } - - public boolean containsAABB(AABBic aabb) { - return aabb.minX() >= minX && aabb.maxX() <= maxX && - aabb.minY() >= minY && aabb.maxY() <= maxY && - aabb.minZ() >= minZ && aabb.maxZ() <= maxZ; - } - - public boolean containsPoint(float x, float y, float z) { - return x > minX && y > minY && z > minZ && x < maxX && y < maxY && z < maxZ; - } - - public boolean containsPoint(Vector3fc point) { - return containsPoint(point.x(), point.y(), point.z()); - } - - public boolean intersectsPlane(float a, float b, float c, float d) { - return Intersectionf.testAabPlane(minX, minY, minZ, maxX, maxY, maxZ, a, b, c, d); - } - - public boolean intersectsPlane(Planef plane) { - return Intersectionf.testAabPlane(this, plane); - } - - public boolean intersectsAABB(AABBfc other) { - return this.maxX >= other.minX() && this.maxY >= other.minY() && this.maxZ >= other.minZ() && - this.minX <= other.maxX() && this.minY <= other.maxY() && this.minZ <= other.maxZ(); - } - - public boolean intersectsSphere(float centerX, float centerY, float centerZ, float radiusSquared) { - return Intersectionf.testAabSphere(minX, minY, minZ, maxX, maxY, maxZ, centerX, centerY, centerZ, radiusSquared); - } - - public boolean intersectsSphere(Spheref sphere) { - return Intersectionf.testAabSphere(this, sphere); - } - - public boolean intersectsRay(float originX, float originY, float originZ, float dirX, float dirY, float dirZ) { - return Intersectionf.testRayAab(originX, originY, originZ, dirX, dirY, dirZ, minX, minY, minZ, maxX, maxY, maxZ); - } - - public boolean intersectsRay(Rayf ray) { - return Intersectionf.testRayAab(ray, this); - } - - public boolean intersectsRay(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, Vector2f result) { - return Intersectionf.intersectRayAab(originX, originY, originZ, dirX, dirY, dirZ, minX, minY, minZ, maxX, maxY, maxZ, result); - } - - public boolean intersectsRay(Rayf ray, Vector2f result) { - return Intersectionf.intersectRayAab(ray, this, result); - } - - public int intersectsLineSegment(float p0X, float p0Y, float p0Z, float p1X, float p1Y, float p1Z, Vector2f result) { - return Intersectionf.intersectLineSegmentAab(p0X, p0Y, p0Z, p1X, p1Y, p1Z, minX, minY, minZ, maxX, maxY, maxZ, result); - } - - public int intersectsLineSegment(LineSegmentf lineSegment, Vector2f result) { - return Intersectionf.intersectLineSegmentAab(lineSegment, this, result); - } - - /** - * Apply the given {@link Matrix4fc#isAffine() affine} transformation to this {@link AABBf}. - *

- * The matrix in m must be {@link Matrix4fc#isAffine() affine}. - * - * @param m - * the affine transformation matrix - * @return this - */ - public AABBf transform(Matrix4fc m) { - return transform(m, this); - } - - public AABBf transform(Matrix4fc m, AABBf dest) { - float dx = maxX - minX, dy = maxY - minY, dz = maxZ - minZ; - float minx = Float.POSITIVE_INFINITY, miny = Float.POSITIVE_INFINITY, minz = Float.POSITIVE_INFINITY; - float maxx = Float.NEGATIVE_INFINITY, maxy = Float.NEGATIVE_INFINITY, maxz = Float.NEGATIVE_INFINITY; - for (int i = 0; i < 8; i++) { - float x = minX + (i & 1) * dx, y = minY + (i >> 1 & 1) * dy, z = minZ + (i >> 2 & 1) * dz; - float tx = m.m00() * x + m.m10() * y + m.m20() * z + m.m30(); - float ty = m.m01() * x + m.m11() * y + m.m21() * z + m.m31(); - float tz = m.m02() * x + m.m12() * y + m.m22() * z + m.m32(); - minx = Math.min(tx, minx); - miny = Math.min(ty, miny); - minz = Math.min(tz, minz); - maxx = Math.max(tx, maxx); - maxy = Math.max(ty, maxy); - maxz = Math.max(tz, maxz); - } - dest.minX = minx; - dest.minY = miny; - dest.minZ = minz; - dest.maxX = maxx; - dest.maxY = maxy; - dest.maxZ = maxz; - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(maxX); - result = prime * result + Float.floatToIntBits(maxY); - result = prime * result + Float.floatToIntBits(maxZ); - result = prime * result + Float.floatToIntBits(minX); - result = prime * result + Float.floatToIntBits(minY); - result = prime * result + Float.floatToIntBits(minZ); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - AABBf other = (AABBf) obj; - if (Float.floatToIntBits(maxX) != Float.floatToIntBits(other.maxX)) - return false; - if (Float.floatToIntBits(maxY) != Float.floatToIntBits(other.maxY)) - return false; - if (Float.floatToIntBits(maxZ) != Float.floatToIntBits(other.maxZ)) - return false; - if (Float.floatToIntBits(minX) != Float.floatToIntBits(other.minX)) - return false; - if (Float.floatToIntBits(minY) != Float.floatToIntBits(other.minY)) - return false; - if (Float.floatToIntBits(minZ) != Float.floatToIntBits(other.minZ)) - return false; - return true; - } - - /** - * Return a string representation of this AABB. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(minX, formatter) + " " + Runtime.format(minY, formatter) + " " + Runtime.format(minZ, formatter) + ") < " - + "(" + Runtime.format(maxX, formatter) + " " + Runtime.format(maxY, formatter) + " " + Runtime.format(maxZ, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(minX); - out.writeFloat(minY); - out.writeFloat(minZ); - out.writeFloat(maxX); - out.writeFloat(maxY); - out.writeFloat(maxZ); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - minX = in.readFloat(); - minY = in.readFloat(); - minZ = in.readFloat(); - maxX = in.readFloat(); - maxY = in.readFloat(); - maxZ = in.readFloat(); - } - -} diff --git a/src/org/joml/AABBfc.java b/src/org/joml/AABBfc.java deleted file mode 100644 index ebfb9ab1d..000000000 --- a/src/org/joml/AABBfc.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML - * - * 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 org.joml; - -import java.text.NumberFormat; - -/** - * Interface to a read-only view of an axis-aligned box defined via the minimum - * and maximum corner coordinates as single-precision floats. - */ -public interface AABBfc { - - /** - * @return The x coordinate of the minimum corner. - */ - float minX(); - - /** - * @return The y coordinate of the minimum corner. - */ - float minY(); - - /** - * @return The z coordinate of the minimum corner. - */ - float minZ(); - - /** - * @return The x coordinate of the maximum corner. - */ - float maxX(); - - /** - * @return The y coordinate of the maximum corner. - */ - float maxY(); - - /** - * @return The z coordinate of the maximum corner. - */ - float maxZ(); - - /** - * Check whether this rectangle represents a valid AABB. - * - * @return true iff this rectangle is valid; false otherwise - */ - boolean isValid(); - - /** - * Get the maximum corner coordinate of the given component. - * - * @param component - * the component, within [0..2] - * @return the maximum coordinate - * @throws IllegalArgumentException if component is not within [0..2] - */ - float getMax(int component); - - /** - * Get the minimum corner coordinate of the given component. - * - * @param component - * the component, within [0..2] - * @return the maximum coordinate - * @throws IllegalArgumentException if component is not within [0..2] - */ - float getMin(int component); - - /** - * Return the center of the aabb - * - * @param dest will hold the result - * @return dest - */ - Vector3f center(Vector3f dest); - - /** - * Return the center of the aabb - * - * @param dest will hold the result - * @return dest - */ - Vector3d center(Vector3d dest); - - /** - * Extent of the aabb (max - min) / 2.0. - * - * @param dest will hold the result - * @return dest - */ - Vector3d extent(Vector3d dest); - - /** - * Extent of the aabb (max - min) / 2.0. - * - * @param dest will hold the result - * @return dest - */ - Vector3f extent(Vector3f dest); - - /** - * Compute the union of this and the given point (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @param dest - * will hold the result - * @return dest - */ - AABBf union(float x, float y, float z, AABBf dest); - - /** - * Compute the union of this and the given point p and store the result in dest. - * - * @param p - * the point - * @param dest - * will hold the result - * @return dest - */ - AABBf union(Vector3fc p, AABBf dest); - - /** - * Compute the union of this and other and store the result in dest. - * - * @param other - * the other {@link AABBf} - * @param dest - * will hold the result - * @return dest - */ - AABBf union(AABBf other, AABBf dest); - - /** - * Translate this by the given vector xyz and store the result in dest. - * - * @param xyz - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - AABBf translate(Vector3fc xyz, AABBf dest); - - /** - * Translate this by the vector (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param z - * the z coordinate to translate by - * @param dest - * will hold the result - * @return dest - */ - AABBf translate(float x, float y, float z, AABBf dest); - - /** - * Compute the AABB of intersection between this and the given AABB. - *

- * If the two AABBs do not intersect, then the minimum coordinates of this - * will have a value of {@link Float#POSITIVE_INFINITY} and the maximum coordinates will have a value of - * {@link Float#NEGATIVE_INFINITY}. - * - * @param other - * the other AABB - * @param dest - * will hold the result - * @return dest - */ - AABBf intersection(AABBfc other, AABBf dest); - - /** - * Check if this AABB contains the given AABB. - * - * @param aabb - * the AABB to test - * @return true iff this AABB contains the AABB; false otherwise - */ - boolean containsAABB(AABBdc aabb); - - /** - * Check if this AABB contains the given AABB. - * - * @param aabb - * the AABB to test - * @return true iff this AABB contains the AABB; false otherwise - */ - boolean containsAABB(AABBfc aabb); - - /** - * Check if this AABB contains the given AABB. - * - * @param aabb - * the AABB to test - * @return true iff this AABB contains the AABB; false otherwise - */ - boolean containsAABB(AABBic aabb); - - /** - * Test whether the point (x, y, z) lies inside this AABB. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @return true iff the given point lies inside this AABB; false otherwise - */ - boolean containsPoint(float x, float y, float z); - - /** - * Test whether the given point lies inside this AABB. - * - * @param point - * the coordinates of the point - * @return true iff the given point lies inside this AABB; false otherwise - */ - boolean containsPoint(Vector3fc point); - - /** - * Test whether the plane given via its plane equation a*x + b*y + c*z + d = 0 intersects this AABB. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return true iff the plane intersects this AABB; false otherwise - */ - boolean intersectsPlane(float a, float b, float c, float d); - - /** - * Test whether the given plane intersects this AABB. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param plane - * the plane - * @return true iff the plane intersects this AABB; false otherwise - */ - boolean intersectsPlane(Planef plane); - - /** - * Test whether this and other intersect. - * - * @param other - * the other AABB - * @return true iff both AABBs intersect; false otherwise - */ - boolean intersectsAABB(AABBfc other); - - /** - * Test whether this AABB intersects the given sphere with equation - * (x - centerX)^2 + (y - centerY)^2 + (z - centerZ)^2 - radiusSquared = 0. - *

- * Reference: http://stackoverflow.com - * - * @param centerX - * the x coordinate of the center of the sphere - * @param centerY - * the y coordinate of the center of the sphere - * @param centerZ - * the z coordinate of the center of the sphere - * @param radiusSquared - * the square radius of the sphere - * @return true iff this AABB and the sphere intersect; false otherwise - */ - boolean intersectsSphere(float centerX, float centerY, float centerZ, float radiusSquared); - - /** - * Test whether this AABB intersects the given sphere. - *

- * Reference: http://stackoverflow.com - * - * @param sphere - * the sphere - * @return true iff this AABB and the sphere intersect; false otherwise - */ - boolean intersectsSphere(Spheref sphere); - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects this AABB. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @return true if this AABB and the ray intersect; false otherwise - */ - boolean intersectsRay(float originX, float originY, float originZ, float dirX, float dirY, float dirZ); - - /** - * Test whether the given ray intersects this AABB. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param ray - * the ray - * @return true if this AABB and the ray intersect; false otherwise - */ - boolean intersectsRay(Rayf ray); - - - - /** - * Determine whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + t * dir of the near and far point of intersection. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects this AABB - * @return true if the given ray intersects this AABB; false otherwise - */ - boolean intersectsRay(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, Vector2f result); - - - /** - * Determine whether the given ray intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + t * dir of the near and far point of intersection. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param ray - * the ray - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects this AABB - * @return true if the given ray intersects this AABB; false otherwise - */ - boolean intersectsRay(Rayf ray, Vector2f result); - - /** - * Determine whether the undirected line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects this AABB - * @return {@link Intersectionf#INSIDE} if the line segment lies completely inside of this AABB; or - * {@link Intersectionf#OUTSIDE} if the line segment lies completely outside of this AABB; or - * {@link Intersectionf#ONE_INTERSECTION} if one of the end points of the line segment lies inside of this AABB; or - * {@link Intersectionf#TWO_INTERSECTION} if the line segment intersects two sides of this AABB or lies on an edge or a side of this AABB - */ - int intersectsLineSegment(float p0X, float p0Y, float p0Z, float p1X, float p1Y, float p1Z, Vector2f result); - - /** - * Determine whether the given undirected line segment intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param lineSegment - * the line segment - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects this AABB - * @return {@link Intersectionf#INSIDE} if the line segment lies completely inside of this AABB; or - * {@link Intersectionf#OUTSIDE} if the line segment lies completely outside of this AABB; or - * {@link Intersectionf#ONE_INTERSECTION} if one of the end points of the line segment lies inside of this AABB; or - * {@link Intersectionf#TWO_INTERSECTION} if the line segment intersects two sides of this AABB or lies on an edge or a side of this AABB - */ - int intersectsLineSegment(LineSegmentf lineSegment, Vector2f result); - - /** - * Apply the given {@link Matrix4fc#isAffine() affine} transformation to this - * {@link AABBf} and store the resulting AABB into dest. - *

- * The matrix in m must be {@link Matrix4fc#isAffine() affine}. - * - * @param m - * the affine transformation matrix - * @param dest - * will hold the result - * @return dest - */ - AABBf transform(Matrix4fc m, AABBf dest); - - /** - * Return a string representation of this AABB by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - String toString(NumberFormat formatter); -} diff --git a/src/org/joml/AABBi.java b/src/org/joml/AABBi.java deleted file mode 100644 index f3426d276..000000000 --- a/src/org/joml/AABBi.java +++ /dev/null @@ -1,680 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML. - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; - -/** - * Represents an axis-aligned box defined via the minimum and maximum corner coordinates as ints. - * - * @author Kai Burjack - */ -public class AABBi implements Externalizable, AABBic { - - /** - * The x coordinate of the minimum corner. - */ - public int minX = Integer.MAX_VALUE; - /** - * The y coordinate of the minimum corner. - */ - public int minY = Integer.MAX_VALUE; - /** - * The z coordinate of the minimum corner. - */ - public int minZ = Integer.MAX_VALUE; - /** - * The x coordinate of the maximum corner. - */ - public int maxX = Integer.MIN_VALUE; - /** - * The y coordinate of the maximum corner. - */ - public int maxY = Integer.MIN_VALUE; - /** - * The z coordinate of the maximum corner. - */ - public int maxZ = Integer.MIN_VALUE; - - - /** - * Create a new {@link AABBi} representing the box with - * (minX, minY, minZ)=(+inf, +inf, +inf) and (maxX, maxY, maxZ)=(-inf, -inf, -inf). - */ - public AABBi() { - } - - /** - * Create a new {@link AABBi} as a copy of the given source. - * - * @param source - * the {@link AABBi} to copy from - */ - public AABBi(AABBic source) { - this.minX = source.minX(); - this.minY = source.minY(); - this.minZ = source.minZ(); - this.maxX = source.maxX(); - this.maxY = source.maxY(); - this.maxZ = source.maxZ(); - } - - /** - * Create a new {@link AABBi} with the given minimum and maximum corner coordinates. - * - * @param min - * the minimum coordinates - * @param max - * the maximum coordinates - */ - public AABBi(Vector3ic min, Vector3ic max) { - this.minX = min.x(); - this.minY = min.y(); - this.minZ = min.z(); - this.maxX = max.x(); - this.maxY = max.y(); - this.maxZ = max.z(); - } - - /** - * Create a new {@link AABBi} with the given minimum and maximum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @param minZ - * the z coordinate of the minimum corner - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - * @param maxZ - * the z coordinate of the maximum corner - */ - public AABBi(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { - this.minX = minX; - this.minY = minY; - this.minZ = minZ; - this.maxX = maxX; - this.maxY = maxY; - this.maxZ = maxZ; - } - - public int minX() { - return minX; - } - - public int minY() { - return minY; - } - - public int minZ() { - return minZ; - } - - public int maxX() { - return maxX; - } - - public int maxY() { - return maxY; - } - - public int maxZ() { - return maxZ; - } - - - /** - * Set the minimum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @param minZ - * the z coordinate of the minimum corner - * @return this - */ - public AABBi setMin(int minX, int minY, int minZ) { - this.minX = minX; - this.minY = minY; - this.minZ = minZ; - return this; - } - - /** - * Set the maximum corner coordinates. - * - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - * @param maxZ - * the z coordinate of the maximum corner - * @return this - */ - public AABBi setMax(int maxX, int maxY, int maxZ) { - this.maxX = maxX; - this.maxY = maxY; - this.maxZ = maxZ; - return this; - } - - /** - * Set this {@link AABBi} to be a clone of source. - * - * @param source - * the {@link AABBi} to copy from - * @return this - */ - public AABBi set(AABBic source){ - this.minX = source.minX(); - this.minY = source.minY(); - this.minZ = source.minZ(); - this.maxX = source.maxX(); - this.maxY = source.maxY(); - this.maxZ = source.maxZ(); - return this; - } - - private AABBi validate() { - if (!isValid()) { - minX = Integer.MAX_VALUE; - minY = Integer.MAX_VALUE; - minZ = Integer.MAX_VALUE; - - maxX = Integer.MIN_VALUE; - maxY = Integer.MIN_VALUE; - maxZ = Integer.MIN_VALUE; - } - return this; - } - - public boolean isValid() { - return minX < maxX && minY < maxY && minZ < maxZ; - } - - /** - * Set the minimum corner coordinates. - * - * @param min - * the minimum coordinates - * @return this - */ - public AABBi setMin(Vector3ic min) { - return this.setMin(min.x(), min.y(), min.z()); - } - - /** - * Set the maximum corner coordinates. - * - * @param max - * the maximum coordinates - * @return this - */ - public AABBi setMax(Vector3ic max) { - return this.setMax(max.x(), max.y(), max.z()); - } - - public int getMax(int component) throws IllegalArgumentException { - switch (component) { - case 0: - return maxX; - case 1: - return maxY; - case 2: - return maxZ; - default: - throw new IllegalArgumentException(); - } - } - - public int getMin(int component) throws IllegalArgumentException { - switch (component) { - case 0: - return minX; - case 1: - return minY; - case 2: - return minZ; - default: - throw new IllegalArgumentException(); - } - } - - public Vector3f center(Vector3f dest) { - return dest.set(minX + ((maxX - minX) / 2.0f), minY + ((maxY - minY) / 2.0f), minZ + ((maxZ - minZ) / 2.0f)); - } - - public Vector3d center(Vector3d dest) { - return dest.set(minX + ((maxX - minX) / 2.0), minY + ((maxY - minY) / 2.0), minZ + ((maxZ - minZ) / 2.0)); - } - - public Vector3d extent(Vector3d dest) { - return dest.set((maxX - minX) / 2.0, (maxY - minY) / 2.0, (maxZ - minZ) / 2.0); - } - - public Vector3f extent(Vector3f dest) { - return dest.set((maxX - minX) / 2.0f, (maxY - minY) / 2.0f, (maxZ - minZ) / 2.0f); - } - - /** - * Return the length along the x component - * - * @return length in the x dimension - */ - public int lengthX(){ - return maxX - minX; - } - - /** - * Return the length along the y component - * - * @return length in the y dimension - */ - public int lengthY(){ - return maxY - minY; - } - - /** - * Return the length along the z component. - * - * @return length in the z dimension - */ - public int lengthZ(){ - return maxZ - minZ; - } - - /** - * Get the size of the aabb. - * - * @param dest - * will hold the result - * @return dest - */ - public Vector3i getSize(Vector3i dest) { - return dest.set(maxX - minX, maxY - minY, maxZ - minZ); - } - - /** - * Get the size of the aabb. - * - * @param dest - * will hold the result - * @return dest - */ - public Vector3f getSize(Vector3f dest) { - return dest.set(maxX - minX, maxY - minY, maxZ - minZ); - } - - /** - * Get the size of the aabb. - * - * @param dest - * will hold the result - * @return dest - */ - public Vector3d getSize(Vector3d dest) { - return dest.set(maxX - minX, maxY - minY, maxZ - minZ); - } - - - /** - * Set this to the union of this and the given point (x, y, z). - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @return this - */ - public AABBi union(int x, int y, int z) { - return union(x, y, z, this); - } - - /** - * Set this to the union of this and the given point p. - * - * @param p - * the point - * @return this - */ - public AABBi union(Vector3ic p) { - return union(p.x(), p.y(), p.z(), this); - } - - public AABBi union(int x, int y, int z, AABBi dest) { - dest.minX = this.minX < x ? this.minX : x; - dest.minY = this.minY < y ? this.minY : y; - dest.minZ = this.minZ < z ? this.minZ : z; - dest.maxX = this.maxX > x ? this.maxX : x; - dest.maxY = this.maxY > y ? this.maxY : y; - dest.maxZ = this.maxZ > z ? this.maxZ : z; - return dest; - } - - public AABBi union(Vector3ic p, AABBi dest) { - return union(p.x(), p.y(), p.z(), dest); - } - - /** - * Set this to the union of this and other. - * - * @param other - * the other {@link AABBi} - * @return this - */ - public AABBi union(AABBic other) { - return this.union(other, this); - } - - public AABBi union(AABBic other, AABBi dest) { - dest.minX = this.minX < other.minX() ? this.minX : other.minX(); - dest.minY = this.minY < other.minY() ? this.minY : other.minY(); - dest.minZ = this.minZ < other.minZ() ? this.minZ : other.minZ(); - dest.maxX = this.maxX > other.maxX() ? this.maxX : other.maxX(); - dest.maxY = this.maxY > other.maxY() ? this.maxY : other.maxY(); - dest.maxZ = this.maxZ > other.maxZ() ? this.maxZ : other.maxZ(); - return dest; - } - - /** - * Ensure that the minimum coordinates are strictly less than or equal to the maximum coordinates by swapping - * them if necessary. - * - * @return this - */ - public AABBi correctBounds() { - int tmp; - if (this.minX > this.maxX) { - tmp = this.minX; - this.minX = this.maxX; - this.maxX = tmp; - } - if (this.minY > this.maxY) { - tmp = this.minY; - this.minY = this.maxY; - this.maxY = tmp; - } - if (this.minZ > this.maxZ) { - tmp = this.minZ; - this.minZ = this.maxZ; - this.maxZ = tmp; - } - return this; - } - - /** - * Translate this by the given vector xyz. - * - * @param xyz - * the vector to translate by - * @return this - */ - public AABBi translate(Vector3ic xyz) { - return translate(xyz.x(), xyz.y(), xyz.z(), this); - } - - /** - * Translate this by the given vector xyz and store the result in dest. - * - * @param xyz - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public AABBi translate(Vector3ic xyz, AABBi dest) { - return translate(xyz.x(), xyz.y(), xyz.z(), dest); - } - - /** - * Translate this by the vector (x, y, z). - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param z - * the z coordinate to translate by - * @return this - */ - public AABBi translate(int x, int y, int z) { - return translate(x, y, z, this); - } - - public AABBi translate(int x, int y, int z, AABBi dest) { - dest.minX = minX + x; - dest.minY = minY + y; - dest.minZ = minZ + z; - dest.maxX = maxX + x; - dest.maxY = maxY + y; - dest.maxZ = maxZ + z; - return dest; - } - - public AABBi intersection(AABBic other, AABBi dest) { - dest.minX = Math.max(minX, other.minX()); - dest.minY = Math.max(minY, other.minY()); - dest.minZ = Math.max(minZ, other.minZ()); - - dest.maxX = Math.min(maxX, other.maxX()); - dest.maxY = Math.min(maxY, other.maxY()); - dest.maxZ = Math.min(maxZ, other.maxZ()); - return dest.validate(); - } - - - /** - * Compute the AABB of intersection between this and the given AABB. - *

- * If the two AABBs do not intersect, then the minimum coordinates of this - * will have a value of {@link Integer#MAX_VALUE} and the maximum coordinates will have a value of - * {@link Integer#MIN_VALUE}. - * - * @param other - * the other AABB - * @return this - */ - public AABBi intersection(AABBic other) { - return intersection(other, this); - } - - public boolean containsAABB(AABBdc aabb) { - return aabb.minX() >= minX && aabb.maxX() <= maxX && - aabb.minY() >= minY && aabb.maxY() <= maxY && - aabb.minZ() >= minZ && aabb.maxZ() <= maxZ; - } - - public boolean containsAABB(AABBfc aabb) { - return aabb.minX() >= minX && aabb.maxX() <= maxX && - aabb.minY() >= minY && aabb.maxY() <= maxY && - aabb.minZ() >= minZ && aabb.maxZ() <= maxZ; - } - - public boolean containsAABB(AABBic aabb) { - return aabb.minX() >= minX && aabb.maxX() <= maxX && - aabb.minY() >= minY && aabb.maxY() <= maxY && - aabb.minZ() >= minZ && aabb.maxZ() <= maxZ; - } - - public boolean containsPoint(int x, int y, int z){ - return x > minX && y > minY && z > minZ && x < maxX && y < maxY && z < maxZ; - } - - public boolean containsPoint(float x, float y, float z){ - return x > minX && y > minY && z > minZ && x < maxX && y < maxY && z < maxZ; - } - - public boolean containsPoint(Vector3ic point) { - return containsPoint(point.x(), point.y(), point.z()); - } - - public boolean containsPoint(Vector3fc point) { - return containsPoint(point.x(), point.y(), point.z()); - } - - public boolean intersectsPlane(float a, float b, float c, float d) { - return Intersectionf.testAabPlane(minX, minY, minZ, maxX, maxY, maxZ, a, b, c, d); - } - - public boolean intersectsPlane(Planef plane) { - return Intersectionf.testAabPlane(this, plane); - } - - public boolean intersectsAABB(AABBic other) { - return this.maxX >= other.minX() && this.maxY >= other.minY() && this.maxZ >= other.minZ() && - this.minX <= other.maxX() && this.minY <= other.maxY() && this.minZ <= other.maxZ(); - } - - public boolean intersectsAABB(AABBfc other) { - return this.maxX >= other.minX() && this.maxY >= other.minY() && this.maxZ >= other.minZ() && - this.minX <= other.maxX() && this.minY <= other.maxY() && this.minZ <= other.maxZ(); - } - - public boolean intersectsSphere(float centerX, float centerY, float centerZ, float radiusSquared) { - return Intersectionf.testAabSphere(minX, minY, minZ, maxX, maxY, maxZ, centerX, centerY, centerZ, radiusSquared); - } - - public boolean intersectsSphere(Spheref sphere) { - return Intersectionf.testAabSphere(this, sphere); - } - - public boolean intersectsRay(float originX, float originY, float originZ, float dirX, float dirY, float dirZ) { - return Intersectionf.testRayAab(originX, originY, originZ, dirX, dirY, dirZ, minX, minY, minZ, maxX, maxY, maxZ); - } - - public boolean intersectsRay(Rayf ray) { - return Intersectionf.testRayAab(ray, this); - } - - public boolean intersectsRay(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, Vector2f result) { - return Intersectionf.intersectRayAab(originX, originY, originZ, dirX, dirY, dirZ, minX, minY, minZ, maxX, maxY, maxZ, result); - } - - public boolean intersectsRay(Rayf ray, Vector2f result) { - return Intersectionf.intersectRayAab(ray, this, result); - } - - public int intersectLineSegment(float p0X, float p0Y, float p0Z, float p1X, float p1Y, float p1Z, Vector2f result) { - return Intersectionf.intersectLineSegmentAab(p0X, p0Y, p0Z, p1X, p1Y, p1Z, minX, minY, minZ, maxX, maxY, maxZ, result); - } - - public int intersectLineSegment(LineSegmentf lineSegment, Vector2f result) { - return Intersectionf.intersectLineSegmentAab(lineSegment, this, result); - } - - - /** - * Apply the given {@link Matrix4fc#isAffine() affine} transformation to this {@link AABBi}. - *

- * The matrix in m must be {@link Matrix4fc#isAffine() affine}. - * - * @param m - * the affine transformation matrix - * @return this - */ - public AABBi transform(Matrix4fc m) { - return transform(m, this); - } - - public AABBi transform(Matrix4fc m, AABBi dest) { - float dx = maxX - minX, dy = maxY - minY, dz = maxZ - minZ; - float minx = Float.POSITIVE_INFINITY, miny = Float.POSITIVE_INFINITY, minz = Float.POSITIVE_INFINITY; - float maxx = Float.NEGATIVE_INFINITY, maxy = Float.NEGATIVE_INFINITY, maxz = Float.NEGATIVE_INFINITY; - for (int i = 0; i < 8; i++) { - float x = minX + (i & 1) * dx, y = minY + (i >> 1 & 1) * dy, z = minZ + (i >> 2 & 1) * dz; - float tx = m.m00() * x + m.m10() * y + m.m20() * z + m.m30(); - float ty = m.m01() * x + m.m11() * y + m.m21() * z + m.m31(); - float tz = m.m02() * x + m.m12() * y + m.m22() * z + m.m32(); - minx = Math.min(tx, minx); - miny = Math.min(ty, miny); - minz = Math.min(tz, minz); - maxx = Math.max(tx, maxx); - maxy = Math.max(ty, maxy); - maxz = Math.max(tz, maxz); - } - dest.minX = Math.roundUsing(minx, RoundingMode.FLOOR); - dest.minY = Math.roundUsing(miny, RoundingMode.FLOOR); - dest.minZ = Math.roundUsing(minz, RoundingMode.FLOOR); - dest.maxX = Math.roundUsing(maxx, RoundingMode.CEILING); - dest.maxY = Math.roundUsing(maxy, RoundingMode.CEILING); - dest.maxZ = Math.roundUsing(maxz, RoundingMode.CEILING); - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + minX; - result = prime * result + minY; - result = prime * result + minZ; - result = prime * result + maxX; - result = prime * result + maxY; - result = prime * result + maxZ; - return result; - } - - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) return false; - AABBi aabBi = (AABBi) obj; - return minX == aabBi.minX && - minY == aabBi.minY && - minZ == aabBi.minZ && - maxX == aabBi.maxX && - maxY == aabBi.maxY && - maxZ == aabBi.maxZ; - } - - public String toString() { - return "(" + this.minX + " " + this.minY + " " + this.minZ + ") < " + - "(" + this.maxX + " " + this.maxY + " " + this.maxZ + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeInt(minX); - out.writeInt(minY); - out.writeInt(minZ); - out.writeInt(maxX); - out.writeInt(maxY); - out.writeInt(maxZ); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - minX = in.readInt(); - minY = in.readInt(); - minZ = in.readInt(); - maxX = in.readInt(); - maxY = in.readInt(); - maxZ = in.readInt(); - } -} diff --git a/src/org/joml/AABBic.java b/src/org/joml/AABBic.java deleted file mode 100644 index 14dfdbf7a..000000000 --- a/src/org/joml/AABBic.java +++ /dev/null @@ -1,501 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML - * - * 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 org.joml; - -/** - * Interface to a read-only view of an axis-aligned box defined via the minimum - * and maximum corner coordinates as ints. - */ -public interface AABBic { - - /** - * @return The x coordinate of the minimum corner. - */ - int minX(); - - /** - * @return The y coordinate of the minimum corner. - */ - int minY(); - - /** - * @return The z coordinate of the minimum corner. - */ - int minZ(); - - /** - * @return The x coordinate of the maximum corner. - */ - int maxX(); - - /** - * @return The y coordinate of the maximum corner. - */ - int maxY(); - - /** - * @return The z coordinate of the maximum corner. - */ - int maxZ(); - - /** - * Check whether this AABB represents a valid AABB. - * - * @return true iff this AABB is valid; false otherwise - */ - boolean isValid(); - - /** - * Get the maximum corner coordinate of the given component. - * - * @param component - * the component, within [0..2] - * @return the maximum coordinate - * @throws IllegalArgumentException if component is not within [0..2] - */ - int getMax(int component); - - - /** - * Get the minimum corner coordinate of the given component. - * - * @param component - * the component, within [0..2] - * @return the maximum coordinate - * @throws IllegalArgumentException if component is not within [0..2] - */ - int getMin(int component); - - - /** - * Return the center of the aabb - * - * @param dest will hold the result - * @return dest - */ - Vector3f center(Vector3f dest); - - - /** - * Return the center of the aabb - * - * @param dest will hold the result - * @return dest - */ - Vector3d center(Vector3d dest); - - - /** - * Extent of the aabb (max - min) / 2.0. - * - * @param dest will hold the result - * @return dest - */ - Vector3d extent(Vector3d dest); - - - /** - * Extent of the aabb (max - min) / 2.0. - * - * @param dest will hold the result - * @return dest - */ - Vector3f extent(Vector3f dest); - - - /** - * Compute the union of this and the given point (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @param dest - * will hold the result - * @return dest - */ - AABBi union(int x, int y, int z, AABBi dest); - - /** - * Compute the union of this and the given point p and store the result in dest. - * - * @param p - * the point - * @param dest - * will hold the result - * @return dest - */ - AABBi union(Vector3ic p, AABBi dest); - - - - /** - * Compute the union of this and other and store the result in dest. - * - * @param other - * the other {@link AABBi} - * @param dest - * will hold the result - * @return dest - */ - AABBi union(AABBic other, AABBi dest); - - /** - * Translate this by the vector (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param z - * the z coordinate to translate by - * @param dest - * will hold the result - * @return dest - */ - AABBi translate(int x, int y, int z, AABBi dest); - - - /** - * Compute the AABB of intersection between this and the given AABB. - *

- * If the two AABBs do not intersect, then the minimum coordinates of this - * will have a value of {@link Integer#MAX_VALUE} and the maximum coordinates will have a value of - * {@link Integer#MIN_VALUE}. - * - * @param other - * the other AABB - * @param dest - * will hold the result - * @return dest - */ - AABBi intersection(AABBic other, AABBi dest); - - - /** - * Check if this AABB contains the given AABB. - * - * @param aabb - * the AABB to test - * @return true iff this AABB contains the AABB; false otherwise - */ - boolean containsAABB(AABBdc aabb); - - - /** - * Check if this AABB contains the given AABB. - * - * @param aabb - * the AABB to test - * @return true iff this AABB contains the AABB; false otherwise - */ - boolean containsAABB(AABBfc aabb); - - /** - * Check if this AABB contains the given AABB. - * - * @param aabb - * the AABB to test - * @return true iff this AABB contains the AABB; false otherwise - */ - boolean containsAABB(AABBic aabb); - - - /** - * Test whether the point (x, y, z) lies inside this AABB. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @return true iff the given point lies inside this AABB; false otherwise - */ - boolean containsPoint(int x, int y, int z); - - - /** - * Test whether the point (x, y, z) lies inside this AABB. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @return true iff the given point lies inside this AABB; false otherwise - */ - boolean containsPoint(float x, float y, float z); - - - /** - * Test whether the given point lies inside this AABB. - * - * @param point - * the coordinates of the point - * @return true iff the given point lies inside this AABB; false otherwise - */ - boolean containsPoint(Vector3ic point); - - - /** - * Test whether the given point lies inside this AABB. - * - * @param point - * the coordinates of the point - * @return true iff the given point lies inside this AABB; false otherwise - */ - boolean containsPoint(Vector3fc point); - - /** - * Test whether the plane given via its plane equation a*x + b*y + c*z + d = 0 intersects this AABB. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return true iff the plane intersects this AABB; false otherwise - */ - boolean intersectsPlane(float a, float b, float c, float d); - - - /** - * Test whether the given plane intersects this AABB. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param plane - * the plane - * @return true iff the plane intersects this AABB; false otherwise - */ - boolean intersectsPlane(Planef plane); - - /** - * Test whether this and other intersect. - * - * @param other - * the other AABB - * @return true iff both AABBs intersect; false otherwise - */ - boolean intersectsAABB(AABBic other); - - /** - * Test whether this and other intersect. - * - * @param other - * the other AABB - * @return true iff both AABBs intersect; false otherwise - */ - boolean intersectsAABB(AABBfc other); - - /** - * Test whether this AABB intersects the given sphere with equation - * (x - centerX)^2 + (y - centerY)^2 + (z - centerZ)^2 - radiusSquared = 0. - *

- * Reference: http://stackoverflow.com - * - * @param centerX - * the x coordinate of the center of the sphere - * @param centerY - * the y coordinate of the center of the sphere - * @param centerZ - * the z coordinate of the center of the sphere - * @param radiusSquared - * the square radius of the sphere - * @return true iff this AABB and the sphere intersect; false otherwise - */ - boolean intersectsSphere(float centerX, float centerY, float centerZ, float radiusSquared) ; - - /** - * Test whether this AABB intersects the given sphere. - *

- * Reference: http://stackoverflow.com - * - * @param sphere - * the sphere - * @return true iff this AABB and the sphere intersect; false otherwise - */ - boolean intersectsSphere(Spheref sphere); - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects this AABB. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @return true if this AABB and the ray intersect; false otherwise - */ - boolean intersectsRay(float originX, float originY, float originZ, float dirX, float dirY, float dirZ); - - - /** - * Test whether the given ray intersects this AABB. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param ray - * the ray - * @return true if this AABB and the ray intersect; false otherwise - */ - boolean intersectsRay(Rayf ray); - /** - * Determine whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + t * dir of the near and far point of intersection. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects this AABB - * @return true if the given ray intersects this AABB; false otherwise - */ - boolean intersectsRay(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, Vector2f result); - - /** - * Determine whether the given ray intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + t * dir of the near and far point of intersection. - *

- * This method returns true for a ray whose origin lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param ray - * the ray - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects this AABB - * @return true if the given ray intersects this AABB; false otherwise - */ - boolean intersectsRay(Rayf ray, Vector2f result); - - /** - * Determine whether the undirected line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects this AABB - * @return {@link Intersectionf#INSIDE} if the line segment lies completely inside of this AABB; or - * {@link Intersectionf#OUTSIDE} if the line segment lies completely outside of this AABB; or - * {@link Intersectionf#ONE_INTERSECTION} if one of the end points of the line segment lies inside of this AABB; or - * {@link Intersectionf#TWO_INTERSECTION} if the line segment intersects two sides of this AABB or lies on an edge or a side of this AABB - */ - int intersectLineSegment(float p0X, float p0Y, float p0Z, float p1X, float p1Y, float p1Z, Vector2f result) ; - - /** - * Determine whether the given undirected line segment intersects this AABB, and return the values of the parameter t in the ray equation - * p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside this AABB. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @param lineSegment - * the line segment - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects this AABB - * @return {@link Intersectionf#INSIDE} if the line segment lies completely inside of this AABB; or - * {@link Intersectionf#OUTSIDE} if the line segment lies completely outside of this AABB; or - * {@link Intersectionf#ONE_INTERSECTION} if one of the end points of the line segment lies inside of this AABB; or - * {@link Intersectionf#TWO_INTERSECTION} if the line segment intersects two sides of this AABB or lies on an edge or a side of this AABB - */ - int intersectLineSegment(LineSegmentf lineSegment, Vector2f result); - - /** - * Apply the given {@link Matrix4fc#isAffine() affine} transformation to this - * {@link AABBi} and store the resulting AABB into dest. - *

- * The matrix in m must be {@link Matrix4fc#isAffine() affine}. - * - * @param m - * the affine transformation matrix - * @param dest - * will hold the result - * @return dest - */ - AABBi transform(Matrix4fc m, AABBi dest); - -} diff --git a/src/org/joml/Circled.java b/src/org/joml/Circled.java deleted file mode 100644 index f1ac70b73..000000000 --- a/src/org/joml/Circled.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a 2D circle using double-precision floating-point numbers. - * - * @author Kai Burjack - */ -public class Circled implements Externalizable { - - /** - * The x coordiante of the circle's center. - */ - public double x; - - /** - * The y coordiante of the circle's center. - */ - public double y; - - /** - * The radius of the circle. - */ - public double r; - - /** - * Create a new {@link Circled} with center position (0, 0, 0) and radius 0. - */ - public Circled() { - } - - /** - * Create a new {@link Circled} as a copy of the given source. - * - * @param source - * the {@link Circled} to copy from - */ - public Circled(Circled source) { - this.x = source.x; - this.y = source.y; - this.r = source.r; - } - - /** - * Create a new {@link Circled} with center position (x, y) and radius r. - * - * @param x - * the x coordinate of the circle's center - * @param y - * the y coordinate of the circle's center - * @param r - * the radius of the circle - */ - public Circled(double x, double y, double r) { - this.x = x; - this.y = y; - this.r = r; - } - - /** - * Translate this by the given vector xy. - * - * @param xy - * the vector to translate by - * @return this - */ - public Circled translate(Vector2dc xy) { - return translate(xy.x(), xy.y(), this); - } - - /** - * Translate this by the given vector xy and store the result in dest. - * - * @param xy - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public Circled translate(Vector2dc xy, Circled dest) { - return translate(xy.x(), xy.y(), dest); - } - - /** - * Translate this by the given vector xy. - * - * @param xy - * the vector to translate by - * @return this - */ - public Circled translate(Vector2fc xy) { - return translate(xy.x(), xy.y(), this); - } - - /** - * Translate this by the given vector xy and store the result in dest. - * - * @param xy - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public Circled translate(Vector2fc xy, Circled dest) { - return translate(xy.x(), xy.y(), dest); - } - - /** - * Translate this by the vector (x, y). - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @return this - */ - public Circled translate(double x, double y) { - return translate(x, y, this); - } - - /** - * Translate this by the vector (x, y) and store the result in dest. - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param dest - * will hold the result - * @return dest - */ - public Circled translate(double x, double y, Circled dest) { - dest.x = this.x + x; - dest.y = this.y + y; - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(r); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(x); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(y); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Circled other = (Circled) obj; - if (Double.doubleToLongBits(r) != Double.doubleToLongBits(other.r)) - return false; - if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) - return false; - if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) - return false; - return true; - } - - /** - * Return a string representation of this circle. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this circle by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(x, formatter) + " " + Runtime.format(y, formatter) + " " + Runtime.format(r, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeDouble(x); - out.writeDouble(y); - out.writeDouble(r); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - x = in.readDouble(); - y = in.readDouble(); - r = in.readDouble(); - } - -} diff --git a/src/org/joml/Circlef.java b/src/org/joml/Circlef.java deleted file mode 100644 index 15daeeecf..000000000 --- a/src/org/joml/Circlef.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a 2D circle using single-precision floating-point numbers. - * - * @author Kai Burjack - */ -public class Circlef implements Externalizable { - - /** - * The x coordiante of the circle's center. - */ - public float x; - - /** - * The y coordiante of the circle's center. - */ - public float y; - - /** - * The radius of the circle. - */ - public float r; - - /** - * Create a new {@link Circlef} with center position (0, 0, 0) and radius 0. - */ - public Circlef() { - } - - /** - * Create a new {@link Circlef} as a copy of the given source. - * - * @param source - * the {@link Circlef} to copy from - */ - public Circlef(Circlef source) { - this.x = source.x; - this.y = source.y; - this.r = source.r; - } - - /** - * Create a new {@link Circlef} with center position (x, y) and radius r. - * - * @param x - * the x coordinate of the circle's center - * @param y - * the y coordinate of the circle's center - * @param r - * the radius of the circle - */ - public Circlef(float x, float y, float r) { - this.x = x; - this.y = y; - this.r = r; - } - - /** - * Translate this by the given vector xy. - * - * @param xy - * the vector to translate by - * @return this - */ - public Circlef translate(Vector2fc xy) { - return translate(xy.x(), xy.y(), this); - } - - /** - * Translate this by the given vector xy and store the result in dest. - * - * @param xy - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public Circlef translate(Vector2fc xy, Circlef dest) { - return translate(xy.x(), xy.y(), dest); - } - - /** - * Translate this by the vector (x, y). - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @return this - */ - public Circlef translate(float x, float y) { - return translate(x, y, this); - } - - /** - * Translate this by the vector (x, y) and store the result in dest. - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param dest - * will hold the result - * @return dest - */ - public Circlef translate(float x, float y, Circlef dest) { - dest.x = this.x + x; - dest.y = this.y + y; - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(r); - result = prime * result + Float.floatToIntBits(x); - result = prime * result + Float.floatToIntBits(y); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Circlef other = (Circlef) obj; - if (Float.floatToIntBits(r) != Float.floatToIntBits(other.r)) - return false; - if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x)) - return false; - if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y)) - return false; - return true; - } - - /** - * Return a string representation of this circle. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this circle by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(x, formatter) + " " + Runtime.format(y, formatter) + " " + Runtime.format(r, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(x); - out.writeFloat(y); - out.writeFloat(r); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - x = in.readFloat(); - y = in.readFloat(); - r = in.readFloat(); - } - -} diff --git a/src/org/joml/Intersectiond.java b/src/org/joml/Intersectiond.java deleted file mode 100644 index 2cdae9a98..000000000 --- a/src/org/joml/Intersectiond.java +++ /dev/null @@ -1,5005 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2015-2020 Kai Burjack - * - * 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 org.joml; - -/** - * Contains intersection and distance tests for some 2D and 3D geometric primitives. - * - * @author Kai Burjack - */ -public class Intersectiond { - - /** - * Return value of - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)}, - * {@link #findClosestPointOnTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3d)}, - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #findClosestPointOnTriangle(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point is the first vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_VERTEX_0 = 1; - /** - * Return value of - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)}, - * {@link #findClosestPointOnTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3d)}, - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #findClosestPointOnTriangle(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point is the second vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_VERTEX_1 = 2; - /** - * Return value of - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)}, - * {@link #findClosestPointOnTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3d)}, - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #findClosestPointOnTriangle(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point is the third vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_VERTEX_2 = 3; - - /** - * Return value of - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)}, - * {@link #findClosestPointOnTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3d)}, - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #findClosestPointOnTriangle(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point lies on the edge between the first and second vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_EDGE_01 = 4; - /** - * Return value of - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)}, - * {@link #findClosestPointOnTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3d)}, - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #findClosestPointOnTriangle(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point lies on the edge between the second and third vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_EDGE_12 = 5; - /** - * Return value of - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)}, - * {@link #findClosestPointOnTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3d)}, - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #findClosestPointOnTriangle(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point lies on the edge between the third and first vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_EDGE_20 = 6; - - /** - * Return value of - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)}, - * {@link #findClosestPointOnTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3d)}, - * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #findClosestPointOnTriangle(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point lies on the face of the triangle. - */ - public static final int POINT_ON_TRIANGLE_FACE = 7; - - /** - * Return value of {@link #intersectRayAar(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectRayAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} - * to indicate that the ray intersects the side of the axis-aligned rectangle with the minimum x coordinate. - */ - public static final int AAR_SIDE_MINX = 0; - /** - * Return value of {@link #intersectRayAar(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectRayAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} - * to indicate that the ray intersects the side of the axis-aligned rectangle with the minimum y coordinate. - */ - public static final int AAR_SIDE_MINY = 1; - /** - * Return value of {@link #intersectRayAar(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectRayAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} - * to indicate that the ray intersects the side of the axis-aligned rectangle with the maximum x coordinate. - */ - public static final int AAR_SIDE_MAXX = 2; - /** - * Return value of {@link #intersectRayAar(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectRayAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} - * to indicate that the ray intersects the side of the axis-aligned rectangle with the maximum y coordinate. - */ - public static final int AAR_SIDE_MAXY = 3; - - /** - * Return value of {@link #intersectLineSegmentAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectLineSegmentAab(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector2d)} to indicate that the line segment does not intersect the axis-aligned box; - * or return value of {@link #intersectLineSegmentAar(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectLineSegmentAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} to indicate that the line segment does not intersect the axis-aligned rectangle. - */ - public static final int OUTSIDE = -1; - /** - * Return value of {@link #intersectLineSegmentAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectLineSegmentAab(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector2d)} to indicate that one end point of the line segment lies inside of the axis-aligned box; - * or return value of {@link #intersectLineSegmentAar(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectLineSegmentAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} to indicate that one end point of the line segment lies inside of the axis-aligned rectangle. - */ - public static final int ONE_INTERSECTION = 1; - /** - * Return value of {@link #intersectLineSegmentAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectLineSegmentAab(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector2d)} to indicate that the line segment intersects two sides of the axis-aligned box - * or lies on an edge or a side of the box; - * or return value of {@link #intersectLineSegmentAar(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectLineSegmentAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} to indicate that the line segment intersects two edges of the axis-aligned rectangle - * or lies on an edge of the rectangle. - */ - public static final int TWO_INTERSECTION = 2; - /** - * Return value of {@link #intersectLineSegmentAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectLineSegmentAab(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector2d)} to indicate that the line segment lies completely inside of the axis-aligned box; - * or return value of {@link #intersectLineSegmentAar(double, double, double, double, double, double, double, double, Vector2d)} and - * {@link #intersectLineSegmentAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d)} to indicate that the line segment lies completely inside of the axis-aligned rectangle. - */ - public static final int INSIDE = 3; - - /** - * Test whether the plane with the general plane equation a*x + b*y + c*z + d = 0 intersects the sphere with center - * (centerX, centerY, centerZ) and radius. - *

- * Reference: http://math.stackexchange.com - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radius - * the radius of the sphere - * @return true iff the plane intersects the sphere; false otherwise - */ - public static boolean testPlaneSphere( - double a, double b, double c, double d, - double centerX, double centerY, double centerZ, double radius) { - double denom = Math.sqrt(a * a + b * b + c * c); - double dist = (a * centerX + b * centerY + c * centerZ + d) / denom; - return -radius <= dist && dist <= radius; - } - - /** - * Test whether the given plane intersects the given sphere with center. - *

- * Reference: http://math.stackexchange.com - * - * @param plane - * the plane - * @param sphere - * the sphere - * @return true iff the plane intersects the sphere; false otherwise - */ - public static boolean testPlaneSphere(Planed plane, Spheref sphere) { - return testPlaneSphere(plane.a, plane.b, plane.c, plane.d, sphere.x, sphere.y, sphere.z, sphere.r); - } - - /** - * Test whether the plane with the general plane equation a*x + b*y + c*z + d = 0 intersects the sphere with center - * (centerX, centerY, centerZ) and radius, and store the center of the circle of - * intersection in the (x, y, z) components of the supplied vector and the radius of that circle in the w component. - *

- * Reference: http://math.stackexchange.com - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radius - * the radius of the sphere - * @param intersectionCenterAndRadius - * will hold the center of the circle of intersection in the (x, y, z) components and the radius in the w component - * @return true iff the plane intersects the sphere; false otherwise - */ - public static boolean intersectPlaneSphere( - double a, double b, double c, double d, - double centerX, double centerY, double centerZ, double radius, - Vector4d intersectionCenterAndRadius) { - double invDenom = Math.invsqrt(a * a + b * b + c * c); - double dist = (a * centerX + b * centerY + c * centerZ + d) * invDenom; - if (-radius <= dist && dist <= radius) { - intersectionCenterAndRadius.x = centerX + dist * a * invDenom; - intersectionCenterAndRadius.y = centerY + dist * b * invDenom; - intersectionCenterAndRadius.z = centerZ + dist * c * invDenom; - intersectionCenterAndRadius.w = Math.sqrt(radius * radius - dist * dist); - return true; - } - return false; - } - - /** - * Test whether the plane with the general plane equation a*x + b*y + c*z + d = 0 intersects the moving sphere with center - * (cX, cY, cZ), radius and velocity (vX, vY, vZ), and store the point of intersection - * in the (x, y, z) components of the supplied vector and the time of intersection in the w component. - *

- * The normal vector (a, b, c) of the plane equation needs to be normalized. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.5.3 "Intersecting Moving Sphere Against Plane" - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param cX - * the x coordinate of the center position of the sphere at t=0 - * @param cY - * the y coordinate of the center position of the sphere at t=0 - * @param cZ - * the z coordinate of the center position of the sphere at t=0 - * @param radius - * the sphere's radius - * @param vX - * the x component of the velocity of the sphere - * @param vY - * the y component of the velocity of the sphere - * @param vZ - * the z component of the velocity of the sphere - * @param pointAndTime - * will hold the point and time of intersection (if any) - * @return true iff the sphere intersects the plane; false otherwise - */ - public static boolean intersectPlaneSweptSphere( - double a, double b, double c, double d, - double cX, double cY, double cZ, double radius, - double vX, double vY, double vZ, - Vector4d pointAndTime) { - // Compute distance of sphere center to plane - double dist = a * cX + b * cY + c * cZ - d; - if (Math.abs(dist) <= radius) { - // The sphere is already overlapping the plane. Set time of - // intersection to zero and q to sphere center - pointAndTime.set(cX, cY, cZ, 0.0); - return true; - } - double denom = a * vX + b * vY + c * vZ; - if (denom * dist >= 0.0) { - // No intersection as sphere moving parallel to or away from plane - return false; - } - // Sphere is moving towards the plane - // Use +r in computations if sphere in front of plane, else -r - double r = dist > 0.0 ? radius : -radius; - double t = (r - dist) / denom; - pointAndTime.set( - cX + t * vX - r * a, - cY + t * vY - r * b, - cZ + t * vZ - r * c, - t); - return true; - } - - /** - * Test whether the plane with the general plane equation a*x + b*y + c*z + d = 0 intersects the sphere moving from center - * position (t0X, t0Y, t0Z) to (t1X, t1Y, t1Z) and having the given radius. - *

- * The normal vector (a, b, c) of the plane equation needs to be normalized. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.5.3 "Intersecting Moving Sphere Against Plane" - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param t0X - * the x coordinate of the start position of the sphere - * @param t0Y - * the y coordinate of the start position of the sphere - * @param t0Z - * the z coordinate of the start position of the sphere - * @param r - * the sphere's radius - * @param t1X - * the x coordinate of the end position of the sphere - * @param t1Y - * the y coordinate of the end position of the sphere - * @param t1Z - * the z coordinate of the end position of the sphere - * @return true if the sphere intersects the plane; false otherwise - */ - public static boolean testPlaneSweptSphere( - double a, double b, double c, double d, - double t0X, double t0Y, double t0Z, double r, - double t1X, double t1Y, double t1Z) { - // Get the distance for both a and b from plane p - double adist = t0X * a + t0Y * b + t0Z * c - d; - double bdist = t1X * a + t1Y * b + t1Z * c - d; - // Intersects if on different sides of plane (distances have different signs) - if (adist * bdist < 0.0) return true; - // Intersects if start or end position within radius from plane - if (Math.abs(adist) <= r || Math.abs(bdist) <= r) return true; - // No intersection - return false; - } - - /** - * Test whether the axis-aligned box with minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ) - * intersects the plane with the general equation a*x + b*y + c*z + d = 0. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned box - * @param minY - * the y coordinate of the minimum corner of the axis-aligned box - * @param minZ - * the z coordinate of the minimum corner of the axis-aligned box - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned box - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned box - * @param maxZ - * the z coordinate of the maximum corner of the axis-aligned box - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return true iff the axis-aligned box intersects the plane; false otherwise - */ - public static boolean testAabPlane( - double minX, double minY, double minZ, - double maxX, double maxY, double maxZ, - double a, double b, double c, double d) { - double pX, pY, pZ, nX, nY, nZ; - if (a > 0.0) { - pX = maxX; - nX = minX; - } else { - pX = minX; - nX = maxX; - } - if (b > 0.0) { - pY = maxY; - nY = minY; - } else { - pY = minY; - nY = maxY; - } - if (c > 0.0) { - pZ = maxZ; - nZ = minZ; - } else { - pZ = minZ; - nZ = maxZ; - } - double distN = d + a * nX + b * nY + c * nZ; - double distP = d + a * pX + b * pY + c * pZ; - return distN <= 0.0 && distP >= 0.0; - } - - /** - * Test whether the axis-aligned box intersects the plane. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param aabb - * the AABB - * @param plane - * the plane - * @return true iff the axis-aligned box intersects the plane; false otherwise - */ - public static boolean testAabPlane(AABBd aabb, Planed plane) { - return testAabPlane(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, plane.a, plane.b, plane.c, plane.d); - } - - /** - * Test whether the axis-aligned box with minimum corner min and maximum corner max - * intersects the plane with the general equation a*x + b*y + c*z + d = 0. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return true iff the axis-aligned box intersects the plane; false otherwise - */ - public static boolean testAabPlane(Vector3dc min, Vector3dc max, double a, double b, double c, double d) { - return testAabPlane(min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), a, b, c, d); - } - - /** - * Test whether the axis-aligned box with minimum corner (minXA, minYA, minZA) and maximum corner (maxXA, maxYA, maxZA) - * intersects the axis-aligned box with minimum corner (minXB, minYB, minZB) and maximum corner (maxXB, maxYB, maxZB). - * - * @param minXA - * the x coordinate of the minimum corner of the first axis-aligned box - * @param minYA - * the y coordinate of the minimum corner of the first axis-aligned box - * @param minZA - * the z coordinate of the minimum corner of the first axis-aligned box - * @param maxXA - * the x coordinate of the maximum corner of the first axis-aligned box - * @param maxYA - * the y coordinate of the maximum corner of the first axis-aligned box - * @param maxZA - * the z coordinate of the maximum corner of the first axis-aligned box - * @param minXB - * the x coordinate of the minimum corner of the second axis-aligned box - * @param minYB - * the y coordinate of the minimum corner of the second axis-aligned box - * @param minZB - * the z coordinate of the minimum corner of the second axis-aligned box - * @param maxXB - * the x coordinate of the maximum corner of the second axis-aligned box - * @param maxYB - * the y coordinate of the maximum corner of the second axis-aligned box - * @param maxZB - * the z coordinate of the maximum corner of the second axis-aligned box - * @return true iff both axis-aligned boxes intersect; false otherwise - */ - public static boolean testAabAab( - double minXA, double minYA, double minZA, - double maxXA, double maxYA, double maxZA, - double minXB, double minYB, double minZB, - double maxXB, double maxYB, double maxZB) { - return maxXA >= minXB && maxYA >= minYB && maxZA >= minZB && - minXA <= maxXB && minYA <= maxYB && minZA <= maxZB; - } - - /** - * Test whether the axis-aligned box with minimum corner minA and maximum corner maxA - * intersects the axis-aligned box with minimum corner minB and maximum corner maxB. - * - * @param minA - * the minimum corner of the first axis-aligned box - * @param maxA - * the maximum corner of the first axis-aligned box - * @param minB - * the minimum corner of the second axis-aligned box - * @param maxB - * the maximum corner of the second axis-aligned box - * @return true iff both axis-aligned boxes intersect; false otherwise - */ - public static boolean testAabAab(Vector3dc minA, Vector3dc maxA, Vector3dc minB, Vector3dc maxB) { - return testAabAab(minA.x(), minA.y(), minA.z(), maxA.x(), maxA.y(), maxA.z(), minB.x(), minB.y(), minB.z(), maxB.x(), maxB.y(), maxB.z()); - } - - /** - * Test whether the two axis-aligned boxes intersect. - * - * @param aabb1 - * the first AABB - * @param aabb2 - * the second AABB - * @return true iff both axis-aligned boxes intersect; false otherwise - */ - public static boolean testAabAab(AABBd aabb1, AABBd aabb2) { - return testAabAab(aabb1.minX, aabb1.minY, aabb1.minZ, aabb1.maxX, aabb1.maxY, aabb1.maxZ, aabb2.minX, aabb2.minY, aabb2.minZ, aabb2.maxX, aabb2.maxY, aabb2.maxZ); - } - - /** - * Test whether two oriented boxes given via their center position, orientation and half-size, intersect. - *

- * The orientation of a box is given as three unit vectors spanning the local orthonormal basis of the box. - *

- * The size is given as the half-size along each of the unit vectors defining the orthonormal basis. - *

- * Reference: Book "Real-Time Collision Detection" chapter 4.4.1 "OBB-OBB Intersection" - * - * @param b0c - * the center of the first box - * @param b0uX - * the local X unit vector of the first box - * @param b0uY - * the local Y unit vector of the first box - * @param b0uZ - * the local Z unit vector of the first box - * @param b0hs - * the half-size of the first box - * @param b1c - * the center of the second box - * @param b1uX - * the local X unit vector of the second box - * @param b1uY - * the local Y unit vector of the second box - * @param b1uZ - * the local Z unit vector of the second box - * @param b1hs - * the half-size of the second box - * @return true if both boxes intersect; false otherwise - */ - public static boolean testObOb( - Vector3d b0c, Vector3d b0uX, Vector3d b0uY, Vector3d b0uZ, Vector3d b0hs, - Vector3d b1c, Vector3d b1uX, Vector3d b1uY, Vector3d b1uZ, Vector3d b1hs) { - return testObOb( - b0c.x, b0c.y, b0c.z, b0uX.x, b0uX.y, b0uX.z, b0uY.x, b0uY.y, b0uY.z, b0uZ.x, b0uZ.y, b0uZ.z, b0hs.x, b0hs.y, b0hs.z, - b1c.x, b1c.y, b1c.z, b1uX.x, b1uX.y, b1uX.z, b1uY.x, b1uY.y, b1uY.z, b1uZ.x, b1uZ.y, b1uZ.z, b1hs.x, b1hs.y, b1hs.z); - } - - /** - * Test whether two oriented boxes given via their center position, orientation and half-size, intersect. - *

- * The orientation of a box is given as three unit vectors spanning the local orthonormal basis of the box. - *

- * The size is given as the half-size along each of the unit vectors defining the orthonormal basis. - *

- * Reference: Book "Real-Time Collision Detection" chapter 4.4.1 "OBB-OBB Intersection" - * - * @param b0cX - * the x coordinate of the center of the first box - * @param b0cY - * the y coordinate of the center of the first box - * @param b0cZ - * the z coordinate of the center of the first box - * @param b0uXx - * the x coordinate of the local X unit vector of the first box - * @param b0uXy - * the y coordinate of the local X unit vector of the first box - * @param b0uXz - * the z coordinate of the local X unit vector of the first box - * @param b0uYx - * the x coordinate of the local Y unit vector of the first box - * @param b0uYy - * the y coordinate of the local Y unit vector of the first box - * @param b0uYz - * the z coordinate of the local Y unit vector of the first box - * @param b0uZx - * the x coordinate of the local Z unit vector of the first box - * @param b0uZy - * the y coordinate of the local Z unit vector of the first box - * @param b0uZz - * the z coordinate of the local Z unit vector of the first box - * @param b0hsX - * the half-size of the first box along its local X axis - * @param b0hsY - * the half-size of the first box along its local Y axis - * @param b0hsZ - * the half-size of the first box along its local Z axis - * @param b1cX - * the x coordinate of the center of the second box - * @param b1cY - * the y coordinate of the center of the second box - * @param b1cZ - * the z coordinate of the center of the second box - * @param b1uXx - * the x coordinate of the local X unit vector of the second box - * @param b1uXy - * the y coordinate of the local X unit vector of the second box - * @param b1uXz - * the z coordinate of the local X unit vector of the second box - * @param b1uYx - * the x coordinate of the local Y unit vector of the second box - * @param b1uYy - * the y coordinate of the local Y unit vector of the second box - * @param b1uYz - * the z coordinate of the local Y unit vector of the second box - * @param b1uZx - * the x coordinate of the local Z unit vector of the second box - * @param b1uZy - * the y coordinate of the local Z unit vector of the second box - * @param b1uZz - * the z coordinate of the local Z unit vector of the second box - * @param b1hsX - * the half-size of the second box along its local X axis - * @param b1hsY - * the half-size of the second box along its local Y axis - * @param b1hsZ - * the half-size of the second box along its local Z axis - * @return true if both boxes intersect; false otherwise - */ - public static boolean testObOb( - double b0cX, double b0cY, double b0cZ, double b0uXx, double b0uXy, double b0uXz, double b0uYx, double b0uYy, double b0uYz, double b0uZx, double b0uZy, double b0uZz, double b0hsX, double b0hsY, double b0hsZ, - double b1cX, double b1cY, double b1cZ, double b1uXx, double b1uXy, double b1uXz, double b1uYx, double b1uYy, double b1uYz, double b1uZx, double b1uZy, double b1uZz, double b1hsX, double b1hsY, double b1hsZ) { - double ra, rb; - // Compute rotation matrix expressing b in a's coordinate frame - double rm00 = b0uXx * b1uXx + b0uYx * b1uYx + b0uZx * b1uZx; - double rm10 = b0uXx * b1uXy + b0uYx * b1uYy + b0uZx * b1uZy; - double rm20 = b0uXx * b1uXz + b0uYx * b1uYz + b0uZx * b1uZz; - double rm01 = b0uXy * b1uXx + b0uYy * b1uYx + b0uZy * b1uZx; - double rm11 = b0uXy * b1uXy + b0uYy * b1uYy + b0uZy * b1uZy; - double rm21 = b0uXy * b1uXz + b0uYy * b1uYz + b0uZy * b1uZz; - double rm02 = b0uXz * b1uXx + b0uYz * b1uYx + b0uZz * b1uZx; - double rm12 = b0uXz * b1uXy + b0uYz * b1uYy + b0uZz * b1uZy; - double rm22 = b0uXz * b1uXz + b0uYz * b1uYz + b0uZz * b1uZz; - // Compute common subexpressions. Add in an epsilon term to - // counteract arithmetic errors when two edges are parallel and - // their cross product is (near) null (see text for details) - double EPSILON = 1E-8; - double arm00 = Math.abs(rm00) + EPSILON; - double arm01 = Math.abs(rm01) + EPSILON; - double arm02 = Math.abs(rm02) + EPSILON; - double arm10 = Math.abs(rm10) + EPSILON; - double arm11 = Math.abs(rm11) + EPSILON; - double arm12 = Math.abs(rm12) + EPSILON; - double arm20 = Math.abs(rm20) + EPSILON; - double arm21 = Math.abs(rm21) + EPSILON; - double arm22 = Math.abs(rm22) + EPSILON; - // Compute translation vector t - double tx = b1cX - b0cX, ty = b1cY - b0cY, tz = b1cZ - b0cZ; - // Bring translation into a's coordinate frame - double tax = tx * b0uXx + ty * b0uXy + tz * b0uXz; - double tay = tx * b0uYx + ty * b0uYy + tz * b0uYz; - double taz = tx * b0uZx + ty * b0uZy + tz * b0uZz; - // Test axes L = A0, L = A1, L = A2 - ra = b0hsX; - rb = b1hsX * arm00 + b1hsY * arm01 + b1hsZ * arm02; - if (Math.abs(tax) > ra + rb) return false; - ra = b0hsY; - rb = b1hsX * arm10 + b1hsY * arm11 + b1hsZ * arm12; - if (Math.abs(tay) > ra + rb) return false; - ra = b0hsZ; - rb = b1hsX * arm20 + b1hsY * arm21 + b1hsZ * arm22; - if (Math.abs(taz) > ra + rb) return false; - // Test axes L = B0, L = B1, L = B2 - ra = b0hsX * arm00 + b0hsY * arm10 + b0hsZ * arm20; - rb = b1hsX; - if (Math.abs(tax * rm00 + tay * rm10 + taz * rm20) > ra + rb) return false; - ra = b0hsX * arm01 + b0hsY * arm11 + b0hsZ * arm21; - rb = b1hsY; - if (Math.abs(tax * rm01 + tay * rm11 + taz * rm21) > ra + rb) return false; - ra = b0hsX * arm02 + b0hsY * arm12 + b0hsZ * arm22; - rb = b1hsZ; - if (Math.abs(tax * rm02 + tay * rm12 + taz * rm22) > ra + rb) return false; - // Test axis L = A0 x B0 - ra = b0hsY * arm20 + b0hsZ * arm10; - rb = b1hsY * arm02 + b1hsZ * arm01; - if (Math.abs(taz * rm10 - tay * rm20) > ra + rb) return false; - // Test axis L = A0 x B1 - ra = b0hsY * arm21 + b0hsZ * arm11; - rb = b1hsX * arm02 + b1hsZ * arm00; - if (Math.abs(taz * rm11 - tay * rm21) > ra + rb) return false; - // Test axis L = A0 x B2 - ra = b0hsY * arm22 + b0hsZ * arm12; - rb = b1hsX * arm01 + b1hsY * arm00; - if (Math.abs(taz * rm12 - tay * rm22) > ra + rb) return false; - // Test axis L = A1 x B0 - ra = b0hsX * arm20 + b0hsZ * arm00; - rb = b1hsY * arm12 + b1hsZ * arm11; - if (Math.abs(tax * rm20 - taz * rm00) > ra + rb) return false; - // Test axis L = A1 x B1 - ra = b0hsX * arm21 + b0hsZ * arm01; - rb = b1hsX * arm12 + b1hsZ * arm10; - if (Math.abs(tax * rm21 - taz * rm01) > ra + rb) return false; - // Test axis L = A1 x B2 - ra = b0hsX * arm22 + b0hsZ * arm02; - rb = b1hsX * arm11 + b1hsY * arm10; - if (Math.abs(tax * rm22 - taz * rm02) > ra + rb) return false; - // Test axis L = A2 x B0 - ra = b0hsX * arm10 + b0hsY * arm00; - rb = b1hsY * arm22 + b1hsZ * arm21; - if (Math.abs(tay * rm00 - tax * rm10) > ra + rb) return false; - // Test axis L = A2 x B1 - ra = b0hsX * arm11 + b0hsY * arm01; - rb = b1hsX * arm22 + b1hsZ * arm20; - if (Math.abs(tay * rm01 - tax * rm11) > ra + rb) return false; - // Test axis L = A2 x B2 - ra = b0hsX * arm12 + b0hsY * arm02; - rb = b1hsX * arm21 + b1hsY * arm20; - if (Math.abs(tay * rm02 - tax * rm12) > ra + rb) return false; - // Since no separating axis is found, the OBBs must be intersecting - return true; - } - - /** - * Test whether the one sphere with center (aX, aY, aZ) and square radius radiusSquaredA intersects the other - * sphere with center (bX, bY, bZ) and square radius radiusSquaredB, and store the center of the circle of - * intersection in the (x, y, z) components of the supplied vector and the radius of that circle in the w component. - *

- * The normal vector of the circle of intersection can simply be obtained by subtracting the center of either sphere from the other. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param aX - * the x coordinate of the first sphere's center - * @param aY - * the y coordinate of the first sphere's center - * @param aZ - * the z coordinate of the first sphere's center - * @param radiusSquaredA - * the square of the first sphere's radius - * @param bX - * the x coordinate of the second sphere's center - * @param bY - * the y coordinate of the second sphere's center - * @param bZ - * the z coordinate of the second sphere's center - * @param radiusSquaredB - * the square of the second sphere's radius - * @param centerAndRadiusOfIntersectionCircle - * will hold the center of the circle of intersection in the (x, y, z) components and the radius in the w component - * @return true iff both spheres intersect; false otherwise - */ - public static boolean intersectSphereSphere( - double aX, double aY, double aZ, double radiusSquaredA, - double bX, double bY, double bZ, double radiusSquaredB, - Vector4d centerAndRadiusOfIntersectionCircle) { - double dX = bX - aX, dY = bY - aY, dZ = bZ - aZ; - double distSquared = dX * dX + dY * dY + dZ * dZ; - double h = 0.5 + (radiusSquaredA - radiusSquaredB) / distSquared; - double r_i = radiusSquaredA - h * h * distSquared; - if (r_i >= 0.0) { - centerAndRadiusOfIntersectionCircle.x = aX + h * dX; - centerAndRadiusOfIntersectionCircle.y = aY + h * dY; - centerAndRadiusOfIntersectionCircle.z = aZ + h * dZ; - centerAndRadiusOfIntersectionCircle.w = Math.sqrt(r_i); - return true; - } - return false; - } - - /** - * Test whether the one sphere with center centerA and square radius radiusSquaredA intersects the other - * sphere with center centerB and square radius radiusSquaredB, and store the center of the circle of - * intersection in the (x, y, z) components of the supplied vector and the radius of that circle in the w component. - *

- * The normal vector of the circle of intersection can simply be obtained by subtracting the center of either sphere from the other. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param centerA - * the first sphere's center - * @param radiusSquaredA - * the square of the first sphere's radius - * @param centerB - * the second sphere's center - * @param radiusSquaredB - * the square of the second sphere's radius - * @param centerAndRadiusOfIntersectionCircle - * will hold the center of the circle of intersection in the (x, y, z) components and the radius in the w component - * @return true iff both spheres intersect; false otherwise - */ - public static boolean intersectSphereSphere(Vector3dc centerA, double radiusSquaredA, Vector3dc centerB, double radiusSquaredB, Vector4d centerAndRadiusOfIntersectionCircle) { - return intersectSphereSphere(centerA.x(), centerA.y(), centerA.z(), radiusSquaredA, centerB.x(), centerB.y(), centerB.z(), radiusSquaredB, centerAndRadiusOfIntersectionCircle); - } - - /** - * Test whether the one sphere with intersects the other sphere, and store the center of the circle of - * intersection in the (x, y, z) components of the supplied vector and the radius of that circle in the w component. - *

- * The normal vector of the circle of intersection can simply be obtained by subtracting the center of either sphere from the other. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param sphereA - * the first sphere - * @param sphereB - * the second sphere - * @param centerAndRadiusOfIntersectionCircle - * will hold the center of the circle of intersection in the (x, y, z) components and the radius in the w component - * @return true iff both spheres intersect; false otherwise - */ - public static boolean intersectSphereSphere(Spheref sphereA, Spheref sphereB, Vector4d centerAndRadiusOfIntersectionCircle) { - return intersectSphereSphere(sphereA.x, sphereA.y, sphereA.z, sphereA.r*sphereA.r, sphereB.x, sphereB.y, sphereB.z, sphereB.r*sphereB.r, centerAndRadiusOfIntersectionCircle); - } - - /** - * Test whether the given sphere with center (sX, sY, sZ) intersects the triangle given by its three vertices, and if they intersect - * store the point of intersection into result. - *

- * This method also returns whether the point of intersection is on one of the triangle's vertices, edges or on the face. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.2.7 "Testing Sphere Against Triangle" - * - * @param sX - * the x coordinate of the sphere's center - * @param sY - * the y coordinate of the sphere's center - * @param sZ - * the z coordinate of the sphere's center - * @param sR - * the sphere's radius - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v0Z - * the z coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v1Z - * the z coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @param v2Z - * the z coordinate of the third vertex of the triangle - * @param result - * will hold the point of intersection - * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}, - * {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or - * {@link #POINT_ON_TRIANGLE_FACE} or 0 - */ - public static int intersectSphereTriangle( - double sX, double sY, double sZ, double sR, - double v0X, double v0Y, double v0Z, - double v1X, double v1Y, double v1Z, - double v2X, double v2Y, double v2Z, - Vector3d result) { - int closest = findClosestPointOnTriangle(v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z, sX, sY, sZ, result); - double vX = result.x - sX, vY = result.y - sY, vZ = result.z - sZ; - double dot = vX * vX + vY * vY + vZ * vZ; - if (dot <= sR * sR) { - return closest; - } - return 0; - } - - /** - * Test whether the one sphere with center (aX, aY, aZ) and square radius radiusSquaredA intersects the other - * sphere with center (bX, bY, bZ) and square radius radiusSquaredB. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param aX - * the x coordinate of the first sphere's center - * @param aY - * the y coordinate of the first sphere's center - * @param aZ - * the z coordinate of the first sphere's center - * @param radiusSquaredA - * the square of the first sphere's radius - * @param bX - * the x coordinate of the second sphere's center - * @param bY - * the y coordinate of the second sphere's center - * @param bZ - * the z coordinate of the second sphere's center - * @param radiusSquaredB - * the square of the second sphere's radius - * @return true iff both spheres intersect; false otherwise - */ - public static boolean testSphereSphere( - double aX, double aY, double aZ, double radiusSquaredA, - double bX, double bY, double bZ, double radiusSquaredB) { - double dX = bX - aX, dY = bY - aY, dZ = bZ - aZ; - double distSquared = dX * dX + dY * dY + dZ * dZ; - double h = 0.5 + (radiusSquaredA - radiusSquaredB) / distSquared; - double r_i = radiusSquaredA - h * h * distSquared; - return r_i >= 0.0; - } - - /** - * Test whether the one sphere with center centerA and square radius radiusSquaredA intersects the other - * sphere with center centerB and square radius radiusSquaredB. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param centerA - * the first sphere's center - * @param radiusSquaredA - * the square of the first sphere's radius - * @param centerB - * the second sphere's center - * @param radiusSquaredB - * the square of the second sphere's radius - * @return true iff both spheres intersect; false otherwise - */ - public static boolean testSphereSphere(Vector3dc centerA, double radiusSquaredA, Vector3dc centerB, double radiusSquaredB) { - return testSphereSphere(centerA.x(), centerA.y(), centerA.z(), radiusSquaredA, centerB.x(), centerB.y(), centerB.z(), radiusSquaredB); - } - - /** - * Determine the signed distance of the given point (pointX, pointY, pointZ) to the plane specified via its general plane equation - * a*x + b*y + c*z + d = 0. - * - * @param pointX - * the x coordinate of the point - * @param pointY - * the y coordinate of the point - * @param pointZ - * the z coordinate of the point - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return the distance between the point and the plane - */ - public static double distancePointPlane(double pointX, double pointY, double pointZ, double a, double b, double c, double d) { - double denom = Math.sqrt(a * a + b * b + c * c); - return (a * pointX + b * pointY + c * pointZ + d) / denom; - } - - /** - * Determine the signed distance of the given point (pointX, pointY, pointZ) to the plane of the triangle specified by its three points - * (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z). - *

- * If the point lies on the front-facing side of the triangle's plane, that is, if the triangle has counter-clockwise winding order - * as seen from the point, then this method returns a positive number. - * - * @param pointX - * the x coordinate of the point - * @param pointY - * the y coordinate of the point - * @param pointZ - * the z coordinate of the point - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v0Z - * the z coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v1Z - * the z coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @param v2Z - * the z coordinate of the third vertex of the triangle - * @return the signed distance between the point and the plane of the triangle - */ - public static double distancePointPlane(double pointX, double pointY, double pointZ, - double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z) { - double v1Y0Y = v1Y - v0Y; - double v2Z0Z = v2Z - v0Z; - double v2Y0Y = v2Y - v0Y; - double v1Z0Z = v1Z - v0Z; - double v2X0X = v2X - v0X; - double v1X0X = v1X - v0X; - double a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z; - double b = v1Z0Z * v2X0X - v2Z0Z * v1X0X; - double c = v1X0X * v2Y0Y - v2X0X * v1Y0Y; - double d = -(a * v0X + b * v0Y + c * v0Z); - return distancePointPlane(pointX, pointY, pointZ, a, b, c, d); - } - - /** - * Test whether the ray with given origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) intersects the plane - * containing the given point (pointX, pointY, pointZ) and having the normal (normalX, normalY, normalZ), and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the plane, because it is either parallel to the plane or its direction points - * away from the plane or the ray's origin is on the negative side of the plane (i.e. the plane's normal points away from the ray's origin). - *

- * Reference: https://www.siggraph.org/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param pointX - * the x coordinate of a point on the plane - * @param pointY - * the y coordinate of a point on the plane - * @param pointZ - * the z coordinate of a point on the plane - * @param normalX - * the x coordinate of the plane's normal - * @param normalY - * the y coordinate of the plane's normal - * @param normalZ - * the z coordinate of the plane's normal - * @param epsilon - * some small epsilon for when the ray is parallel to the plane - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the plane; -1.0 otherwise - */ - public static double intersectRayPlane(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, - double pointX, double pointY, double pointZ, double normalX, double normalY, double normalZ, double epsilon) { - double denom = normalX * dirX + normalY * dirY + normalZ * dirZ; - if (denom < epsilon) { - double t = ((pointX - originX) * normalX + (pointY - originY) * normalY + (pointZ - originZ) * normalZ) / denom; - if (t >= 0.0) - return t; - } - return -1.0; - } - - /** - * Test whether the ray with given origin and direction dir intersects the plane - * containing the given point and having the given normal, and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the plane, because it is either parallel to the plane or its direction points - * away from the plane or the ray's origin is on the negative side of the plane (i.e. the plane's normal points away from the ray's origin). - *

- * Reference: https://www.siggraph.org/ - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param point - * a point on the plane - * @param normal - * the plane's normal - * @param epsilon - * some small epsilon for when the ray is parallel to the plane - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the plane; -1.0 otherwise - */ - public static double intersectRayPlane(Vector3dc origin, Vector3dc dir, Vector3dc point, Vector3dc normal, double epsilon) { - return intersectRayPlane(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), point.x(), point.y(), point.z(), normal.x(), normal.y(), normal.z(), epsilon); - } - - /** - * Test whether the given ray intersects the given plane, and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the plane, because it is either parallel to the plane or its direction points - * away from the plane or the ray's origin is on the negative side of the plane (i.e. the plane's normal points away from the ray's origin). - *

- * Reference: https://www.siggraph.org/ - * - * @param ray - * the ray - * @param plane - * the plane - * @param epsilon - * some small epsilon for when the ray is parallel to the plane - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the plane; -1.0 otherwise - */ - public static double intersectRayPlane(Rayd ray, Planed plane, double epsilon) { - return intersectRayPlane(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, plane.a, plane.b, plane.c, plane.d, epsilon); - } - - /** - * Test whether the ray with given origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) intersects the plane - * given as the general plane equation a*x + b*y + c*z + d = 0, and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the plane, because it is either parallel to the plane or its direction points - * away from the plane or the ray's origin is on the negative side of the plane (i.e. the plane's normal points away from the ray's origin). - *

- * Reference: https://www.siggraph.org/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param epsilon - * some small epsilon for when the ray is parallel to the plane - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the plane; -1.0 otherwise - */ - public static double intersectRayPlane(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, - double a, double b, double c, double d, double epsilon) { - double denom = a * dirX + b * dirY + c * dirZ; - if (denom < 0.0) { - double t = -(a * originX + b * originY + c * originZ + d) / denom; - if (t >= 0.0) - return t; - } - return -1.0; - } - - /** - * Test whether the axis-aligned box with minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ) - * intersects the sphere with the given center (centerX, centerY, centerZ) and square radius radiusSquared. - *

- * Reference: http://stackoverflow.com - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned box - * @param minY - * the y coordinate of the minimum corner of the axis-aligned box - * @param minZ - * the z coordinate of the minimum corner of the axis-aligned box - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned box - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned box - * @param maxZ - * the z coordinate of the maximum corner of the axis-aligned box - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radiusSquared - * the square of the sphere's radius - * @return true iff the axis-aligned box intersects the sphere; false otherwise - */ - public static boolean testAabSphere( - double minX, double minY, double minZ, - double maxX, double maxY, double maxZ, - double centerX, double centerY, double centerZ, double radiusSquared) { - double radius2 = radiusSquared; - if (centerX < minX) { - double d = (centerX - minX); - radius2 -= d * d; - } else if (centerX > maxX) { - double d = (centerX - maxX); - radius2 -= d * d; - } - if (centerY < minY) { - double d = (centerY - minY); - radius2 -= d * d; - } else if (centerY > maxY) { - double d = (centerY - maxY); - radius2 -= d * d; - } - if (centerZ < minZ) { - double d = (centerZ - minZ); - radius2 -= d * d; - } else if (centerZ > maxZ) { - double d = (centerZ - maxZ); - radius2 -= d * d; - } - return radius2 >= 0.0; - } - - /** - * Test whether the axis-aligned box with minimum corner min and maximum corner max - * intersects the sphere with the given center and square radius radiusSquared. - *

- * Reference: http://stackoverflow.com - * - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @param center - * the sphere's center - * @param radiusSquared - * the squared of the sphere's radius - * @return true iff the axis-aligned box intersects the sphere; false otherwise - */ - public static boolean testAabSphere(Vector3dc min, Vector3dc max, Vector3dc center, double radiusSquared) { - return testAabSphere(min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), center.x(), center.y(), center.z(), radiusSquared); - } - - /** - * Test whether the given axis-aligned box intersects the given sphere. - *

- * Reference: http://stackoverflow.com - * - * @param aabb - * the AABB - * @param sphere - * the sphere - * @return true iff the axis-aligned box intersects the sphere; false otherwise - */ - public static boolean testAabSphere(AABBd aabb, Spheref sphere) { - return testAabSphere(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, sphere.x, sphere.y, sphere.z, sphere.r*sphere.r); - } - - /** - * Find the point on the given plane which is closest to the specified point (pX, pY, pZ) and store the result in result. - * - * @param aX - * the x coordinate of one point on the plane - * @param aY - * the y coordinate of one point on the plane - * @param aZ - * the z coordinate of one point on the plane - * @param nX - * the x coordinate of the unit normal of the plane - * @param nY - * the y coordinate of the unit normal of the plane - * @param nZ - * the z coordinate of the unit normal of the plane - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param pZ - * the z coordinate of the point - * @param result - * will hold the result - * @return result - */ - public static Vector3d findClosestPointOnPlane(double aX, double aY, double aZ, double nX, double nY, double nZ, double pX, double pY, double pZ, Vector3d result) { - double d = -(nX * aX + nY * aY + nZ * aZ); - double t = nX * pX + nY * pY + nZ * pZ - d; - result.x = pX - t * nX; - result.y = pY - t * nY; - result.z = pZ - t * nZ; - return result; - } - - /** - * Find the point on the given line segment which is closest to the specified point (pX, pY, pZ), and store the result in result. - * - * @param aX - * the x coordinate of the first end point of the line segment - * @param aY - * the y coordinate of the first end point of the line segment - * @param aZ - * the z coordinate of the first end point of the line segment - * @param bX - * the x coordinate of the second end point of the line segment - * @param bY - * the y coordinate of the second end point of the line segment - * @param bZ - * the z coordinate of the second end point of the line segment - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param pZ - * the z coordinate of the point - * @param result - * will hold the result - * @return result - */ - public static Vector3d findClosestPointOnLineSegment(double aX, double aY, double aZ, double bX, double bY, double bZ, double pX, double pY, double pZ, Vector3d result) { - double abX = bX - aX, abY = bY - aY, abZ = bZ - aZ; - double t = ((pX - aX) * abX + (pY - aY) * abY + (pZ - aZ) * abZ) / (abX * abX + abY * abY + abZ * abZ); - if (t < 0.0) t = 0.0; - if (t > 1.0) t = 1.0; - result.x = aX + t * abX; - result.y = aY + t * abY; - result.z = aZ + t * abZ; - return result; - } - - /** - * Find the closest points on the two line segments, store the point on the first line segment in resultA and - * the point on the second line segment in resultB, and return the square distance between both points. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.9 "Closest Points of Two Line Segments" - * - * @param a0X - * the x coordinate of the first line segment's first end point - * @param a0Y - * the y coordinate of the first line segment's first end point - * @param a0Z - * the z coordinate of the first line segment's first end point - * @param a1X - * the x coordinate of the first line segment's second end point - * @param a1Y - * the y coordinate of the first line segment's second end point - * @param a1Z - * the z coordinate of the first line segment's second end point - * @param b0X - * the x coordinate of the second line segment's first end point - * @param b0Y - * the y coordinate of the second line segment's first end point - * @param b0Z - * the z coordinate of the second line segment's first end point - * @param b1X - * the x coordinate of the second line segment's second end point - * @param b1Y - * the y coordinate of the second line segment's second end point - * @param b1Z - * the z coordinate of the second line segment's second end point - * @param resultA - * will hold the point on the first line segment - * @param resultB - * will hold the point on the second line segment - * @return the square distance between the two closest points - */ - public static double findClosestPointsLineSegments( - double a0X, double a0Y, double a0Z, double a1X, double a1Y, double a1Z, - double b0X, double b0Y, double b0Z, double b1X, double b1Y, double b1Z, - Vector3d resultA, Vector3d resultB) { - double d1x = a1X - a0X, d1y = a1Y - a0Y, d1z = a1Z - a0Z; - double d2x = b1X - b0X, d2y = b1Y - b0Y, d2z = b1Z - b0Z; - double rX = a0X - b0X, rY = a0Y - b0Y, rZ = a0Z - b0Z; - double a = d1x * d1x + d1y * d1y + d1z * d1z; - double e = d2x * d2x + d2y * d2y + d2z * d2z; - double f = d2x * rX + d2y * rY + d2z * rZ; - double EPSILON = 1E-8; - double s, t; - if (a <= EPSILON && e <= EPSILON) { - // Both segments degenerate into points - resultA.set(a0X, a0Y, a0Z); - resultB.set(b0X, b0Y, b0Z); - return resultA.dot(resultB); - } - if (a <= EPSILON) { - // First segment degenerates into a point - s = 0.0; - t = f / e; - t = Math.min(Math.max(t, 0.0), 1.0); - } else { - double c = d1x * rX + d1y * rY + d1z * rZ; - if (e <= EPSILON) { - // Second segment degenerates into a point - t = 0.0; - s = Math.min(Math.max(-c / a, 0.0), 1.0); - } else { - // The general nondegenerate case starts here - double b = d1x * d2x + d1y * d2y + d1z * d2z; - double denom = a * e - b * b; - // If segments not parallel, compute closest point on L1 to L2 and - // clamp to segment S1. Else pick arbitrary s (here 0) - if (denom != 0.0) - s = Math.min(Math.max((b*f - c*e) / denom, 0.0), 1.0); - else - s = 0.0; - // Compute point on L2 closest to S1(s) using - // t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e - t = (b * s + f) / e; - // If t in [0,1] done. Else clamp t, recompute s for the new value - // of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a - // and clamp s to [0, 1] - if (t < 0.0) { - t = 0.0; - s = Math.min(Math.max(-c / a, 0.0), 1.0); - } else if (t > 1.0) { - t = 1.0; - s = Math.min(Math.max((b - c) / a, 0.0), 1.0); - } - } - } - resultA.set(a0X + d1x * s, a0Y + d1y * s, a0Z + d1z * s); - resultB.set(b0X + d2x * t, b0Y + d2y * t, b0Z + d2z * t); - double dX = resultA.x - resultB.x, dY = resultA.y - resultB.y, dZ = resultA.z - resultB.z; - return dX*dX + dY*dY + dZ*dZ; - } - - /** - * Find the closest points on a line segment and a triangle. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.10 "Closest Points of a Line Segment and a Triangle" - * - * @param aX - * the x coordinate of the line segment's first end point - * @param aY - * the y coordinate of the line segment's first end point - * @param aZ - * the z coordinate of the line segment's first end point - * @param bX - * the x coordinate of the line segment's second end point - * @param bY - * the y coordinate of the line segment's second end point - * @param bZ - * the z coordinate of the line segment's second end point - * @param v0X - * the x coordinate of the triangle's first vertex - * @param v0Y - * the y coordinate of the triangle's first vertex - * @param v0Z - * the z coordinate of the triangle's first vertex - * @param v1X - * the x coordinate of the triangle's second vertex - * @param v1Y - * the y coordinate of the triangle's second vertex - * @param v1Z - * the z coordinate of the triangle's second vertex - * @param v2X - * the x coordinate of the triangle's third vertex - * @param v2Y - * the y coordinate of the triangle's third vertex - * @param v2Z - * the z coordinate of the triangle's third vertex - * @param lineSegmentResult - * will hold the closest point on the line segment - * @param triangleResult - * will hold the closest point on the triangle - * @return the square distance of the closest points - */ - public static double findClosestPointsLineSegmentTriangle( - double aX, double aY, double aZ, double bX, double bY, double bZ, - double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z, - Vector3d lineSegmentResult, Vector3d triangleResult) { - double min, d; - double minlsX, minlsY, minlsZ, mintX, mintY, mintZ; - // AB -> V0V1 - d = findClosestPointsLineSegments(aX, aY, aZ, bX, bY, bZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, lineSegmentResult, triangleResult); - min = d; - minlsX = lineSegmentResult.x; minlsY = lineSegmentResult.y; minlsZ = lineSegmentResult.z; - mintX = triangleResult.x; mintY = triangleResult.y; mintZ = triangleResult.z; - // AB -> V1V2 - d = findClosestPointsLineSegments(aX, aY, aZ, bX, bY, bZ, v1X, v1Y, v1Z, v2X, v2Y, v2Z, lineSegmentResult, triangleResult); - if (d < min) { - min = d; - minlsX = lineSegmentResult.x; minlsY = lineSegmentResult.y; minlsZ = lineSegmentResult.z; - mintX = triangleResult.x; mintY = triangleResult.y; mintZ = triangleResult.z; - } - // AB -> V2V0 - d = findClosestPointsLineSegments(aX, aY, aZ, bX, bY, bZ, v2X, v2Y, v2Z, v0X, v0Y, v0Z, lineSegmentResult, triangleResult); - if (d < min) { - min = d; - minlsX = lineSegmentResult.x; minlsY = lineSegmentResult.y; minlsZ = lineSegmentResult.z; - mintX = triangleResult.x; mintY = triangleResult.y; mintZ = triangleResult.z; - } - // segment endpoint A and plane of triangle (when A projects inside V0V1V2) - boolean computed = false; - double a = Double.NaN, b = Double.NaN, c = Double.NaN, nd = Double.NaN; - if (testPointInTriangle(aX, aY, aZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z)) { - double v1Y0Y = v1Y - v0Y; - double v2Z0Z = v2Z - v0Z; - double v2Y0Y = v2Y - v0Y; - double v1Z0Z = v1Z - v0Z; - double v2X0X = v2X - v0X; - double v1X0X = v1X - v0X; - a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z; - b = v1Z0Z * v2X0X - v2Z0Z * v1X0X; - c = v1X0X * v2Y0Y - v2X0X * v1Y0Y; - computed = true; - double invLen = Math.invsqrt(a*a + b*b + c*c); - a *= invLen; b *= invLen; c *= invLen; - nd = -(a * v0X + b * v0Y + c * v0Z); - d = (a * aX + b * aY + c * aZ + nd); - double l = d; - d *= d; - if (d < min) { - min = d; - minlsX = aX; minlsY = aY; minlsZ = aZ; - mintX = aX - a*l; mintY = aY - b*l; mintZ = aZ - c*l; - } - } - // segment endpoint B and plane of triangle (when B projects inside V0V1V2) - if (testPointInTriangle(bX, bY, bZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z)) { - if (!computed) { - double v1Y0Y = v1Y - v0Y; - double v2Z0Z = v2Z - v0Z; - double v2Y0Y = v2Y - v0Y; - double v1Z0Z = v1Z - v0Z; - double v2X0X = v2X - v0X; - double v1X0X = v1X - v0X; - a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z; - b = v1Z0Z * v2X0X - v2Z0Z * v1X0X; - c = v1X0X * v2Y0Y - v2X0X * v1Y0Y; - double invLen = Math.invsqrt(a*a + b*b + c*c); - a *= invLen; b *= invLen; c *= invLen; - nd = -(a * v0X + b * v0Y + c * v0Z); - } - d = (a * bX + b * bY + c * bZ + nd); - double l = d; - d *= d; - if (d < min) { - min = d; - minlsX = bX; minlsY = bY; minlsZ = bZ; - mintX = bX - a*l; mintY = bY - b*l; mintZ = bZ - c*l; - } - } - lineSegmentResult.set(minlsX, minlsY, minlsZ); - triangleResult.set(mintX, mintY, mintZ); - return min; - } - - /** - * Determine the closest point on the triangle with the given vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z), (v2X, v2Y, v2Z) - * between that triangle and the given point (pX, pY, pZ) and store that point into the given result. - *

- * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}) - * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20}) - * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point" - * - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v0Z - * the z coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v1Z - * the z coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @param v2Z - * the z coordinate of the third vertex of the triangle - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param pZ - * the y coordinate of the point - * @param result - * will hold the closest point - * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}, - * {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or - * {@link #POINT_ON_TRIANGLE_FACE} - */ - public static int findClosestPointOnTriangle( - double v0X, double v0Y, double v0Z, - double v1X, double v1Y, double v1Z, - double v2X, double v2Y, double v2Z, - double pX, double pY, double pZ, - Vector3d result) { - double abX = v1X - v0X, abY = v1Y - v0Y, abZ = v1Z - v0Z; - double acX = v2X - v0X, acY = v2Y - v0Y, acZ = v2Z - v0Z; - double apX = pX - v0X, apY = pY - v0Y, apZ = pZ - v0Z; - double d1 = abX * apX + abY * apY + abZ * apZ; - double d2 = acX * apX + acY * apY + acZ * apZ; - if (d1 <= 0.0 && d2 <= 0.0) { - result.x = v0X; - result.y = v0Y; - result.z = v0Z; - return POINT_ON_TRIANGLE_VERTEX_0; - } - double bpX = pX - v1X, bpY = pY - v1Y, bpZ = pZ - v1Z; - double d3 = abX * bpX + abY * bpY + abZ * bpZ; - double d4 = acX * bpX + acY * bpY + acZ * bpZ; - if (d3 >= 0.0 && d4 <= d3) { - result.x = v1X; - result.y = v1Y; - result.z = v1Z; - return POINT_ON_TRIANGLE_VERTEX_1; - } - double vc = d1 * d4 - d3 * d2; - if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) { - double v = d1 / (d1 - d3); - result.x = v0X + v * abX; - result.y = v0Y + v * abY; - result.z = v0Z + v * abZ; - return POINT_ON_TRIANGLE_EDGE_01; - } - double cpX = pX - v2X, cpY = pY - v2Y, cpZ = pZ - v2Z; - double d5 = abX * cpX + abY * cpY + abZ * cpZ; - double d6 = acX * cpX + acY * cpY + acZ * cpZ; - if (d6 >= 0.0 && d5 <= d6) { - result.x = v2X; - result.y = v2Y; - result.z = v2Z; - return POINT_ON_TRIANGLE_VERTEX_2; - } - double vb = d5 * d2 - d1 * d6; - if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) { - double w = d2 / (d2 - d6); - result.x = v0X + w * acX; - result.y = v0Y + w * acY; - result.z = v0Z + w * acZ; - return POINT_ON_TRIANGLE_EDGE_20; - } - double va = d3 * d6 - d5 * d4; - if (va <= 0.0 && d4 - d3 >= 0.0 && d5 - d6 >= 0.0) { - double w = (d4 - d3) / (d4 - d3 + d5 - d6); - result.x = v1X + w * (v2X - v1X); - result.y = v1Y + w * (v2Y - v1Y); - result.z = v1Z + w * (v2Z - v1Z); - return POINT_ON_TRIANGLE_EDGE_12; - } - double denom = 1.0 / (va + vb + vc); - double v = vb * denom; - double w = vc * denom; - result.x = v0X + abX * v + acX * w; - result.y = v0Y + abY * v + acY * w; - result.z = v0Z + abZ * v + acZ * w; - return POINT_ON_TRIANGLE_FACE; - } - - /** - * Determine the closest point on the triangle with the vertices v0, v1, v2 - * between that triangle and the given point p and store that point into the given result. - *

- * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}) - * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20}) - * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point" - * - * @param v0 - * the first vertex of the triangle - * @param v1 - * the second vertex of the triangle - * @param v2 - * the third vertex of the triangle - * @param p - * the point - * @param result - * will hold the closest point - * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}, - * {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or - * {@link #POINT_ON_TRIANGLE_FACE} - */ - public static int findClosestPointOnTriangle(Vector3dc v0, Vector3dc v1, Vector3dc v2, Vector3dc p, Vector3d result) { - return findClosestPointOnTriangle(v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), p.x(), p.y(), p.z(), result); - } - - /** - * Find the point on a given rectangle, specified via three of its corners, which is closest to the specified point - * (pX, pY, pZ) and store the result into res. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.4.2 "Closest Point on 3D Rectangle to Point" - * - * @param aX - * the x coordinate of the first corner point of the rectangle - * @param aY - * the y coordinate of the first corner point of the rectangle - * @param aZ - * the z coordinate of the first corner point of the rectangle - * @param bX - * the x coordinate of the second corner point of the rectangle - * @param bY - * the y coordinate of the second corner point of the rectangle - * @param bZ - * the z coordinate of the second corner point of the rectangle - * @param cX - * the x coordinate of the third corner point of the rectangle - * @param cY - * the y coordinate of the third corner point of the rectangle - * @param cZ - * the z coordinate of the third corner point of the rectangle - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param pZ - * the z coordinate of the point - * @param res - * will hold the result - * @return res - */ - public static Vector3d findClosestPointOnRectangle( - double aX, double aY, double aZ, - double bX, double bY, double bZ, - double cX, double cY, double cZ, - double pX, double pY, double pZ, Vector3d res) { - double abX = bX - aX, abY = bY - aY, abZ = bZ - aZ; - double acX = cX - aX, acY = cY - aY, acZ = cZ - aZ; - double dX = pX - aX, dY = pY - aY, dZ = pZ - aZ; - double qX = aX, qY = aY, qZ = aZ; - double dist = dX * abX + dY * abY + dZ * abZ; - double maxdist = abX * abX + abY * abY + abZ * abZ; - if (dist >= maxdist) { - qX += abX; - qY += abY; - qZ += abZ; - } else if (dist > 0.0) { - qX += (dist / maxdist) * abX; - qY += (dist / maxdist) * abY; - qZ += (dist / maxdist) * abZ; - } - dist = dX * acX + dY * acY + dZ * acZ; - maxdist = acX * acX + acY * acY + acZ * acZ; - if (dist >= maxdist) { - qX += acX; - qY += acY; - qZ += acZ; - } else if (dist > 0.0) { - qX += (dist / maxdist) * acX; - qY += (dist / maxdist) * acY; - qZ += (dist / maxdist) * acZ; - } - res.x = qX; - res.y = qY; - res.z = qZ; - return res; - } - - /** - * Determine the point of intersection between a sphere with the given center (centerX, centerY, centerZ) and radius moving - * with the given velocity (velX, velY, velZ) and the triangle specified via its three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z), (v2X, v2Y, v2Z). - *

- * The vertices of the triangle must be specified in counter-clockwise winding order. - *

- * An intersection is only considered if the time of intersection is smaller than the given maxT value. - *

- * Reference: Improved Collision detection and Response - * - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radius - * the radius of the sphere - * @param velX - * the x component of the velocity of the sphere - * @param velY - * the y component of the velocity of the sphere - * @param velZ - * the z component of the velocity of the sphere - * @param v0X - * the x coordinate of the first triangle vertex - * @param v0Y - * the y coordinate of the first triangle vertex - * @param v0Z - * the z coordinate of the first triangle vertex - * @param v1X - * the x coordinate of the second triangle vertex - * @param v1Y - * the y coordinate of the second triangle vertex - * @param v1Z - * the z coordinate of the second triangle vertex - * @param v2X - * the x coordinate of the third triangle vertex - * @param v2Y - * the y coordinate of the third triangle vertex - * @param v2Z - * the z coordinate of the third triangle vertex - * @param epsilon - * a small epsilon when testing spheres that move almost parallel to the triangle - * @param maxT - * the maximum intersection time - * @param pointAndTime - * iff the moving sphere and the triangle intersect, this will hold the point of intersection in the (x, y, z) components - * and the time of intersection in the w component - * @return {@link #POINT_ON_TRIANGLE_FACE} if the intersection point lies on the triangle's face, - * or {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1} or {@link #POINT_ON_TRIANGLE_VERTEX_2} if the intersection point is a vertex, - * or {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12} or {@link #POINT_ON_TRIANGLE_EDGE_20} if the intersection point lies on an edge; - * or 0 if no intersection - */ - public static int intersectSweptSphereTriangle( - double centerX, double centerY, double centerZ, double radius, double velX, double velY, double velZ, - double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z, - double epsilon, double maxT, Vector4d pointAndTime) { - double v10X = v1X - v0X; - double v10Y = v1Y - v0Y; - double v10Z = v1Z - v0Z; - double v20X = v2X - v0X; - double v20Y = v2Y - v0Y; - double v20Z = v2Z - v0Z; - // build triangle plane - double a = v10Y * v20Z - v20Y * v10Z; - double b = v10Z * v20X - v20Z * v10X; - double c = v10X * v20Y - v20X * v10Y; - double d = -(a * v0X + b * v0Y + c * v0Z); - double invLen = Math.invsqrt(a * a + b * b + c * c); - double signedDist = (a * centerX + b * centerY + c * centerZ + d) * invLen; - double dot = (a * velX + b * velY + c * velZ) * invLen; - if (dot < epsilon && dot > -epsilon) - return 0; - double pt0 = (radius - signedDist) / dot; - if (pt0 > maxT) - return 0; - double pt1 = (-radius - signedDist) / dot; - double p0X = centerX - radius * a * invLen + velX * pt0; - double p0Y = centerY - radius * b * invLen + velY * pt0; - double p0Z = centerZ - radius * c * invLen + velZ * pt0; - boolean insideTriangle = testPointInTriangle(p0X, p0Y, p0Z, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z); - if (insideTriangle) { - pointAndTime.x = p0X; - pointAndTime.y = p0Y; - pointAndTime.z = p0Z; - pointAndTime.w = pt0; - return POINT_ON_TRIANGLE_FACE; - } - int isect = 0; - double t0 = maxT; - double A = velX * velX + velY * velY + velZ * velZ; - double radius2 = radius * radius; - // test against v0 - double centerV0X = centerX - v0X; - double centerV0Y = centerY - v0Y; - double centerV0Z = centerZ - v0Z; - double B0 = 2.0 * (velX * centerV0X + velY * centerV0Y + velZ * centerV0Z); - double C0 = centerV0X * centerV0X + centerV0Y * centerV0Y + centerV0Z * centerV0Z - radius2; - double root0 = computeLowestRoot(A, B0, C0, t0); - if (root0 < t0) { - pointAndTime.x = v0X; - pointAndTime.y = v0Y; - pointAndTime.z = v0Z; - pointAndTime.w = root0; - t0 = root0; - isect = POINT_ON_TRIANGLE_VERTEX_0; - } - // test against v1 - double centerV1X = centerX - v1X; - double centerV1Y = centerY - v1Y; - double centerV1Z = centerZ - v1Z; - double centerV1Len = centerV1X * centerV1X + centerV1Y * centerV1Y + centerV1Z * centerV1Z; - double B1 = 2.0 * (velX * centerV1X + velY * centerV1Y + velZ * centerV1Z); - double C1 = centerV1Len - radius2; - double root1 = computeLowestRoot(A, B1, C1, t0); - if (root1 < t0) { - pointAndTime.x = v1X; - pointAndTime.y = v1Y; - pointAndTime.z = v1Z; - pointAndTime.w = root1; - t0 = root1; - isect = POINT_ON_TRIANGLE_VERTEX_1; - } - // test against v2 - double centerV2X = centerX - v2X; - double centerV2Y = centerY - v2Y; - double centerV2Z = centerZ - v2Z; - double B2 = 2.0 * (velX * centerV2X + velY * centerV2Y + velZ * centerV2Z); - double C2 = centerV2X * centerV2X + centerV2Y * centerV2Y + centerV2Z * centerV2Z - radius2; - double root2 = computeLowestRoot(A, B2, C2, t0); - if (root2 < t0) { - pointAndTime.x = v2X; - pointAndTime.y = v2Y; - pointAndTime.z = v2Z; - pointAndTime.w = root2; - t0 = root2; - isect = POINT_ON_TRIANGLE_VERTEX_2; - } - double velLen = velX * velX + velY * velY + velZ * velZ; - // test against edge10 - double len10 = v10X * v10X + v10Y * v10Y + v10Z * v10Z; - double baseTo0Len = centerV0X * centerV0X + centerV0Y * centerV0Y + centerV0Z * centerV0Z; - double v10Vel = (v10X * velX + v10Y * velY + v10Z * velZ); - double A10 = len10 * -velLen + v10Vel * v10Vel; - double v10BaseTo0 = v10X * -centerV0X + v10Y * -centerV0Y + v10Z * -centerV0Z; - double velBaseTo0 = velX * -centerV0X + velY * -centerV0Y + velZ * -centerV0Z; - double B10 = len10 * 2 * velBaseTo0 - 2 * v10Vel * v10BaseTo0; - double C10 = len10 * (radius2 - baseTo0Len) + v10BaseTo0 * v10BaseTo0; - double root10 = computeLowestRoot(A10, B10, C10, t0); - double f10 = (v10Vel * root10 - v10BaseTo0) / len10; - if (f10 >= 0.0 && f10 <= 1.0 && root10 < t0) { - pointAndTime.x = v0X + f10 * v10X; - pointAndTime.y = v0Y + f10 * v10Y; - pointAndTime.z = v0Z + f10 * v10Z; - pointAndTime.w = root10; - t0 = root10; - isect = POINT_ON_TRIANGLE_EDGE_01; - } - // test against edge20 - double len20 = v20X * v20X + v20Y * v20Y + v20Z * v20Z; - double v20Vel = (v20X * velX + v20Y * velY + v20Z * velZ); - double A20 = len20 * -velLen + v20Vel * v20Vel; - double v20BaseTo0 = v20X * -centerV0X + v20Y * -centerV0Y + v20Z * -centerV0Z; - double B20 = len20 * 2 * velBaseTo0 - 2 * v20Vel * v20BaseTo0; - double C20 = len20 * (radius2 - baseTo0Len) + v20BaseTo0 * v20BaseTo0; - double root20 = computeLowestRoot(A20, B20, C20, t0); - double f20 = (v20Vel * root20 - v20BaseTo0) / len20; - if (f20 >= 0.0 && f20 <= 1.0 && root20 < pt1) { - pointAndTime.x = v0X + f20 * v20X; - pointAndTime.y = v0Y + f20 * v20Y; - pointAndTime.z = v0Z + f20 * v20Z; - pointAndTime.w = root20; - t0 = root20; - isect = POINT_ON_TRIANGLE_EDGE_20; - } - // test against edge21 - double v21X = v2X - v1X; - double v21Y = v2Y - v1Y; - double v21Z = v2Z - v1Z; - double len21 = v21X * v21X + v21Y * v21Y + v21Z * v21Z; - double baseTo1Len = centerV1Len; - double v21Vel = (v21X * velX + v21Y * velY + v21Z * velZ); - double A21 = len21 * -velLen + v21Vel * v21Vel; - double v21BaseTo1 = v21X * -centerV1X + v21Y * -centerV1Y + v21Z * -centerV1Z; - double velBaseTo1 = velX * -centerV1X + velY * -centerV1Y + velZ * -centerV1Z; - double B21 = len21 * 2 * velBaseTo1 - 2 * v21Vel * v21BaseTo1; - double C21 = len21 * (radius2 - baseTo1Len) + v21BaseTo1 * v21BaseTo1; - double root21 = computeLowestRoot(A21, B21, C21, t0); - double f21 = (v21Vel * root21 - v21BaseTo1) / len21; - if (f21 >= 0.0 && f21 <= 1.0 && root21 < t0) { - pointAndTime.x = v1X + f21 * v21X; - pointAndTime.y = v1Y + f21 * v21Y; - pointAndTime.z = v1Z + f21 * v21Z; - pointAndTime.w = root21; - t0 = root21; - isect = POINT_ON_TRIANGLE_EDGE_12; - } - return isect; - } - - /** - * Compute the lowest root for t in the quadratic equation a*t*t + b*t + c = 0. - *

- * This is a helper method for {@link #intersectSweptSphereTriangle} - * - * @param a - * the quadratic factor - * @param b - * the linear factor - * @param c - * the constant - * @param maxR - * the maximum expected root - * @return the lowest of the two roots of the quadratic equation; or {@link Double#POSITIVE_INFINITY} - */ - private static double computeLowestRoot(double a, double b, double c, double maxR) { - double determinant = b * b - 4.0 * a * c; - if (determinant < 0.0) - return Double.POSITIVE_INFINITY; - double sqrtD = Math.sqrt(determinant); - double r1 = (-b - sqrtD) / (2.0 * a); - double r2 = (-b + sqrtD) / (2.0 * a); - if (r1 > r2) { - double temp = r2; - r2 = r1; - r1 = temp; - } - if (r1 > 0.0 && r1 < maxR) { - return r1; - } - if (r2 > 0.0 && r2 < maxR) { - return r2; - } - return Double.POSITIVE_INFINITY; - } - - /** - * Test whether the projection of the given point (pX, pY, pZ) lies inside of the triangle defined by the three vertices - * (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z). - *

- * Reference: Improved Collision detection and Response - * - * @param pX - * the x coordinate of the point to test - * @param pY - * the y coordinate of the point to test - * @param pZ - * the z coordinate of the point to test - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @return true if the projection of the given point lies inside of the given triangle; false otherwise - */ - public static boolean testPointInTriangle(double pX, double pY, double pZ, double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z) { - double e10X = v1X - v0X; - double e10Y = v1Y - v0Y; - double e10Z = v1Z - v0Z; - double e20X = v2X - v0X; - double e20Y = v2Y - v0Y; - double e20Z = v2Z - v0Z; - double a = e10X * e10X + e10Y * e10Y + e10Z * e10Z; - double b = e10X * e20X + e10Y * e20Y + e10Z * e20Z; - double c = e20X * e20X + e20Y * e20Y + e20Z * e20Z; - double ac_bb = a * c - b * b; - double vpX = pX - v0X; - double vpY = pY - v0Y; - double vpZ = pZ - v0Z; - double d = vpX * e10X + vpY * e10Y + vpZ * e10Z; - double e = vpX * e20X + vpY * e20Y + vpZ * e20Z; - double x = d * c - e * b; - double y = e * a - d * b; - double z = x + y - ac_bb; - return ((Runtime.doubleToLongBits(z) & ~(Runtime.doubleToLongBits(x) | Runtime.doubleToLongBits(y))) & 0x8000000000000000L) != 0L; - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and normalized direction (dirX, dirY, dirZ) - * intersects the given sphere with center (centerX, centerY, centerZ) and square radius radiusSquared, - * and store the values of the parameter t in the ray equation p(t) = origin + t * dir for both points (near - * and far) of intersections into the given result vector. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's normalized direction - * @param dirY - * the y coordinate of the ray's normalized direction - * @param dirZ - * the z coordinate of the ray's normalized direction - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radiusSquared - * the sphere radius squared - * @param result - * a vector that will contain the values of the parameter t in the ray equation - * p(t) = origin + t * dir for both points (near, far) of intersections with the sphere - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean intersectRaySphere(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, - double centerX, double centerY, double centerZ, double radiusSquared, Vector2d result) { - double Lx = centerX - originX; - double Ly = centerY - originY; - double Lz = centerZ - originZ; - double tca = Lx * dirX + Ly * dirY + Lz * dirZ; - double d2 = Lx * Lx + Ly * Ly + Lz * Lz - tca * tca; - if (d2 > radiusSquared) - return false; - double thc = Math.sqrt(radiusSquared - d2); - double t0 = tca - thc; - double t1 = tca + thc; - if (t0 < t1 && t1 >= 0.0) { - result.x = t0; - result.y = t1; - return true; - } - return false; - } - - /** - * Test whether the ray with the given origin and normalized direction dir - * intersects the sphere with the given center and square radius radiusSquared, - * and store the values of the parameter t in the ray equation p(t) = origin + t * dir for both points (near - * and far) of intersections into the given result vector. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param origin - * the ray's origin - * @param dir - * the ray's normalized direction - * @param center - * the sphere's center - * @param radiusSquared - * the sphere radius squared - * @param result - * a vector that will contain the values of the parameter t in the ray equation - * p(t) = origin + t * dir for both points (near, far) of intersections with the sphere - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean intersectRaySphere(Vector3dc origin, Vector3dc dir, Vector3dc center, double radiusSquared, Vector2d result) { - return intersectRaySphere(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), center.x(), center.y(), center.z(), radiusSquared, result); - } - - /** - * Test whether the given ray intersects the given sphere, - * and store the values of the parameter t in the ray equation p(t) = origin + t * dir for both points (near - * and far) of intersections into the given result vector. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param ray - * the ray - * @param sphere - * the sphere - * @param result - * a vector that will contain the values of the parameter t in the ray equation - * p(t) = origin + t * dir for both points (near, far) of intersections with the sphere - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean intersectRaySphere(Rayd ray, Spheref sphere, Vector2d result) { - return intersectRaySphere(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, sphere.x, sphere.y, sphere.z, sphere.r*sphere.r, result); - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and normalized direction (dirX, dirY, dirZ) - * intersects the given sphere with center (centerX, centerY, centerZ) and square radius radiusSquared. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's normalized direction - * @param dirY - * the y coordinate of the ray's normalized direction - * @param dirZ - * the z coordinate of the ray's normalized direction - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radiusSquared - * the sphere radius squared - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean testRaySphere(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, - double centerX, double centerY, double centerZ, double radiusSquared) { - double Lx = centerX - originX; - double Ly = centerY - originY; - double Lz = centerZ - originZ; - double tca = Lx * dirX + Ly * dirY + Lz * dirZ; - double d2 = Lx * Lx + Ly * Ly + Lz * Lz - tca * tca; - if (d2 > radiusSquared) - return false; - double thc = Math.sqrt(radiusSquared - d2); - double t0 = tca - thc; - double t1 = tca + thc; - return t0 < t1 && t1 >= 0.0; - } - - /** - * Test whether the ray with the given origin and normalized direction dir - * intersects the sphere with the given center and square radius. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param origin - * the ray's origin - * @param dir - * the ray's normalized direction - * @param center - * the sphere's center - * @param radiusSquared - * the sphere radius squared - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean testRaySphere(Vector3dc origin, Vector3dc dir, Vector3dc center, double radiusSquared) { - return testRaySphere(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), center.x(), center.y(), center.z(), radiusSquared); - } - - /** - * Test whether the given ray intersects the given sphere. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param ray - * the ray - * @param sphere - * the sphere - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean testRaySphere(Rayd ray, Spheref sphere) { - return testRaySphere(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, sphere.x, sphere.y, sphere.z, sphere.r*sphere.r); - } - - /** - * Test whether the line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects the given sphere with center (centerX, centerY, centerZ) and square radius radiusSquared. - *

- * Reference: http://paulbourke.net/ - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radiusSquared - * the sphere radius squared - * @return true if the line segment intersects the sphere; false otherwise - */ - public static boolean testLineSegmentSphere(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z, - double centerX, double centerY, double centerZ, double radiusSquared) { - double dX = p1X - p0X; - double dY = p1Y - p0Y; - double dZ = p1Z - p0Z; - double nom = (centerX - p0X) * dX + (centerY - p0Y) * dY + (centerZ - p0Z) * dZ; - double den = dX * dX + dY * dY + dZ * dZ; - double u = nom / den; - if (u < 0.0) { - dX = p0X - centerX; - dY = p0Y - centerY; - dZ = p0Z - centerZ; - } else if (u > 1.0) { - dX = p1X - centerX; - dY = p1Y - centerY; - dZ = p1Z - centerZ; - } else { // has to be >= 0 and <= 1 - double pX = p0X + u * dX; - double pY = p0Y + u * dY; - double pZ = p0Z + u * dZ; - dX = pX - centerX; - dY = pY - centerY; - dZ = pZ - centerZ; - } - double dist = dX * dX + dY * dY + dZ * dZ; - return dist <= radiusSquared; - } - - /** - * Test whether the line segment with the end points p0 and p1 - * intersects the given sphere with center center and square radius radiusSquared. - *

- * Reference: http://paulbourke.net/ - * - * @param p0 - * the line segment's first end point - * @param p1 - * the line segment's second end point - * @param center - * the sphere's center - * @param radiusSquared - * the sphere radius squared - * @return true if the line segment intersects the sphere; false otherwise - */ - public static boolean testLineSegmentSphere(Vector3dc p0, Vector3dc p1, Vector3dc center, double radiusSquared) { - return testLineSegmentSphere(p0.x(), p0.y(), p0.z(), p1.x(), p1.y(), p1.z(), center.x(), center.y(), center.z(), radiusSquared); - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the axis-aligned box given as its minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ), - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAab(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector2d) - * @see RayAabIntersection - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param minX - * the x coordinate of the minimum corner of the axis-aligned box - * @param minY - * the y coordinate of the minimum corner of the axis-aligned box - * @param minZ - * the z coordinate of the minimum corner of the axis-aligned box - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned box - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned box - * @param maxZ - * the y coordinate of the maximum corner of the axis-aligned box - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean intersectRayAab(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, - double minX, double minY, double minZ, double maxX, double maxY, double maxZ, Vector2d result) { - double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY, invDirZ = 1.0 / dirZ; - double tNear, tFar, tymin, tymax, tzmin, tzmax; - if (invDirX >= 0.0) { - tNear = (minX - originX) * invDirX; - tFar = (maxX - originX) * invDirX; - } else { - tNear = (maxX - originX) * invDirX; - tFar = (minX - originX) * invDirX; - } - if (invDirY >= 0.0) { - tymin = (minY - originY) * invDirY; - tymax = (maxY - originY) * invDirY; - } else { - tymin = (maxY - originY) * invDirY; - tymax = (minY - originY) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return false; - if (invDirZ >= 0.0) { - tzmin = (minZ - originZ) * invDirZ; - tzmax = (maxZ - originZ) * invDirZ; - } else { - tzmin = (maxZ - originZ) * invDirZ; - tzmax = (minZ - originZ) * invDirZ; - } - if (tNear > tzmax || tzmin > tFar) - return false; - tNear = tymin > tNear || Double.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Double.isNaN(tFar) ? tymax : tFar; - tNear = tzmin > tNear ? tzmin : tNear; - tFar = tzmax < tFar ? tzmax : tFar; - if (tNear < tFar && tFar >= 0.0) { - result.x = tNear; - result.y = tFar; - return true; - } - return false; - } - - /** - * Test whether the ray with the given origin and direction dir - * intersects the axis-aligned box specified as its minimum corner min and maximum corner max, - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection.. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d) - * @see RayAabIntersection - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean intersectRayAab(Vector3dc origin, Vector3dc dir, Vector3dc min, Vector3dc max, Vector2d result) { - return intersectRayAab(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), result); - } - - /** - * Test whether the given ray intersects given the axis-aligned box - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection.. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d) - * @see RayAabIntersection - * - * @param ray - * the ray - * @param aabb - * the AABB - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean intersectRayAab(Rayd ray, AABBd aabb, Vector2d result) { - return intersectRayAab(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, result); - } - - /** - * Determine whether the undirected line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects the axis-aligned box given as its minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ), - * and return the values of the parameter t in the ray equation p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside the axis-aligned box. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectLineSegmentAab(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector2d) - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param minX - * the x coordinate of one corner of the axis-aligned box - * @param minY - * the y coordinate of one corner of the axis-aligned box - * @param minZ - * the z coordinate of one corner of the axis-aligned box - * @param maxX - * the x coordinate of the opposite corner of the axis-aligned box - * @param maxY - * the y coordinate of the opposite corner of the axis-aligned box - * @param maxZ - * the y coordinate of the opposite corner of the axis-aligned box - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects the axis-aligned box - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned box; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned box; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned box; or - * {@link #TWO_INTERSECTION} if the line segment intersects two sides of the axis-aligned box - * or lies on an edge or a side of the box - */ - public static int intersectLineSegmentAab(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z, - double minX, double minY, double minZ, double maxX, double maxY, double maxZ, Vector2d result) { - double dirX = p1X - p0X, dirY = p1Y - p0Y, dirZ = p1Z - p0Z; - double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY, invDirZ = 1.0 / dirZ; - double tNear, tFar, tymin, tymax, tzmin, tzmax; - if (invDirX >= 0.0) { - tNear = (minX - p0X) * invDirX; - tFar = (maxX - p0X) * invDirX; - } else { - tNear = (maxX - p0X) * invDirX; - tFar = (minX - p0X) * invDirX; - } - if (invDirY >= 0.0) { - tymin = (minY - p0Y) * invDirY; - tymax = (maxY - p0Y) * invDirY; - } else { - tymin = (maxY - p0Y) * invDirY; - tymax = (minY - p0Y) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return OUTSIDE; - if (invDirZ >= 0.0) { - tzmin = (minZ - p0Z) * invDirZ; - tzmax = (maxZ - p0Z) * invDirZ; - } else { - tzmin = (maxZ - p0Z) * invDirZ; - tzmax = (minZ - p0Z) * invDirZ; - } - if (tNear > tzmax || tzmin > tFar) - return OUTSIDE; - tNear = tymin > tNear || Double.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Double.isNaN(tFar) ? tymax : tFar; - tNear = tzmin > tNear ? tzmin : tNear; - tFar = tzmax < tFar ? tzmax : tFar; - int type = OUTSIDE; - if (tNear <= tFar && tNear <= 1.0f && tFar >= 0.0f) { - if (tNear >= 0.0f && tFar > 1.0f) { - tFar = tNear; - type = ONE_INTERSECTION; - } else if (tNear < 0.0f && tFar <= 1.0f) { - tNear = tFar; - type = ONE_INTERSECTION; - } else if (tNear < 0.0f && tFar > 1.0f) { - type = INSIDE; - } else { - type = TWO_INTERSECTION; - } - result.x = tNear; - result.y = tFar; - } - return type; - } - - /** - * Determine whether the undirected line segment with the end points p0 and p1 - * intersects the axis-aligned box given as its minimum corner min and maximum corner max, - * and return the values of the parameter t in the ray equation p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside the axis-aligned box. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectLineSegmentAab(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector2d) - * - * @param p0 - * the line segment's first end point - * @param p1 - * the line segment's second end point - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects the axis-aligned box - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned box; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned box; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned box; or - * {@link #TWO_INTERSECTION} if the line segment intersects two sides of the axis-aligned box - * or lies on an edge or a side of the box - */ - public static int intersectLineSegmentAab(Vector3dc p0, Vector3dc p1, Vector3dc min, Vector3dc max, Vector2d result) { - return intersectLineSegmentAab(p0.x(), p0.y(), p0.z(), p1.x(), p1.y(), p1.z(), min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), result); - } - - /** - * Determine whether the given undirected line segment intersects the given axis-aligned box, - * and return the values of the parameter t in the ray equation p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside the axis-aligned box. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectLineSegmentAab(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector2d) - * - * @param lineSegment - * the line segment - * @param aabb - * the AABB - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects the axis-aligned box - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned box; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned box; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned box; or - * {@link #TWO_INTERSECTION} if the line segment intersects two sides of the axis-aligned box - * or lies on an edge or a side of the box - */ - public static int intersectLineSegmentAab(LineSegmentf lineSegment, AABBd aabb, Vector2d result) { - return intersectLineSegmentAab(lineSegment.aX, lineSegment.aY, lineSegment.aZ, lineSegment.bX, lineSegment.bY, lineSegment.bZ, aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, result); - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the axis-aligned box given as its minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ). - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAab(Vector3dc, Vector3dc, Vector3dc, Vector3dc) - * @see RayAabIntersection - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param minX - * the x coordinate of the minimum corner of the axis-aligned box - * @param minY - * the y coordinate of the minimum corner of the axis-aligned box - * @param minZ - * the z coordinate of the minimum corner of the axis-aligned box - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned box - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned box - * @param maxZ - * the y coordinate of the maximum corner of the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean testRayAab(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, - double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { - double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY, invDirZ = 1.0 / dirZ; - double tNear, tFar, tymin, tymax, tzmin, tzmax; - if (invDirX >= 0.0) { - tNear = (minX - originX) * invDirX; - tFar = (maxX - originX) * invDirX; - } else { - tNear = (maxX - originX) * invDirX; - tFar = (minX - originX) * invDirX; - } - if (invDirY >= 0.0) { - tymin = (minY - originY) * invDirY; - tymax = (maxY - originY) * invDirY; - } else { - tymin = (maxY - originY) * invDirY; - tymax = (minY - originY) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return false; - if (invDirZ >= 0.0) { - tzmin = (minZ - originZ) * invDirZ; - tzmax = (maxZ - originZ) * invDirZ; - } else { - tzmin = (maxZ - originZ) * invDirZ; - tzmax = (minZ - originZ) * invDirZ; - } - if (tNear > tzmax || tzmin > tFar) - return false; - tNear = tymin > tNear || Double.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Double.isNaN(tFar) ? tymax : tFar; - tNear = tzmin > tNear ? tzmin : tNear; - tFar = tzmax < tFar ? tzmax : tFar; - return tNear < tFar && tFar >= 0.0; - } - - /** - * Test whether the ray with the given origin and direction dir - * intersects the axis-aligned box specified as its minimum corner min and maximum corner max. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAab(double, double, double, double, double, double, double, double, double, double, double, double) - * @see RayAabIntersection - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean testRayAab(Vector3dc origin, Vector3dc dir, Vector3dc min, Vector3dc max) { - return testRayAab(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), min.x(), min.y(), min.z(), max.x(), max.y(), max.z()); - } - - /** - * Test whether the given ray intersects the given axis-aligned box. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAab(double, double, double, double, double, double, double, double, double, double, double, double) - * @see RayAabIntersection - * - * @param ray - * the ray - * @param aabb - * the AABB - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean testRayAab(Rayd ray, AABBd aabb) { - return testRayAab(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ); - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the frontface of the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z). - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test implements backface culling, that is, it will return false when the triangle is in clockwise - * winding order assuming a right-handed coordinate system when seen along the ray's direction, even if the ray intersects the triangle. - * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings. - * - * @see #testRayTriangleFront(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3dc, double) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return true if the given ray intersects the frontface of the triangle; false otherwise - */ - public static boolean testRayTriangleFront(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, - double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z, - double epsilon) { - double edge1X = v1X - v0X; - double edge1Y = v1Y - v0Y; - double edge1Z = v1Z - v0Z; - double edge2X = v2X - v0X; - double edge2Y = v2Y - v0Y; - double edge2Z = v2Z - v0Z; - double pvecX = dirY * edge2Z - dirZ * edge2Y; - double pvecY = dirZ * edge2X - dirX * edge2Z; - double pvecZ = dirX * edge2Y - dirY * edge2X; - double det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ; - if (det < epsilon) - return false; - double tvecX = originX - v0X; - double tvecY = originY - v0Y; - double tvecZ = originZ - v0Z; - double u = (tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ); - if (u < 0.0 || u > det) - return false; - double qvecX = tvecY * edge1Z - tvecZ * edge1Y; - double qvecY = tvecZ * edge1X - tvecX * edge1Z; - double qvecZ = tvecX * edge1Y - tvecY * edge1X; - double v = (dirX * qvecX + dirY * qvecY + dirZ * qvecZ); - if (v < 0.0 || u + v > det) - return false; - double invDet = 1.0 / det; - double t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet; - return t >= epsilon; - } - - /** - * Test whether the ray with the given origin and the given dir intersects the frontface of the triangle consisting of the three vertices - * v0, v1 and v2. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test implements backface culling, that is, it will return false when the triangle is in clockwise - * winding order assuming a right-handed coordinate system when seen along the ray's direction, even if the ray intersects the triangle. - * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings. - * - * @see #testRayTriangleFront(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return true if the given ray intersects the frontface of the triangle; false otherwise - */ - public static boolean testRayTriangleFront(Vector3dc origin, Vector3dc dir, Vector3dc v0, Vector3dc v1, Vector3dc v2, double epsilon) { - return testRayTriangleFront(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon); - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z). - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle. - * - * @see #testRayTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3dc, double) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return true if the given ray intersects the frontface of the triangle; false otherwise - */ - public static boolean testRayTriangle(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, - double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z, - double epsilon) { - double edge1X = v1X - v0X; - double edge1Y = v1Y - v0Y; - double edge1Z = v1Z - v0Z; - double edge2X = v2X - v0X; - double edge2Y = v2Y - v0Y; - double edge2Z = v2Z - v0Z; - double pvecX = dirY * edge2Z - dirZ * edge2Y; - double pvecY = dirZ * edge2X - dirX * edge2Z; - double pvecZ = dirX * edge2Y - dirY * edge2X; - double det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ; - if (det > -epsilon && det < epsilon) - return false; - double tvecX = originX - v0X; - double tvecY = originY - v0Y; - double tvecZ = originZ - v0Z; - double invDet = 1.0 / det; - double u = (tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ) * invDet; - if (u < 0.0 || u > 1.0) - return false; - double qvecX = tvecY * edge1Z - tvecZ * edge1Y; - double qvecY = tvecZ * edge1X - tvecX * edge1Z; - double qvecZ = tvecX * edge1Y - tvecY * edge1X; - double v = (dirX * qvecX + dirY * qvecY + dirZ * qvecZ) * invDet; - if (v < 0.0 || u + v > 1.0) - return false; - double t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet; - return t >= epsilon; - } - - /** - * Test whether the ray with the given origin and the given dir intersects the frontface of the triangle consisting of the three vertices - * v0, v1 and v2. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle. - * - * @see #testRayTriangle(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return true if the given ray intersects the frontface of the triangle; false otherwise - */ - public static boolean testRayTriangle(Vector3dc origin, Vector3dc dir, Vector3dc v0, Vector3dc v1, Vector3dc v2, double epsilon) { - return testRayTriangle(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon); - } - - /** - * Determine whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the frontface of the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z) - * and return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test implements backface culling, that is, it will return false when the triangle is in clockwise - * winding order assuming a right-handed coordinate system when seen along the ray's direction, even if the ray intersects the triangle. - * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings. - * - * @see #testRayTriangleFront(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3dc, double) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection - * if the ray intersects the frontface of the triangle; -1.0 otherwise - */ - public static double intersectRayTriangleFront(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, - double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z, - double epsilon) { - double edge1X = v1X - v0X; - double edge1Y = v1Y - v0Y; - double edge1Z = v1Z - v0Z; - double edge2X = v2X - v0X; - double edge2Y = v2Y - v0Y; - double edge2Z = v2Z - v0Z; - double pvecX = dirY * edge2Z - dirZ * edge2Y; - double pvecY = dirZ * edge2X - dirX * edge2Z; - double pvecZ = dirX * edge2Y - dirY * edge2X; - double det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ; - if (det <= epsilon) - return -1.0; - double tvecX = originX - v0X; - double tvecY = originY - v0Y; - double tvecZ = originZ - v0Z; - double u = tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ; - if (u < 0.0 || u > det) - return -1.0; - double qvecX = tvecY * edge1Z - tvecZ * edge1Y; - double qvecY = tvecZ * edge1X - tvecX * edge1Z; - double qvecZ = tvecX * edge1Y - tvecY * edge1X; - double v = dirX * qvecX + dirY * qvecY + dirZ * qvecZ; - if (v < 0.0 || u + v > det) - return -1.0; - double invDet = 1.0 / det; - double t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet; - return t; - } - - /** - * Determine whether the ray with the given origin and the given dir intersects the frontface of the triangle consisting of the three vertices - * v0, v1 and v2 and return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test implements backface culling, that is, it will return false when the triangle is in clockwise - * winding order assuming a right-handed coordinate system when seen along the ray's direction, even if the ray intersects the triangle. - * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings. - * - * @see #intersectRayTriangleFront(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection - * if the ray intersects the frontface of the triangle; -1.0 otherwise - */ - public static double intersectRayTriangleFront(Vector3dc origin, Vector3dc dir, Vector3dc v0, Vector3dc v1, Vector3dc v2, double epsilon) { - return intersectRayTriangleFront(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon); - } - - /** - * Determine whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z) - * and return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle. - * - * @see #testRayTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3dc, double) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection - * if the ray intersects the triangle; -1.0 otherwise - */ - public static double intersectRayTriangle(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, - double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z, - double epsilon) { - double edge1X = v1X - v0X; - double edge1Y = v1Y - v0Y; - double edge1Z = v1Z - v0Z; - double edge2X = v2X - v0X; - double edge2Y = v2Y - v0Y; - double edge2Z = v2Z - v0Z; - double pvecX = dirY * edge2Z - dirZ * edge2Y; - double pvecY = dirZ * edge2X - dirX * edge2Z; - double pvecZ = dirX * edge2Y - dirY * edge2X; - double det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ; - if (det > -epsilon && det < epsilon) - return -1.0; - double tvecX = originX - v0X; - double tvecY = originY - v0Y; - double tvecZ = originZ - v0Z; - double invDet = 1.0 / det; - double u = (tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ) * invDet; - if (u < 0.0 || u > 1.0) - return -1.0; - double qvecX = tvecY * edge1Z - tvecZ * edge1Y; - double qvecY = tvecZ * edge1X - tvecX * edge1Z; - double qvecZ = tvecX * edge1Y - tvecY * edge1X; - double v = (dirX * qvecX + dirY * qvecY + dirZ * qvecZ) * invDet; - if (v < 0.0 || u + v > 1.0) - return -1.0; - double t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet; - return t; - } - - /** - * Determine whether the ray with the given origin and the given dir intersects the triangle consisting of the three vertices - * v0, v1 and v2 and return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle. - * - * @see #intersectRayTriangle(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection - * if the ray intersects the triangle; -1.0 otherwise - */ - public static double intersectRayTriangle(Vector3dc origin, Vector3dc dir, Vector3dc v0, Vector3dc v1, Vector3dc v2, double epsilon) { - return intersectRayTriangle(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon); - } - - /** - * Test whether the line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z), - * regardless of the winding order of the triangle or the direction of the line segment between its two end points. - *

- * Reference: - * Fast, Minimum Storage Ray/Triangle Intersection - * - * @see #testLineSegmentTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3dc, double) - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing line segments that are almost parallel to the triangle - * @return true if the given line segment intersects the triangle; false otherwise - */ - public static boolean testLineSegmentTriangle(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z, - double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z, - double epsilon) { - double dirX = p1X - p0X; - double dirY = p1Y - p0Y; - double dirZ = p1Z - p0Z; - double t = intersectRayTriangle(p0X, p0Y, p0Z, dirX, dirY, dirZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z, epsilon); - return t >= 0.0 && t <= 1.0; - } - - /** - * Test whether the line segment with the end points p0 and p1 - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z), - * regardless of the winding order of the triangle or the direction of the line segment between its two end points. - *

- * Reference: - * Fast, Minimum Storage Ray/Triangle Intersection - * - * @see #testLineSegmentTriangle(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double) - * - * @param p0 - * the line segment's first end point - * @param p1 - * the line segment's second end point - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing line segments that are almost parallel to the triangle - * @return true if the given line segment intersects the triangle; false otherwise - */ - public static boolean testLineSegmentTriangle(Vector3dc p0, Vector3dc p1, Vector3dc v0, Vector3dc v1, Vector3dc v2, double epsilon) { - return testLineSegmentTriangle(p0.x(), p0.y(), p0.z(), p1.x(), p1.y(), p1.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon); - } - - /** - * Determine whether the line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z), - * regardless of the winding order of the triangle or the direction of the line segment between its two end points, - * and return the point of intersection. - *

- * Reference: - * Fast, Minimum Storage Ray/Triangle Intersection - * - * @see #intersectLineSegmentTriangle(Vector3dc, Vector3dc, Vector3dc, Vector3dc, Vector3dc, double, Vector3d) - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing line segments that are almost parallel to the triangle - * @param intersectionPoint - * the point of intersection - * @return true if the given line segment intersects the triangle; false otherwise - */ - public static boolean intersectLineSegmentTriangle(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z, - double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z, - double epsilon, Vector3d intersectionPoint) { - double dirX = p1X - p0X; - double dirY = p1Y - p0Y; - double dirZ = p1Z - p0Z; - double t = intersectRayTriangle(p0X, p0Y, p0Z, dirX, dirY, dirZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z, epsilon); - if (t >= 0.0 && t <= 1.0) { - intersectionPoint.x = p0X + dirX * t; - intersectionPoint.y = p0Y + dirY * t; - intersectionPoint.z = p0Z + dirZ * t; - return true; - } - return false; - } - - /** - * Determine whether the line segment with the end points p0 and p1 - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z), - * regardless of the winding order of the triangle or the direction of the line segment between its two end points, - * and return the point of intersection. - *

- * Reference: - * Fast, Minimum Storage Ray/Triangle Intersection - * - * @see #intersectLineSegmentTriangle(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, Vector3d) - * - * @param p0 - * the line segment's first end point - * @param p1 - * the line segment's second end point - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing line segments that are almost parallel to the triangle - * @param intersectionPoint - * the point of intersection - * @return true if the given line segment intersects the triangle; false otherwise - */ - public static boolean intersectLineSegmentTriangle(Vector3dc p0, Vector3dc p1, Vector3dc v0, Vector3dc v1, Vector3dc v2, double epsilon, Vector3d intersectionPoint) { - return intersectLineSegmentTriangle(p0.x(), p0.y(), p0.z(), p1.x(), p1.y(), p1.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon, intersectionPoint); - } - - /** - * Determine whether the line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects the plane given as the general plane equation a*x + b*y + c*z + d = 0, - * and return the point of intersection. - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param intersectionPoint - * the point of intersection - * @return true if the given line segment intersects the plane; false otherwise - */ - public static boolean intersectLineSegmentPlane(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z, - double a, double b, double c, double d, Vector3d intersectionPoint) { - double dirX = p1X - p0X; - double dirY = p1Y - p0Y; - double dirZ = p1Z - p0Z; - double denom = a * dirX + b * dirY + c * dirZ; - double t = -(a * p0X + b * p0Y + c * p0Z + d) / denom; - if (t >= 0.0 && t <= 1.0) { - intersectionPoint.x = p0X + t * dirX; - intersectionPoint.y = p0Y + t * dirY; - intersectionPoint.z = p0Z + t * dirZ; - return true; - } - return false; - } - - /** - * Test whether the line with the general line equation a*x + b*y + c = 0 intersects the circle with center - * (centerX, centerY) and radius. - *

- * Reference: http://math.stackexchange.com - * - * @param a - * the x factor in the line equation - * @param b - * the y factor in the line equation - * @param c - * the constant in the line equation - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radius - * the radius of the circle - * @return true iff the line intersects the circle; false otherwise - */ - public static boolean testLineCircle(double a, double b, double c, double centerX, double centerY, double radius) { - double denom = Math.sqrt(a * a + b * b); - double dist = (a * centerX + b * centerY + c) / denom; - return -radius <= dist && dist <= radius; - } - - /** - * Test whether the line with the general line equation a*x + b*y + c = 0 intersects the circle with center - * (centerX, centerY) and radius, and store the center of the line segment of - * intersection in the (x, y) components of the supplied vector and the half-length of that line segment in the z component. - *

- * Reference: http://math.stackexchange.com - * - * @param a - * the x factor in the line equation - * @param b - * the y factor in the line equation - * @param c - * the constant in the line equation - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radius - * the radius of the circle - * @param intersectionCenterAndHL - * will hold the center of the line segment of intersection in the (x, y) components and the half-length in the z component - * @return true iff the line intersects the circle; false otherwise - */ - public static boolean intersectLineCircle(double a, double b, double c, double centerX, double centerY, double radius, Vector3d intersectionCenterAndHL) { - double invDenom = Math.invsqrt(a * a + b * b); - double dist = (a * centerX + b * centerY + c) * invDenom; - if (-radius <= dist && dist <= radius) { - intersectionCenterAndHL.x = centerX + dist * a * invDenom; - intersectionCenterAndHL.y = centerY + dist * b * invDenom; - intersectionCenterAndHL.z = Math.sqrt(radius * radius - dist * dist); - return true; - } - return false; - } - - /** - * Test whether the line defined by the two points (x0, y0) and (x1, y1) intersects the circle with center - * (centerX, centerY) and radius, and store the center of the line segment of - * intersection in the (x, y) components of the supplied vector and the half-length of that line segment in the z component. - *

- * Reference: http://math.stackexchange.com - * - * @param x0 - * the x coordinate of the first point on the line - * @param y0 - * the y coordinate of the first point on the line - * @param x1 - * the x coordinate of the second point on the line - * @param y1 - * the y coordinate of the second point on the line - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radius - * the radius of the circle - * @param intersectionCenterAndHL - * will hold the center of the line segment of intersection in the (x, y) components and the half-length in the z component - * @return true iff the line intersects the circle; false otherwise - */ - public static boolean intersectLineCircle(double x0, double y0, double x1, double y1, double centerX, double centerY, double radius, Vector3d intersectionCenterAndHL) { - // Build general line equation from two points and use the other method - return intersectLineCircle(y0 - y1, x1 - x0, (x0 - x1) * y0 + (y1 - y0) * x0, centerX, centerY, radius, intersectionCenterAndHL); - } - - /** - * Test whether the axis-aligned rectangle with minimum corner (minX, minY) and maximum corner (maxX, maxY) - * intersects the line with the general equation a*x + b*y + c = 0. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @param a - * the x factor in the line equation - * @param b - * the y factor in the line equation - * @param c - * the constant in the plane equation - * @return true iff the axis-aligned rectangle intersects the line; false otherwise - */ - public static boolean testAarLine(double minX, double minY, double maxX, double maxY, double a, double b, double c) { - double pX, pY, nX, nY; - if (a > 0.0) { - pX = maxX; - nX = minX; - } else { - pX = minX; - nX = maxX; - } - if (b > 0.0) { - pY = maxY; - nY = minY; - } else { - pY = minY; - nY = maxY; - } - double distN = c + a * nX + b * nY; - double distP = c + a * pX + b * pY; - return distN <= 0.0 && distP >= 0.0; - } - - /** - * Test whether the axis-aligned rectangle with minimum corner min and maximum corner max - * intersects the line with the general equation a*x + b*y + c = 0. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param min - * the minimum corner of the axis-aligned rectangle - * @param max - * the maximum corner of the axis-aligned rectangle - * @param a - * the x factor in the line equation - * @param b - * the y factor in the line equation - * @param c - * the constant in the line equation - * @return true iff the axis-aligned rectangle intersects the line; false otherwise - */ - public static boolean testAarLine(Vector2dc min, Vector2dc max, double a, double b, double c) { - return testAarLine(min.x(), min.y(), max.x(), max.y(), a, b, c); - } - - /** - * Test whether the axis-aligned rectangle with minimum corner (minX, minY) and maximum corner (maxX, maxY) - * intersects the line defined by the two points (x0, y0) and (x1, y1). - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @param x0 - * the x coordinate of the first point on the line - * @param y0 - * the y coordinate of the first point on the line - * @param x1 - * the x coordinate of the second point on the line - * @param y1 - * the y coordinate of the second point on the line - * @return true iff the axis-aligned rectangle intersects the line; false otherwise - */ - public static boolean testAarLine(double minX, double minY, double maxX, double maxY, double x0, double y0, double x1, double y1) { - double a = y0 - y1; - double b = x1 - x0; - double c = -b * y0 - a * x0; - return testAarLine(minX, minY, maxX, maxY, a, b, c); - } - - /** - * Test whether the axis-aligned rectangle with minimum corner (minXA, minYA) and maximum corner (maxXA, maxYA) - * intersects the axis-aligned rectangle with minimum corner (minXB, minYB) and maximum corner (maxXB, maxYB). - * - * @param minXA - * the x coordinate of the minimum corner of the first axis-aligned rectangle - * @param minYA - * the y coordinate of the minimum corner of the first axis-aligned rectangle - * @param maxXA - * the x coordinate of the maximum corner of the first axis-aligned rectangle - * @param maxYA - * the y coordinate of the maximum corner of the first axis-aligned rectangle - * @param minXB - * the x coordinate of the minimum corner of the second axis-aligned rectangle - * @param minYB - * the y coordinate of the minimum corner of the second axis-aligned rectangle - * @param maxXB - * the x coordinate of the maximum corner of the second axis-aligned rectangle - * @param maxYB - * the y coordinate of the maximum corner of the second axis-aligned rectangle - * @return true iff both axis-aligned rectangles intersect; false otherwise - */ - public static boolean testAarAar(double minXA, double minYA, double maxXA, double maxYA, double minXB, double minYB, double maxXB, double maxYB) { - return maxXA >= minXB && maxYA >= minYB && minXA <= maxXB && minYA <= maxYB; - } - - /** - * Test whether the axis-aligned rectangle with minimum corner minA and maximum corner maxA - * intersects the axis-aligned rectangle with minimum corner minB and maximum corner maxB. - * - * @param minA - * the minimum corner of the first axis-aligned rectangle - * @param maxA - * the maximum corner of the first axis-aligned rectangle - * @param minB - * the minimum corner of the second axis-aligned rectangle - * @param maxB - * the maximum corner of the second axis-aligned rectangle - * @return true iff both axis-aligned rectangles intersect; false otherwise - */ - public static boolean testAarAar(Vector2dc minA, Vector2dc maxA, Vector2dc minB, Vector2dc maxB) { - return testAarAar(minA.x(), minA.y(), maxA.x(), maxA.y(), minB.x(), minB.y(), maxB.x(), maxB.y()); - } - - /** - * Test whether a given circle with center (aX, aY) and radius aR and travelled distance vector (maX, maY) - * intersects a given static circle with center (bX, bY) and radius bR. - *

- * Note that the case of two moving circles can always be reduced to this case by expressing the moved distance of one of the circles relative - * to the other. - *

- * Reference: https://www.gamasutra.com - * - * @param aX - * the x coordinate of the first circle's center - * @param aY - * the y coordinate of the first circle's center - * @param maX - * the x coordinate of the first circle's travelled distance vector - * @param maY - * the y coordinate of the first circle's travelled distance vector - * @param aR - * the radius of the first circle - * @param bX - * the x coordinate of the second circle's center - * @param bY - * the y coordinate of the second circle's center - * @param bR - * the radius of the second circle - * @return true if both circle intersect; false otherwise - */ - public static boolean testMovingCircleCircle(double aX, double aY, double maX, double maY, double aR, double bX, double bY, double bR) { - double aRbR = aR + bR; - double dist = Math.sqrt((aX - bX) * (aX - bX) + (aY - bY) * (aY - bY)) - aRbR; - double mLen = Math.sqrt(maX * maX + maY * maY); - if (mLen < dist) - return false; - double invMLen = 1.0 / mLen; - double nX = maX * invMLen; - double nY = maY * invMLen; - double cX = bX - aX; - double cY = bY - aY; - double nDotC = nX * cX + nY * cY; - if (nDotC <= 0.0) - return false; - double cLen = Math.sqrt(cX * cX + cY * cY); - double cLenNdotC = cLen * cLen - nDotC * nDotC; - double aRbR2 = aRbR * aRbR; - if (cLenNdotC >= aRbR2) - return false; - double t = aRbR2 - cLenNdotC; - if (t < 0.0) - return false; - double distance = nDotC - Math.sqrt(t); - double mag = mLen; - if (mag < distance) - return false; - return true; - } - - /** - * Test whether a given circle with center centerA and radius aR and travelled distance vector moveA - * intersects a given static circle with center centerB and radius bR. - *

- * Note that the case of two moving circles can always be reduced to this case by expressing the moved distance of one of the circles relative - * to the other. - *

- * Reference: https://www.gamasutra.com - * - * @param centerA - * the coordinates of the first circle's center - * @param moveA - * the coordinates of the first circle's travelled distance vector - * @param aR - * the radius of the first circle - * @param centerB - * the coordinates of the second circle's center - * @param bR - * the radius of the second circle - * @return true if both circle intersect; false otherwise - */ - public static boolean testMovingCircleCircle(Vector2d centerA, Vector2d moveA, double aR, Vector2d centerB, double bR) { - return testMovingCircleCircle(centerA.x, centerA.y, moveA.x, moveA.y, aR, centerB.x, centerB.y, bR); - } - - /** - * Test whether the one circle with center (aX, aY) and square radius radiusSquaredA intersects the other - * circle with center (bX, bY) and square radius radiusSquaredB, and store the center of the line segment of - * intersection in the (x, y) components of the supplied vector and the half-length of that line segment in the z component. - *

- * This method returns false when one circle contains the other circle. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param aX - * the x coordinate of the first circle's center - * @param aY - * the y coordinate of the first circle's center - * @param radiusSquaredA - * the square of the first circle's radius - * @param bX - * the x coordinate of the second circle's center - * @param bY - * the y coordinate of the second circle's center - * @param radiusSquaredB - * the square of the second circle's radius - * @param intersectionCenterAndHL - * will hold the center of the circle of intersection in the (x, y, z) components and the radius in the w component - * @return true iff both circles intersect; false otherwise - */ - public static boolean intersectCircleCircle(double aX, double aY, double radiusSquaredA, double bX, double bY, double radiusSquaredB, Vector3d intersectionCenterAndHL) { - double dX = bX - aX, dY = bY - aY; - double distSquared = dX * dX + dY * dY; - double h = 0.5 + (radiusSquaredA - radiusSquaredB) / distSquared; - double r_i = Math.sqrt(radiusSquaredA - h * h * distSquared); - if (r_i >= 0.0) { - intersectionCenterAndHL.x = aX + h * dX; - intersectionCenterAndHL.y = aY + h * dY; - intersectionCenterAndHL.z = r_i; - return true; - } - return false; - } - - /** - * Test whether the one circle with center centerA and square radius radiusSquaredA intersects the other - * circle with center centerB and square radius radiusSquaredB, and store the center of the line segment of - * intersection in the (x, y) components of the supplied vector and the half-length of that line segment in the z component. - *

- * This method returns false when one circle contains the other circle. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param centerA - * the first circle's center - * @param radiusSquaredA - * the square of the first circle's radius - * @param centerB - * the second circle's center - * @param radiusSquaredB - * the square of the second circle's radius - * @param intersectionCenterAndHL - * will hold the center of the line segment of intersection in the (x, y) components and the half-length in the z component - * @return true iff both circles intersect; false otherwise - */ - public static boolean intersectCircleCircle(Vector2dc centerA, double radiusSquaredA, Vector2dc centerB, double radiusSquaredB, Vector3d intersectionCenterAndHL) { - return intersectCircleCircle(centerA.x(), centerA.y(), radiusSquaredA, centerB.x(), centerB.y(), radiusSquaredB, intersectionCenterAndHL); - } - - /** - * Test whether the one circle with center (aX, aY) and radius rA intersects the other circle with center (bX, bY) and radius rB. - *

- * This method returns true when one circle contains the other circle. - *

- * Reference: http://math.stackexchange.com/ - * - * @param aX - * the x coordinate of the first circle's center - * @param aY - * the y coordinate of the first circle's center - * @param rA - * the square of the first circle's radius - * @param bX - * the x coordinate of the second circle's center - * @param bY - * the y coordinate of the second circle's center - * @param rB - * the square of the second circle's radius - * @return true iff both circles intersect; false otherwise - */ - public static boolean testCircleCircle(double aX, double aY, double rA, double bX, double bY, double rB) { - double d = (aX - bX) * (aX - bX) + (aY - bY) * (aY - bY); - return d <= (rA + rB) * (rA + rB); - } - - /** - * Test whether the one circle with center centerA and square radius radiusSquaredA intersects the other - * circle with center centerB and square radius radiusSquaredB. - *

- * This method returns true when one circle contains the other circle. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param centerA - * the first circle's center - * @param radiusSquaredA - * the square of the first circle's radius - * @param centerB - * the second circle's center - * @param radiusSquaredB - * the square of the second circle's radius - * @return true iff both circles intersect; false otherwise - */ - public static boolean testCircleCircle(Vector2dc centerA, double radiusSquaredA, Vector2dc centerB, double radiusSquaredB) { - return testCircleCircle(centerA.x(), centerA.y(), radiusSquaredA, centerB.x(), centerB.y(), radiusSquaredB); - } - - /** - * Determine the signed distance of the given point (pointX, pointY) to the line specified via its general plane equation - * a*x + b*y + c = 0. - *

- * Reference: http://mathworld.wolfram.com - * - * @param pointX - * the x coordinate of the point - * @param pointY - * the y coordinate of the point - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the constant in the plane equation - * @return the distance between the point and the line - */ - public static double distancePointLine(double pointX, double pointY, double a, double b, double c) { - double denom = Math.sqrt(a * a + b * b); - return (a * pointX + b * pointY + c) / denom; - } - - /** - * Determine the signed distance of the given point (pointX, pointY) to the line defined by the two points (x0, y0) and (x1, y1). - *

- * Reference: http://mathworld.wolfram.com - * - * @param pointX - * the x coordinate of the point - * @param pointY - * the y coordinate of the point - * @param x0 - * the x coordinate of the first point on the line - * @param y0 - * the y coordinate of the first point on the line - * @param x1 - * the x coordinate of the second point on the line - * @param y1 - * the y coordinate of the second point on the line - * @return the distance between the point and the line - */ - public static double distancePointLine(double pointX, double pointY, double x0, double y0, double x1, double y1) { - double dx = x1 - x0; - double dy = y1 - y0; - double denom = Math.sqrt(dx * dx + dy * dy); - return (dx * (y0 - pointY) - (x0 - pointX) * dy) / denom; - } - - /** - * Compute the distance of the given point (pX, pY, pZ) to the line defined by the two points (x0, y0, z0) and (x1, y1, z1). - *

- * Reference: http://mathworld.wolfram.com - * - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param pZ - * the z coordinate of the point - * @param x0 - * the x coordinate of the first point on the line - * @param y0 - * the y coordinate of the first point on the line - * @param z0 - * the z coordinate of the first point on the line - * @param x1 - * the x coordinate of the second point on the line - * @param y1 - * the y coordinate of the second point on the line - * @param z1 - * the z coordinate of the second point on the line - * @return the distance between the point and the line - */ - public static double distancePointLine(double pX, double pY, double pZ, - double x0, double y0, double z0, double x1, double y1, double z1) { - double d21x = x1 - x0, d21y = y1 - y0, d21z = z1 - z0; - double d10x = x0 - pX, d10y = y0 - pY, d10z = z0 - pZ; - double cx = d21y * d10z - d21z * d10y, cy = d21z * d10x - d21x * d10z, cz = d21x * d10y - d21y * d10x; - return Math.sqrt((cx*cx + cy*cy + cz*cz) / (d21x*d21x + d21y*d21y + d21z*d21z)); - } - - /** - * Test whether the ray with given origin (originX, originY) and direction (dirX, dirY) intersects the line - * containing the given point (pointX, pointY) and having the normal (normalX, normalY), and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the line, because it is either parallel to the line or its direction points - * away from the line or the ray's origin is on the negative side of the line (i.e. the line's normal points away from the ray's origin). - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param pointX - * the x coordinate of a point on the line - * @param pointY - * the y coordinate of a point on the line - * @param normalX - * the x coordinate of the line's normal - * @param normalY - * the y coordinate of the line's normal - * @param epsilon - * some small epsilon for when the ray is parallel to the line - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the line; -1.0 otherwise - */ - public static double intersectRayLine(double originX, double originY, double dirX, double dirY, double pointX, double pointY, double normalX, double normalY, double epsilon) { - double denom = normalX * dirX + normalY * dirY; - if (denom < epsilon) { - double t = ((pointX - originX) * normalX + (pointY - originY) * normalY) / denom; - if (t >= 0.0) - return t; - } - return -1.0; - } - - /** - * Test whether the ray with given origin and direction dir intersects the line - * containing the given point and having the given normal, and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the line, because it is either parallel to the line or its direction points - * away from the line or the ray's origin is on the negative side of the line (i.e. the line's normal points away from the ray's origin). - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param point - * a point on the line - * @param normal - * the line's normal - * @param epsilon - * some small epsilon for when the ray is parallel to the line - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the line; -1.0 otherwise - */ - public static double intersectRayLine(Vector2dc origin, Vector2dc dir, Vector2dc point, Vector2dc normal, double epsilon) { - return intersectRayLine(origin.x(), origin.y(), dir.x(), dir.y(), point.x(), point.y(), normal.x(), normal.y(), epsilon); - } - - /** - * Determine whether the ray with given origin (originX, originY) and direction (dirX, dirY) intersects the undirected line segment - * given by the two end points (aX, bY) and (bX, bY), and return the value of the parameter t in the ray equation - * p(t) = origin + t * dir of the intersection point, if any. - *

- * This method returns -1.0 if the ray does not intersect the line segment. - * - * @see #intersectRayLineSegment(Vector2dc, Vector2dc, Vector2dc, Vector2dc) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param aX - * the x coordinate of the line segment's first end point - * @param aY - * the y coordinate of the line segment's first end point - * @param bX - * the x coordinate of the line segment's second end point - * @param bY - * the y coordinate of the line segment's second end point - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the line segment; -1.0 otherwise - */ - public static double intersectRayLineSegment(double originX, double originY, double dirX, double dirY, double aX, double aY, double bX, double bY) { - double v1X = originX - aX; - double v1Y = originY - aY; - double v2X = bX - aX; - double v2Y = bY - aY; - double invV23 = 1.0 / (v2Y * dirX - v2X * dirY); - double t1 = (v2X * v1Y - v2Y * v1X) * invV23; - double t2 = (v1Y * dirX - v1X * dirY) * invV23; - if (t1 >= 0.0 && t2 >= 0.0 && t2 <= 1.0) - return t1; - return -1.0; - } - - /** - * Determine whether the ray with given origin and direction dir intersects the undirected line segment - * given by the two end points a and b, and return the value of the parameter t in the ray equation - * p(t) = origin + t * dir of the intersection point, if any. - *

- * This method returns -1.0 if the ray does not intersect the line segment. - * - * @see #intersectRayLineSegment(double, double, double, double, double, double, double, double) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param a - * the line segment's first end point - * @param b - * the line segment's second end point - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the line segment; -1.0 otherwise - */ - public static double intersectRayLineSegment(Vector2dc origin, Vector2dc dir, Vector2dc a, Vector2dc b) { - return intersectRayLineSegment(origin.x(), origin.y(), dir.x(), dir.y(), a.x(), a.y(), b.x(), b.y()); - } - - /** - * Test whether the axis-aligned rectangle with minimum corner (minX, minY) and maximum corner (maxX, maxY) - * intersects the circle with the given center (centerX, centerY) and square radius radiusSquared. - *

- * Reference: http://stackoverflow.com - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radiusSquared - * the square of the circle's radius - * @return true iff the axis-aligned rectangle intersects the circle; false otherwise - */ - public static boolean testAarCircle(double minX, double minY, double maxX, double maxY, double centerX, double centerY, double radiusSquared) { - double radius2 = radiusSquared; - if (centerX < minX) { - double d = (centerX - minX); - radius2 -= d * d; - } else if (centerX > maxX) { - double d = (centerX - maxX); - radius2 -= d * d; - } - if (centerY < minY) { - double d = (centerY - minY); - radius2 -= d * d; - } else if (centerY > maxY) { - double d = (centerY - maxY); - radius2 -= d * d; - } - return radius2 >= 0.0; - } - - /** - * Test whether the axis-aligned rectangle with minimum corner min and maximum corner max - * intersects the circle with the given center and square radius radiusSquared. - *

- * Reference: http://stackoverflow.com - * - * @param min - * the minimum corner of the axis-aligned rectangle - * @param max - * the maximum corner of the axis-aligned rectangle - * @param center - * the circle's center - * @param radiusSquared - * the squared of the circle's radius - * @return true iff the axis-aligned rectangle intersects the circle; false otherwise - */ - public static boolean testAarCircle(Vector2dc min, Vector2dc max, Vector2dc center, double radiusSquared) { - return testAarCircle(min.x(), min.y(), max.x(), max.y(), center.x(), center.y(), radiusSquared); - } - - /** - * Determine the closest point on the triangle with the given vertices (v0X, v0Y), (v1X, v1Y), (v2X, v2Y) - * between that triangle and the given point (pX, pY) and store that point into the given result. - *

- * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}) - * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20}) - * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point" - * - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param result - * will hold the closest point - * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}, - * {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or - * {@link #POINT_ON_TRIANGLE_FACE} - */ - public static int findClosestPointOnTriangle(double v0X, double v0Y, double v1X, double v1Y, double v2X, double v2Y, double pX, double pY, Vector2d result) { - double abX = v1X - v0X, abY = v1Y - v0Y; - double acX = v2X - v0X, acY = v2Y - v0Y; - double apX = pX - v0X, apY = pY - v0Y; - double d1 = abX * apX + abY * apY; - double d2 = acX * apX + acY * apY; - if (d1 <= 0.0 && d2 <= 0.0) { - result.x = v0X; - result.y = v0Y; - return POINT_ON_TRIANGLE_VERTEX_0; - } - double bpX = pX - v1X, bpY = pY - v1Y; - double d3 = abX * bpX + abY * bpY; - double d4 = acX * bpX + acY * bpY; - if (d3 >= 0.0 && d4 <= d3) { - result.x = v1X; - result.y = v1Y; - return POINT_ON_TRIANGLE_VERTEX_1; - } - double vc = d1 * d4 - d3 * d2; - if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) { - double v = d1 / (d1 - d3); - result.x = v0X + v * abX; - result.y = v0Y + v * abY; - return POINT_ON_TRIANGLE_EDGE_01; - } - double cpX = pX - v2X, cpY = pY - v2Y; - double d5 = abX * cpX + abY * cpY; - double d6 = acX * cpX + acY * cpY; - if (d6 >= 0.0 && d5 <= d6) { - result.x = v2X; - result.y = v2Y; - return POINT_ON_TRIANGLE_VERTEX_2; - } - double vb = d5 * d2 - d1 * d6; - if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) { - double w = d2 / (d2 - d6); - result.x = v0X + w * acX; - result.y = v0Y + w * acY; - return POINT_ON_TRIANGLE_EDGE_20; - } - double va = d3 * d6 - d5 * d4; - if (va <= 0.0 && d4 - d3 >= 0.0 && d5 - d6 >= 0.0) { - double w = (d4 - d3) / (d4 - d3 + d5 - d6); - result.x = v1X + w * (v2X - v1X); - result.y = v1Y + w * (v2Y - v1Y); - return POINT_ON_TRIANGLE_EDGE_12; - } - double denom = 1.0 / (va + vb + vc); - double v = vb * denom; - double w = vc * denom; - result.x = v0X + abX * v + acX * w; - result.y = v0Y + abY * v + acY * w; - return POINT_ON_TRIANGLE_FACE; - } - - /** - * Determine the closest point on the triangle with the vertices v0, v1, v2 - * between that triangle and the given point p and store that point into the given result. - *

- * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}) - * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20}) - * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point" - * - * @param v0 - * the first vertex of the triangle - * @param v1 - * the second vertex of the triangle - * @param v2 - * the third vertex of the triangle - * @param p - * the point - * @param result - * will hold the closest point - * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}, - * {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or - * {@link #POINT_ON_TRIANGLE_FACE} - */ - public static int findClosestPointOnTriangle(Vector2dc v0, Vector2dc v1, Vector2dc v2, Vector2dc p, Vector2d result) { - return findClosestPointOnTriangle(v0.x(), v0.y(), v1.x(), v1.y(), v2.x(), v2.y(), p.x(), p.y(), result); - } - - /** - * Test whether the given ray with the origin (originX, originY) and direction (dirX, dirY) - * intersects the given circle with center (centerX, centerY) and square radius radiusSquared, - * and store the values of the parameter t in the ray equation p(t) = origin + t * dir for both points (near - * and far) of intersections into the given result vector. - *

- * This method returns true for a ray whose origin lies inside the circle. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radiusSquared - * the circle radius squared - * @param result - * a vector that will contain the values of the parameter t in the ray equation - * p(t) = origin + t * dir for both points (near, far) of intersections with the circle - * @return true if the ray intersects the circle; false otherwise - */ - public static boolean intersectRayCircle(double originX, double originY, double dirX, double dirY, - double centerX, double centerY, double radiusSquared, Vector2d result) { - double Lx = centerX - originX; - double Ly = centerY - originY; - double tca = Lx * dirX + Ly * dirY; - double d2 = Lx * Lx + Ly * Ly - tca * tca; - if (d2 > radiusSquared) - return false; - double thc = Math.sqrt(radiusSquared - d2); - double t0 = tca - thc; - double t1 = tca + thc; - if (t0 < t1 && t1 >= 0.0) { - result.x = t0; - result.y = t1; - return true; - } - return false; - } - - /** - * Test whether the ray with the given origin and direction dir - * intersects the circle with the given center and square radius radiusSquared, - * and store the values of the parameter t in the ray equation p(t) = origin + t * dir for both points (near - * and far) of intersections into the given result vector. - *

- * This method returns true for a ray whose origin lies inside the circle. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param center - * the circle's center - * @param radiusSquared - * the circle radius squared - * @param result - * a vector that will contain the values of the parameter t in the ray equation - * p(t) = origin + t * dir for both points (near, far) of intersections with the circle - * @return true if the ray intersects the circle; false otherwise - */ - public static boolean intersectRayCircle(Vector2dc origin, Vector2dc dir, Vector2dc center, double radiusSquared, Vector2d result) { - return intersectRayCircle(origin.x(), origin.y(), dir.x(), dir.y(), center.x(), center.y(), radiusSquared, result); - } - - /** - * Test whether the given ray with the origin (originX, originY) and direction (dirX, dirY) - * intersects the given circle with center (centerX, centerY) and square radius radiusSquared. - *

- * This method returns true for a ray whose origin lies inside the circle. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radiusSquared - * the circle radius squared - * @return true if the ray intersects the circle; false otherwise - */ - public static boolean testRayCircle(double originX, double originY, double dirX, double dirY, - double centerX, double centerY, double radiusSquared) { - double Lx = centerX - originX; - double Ly = centerY - originY; - double tca = Lx * dirX + Ly * dirY; - double d2 = Lx * Lx + Ly * Ly - tca * tca; - if (d2 > radiusSquared) - return false; - double thc = Math.sqrt(radiusSquared - d2); - double t0 = tca - thc; - double t1 = tca + thc; - return t0 < t1 && t1 >= 0.0; - } - - /** - * Test whether the ray with the given origin and direction dir - * intersects the circle with the given center and square radius. - *

- * This method returns true for a ray whose origin lies inside the circle. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param center - * the circle's center - * @param radiusSquared - * the circle radius squared - * @return true if the ray intersects the circle; false otherwise - */ - public static boolean testRayCircle(Vector2dc origin, Vector2dc dir, Vector2dc center, double radiusSquared) { - return testRayCircle(origin.x(), origin.y(), dir.x(), dir.y(), center.x(), center.y(), radiusSquared); - } - - /** - * Determine whether the given ray with the origin (originX, originY) and direction (dirX, dirY) - * intersects the axis-aligned rectangle given as its minimum corner (minX, minY) and maximum corner (maxX, maxY), - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * as well as the side of the axis-aligned rectangle the ray intersects. - *

- * This method also detects an intersection for a ray whose origin lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @param result - * a vector which will hold the values of the parameter t in the ray equation - * p(t) = origin + t * dir of the near and far point of intersection - * @return the side on which the near intersection occurred as one of - * {@link #AAR_SIDE_MINX}, {@link #AAR_SIDE_MINY}, {@link #AAR_SIDE_MAXX} or {@link #AAR_SIDE_MAXY}; - * or -1 if the ray does not intersect the axis-aligned rectangle; - */ - public static int intersectRayAar(double originX, double originY, double dirX, double dirY, - double minX, double minY, double maxX, double maxY, Vector2d result) { - double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY; - double tNear, tFar, tymin, tymax; - if (invDirX >= 0.0) { - tNear = (minX - originX) * invDirX; - tFar = (maxX - originX) * invDirX; - } else { - tNear = (maxX - originX) * invDirX; - tFar = (minX - originX) * invDirX; - } - if (invDirY >= 0.0) { - tymin = (minY - originY) * invDirY; - tymax = (maxY - originY) * invDirY; - } else { - tymin = (maxY - originY) * invDirY; - tymax = (minY - originY) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return OUTSIDE; - tNear = tymin > tNear || Double.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Double.isNaN(tFar) ? tymax : tFar; - int side = -1; // no intersection side - if (tNear < tFar && tFar >= 0.0) { - double px = originX + tNear * dirX; - double py = originY + tNear * dirY; - result.x = tNear; - result.y = tFar; - double daX = Math.abs(px - minX); - double daY = Math.abs(py - minY); - double dbX = Math.abs(px - maxX); - double dbY = Math.abs(py - maxY); - side = 0; // min x coordinate - double min = daX; - if (daY < min) { - min = daY; - side = 1; // min y coordinate - } - if (dbX < min) { - min = dbX; - side = 2; // max xcoordinate - } - if (dbY < min) - side = 3; // max y coordinate - } - return side; - } - - /** - * Determine whether the given ray with the given origin and direction dir - * intersects the axis-aligned rectangle given as its minimum corner min and maximum corner max, - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * as well as the side of the axis-aligned rectangle the ray intersects. - *

- * This method also detects an intersection for a ray whose origin lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAar(double, double, double, double, double, double, double, double, Vector2d) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param min - * the minimum corner of the axis-aligned rectangle - * @param max - * the maximum corner of the axis-aligned rectangle - * @param result - * a vector which will hold the values of the parameter t in the ray equation - * p(t) = origin + t * dir of the near and far point of intersection - * @return the side on which the near intersection occurred as one of - * {@link #AAR_SIDE_MINX}, {@link #AAR_SIDE_MINY}, {@link #AAR_SIDE_MAXX} or {@link #AAR_SIDE_MAXY}; - * or -1 if the ray does not intersect the axis-aligned rectangle; - */ - public static int intersectRayAar(Vector2dc origin, Vector2dc dir, Vector2dc min, Vector2dc max, Vector2d result) { - return intersectRayAar(origin.x(), origin.y(), dir.x(), dir.y(), min.x(), min.y(), max.x(), max.y(), result); - } - - /** - * Determine whether the undirected line segment with the end points (p0X, p0Y) and (p1X, p1Y) - * intersects the axis-aligned rectangle given as its minimum corner (minX, minY) and maximum corner (maxX, maxY), - * and store the values of the parameter t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * into result. - *

- * This method also detects an intersection of a line segment whose either end point lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectLineSegmentAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc, Vector2d) - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @param result - * a vector which will hold the values of the parameter t in the ray equation - * p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned rectangle; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned rectangle; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned rectangle; or - * {@link #TWO_INTERSECTION} if the line segment intersects two edges of the axis-aligned rectangle or lies on one edge of the rectangle - */ - public static int intersectLineSegmentAar(double p0X, double p0Y, double p1X, double p1Y, - double minX, double minY, double maxX, double maxY, Vector2d result) { - double dirX = p1X - p0X, dirY = p1Y - p0Y; - double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY; - double tNear, tFar, tymin, tymax; - if (invDirX >= 0.0) { - tNear = (minX - p0X) * invDirX; - tFar = (maxX - p0X) * invDirX; - } else { - tNear = (maxX - p0X) * invDirX; - tFar = (minX - p0X) * invDirX; - } - if (invDirY >= 0.0) { - tymin = (minY - p0Y) * invDirY; - tymax = (maxY - p0Y) * invDirY; - } else { - tymin = (maxY - p0Y) * invDirY; - tymax = (minY - p0Y) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return OUTSIDE; - tNear = tymin > tNear || Double.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Double.isNaN(tFar) ? tymax : tFar; - int type = OUTSIDE; - if (tNear <= tFar && tNear <= 1.0f && tFar >= 0.0f) { - if (tNear >= 0.0f && tFar > 1.0f) { - tFar = tNear; - type = ONE_INTERSECTION; - } else if (tNear < 0.0f && tFar <= 1.0f) { - tNear = tFar; - type = ONE_INTERSECTION; - } else if (tNear < 0.0f && tFar > 1.0f) { - type = INSIDE; - } else { - type = TWO_INTERSECTION; - } - result.x = tNear; - result.y = tFar; - } - return type; - } - - /** - * Determine whether the undirected line segment with the end points p0 and p1 - * intersects the axis-aligned rectangle given as its minimum corner min and maximum corner max, - * and store the values of the parameter t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * into result. - *

- * This method also detects an intersection of a line segment whose either end point lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * #see {@link #intersectLineSegmentAar(double, double, double, double, double, double, double, double, Vector2d)} - * - * @param p0 - * the line segment's first end point - * @param p1 - * the line segment's second end point - * @param min - * the minimum corner of the axis-aligned rectangle - * @param max - * the maximum corner of the axis-aligned rectangle - * @param result - * a vector which will hold the values of the parameter t in the ray equation - * p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned rectangle; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned rectangle; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned rectangle; or - * {@link #TWO_INTERSECTION} if the line segment intersects two edges of the axis-aligned rectangle - */ - public static int intersectLineSegmentAar(Vector2dc p0, Vector2dc p1, Vector2dc min, Vector2dc max, Vector2d result) { - return intersectLineSegmentAar(p0.x(), p0.y(), p1.x(), p1.y(), min.x(), min.y(), max.x(), max.y(), result); - } - - /** - * Test whether the given ray with the origin (originX, originY) and direction (dirX, dirY) - * intersects the given axis-aligned rectangle given as its minimum corner (minX, minY) and maximum corner (maxX, maxY). - *

- * This method returns true for a ray whose origin lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAar(Vector2dc, Vector2dc, Vector2dc, Vector2dc) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @return true if the given ray intersects the axis-aligned rectangle; false otherwise - */ - public static boolean testRayAar(double originX, double originY, double dirX, double dirY, double minX, double minY, double maxX, double maxY) { - double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY; - double tNear, tFar, tymin, tymax; - if (invDirX >= 0.0) { - tNear = (minX - originX) * invDirX; - tFar = (maxX - originX) * invDirX; - } else { - tNear = (maxX - originX) * invDirX; - tFar = (minX - originX) * invDirX; - } - if (invDirY >= 0.0) { - tymin = (minY - originY) * invDirY; - tymax = (maxY - originY) * invDirY; - } else { - tymin = (maxY - originY) * invDirY; - tymax = (minY - originY) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return false; - tNear = tymin > tNear || Double.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Double.isNaN(tFar) ? tymax : tFar; - return tNear < tFar && tFar >= 0.0; - } - - /** - * Test whether the ray with the given origin and direction dir - * intersects the given axis-aligned rectangle specified as its minimum corner min and maximum corner max. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAar(double, double, double, double, double, double, double, double) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param min - * the minimum corner of the axis-aligned rectangle - * @param max - * the maximum corner of the axis-aligned rectangle - * @return true if the given ray intersects the axis-aligned rectangle; false otherwise - */ - public static boolean testRayAar(Vector2dc origin, Vector2dc dir, Vector2dc min, Vector2dc max) { - return testRayAar(origin.x(), origin.y(), dir.x(), dir.y(), min.x(), min.y(), max.x(), max.y()); - } - - /** - * Test whether the given point (pX, pY) lies inside the triangle with the vertices (v0X, v0Y), (v1X, v1Y), (v2X, v2Y). - * - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @return true iff the point lies inside the triangle; false otherwise - */ - public static boolean testPointTriangle(double pX, double pY, double v0X, double v0Y, double v1X, double v1Y, double v2X, double v2Y) { - boolean b1 = (pX - v1X) * (v0Y - v1Y) - (v0X - v1X) * (pY - v1Y) < 0.0; - boolean b2 = (pX - v2X) * (v1Y - v2Y) - (v1X - v2X) * (pY - v2Y) < 0.0; - if (b1 != b2) - return false; - boolean b3 = (pX - v0X) * (v2Y - v0Y) - (v2X - v0X) * (pY - v0Y) < 0.0; - return b2 == b3; - } - - /** - * Test whether the given point lies inside the triangle with the vertices v0, v1, v2. - * - * @param v0 - * the first vertex of the triangle - * @param v1 - * the second vertex of the triangle - * @param v2 - * the third vertex of the triangle - * @param point - * the point - * @return true iff the point lies inside the triangle; false otherwise - */ - public static boolean testPointTriangle(Vector2dc point, Vector2dc v0, Vector2dc v1, Vector2dc v2) { - return testPointTriangle(point.x(), point.y(), v0.x(), v0.y(), v1.x(), v1.y(), v2.x(), v2.y()); - } - - /** - * Test whether the given point (pX, pY) lies inside the axis-aligned rectangle with the minimum corner (minX, minY) - * and maximum corner (maxX, maxY). - * - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @return true iff the point lies inside the axis-aligned rectangle; false otherwise - */ - public static boolean testPointAar(double pX, double pY, double minX, double minY, double maxX, double maxY) { - return pX >= minX && pY >= minY && pX <= maxX && pY <= maxY; - } - - /** - * Test whether the point (pX, pY) lies inside the circle with center (centerX, centerY) and square radius radiusSquared. - * - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radiusSquared - * the square radius of the circle - * @return true iff the point lies inside the circle; false otherwise - */ - public static boolean testPointCircle(double pX, double pY, double centerX, double centerY, double radiusSquared) { - double dx = pX - centerX; - double dy = pY - centerY; - double dx2 = dx * dx; - double dy2 = dy * dy; - return dx2 + dy2 <= radiusSquared; - } - - /** - * Test whether the circle with center (centerX, centerY) and square radius radiusSquared intersects the triangle with counter-clockwise vertices - * (v0X, v0Y), (v1X, v1Y), (v2X, v2Y). - *

- * The vertices of the triangle must be specified in counter-clockwise order. - *

- * Reference: http://www.phatcode.net/ - * - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radiusSquared - * the square radius of the circle - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @return true iff the circle intersects the triangle; false otherwise - */ - public static boolean testCircleTriangle(double centerX, double centerY, double radiusSquared, double v0X, double v0Y, double v1X, double v1Y, double v2X, double v2Y) { - double c1x = centerX - v0X, c1y = centerY - v0Y; - double c1sqr = c1x * c1x + c1y * c1y - radiusSquared; - if (c1sqr <= 0.0) - return true; - double c2x = centerX - v1X, c2y = centerY - v1Y; - double c2sqr = c2x * c2x + c2y * c2y - radiusSquared; - if (c2sqr <= 0.0) - return true; - double c3x = centerX - v2X, c3y = centerY - v2Y; - double c3sqr = c3x * c3x + c3y * c3y - radiusSquared; - if (c3sqr <= 0.0) - return true; - double e1x = v1X - v0X, e1y = v1Y - v0Y; - double e2x = v2X - v1X, e2y = v2Y - v1Y; - double e3x = v0X - v2X, e3y = v0Y - v2Y; - if (e1x * c1y - e1y * c1x >= 0.0 && e2x * c2y - e2y * c2x >= 0.0 && e3x * c3y - e3y * c3x >= 0.0) - return true; - double k = c1x * e1x + c1y * e1y; - if (k >= 0.0) { - double len = e1x * e1x + e1y * e1y; - if (k <= len) { - if (c1sqr * len <= k * k) - return true; - } - } - k = c2x * e2x + c2y * e2y; - if (k > 0.0) { - double len = e2x * e2x + e2y * e2y; - if (k <= len) { - if (c2sqr * len <= k * k) - return true; - } - } - k = c3x * e3x + c3y * e3y; - if (k >= 0.0) { - double len = e3x * e3x + e3y * e3y; - if (k < len) { - if (c3sqr * len <= k * k) - return true; - } - } - return false; - } - - /** - * Test whether the circle with given center and square radius radiusSquared intersects the triangle with counter-clockwise vertices - * v0, v1, v2. - *

- * The vertices of the triangle must be specified in counter-clockwise order. - *

- * Reference: http://www.phatcode.net/ - * - * @param center - * the circle's center - * @param radiusSquared - * the square radius of the circle - * @param v0 - * the first vertex of the triangle - * @param v1 - * the second vertex of the triangle - * @param v2 - * the third vertex of the triangle - * @return true iff the circle intersects the triangle; false otherwise - */ - public static boolean testCircleTriangle(Vector2dc center, double radiusSquared, Vector2dc v0, Vector2dc v1, Vector2dc v2) { - return testCircleTriangle(center.x(), center.y(), radiusSquared, v0.x(), v0.y(), v1.x(), v1.y(), v2.x(), v2.y()); - } - - /** - * Determine whether the polygon specified by the given sequence of (x, y) coordinate pairs intersects with the ray - * with given origin (originX, originY, originZ) and direction (dirX, dirY, dirZ), and store the point of intersection - * into the given vector p. - *

- * If the polygon intersects the ray, this method returns the index of the polygon edge intersecting the ray, that is, the index of the - * first vertex of the directed line segment. The second vertex is always that index + 1, modulus the number of polygon vertices. - * - * @param verticesXY - * the sequence of (x, y) coordinate pairs of all vertices of the polygon - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param p - * will hold the point of intersection - * @return the index of the first vertex of the polygon edge that intersects the ray; or -1 if the ray does not intersect the polygon - */ - public static int intersectPolygonRay(double[] verticesXY, double originX, double originY, double dirX, double dirY, Vector2d p) { - double nearestT = Double.POSITIVE_INFINITY; - int count = verticesXY.length >> 1; - int edgeIndex = -1; - double aX = verticesXY[(count-1)<<1], aY = verticesXY[((count-1)<<1) + 1]; - for (int i = 0; i < count; i++) { - double bX = verticesXY[i << 1], bY = verticesXY[(i << 1) + 1]; - double doaX = originX - aX, doaY = originY - aY; - double dbaX = bX - aX, dbaY = bY - aY; - double invDbaDir = 1.0 / (dbaY * dirX - dbaX * dirY); - double t = (dbaX * doaY - dbaY * doaX) * invDbaDir; - if (t >= 0.0 && t < nearestT) { - double t2 = (doaY * dirX - doaX * dirY) * invDbaDir; - if (t2 >= 0.0 && t2 <= 1.0) { - edgeIndex = (i - 1 + count) % count; - nearestT = t; - p.x = originX + t * dirX; - p.y = originY + t * dirY; - } - } - aX = bX; - aY = bY; - } - return edgeIndex; - } - - /** - * Determine whether the polygon specified by the given sequence of vertices intersects with the ray - * with given origin (originX, originY, originZ) and direction (dirX, dirY, dirZ), and store the point of intersection - * into the given vector p. - *

- * If the polygon intersects the ray, this method returns the index of the polygon edge intersecting the ray, that is, the index of the - * first vertex of the directed line segment. The second vertex is always that index + 1, modulus the number of polygon vertices. - * - * @param vertices - * the sequence of (x, y) coordinate pairs of all vertices of the polygon - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param p - * will hold the point of intersection - * @return the index of the first vertex of the polygon edge that intersects the ray; or -1 if the ray does not intersect the polygon - */ - public static int intersectPolygonRay(Vector2dc[] vertices, double originX, double originY, double dirX, double dirY, Vector2d p) { - double nearestT = Double.POSITIVE_INFINITY; - int count = vertices.length; - int edgeIndex = -1; - double aX = vertices[count-1].x(), aY = vertices[count-1].y(); - for (int i = 0; i < count; i++) { - Vector2dc b = vertices[i]; - double bX = b.x(), bY = b.y(); - double doaX = originX - aX, doaY = originY - aY; - double dbaX = bX - aX, dbaY = bY - aY; - double invDbaDir = 1.0 / (dbaY * dirX - dbaX * dirY); - double t = (dbaX * doaY - dbaY * doaX) * invDbaDir; - if (t >= 0.0 && t < nearestT) { - double t2 = (doaY * dirX - doaX * dirY) * invDbaDir; - if (t2 >= 0.0 && t2 <= 1.0) { - edgeIndex = (i - 1 + count) % count; - nearestT = t; - p.x = originX + t * dirX; - p.y = originY + t * dirY; - } - } - aX = bX; - aY = bY; - } - return edgeIndex; - } - - /** - * Determine whether the two lines, specified via two points lying on each line, intersect each other, and store the point of intersection - * into the given vector p. - * - * @param ps1x - * the x coordinate of the first point on the first line - * @param ps1y - * the y coordinate of the first point on the first line - * @param pe1x - * the x coordinate of the second point on the first line - * @param pe1y - * the y coordinate of the second point on the first line - * @param ps2x - * the x coordinate of the first point on the second line - * @param ps2y - * the y coordinate of the first point on the second line - * @param pe2x - * the x coordinate of the second point on the second line - * @param pe2y - * the y coordinate of the second point on the second line - * @param p - * will hold the point of intersection - * @return true iff the two lines intersect; false otherwise - */ - public static boolean intersectLineLine(double ps1x, double ps1y, double pe1x, double pe1y, double ps2x, double ps2y, double pe2x, double pe2y, Vector2d p) { - double d1x = ps1x - pe1x; - double d1y = pe1y - ps1y; - double d1ps1 = d1y * ps1x + d1x * ps1y; - double d2x = ps2x - pe2x; - double d2y = pe2y - ps2y; - double d2ps2 = d2y * ps2x + d2x * ps2y; - double det = d1y * d2x - d2y * d1x; - if (det == 0.0) - return false; - p.x = (d2x * d1ps1 - d1x * d2ps2) / det; - p.y = (d1y * d2ps2 - d2y * d1ps1) / det; - return true; - } - - private static boolean separatingAxis(Vector2d[] v1s, Vector2d[] v2s, double aX, double aY) { - double minA = Double.POSITIVE_INFINITY, maxA = Double.NEGATIVE_INFINITY; - double minB = Double.POSITIVE_INFINITY, maxB = Double.NEGATIVE_INFINITY; - int maxLen = Math.max(v1s.length, v2s.length); - /* Project both polygons on axis */ - for (int k = 0; k < maxLen; k++) { - if (k < v1s.length) { - Vector2d v1 = v1s[k]; - double d = v1.x * aX + v1.y * aY; - if (d < minA) minA = d; - if (d > maxA) maxA = d; - } - if (k < v2s.length) { - Vector2d v2 = v2s[k]; - double d = v2.x * aX + v2.y * aY; - if (d < minB) minB = d; - if (d > maxB) maxB = d; - } - /* Early-out if overlap found */ - if (minA <= maxB && minB <= maxA) { - return false; - } - } - return true; - } - - /** - * Test if the two polygons, given via their vertices, intersect. - * - * @param v1s - * the vertices of the first polygon - * @param v2s - * the vertices of the second polygon - * @return true if the polygons intersect; false otherwise - */ - public static boolean testPolygonPolygon(Vector2d[] v1s, Vector2d[] v2s) { - /* Try to find a separating axis using the first polygon's edges */ - for (int i = 0, j = v1s.length - 1; i < v1s.length; j = i, i++) { - Vector2d s = v1s[i], t = v1s[j]; - if (separatingAxis(v1s, v2s, s.y - t.y, t.x - s.x)) - return false; - } - /* Try to find a separating axis using the second polygon's edges */ - for (int i = 0, j = v2s.length - 1; i < v2s.length; j = i, i++) { - Vector2d s = v2s[i], t = v2s[j]; - if (separatingAxis(v1s, v2s, s.y - t.y, t.x - s.x)) - return false; - } - return true; - } - -} diff --git a/src/org/joml/Intersectionf.java b/src/org/joml/Intersectionf.java deleted file mode 100644 index db572df9c..000000000 --- a/src/org/joml/Intersectionf.java +++ /dev/null @@ -1,5113 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2015-2020 Kai Burjack - * - * 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 org.joml; - -/** - * Contains intersection and distance tests for some 2D and 3D geometric primitives. - * - * @author Kai Burjack - */ -public class Intersectionf { - - /** - * Return value of - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, float, float, float, float, Vector3f)}, - * {@link #findClosestPointOnTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3f)}, - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #findClosestPointOnTriangle(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point is the first vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_VERTEX_0 = 1; - /** - * Return value of - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, float, float, float, float, Vector3f)}, - * {@link #findClosestPointOnTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3f)}, - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #findClosestPointOnTriangle(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point is the second vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_VERTEX_1 = 2; - /** - * Return value of - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, float, float, float, float, Vector3f)}, - * {@link #findClosestPointOnTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3f)}, - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #findClosestPointOnTriangle(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point is the third vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_VERTEX_2 = 3; - - /** - * Return value of - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, float, float, float, float, Vector3f)}, - * {@link #findClosestPointOnTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3f)}, - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #findClosestPointOnTriangle(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point lies on the edge between the first and second vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_EDGE_01 = 4; - /** - * Return value of - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, float, float, float, float, Vector3f)}, - * {@link #findClosestPointOnTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3f)}, - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #findClosestPointOnTriangle(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point lies on the edge between the second and third vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_EDGE_12 = 5; - /** - * Return value of - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, float, float, float, float, Vector3f)}, - * {@link #findClosestPointOnTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3f)}, - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #findClosestPointOnTriangle(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point lies on the edge between the third and first vertex of the triangle. - */ - public static final int POINT_ON_TRIANGLE_EDGE_20 = 6; - - /** - * Return value of - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, float, float, float, float, Vector3f)}, - * {@link #findClosestPointOnTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3f)}, - * {@link #findClosestPointOnTriangle(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #findClosestPointOnTriangle(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} or - * {@link #intersectSweptSphereTriangle} - * to signal that the closest point lies on the face of the triangle. - */ - public static final int POINT_ON_TRIANGLE_FACE = 7; - - /** - * Return value of {@link #intersectRayAar(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectRayAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} - * to indicate that the ray intersects the side of the axis-aligned rectangle with the minimum x coordinate. - */ - public static final int AAR_SIDE_MINX = 0; - /** - * Return value of {@link #intersectRayAar(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectRayAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} - * to indicate that the ray intersects the side of the axis-aligned rectangle with the minimum y coordinate. - */ - public static final int AAR_SIDE_MINY = 1; - /** - * Return value of {@link #intersectRayAar(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectRayAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} - * to indicate that the ray intersects the side of the axis-aligned rectangle with the maximum x coordinate. - */ - public static final int AAR_SIDE_MAXX = 2; - /** - * Return value of {@link #intersectRayAar(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectRayAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} - * to indicate that the ray intersects the side of the axis-aligned rectangle with the maximum y coordinate. - */ - public static final int AAR_SIDE_MAXY = 3; - - /** - * Return value of {@link #intersectLineSegmentAab(float, float, float, float, float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectLineSegmentAab(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector2f)} to indicate that the line segment does not intersect the axis-aligned box; - * or return value of {@link #intersectLineSegmentAar(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectLineSegmentAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} to indicate that the line segment does not intersect the axis-aligned rectangle. - */ - public static final int OUTSIDE = -1; - /** - * Return value of {@link #intersectLineSegmentAab(float, float, float, float, float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectLineSegmentAab(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector2f)} to indicate that one end point of the line segment lies inside of the axis-aligned box; - * or return value of {@link #intersectLineSegmentAar(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectLineSegmentAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} to indicate that one end point of the line segment lies inside of the axis-aligned rectangle. - */ - public static final int ONE_INTERSECTION = 1; - /** - * Return value of {@link #intersectLineSegmentAab(float, float, float, float, float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectLineSegmentAab(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector2f)} to indicate that the line segment intersects two sides of the axis-aligned box - * or lies on an edge or a side of the box; - * or return value of {@link #intersectLineSegmentAar(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectLineSegmentAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} to indicate that the line segment intersects two edges of the axis-aligned rectangle - * or lies on an edge of the rectangle. - */ - public static final int TWO_INTERSECTION = 2; - /** - * Return value of {@link #intersectLineSegmentAab(float, float, float, float, float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectLineSegmentAab(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector2f)} to indicate that the line segment lies completely inside of the axis-aligned box; - * or return value of {@link #intersectLineSegmentAar(float, float, float, float, float, float, float, float, Vector2f)} and - * {@link #intersectLineSegmentAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f)} to indicate that the line segment lies completely inside of the axis-aligned rectangle. - */ - public static final int INSIDE = 3; - - /** - * Test whether the plane with the general plane equation a*x + b*y + c*z + d = 0 intersects the sphere with center - * (centerX, centerY, centerZ) and radius. - *

- * Reference: http://math.stackexchange.com - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radius - * the radius of the sphere - * @return true iff the plane intersects the sphere; false otherwise - */ - public static boolean testPlaneSphere( - float a, float b, float c, float d, - float centerX, float centerY, float centerZ, float radius) { - float denom = (float) Math.sqrt(a * a + b * b + c * c); - float dist = (a * centerX + b * centerY + c * centerZ + d) / denom; - return -radius <= dist && dist <= radius; - } - - /** - * Test whether the given plane intersects the given sphere with center. - *

- * Reference: http://math.stackexchange.com - * - * @param plane - * the plane - * @param sphere - * the sphere - * @return true iff the plane intersects the sphere; false otherwise - */ - public static boolean testPlaneSphere(Planef plane, Spheref sphere) { - return testPlaneSphere(plane.a, plane.b, plane.c, plane.d, sphere.x, sphere.y, sphere.z, sphere.r); - } - - /** - * Test whether the plane with the general plane equation a*x + b*y + c*z + d = 0 intersects the sphere with center - * (centerX, centerY, centerZ) and radius, and store the center of the circle of - * intersection in the (x, y, z) components of the supplied vector and the radius of that circle in the w component. - *

- * Reference: http://math.stackexchange.com - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radius - * the radius of the sphere - * @param intersectionCenterAndRadius - * will hold the center of the circle of intersection in the (x, y, z) components and the radius in the w component - * @return true iff the plane intersects the sphere; false otherwise - */ - public static boolean intersectPlaneSphere( - float a, float b, float c, float d, - float centerX, float centerY, float centerZ, float radius, - Vector4f intersectionCenterAndRadius) { - float invDenom = Math.invsqrt(a * a + b * b + c * c); - float dist = (a * centerX + b * centerY + c * centerZ + d) * invDenom; - if (-radius <= dist && dist <= radius) { - intersectionCenterAndRadius.x = centerX + dist * a * invDenom; - intersectionCenterAndRadius.y = centerY + dist * b * invDenom; - intersectionCenterAndRadius.z = centerZ + dist * c * invDenom; - intersectionCenterAndRadius.w = (float) Math.sqrt(radius * radius - dist * dist); - return true; - } - return false; - } - - /** - * Test whether the plane with the general plane equation a*x + b*y + c*z + d = 0 intersects the moving sphere with center - * (cX, cY, cZ), radius and velocity (vX, vY, vZ), and store the point of intersection - * in the (x, y, z) components of the supplied vector and the time of intersection in the w component. - *

- * The normal vector (a, b, c) of the plane equation needs to be normalized. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.5.3 "Intersecting Moving Sphere Against Plane" - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param cX - * the x coordinate of the center position of the sphere at t=0 - * @param cY - * the y coordinate of the center position of the sphere at t=0 - * @param cZ - * the z coordinate of the center position of the sphere at t=0 - * @param radius - * the sphere's radius - * @param vX - * the x component of the velocity of the sphere - * @param vY - * the y component of the velocity of the sphere - * @param vZ - * the z component of the velocity of the sphere - * @param pointAndTime - * will hold the point and time of intersection (if any) - * @return true iff the sphere intersects the plane; false otherwise - */ - public static boolean intersectPlaneSweptSphere( - float a, float b, float c, float d, - float cX, float cY, float cZ, float radius, - float vX, float vY, float vZ, - Vector4f pointAndTime) { - // Compute distance of sphere center to plane - float dist = a * cX + b * cY + c * cZ - d; - if (Math.abs(dist) <= radius) { - // The sphere is already overlapping the plane. Set time of - // intersection to zero and q to sphere center - pointAndTime.set(cX, cY, cZ, 0.0f); - return true; - } - float denom = a * vX + b * vY + c * vZ; - if (denom * dist >= 0.0f) { - // No intersection as sphere moving parallel to or away from plane - return false; - } - // Sphere is moving towards the plane - // Use +r in computations if sphere in front of plane, else -r - float r = dist > 0.0f ? radius : -radius; - float t = (r - dist) / denom; - pointAndTime.set( - cX + t * vX - r * a, - cY + t * vY - r * b, - cZ + t * vZ - r * c, - t); - return true; - } - - /** - * Test whether the plane with the general plane equation a*x + b*y + c*z + d = 0 intersects the sphere moving from center - * position (t0X, t0Y, t0Z) to (t1X, t1Y, t1Z) and having the given radius. - *

- * The normal vector (a, b, c) of the plane equation needs to be normalized. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.5.3 "Intersecting Moving Sphere Against Plane" - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param t0X - * the x coordinate of the start position of the sphere - * @param t0Y - * the y coordinate of the start position of the sphere - * @param t0Z - * the z coordinate of the start position of the sphere - * @param r - * the sphere's radius - * @param t1X - * the x coordinate of the end position of the sphere - * @param t1Y - * the y coordinate of the end position of the sphere - * @param t1Z - * the z coordinate of the end position of the sphere - * @return true if the sphere intersects the plane; false otherwise - */ - public static boolean testPlaneSweptSphere( - float a, float b, float c, float d, - float t0X, float t0Y, float t0Z, float r, - float t1X, float t1Y, float t1Z) { - // Get the distance for both a and b from plane p - float adist = t0X * a + t0Y * b + t0Z * c - d; - float bdist = t1X * a + t1Y * b + t1Z * c - d; - // Intersects if on different sides of plane (distances have different signs) - if (adist * bdist < 0.0f) return true; - // Intersects if start or end position within radius from plane - if (Math.abs(adist) <= r || Math.abs(bdist) <= r) return true; - // No intersection - return false; - } - - /** - * Test whether the axis-aligned box with minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ) - * intersects the plane with the general equation a*x + b*y + c*z + d = 0. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned box - * @param minY - * the y coordinate of the minimum corner of the axis-aligned box - * @param minZ - * the z coordinate of the minimum corner of the axis-aligned box - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned box - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned box - * @param maxZ - * the z coordinate of the maximum corner of the axis-aligned box - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return true iff the axis-aligned box intersects the plane; false otherwise - */ - public static boolean testAabPlane( - float minX, float minY, float minZ, - float maxX, float maxY, float maxZ, - float a, float b, float c, float d) { - float pX, pY, pZ, nX, nY, nZ; - if (a > 0.0f) { - pX = maxX; - nX = minX; - } else { - pX = minX; - nX = maxX; - } - if (b > 0.0f) { - pY = maxY; - nY = minY; - } else { - pY = minY; - nY = maxY; - } - if (c > 0.0f) { - pZ = maxZ; - nZ = minZ; - } else { - pZ = minZ; - nZ = maxZ; - } - float distN = d + a * nX + b * nY + c * nZ; - float distP = d + a * pX + b * pY + c * pZ; - return distN <= 0.0f && distP >= 0.0f; - } - - /** - * Test whether the axis-aligned box intersects the plane. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param aabb - * the AABB - * @param plane - * the plane - * @return true iff the axis-aligned box intersects the plane; false otherwise - */ - public static boolean testAabPlane(AABBf aabb, Planef plane) { - return testAabPlane(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, plane.a, plane.b, plane.c, plane.d); - } - - /** - * Test whether the axis-aligned box intersects the plane. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param aabb - * the AABB - * @param plane - * the plane - * @return true iff the axis-aligned box intersects the plane; false otherwise - */ - public static boolean testAabPlane(AABBi aabb, Planef plane ) { - return testAabPlane(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, plane.a, plane.b, plane.c, plane.d); - } - - /** - * Test whether the axis-aligned box with minimum corner min and maximum corner max - * intersects the plane with the general equation a*x + b*y + c*z + d = 0. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return true iff the axis-aligned box intersects the plane; false otherwise - */ - public static boolean testAabPlane(Vector3fc min, Vector3fc max, float a, float b, float c, float d) { - return testAabPlane(min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), a, b, c, d); - } - - /** - * Test whether the axis-aligned box with minimum corner (minXA, minYA, minZA) and maximum corner (maxXA, maxYA, maxZA) - * intersects the axis-aligned box with minimum corner (minXB, minYB, minZB) and maximum corner (maxXB, maxYB, maxZB). - * - * @param minXA - * the x coordinate of the minimum corner of the first axis-aligned box - * @param minYA - * the y coordinate of the minimum corner of the first axis-aligned box - * @param minZA - * the z coordinate of the minimum corner of the first axis-aligned box - * @param maxXA - * the x coordinate of the maximum corner of the first axis-aligned box - * @param maxYA - * the y coordinate of the maximum corner of the first axis-aligned box - * @param maxZA - * the z coordinate of the maximum corner of the first axis-aligned box - * @param minXB - * the x coordinate of the minimum corner of the second axis-aligned box - * @param minYB - * the y coordinate of the minimum corner of the second axis-aligned box - * @param minZB - * the z coordinate of the minimum corner of the second axis-aligned box - * @param maxXB - * the x coordinate of the maximum corner of the second axis-aligned box - * @param maxYB - * the y coordinate of the maximum corner of the second axis-aligned box - * @param maxZB - * the z coordinate of the maximum corner of the second axis-aligned box - * @return true iff both axis-aligned boxes intersect; false otherwise - */ - public static boolean testAabAab( - float minXA, float minYA, float minZA, - float maxXA, float maxYA, float maxZA, - float minXB, float minYB, float minZB, - float maxXB, float maxYB, float maxZB) { - return maxXA >= minXB && maxYA >= minYB && maxZA >= minZB && - minXA <= maxXB && minYA <= maxYB && minZA <= maxZB; - } - - /** - * Test whether the axis-aligned box with minimum corner minA and maximum corner maxA - * intersects the axis-aligned box with minimum corner minB and maximum corner maxB. - * - * @param minA - * the minimum corner of the first axis-aligned box - * @param maxA - * the maximum corner of the first axis-aligned box - * @param minB - * the minimum corner of the second axis-aligned box - * @param maxB - * the maximum corner of the second axis-aligned box - * @return true iff both axis-aligned boxes intersect; false otherwise - */ - public static boolean testAabAab(Vector3fc minA, Vector3fc maxA, Vector3fc minB, Vector3fc maxB) { - return testAabAab(minA.x(), minA.y(), minA.z(), maxA.x(), maxA.y(), maxA.z(), minB.x(), minB.y(), minB.z(), maxB.x(), maxB.y(), maxB.z()); - } - - /** - * Test whether the two axis-aligned boxes intersect. - * - * @param aabb1 - * the first AABB - * @param aabb2 - * the second AABB - * @return true iff both axis-aligned boxes intersect; false otherwise - */ - public static boolean testAabAab(AABBf aabb1, AABBf aabb2) { - return testAabAab(aabb1.minX, aabb1.minY, aabb1.minZ, aabb1.maxX, aabb1.maxY, aabb1.maxZ, aabb2.minX, aabb2.minY, aabb2.minZ, aabb2.maxX, aabb2.maxY, aabb2.maxZ); - } - - /** - * Test whether two oriented boxes given via their center position, orientation and half-size, intersect. - *

- * The orientation of a box is given as three unit vectors spanning the local orthonormal basis of the box. - *

- * The size is given as the half-size along each of the unit vectors defining the orthonormal basis. - *

- * Reference: Book "Real-Time Collision Detection" chapter 4.4.1 "OBB-OBB Intersection" - * - * @param b0c - * the center of the first box - * @param b0uX - * the local X unit vector of the first box - * @param b0uY - * the local Y unit vector of the first box - * @param b0uZ - * the local Z unit vector of the first box - * @param b0hs - * the half-size of the first box - * @param b1c - * the center of the second box - * @param b1uX - * the local X unit vector of the second box - * @param b1uY - * the local Y unit vector of the second box - * @param b1uZ - * the local Z unit vector of the second box - * @param b1hs - * the half-size of the second box - * @return true if both boxes intersect; false otherwise - */ - public static boolean testObOb( - Vector3f b0c, Vector3f b0uX, Vector3f b0uY, Vector3f b0uZ, Vector3f b0hs, - Vector3f b1c, Vector3f b1uX, Vector3f b1uY, Vector3f b1uZ, Vector3f b1hs) { - return testObOb( - b0c.x, b0c.y, b0c.z, b0uX.x, b0uX.y, b0uX.z, b0uY.x, b0uY.y, b0uY.z, b0uZ.x, b0uZ.y, b0uZ.z, b0hs.x, b0hs.y, b0hs.z, - b1c.x, b1c.y, b1c.z, b1uX.x, b1uX.y, b1uX.z, b1uY.x, b1uY.y, b1uY.z, b1uZ.x, b1uZ.y, b1uZ.z, b1hs.x, b1hs.y, b1hs.z); - } - - /** - * Test whether two oriented boxes given via their center position, orientation and half-size, intersect. - *

- * The orientation of a box is given as three unit vectors spanning the local orthonormal basis of the box. - *

- * The size is given as the half-size along each of the unit vectors defining the orthonormal basis. - *

- * Reference: Book "Real-Time Collision Detection" chapter 4.4.1 "OBB-OBB Intersection" - * - * @param b0cX - * the x coordinate of the center of the first box - * @param b0cY - * the y coordinate of the center of the first box - * @param b0cZ - * the z coordinate of the center of the first box - * @param b0uXx - * the x coordinate of the local X unit vector of the first box - * @param b0uXy - * the y coordinate of the local X unit vector of the first box - * @param b0uXz - * the z coordinate of the local X unit vector of the first box - * @param b0uYx - * the x coordinate of the local Y unit vector of the first box - * @param b0uYy - * the y coordinate of the local Y unit vector of the first box - * @param b0uYz - * the z coordinate of the local Y unit vector of the first box - * @param b0uZx - * the x coordinate of the local Z unit vector of the first box - * @param b0uZy - * the y coordinate of the local Z unit vector of the first box - * @param b0uZz - * the z coordinate of the local Z unit vector of the first box - * @param b0hsX - * the half-size of the first box along its local X axis - * @param b0hsY - * the half-size of the first box along its local Y axis - * @param b0hsZ - * the half-size of the first box along its local Z axis - * @param b1cX - * the x coordinate of the center of the second box - * @param b1cY - * the y coordinate of the center of the second box - * @param b1cZ - * the z coordinate of the center of the second box - * @param b1uXx - * the x coordinate of the local X unit vector of the second box - * @param b1uXy - * the y coordinate of the local X unit vector of the second box - * @param b1uXz - * the z coordinate of the local X unit vector of the second box - * @param b1uYx - * the x coordinate of the local Y unit vector of the second box - * @param b1uYy - * the y coordinate of the local Y unit vector of the second box - * @param b1uYz - * the z coordinate of the local Y unit vector of the second box - * @param b1uZx - * the x coordinate of the local Z unit vector of the second box - * @param b1uZy - * the y coordinate of the local Z unit vector of the second box - * @param b1uZz - * the z coordinate of the local Z unit vector of the second box - * @param b1hsX - * the half-size of the second box along its local X axis - * @param b1hsY - * the half-size of the second box along its local Y axis - * @param b1hsZ - * the half-size of the second box along its local Z axis - * @return true if both boxes intersect; false otherwise - */ - public static boolean testObOb( - float b0cX, float b0cY, float b0cZ, float b0uXx, float b0uXy, float b0uXz, float b0uYx, float b0uYy, float b0uYz, float b0uZx, float b0uZy, float b0uZz, float b0hsX, float b0hsY, float b0hsZ, - float b1cX, float b1cY, float b1cZ, float b1uXx, float b1uXy, float b1uXz, float b1uYx, float b1uYy, float b1uYz, float b1uZx, float b1uZy, float b1uZz, float b1hsX, float b1hsY, float b1hsZ) { - float ra, rb; - // Compute rotation matrix expressing b in a's coordinate frame - float rm00 = b0uXx * b1uXx + b0uYx * b1uYx + b0uZx * b1uZx; - float rm10 = b0uXx * b1uXy + b0uYx * b1uYy + b0uZx * b1uZy; - float rm20 = b0uXx * b1uXz + b0uYx * b1uYz + b0uZx * b1uZz; - float rm01 = b0uXy * b1uXx + b0uYy * b1uYx + b0uZy * b1uZx; - float rm11 = b0uXy * b1uXy + b0uYy * b1uYy + b0uZy * b1uZy; - float rm21 = b0uXy * b1uXz + b0uYy * b1uYz + b0uZy * b1uZz; - float rm02 = b0uXz * b1uXx + b0uYz * b1uYx + b0uZz * b1uZx; - float rm12 = b0uXz * b1uXy + b0uYz * b1uYy + b0uZz * b1uZy; - float rm22 = b0uXz * b1uXz + b0uYz * b1uYz + b0uZz * b1uZz; - // Compute common subexpressions. Add in an epsilon term to - // counteract arithmetic errors when two edges are parallel and - // their cross product is (near) null (see text for details) - float EPSILON = 1E-5f; - float arm00 = Math.abs(rm00) + EPSILON; - float arm01 = Math.abs(rm01) + EPSILON; - float arm02 = Math.abs(rm02) + EPSILON; - float arm10 = Math.abs(rm10) + EPSILON; - float arm11 = Math.abs(rm11) + EPSILON; - float arm12 = Math.abs(rm12) + EPSILON; - float arm20 = Math.abs(rm20) + EPSILON; - float arm21 = Math.abs(rm21) + EPSILON; - float arm22 = Math.abs(rm22) + EPSILON; - // Compute translation vector t - float tx = b1cX - b0cX, ty = b1cY - b0cY, tz = b1cZ - b0cZ; - // Bring translation into a's coordinate frame - float tax = tx * b0uXx + ty * b0uXy + tz * b0uXz; - float tay = tx * b0uYx + ty * b0uYy + tz * b0uYz; - float taz = tx * b0uZx + ty * b0uZy + tz * b0uZz; - // Test axes L = A0, L = A1, L = A2 - ra = b0hsX; - rb = b1hsX * arm00 + b1hsY * arm01 + b1hsZ * arm02; - if (Math.abs(tax) > ra + rb) return false; - ra = b0hsY; - rb = b1hsX * arm10 + b1hsY * arm11 + b1hsZ * arm12; - if (Math.abs(tay) > ra + rb) return false; - ra = b0hsZ; - rb = b1hsX * arm20 + b1hsY * arm21 + b1hsZ * arm22; - if (Math.abs(taz) > ra + rb) return false; - // Test axes L = B0, L = B1, L = B2 - ra = b0hsX * arm00 + b0hsY * arm10 + b0hsZ * arm20; - rb = b1hsX; - if (Math.abs(tax * rm00 + tay * rm10 + taz * rm20) > ra + rb) return false; - ra = b0hsX * arm01 + b0hsY * arm11 + b0hsZ * arm21; - rb = b1hsY; - if (Math.abs(tax * rm01 + tay * rm11 + taz * rm21) > ra + rb) return false; - ra = b0hsX * arm02 + b0hsY * arm12 + b0hsZ * arm22; - rb = b1hsZ; - if (Math.abs(tax * rm02 + tay * rm12 + taz * rm22) > ra + rb) return false; - // Test axis L = A0 x B0 - ra = b0hsY * arm20 + b0hsZ * arm10; - rb = b1hsY * arm02 + b1hsZ * arm01; - if (Math.abs(taz * rm10 - tay * rm20) > ra + rb) return false; - // Test axis L = A0 x B1 - ra = b0hsY * arm21 + b0hsZ * arm11; - rb = b1hsX * arm02 + b1hsZ * arm00; - if (Math.abs(taz * rm11 - tay * rm21) > ra + rb) return false; - // Test axis L = A0 x B2 - ra = b0hsY * arm22 + b0hsZ * arm12; - rb = b1hsX * arm01 + b1hsY * arm00; - if (Math.abs(taz * rm12 - tay * rm22) > ra + rb) return false; - // Test axis L = A1 x B0 - ra = b0hsX * arm20 + b0hsZ * arm00; - rb = b1hsY * arm12 + b1hsZ * arm11; - if (Math.abs(tax * rm20 - taz * rm00) > ra + rb) return false; - // Test axis L = A1 x B1 - ra = b0hsX * arm21 + b0hsZ * arm01; - rb = b1hsX * arm12 + b1hsZ * arm10; - if (Math.abs(tax * rm21 - taz * rm01) > ra + rb) return false; - // Test axis L = A1 x B2 - ra = b0hsX * arm22 + b0hsZ * arm02; - rb = b1hsX * arm11 + b1hsY * arm10; - if (Math.abs(tax * rm22 - taz * rm02) > ra + rb) return false; - // Test axis L = A2 x B0 - ra = b0hsX * arm10 + b0hsY * arm00; - rb = b1hsY * arm22 + b1hsZ * arm21; - if (Math.abs(tay * rm00 - tax * rm10) > ra + rb) return false; - // Test axis L = A2 x B1 - ra = b0hsX * arm11 + b0hsY * arm01; - rb = b1hsX * arm22 + b1hsZ * arm20; - if (Math.abs(tay * rm01 - tax * rm11) > ra + rb) return false; - // Test axis L = A2 x B2 - ra = b0hsX * arm12 + b0hsY * arm02; - rb = b1hsX * arm21 + b1hsY * arm20; - if (Math.abs(tay * rm02 - tax * rm12) > ra + rb) return false; - // Since no separating axis is found, the OBBs must be intersecting - return true; - } - - /** - * Test whether the one sphere with center (aX, aY, aZ) and square radius radiusSquaredA intersects the other - * sphere with center (bX, bY, bZ) and square radius radiusSquaredB, and store the center of the circle of - * intersection in the (x, y, z) components of the supplied vector and the radius of that circle in the w component. - *

- * The normal vector of the circle of intersection can simply be obtained by subtracting the center of either sphere from the other. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param aX - * the x coordinate of the first sphere's center - * @param aY - * the y coordinate of the first sphere's center - * @param aZ - * the z coordinate of the first sphere's center - * @param radiusSquaredA - * the square of the first sphere's radius - * @param bX - * the x coordinate of the second sphere's center - * @param bY - * the y coordinate of the second sphere's center - * @param bZ - * the z coordinate of the second sphere's center - * @param radiusSquaredB - * the square of the second sphere's radius - * @param centerAndRadiusOfIntersectionCircle - * will hold the center of the circle of intersection in the (x, y, z) components and the radius in the w component - * @return true iff both spheres intersect; false otherwise - */ - public static boolean intersectSphereSphere( - float aX, float aY, float aZ, float radiusSquaredA, - float bX, float bY, float bZ, float radiusSquaredB, - Vector4f centerAndRadiusOfIntersectionCircle) { - float dX = bX - aX, dY = bY - aY, dZ = bZ - aZ; - float distSquared = dX * dX + dY * dY + dZ * dZ; - float h = 0.5f + (radiusSquaredA - radiusSquaredB) / distSquared; - float r_i = radiusSquaredA - h * h * distSquared; - if (r_i >= 0.0f) { - centerAndRadiusOfIntersectionCircle.x = aX + h * dX; - centerAndRadiusOfIntersectionCircle.y = aY + h * dY; - centerAndRadiusOfIntersectionCircle.z = aZ + h * dZ; - centerAndRadiusOfIntersectionCircle.w = (float) Math.sqrt(r_i); - return true; - } - return false; - } - - /** - * Test whether the one sphere with center centerA and square radius radiusSquaredA intersects the other - * sphere with center centerB and square radius radiusSquaredB, and store the center of the circle of - * intersection in the (x, y, z) components of the supplied vector and the radius of that circle in the w component. - *

- * The normal vector of the circle of intersection can simply be obtained by subtracting the center of either sphere from the other. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param centerA - * the first sphere's center - * @param radiusSquaredA - * the square of the first sphere's radius - * @param centerB - * the second sphere's center - * @param radiusSquaredB - * the square of the second sphere's radius - * @param centerAndRadiusOfIntersectionCircle - * will hold the center of the circle of intersection in the (x, y, z) components and the radius in the w component - * @return true iff both spheres intersect; false otherwise - */ - public static boolean intersectSphereSphere(Vector3fc centerA, float radiusSquaredA, Vector3fc centerB, float radiusSquaredB, Vector4f centerAndRadiusOfIntersectionCircle) { - return intersectSphereSphere(centerA.x(), centerA.y(), centerA.z(), radiusSquaredA, centerB.x(), centerB.y(), centerB.z(), radiusSquaredB, centerAndRadiusOfIntersectionCircle); - } - - /** - * Test whether the one sphere with intersects the other sphere, and store the center of the circle of - * intersection in the (x, y, z) components of the supplied vector and the radius of that circle in the w component. - *

- * The normal vector of the circle of intersection can simply be obtained by subtracting the center of either sphere from the other. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param sphereA - * the first sphere - * @param sphereB - * the second sphere - * @param centerAndRadiusOfIntersectionCircle - * will hold the center of the circle of intersection in the (x, y, z) components and the radius in the w component - * @return true iff both spheres intersect; false otherwise - */ - public static boolean intersectSphereSphere(Spheref sphereA, Spheref sphereB, Vector4f centerAndRadiusOfIntersectionCircle) { - return intersectSphereSphere(sphereA.x, sphereA.y, sphereA.z, sphereA.r*sphereA.r, sphereB.x, sphereB.y, sphereB.z, sphereB.r*sphereB.r, centerAndRadiusOfIntersectionCircle); - } - - /** - * Test whether the given sphere with center (sX, sY, sZ) intersects the triangle given by its three vertices, and if they intersect - * store the point of intersection into result. - *

- * This method also returns whether the point of intersection is on one of the triangle's vertices, edges or on the face. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.2.7 "Testing Sphere Against Triangle" - * - * @param sX - * the x coordinate of the sphere's center - * @param sY - * the y coordinate of the sphere's center - * @param sZ - * the z coordinate of the sphere's center - * @param sR - * the sphere's radius - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v0Z - * the z coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v1Z - * the z coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @param v2Z - * the z coordinate of the third vertex of the triangle - * @param result - * will hold the point of intersection - * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}, - * {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or - * {@link #POINT_ON_TRIANGLE_FACE} or 0 - */ - public static int intersectSphereTriangle( - float sX, float sY, float sZ, float sR, - float v0X, float v0Y, float v0Z, - float v1X, float v1Y, float v1Z, - float v2X, float v2Y, float v2Z, - Vector3f result) { - int closest = findClosestPointOnTriangle(v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z, sX, sY, sZ, result); - float vX = result.x - sX, vY = result.y - sY, vZ = result.z - sZ; - float dot = vX * vX + vY * vY + vZ * vZ; - if (dot <= sR * sR) { - return closest; - } - return 0; - } - - /** - * Test whether the one sphere with center (aX, aY, aZ) and square radius radiusSquaredA intersects the other - * sphere with center (bX, bY, bZ) and square radius radiusSquaredB. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param aX - * the x coordinate of the first sphere's center - * @param aY - * the y coordinate of the first sphere's center - * @param aZ - * the z coordinate of the first sphere's center - * @param radiusSquaredA - * the square of the first sphere's radius - * @param bX - * the x coordinate of the second sphere's center - * @param bY - * the y coordinate of the second sphere's center - * @param bZ - * the z coordinate of the second sphere's center - * @param radiusSquaredB - * the square of the second sphere's radius - * @return true iff both spheres intersect; false otherwise - */ - public static boolean testSphereSphere( - float aX, float aY, float aZ, float radiusSquaredA, - float bX, float bY, float bZ, float radiusSquaredB) { - float dX = bX - aX, dY = bY - aY, dZ = bZ - aZ; - float distSquared = dX * dX + dY * dY + dZ * dZ; - float h = 0.5f + (radiusSquaredA - radiusSquaredB) / distSquared; - float r_i = radiusSquaredA - h * h * distSquared; - return r_i >= 0.0f; - } - - /** - * Test whether the one sphere with center centerA and square radius radiusSquaredA intersects the other - * sphere with center centerB and square radius radiusSquaredB. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param centerA - * the first sphere's center - * @param radiusSquaredA - * the square of the first sphere's radius - * @param centerB - * the second sphere's center - * @param radiusSquaredB - * the square of the second sphere's radius - * @return true iff both spheres intersect; false otherwise - */ - public static boolean testSphereSphere(Vector3fc centerA, float radiusSquaredA, Vector3fc centerB, float radiusSquaredB) { - return testSphereSphere(centerA.x(), centerA.y(), centerA.z(), radiusSquaredA, centerB.x(), centerB.y(), centerB.z(), radiusSquaredB); - } - - /** - * Determine the signed distance of the given point (pointX, pointY, pointZ) to the plane specified via its general plane equation - * a*x + b*y + c*z + d = 0. - * - * @param pointX - * the x coordinate of the point - * @param pointY - * the y coordinate of the point - * @param pointZ - * the z coordinate of the point - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return the distance between the point and the plane - */ - public static float distancePointPlane(float pointX, float pointY, float pointZ, float a, float b, float c, float d) { - float denom = (float) Math.sqrt(a * a + b * b + c * c); - return (a * pointX + b * pointY + c * pointZ + d) / denom; - } - - /** - * Determine the signed distance of the given point (pointX, pointY, pointZ) to the plane of the triangle specified by its three points - * (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z). - *

- * If the point lies on the front-facing side of the triangle's plane, that is, if the triangle has counter-clockwise winding order - * as seen from the point, then this method returns a positive number. - * - * @param pointX - * the x coordinate of the point - * @param pointY - * the y coordinate of the point - * @param pointZ - * the z coordinate of the point - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v0Z - * the z coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v1Z - * the z coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @param v2Z - * the z coordinate of the third vertex of the triangle - * @return the signed distance between the point and the plane of the triangle - */ - public static float distancePointPlane(float pointX, float pointY, float pointZ, - float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z) { - float v1Y0Y = v1Y - v0Y; - float v2Z0Z = v2Z - v0Z; - float v2Y0Y = v2Y - v0Y; - float v1Z0Z = v1Z - v0Z; - float v2X0X = v2X - v0X; - float v1X0X = v1X - v0X; - float a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z; - float b = v1Z0Z * v2X0X - v2Z0Z * v1X0X; - float c = v1X0X * v2Y0Y - v2X0X * v1Y0Y; - float d = -(a * v0X + b * v0Y + c * v0Z); - return distancePointPlane(pointX, pointY, pointZ, a, b, c, d); - } - - /** - * Test whether the ray with given origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) intersects the plane - * containing the given point (pointX, pointY, pointZ) and having the normal (normalX, normalY, normalZ), and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the plane, because it is either parallel to the plane or its direction points - * away from the plane or the ray's origin is on the negative side of the plane (i.e. the plane's normal points away from the ray's origin). - *

- * Reference: https://www.siggraph.org/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param pointX - * the x coordinate of a point on the plane - * @param pointY - * the y coordinate of a point on the plane - * @param pointZ - * the z coordinate of a point on the plane - * @param normalX - * the x coordinate of the plane's normal - * @param normalY - * the y coordinate of the plane's normal - * @param normalZ - * the z coordinate of the plane's normal - * @param epsilon - * some small epsilon for when the ray is parallel to the plane - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the plane; -1.0 otherwise - */ - public static float intersectRayPlane(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, - float pointX, float pointY, float pointZ, float normalX, float normalY, float normalZ, float epsilon) { - float denom = normalX * dirX + normalY * dirY + normalZ * dirZ; - if (denom < epsilon) { - float t = ((pointX - originX) * normalX + (pointY - originY) * normalY + (pointZ - originZ) * normalZ) / denom; - if (t >= 0.0f) - return t; - } - return -1.0f; - } - - /** - * Test whether the ray with given origin and direction dir intersects the plane - * containing the given point and having the given normal, and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the plane, because it is either parallel to the plane or its direction points - * away from the plane or the ray's origin is on the negative side of the plane (i.e. the plane's normal points away from the ray's origin). - *

- * Reference: https://www.siggraph.org/ - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param point - * a point on the plane - * @param normal - * the plane's normal - * @param epsilon - * some small epsilon for when the ray is parallel to the plane - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the plane; -1.0 otherwise - */ - public static float intersectRayPlane(Vector3fc origin, Vector3fc dir, Vector3fc point, Vector3fc normal, float epsilon) { - return intersectRayPlane(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), point.x(), point.y(), point.z(), normal.x(), normal.y(), normal.z(), epsilon); - } - - /** - * Test whether the given ray intersects the given plane, and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the plane, because it is either parallel to the plane or its direction points - * away from the plane or the ray's origin is on the negative side of the plane (i.e. the plane's normal points away from the ray's origin). - *

- * Reference: https://www.siggraph.org/ - * - * @param ray - * the ray - * @param plane - * the plane - * @param epsilon - * some small epsilon for when the ray is parallel to the plane - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the plane; -1.0 otherwise - */ - public static float intersectRayPlane(Rayf ray, Planef plane, float epsilon) { - return intersectRayPlane(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, plane.a, plane.b, plane.c, plane.d, epsilon); - } - - /** - * Test whether the ray with given origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) intersects the plane - * given as the general plane equation a*x + b*y + c*z + d = 0, and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the plane, because it is either parallel to the plane or its direction points - * away from the plane or the ray's origin is on the negative side of the plane (i.e. the plane's normal points away from the ray's origin). - *

- * Reference: https://www.siggraph.org/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param epsilon - * some small epsilon for when the ray is parallel to the plane - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the plane; -1.0 otherwise - */ - public static float intersectRayPlane(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, - float a, float b, float c, float d, float epsilon) { - float denom = a * dirX + b * dirY + c * dirZ; - if (denom < 0.0f) { - float t = -(a * originX + b * originY + c * originZ + d) / denom; - if (t >= 0.0f) - return t; - } - return -1.0f; - } - - /** - * Test whether the axis-aligned box with minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ) - * intersects the sphere with the given center (centerX, centerY, centerZ) and square radius radiusSquared. - *

- * Reference: http://stackoverflow.com - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned box - * @param minY - * the y coordinate of the minimum corner of the axis-aligned box - * @param minZ - * the z coordinate of the minimum corner of the axis-aligned box - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned box - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned box - * @param maxZ - * the z coordinate of the maximum corner of the axis-aligned box - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radiusSquared - * the square of the sphere's radius - * @return true iff the axis-aligned box intersects the sphere; false otherwise - */ - public static boolean testAabSphere( - float minX, float minY, float minZ, - float maxX, float maxY, float maxZ, - float centerX, float centerY, float centerZ, float radiusSquared) { - float radius2 = radiusSquared; - if (centerX < minX) { - float d = (centerX - minX); - radius2 -= d * d; - } else if (centerX > maxX) { - float d = (centerX - maxX); - radius2 -= d * d; - } - if (centerY < minY) { - float d = (centerY - minY); - radius2 -= d * d; - } else if (centerY > maxY) { - float d = (centerY - maxY); - radius2 -= d * d; - } - if (centerZ < minZ) { - float d = (centerZ - minZ); - radius2 -= d * d; - } else if (centerZ > maxZ) { - float d = (centerZ - maxZ); - radius2 -= d * d; - } - return radius2 >= 0.0f; - } - - /** - * Test whether the axis-aligned box with minimum corner min and maximum corner max - * intersects the sphere with the given center and square radius radiusSquared. - *

- * Reference: http://stackoverflow.com - * - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @param center - * the sphere's center - * @param radiusSquared - * the squared of the sphere's radius - * @return true iff the axis-aligned box intersects the sphere; false otherwise - */ - public static boolean testAabSphere(Vector3fc min, Vector3fc max, Vector3fc center, float radiusSquared) { - return testAabSphere(min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), center.x(), center.y(), center.z(), radiusSquared); - } - - /** - * Test whether the given axis-aligned box intersects the given sphere. - *

- * Reference: http://stackoverflow.com - * - * @param aabb - * the AABB - * @param sphere - * the sphere - * @return true iff the axis-aligned box intersects the sphere; false otherwise - */ - public static boolean testAabSphere(AABBf aabb, Spheref sphere) { - return testAabSphere(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, sphere.x, sphere.y, sphere.z, sphere.r*sphere.r); - } - - - /** - * Test whether the given axis-aligned box intersects the given sphere. - *

- * Reference: http://stackoverflow.com - * - * @param aabb - * the AABB - * @param sphere - * the sphere - * @return true iff the axis-aligned box intersects the sphere; false otherwise - */ - public static boolean testAabSphere(AABBi aabb, Spheref sphere) { - return testAabSphere(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, sphere.x, sphere.y, sphere.z, sphere.r*sphere.r); - } - - /** - * Find the point on the given plane which is closest to the specified point (pX, pY, pZ) and store the result in result. - * - * @param aX - * the x coordinate of one point on the plane - * @param aY - * the y coordinate of one point on the plane - * @param aZ - * the z coordinate of one point on the plane - * @param nX - * the x coordinate of the unit normal of the plane - * @param nY - * the y coordinate of the unit normal of the plane - * @param nZ - * the z coordinate of the unit normal of the plane - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param pZ - * the z coordinate of the point - * @param result - * will hold the result - * @return result - */ - public static Vector3f findClosestPointOnPlane(float aX, float aY, float aZ, float nX, float nY, float nZ, float pX, float pY, float pZ, Vector3f result) { - float d = -(nX * aX + nY * aY + nZ * aZ); - float t = nX * pX + nY * pY + nZ * pZ - d; - result.x = pX - t * nX; - result.y = pY - t * nY; - result.z = pZ - t * nZ; - return result; - } - - /** - * Find the point on the given line segment which is closest to the specified point (pX, pY, pZ), and store the result in result. - * - * @param aX - * the x coordinate of the first end point of the line segment - * @param aY - * the y coordinate of the first end point of the line segment - * @param aZ - * the z coordinate of the first end point of the line segment - * @param bX - * the x coordinate of the second end point of the line segment - * @param bY - * the y coordinate of the second end point of the line segment - * @param bZ - * the z coordinate of the second end point of the line segment - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param pZ - * the z coordinate of the point - * @param result - * will hold the result - * @return result - */ - public static Vector3f findClosestPointOnLineSegment(float aX, float aY, float aZ, float bX, float bY, float bZ, float pX, float pY, float pZ, Vector3f result) { - float abX = bX - aX, abY = bY - aY, abZ = bZ - aZ; - float t = ((pX - aX) * abX + (pY - aY) * abY + (pZ - aZ) * abZ) / (abX * abX + abY * abY + abZ * abZ); - if (t < 0.0f) t = 0.0f; - if (t > 1.0f) t = 1.0f; - result.x = aX + t * abX; - result.y = aY + t * abY; - result.z = aZ + t * abZ; - return result; - } - - /** - * Find the closest points on the two line segments, store the point on the first line segment in resultA and - * the point on the second line segment in resultB, and return the square distance between both points. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.9 "Closest Points of Two Line Segments" - * - * @param a0X - * the x coordinate of the first line segment's first end point - * @param a0Y - * the y coordinate of the first line segment's first end point - * @param a0Z - * the z coordinate of the first line segment's first end point - * @param a1X - * the x coordinate of the first line segment's second end point - * @param a1Y - * the y coordinate of the first line segment's second end point - * @param a1Z - * the z coordinate of the first line segment's second end point - * @param b0X - * the x coordinate of the second line segment's first end point - * @param b0Y - * the y coordinate of the second line segment's first end point - * @param b0Z - * the z coordinate of the second line segment's first end point - * @param b1X - * the x coordinate of the second line segment's second end point - * @param b1Y - * the y coordinate of the second line segment's second end point - * @param b1Z - * the z coordinate of the second line segment's second end point - * @param resultA - * will hold the point on the first line segment - * @param resultB - * will hold the point on the second line segment - * @return the square distance between the two closest points - */ - public static float findClosestPointsLineSegments( - float a0X, float a0Y, float a0Z, float a1X, float a1Y, float a1Z, - float b0X, float b0Y, float b0Z, float b1X, float b1Y, float b1Z, - Vector3f resultA, Vector3f resultB) { - float d1x = a1X - a0X, d1y = a1Y - a0Y, d1z = a1Z - a0Z; - float d2x = b1X - b0X, d2y = b1Y - b0Y, d2z = b1Z - b0Z; - float rX = a0X - b0X, rY = a0Y - b0Y, rZ = a0Z - b0Z; - float a = d1x * d1x + d1y * d1y + d1z * d1z; - float e = d2x * d2x + d2y * d2y + d2z * d2z; - float f = d2x * rX + d2y * rY + d2z * rZ; - float EPSILON = 1E-5f; - float s, t; - if (a <= EPSILON && e <= EPSILON) { - // Both segments degenerate into points - resultA.set(a0X, a0Y, a0Z); - resultB.set(b0X, b0Y, b0Z); - return resultA.dot(resultB); - } - if (a <= EPSILON) { - // First segment degenerates into a point - s = 0.0f; - t = f / e; - t = Math.min(Math.max(t, 0.0f), 1.0f); - } else { - float c = d1x * rX + d1y * rY + d1z * rZ; - if (e <= EPSILON) { - // Second segment degenerates into a point - t = 0.0f; - s = Math.min(Math.max(-c / a, 0.0f), 1.0f); - } else { - // The general nondegenerate case starts here - float b = d1x * d2x + d1y * d2y + d1z * d2z; - float denom = a * e - b * b; - // If segments not parallel, compute closest point on L1 to L2 and - // clamp to segment S1. Else pick arbitrary s (here 0) - if (denom != 0.0) - s = Math.min(Math.max((b*f - c*e) / denom, 0.0f), 1.0f); - else - s = 0.0f; - // Compute point on L2 closest to S1(s) using - // t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e - t = (b * s + f) / e; - // If t in [0,1] done. Else clamp t, recompute s for the new value - // of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a - // and clamp s to [0, 1] - if (t < 0.0) { - t = 0.0f; - s = Math.min(Math.max(-c / a, 0.0f), 1.0f); - } else if (t > 1.0) { - t = 1.0f; - s = Math.min(Math.max((b - c) / a, 0.0f), 1.0f); - } - } - } - resultA.set(a0X + d1x * s, a0Y + d1y * s, a0Z + d1z * s); - resultB.set(b0X + d2x * t, b0Y + d2y * t, b0Z + d2z * t); - float dX = resultA.x - resultB.x, dY = resultA.y - resultB.y, dZ = resultA.z - resultB.z; - return dX*dX + dY*dY + dZ*dZ; - } - - /** - * Find the closest points on a line segment and a triangle. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.10 "Closest Points of a Line Segment and a Triangle" - * - * @param aX - * the x coordinate of the line segment's first end point - * @param aY - * the y coordinate of the line segment's first end point - * @param aZ - * the z coordinate of the line segment's first end point - * @param bX - * the x coordinate of the line segment's second end point - * @param bY - * the y coordinate of the line segment's second end point - * @param bZ - * the z coordinate of the line segment's second end point - * @param v0X - * the x coordinate of the triangle's first vertex - * @param v0Y - * the y coordinate of the triangle's first vertex - * @param v0Z - * the z coordinate of the triangle's first vertex - * @param v1X - * the x coordinate of the triangle's second vertex - * @param v1Y - * the y coordinate of the triangle's second vertex - * @param v1Z - * the z coordinate of the triangle's second vertex - * @param v2X - * the x coordinate of the triangle's third vertex - * @param v2Y - * the y coordinate of the triangle's third vertex - * @param v2Z - * the z coordinate of the triangle's third vertex - * @param lineSegmentResult - * will hold the closest point on the line segment - * @param triangleResult - * will hold the closest point on the triangle - * @return the square distance of the closest points - */ - public static float findClosestPointsLineSegmentTriangle( - float aX, float aY, float aZ, float bX, float bY, float bZ, - float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, - Vector3f lineSegmentResult, Vector3f triangleResult) { - float min, d; - float minlsX, minlsY, minlsZ, mintX, mintY, mintZ; - // AB -> V0V1 - d = findClosestPointsLineSegments(aX, aY, aZ, bX, bY, bZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, lineSegmentResult, triangleResult); - min = d; - minlsX = lineSegmentResult.x; minlsY = lineSegmentResult.y; minlsZ = lineSegmentResult.z; - mintX = triangleResult.x; mintY = triangleResult.y; mintZ = triangleResult.z; - // AB -> V1V2 - d = findClosestPointsLineSegments(aX, aY, aZ, bX, bY, bZ, v1X, v1Y, v1Z, v2X, v2Y, v2Z, lineSegmentResult, triangleResult); - if (d < min) { - min = d; - minlsX = lineSegmentResult.x; minlsY = lineSegmentResult.y; minlsZ = lineSegmentResult.z; - mintX = triangleResult.x; mintY = triangleResult.y; mintZ = triangleResult.z; - } - // AB -> V2V0 - d = findClosestPointsLineSegments(aX, aY, aZ, bX, bY, bZ, v2X, v2Y, v2Z, v0X, v0Y, v0Z, lineSegmentResult, triangleResult); - if (d < min) { - min = d; - minlsX = lineSegmentResult.x; minlsY = lineSegmentResult.y; minlsZ = lineSegmentResult.z; - mintX = triangleResult.x; mintY = triangleResult.y; mintZ = triangleResult.z; - } - // segment endpoint A and plane of triangle (when A projects inside V0V1V2) - boolean computed = false; - float a = Float.NaN, b = Float.NaN, c = Float.NaN, nd = Float.NaN; - if (testPointInTriangle(aX, aY, aZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z)) { - float v1Y0Y = v1Y - v0Y; - float v2Z0Z = v2Z - v0Z; - float v2Y0Y = v2Y - v0Y; - float v1Z0Z = v1Z - v0Z; - float v2X0X = v2X - v0X; - float v1X0X = v1X - v0X; - a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z; - b = v1Z0Z * v2X0X - v2Z0Z * v1X0X; - c = v1X0X * v2Y0Y - v2X0X * v1Y0Y; - computed = true; - float invLen = Math.invsqrt(a*a + b*b + c*c); - a *= invLen; b *= invLen; c *= invLen; - nd = -(a * v0X + b * v0Y + c * v0Z); - d = (a * aX + b * aY + c * aZ + nd); - float l = d; - d *= d; - if (d < min) { - min = d; - minlsX = aX; minlsY = aY; minlsZ = aZ; - mintX = aX - a*l; mintY = aY - b*l; mintZ = aZ - c*l; - } - } - // segment endpoint B and plane of triangle (when B projects inside V0V1V2) - if (testPointInTriangle(bX, bY, bZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z)) { - if (!computed) { - float v1Y0Y = v1Y - v0Y; - float v2Z0Z = v2Z - v0Z; - float v2Y0Y = v2Y - v0Y; - float v1Z0Z = v1Z - v0Z; - float v2X0X = v2X - v0X; - float v1X0X = v1X - v0X; - a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z; - b = v1Z0Z * v2X0X - v2Z0Z * v1X0X; - c = v1X0X * v2Y0Y - v2X0X * v1Y0Y; - float invLen = Math.invsqrt(a*a + b*b + c*c); - a *= invLen; b *= invLen; c *= invLen; - nd = -(a * v0X + b * v0Y + c * v0Z); - } - d = (a * bX + b * bY + c * bZ + nd); - float l = d; - d *= d; - if (d < min) { - min = d; - minlsX = bX; minlsY = bY; minlsZ = bZ; - mintX = bX - a*l; mintY = bY - b*l; mintZ = bZ - c*l; - } - } - lineSegmentResult.set(minlsX, minlsY, minlsZ); - triangleResult.set(mintX, mintY, mintZ); - return min; - } - - /** - * Determine the closest point on the triangle with the given vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z), (v2X, v2Y, v2Z) - * between that triangle and the given point (pX, pY, pZ) and store that point into the given result. - *

- * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}) - * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20}) - * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point" - * - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v0Z - * the z coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v1Z - * the z coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @param v2Z - * the z coordinate of the third vertex of the triangle - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param pZ - * the y coordinate of the point - * @param result - * will hold the closest point - * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}, - * {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or - * {@link #POINT_ON_TRIANGLE_FACE} - */ - public static int findClosestPointOnTriangle( - float v0X, float v0Y, float v0Z, - float v1X, float v1Y, float v1Z, - float v2X, float v2Y, float v2Z, - float pX, float pY, float pZ, - Vector3f result) { - float abX = v1X - v0X, abY = v1Y - v0Y, abZ = v1Z - v0Z; - float acX = v2X - v0X, acY = v2Y - v0Y, acZ = v2Z - v0Z; - float apX = pX - v0X, apY = pY - v0Y, apZ = pZ - v0Z; - float d1 = abX * apX + abY * apY + abZ * apZ; - float d2 = acX * apX + acY * apY + acZ * apZ; - if (d1 <= 0.0f && d2 <= 0.0f) { - result.x = v0X; - result.y = v0Y; - result.z = v0Z; - return POINT_ON_TRIANGLE_VERTEX_0; - } - float bpX = pX - v1X, bpY = pY - v1Y, bpZ = pZ - v1Z; - float d3 = abX * bpX + abY * bpY + abZ * bpZ; - float d4 = acX * bpX + acY * bpY + acZ * bpZ; - if (d3 >= 0.0f && d4 <= d3) { - result.x = v1X; - result.y = v1Y; - result.z = v1Z; - return POINT_ON_TRIANGLE_VERTEX_1; - } - float vc = d1 * d4 - d3 * d2; - if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) { - float v = d1 / (d1 - d3); - result.x = v0X + v * abX; - result.y = v0Y + v * abY; - result.z = v0Z + v * abZ; - return POINT_ON_TRIANGLE_EDGE_01; - } - float cpX = pX - v2X, cpY = pY - v2Y, cpZ = pZ - v2Z; - float d5 = abX * cpX + abY * cpY + abZ * cpZ; - float d6 = acX * cpX + acY * cpY + acZ * cpZ; - if (d6 >= 0.0f && d5 <= d6) { - result.x = v2X; - result.y = v2Y; - result.z = v2Z; - return POINT_ON_TRIANGLE_VERTEX_2; - } - float vb = d5 * d2 - d1 * d6; - if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) { - float w = d2 / (d2 - d6); - result.x = v0X + w * acX; - result.y = v0Y + w * acY; - result.z = v0Z + w * acZ; - return POINT_ON_TRIANGLE_EDGE_20; - } - float va = d3 * d6 - d5 * d4; - if (va <= 0.0f && d4 - d3 >= 0.0f && d5 - d6 >= 0.0f) { - float w = (d4 - d3) / (d4 - d3 + d5 - d6); - result.x = v1X + w * (v2X - v1X); - result.y = v1Y + w * (v2Y - v1Y); - result.z = v1Z + w * (v2Z - v1Z); - return POINT_ON_TRIANGLE_EDGE_12; - } - float denom = 1.0f / (va + vb + vc); - float v = vb * denom; - float w = vc * denom; - result.x = v0X + abX * v + acX * w; - result.y = v0Y + abY * v + acY * w; - result.z = v0Z + abZ * v + acZ * w; - return POINT_ON_TRIANGLE_FACE; - } - - /** - * Determine the closest point on the triangle with the vertices v0, v1, v2 - * between that triangle and the given point p and store that point into the given result. - *

- * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}) - * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20}) - * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point" - * - * @param v0 - * the first vertex of the triangle - * @param v1 - * the second vertex of the triangle - * @param v2 - * the third vertex of the triangle - * @param p - * the point - * @param result - * will hold the closest point - * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}, - * {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or - * {@link #POINT_ON_TRIANGLE_FACE} - */ - public static int findClosestPointOnTriangle(Vector3fc v0, Vector3fc v1, Vector3fc v2, Vector3fc p, Vector3f result) { - return findClosestPointOnTriangle(v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), p.x(), p.y(), p.z(), result); - } - - /** - * Find the point on a given rectangle, specified via three of its corners, which is closest to the specified point - * (pX, pY, pZ) and store the result into res. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.4.2 "Closest Point on 3D Rectangle to Point" - * - * @param aX - * the x coordinate of the first corner point of the rectangle - * @param aY - * the y coordinate of the first corner point of the rectangle - * @param aZ - * the z coordinate of the first corner point of the rectangle - * @param bX - * the x coordinate of the second corner point of the rectangle - * @param bY - * the y coordinate of the second corner point of the rectangle - * @param bZ - * the z coordinate of the second corner point of the rectangle - * @param cX - * the x coordinate of the third corner point of the rectangle - * @param cY - * the y coordinate of the third corner point of the rectangle - * @param cZ - * the z coordinate of the third corner point of the rectangle - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param pZ - * the z coordinate of the point - * @param res - * will hold the result - * @return res - */ - public static Vector3f findClosestPointOnRectangle( - float aX, float aY, float aZ, - float bX, float bY, float bZ, - float cX, float cY, float cZ, - float pX, float pY, float pZ, Vector3f res) { - float abX = bX - aX, abY = bY - aY, abZ = bZ - aZ; - float acX = cX - aX, acY = cY - aY, acZ = cZ - aZ; - float dX = pX - aX, dY = pY - aY, dZ = pZ - aZ; - float qX = aX, qY = aY, qZ = aZ; - float dist = dX * abX + dY * abY + dZ * abZ; - float maxdist = abX * abX + abY * abY + abZ * abZ; - if (dist >= maxdist) { - qX += abX; - qY += abY; - qZ += abZ; - } else if (dist > 0.0f) { - qX += (dist / maxdist) * abX; - qY += (dist / maxdist) * abY; - qZ += (dist / maxdist) * abZ; - } - dist = dX * acX + dY * acY + dZ * acZ; - maxdist = acX * acX + acY * acY + acZ * acZ; - if (dist >= maxdist) { - qX += acX; - qY += acY; - qZ += acZ; - } else if (dist > 0.0f) { - qX += (dist / maxdist) * acX; - qY += (dist / maxdist) * acY; - qZ += (dist / maxdist) * acZ; - } - res.x = qX; - res.y = qY; - res.z = qZ; - return res; - } - - /** - * Determine the point of intersection between a sphere with the given center (centerX, centerY, centerZ) and radius moving - * with the given velocity (velX, velY, velZ) and the triangle specified via its three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z), (v2X, v2Y, v2Z). - *

- * The vertices of the triangle must be specified in counter-clockwise winding order. - *

- * An intersection is only considered if the time of intersection is smaller than the given maxT value. - *

- * Reference: Improved Collision detection and Response - * - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radius - * the radius of the sphere - * @param velX - * the x component of the velocity of the sphere - * @param velY - * the y component of the velocity of the sphere - * @param velZ - * the z component of the velocity of the sphere - * @param v0X - * the x coordinate of the first triangle vertex - * @param v0Y - * the y coordinate of the first triangle vertex - * @param v0Z - * the z coordinate of the first triangle vertex - * @param v1X - * the x coordinate of the second triangle vertex - * @param v1Y - * the y coordinate of the second triangle vertex - * @param v1Z - * the z coordinate of the second triangle vertex - * @param v2X - * the x coordinate of the third triangle vertex - * @param v2Y - * the y coordinate of the third triangle vertex - * @param v2Z - * the z coordinate of the third triangle vertex - * @param epsilon - * a small epsilon when testing spheres that move almost parallel to the triangle - * @param maxT - * the maximum intersection time - * @param pointAndTime - * iff the moving sphere and the triangle intersect, this will hold the point of intersection in the (x, y, z) components - * and the time of intersection in the w component - * @return {@link #POINT_ON_TRIANGLE_FACE} if the intersection point lies on the triangle's face, - * or {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1} or {@link #POINT_ON_TRIANGLE_VERTEX_2} if the intersection point is a vertex, - * or {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12} or {@link #POINT_ON_TRIANGLE_EDGE_20} if the intersection point lies on an edge; - * or 0 if no intersection - */ - public static int intersectSweptSphereTriangle( - float centerX, float centerY, float centerZ, float radius, float velX, float velY, float velZ, - float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, - float epsilon, float maxT, Vector4f pointAndTime) { - float v10X = v1X - v0X; - float v10Y = v1Y - v0Y; - float v10Z = v1Z - v0Z; - float v20X = v2X - v0X; - float v20Y = v2Y - v0Y; - float v20Z = v2Z - v0Z; - // build triangle plane - float a = v10Y * v20Z - v20Y * v10Z; - float b = v10Z * v20X - v20Z * v10X; - float c = v10X * v20Y - v20X * v10Y; - float d = -(a * v0X + b * v0Y + c * v0Z); - float invLen = Math.invsqrt(a * a + b * b + c * c); - float signedDist = (a * centerX + b * centerY + c * centerZ + d) * invLen; - float dot = (a * velX + b * velY + c * velZ) * invLen; - if (dot < epsilon && dot > -epsilon) - return 0; - float pt0 = (radius - signedDist) / dot; - if (pt0 > maxT) - return 0; - float pt1 = (-radius - signedDist) / dot; - float p0X = centerX - radius * a * invLen + velX * pt0; - float p0Y = centerY - radius * b * invLen + velY * pt0; - float p0Z = centerZ - radius * c * invLen + velZ * pt0; - boolean insideTriangle = testPointInTriangle(p0X, p0Y, p0Z, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z); - if (insideTriangle) { - pointAndTime.x = p0X; - pointAndTime.y = p0Y; - pointAndTime.z = p0Z; - pointAndTime.w = pt0; - return POINT_ON_TRIANGLE_FACE; - } - int isect = 0; - float t0 = maxT; - float A = velX * velX + velY * velY + velZ * velZ; - float radius2 = radius * radius; - // test against v0 - float centerV0X = centerX - v0X; - float centerV0Y = centerY - v0Y; - float centerV0Z = centerZ - v0Z; - float B0 = 2.0f * (velX * centerV0X + velY * centerV0Y + velZ * centerV0Z); - float C0 = centerV0X * centerV0X + centerV0Y * centerV0Y + centerV0Z * centerV0Z - radius2; - float root0 = computeLowestRoot(A, B0, C0, t0); - if (root0 < t0) { - pointAndTime.x = v0X; - pointAndTime.y = v0Y; - pointAndTime.z = v0Z; - pointAndTime.w = root0; - t0 = root0; - isect = POINT_ON_TRIANGLE_VERTEX_0; - } - // test against v1 - float centerV1X = centerX - v1X; - float centerV1Y = centerY - v1Y; - float centerV1Z = centerZ - v1Z; - float centerV1Len = centerV1X * centerV1X + centerV1Y * centerV1Y + centerV1Z * centerV1Z; - float B1 = 2.0f * (velX * centerV1X + velY * centerV1Y + velZ * centerV1Z); - float C1 = centerV1Len - radius2; - float root1 = computeLowestRoot(A, B1, C1, t0); - if (root1 < t0) { - pointAndTime.x = v1X; - pointAndTime.y = v1Y; - pointAndTime.z = v1Z; - pointAndTime.w = root1; - t0 = root1; - isect = POINT_ON_TRIANGLE_VERTEX_1; - } - // test against v2 - float centerV2X = centerX - v2X; - float centerV2Y = centerY - v2Y; - float centerV2Z = centerZ - v2Z; - float B2 = 2.0f * (velX * centerV2X + velY * centerV2Y + velZ * centerV2Z); - float C2 = centerV2X * centerV2X + centerV2Y * centerV2Y + centerV2Z * centerV2Z - radius2; - float root2 = computeLowestRoot(A, B2, C2, t0); - if (root2 < t0) { - pointAndTime.x = v2X; - pointAndTime.y = v2Y; - pointAndTime.z = v2Z; - pointAndTime.w = root2; - t0 = root2; - isect = POINT_ON_TRIANGLE_VERTEX_2; - } - float velLen = velX * velX + velY * velY + velZ * velZ; - // test against edge10 - float len10 = v10X * v10X + v10Y * v10Y + v10Z * v10Z; - float baseTo0Len = centerV0X * centerV0X + centerV0Y * centerV0Y + centerV0Z * centerV0Z; - float v10Vel = (v10X * velX + v10Y * velY + v10Z * velZ); - float A10 = len10 * -velLen + v10Vel * v10Vel; - float v10BaseTo0 = v10X * -centerV0X + v10Y * -centerV0Y + v10Z * -centerV0Z; - float velBaseTo0 = velX * -centerV0X + velY * -centerV0Y + velZ * -centerV0Z; - float B10 = len10 * 2 * velBaseTo0 - 2 * v10Vel * v10BaseTo0; - float C10 = len10 * (radius2 - baseTo0Len) + v10BaseTo0 * v10BaseTo0; - float root10 = computeLowestRoot(A10, B10, C10, t0); - float f10 = (v10Vel * root10 - v10BaseTo0) / len10; - if (f10 >= 0.0f && f10 <= 1.0f && root10 < t0) { - pointAndTime.x = v0X + f10 * v10X; - pointAndTime.y = v0Y + f10 * v10Y; - pointAndTime.z = v0Z + f10 * v10Z; - pointAndTime.w = root10; - t0 = root10; - isect = POINT_ON_TRIANGLE_EDGE_01; - } - // test against edge20 - float len20 = v20X * v20X + v20Y * v20Y + v20Z * v20Z; - float v20Vel = (v20X * velX + v20Y * velY + v20Z * velZ); - float A20 = len20 * -velLen + v20Vel * v20Vel; - float v20BaseTo0 = v20X * -centerV0X + v20Y * -centerV0Y + v20Z * -centerV0Z; - float B20 = len20 * 2 * velBaseTo0 - 2 * v20Vel * v20BaseTo0; - float C20 = len20 * (radius2 - baseTo0Len) + v20BaseTo0 * v20BaseTo0; - float root20 = computeLowestRoot(A20, B20, C20, t0); - float f20 = (v20Vel * root20 - v20BaseTo0) / len20; - if (f20 >= 0.0f && f20 <= 1.0f && root20 < pt1) { - pointAndTime.x = v0X + f20 * v20X; - pointAndTime.y = v0Y + f20 * v20Y; - pointAndTime.z = v0Z + f20 * v20Z; - pointAndTime.w = root20; - t0 = root20; - isect = POINT_ON_TRIANGLE_EDGE_20; - } - // test against edge21 - float v21X = v2X - v1X; - float v21Y = v2Y - v1Y; - float v21Z = v2Z - v1Z; - float len21 = v21X * v21X + v21Y * v21Y + v21Z * v21Z; - float baseTo1Len = centerV1Len; - float v21Vel = (v21X * velX + v21Y * velY + v21Z * velZ); - float A21 = len21 * -velLen + v21Vel * v21Vel; - float v21BaseTo1 = v21X * -centerV1X + v21Y * -centerV1Y + v21Z * -centerV1Z; - float velBaseTo1 = velX * -centerV1X + velY * -centerV1Y + velZ * -centerV1Z; - float B21 = len21 * 2 * velBaseTo1 - 2 * v21Vel * v21BaseTo1; - float C21 = len21 * (radius2 - baseTo1Len) + v21BaseTo1 * v21BaseTo1; - float root21 = computeLowestRoot(A21, B21, C21, t0); - float f21 = (v21Vel * root21 - v21BaseTo1) / len21; - if (f21 >= 0.0f && f21 <= 1.0f && root21 < t0) { - pointAndTime.x = v1X + f21 * v21X; - pointAndTime.y = v1Y + f21 * v21Y; - pointAndTime.z = v1Z + f21 * v21Z; - pointAndTime.w = root21; - t0 = root21; - isect = POINT_ON_TRIANGLE_EDGE_12; - } - return isect; - } - - /** - * Compute the lowest root for t in the quadratic equation a*t*t + b*t + c = 0. - *

- * This is a helper method for {@link #intersectSweptSphereTriangle} - * - * @param a - * the quadratic factor - * @param b - * the linear factor - * @param c - * the constant - * @param maxR - * the maximum expected root - * @return the lowest of the two roots of the quadratic equation; or {@link Float#POSITIVE_INFINITY} - */ - private static float computeLowestRoot(float a, float b, float c, float maxR) { - float determinant = b * b - 4.0f * a * c; - if (determinant < 0.0f) - return Float.POSITIVE_INFINITY; - float sqrtD = (float) Math.sqrt(determinant); - float r1 = (-b - sqrtD) / (2.0f * a); - float r2 = (-b + sqrtD) / (2.0f * a); - if (r1 > r2) { - float temp = r2; - r2 = r1; - r1 = temp; - } - if (r1 > 0.0f && r1 < maxR) { - return r1; - } - if (r2 > 0.0f && r2 < maxR) { - return r2; - } - return Float.POSITIVE_INFINITY; - } - - /** - * Test whether the projection of the given point (pX, pY, pZ) lies inside of the triangle defined by the three vertices - * (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z). - *

- * Reference: Improved Collision detection and Response - * - * @param pX - * the x coordinate of the point to test - * @param pY - * the y coordinate of the point to test - * @param pZ - * the z coordinate of the point to test - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @return true if the projection of the given point lies inside of the given triangle; false otherwise - */ - public static boolean testPointInTriangle(float pX, float pY, float pZ, float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z) { - float e10X = v1X - v0X; - float e10Y = v1Y - v0Y; - float e10Z = v1Z - v0Z; - float e20X = v2X - v0X; - float e20Y = v2Y - v0Y; - float e20Z = v2Z - v0Z; - float a = e10X * e10X + e10Y * e10Y + e10Z * e10Z; - float b = e10X * e20X + e10Y * e20Y + e10Z * e20Z; - float c = e20X * e20X + e20Y * e20Y + e20Z * e20Z; - float ac_bb = a * c - b * b; - float vpX = pX - v0X; - float vpY = pY - v0Y; - float vpZ = pZ - v0Z; - float d = vpX * e10X + vpY * e10Y + vpZ * e10Z; - float e = vpX * e20X + vpY * e20Y + vpZ * e20Z; - float x = d * c - e * b; - float y = e * a - d * b; - float z = x + y - ac_bb; - return ((Runtime.floatToIntBits(z) & ~(Runtime.floatToIntBits(x) | Runtime.floatToIntBits(y))) & 0x8000000000000000L) != 0L; - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and normalized direction (dirX, dirY, dirZ) - * intersects the given sphere with center (centerX, centerY, centerZ) and square radius radiusSquared, - * and store the values of the parameter t in the ray equation p(t) = origin + t * dir for both points (near - * and far) of intersections into the given result vector. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's normalized direction - * @param dirY - * the y coordinate of the ray's normalized direction - * @param dirZ - * the z coordinate of the ray's normalized direction - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radiusSquared - * the sphere radius squared - * @param result - * a vector that will contain the values of the parameter t in the ray equation - * p(t) = origin + t * dir for both points (near, far) of intersections with the sphere - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean intersectRaySphere(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, - float centerX, float centerY, float centerZ, float radiusSquared, Vector2f result) { - float Lx = centerX - originX; - float Ly = centerY - originY; - float Lz = centerZ - originZ; - float tca = Lx * dirX + Ly * dirY + Lz * dirZ; - float d2 = Lx * Lx + Ly * Ly + Lz * Lz - tca * tca; - if (d2 > radiusSquared) - return false; - float thc = (float) Math.sqrt(radiusSquared - d2); - float t0 = tca - thc; - float t1 = tca + thc; - if (t0 < t1 && t1 >= 0.0f) { - result.x = t0; - result.y = t1; - return true; - } - return false; - } - - /** - * Test whether the ray with the given origin and normalized direction dir - * intersects the sphere with the given center and square radius radiusSquared, - * and store the values of the parameter t in the ray equation p(t) = origin + t * dir for both points (near - * and far) of intersections into the given result vector. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param origin - * the ray's origin - * @param dir - * the ray's normalized direction - * @param center - * the sphere's center - * @param radiusSquared - * the sphere radius squared - * @param result - * a vector that will contain the values of the parameter t in the ray equation - * p(t) = origin + t * dir for both points (near, far) of intersections with the sphere - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean intersectRaySphere(Vector3fc origin, Vector3fc dir, Vector3fc center, float radiusSquared, Vector2f result) { - return intersectRaySphere(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), center.x(), center.y(), center.z(), radiusSquared, result); - } - - /** - * Test whether the given ray intersects the given sphere, - * and store the values of the parameter t in the ray equation p(t) = origin + t * dir for both points (near - * and far) of intersections into the given result vector. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param ray - * the ray - * @param sphere - * the sphere - * @param result - * a vector that will contain the values of the parameter t in the ray equation - * p(t) = origin + t * dir for both points (near, far) of intersections with the sphere - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean intersectRaySphere(Rayf ray, Spheref sphere, Vector2f result) { - return intersectRaySphere(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, sphere.x, sphere.y, sphere.z, sphere.r*sphere.r, result); - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and normalized direction (dirX, dirY, dirZ) - * intersects the given sphere with center (centerX, centerY, centerZ) and square radius radiusSquared. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's normalized direction - * @param dirY - * the y coordinate of the ray's normalized direction - * @param dirZ - * the z coordinate of the ray's normalized direction - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radiusSquared - * the sphere radius squared - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean testRaySphere(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, - float centerX, float centerY, float centerZ, float radiusSquared) { - float Lx = centerX - originX; - float Ly = centerY - originY; - float Lz = centerZ - originZ; - float tca = Lx * dirX + Ly * dirY + Lz * dirZ; - float d2 = Lx * Lx + Ly * Ly + Lz * Lz - tca * tca; - if (d2 > radiusSquared) - return false; - float thc = (float) Math.sqrt(radiusSquared - d2); - float t0 = tca - thc; - float t1 = tca + thc; - return t0 < t1 && t1 >= 0.0f; - } - - /** - * Test whether the ray with the given origin and normalized direction dir - * intersects the sphere with the given center and square radius. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param origin - * the ray's origin - * @param dir - * the ray's normalized direction - * @param center - * the sphere's center - * @param radiusSquared - * the sphere radius squared - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean testRaySphere(Vector3fc origin, Vector3fc dir, Vector3fc center, float radiusSquared) { - return testRaySphere(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), center.x(), center.y(), center.z(), radiusSquared); - } - - /** - * Test whether the given ray intersects the given sphere. - *

- * This method returns true for a ray whose origin lies inside the sphere. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param ray - * the ray - * @param sphere - * the sphere - * @return true if the ray intersects the sphere; false otherwise - */ - public static boolean testRaySphere(Rayf ray, Spheref sphere) { - return testRaySphere(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, sphere.x, sphere.y, sphere.z, sphere.r*sphere.r); - } - - /** - * Test whether the line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects the given sphere with center (centerX, centerY, centerZ) and square radius radiusSquared. - *

- * Reference: http://paulbourke.net/ - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param centerX - * the x coordinate of the sphere's center - * @param centerY - * the y coordinate of the sphere's center - * @param centerZ - * the z coordinate of the sphere's center - * @param radiusSquared - * the sphere radius squared - * @return true if the line segment intersects the sphere; false otherwise - */ - public static boolean testLineSegmentSphere(float p0X, float p0Y, float p0Z, float p1X, float p1Y, float p1Z, - float centerX, float centerY, float centerZ, float radiusSquared) { - float dX = p1X - p0X; - float dY = p1Y - p0Y; - float dZ = p1Z - p0Z; - float nom = (centerX - p0X) * dX + (centerY - p0Y) * dY + (centerZ - p0Z) * dZ; - float den = dX * dX + dY * dY + dZ * dZ; - float u = nom / den; - if (u < 0.0f) { - dX = p0X - centerX; - dY = p0Y - centerY; - dZ = p0Z - centerZ; - } else if (u > 1.0f) { - dX = p1X - centerX; - dY = p1Y - centerY; - dZ = p1Z - centerZ; - } else { // has to be >= 0 and <= 1 - float pX = p0X + u * dX; - float pY = p0Y + u * dY; - float pZ = p0Z + u * dZ; - dX = pX - centerX; - dY = pY - centerY; - dZ = pZ - centerZ; - } - float dist = dX * dX + dY * dY + dZ * dZ; - return dist <= radiusSquared; - } - - /** - * Test whether the line segment with the end points p0 and p1 - * intersects the given sphere with center center and square radius radiusSquared. - *

- * Reference: http://paulbourke.net/ - * - * @param p0 - * the line segment's first end point - * @param p1 - * the line segment's second end point - * @param center - * the sphere's center - * @param radiusSquared - * the sphere radius squared - * @return true if the line segment intersects the sphere; false otherwise - */ - public static boolean testLineSegmentSphere(Vector3fc p0, Vector3fc p1, Vector3fc center, float radiusSquared) { - return testLineSegmentSphere(p0.x(), p0.y(), p0.z(), p1.x(), p1.y(), p1.z(), center.x(), center.y(), center.z(), radiusSquared); - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the axis-aligned box given as its minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ), - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAab(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector2f) - * @see RayAabIntersection - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param minX - * the x coordinate of the minimum corner of the axis-aligned box - * @param minY - * the y coordinate of the minimum corner of the axis-aligned box - * @param minZ - * the z coordinate of the minimum corner of the axis-aligned box - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned box - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned box - * @param maxZ - * the y coordinate of the maximum corner of the axis-aligned box - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean intersectRayAab(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, - float minX, float minY, float minZ, float maxX, float maxY, float maxZ, Vector2f result) { - float invDirX = 1.0f / dirX, invDirY = 1.0f / dirY, invDirZ = 1.0f / dirZ; - float tNear, tFar, tymin, tymax, tzmin, tzmax; - if (invDirX >= 0.0f) { - tNear = (minX - originX) * invDirX; - tFar = (maxX - originX) * invDirX; - } else { - tNear = (maxX - originX) * invDirX; - tFar = (minX - originX) * invDirX; - } - if (invDirY >= 0.0f) { - tymin = (minY - originY) * invDirY; - tymax = (maxY - originY) * invDirY; - } else { - tymin = (maxY - originY) * invDirY; - tymax = (minY - originY) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return false; - if (invDirZ >= 0.0f) { - tzmin = (minZ - originZ) * invDirZ; - tzmax = (maxZ - originZ) * invDirZ; - } else { - tzmin = (maxZ - originZ) * invDirZ; - tzmax = (minZ - originZ) * invDirZ; - } - if (tNear > tzmax || tzmin > tFar) - return false; - tNear = tymin > tNear || Float.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Float.isNaN(tFar) ? tymax : tFar; - tNear = tzmin > tNear ? tzmin : tNear; - tFar = tzmax < tFar ? tzmax : tFar; - if (tNear < tFar && tFar >= 0.0f) { - result.x = tNear; - result.y = tFar; - return true; - } - return false; - } - - /** - * Test whether the ray with the given origin and direction dir - * intersects the axis-aligned box specified as its minimum corner min and maximum corner max, - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection.. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAab(float, float, float, float, float, float, float, float, float, float, float, float, Vector2f) - * @see RayAabIntersection - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean intersectRayAab(Vector3fc origin, Vector3fc dir, Vector3fc min, Vector3fc max, Vector2f result) { - return intersectRayAab(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), result); - } - - /** - * Test whether the given ray intersects given the axis-aligned box - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection.. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAab(float, float, float, float, float, float, float, float, float, float, float, float, Vector2f) - * @see RayAabIntersection - * - * @param ray - * the ray - * @param aabb - * the AABB - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean intersectRayAab(Rayf ray, AABBf aabb, Vector2f result) { - return intersectRayAab(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, result); - } - - /** - * Test whether the given ray intersects given the axis-aligned box - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection.. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAab(float, float, float, float, float, float, float, float, float, float, float, float, Vector2f) - * @see RayAabIntersection - * - * @param ray - * the ray - * @param aabb - * the AABB - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * iff the ray intersects the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean intersectRayAab(Rayf ray, AABBi aabb, Vector2f result) { - return intersectRayAab(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, result); - } - /** - * Determine whether the undirected line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects the axis-aligned box given as its minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ), - * and return the values of the parameter t in the ray equation p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside the axis-aligned box. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectLineSegmentAab(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector2f) - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param minX - * the x coordinate of one corner of the axis-aligned box - * @param minY - * the y coordinate of one corner of the axis-aligned box - * @param minZ - * the z coordinate of one corner of the axis-aligned box - * @param maxX - * the x coordinate of the opposite corner of the axis-aligned box - * @param maxY - * the y coordinate of the opposite corner of the axis-aligned box - * @param maxZ - * the y coordinate of the opposite corner of the axis-aligned box - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects the axis-aligned box - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned box; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned box; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned box; or - * {@link #TWO_INTERSECTION} if the line segment intersects two sides of the axis-aligned box - * or lies on an edge or a side of the box - */ - public static int intersectLineSegmentAab(float p0X, float p0Y, float p0Z, float p1X, float p1Y, float p1Z, - float minX, float minY, float minZ, float maxX, float maxY, float maxZ, Vector2f result) { - float dirX = p1X - p0X, dirY = p1Y - p0Y, dirZ = p1Z - p0Z; - float invDirX = 1.0f / dirX, invDirY = 1.0f / dirY, invDirZ = 1.0f / dirZ; - float tNear, tFar, tymin, tymax, tzmin, tzmax; - if (invDirX >= 0.0f) { - tNear = (minX - p0X) * invDirX; - tFar = (maxX - p0X) * invDirX; - } else { - tNear = (maxX - p0X) * invDirX; - tFar = (minX - p0X) * invDirX; - } - if (invDirY >= 0.0f) { - tymin = (minY - p0Y) * invDirY; - tymax = (maxY - p0Y) * invDirY; - } else { - tymin = (maxY - p0Y) * invDirY; - tymax = (minY - p0Y) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return OUTSIDE; - if (invDirZ >= 0.0f) { - tzmin = (minZ - p0Z) * invDirZ; - tzmax = (maxZ - p0Z) * invDirZ; - } else { - tzmin = (maxZ - p0Z) * invDirZ; - tzmax = (minZ - p0Z) * invDirZ; - } - if (tNear > tzmax || tzmin > tFar) - return OUTSIDE; - tNear = tymin > tNear || Float.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Float.isNaN(tFar) ? tymax : tFar; - tNear = tzmin > tNear ? tzmin : tNear; - tFar = tzmax < tFar ? tzmax : tFar; - int type = OUTSIDE; - if (tNear <= tFar && tNear <= 1.0f && tFar >= 0.0f) { - if (tNear >= 0.0f && tFar > 1.0f) { - tFar = tNear; - type = ONE_INTERSECTION; - } else if (tNear < 0.0f && tFar <= 1.0f) { - tNear = tFar; - type = ONE_INTERSECTION; - } else if (tNear < 0.0f && tFar > 1.0f) { - type = INSIDE; - } else { - type = TWO_INTERSECTION; - } - result.x = tNear; - result.y = tFar; - } - return type; - } - - /** - * Determine whether the undirected line segment with the end points p0 and p1 - * intersects the axis-aligned box given as its minimum corner min and maximum corner max, - * and return the values of the parameter t in the ray equation p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside the axis-aligned box. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectLineSegmentAab(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector2f) - * - * @param p0 - * the line segment's first end point - * @param p1 - * the line segment's second end point - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects the axis-aligned box - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned box; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned box; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned box; or - * {@link #TWO_INTERSECTION} if the line segment intersects two sides of the axis-aligned box - * or lies on an edge or a side of the box - */ - public static int intersectLineSegmentAab(Vector3fc p0, Vector3fc p1, Vector3fc min, Vector3fc max, Vector2f result) { - return intersectLineSegmentAab(p0.x(), p0.y(), p0.z(), p1.x(), p1.y(), p1.z(), min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), result); - } - - /** - * Determine whether the given undirected line segment intersects the given axis-aligned box, - * and return the values of the parameter t in the ray equation p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside the axis-aligned box. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectLineSegmentAab(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector2f) - * - * @param lineSegment - * the line segment - * @param aabb - * the AABB - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects the axis-aligned box - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned box; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned box; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned box; or - * {@link #TWO_INTERSECTION} if the line segment intersects two sides of the axis-aligned box - * or lies on an edge or a side of the box - */ - public static int intersectLineSegmentAab(LineSegmentf lineSegment, AABBf aabb, Vector2f result) { - return intersectLineSegmentAab(lineSegment.aX, lineSegment.aY, lineSegment.aZ, lineSegment.bX, lineSegment.bY, lineSegment.bZ, aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, result); - } - - /** - * Determine whether the given undirected line segment intersects the given axis-aligned box, - * and return the values of the parameter t in the ray equation p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection. - *

- * This method returns true for a line segment whose either end point lies inside the axis-aligned box. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectLineSegmentAab(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector2f) - * - * @param lineSegment - * the line segment - * @param aabb - * the AABB - * @param result - * a vector which will hold the resulting values of the parameter - * t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * iff the line segment intersects the axis-aligned box - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned box; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned box; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned box; or - * {@link #TWO_INTERSECTION} if the line segment intersects two sides of the axis-aligned box - * or lies on an edge or a side of the box - */ - public static int intersectLineSegmentAab(LineSegmentf lineSegment, AABBi aabb, Vector2f result) { - return intersectLineSegmentAab(lineSegment.aX, lineSegment.aY, lineSegment.aZ, lineSegment.bX, lineSegment.bY, lineSegment.bZ, aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ, result); - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the axis-aligned box given as its minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ). - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAab(Vector3fc, Vector3fc, Vector3fc, Vector3fc) - * @see RayAabIntersection - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param minX - * the x coordinate of the minimum corner of the axis-aligned box - * @param minY - * the y coordinate of the minimum corner of the axis-aligned box - * @param minZ - * the z coordinate of the minimum corner of the axis-aligned box - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned box - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned box - * @param maxZ - * the y coordinate of the maximum corner of the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean testRayAab(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, - float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - float invDirX = 1.0f / dirX, invDirY = 1.0f / dirY, invDirZ = 1.0f / dirZ; - float tNear, tFar, tymin, tymax, tzmin, tzmax; - if (invDirX >= 0.0f) { - tNear = (minX - originX) * invDirX; - tFar = (maxX - originX) * invDirX; - } else { - tNear = (maxX - originX) * invDirX; - tFar = (minX - originX) * invDirX; - } - if (invDirY >= 0.0f) { - tymin = (minY - originY) * invDirY; - tymax = (maxY - originY) * invDirY; - } else { - tymin = (maxY - originY) * invDirY; - tymax = (minY - originY) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return false; - if (invDirZ >= 0.0f) { - tzmin = (minZ - originZ) * invDirZ; - tzmax = (maxZ - originZ) * invDirZ; - } else { - tzmin = (maxZ - originZ) * invDirZ; - tzmax = (minZ - originZ) * invDirZ; - } - if (tNear > tzmax || tzmin > tFar) - return false; - tNear = tymin > tNear || Float.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Float.isNaN(tFar) ? tymax : tFar; - tNear = tzmin > tNear ? tzmin : tNear; - tFar = tzmax < tFar ? tzmax : tFar; - return tNear < tFar && tFar >= 0.0f; - } - - /** - * Test whether the ray with the given origin and direction dir - * intersects the axis-aligned box specified as its minimum corner min and maximum corner max. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAab(float, float, float, float, float, float, float, float, float, float, float, float) - * @see RayAabIntersection - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean testRayAab(Vector3fc origin, Vector3fc dir, Vector3fc min, Vector3fc max) { - return testRayAab(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), min.x(), min.y(), min.z(), max.x(), max.y(), max.z()); - } - - /** - * Test whether the given ray intersects the given axis-aligned box. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAab(float, float, float, float, float, float, float, float, float, float, float, float) - * @see RayAabIntersection - * - * @param ray - * the ray - * @param aabb - * the AABB - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean testRayAab(Rayf ray, AABBf aabb) { - return testRayAab(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ); - } - - /** - * Test whether the given ray intersects the given axis-aligned box. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned box. - *

- * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAab(float, float, float, float, float, float, float, float, float, float, float, float) - * @see RayAabIntersection - * - * @param ray - * the ray - * @param aabb - * the AABB - * @return true if the given ray intersects the axis-aligned box; false otherwise - */ - public static boolean testRayAab(Rayf ray, AABBi aabb) { - return testRayAab(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ, aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ); - } - - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the frontface of the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z). - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test implements backface culling, that is, it will return false when the triangle is in clockwise - * winding order assuming a right-handed coordinate system when seen along the ray's direction, even if the ray intersects the triangle. - * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings. - * - * @see #testRayTriangleFront(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3fc, float) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return true if the given ray intersects the frontface of the triangle; false otherwise - */ - public static boolean testRayTriangleFront(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, - float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, - float epsilon) { - float edge1X = v1X - v0X; - float edge1Y = v1Y - v0Y; - float edge1Z = v1Z - v0Z; - float edge2X = v2X - v0X; - float edge2Y = v2Y - v0Y; - float edge2Z = v2Z - v0Z; - float pvecX = dirY * edge2Z - dirZ * edge2Y; - float pvecY = dirZ * edge2X - dirX * edge2Z; - float pvecZ = dirX * edge2Y - dirY * edge2X; - float det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ; - if (det < epsilon) - return false; - float tvecX = originX - v0X; - float tvecY = originY - v0Y; - float tvecZ = originZ - v0Z; - float u = (tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ); - if (u < 0.0f || u > det) - return false; - float qvecX = tvecY * edge1Z - tvecZ * edge1Y; - float qvecY = tvecZ * edge1X - tvecX * edge1Z; - float qvecZ = tvecX * edge1Y - tvecY * edge1X; - float v = (dirX * qvecX + dirY * qvecY + dirZ * qvecZ); - if (v < 0.0f || u + v > det) - return false; - float invDet = 1.0f / det; - float t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet; - return t >= epsilon; - } - - /** - * Test whether the ray with the given origin and the given dir intersects the frontface of the triangle consisting of the three vertices - * v0, v1 and v2. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test implements backface culling, that is, it will return false when the triangle is in clockwise - * winding order assuming a right-handed coordinate system when seen along the ray's direction, even if the ray intersects the triangle. - * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings. - * - * @see #testRayTriangleFront(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return true if the given ray intersects the frontface of the triangle; false otherwise - */ - public static boolean testRayTriangleFront(Vector3fc origin, Vector3fc dir, Vector3fc v0, Vector3fc v1, Vector3fc v2, float epsilon) { - return testRayTriangleFront(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon); - } - - /** - * Test whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z). - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle. - * - * @see #testRayTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3fc, float) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return true if the given ray intersects the frontface of the triangle; false otherwise - */ - public static boolean testRayTriangle(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, - float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, - float epsilon) { - float edge1X = v1X - v0X; - float edge1Y = v1Y - v0Y; - float edge1Z = v1Z - v0Z; - float edge2X = v2X - v0X; - float edge2Y = v2Y - v0Y; - float edge2Z = v2Z - v0Z; - float pvecX = dirY * edge2Z - dirZ * edge2Y; - float pvecY = dirZ * edge2X - dirX * edge2Z; - float pvecZ = dirX * edge2Y - dirY * edge2X; - float det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ; - if (det > -epsilon && det < epsilon) - return false; - float tvecX = originX - v0X; - float tvecY = originY - v0Y; - float tvecZ = originZ - v0Z; - float invDet = 1.0f / det; - float u = (tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ) * invDet; - if (u < 0.0f || u > 1.0f) - return false; - float qvecX = tvecY * edge1Z - tvecZ * edge1Y; - float qvecY = tvecZ * edge1X - tvecX * edge1Z; - float qvecZ = tvecX * edge1Y - tvecY * edge1X; - float v = (dirX * qvecX + dirY * qvecY + dirZ * qvecZ) * invDet; - if (v < 0.0f || u + v > 1.0f) - return false; - float t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet; - return t >= epsilon; - } - - /** - * Test whether the ray with the given origin and the given dir intersects the frontface of the triangle consisting of the three vertices - * v0, v1 and v2. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle. - * - * @see #testRayTriangle(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return true if the given ray intersects the frontface of the triangle; false otherwise - */ - public static boolean testRayTriangle(Vector3fc origin, Vector3fc dir, Vector3fc v0, Vector3fc v1, Vector3fc v2, float epsilon) { - return testRayTriangle(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon); - } - - /** - * Determine whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the frontface of the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z) - * and return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test implements backface culling, that is, it will return false when the triangle is in clockwise - * winding order assuming a right-handed coordinate system when seen along the ray's direction, even if the ray intersects the triangle. - * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings. - * - * @see #testRayTriangleFront(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3fc, float) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection - * if the ray intersects the frontface of the triangle; -1.0 otherwise - */ - public static float intersectRayTriangleFront(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, - float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, - float epsilon) { - float edge1X = v1X - v0X; - float edge1Y = v1Y - v0Y; - float edge1Z = v1Z - v0Z; - float edge2X = v2X - v0X; - float edge2Y = v2Y - v0Y; - float edge2Z = v2Z - v0Z; - float pvecX = dirY * edge2Z - dirZ * edge2Y; - float pvecY = dirZ * edge2X - dirX * edge2Z; - float pvecZ = dirX * edge2Y - dirY * edge2X; - float det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ; - if (det <= epsilon) - return -1.0f; - float tvecX = originX - v0X; - float tvecY = originY - v0Y; - float tvecZ = originZ - v0Z; - float u = tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ; - if (u < 0.0f || u > det) - return -1.0f; - float qvecX = tvecY * edge1Z - tvecZ * edge1Y; - float qvecY = tvecZ * edge1X - tvecX * edge1Z; - float qvecZ = tvecX * edge1Y - tvecY * edge1X; - float v = dirX * qvecX + dirY * qvecY + dirZ * qvecZ; - if (v < 0.0f || u + v > det) - return -1.0f; - float invDet = 1.0f / det; - float t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet; - return t; - } - - /** - * Determine whether the ray with the given origin and the given dir intersects the frontface of the triangle consisting of the three vertices - * v0, v1 and v2 and return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test implements backface culling, that is, it will return false when the triangle is in clockwise - * winding order assuming a right-handed coordinate system when seen along the ray's direction, even if the ray intersects the triangle. - * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings. - * - * @see #intersectRayTriangleFront(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection - * if the ray intersects the frontface of the triangle; -1.0 otherwise - */ - public static float intersectRayTriangleFront(Vector3fc origin, Vector3fc dir, Vector3fc v0, Vector3fc v1, Vector3fc v2, float epsilon) { - return intersectRayTriangleFront(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon); - } - - /** - * Determine whether the given ray with the origin (originX, originY, originZ) and direction (dirX, dirY, dirZ) - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z) - * and return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle. - * - * @see #testRayTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3fc, float) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param originZ - * the z coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param dirZ - * the z coordinate of the ray's direction - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection - * if the ray intersects the triangle; -1.0 otherwise - */ - public static float intersectRayTriangle(float originX, float originY, float originZ, float dirX, float dirY, float dirZ, - float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, - float epsilon) { - float edge1X = v1X - v0X; - float edge1Y = v1Y - v0Y; - float edge1Z = v1Z - v0Z; - float edge2X = v2X - v0X; - float edge2Y = v2Y - v0Y; - float edge2Z = v2Z - v0Z; - float pvecX = dirY * edge2Z - dirZ * edge2Y; - float pvecY = dirZ * edge2X - dirX * edge2Z; - float pvecZ = dirX * edge2Y - dirY * edge2X; - float det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ; - if (det > -epsilon && det < epsilon) - return -1.0f; - float tvecX = originX - v0X; - float tvecY = originY - v0Y; - float tvecZ = originZ - v0Z; - float invDet = 1.0f / det; - float u = (tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ) * invDet; - if (u < 0.0f || u > 1.0f) - return -1.0f; - float qvecX = tvecY * edge1Z - tvecZ * edge1Y; - float qvecY = tvecZ * edge1X - tvecX * edge1Z; - float qvecZ = tvecX * edge1Y - tvecY * edge1X; - float v = (dirX * qvecX + dirY * qvecY + dirZ * qvecZ) * invDet; - if (v < 0.0f || u + v > 1.0f) - return -1.0f; - float t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet; - return t; - } - - /** - * Determine whether the ray with the given origin and the given dir intersects the triangle consisting of the three vertices - * v0, v1 and v2 and return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection. - *

- * This is an implementation of the - * Fast, Minimum Storage Ray/Triangle Intersection method. - *

- * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle. - * - * @see #intersectRayTriangle(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing rays that are almost parallel to the triangle - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the point of intersection - * if the ray intersects the triangle; -1.0 otherwise - */ - public static float intersectRayTriangle(Vector3fc origin, Vector3fc dir, Vector3fc v0, Vector3fc v1, Vector3fc v2, float epsilon) { - return intersectRayTriangle(origin.x(), origin.y(), origin.z(), dir.x(), dir.y(), dir.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon); - } - - /** - * Test whether the line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z), - * regardless of the winding order of the triangle or the direction of the line segment between its two end points. - *

- * Reference: - * Fast, Minimum Storage Ray/Triangle Intersection - * - * @see #testLineSegmentTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3fc, float) - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing line segments that are almost parallel to the triangle - * @return true if the given line segment intersects the triangle; false otherwise - */ - public static boolean testLineSegmentTriangle(float p0X, float p0Y, float p0Z, float p1X, float p1Y, float p1Z, - float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, - float epsilon) { - float dirX = p1X - p0X; - float dirY = p1Y - p0Y; - float dirZ = p1Z - p0Z; - float t = intersectRayTriangle(p0X, p0Y, p0Z, dirX, dirY, dirZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z, epsilon); - return t >= 0.0f && t <= 1.0f; - } - - /** - * Test whether the line segment with the end points p0 and p1 - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z), - * regardless of the winding order of the triangle or the direction of the line segment between its two end points. - *

- * Reference: - * Fast, Minimum Storage Ray/Triangle Intersection - * - * @see #testLineSegmentTriangle(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float) - * - * @param p0 - * the line segment's first end point - * @param p1 - * the line segment's second end point - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing line segments that are almost parallel to the triangle - * @return true if the given line segment intersects the triangle; false otherwise - */ - public static boolean testLineSegmentTriangle(Vector3fc p0, Vector3fc p1, Vector3fc v0, Vector3fc v1, Vector3fc v2, float epsilon) { - return testLineSegmentTriangle(p0.x(), p0.y(), p0.z(), p1.x(), p1.y(), p1.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon); - } - - /** - * Determine whether the line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z), - * regardless of the winding order of the triangle or the direction of the line segment between its two end points, - * and return the point of intersection. - *

- * Reference: - * Fast, Minimum Storage Ray/Triangle Intersection - * - * @see #intersectLineSegmentTriangle(Vector3fc, Vector3fc, Vector3fc, Vector3fc, Vector3fc, float, Vector3f) - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param v0X - * the x coordinate of the first vertex - * @param v0Y - * the y coordinate of the first vertex - * @param v0Z - * the z coordinate of the first vertex - * @param v1X - * the x coordinate of the second vertex - * @param v1Y - * the y coordinate of the second vertex - * @param v1Z - * the z coordinate of the second vertex - * @param v2X - * the x coordinate of the third vertex - * @param v2Y - * the y coordinate of the third vertex - * @param v2Z - * the z coordinate of the third vertex - * @param epsilon - * a small epsilon when testing line segments that are almost parallel to the triangle - * @param intersectionPoint - * the point of intersection - * @return true if the given line segment intersects the triangle; false otherwise - */ - public static boolean intersectLineSegmentTriangle(float p0X, float p0Y, float p0Z, float p1X, float p1Y, float p1Z, - float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, - float epsilon, Vector3f intersectionPoint) { - float dirX = p1X - p0X; - float dirY = p1Y - p0Y; - float dirZ = p1Z - p0Z; - float t = intersectRayTriangle(p0X, p0Y, p0Z, dirX, dirY, dirZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z, epsilon); - if (t >= 0.0f && t <= 1.0f) { - intersectionPoint.x = p0X + dirX * t; - intersectionPoint.y = p0Y + dirY * t; - intersectionPoint.z = p0Z + dirZ * t; - return true; - } - return false; - } - - /** - * Determine whether the line segment with the end points p0 and p1 - * intersects the triangle consisting of the three vertices (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and (v2X, v2Y, v2Z), - * regardless of the winding order of the triangle or the direction of the line segment between its two end points, - * and return the point of intersection. - *

- * Reference: - * Fast, Minimum Storage Ray/Triangle Intersection - * - * @see #intersectLineSegmentTriangle(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, Vector3f) - * - * @param p0 - * the line segment's first end point - * @param p1 - * the line segment's second end point - * @param v0 - * the position of the first vertex - * @param v1 - * the position of the second vertex - * @param v2 - * the position of the third vertex - * @param epsilon - * a small epsilon when testing line segments that are almost parallel to the triangle - * @param intersectionPoint - * the point of intersection - * @return true if the given line segment intersects the triangle; false otherwise - */ - public static boolean intersectLineSegmentTriangle(Vector3fc p0, Vector3fc p1, Vector3fc v0, Vector3fc v1, Vector3fc v2, float epsilon, Vector3f intersectionPoint) { - return intersectLineSegmentTriangle(p0.x(), p0.y(), p0.z(), p1.x(), p1.y(), p1.z(), v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), epsilon, intersectionPoint); - } - - /** - * Determine whether the line segment with the end points (p0X, p0Y, p0Z) and (p1X, p1Y, p1Z) - * intersects the plane given as the general plane equation a*x + b*y + c*z + d = 0, - * and return the point of intersection. - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p0Z - * the z coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param p1Z - * the z coordinate of the line segment's second end point - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param intersectionPoint - * the point of intersection - * @return true if the given line segment intersects the plane; false otherwise - */ - public static boolean intersectLineSegmentPlane(float p0X, float p0Y, float p0Z, float p1X, float p1Y, float p1Z, - float a, float b, float c, float d, Vector3f intersectionPoint) { - float dirX = p1X - p0X; - float dirY = p1Y - p0Y; - float dirZ = p1Z - p0Z; - float denom = a * dirX + b * dirY + c * dirZ; - float t = -(a * p0X + b * p0Y + c * p0Z + d) / denom; - if (t >= 0.0f && t <= 1.0f) { - intersectionPoint.x = p0X + t * dirX; - intersectionPoint.y = p0Y + t * dirY; - intersectionPoint.z = p0Z + t * dirZ; - return true; - } - return false; - } - - /** - * Test whether the line with the general line equation a*x + b*y + c = 0 intersects the circle with center - * (centerX, centerY) and radius. - *

- * Reference: http://math.stackexchange.com - * - * @param a - * the x factor in the line equation - * @param b - * the y factor in the line equation - * @param c - * the constant in the line equation - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radius - * the radius of the circle - * @return true iff the line intersects the circle; false otherwise - */ - public static boolean testLineCircle(float a, float b, float c, float centerX, float centerY, float radius) { - float denom = (float) Math.sqrt(a * a + b * b); - float dist = (a * centerX + b * centerY + c) / denom; - return -radius <= dist && dist <= radius; - } - - /** - * Test whether the line with the general line equation a*x + b*y + c = 0 intersects the circle with center - * (centerX, centerY) and radius, and store the center of the line segment of - * intersection in the (x, y) components of the supplied vector and the half-length of that line segment in the z component. - *

- * Reference: http://math.stackexchange.com - * - * @param a - * the x factor in the line equation - * @param b - * the y factor in the line equation - * @param c - * the constant in the line equation - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radius - * the radius of the circle - * @param intersectionCenterAndHL - * will hold the center of the line segment of intersection in the (x, y) components and the half-length in the z component - * @return true iff the line intersects the circle; false otherwise - */ - public static boolean intersectLineCircle(float a, float b, float c, float centerX, float centerY, float radius, Vector3f intersectionCenterAndHL) { - float invDenom = Math.invsqrt(a * a + b * b); - float dist = (a * centerX + b * centerY + c) * invDenom; - if (-radius <= dist && dist <= radius) { - intersectionCenterAndHL.x = centerX + dist * a * invDenom; - intersectionCenterAndHL.y = centerY + dist * b * invDenom; - intersectionCenterAndHL.z = (float) Math.sqrt(radius * radius - dist * dist); - return true; - } - return false; - } - - /** - * Test whether the line defined by the two points (x0, y0) and (x1, y1) intersects the circle with center - * (centerX, centerY) and radius, and store the center of the line segment of - * intersection in the (x, y) components of the supplied vector and the half-length of that line segment in the z component. - *

- * Reference: http://math.stackexchange.com - * - * @param x0 - * the x coordinate of the first point on the line - * @param y0 - * the y coordinate of the first point on the line - * @param x1 - * the x coordinate of the second point on the line - * @param y1 - * the y coordinate of the second point on the line - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radius - * the radius of the circle - * @param intersectionCenterAndHL - * will hold the center of the line segment of intersection in the (x, y) components and the half-length in the z component - * @return true iff the line intersects the circle; false otherwise - */ - public static boolean intersectLineCircle(float x0, float y0, float x1, float y1, float centerX, float centerY, float radius, Vector3f intersectionCenterAndHL) { - // Build general line equation from two points and use the other method - return intersectLineCircle(y0 - y1, x1 - x0, (x0 - x1) * y0 + (y1 - y0) * x0, centerX, centerY, radius, intersectionCenterAndHL); - } - - /** - * Test whether the axis-aligned rectangle with minimum corner (minX, minY) and maximum corner (maxX, maxY) - * intersects the line with the general equation a*x + b*y + c = 0. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @param a - * the x factor in the line equation - * @param b - * the y factor in the line equation - * @param c - * the constant in the plane equation - * @return true iff the axis-aligned rectangle intersects the line; false otherwise - */ - public static boolean testAarLine(float minX, float minY, float maxX, float maxY, float a, float b, float c) { - float pX, pY, nX, nY; - if (a > 0.0f) { - pX = maxX; - nX = minX; - } else { - pX = minX; - nX = maxX; - } - if (b > 0.0f) { - pY = maxY; - nY = minY; - } else { - pY = minY; - nY = maxY; - } - float distN = c + a * nX + b * nY; - float distP = c + a * pX + b * pY; - return distN <= 0.0f && distP >= 0.0f; - } - - /** - * Test whether the axis-aligned rectangle with minimum corner min and maximum corner max - * intersects the line with the general equation a*x + b*y + c = 0. - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param min - * the minimum corner of the axis-aligned rectangle - * @param max - * the maximum corner of the axis-aligned rectangle - * @param a - * the x factor in the line equation - * @param b - * the y factor in the line equation - * @param c - * the constant in the line equation - * @return true iff the axis-aligned rectangle intersects the line; false otherwise - */ - public static boolean testAarLine(Vector2fc min, Vector2fc max, float a, float b, float c) { - return testAarLine(min.x(), min.y(), max.x(), max.y(), a, b, c); - } - - /** - * Test whether the axis-aligned rectangle with minimum corner (minX, minY) and maximum corner (maxX, maxY) - * intersects the line defined by the two points (x0, y0) and (x1, y1). - *

- * Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II") - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @param x0 - * the x coordinate of the first point on the line - * @param y0 - * the y coordinate of the first point on the line - * @param x1 - * the x coordinate of the second point on the line - * @param y1 - * the y coordinate of the second point on the line - * @return true iff the axis-aligned rectangle intersects the line; false otherwise - */ - public static boolean testAarLine(float minX, float minY, float maxX, float maxY, float x0, float y0, float x1, float y1) { - float a = y0 - y1; - float b = x1 - x0; - float c = -b * y0 - a * x0; - return testAarLine(minX, minY, maxX, maxY, a, b, c); - } - - /** - * Test whether the axis-aligned rectangle with minimum corner (minXA, minYA) and maximum corner (maxXA, maxYA) - * intersects the axis-aligned rectangle with minimum corner (minXB, minYB) and maximum corner (maxXB, maxYB). - * - * @param minXA - * the x coordinate of the minimum corner of the first axis-aligned rectangle - * @param minYA - * the y coordinate of the minimum corner of the first axis-aligned rectangle - * @param maxXA - * the x coordinate of the maximum corner of the first axis-aligned rectangle - * @param maxYA - * the y coordinate of the maximum corner of the first axis-aligned rectangle - * @param minXB - * the x coordinate of the minimum corner of the second axis-aligned rectangle - * @param minYB - * the y coordinate of the minimum corner of the second axis-aligned rectangle - * @param maxXB - * the x coordinate of the maximum corner of the second axis-aligned rectangle - * @param maxYB - * the y coordinate of the maximum corner of the second axis-aligned rectangle - * @return true iff both axis-aligned rectangles intersect; false otherwise - */ - public static boolean testAarAar(float minXA, float minYA, float maxXA, float maxYA, float minXB, float minYB, float maxXB, float maxYB) { - return maxXA >= minXB && maxYA >= minYB && minXA <= maxXB && minYA <= maxYB; - } - - /** - * Test whether the axis-aligned rectangle with minimum corner minA and maximum corner maxA - * intersects the axis-aligned rectangle with minimum corner minB and maximum corner maxB. - * - * @param minA - * the minimum corner of the first axis-aligned rectangle - * @param maxA - * the maximum corner of the first axis-aligned rectangle - * @param minB - * the minimum corner of the second axis-aligned rectangle - * @param maxB - * the maximum corner of the second axis-aligned rectangle - * @return true iff both axis-aligned rectangles intersect; false otherwise - */ - public static boolean testAarAar(Vector2fc minA, Vector2fc maxA, Vector2fc minB, Vector2fc maxB) { - return testAarAar(minA.x(), minA.y(), maxA.x(), maxA.y(), minB.x(), minB.y(), maxB.x(), maxB.y()); - } - - /** - * Test whether a given circle with center (aX, aY) and radius aR and travelled distance vector (maX, maY) - * intersects a given static circle with center (bX, bY) and radius bR. - *

- * Note that the case of two moving circles can always be reduced to this case by expressing the moved distance of one of the circles relative - * to the other. - *

- * Reference: https://www.gamasutra.com - * - * @param aX - * the x coordinate of the first circle's center - * @param aY - * the y coordinate of the first circle's center - * @param maX - * the x coordinate of the first circle's travelled distance vector - * @param maY - * the y coordinate of the first circle's travelled distance vector - * @param aR - * the radius of the first circle - * @param bX - * the x coordinate of the second circle's center - * @param bY - * the y coordinate of the second circle's center - * @param bR - * the radius of the second circle - * @return true if both circle intersect; false otherwise - */ - public static boolean testMovingCircleCircle(float aX, float aY, float maX, float maY, float aR, float bX, float bY, float bR) { - float aRbR = aR + bR; - float dist = (float) Math.sqrt((aX - bX) * (aX - bX) + (aY - bY) * (aY - bY)) - aRbR; - float mLen = (float) Math.sqrt(maX * maX + maY * maY); - if (mLen < dist) - return false; - float invMLen = 1.0f / mLen; - float nX = maX * invMLen; - float nY = maY * invMLen; - float cX = bX - aX; - float cY = bY - aY; - float nDotC = nX * cX + nY * cY; - if (nDotC <= 0.0f) - return false; - float cLen = (float) Math.sqrt(cX * cX + cY * cY); - float cLenNdotC = cLen * cLen - nDotC * nDotC; - float aRbR2 = aRbR * aRbR; - if (cLenNdotC >= aRbR2) - return false; - float t = aRbR2 - cLenNdotC; - if (t < 0.0f) - return false; - float distance = nDotC - (float) Math.sqrt(t); - float mag = mLen; - if (mag < distance) - return false; - return true; - } - - /** - * Test whether a given circle with center centerA and radius aR and travelled distance vector moveA - * intersects a given static circle with center centerB and radius bR. - *

- * Note that the case of two moving circles can always be reduced to this case by expressing the moved distance of one of the circles relative - * to the other. - *

- * Reference: https://www.gamasutra.com - * - * @param centerA - * the coordinates of the first circle's center - * @param moveA - * the coordinates of the first circle's travelled distance vector - * @param aR - * the radius of the first circle - * @param centerB - * the coordinates of the second circle's center - * @param bR - * the radius of the second circle - * @return true if both circle intersect; false otherwise - */ - public static boolean testMovingCircleCircle(Vector2f centerA, Vector2f moveA, float aR, Vector2f centerB, float bR) { - return testMovingCircleCircle(centerA.x, centerA.y, moveA.x, moveA.y, aR, centerB.x, centerB.y, bR); - } - - /** - * Test whether the one circle with center (aX, aY) and square radius radiusSquaredA intersects the other - * circle with center (bX, bY) and square radius radiusSquaredB, and store the center of the line segment of - * intersection in the (x, y) components of the supplied vector and the half-length of that line segment in the z component. - *

- * This method returns false when one circle contains the other circle. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param aX - * the x coordinate of the first circle's center - * @param aY - * the y coordinate of the first circle's center - * @param radiusSquaredA - * the square of the first circle's radius - * @param bX - * the x coordinate of the second circle's center - * @param bY - * the y coordinate of the second circle's center - * @param radiusSquaredB - * the square of the second circle's radius - * @param intersectionCenterAndHL - * will hold the center of the circle of intersection in the (x, y, z) components and the radius in the w component - * @return true iff both circles intersect; false otherwise - */ - public static boolean intersectCircleCircle(float aX, float aY, float radiusSquaredA, float bX, float bY, float radiusSquaredB, Vector3f intersectionCenterAndHL) { - float dX = bX - aX, dY = bY - aY; - float distSquared = dX * dX + dY * dY; - float h = 0.5f + (radiusSquaredA - radiusSquaredB) / distSquared; - float r_i = (float) Math.sqrt(radiusSquaredA - h * h * distSquared); - if (r_i >= 0.0f) { - intersectionCenterAndHL.x = aX + h * dX; - intersectionCenterAndHL.y = aY + h * dY; - intersectionCenterAndHL.z = r_i; - return true; - } - return false; - } - - /** - * Test whether the one circle with center centerA and square radius radiusSquaredA intersects the other - * circle with center centerB and square radius radiusSquaredB, and store the center of the line segment of - * intersection in the (x, y) components of the supplied vector and the half-length of that line segment in the z component. - *

- * This method returns false when one circle contains the other circle. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param centerA - * the first circle's center - * @param radiusSquaredA - * the square of the first circle's radius - * @param centerB - * the second circle's center - * @param radiusSquaredB - * the square of the second circle's radius - * @param intersectionCenterAndHL - * will hold the center of the line segment of intersection in the (x, y) components and the half-length in the z component - * @return true iff both circles intersect; false otherwise - */ - public static boolean intersectCircleCircle(Vector2fc centerA, float radiusSquaredA, Vector2fc centerB, float radiusSquaredB, Vector3f intersectionCenterAndHL) { - return intersectCircleCircle(centerA.x(), centerA.y(), radiusSquaredA, centerB.x(), centerB.y(), radiusSquaredB, intersectionCenterAndHL); - } - - /** - * Test whether the one circle with center (aX, aY) and radius rA intersects the other circle with center (bX, bY) and radius rB. - *

- * This method returns true when one circle contains the other circle. - *

- * Reference: http://math.stackexchange.com/ - * - * @param aX - * the x coordinate of the first circle's center - * @param aY - * the y coordinate of the first circle's center - * @param rA - * the square of the first circle's radius - * @param bX - * the x coordinate of the second circle's center - * @param bY - * the y coordinate of the second circle's center - * @param rB - * the square of the second circle's radius - * @return true iff both circles intersect; false otherwise - */ - public static boolean testCircleCircle(float aX, float aY, float rA, float bX, float bY, float rB) { - float d = (aX - bX) * (aX - bX) + (aY - bY) * (aY - bY); - return d <= (rA + rB) * (rA + rB); - } - - /** - * Test whether the one circle with center centerA and square radius radiusSquaredA intersects the other - * circle with center centerB and square radius radiusSquaredB. - *

- * This method returns true when one circle contains the other circle. - *

- * Reference: http://gamedev.stackexchange.com - * - * @param centerA - * the first circle's center - * @param radiusSquaredA - * the square of the first circle's radius - * @param centerB - * the second circle's center - * @param radiusSquaredB - * the square of the second circle's radius - * @return true iff both circles intersect; false otherwise - */ - public static boolean testCircleCircle(Vector2fc centerA, float radiusSquaredA, Vector2fc centerB, float radiusSquaredB) { - return testCircleCircle(centerA.x(), centerA.y(), radiusSquaredA, centerB.x(), centerB.y(), radiusSquaredB); - } - - /** - * Determine the signed distance of the given point (pointX, pointY) to the line specified via its general plane equation - * a*x + b*y + c = 0. - *

- * Reference: http://mathworld.wolfram.com - * - * @param pointX - * the x coordinate of the point - * @param pointY - * the y coordinate of the point - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the constant in the plane equation - * @return the distance between the point and the line - */ - public static float distancePointLine(float pointX, float pointY, float a, float b, float c) { - float denom = (float) Math.sqrt(a * a + b * b); - return (a * pointX + b * pointY + c) / denom; - } - - /** - * Determine the signed distance of the given point (pointX, pointY) to the line defined by the two points (x0, y0) and (x1, y1). - *

- * Reference: http://mathworld.wolfram.com - * - * @param pointX - * the x coordinate of the point - * @param pointY - * the y coordinate of the point - * @param x0 - * the x coordinate of the first point on the line - * @param y0 - * the y coordinate of the first point on the line - * @param x1 - * the x coordinate of the second point on the line - * @param y1 - * the y coordinate of the second point on the line - * @return the distance between the point and the line - */ - public static float distancePointLine(float pointX, float pointY, float x0, float y0, float x1, float y1) { - float dx = x1 - x0; - float dy = y1 - y0; - float denom = (float) Math.sqrt(dx * dx + dy * dy); - return (dx * (y0 - pointY) - (x0 - pointX) * dy) / denom; - } - - /** - * Compute the distance of the given point (pX, pY, pZ) to the line defined by the two points (x0, y0, z0) and (x1, y1, z1). - *

- * Reference: http://mathworld.wolfram.com - * - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param pZ - * the z coordinate of the point - * @param x0 - * the x coordinate of the first point on the line - * @param y0 - * the y coordinate of the first point on the line - * @param z0 - * the z coordinate of the first point on the line - * @param x1 - * the x coordinate of the second point on the line - * @param y1 - * the y coordinate of the second point on the line - * @param z1 - * the z coordinate of the second point on the line - * @return the distance between the point and the line - */ - public static float distancePointLine(float pX, float pY, float pZ, - float x0, float y0, float z0, float x1, float y1, float z1) { - float d21x = x1 - x0, d21y = y1 - y0, d21z = z1 - z0; - float d10x = x0 - pX, d10y = y0 - pY, d10z = z0 - pZ; - float cx = d21y * d10z - d21z * d10y, cy = d21z * d10x - d21x * d10z, cz = d21x * d10y - d21y * d10x; - return (float) Math.sqrt((cx*cx + cy*cy + cz*cz) / (d21x*d21x + d21y*d21y + d21z*d21z)); - } - - /** - * Test whether the ray with given origin (originX, originY) and direction (dirX, dirY) intersects the line - * containing the given point (pointX, pointY) and having the normal (normalX, normalY), and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the line, because it is either parallel to the line or its direction points - * away from the line or the ray's origin is on the negative side of the line (i.e. the line's normal points away from the ray's origin). - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param pointX - * the x coordinate of a point on the line - * @param pointY - * the y coordinate of a point on the line - * @param normalX - * the x coordinate of the line's normal - * @param normalY - * the y coordinate of the line's normal - * @param epsilon - * some small epsilon for when the ray is parallel to the line - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the line; -1.0 otherwise - */ - public static float intersectRayLine(float originX, float originY, float dirX, float dirY, float pointX, float pointY, float normalX, float normalY, float epsilon) { - float denom = normalX * dirX + normalY * dirY; - if (denom < epsilon) { - float t = ((pointX - originX) * normalX + (pointY - originY) * normalY) / denom; - if (t >= 0.0f) - return t; - } - return -1.0f; - } - - /** - * Test whether the ray with given origin and direction dir intersects the line - * containing the given point and having the given normal, and return the - * value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point. - *

- * This method returns -1.0 if the ray does not intersect the line, because it is either parallel to the line or its direction points - * away from the line or the ray's origin is on the negative side of the line (i.e. the line's normal points away from the ray's origin). - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param point - * a point on the line - * @param normal - * the line's normal - * @param epsilon - * some small epsilon for when the ray is parallel to the line - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the line; -1.0 otherwise - */ - public static float intersectRayLine(Vector2fc origin, Vector2fc dir, Vector2fc point, Vector2fc normal, float epsilon) { - return intersectRayLine(origin.x(), origin.y(), dir.x(), dir.y(), point.x(), point.y(), normal.x(), normal.y(), epsilon); - } - - /** - * Determine whether the ray with given origin (originX, originY) and direction (dirX, dirY) intersects the undirected line segment - * given by the two end points (aX, bY) and (bX, bY), and return the value of the parameter t in the ray equation - * p(t) = origin + t * dir of the intersection point, if any. - *

- * This method returns -1.0 if the ray does not intersect the line segment. - * - * @see #intersectRayLineSegment(Vector2fc, Vector2fc, Vector2fc, Vector2fc) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param aX - * the x coordinate of the line segment's first end point - * @param aY - * the y coordinate of the line segment's first end point - * @param bX - * the x coordinate of the line segment's second end point - * @param bY - * the y coordinate of the line segment's second end point - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the line segment; -1.0 otherwise - */ - public static float intersectRayLineSegment(float originX, float originY, float dirX, float dirY, float aX, float aY, float bX, float bY) { - float v1X = originX - aX; - float v1Y = originY - aY; - float v2X = bX - aX; - float v2Y = bY - aY; - float invV23 = 1.0f / (v2Y * dirX - v2X * dirY); - float t1 = (v2X * v1Y - v2Y * v1X) * invV23; - float t2 = (v1Y * dirX - v1X * dirY) * invV23; - if (t1 >= 0.0f && t2 >= 0.0f && t2 <= 1.0f) - return t1; - return -1.0f; - } - - /** - * Determine whether the ray with given origin and direction dir intersects the undirected line segment - * given by the two end points a and b, and return the value of the parameter t in the ray equation - * p(t) = origin + t * dir of the intersection point, if any. - *

- * This method returns -1.0 if the ray does not intersect the line segment. - * - * @see #intersectRayLineSegment(float, float, float, float, float, float, float, float) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param a - * the line segment's first end point - * @param b - * the line segment's second end point - * @return the value of the parameter t in the ray equation p(t) = origin + t * dir of the intersection point, if the ray - * intersects the line segment; -1.0 otherwise - */ - public static float intersectRayLineSegment(Vector2fc origin, Vector2fc dir, Vector2fc a, Vector2fc b) { - return intersectRayLineSegment(origin.x(), origin.y(), dir.x(), dir.y(), a.x(), a.y(), b.x(), b.y()); - } - - /** - * Test whether the axis-aligned rectangle with minimum corner (minX, minY) and maximum corner (maxX, maxY) - * intersects the circle with the given center (centerX, centerY) and square radius radiusSquared. - *

- * Reference: http://stackoverflow.com - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radiusSquared - * the square of the circle's radius - * @return true iff the axis-aligned rectangle intersects the circle; false otherwise - */ - public static boolean testAarCircle(float minX, float minY, float maxX, float maxY, float centerX, float centerY, float radiusSquared) { - float radius2 = radiusSquared; - if (centerX < minX) { - float d = (centerX - minX); - radius2 -= d * d; - } else if (centerX > maxX) { - float d = (centerX - maxX); - radius2 -= d * d; - } - if (centerY < minY) { - float d = (centerY - minY); - radius2 -= d * d; - } else if (centerY > maxY) { - float d = (centerY - maxY); - radius2 -= d * d; - } - return radius2 >= 0.0f; - } - - /** - * Test whether the axis-aligned rectangle with minimum corner min and maximum corner max - * intersects the circle with the given center and square radius radiusSquared. - *

- * Reference: http://stackoverflow.com - * - * @param min - * the minimum corner of the axis-aligned rectangle - * @param max - * the maximum corner of the axis-aligned rectangle - * @param center - * the circle's center - * @param radiusSquared - * the squared of the circle's radius - * @return true iff the axis-aligned rectangle intersects the circle; false otherwise - */ - public static boolean testAarCircle(Vector2fc min, Vector2fc max, Vector2fc center, float radiusSquared) { - return testAarCircle(min.x(), min.y(), max.x(), max.y(), center.x(), center.y(), radiusSquared); - } - - /** - * Determine the closest point on the triangle with the given vertices (v0X, v0Y), (v1X, v1Y), (v2X, v2Y) - * between that triangle and the given point (pX, pY) and store that point into the given result. - *

- * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}) - * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20}) - * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point" - * - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param result - * will hold the closest point - * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}, - * {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or - * {@link #POINT_ON_TRIANGLE_FACE} - */ - public static int findClosestPointOnTriangle(float v0X, float v0Y, float v1X, float v1Y, float v2X, float v2Y, float pX, float pY, Vector2f result) { - float abX = v1X - v0X, abY = v1Y - v0Y; - float acX = v2X - v0X, acY = v2Y - v0Y; - float apX = pX - v0X, apY = pY - v0Y; - float d1 = abX * apX + abY * apY; - float d2 = acX * apX + acY * apY; - if (d1 <= 0.0f && d2 <= 0.0f) { - result.x = v0X; - result.y = v0Y; - return POINT_ON_TRIANGLE_VERTEX_0; - } - float bpX = pX - v1X, bpY = pY - v1Y; - float d3 = abX * bpX + abY * bpY; - float d4 = acX * bpX + acY * bpY; - if (d3 >= 0.0f && d4 <= d3) { - result.x = v1X; - result.y = v1Y; - return POINT_ON_TRIANGLE_VERTEX_1; - } - float vc = d1 * d4 - d3 * d2; - if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) { - float v = d1 / (d1 - d3); - result.x = v0X + v * abX; - result.y = v0Y + v * abY; - return POINT_ON_TRIANGLE_EDGE_01; - } - float cpX = pX - v2X, cpY = pY - v2Y; - float d5 = abX * cpX + abY * cpY; - float d6 = acX * cpX + acY * cpY; - if (d6 >= 0.0f && d5 <= d6) { - result.x = v2X; - result.y = v2Y; - return POINT_ON_TRIANGLE_VERTEX_2; - } - float vb = d5 * d2 - d1 * d6; - if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) { - float w = d2 / (d2 - d6); - result.x = v0X + w * acX; - result.y = v0Y + w * acY; - return POINT_ON_TRIANGLE_EDGE_20; - } - float va = d3 * d6 - d5 * d4; - if (va <= 0.0f && d4 - d3 >= 0.0f && d5 - d6 >= 0.0f) { - float w = (d4 - d3) / (d4 - d3 + d5 - d6); - result.x = v1X + w * (v2X - v1X); - result.y = v1Y + w * (v2Y - v1Y); - return POINT_ON_TRIANGLE_EDGE_12; - } - float denom = 1.0f / (va + vb + vc); - float v = vb * denom; - float w = vc * denom; - result.x = v0X + abX * v + acX * w; - result.y = v0Y + abY * v + acY * w; - return POINT_ON_TRIANGLE_FACE; - } - - /** - * Determine the closest point on the triangle with the vertices v0, v1, v2 - * between that triangle and the given point p and store that point into the given result. - *

- * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}) - * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20}) - * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle. - *

- * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point" - * - * @param v0 - * the first vertex of the triangle - * @param v1 - * the second vertex of the triangle - * @param v2 - * the third vertex of the triangle - * @param p - * the point - * @param result - * will hold the closest point - * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2}, - * {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or - * {@link #POINT_ON_TRIANGLE_FACE} - */ - public static int findClosestPointOnTriangle(Vector2fc v0, Vector2fc v1, Vector2fc v2, Vector2fc p, Vector2f result) { - return findClosestPointOnTriangle(v0.x(), v0.y(), v1.x(), v1.y(), v2.x(), v2.y(), p.x(), p.y(), result); - } - - /** - * Test whether the given ray with the origin (originX, originY) and direction (dirX, dirY) - * intersects the given circle with center (centerX, centerY) and square radius radiusSquared, - * and store the values of the parameter t in the ray equation p(t) = origin + t * dir for both points (near - * and far) of intersections into the given result vector. - *

- * This method returns true for a ray whose origin lies inside the circle. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radiusSquared - * the circle radius squared - * @param result - * a vector that will contain the values of the parameter t in the ray equation - * p(t) = origin + t * dir for both points (near, far) of intersections with the circle - * @return true if the ray intersects the circle; false otherwise - */ - public static boolean intersectRayCircle(float originX, float originY, float dirX, float dirY, - float centerX, float centerY, float radiusSquared, Vector2f result) { - float Lx = centerX - originX; - float Ly = centerY - originY; - float tca = Lx * dirX + Ly * dirY; - float d2 = Lx * Lx + Ly * Ly - tca * tca; - if (d2 > radiusSquared) - return false; - float thc = (float) Math.sqrt(radiusSquared - d2); - float t0 = tca - thc; - float t1 = tca + thc; - if (t0 < t1 && t1 >= 0.0f) { - result.x = t0; - result.y = t1; - return true; - } - return false; - } - - /** - * Test whether the ray with the given origin and direction dir - * intersects the circle with the given center and square radius radiusSquared, - * and store the values of the parameter t in the ray equation p(t) = origin + t * dir for both points (near - * and far) of intersections into the given result vector. - *

- * This method returns true for a ray whose origin lies inside the circle. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param center - * the circle's center - * @param radiusSquared - * the circle radius squared - * @param result - * a vector that will contain the values of the parameter t in the ray equation - * p(t) = origin + t * dir for both points (near, far) of intersections with the circle - * @return true if the ray intersects the circle; false otherwise - */ - public static boolean intersectRayCircle(Vector2fc origin, Vector2fc dir, Vector2fc center, float radiusSquared, Vector2f result) { - return intersectRayCircle(origin.x(), origin.y(), dir.x(), dir.y(), center.x(), center.y(), radiusSquared, result); - } - - /** - * Test whether the given ray with the origin (originX, originY) and direction (dirX, dirY) - * intersects the given circle with center (centerX, centerY) and square radius radiusSquared. - *

- * This method returns true for a ray whose origin lies inside the circle. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radiusSquared - * the circle radius squared - * @return true if the ray intersects the circle; false otherwise - */ - public static boolean testRayCircle(float originX, float originY, float dirX, float dirY, - float centerX, float centerY, float radiusSquared) { - float Lx = centerX - originX; - float Ly = centerY - originY; - float tca = Lx * dirX + Ly * dirY; - float d2 = Lx * Lx + Ly * Ly - tca * tca; - if (d2 > radiusSquared) - return false; - float thc = (float) Math.sqrt(radiusSquared - d2); - float t0 = tca - thc; - float t1 = tca + thc; - return t0 < t1 && t1 >= 0.0f; - } - - /** - * Test whether the ray with the given origin and direction dir - * intersects the circle with the given center and square radius. - *

- * This method returns true for a ray whose origin lies inside the circle. - *

- * Reference: http://www.scratchapixel.com/ - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param center - * the circle's center - * @param radiusSquared - * the circle radius squared - * @return true if the ray intersects the circle; false otherwise - */ - public static boolean testRayCircle(Vector2fc origin, Vector2fc dir, Vector2fc center, float radiusSquared) { - return testRayCircle(origin.x(), origin.y(), dir.x(), dir.y(), center.x(), center.y(), radiusSquared); - } - - /** - * Determine whether the given ray with the origin (originX, originY) and direction (dirX, dirY) - * intersects the axis-aligned rectangle given as its minimum corner (minX, minY) and maximum corner (maxX, maxY), - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * as well as the side of the axis-aligned rectangle the ray intersects. - *

- * This method also detects an intersection for a ray whose origin lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @param result - * a vector which will hold the values of the parameter t in the ray equation - * p(t) = origin + t * dir of the near and far point of intersection - * @return the side on which the near intersection occurred as one of - * {@link #AAR_SIDE_MINX}, {@link #AAR_SIDE_MINY}, {@link #AAR_SIDE_MAXX} or {@link #AAR_SIDE_MAXY}; - * or -1 if the ray does not intersect the axis-aligned rectangle; - */ - public static int intersectRayAar(float originX, float originY, float dirX, float dirY, - float minX, float minY, float maxX, float maxY, Vector2f result) { - float invDirX = 1.0f / dirX, invDirY = 1.0f / dirY; - float tNear, tFar, tymin, tymax; - if (invDirX >= 0.0f) { - tNear = (minX - originX) * invDirX; - tFar = (maxX - originX) * invDirX; - } else { - tNear = (maxX - originX) * invDirX; - tFar = (minX - originX) * invDirX; - } - if (invDirY >= 0.0f) { - tymin = (minY - originY) * invDirY; - tymax = (maxY - originY) * invDirY; - } else { - tymin = (maxY - originY) * invDirY; - tymax = (minY - originY) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return OUTSIDE; - tNear = tymin > tNear || Float.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Float.isNaN(tFar) ? tymax : tFar; - int side = -1; // no intersection side - if (tNear <= tFar && tFar >= 0.0f) { - float px = originX + tNear * dirX; - float py = originY + tNear * dirY; - result.x = tNear; - result.y = tFar; - float daX = Math.abs(px - minX); - float daY = Math.abs(py - minY); - float dbX = Math.abs(px - maxX); - float dbY = Math.abs(py - maxY); - side = 0; // min x coordinate - float min = daX; - if (daY < min) { - min = daY; - side = 1; // min y coordinate - } - if (dbX < min) { - min = dbX; - side = 2; // max xcoordinate - } - if (dbY < min) - side = 3; // max y coordinate - } - return side; - } - - /** - * Determine whether the given ray with the given origin and direction dir - * intersects the axis-aligned rectangle given as its minimum corner min and maximum corner max, - * and return the values of the parameter t in the ray equation p(t) = origin + t * dir of the near and far point of intersection - * as well as the side of the axis-aligned rectangle the ray intersects. - *

- * This method also detects an intersection for a ray whose origin lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectRayAar(float, float, float, float, float, float, float, float, Vector2f) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param min - * the minimum corner of the axis-aligned rectangle - * @param max - * the maximum corner of the axis-aligned rectangle - * @param result - * a vector which will hold the values of the parameter t in the ray equation - * p(t) = origin + t * dir of the near and far point of intersection - * @return the side on which the near intersection occurred as one of - * {@link #AAR_SIDE_MINX}, {@link #AAR_SIDE_MINY}, {@link #AAR_SIDE_MAXX} or {@link #AAR_SIDE_MAXY}; - * or -1 if the ray does not intersect the axis-aligned rectangle; - */ - public static int intersectRayAar(Vector2fc origin, Vector2fc dir, Vector2fc min, Vector2fc max, Vector2f result) { - return intersectRayAar(origin.x(), origin.y(), dir.x(), dir.y(), min.x(), min.y(), max.x(), max.y(), result); - } - - /** - * Determine whether the undirected line segment with the end points (p0X, p0Y) and (p1X, p1Y) - * intersects the axis-aligned rectangle given as its minimum corner (minX, minY) and maximum corner (maxX, maxY), - * and store the values of the parameter t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * into result. - *

- * This method also detects an intersection of a line segment whose either end point lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #intersectLineSegmentAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc, Vector2f) - * - * @param p0X - * the x coordinate of the line segment's first end point - * @param p0Y - * the y coordinate of the line segment's first end point - * @param p1X - * the x coordinate of the line segment's second end point - * @param p1Y - * the y coordinate of the line segment's second end point - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @param result - * a vector which will hold the values of the parameter t in the ray equation - * p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned rectangle; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned rectangle; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned rectangle; or - * {@link #TWO_INTERSECTION} if the line segment intersects two edges of the axis-aligned rectangle or lies on one edge of the rectangle - */ - public static int intersectLineSegmentAar(float p0X, float p0Y, float p1X, float p1Y, - float minX, float minY, float maxX, float maxY, Vector2f result) { - float dirX = p1X - p0X, dirY = p1Y - p0Y; - float invDirX = 1.0f / dirX, invDirY = 1.0f / dirY; - float tNear, tFar, tymin, tymax; - if (invDirX >= 0.0f) { - tNear = (minX - p0X) * invDirX; - tFar = (maxX - p0X) * invDirX; - } else { - tNear = (maxX - p0X) * invDirX; - tFar = (minX - p0X) * invDirX; - } - if (invDirY >= 0.0f) { - tymin = (minY - p0Y) * invDirY; - tymax = (maxY - p0Y) * invDirY; - } else { - tymin = (maxY - p0Y) * invDirY; - tymax = (minY - p0Y) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return OUTSIDE; - tNear = tymin > tNear || Float.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Float.isNaN(tFar) ? tymax : tFar; - int type = OUTSIDE; - if (tNear <= tFar && tNear <= 1.0f && tFar >= 0.0f) { - if (tNear >= 0.0f && tFar > 1.0f) { - tFar = tNear; - type = ONE_INTERSECTION; - } else if (tNear < 0.0f && tFar <= 1.0f) { - tNear = tFar; - type = ONE_INTERSECTION; - } else if (tNear < 0.0f && tFar > 1.0f) { - type = INSIDE; - } else { - type = TWO_INTERSECTION; - } - result.x = tNear; - result.y = tFar; - } - return type; - } - - /** - * Determine whether the undirected line segment with the end points p0 and p1 - * intersects the axis-aligned rectangle given as its minimum corner min and maximum corner max, - * and store the values of the parameter t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * into result. - *

- * This method also detects an intersection of a line segment whose either end point lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * #see {@link #intersectLineSegmentAar(float, float, float, float, float, float, float, float, Vector2f)} - * - * @param p0 - * the line segment's first end point - * @param p1 - * the line segment's second end point - * @param min - * the minimum corner of the axis-aligned rectangle - * @param max - * the maximum corner of the axis-aligned rectangle - * @param result - * a vector which will hold the values of the parameter t in the ray equation - * p(t) = p0 + t * (p1 - p0) of the near and far point of intersection - * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned rectangle; or - * {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned rectangle; or - * {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned rectangle; or - * {@link #TWO_INTERSECTION} if the line segment intersects two edges of the axis-aligned rectangle - */ - public static int intersectLineSegmentAar(Vector2fc p0, Vector2fc p1, Vector2fc min, Vector2fc max, Vector2f result) { - return intersectLineSegmentAar(p0.x(), p0.y(), p1.x(), p1.y(), min.x(), min.y(), max.x(), max.y(), result); - } - - /** - * Test whether the given ray with the origin (originX, originY) and direction (dirX, dirY) - * intersects the given axis-aligned rectangle given as its minimum corner (minX, minY) and maximum corner (maxX, maxY). - *

- * This method returns true for a ray whose origin lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAar(Vector2fc, Vector2fc, Vector2fc, Vector2fc) - * - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @return true if the given ray intersects the axis-aligned rectangle; false otherwise - */ - public static boolean testRayAar(float originX, float originY, float dirX, float dirY, float minX, float minY, float maxX, float maxY) { - float invDirX = 1.0f / dirX, invDirY = 1.0f / dirY; - float tNear, tFar, tymin, tymax; - if (invDirX >= 0.0f) { - tNear = (minX - originX) * invDirX; - tFar = (maxX - originX) * invDirX; - } else { - tNear = (maxX - originX) * invDirX; - tFar = (minX - originX) * invDirX; - } - if (invDirY >= 0.0f) { - tymin = (minY - originY) * invDirY; - tymax = (maxY - originY) * invDirY; - } else { - tymin = (maxY - originY) * invDirY; - tymax = (minY - originY) * invDirY; - } - if (tNear > tymax || tymin > tFar) - return false; - tNear = tymin > tNear || Float.isNaN(tNear) ? tymin : tNear; - tFar = tymax < tFar || Float.isNaN(tFar) ? tymax : tFar; - return tNear < tFar && tFar >= 0.0f; - } - - /** - * Test whether the ray with the given origin and direction dir - * intersects the given axis-aligned rectangle specified as its minimum corner min and maximum corner max. - *

- * This method returns true for a ray whose origin lies inside the axis-aligned rectangle. - *

- * Reference: An Efficient and Robust Ray–Box Intersection - * - * @see #testRayAar(float, float, float, float, float, float, float, float) - * - * @param origin - * the ray's origin - * @param dir - * the ray's direction - * @param min - * the minimum corner of the axis-aligned rectangle - * @param max - * the maximum corner of the axis-aligned rectangle - * @return true if the given ray intersects the axis-aligned rectangle; false otherwise - */ - public static boolean testRayAar(Vector2fc origin, Vector2fc dir, Vector2fc min, Vector2fc max) { - return testRayAar(origin.x(), origin.y(), dir.x(), dir.y(), min.x(), min.y(), max.x(), max.y()); - } - - /** - * Test whether the given point (pX, pY) lies inside the triangle with the vertices (v0X, v0Y), (v1X, v1Y), (v2X, v2Y). - * - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @return true iff the point lies inside the triangle; false otherwise - */ - public static boolean testPointTriangle(float pX, float pY, float v0X, float v0Y, float v1X, float v1Y, float v2X, float v2Y) { - boolean b1 = (pX - v1X) * (v0Y - v1Y) - (v0X - v1X) * (pY - v1Y) < 0.0f; - boolean b2 = (pX - v2X) * (v1Y - v2Y) - (v1X - v2X) * (pY - v2Y) < 0.0f; - if (b1 != b2) - return false; - boolean b3 = (pX - v0X) * (v2Y - v0Y) - (v2X - v0X) * (pY - v0Y) < 0.0f; - return b2 == b3; - } - - /** - * Test whether the given point lies inside the triangle with the vertices v0, v1, v2. - * - * @param v0 - * the first vertex of the triangle - * @param v1 - * the second vertex of the triangle - * @param v2 - * the third vertex of the triangle - * @param point - * the point - * @return true iff the point lies inside the triangle; false otherwise - */ - public static boolean testPointTriangle(Vector2fc point, Vector2fc v0, Vector2fc v1, Vector2fc v2) { - return testPointTriangle(point.x(), point.y(), v0.x(), v0.y(), v1.x(), v1.y(), v2.x(), v2.y()); - } - - /** - * Test whether the given point (pX, pY) lies inside the axis-aligned rectangle with the minimum corner (minX, minY) - * and maximum corner (maxX, maxY). - * - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param minX - * the x coordinate of the minimum corner of the axis-aligned rectangle - * @param minY - * the y coordinate of the minimum corner of the axis-aligned rectangle - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned rectangle - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned rectangle - * @return true iff the point lies inside the axis-aligned rectangle; false otherwise - */ - public static boolean testPointAar(float pX, float pY, float minX, float minY, float maxX, float maxY) { - return pX >= minX && pY >= minY && pX <= maxX && pY <= maxY; - } - - /** - * Test whether the point (pX, pY) lies inside the circle with center (centerX, centerY) and square radius radiusSquared. - * - * @param pX - * the x coordinate of the point - * @param pY - * the y coordinate of the point - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radiusSquared - * the square radius of the circle - * @return true iff the point lies inside the circle; false otherwise - */ - public static boolean testPointCircle(float pX, float pY, float centerX, float centerY, float radiusSquared) { - float dx = pX - centerX; - float dy = pY - centerY; - float dx2 = dx * dx; - float dy2 = dy * dy; - return dx2 + dy2 <= radiusSquared; - } - - /** - * Test whether the circle with center (centerX, centerY) and square radius radiusSquared intersects the triangle with counter-clockwise vertices - * (v0X, v0Y), (v1X, v1Y), (v2X, v2Y). - *

- * The vertices of the triangle must be specified in counter-clockwise order. - *

- * Reference: http://www.phatcode.net/ - * - * @param centerX - * the x coordinate of the circle's center - * @param centerY - * the y coordinate of the circle's center - * @param radiusSquared - * the square radius of the circle - * @param v0X - * the x coordinate of the first vertex of the triangle - * @param v0Y - * the y coordinate of the first vertex of the triangle - * @param v1X - * the x coordinate of the second vertex of the triangle - * @param v1Y - * the y coordinate of the second vertex of the triangle - * @param v2X - * the x coordinate of the third vertex of the triangle - * @param v2Y - * the y coordinate of the third vertex of the triangle - * @return true iff the circle intersects the triangle; false otherwise - */ - public static boolean testCircleTriangle(float centerX, float centerY, float radiusSquared, float v0X, float v0Y, float v1X, float v1Y, float v2X, float v2Y) { - float c1x = centerX - v0X, c1y = centerY - v0Y; - float c1sqr = c1x * c1x + c1y * c1y - radiusSquared; - if (c1sqr <= 0.0f) - return true; - float c2x = centerX - v1X, c2y = centerY - v1Y; - float c2sqr = c2x * c2x + c2y * c2y - radiusSquared; - if (c2sqr <= 0.0f) - return true; - float c3x = centerX - v2X, c3y = centerY - v2Y; - float c3sqr = c3x * c3x + c3y * c3y - radiusSquared; - if (c3sqr <= 0.0f) - return true; - float e1x = v1X - v0X, e1y = v1Y - v0Y; - float e2x = v2X - v1X, e2y = v2Y - v1Y; - float e3x = v0X - v2X, e3y = v0Y - v2Y; - if (e1x * c1y - e1y * c1x >= 0.0f && e2x * c2y - e2y * c2x >= 0.0f && e3x * c3y - e3y * c3x >= 0.0f) - return true; - float k = c1x * e1x + c1y * e1y; - if (k >= 0.0f) { - float len = e1x * e1x + e1y * e1y; - if (k <= len) { - if (c1sqr * len <= k * k) - return true; - } - } - k = c2x * e2x + c2y * e2y; - if (k > 0.0f) { - float len = e2x * e2x + e2y * e2y; - if (k <= len) { - if (c2sqr * len <= k * k) - return true; - } - } - k = c3x * e3x + c3y * e3y; - if (k >= 0.0f) { - float len = e3x * e3x + e3y * e3y; - if (k < len) { - if (c3sqr * len <= k * k) - return true; - } - } - return false; - } - - /** - * Test whether the circle with given center and square radius radiusSquared intersects the triangle with counter-clockwise vertices - * v0, v1, v2. - *

- * The vertices of the triangle must be specified in counter-clockwise order. - *

- * Reference: http://www.phatcode.net/ - * - * @param center - * the circle's center - * @param radiusSquared - * the square radius of the circle - * @param v0 - * the first vertex of the triangle - * @param v1 - * the second vertex of the triangle - * @param v2 - * the third vertex of the triangle - * @return true iff the circle intersects the triangle; false otherwise - */ - public static boolean testCircleTriangle(Vector2fc center, float radiusSquared, Vector2fc v0, Vector2fc v1, Vector2fc v2) { - return testCircleTriangle(center.x(), center.y(), radiusSquared, v0.x(), v0.y(), v1.x(), v1.y(), v2.x(), v2.y()); - } - - /** - * Determine whether the polygon specified by the given sequence of (x, y) coordinate pairs intersects with the ray - * with given origin (originX, originY, originZ) and direction (dirX, dirY, dirZ), and store the point of intersection - * into the given vector p. - *

- * If the polygon intersects the ray, this method returns the index of the polygon edge intersecting the ray, that is, the index of the - * first vertex of the directed line segment. The second vertex is always that index + 1, modulus the number of polygon vertices. - * - * @param verticesXY - * the sequence of (x, y) coordinate pairs of all vertices of the polygon - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param p - * will hold the point of intersection - * @return the index of the first vertex of the polygon edge that intersects the ray; or -1 if the ray does not intersect the polygon - */ - public static int intersectPolygonRay(float[] verticesXY, float originX, float originY, float dirX, float dirY, Vector2f p) { - float nearestT = Float.POSITIVE_INFINITY; - int count = verticesXY.length >> 1; - int edgeIndex = -1; - float aX = verticesXY[(count-1)<<1], aY = verticesXY[((count-1)<<1) + 1]; - for (int i = 0; i < count; i++) { - float bX = verticesXY[i << 1], bY = verticesXY[(i << 1) + 1]; - float doaX = originX - aX, doaY = originY - aY; - float dbaX = bX - aX, dbaY = bY - aY; - float invDbaDir = 1.0f / (dbaY * dirX - dbaX * dirY); - float t = (dbaX * doaY - dbaY * doaX) * invDbaDir; - if (t >= 0.0f && t < nearestT) { - float t2 = (doaY * dirX - doaX * dirY) * invDbaDir; - if (t2 >= 0.0f && t2 <= 1.0f) { - edgeIndex = (i - 1 + count) % count; - nearestT = t; - p.x = originX + t * dirX; - p.y = originY + t * dirY; - } - } - aX = bX; - aY = bY; - } - return edgeIndex; - } - - /** - * Determine whether the polygon specified by the given sequence of vertices intersects with the ray - * with given origin (originX, originY, originZ) and direction (dirX, dirY, dirZ), and store the point of intersection - * into the given vector p. - *

- * If the polygon intersects the ray, this method returns the index of the polygon edge intersecting the ray, that is, the index of the - * first vertex of the directed line segment. The second vertex is always that index + 1, modulus the number of polygon vertices. - * - * @param vertices - * the sequence of (x, y) coordinate pairs of all vertices of the polygon - * @param originX - * the x coordinate of the ray's origin - * @param originY - * the y coordinate of the ray's origin - * @param dirX - * the x coordinate of the ray's direction - * @param dirY - * the y coordinate of the ray's direction - * @param p - * will hold the point of intersection - * @return the index of the first vertex of the polygon edge that intersects the ray; or -1 if the ray does not intersect the polygon - */ - public static int intersectPolygonRay(Vector2fc[] vertices, float originX, float originY, float dirX, float dirY, Vector2f p) { - float nearestT = Float.POSITIVE_INFINITY; - int count = vertices.length; - int edgeIndex = -1; - float aX = vertices[count-1].x(), aY = vertices[count-1].y(); - for (int i = 0; i < count; i++) { - Vector2fc b = vertices[i]; - float bX = b.x(), bY = b.y(); - float doaX = originX - aX, doaY = originY - aY; - float dbaX = bX - aX, dbaY = bY - aY; - float invDbaDir = 1.0f / (dbaY * dirX - dbaX * dirY); - float t = (dbaX * doaY - dbaY * doaX) * invDbaDir; - if (t >= 0.0f && t < nearestT) { - float t2 = (doaY * dirX - doaX * dirY) * invDbaDir; - if (t2 >= 0.0f && t2 <= 1.0f) { - edgeIndex = (i - 1 + count) % count; - nearestT = t; - p.x = originX + t * dirX; - p.y = originY + t * dirY; - } - } - aX = bX; - aY = bY; - } - return edgeIndex; - } - - /** - * Determine whether the two lines, specified via two points lying on each line, intersect each other, and store the point of intersection - * into the given vector p. - * - * @param ps1x - * the x coordinate of the first point on the first line - * @param ps1y - * the y coordinate of the first point on the first line - * @param pe1x - * the x coordinate of the second point on the first line - * @param pe1y - * the y coordinate of the second point on the first line - * @param ps2x - * the x coordinate of the first point on the second line - * @param ps2y - * the y coordinate of the first point on the second line - * @param pe2x - * the x coordinate of the second point on the second line - * @param pe2y - * the y coordinate of the second point on the second line - * @param p - * will hold the point of intersection - * @return true iff the two lines intersect; false otherwise - */ - public static boolean intersectLineLine(float ps1x, float ps1y, float pe1x, float pe1y, float ps2x, float ps2y, float pe2x, float pe2y, Vector2f p) { - float d1x = ps1x - pe1x; - float d1y = pe1y - ps1y; - float d1ps1 = d1y * ps1x + d1x * ps1y; - float d2x = ps2x - pe2x; - float d2y = pe2y - ps2y; - float d2ps2 = d2y * ps2x + d2x * ps2y; - float det = d1y * d2x - d2y * d1x; - if (det == 0.0f) - return false; - p.x = (d2x * d1ps1 - d1x * d2ps2) / det; - p.y = (d1y * d2ps2 - d2y * d1ps1) / det; - return true; - } - - private static boolean separatingAxis(Vector2f[] v1s, Vector2f[] v2s, float aX, float aY) { - float minA = Float.POSITIVE_INFINITY, maxA = Float.NEGATIVE_INFINITY; - float minB = Float.POSITIVE_INFINITY, maxB = Float.NEGATIVE_INFINITY; - int maxLen = Math.max(v1s.length, v2s.length); - /* Project both polygons on axis */ - for (int k = 0; k < maxLen; k++) { - if (k < v1s.length) { - Vector2f v1 = v1s[k]; - float d = v1.x * aX + v1.y * aY; - if (d < minA) minA = d; - if (d > maxA) maxA = d; - } - if (k < v2s.length) { - Vector2f v2 = v2s[k]; - float d = v2.x * aX + v2.y * aY; - if (d < minB) minB = d; - if (d > maxB) maxB = d; - } - /* Early-out if overlap found */ - if (minA <= maxB && minB <= maxA) { - return false; - } - } - return true; - } - - /** - * Test if the two polygons, given via their vertices, intersect. - * - * @param v1s - * the vertices of the first polygon - * @param v2s - * the vertices of the second polygon - * @return true if the polygons intersect; false otherwise - */ - public static boolean testPolygonPolygon(Vector2f[] v1s, Vector2f[] v2s) { - /* Try to find a separating axis using the first polygon's edges */ - for (int i = 0, j = v1s.length - 1; i < v1s.length; j = i, i++) { - Vector2f s = v1s[i], t = v1s[j]; - if (separatingAxis(v1s, v2s, s.y - t.y, t.x - s.x)) - return false; - } - /* Try to find a separating axis using the second polygon's edges */ - for (int i = 0, j = v2s.length - 1; i < v2s.length; j = i, i++) { - Vector2f s = v2s[i], t = v2s[j]; - if (separatingAxis(v1s, v2s, s.y - t.y, t.x - s.x)) - return false; - } - return true; - } - -} diff --git a/src/org/joml/LineSegmentd.java b/src/org/joml/LineSegmentd.java deleted file mode 100644 index 0b9469670..000000000 --- a/src/org/joml/LineSegmentd.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents an undirected line segment between two points. - * - * @author Kai Burjack - */ -public class LineSegmentd implements Externalizable { - - /** - * The x coordinate of the first point. - */ - public double aX; - /** - * The y coordinate of the first point. - */ - public double aY; - /** - * The z coordinate of the first point. - */ - public double aZ; - /** - * The x coordinate of the second point. - */ - public double bX; - /** - * The y coordinate of the second point. - */ - public double bY; - /** - * The z coordinate of the second point. - */ - public double bZ; - - /** - * Create a new {@link LineSegmentd} of zero length on the point (0, 0, 0). - */ - public LineSegmentd() { - } - - /** - * Create a new {@link LineSegmentd} as a copy of the given source. - * - * @param source - * the {@link LineSegmentd} to copy from - */ - public LineSegmentd(LineSegmentd source) { - this.aX = source.aX; - this.aY = source.aY; - this.aZ = source.aZ; - this.aX = source.bX; - this.bY = source.bY; - this.bZ = source.bZ; - } - - /** - * Create a new {@link LineSegmentd} between the given two points. - * - * @param a - * the first point - * @param b - * the second point - */ - public LineSegmentd(Vector3dc a, Vector3dc b) { - this.aX = a.x(); - this.aY = a.y(); - this.aZ = a.z(); - this.bX = b.x(); - this.bY = b.y(); - this.bZ = b.z(); - } - - /** - * Create a new {@link LineSegmentd} between the two points. - * - * @param aX - * the x coordinate of the first point - * @param aY - * the y coordinate of the first point - * @param aZ - * the z coordinate of the first point - * @param bX - * the x coordinate of the second point - * @param bY - * the y coordinate of the second point - * @param bZ - * the z coordinate of the second point - */ - public LineSegmentd(double aX, double aY, double aZ, double bX, double bY, double bZ) { - super(); - this.aX = aX; - this.aY = aY; - this.aZ = aZ; - this.bX = bX; - this.bY = bY; - this.bZ = bZ; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(aX); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(aY); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(aZ); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(bX); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(bY); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(bZ); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - LineSegmentd other = (LineSegmentd) obj; - if (Double.doubleToLongBits(aX) != Double.doubleToLongBits(other.aX)) - return false; - if (Double.doubleToLongBits(aY) != Double.doubleToLongBits(other.aY)) - return false; - if (Double.doubleToLongBits(aZ) != Double.doubleToLongBits(other.aZ)) - return false; - if (Double.doubleToLongBits(bX) != Double.doubleToLongBits(other.bX)) - return false; - if (Double.doubleToLongBits(bY) != Double.doubleToLongBits(other.bY)) - return false; - if (Double.doubleToLongBits(bZ) != Double.doubleToLongBits(other.bZ)) - return false; - return true; - } - - /** - * Return a string representation of this line segment. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this line segment by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(aX, formatter) + " " + Runtime.format(aY, formatter) + " " + Runtime.format(aZ, formatter) + ") - " - + "(" + Runtime.format(bX, formatter) + " " + Runtime.format(bY, formatter) + " " + Runtime.format(bZ, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeDouble(aX); - out.writeDouble(aY); - out.writeDouble(aZ); - out.writeDouble(bX); - out.writeDouble(bY); - out.writeDouble(bZ); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - aX = in.readDouble(); - aY = in.readDouble(); - aZ = in.readDouble(); - bX = in.readDouble(); - bY = in.readDouble(); - bZ = in.readDouble(); - } - -} diff --git a/src/org/joml/LineSegmentf.java b/src/org/joml/LineSegmentf.java deleted file mode 100644 index 289c78156..000000000 --- a/src/org/joml/LineSegmentf.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents an undirected line segment between two points. - * - * @author Kai Burjack - */ -public class LineSegmentf implements Externalizable { - - /** - * The x coordinate of the first point. - */ - public float aX; - /** - * The y coordinate of the first point. - */ - public float aY; - /** - * The z coordinate of the first point. - */ - public float aZ; - /** - * The x coordinate of the second point. - */ - public float bX; - /** - * The y coordinate of the second point. - */ - public float bY; - /** - * The z coordinate of the second point. - */ - public float bZ; - - /** - * Create a new {@link LineSegmentf} of zero length on the point (0, 0, 0). - */ - public LineSegmentf() { - } - - /** - * Create a new {@link LineSegmentf} as a copy of the given source. - * - * @param source - * the {@link LineSegmentf} to copy from - */ - public LineSegmentf(LineSegmentf source) { - this.aX = source.aX; - this.aY = source.aY; - this.aZ = source.aZ; - this.aX = source.bX; - this.bY = source.bY; - this.bZ = source.bZ; - } - - /** - * Create a new {@link LineSegmentf} between the given two points. - * - * @param a - * the first point - * @param b - * the second point - */ - public LineSegmentf(Vector3fc a, Vector3fc b) { - this.aX = a.x(); - this.aY = a.y(); - this.aZ = a.z(); - this.bX = b.x(); - this.bY = b.y(); - this.bZ = b.z(); - } - - /** - * Create a new {@link LineSegmentf} between the two points. - * - * @param aX - * the x coordinate of the first point - * @param aY - * the y coordinate of the first point - * @param aZ - * the z coordinate of the first point - * @param bX - * the x coordinate of the second point - * @param bY - * the y coordinate of the second point - * @param bZ - * the z coordinate of the second point - */ - public LineSegmentf(float aX, float aY, float aZ, float bX, float bY, float bZ) { - super(); - this.aX = aX; - this.aY = aY; - this.aZ = aZ; - this.bX = bX; - this.bY = bY; - this.bZ = bZ; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(aX); - result = prime * result + Float.floatToIntBits(aY); - result = prime * result + Float.floatToIntBits(aZ); - result = prime * result + Float.floatToIntBits(bX); - result = prime * result + Float.floatToIntBits(bY); - result = prime * result + Float.floatToIntBits(bZ); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - LineSegmentf other = (LineSegmentf) obj; - if (Float.floatToIntBits(aX) != Float.floatToIntBits(other.aX)) - return false; - if (Float.floatToIntBits(aY) != Float.floatToIntBits(other.aY)) - return false; - if (Float.floatToIntBits(aZ) != Float.floatToIntBits(other.aZ)) - return false; - if (Float.floatToIntBits(bX) != Float.floatToIntBits(other.bX)) - return false; - if (Float.floatToIntBits(bY) != Float.floatToIntBits(other.bY)) - return false; - if (Float.floatToIntBits(bZ) != Float.floatToIntBits(other.bZ)) - return false; - return true; - } - - /** - * Return a string representation of this line segment. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this line segment by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(aX, formatter) + " " + Runtime.format(aY, formatter) + " " + Runtime.format(aZ, formatter) + ") - " - + "(" + Runtime.format(bX, formatter) + " " + Runtime.format(bY, formatter) + " " + Runtime.format(bZ, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(aX); - out.writeFloat(aY); - out.writeFloat(aZ); - out.writeFloat(bX); - out.writeFloat(bY); - out.writeFloat(bZ); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - aX = in.readFloat(); - aY = in.readFloat(); - aZ = in.readFloat(); - bX = in.readFloat(); - bY = in.readFloat(); - bZ = in.readFloat(); - } - -} diff --git a/src/org/joml/Matrix4d.java b/src/org/joml/Matrix4d.java index 09b01c114..2fa90c0f3 100644 --- a/src/org/joml/Matrix4d.java +++ b/src/org/joml/Matrix4d.java @@ -13618,55 +13618,29 @@ public Matrix4d setFromIntrinsic(double alphaX, double alphaY, double gamma, dou public Vector4d frustumPlane(int plane, Vector4d dest) { switch (plane) { case PLANE_NX: - dest.set(m03 + m00, m13 + m10, m23 + m20, m33 + m30).normalize3(dest); + dest.set(m03 + m00, m13 + m10, m23 + m20, m33 + m30).normalize3(); break; case PLANE_PX: - dest.set(m03 - m00, m13 - m10, m23 - m20, m33 - m30).normalize3(dest); + dest.set(m03 - m00, m13 - m10, m23 - m20, m33 - m30).normalize3(); break; case PLANE_NY: - dest.set(m03 + m01, m13 + m11, m23 + m21, m33 + m31).normalize3(dest); + dest.set(m03 + m01, m13 + m11, m23 + m21, m33 + m31).normalize3(); break; case PLANE_PY: - dest.set(m03 - m01, m13 - m11, m23 - m21, m33 - m31).normalize3(dest); + dest.set(m03 - m01, m13 - m11, m23 - m21, m33 - m31).normalize3(); break; case PLANE_NZ: - dest.set(m03 + m02, m13 + m12, m23 + m22, m33 + m32).normalize3(dest); + dest.set(m03 + m02, m13 + m12, m23 + m22, m33 + m32).normalize3(); break; case PLANE_PZ: - dest.set(m03 - m02, m13 - m12, m23 - m22, m33 - m32).normalize3(dest); + dest.set(m03 - m02, m13 - m12, m23 - m22, m33 - m32).normalize3(); break; default: - throw new IllegalArgumentException("plane"); //$NON-NLS-1$ + throw new IllegalArgumentException("dest"); //$NON-NLS-1$ } return dest; } - public Planed frustumPlane(int which, Planed plane) { - switch (which) { - case PLANE_NX: - plane.set(m03 + m00, m13 + m10, m23 + m20, m33 + m30).normalize(plane); - break; - case PLANE_PX: - plane.set(m03 - m00, m13 - m10, m23 - m20, m33 - m30).normalize(plane); - break; - case PLANE_NY: - plane.set(m03 + m01, m13 + m11, m23 + m21, m33 + m31).normalize(plane); - break; - case PLANE_PY: - plane.set(m03 - m01, m13 - m11, m23 - m21, m33 - m31).normalize(plane); - break; - case PLANE_NZ: - plane.set(m03 + m02, m13 + m12, m23 + m22, m33 + m32).normalize(plane); - break; - case PLANE_PZ: - plane.set(m03 - m02, m13 - m12, m23 - m22, m33 - m32).normalize(plane); - break; - default: - throw new IllegalArgumentException("which"); //$NON-NLS-1$ - } - return plane; - } - public Vector3d frustumCorner(int corner, Vector3d dest) { double d1, d2, d3; double n1x, n1y, n1z, n2x, n2y, n2z, n3x, n3y, n3z; diff --git a/src/org/joml/Matrix4dc.java b/src/org/joml/Matrix4dc.java index 457207945..3a054ea6b 100644 --- a/src/org/joml/Matrix4dc.java +++ b/src/org/joml/Matrix4dc.java @@ -38,38 +38,32 @@ public interface Matrix4dc { /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} and - * {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation x=-1 when using the identity matrix. */ int PLANE_NX = 0; /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} and - * {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation x=1 when using the identity matrix. */ int PLANE_PX = 1; /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} and - * {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation y=-1 when using the identity matrix. */ int PLANE_NY = 2; /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} and - * {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation y=1 when using the identity matrix. */ int PLANE_PY = 3; /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} and - * {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation z=-1 when using the identity matrix. */ int PLANE_NZ = 4; /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} and - * {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation z=1 when using the identity matrix. */ int PLANE_PZ = 5; @@ -4621,7 +4615,7 @@ Matrix4d mul3x3( /** * Calculate a frustum plane of this matrix, which * can be a projection matrix or a combined modelview-projection matrix, and store the result - * in the given planeEquation. + * in the given dest. *

* Generally, this method computes the frustum plane in the local frame of * any coordinate system that existed before this @@ -4646,43 +4640,12 @@ Matrix4d mul3x3( * {@link #PLANE_NX}, {@link #PLANE_PX}, * {@link #PLANE_NY}, {@link #PLANE_PY}, * {@link #PLANE_NZ} and {@link #PLANE_PZ} - * @param planeEquation - * will hold the computed plane equation. - * The plane equation will be normalized, meaning that (a, b, c) will be a unit vector - * @return planeEquation - */ - Vector4d frustumPlane(int plane, Vector4d planeEquation); - - /** - * Calculate a frustum plane of this matrix, which - * can be a projection matrix or a combined modelview-projection matrix, and store the result - * in the given plane. - *

- * Generally, this method computes the frustum plane in the local frame of - * any coordinate system that existed before this - * transformation was applied to it in order to yield homogeneous clipping space. - *

- * The plane normal, which is (a, b, c), is directed "inwards" of the frustum. - * Any plane/point test using a*x + b*y + c*z + d therefore will yield a result greater than zero - * if the point is within the frustum (i.e. at the positive side of the frustum plane). - *

- * For performing frustum culling, the class {@link FrustumIntersection} should be used instead of - * manually obtaining the frustum planes and testing them against points, spheres or axis-aligned boxes. - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @param plane - * one of the six possible planes, given as numeric constants - * {@link #PLANE_NX}, {@link #PLANE_PX}, - * {@link #PLANE_NY}, {@link #PLANE_PY}, - * {@link #PLANE_NZ} and {@link #PLANE_PZ} - * @param planeEquation + * @param dest * will hold the computed plane equation. * The plane equation will be normalized, meaning that (a, b, c) will be a unit vector - * @return planeEquation + * @return dest */ - Planed frustumPlane(int plane, Planed planeEquation); + Vector4d frustumPlane(int plane, Vector4d dest); /** * Compute the corner coordinates of the frustum defined by this matrix, which diff --git a/src/org/joml/Matrix4f.java b/src/org/joml/Matrix4f.java index b16c9e5ad..0657d7974 100644 --- a/src/org/joml/Matrix4f.java +++ b/src/org/joml/Matrix4f.java @@ -12373,56 +12373,30 @@ public Matrix3f normalize3x3(Matrix3f dest) { ._m20(m20 * invZlen)._m21(m21 * invZlen)._m22(m22 * invZlen); } - public Vector4f frustumPlane(int plane, Vector4f planeEquation) { + public Vector4f frustumPlane(int plane, Vector4f dest) { switch (plane) { case PLANE_NX: - planeEquation.set(m03 + m00, m13 + m10, m23 + m20, m33 + m30).normalize3(planeEquation); + dest.set(m03 + m00, m13 + m10, m23 + m20, m33 + m30).normalize3(); break; case PLANE_PX: - planeEquation.set(m03 - m00, m13 - m10, m23 - m20, m33 - m30).normalize3(planeEquation); + dest.set(m03 - m00, m13 - m10, m23 - m20, m33 - m30).normalize3(); break; case PLANE_NY: - planeEquation.set(m03 + m01, m13 + m11, m23 + m21, m33 + m31).normalize3(planeEquation); + dest.set(m03 + m01, m13 + m11, m23 + m21, m33 + m31).normalize3(); break; case PLANE_PY: - planeEquation.set(m03 - m01, m13 - m11, m23 - m21, m33 - m31).normalize3(planeEquation); + dest.set(m03 - m01, m13 - m11, m23 - m21, m33 - m31).normalize3(); break; case PLANE_NZ: - planeEquation.set(m03 + m02, m13 + m12, m23 + m22, m33 + m32).normalize3(planeEquation); + dest.set(m03 + m02, m13 + m12, m23 + m22, m33 + m32).normalize3(); break; case PLANE_PZ: - planeEquation.set(m03 - m02, m13 - m12, m23 - m22, m33 - m32).normalize3(planeEquation); + dest.set(m03 - m02, m13 - m12, m23 - m22, m33 - m32).normalize3(); break; default: - throw new IllegalArgumentException("plane"); //$NON-NLS-1$ + throw new IllegalArgumentException("dest"); //$NON-NLS-1$ } - return planeEquation; - } - - public Planef frustumPlane(int which, Planef plane) { - switch (which) { - case PLANE_NX: - plane.set(m03 + m00, m13 + m10, m23 + m20, m33 + m30).normalize(plane); - break; - case PLANE_PX: - plane.set(m03 - m00, m13 - m10, m23 - m20, m33 - m30).normalize(plane); - break; - case PLANE_NY: - plane.set(m03 + m01, m13 + m11, m23 + m21, m33 + m31).normalize(plane); - break; - case PLANE_PY: - plane.set(m03 - m01, m13 - m11, m23 - m21, m33 - m31).normalize(plane); - break; - case PLANE_NZ: - plane.set(m03 + m02, m13 + m12, m23 + m22, m33 + m32).normalize(plane); - break; - case PLANE_PZ: - plane.set(m03 - m02, m13 - m12, m23 - m22, m33 - m32).normalize(plane); - break; - default: - throw new IllegalArgumentException("which"); //$NON-NLS-1$ - } - return plane; + return dest; } public Vector3f frustumCorner(int corner, Vector3f point) { diff --git a/src/org/joml/Matrix4fc.java b/src/org/joml/Matrix4fc.java index e13dc6da1..47dc641e6 100644 --- a/src/org/joml/Matrix4fc.java +++ b/src/org/joml/Matrix4fc.java @@ -41,38 +41,32 @@ public interface Matrix4fc { /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} and - * {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation x=-1 when using the identity matrix. */ int PLANE_NX = 0; /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} and - * {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation x=1 when using the identity matrix. */ int PLANE_PX = 1; /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} and - * {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation y=-1 when using the identity matrix. */ int PLANE_NY = 2; /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} and - * {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation y=1 when using the identity matrix. */ int PLANE_PY = 3; /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} and - * {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation z=-1 when using the identity matrix. */ int PLANE_NZ = 4; /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} and - * {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation z=1 when using the identity matrix. */ int PLANE_PZ = 5; @@ -4448,37 +4442,6 @@ Matrix4f mul3x3( */ Vector4f frustumPlane(int plane, Vector4f planeEquation); - /** - * Calculate a frustum plane of this matrix, which - * can be a projection matrix or a combined modelview-projection matrix, and store the result - * in the given plane. - *

- * Generally, this method computes the frustum plane in the local frame of - * any coordinate system that existed before this - * transformation was applied to it in order to yield homogeneous clipping space. - *

- * The plane normal, which is (a, b, c), is directed "inwards" of the frustum. - * Any plane/point test using a*x + b*y + c*z + d therefore will yield a result greater than zero - * if the point is within the frustum (i.e. at the positive side of the frustum plane). - *

- * For performing frustum culling, the class {@link FrustumIntersection} should be used instead of - * manually obtaining the frustum planes and testing them against points, spheres or axis-aligned boxes. - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @param which - * one of the six possible planes, given as numeric constants - * {@link #PLANE_NX}, {@link #PLANE_PX}, - * {@link #PLANE_NY}, {@link #PLANE_PY}, - * {@link #PLANE_NZ} and {@link #PLANE_PZ} - * @param plane - * will hold the computed plane equation. - * The plane equation will be normalized, meaning that (a, b, c) will be a unit vector - * @return planeEquation - */ - Planef frustumPlane(int which, Planef plane); - /** * Compute the corner coordinates of the frustum defined by this matrix, which * can be a projection matrix or a combined modelview-projection matrix, and store the result diff --git a/src/org/joml/Matrix4x3d.java b/src/org/joml/Matrix4x3d.java index f9d3e0b4d..ae53fa040 100644 --- a/src/org/joml/Matrix4x3d.java +++ b/src/org/joml/Matrix4x3d.java @@ -8429,30 +8429,30 @@ public Matrix4x3d lookAtLH(double eyeX, double eyeY, double eyeZ, return lookAtLH(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, this); } - public Planed frustumPlane(int which, Planed plane) { + public Vector4d frustumPlane(int which, Vector4d dest) { switch (which) { case PLANE_NX: - plane.set(m00, m10, m20, 1.0 + m30).normalize(plane); + dest.set(m00, m10, m20, 1.0 + m30).normalize(); break; case PLANE_PX: - plane.set(-m00, -m10, -m20, 1.0 - m30).normalize(plane); + dest.set(-m00, -m10, -m20, 1.0 - m30).normalize(); break; case PLANE_NY: - plane.set(m01, m11, m21, 1.0 + m31).normalize(plane); + dest.set(m01, m11, m21, 1.0 + m31).normalize(); break; case PLANE_PY: - plane.set(-m01, -m11, -m21, 1.0 - m31).normalize(plane); + dest.set(-m01, -m11, -m21, 1.0 - m31).normalize(); break; case PLANE_NZ: - plane.set(m02, m12, m22, 1.0 + m32).normalize(plane); + dest.set(m02, m12, m22, 1.0 + m32).normalize(); break; case PLANE_PZ: - plane.set(-m02, -m12, -m22, 1.0 - m32).normalize(plane); + dest.set(-m02, -m12, -m22, 1.0 - m32).normalize(); break; default: throw new IllegalArgumentException("which"); //$NON-NLS-1$ } - return plane; + return dest; } public Vector3d positiveZ(Vector3d dir) { diff --git a/src/org/joml/Matrix4x3dc.java b/src/org/joml/Matrix4x3dc.java index 928c706ac..aef9593f1 100644 --- a/src/org/joml/Matrix4x3dc.java +++ b/src/org/joml/Matrix4x3dc.java @@ -38,32 +38,32 @@ public interface Matrix4x3dc { /** - * Argument to the first parameter of {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation x=-1 when using the identity matrix. */ int PLANE_NX = 0; /** - * Argument to the first parameter of {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation x=1 when using the identity matrix. */ int PLANE_PX = 1; /** - * Argument to the first parameter of {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation y=-1 when using the identity matrix. */ int PLANE_NY = 2; /** - * Argument to the first parameter of {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation y=1 when using the identity matrix. */ int PLANE_PY = 3; /** - * Argument to the first parameter of {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation z=-1 when using the identity matrix. */ int PLANE_NZ = 4; /** - * Argument to the first parameter of {@link #frustumPlane(int, Planed)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} * identifying the plane with equation z=1 when using the identity matrix. */ int PLANE_PZ = 5; @@ -2493,7 +2493,7 @@ public interface Matrix4x3dc { /** * Calculate a frustum plane of this matrix, which * can be a projection matrix or a combined modelview-projection matrix, and store the result - * in the given plane. + * in the given dest. *

* Generally, this method computes the frustum plane in the local frame of * any coordinate system that existed before this @@ -2511,12 +2511,12 @@ public interface Matrix4x3dc { * {@link #PLANE_NX}, {@link #PLANE_PX}, * {@link #PLANE_NY}, {@link #PLANE_PY}, * {@link #PLANE_NZ} and {@link #PLANE_PZ} - * @param plane + * @param dest * will hold the computed plane equation. * The plane equation will be normalized, meaning that (a, b, c) will be a unit vector - * @return planeEquation + * @return dest */ - Planed frustumPlane(int which, Planed plane); + Vector4d frustumPlane(int which, Vector4d dest); /** * Obtain the direction of +Z before the transformation represented by this matrix is applied. diff --git a/src/org/joml/Matrix4x3f.java b/src/org/joml/Matrix4x3f.java index 70b0749ff..ec78b50d7 100644 --- a/src/org/joml/Matrix4x3f.java +++ b/src/org/joml/Matrix4x3f.java @@ -7602,30 +7602,30 @@ public Matrix3f normalize3x3(Matrix3f dest) { return dest; } - public Planef frustumPlane(int which, Planef plane) { + public Vector4f frustumPlane(int which, Vector4f dest) { switch (which) { case PLANE_NX: - plane.set(m00, m10, m20, 1.0f + m30).normalize(plane); + dest.set(m00, m10, m20, 1.0f + m30).normalize(); break; case PLANE_PX: - plane.set(-m00, -m10, -m20, 1.0f - m30).normalize(plane); + dest.set(-m00, -m10, -m20, 1.0f - m30).normalize(); break; case PLANE_NY: - plane.set(m01, m11, m21, 1.0f + m31).normalize(plane); + dest.set(m01, m11, m21, 1.0f + m31).normalize(); break; case PLANE_PY: - plane.set(-m01, -m11, -m21, 1.0f - m31).normalize(plane); + dest.set(-m01, -m11, -m21, 1.0f - m31).normalize(); break; case PLANE_NZ: - plane.set(m02, m12, m22, 1.0f + m32).normalize(plane); + dest.set(m02, m12, m22, 1.0f + m32).normalize(); break; case PLANE_PZ: - plane.set(-m02, -m12, -m22, 1.0f - m32).normalize(plane); + dest.set(-m02, -m12, -m22, 1.0f - m32).normalize(); break; default: throw new IllegalArgumentException("which"); //$NON-NLS-1$ } - return plane; + return dest; } public Vector3f positiveZ(Vector3f dir) { diff --git a/src/org/joml/Matrix4x3fc.java b/src/org/joml/Matrix4x3fc.java index 55d5719fa..4289cd180 100644 --- a/src/org/joml/Matrix4x3fc.java +++ b/src/org/joml/Matrix4x3fc.java @@ -41,32 +41,32 @@ public interface Matrix4x3fc { /** - * Argument to the first parameter of {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation x=-1 when using the identity matrix. */ int PLANE_NX = 0; /** - * Argument to the first parameter of {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation x=1 when using the identity matrix. */ int PLANE_PX = 1; /** - * Argument to the first parameter of {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation y=-1 when using the identity matrix. */ int PLANE_NY = 2; /** - * Argument to the first parameter of {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation y=1 when using the identity matrix. */ int PLANE_PY = 3; /** - * Argument to the first parameter of {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation z=-1 when using the identity matrix. */ int PLANE_NZ = 4; /** - * Argument to the first parameter of {@link #frustumPlane(int, Planef)} + * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} * identifying the plane with equation z=1 when using the identity matrix. */ int PLANE_PZ = 5; @@ -2201,7 +2201,7 @@ public interface Matrix4x3fc { /** * Calculate a frustum plane of this matrix, which * can be a projection matrix or a combined modelview-projection matrix, and store the result - * in the given plane. + * in the given dest. *

* Generally, this method computes the frustum plane in the local frame of * any coordinate system that existed before this @@ -2219,12 +2219,12 @@ public interface Matrix4x3fc { * {@link #PLANE_NX}, {@link #PLANE_PX}, * {@link #PLANE_NY}, {@link #PLANE_PY}, * {@link #PLANE_NZ} and {@link #PLANE_PZ} - * @param plane + * @param dest * will hold the computed plane equation. * The plane equation will be normalized, meaning that (a, b, c) will be a unit vector - * @return planeEquation + * @return dest */ - Planef frustumPlane(int which, Planef plane); + Vector4f frustumPlane(int which, Vector4f dest); /** * Obtain the direction of +Z before the transformation represented by this matrix is applied. diff --git a/src/org/joml/Options.java b/src/org/joml/Options.java index 448972581..ae94cc57a 100644 --- a/src/org/joml/Options.java +++ b/src/org/joml/Options.java @@ -35,7 +35,7 @@ * * @author Kai Burjack */ -final class Options { +public final class Options { /** * Whether certain debugging checks should be made, such as that only direct NIO Buffers are used when Unsafe is active, diff --git a/src/org/joml/Planed.java b/src/org/joml/Planed.java deleted file mode 100644 index e6446624d..000000000 --- a/src/org/joml/Planed.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a 3D plane using double-precision floating-point numbers. - * - * @author Kai Burjack - */ -public class Planed implements Externalizable { - - /** - * The factor a in the plane equation a*x + b*y + c*z + d = 0. - */ - public double a; - /** - * The factor b in the plane equation a*x + b*y + c*z + d = 0. - */ - public double b; - /** - * The factor c in the plane equation a*x + b*y + c*z + d = 0. - */ - public double c; - /** - * The constant d in the plane equation a*x + b*y + c*z + d = 0. - */ - public double d; - - /** - * Create a new undefined {@link Planed}. - */ - public Planed() { - } - - /** - * Create a new {@link Planed} as a copy of the given source. - * - * @param source - * the {@link Planed} to copy from - */ - public Planed(Planed source) { - this.a = source.a; - this.b = source.b; - this.c = source.c; - this.d = source.d; - } - - /** - * Create a new {@link Planed} from the given point lying on the plane and the given normal. - * - * @param point - * any point lying on the plane - * @param normal - * the normal of the plane - */ - public Planed(Vector3dc point, Vector3dc normal) { - this.a = normal.x(); - this.b = normal.y(); - this.c = normal.z(); - this.d = -a * point.x() - b * point.y() - c * point.z(); - } - - /** - * Create a new {@link Planed} with the plane equation a*x + b*y + c*z + d = 0. - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - */ - public Planed(double a, double b, double c, double d) { - this.a = a; - this.b = b; - this.c = c; - this.d = d; - } - - /** - * Create a new {@link Planef} from the given three points lying on the plane. - *

- * The resulting plane is not necessarily {@link #normalize() normalized}. - * - * @param pointA - * the first point - * @param pointB - * the second point - * @param pointC - * the third point - */ - public Planed(Vector3dc pointA, Vector3dc pointB, Vector3dc pointC) { - double abX = pointB.x() - pointA.x(), abY = pointB.y() - pointA.y(), abZ = pointB.z() - pointA.z(); - double acX = pointC.x() - pointA.x(), acY = pointC.y() - pointA.y(), acZ = pointC.z() - pointA.z(); - this.a = abY * acZ - abZ * acY; - this.b = abZ * acX - abX * acZ; - this.c = abX * acY - abY * acX; - this.d = -a * pointA.x() - b * pointA.y() - c * pointA.z(); - } - - /** - * Create a new {@link Planef} from the given three points lying on the plane. - *

- * The resulting plane is not necessarily {@link #normalize() normalized}. - * - * @param pointA - * the first point - * @param pointB - * the second point - * @param pointC - * the third point - */ - public Planed(Vector3fc pointA, Vector3fc pointB, Vector3fc pointC) { - double abX = pointB.x() - pointA.x(), abY = pointB.y() - pointA.y(), abZ = pointB.z() - pointA.z(); - double acX = pointC.x() - pointA.x(), acY = pointC.y() - pointA.y(), acZ = pointC.z() - pointA.z(); - this.a = abY * acZ - abZ * acY; - this.b = abZ * acX - abX * acZ; - this.c = abX * acY - abY * acX; - this.d = -a * pointA.x() - b * pointA.y() - c * pointA.z(); - } - - /** - * Set the components of this plane. - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return this - */ - public Planed set(double a, double b, double c, double d) { - this.a = a; - this.b = b; - this.c = c; - this.d = d; - return this; - } - - /** - * Normalize this plane. - * - * @return this - */ - public Planed normalize() { - return normalize(this); - } - - /** - * Normalize this plane and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - public Planed normalize(Planed dest) { - double invLength = Math.invsqrt(a * a + b * b + c * c); - dest.a = a * invLength; - dest.b = b * invLength; - dest.c = c * invLength; - dest.d = d * invLength; - return dest; - } - - /** - * Compute the signed distance between this plane and the given point. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @return the signed distance between this plane and the point - */ - public double distance(double x, double y, double z) { - return Intersectiond.distancePointPlane(x, y, z, a, b, c, d); - } - - /** - * Compute the factors a, b, c and d in the plane equation - * a*x + b*y + c*z + d = 0 from the given three points on the plane, and write the values - * to the x, y, z and w components, respectively, of the given - * dest vector. - * - * @param v0 - * the first point on the plane - * @param v1 - * the second point on the plane - * @param v2 - * the third point on the plane - * @param dest - * will hold the result - * @return dest - */ - public static Vector4d equationFromPoints( - Vector3d v0, Vector3d v1, Vector3d v2, - Vector4d dest) { - return equationFromPoints(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, dest); - } - - /** - * Compute the factors a, b, c and d in the plane equation - * a*x + b*y + c*z + d = 0 from the three points (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and - * (v2X, v2Y, v2Z) on the plane, and write the values to the x, y, z - * and w components, respectively, of the given dest vector. - * - * @param v0X - * the x coordinate of the first point on the plane - * @param v0Y - * the y coordinate of the first point on the plane - * @param v0Z - * the z coordinate of the first point on the plane - * @param v1X - * the x coordinate of the second point on the plane - * @param v1Y - * the y coordinate of the second point on the plane - * @param v1Z - * the z coordinate of the second point on the plane - * @param v2X - * the x coordinate of the third point on the plane - * @param v2Y - * the y coordinate of the third point on the plane - * @param v2Z - * the z coordinate of the third point on the plane - * @param dest - * will hold the result - * @return dest - */ - public static Vector4d equationFromPoints( - double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z, - Vector4d dest) { - double v1Y0Y = v1Y - v0Y; - double v2Z0Z = v2Z - v0Z; - double v2Y0Y = v2Y - v0Y; - double v1Z0Z = v1Z - v0Z; - double v2X0X = v2X - v0X; - double v1X0X = v1X - v0X; - double a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z; - double b = v1Z0Z * v2X0X - v2Z0Z * v1X0X; - double c = v1X0X * v2Y0Y - v2X0X * v1Y0Y; - double d = -(a * v0X + b * v0Y + c * v0Z); - dest.x = a; - dest.y = b; - dest.z = c; - dest.w = d; - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(a); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(b); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(c); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(d); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Planed other = (Planed) obj; - if (Double.doubleToLongBits(a) != Double.doubleToLongBits(other.a)) - return false; - if (Double.doubleToLongBits(b) != Double.doubleToLongBits(other.b)) - return false; - if (Double.doubleToLongBits(c) != Double.doubleToLongBits(other.c)) - return false; - if (Double.doubleToLongBits(d) != Double.doubleToLongBits(other.d)) - return false; - return true; - } - - /** - * Return a string representation of this plane. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this plane by formatting the components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "[" + Runtime.format(a, formatter) + " " + Runtime.format(b, formatter) + " " + Runtime.format(c, formatter) + " " + Runtime.format(d, formatter) + "]"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeDouble(a); - out.writeDouble(b); - out.writeDouble(c); - out.writeDouble(d); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - a = in.readDouble(); - b = in.readDouble(); - c = in.readDouble(); - d = in.readDouble(); - } - -} diff --git a/src/org/joml/Planef.java b/src/org/joml/Planef.java deleted file mode 100644 index 098094599..000000000 --- a/src/org/joml/Planef.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a 3D plane using single-precision floating-point numbers. - * - * @author Kai Burjack - */ -public class Planef implements Externalizable { - - /** - * The factor a in the plane equation a*x + b*y + c*z + d = 0. - */ - public float a; - /** - * The factor b in the plane equation a*x + b*y + c*z + d = 0. - */ - public float b; - /** - * The factor c in the plane equation a*x + b*y + c*z + d = 0. - */ - public float c; - /** - * The constant d in the plane equation a*x + b*y + c*z + d = 0. - */ - public float d; - - /** - * Create a new undefined {@link Planef}. - */ - public Planef() { - } - - /** - * Create a new {@link Planef} as a copy of the given source. - * - * @param source - * the {@link Planef} to copy from - */ - public Planef(Planef source) { - this.a = source.a; - this.b = source.b; - this.c = source.c; - this.d = source.d; - } - - /** - * Create a new {@link Planef} from the given point lying on the plane and the given normal. - * - * @param point - * any point lying on the plane - * @param normal - * the normal of the plane - */ - public Planef(Vector3fc point, Vector3fc normal) { - this.a = normal.x(); - this.b = normal.y(); - this.c = normal.z(); - this.d = -a * point.x() - b * point.y() - c * point.z(); - } - - /** - * Create a new {@link Planef} from the given three points lying on the plane. - *

- * The resulting plane is not necessarily {@link #normalize() normalized}. - * - * @param pointA - * the first point - * @param pointB - * the second point - * @param pointC - * the third point - */ - public Planef(Vector3fc pointA, Vector3fc pointB, Vector3fc pointC) { - float abX = pointB.x() - pointA.x(), abY = pointB.y() - pointA.y(), abZ = pointB.z() - pointA.z(); - float acX = pointC.x() - pointA.x(), acY = pointC.y() - pointA.y(), acZ = pointC.z() - pointA.z(); - this.a = abY * acZ - abZ * acY; - this.b = abZ * acX - abX * acZ; - this.c = abX * acY - abY * acX; - this.d = -a * pointA.x() - b * pointA.y() - c * pointA.z(); - } - - /** - * Create a new {@link Planef} with the plane equation a*x + b*y + c*z + d = 0. - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - */ - public Planef(float a, float b, float c, float d) { - this.a = a; - this.b = b; - this.c = c; - this.d = d; - } - - /** - * Set the components of this plane. - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return this - */ - public Planef set(float a, float b, float c, float d) { - this.a = a; - this.b = b; - this.c = c; - this.d = d; - return this; - } - - /** - * Normalize this plane. - * - * @return this - */ - public Planef normalize() { - return normalize(this); - } - - /** - * Normalize this plane and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - public Planef normalize(Planef dest) { - float invLength = Math.invsqrt(a * a + b * b + c * c); - dest.a = a * invLength; - dest.b = b * invLength; - dest.c = c * invLength; - dest.d = d * invLength; - return dest; - } - - /** - * Compute the signed distance between this plane and the given point. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param z - * the z coordinate of the point - * @return the signed distance between this plane and the point - */ - public float distance(float x, float y, float z) { - return Intersectionf.distancePointPlane(x, y, z, a, b, c, d); - } - - /** - * Compute the factors a, b, c and d in the plane equation - * a*x + b*y + c*z + d = 0 from the given three points on the plane, and write the values - * to the x, y, z and w components, respectively, of the given - * dest vector. - * - * @param v0 - * the first point on the plane - * @param v1 - * the second point on the plane - * @param v2 - * the third point on the plane - * @param dest - * will hold the result - * @return dest - */ - public static Vector4f equationFromPoints( - Vector3f v0, Vector3f v1, Vector3f v2, - Vector4f dest) { - return equationFromPoints(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, dest); - } - - /** - * Compute the factors a, b, c and d in the plane equation - * a*x + b*y + c*z + d = 0 from the three points (v0X, v0Y, v0Z), (v1X, v1Y, v1Z) and - * (v2X, v2Y, v2Z) on the plane, and write the values to the x, y, z - * and w components, respectively, of the given dest vector. - * - * @param v0X - * the x coordinate of the first point on the plane - * @param v0Y - * the y coordinate of the first point on the plane - * @param v0Z - * the z coordinate of the first point on the plane - * @param v1X - * the x coordinate of the second point on the plane - * @param v1Y - * the y coordinate of the second point on the plane - * @param v1Z - * the z coordinate of the second point on the plane - * @param v2X - * the x coordinate of the third point on the plane - * @param v2Y - * the y coordinate of the third point on the plane - * @param v2Z - * the z coordinate of the third point on the plane - * @param dest - * will hold the result - * @return dest - */ - public static Vector4f equationFromPoints( - float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, - Vector4f dest) { - float v1Y0Y = v1Y - v0Y; - float v2Z0Z = v2Z - v0Z; - float v2Y0Y = v2Y - v0Y; - float v1Z0Z = v1Z - v0Z; - float v2X0X = v2X - v0X; - float v1X0X = v1X - v0X; - float a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z; - float b = v1Z0Z * v2X0X - v2Z0Z * v1X0X; - float c = v1X0X * v2Y0Y - v2X0X * v1Y0Y; - float d = -(a * v0X + b * v0Y + c * v0Z); - dest.x = a; - dest.y = b; - dest.z = c; - dest.w = d; - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(a); - result = prime * result + Float.floatToIntBits(b); - result = prime * result + Float.floatToIntBits(c); - result = prime * result + Float.floatToIntBits(d); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Planef other = (Planef) obj; - if (Float.floatToIntBits(a) != Float.floatToIntBits(other.a)) - return false; - if (Float.floatToIntBits(b) != Float.floatToIntBits(other.b)) - return false; - if (Float.floatToIntBits(c) != Float.floatToIntBits(other.c)) - return false; - if (Float.floatToIntBits(d) != Float.floatToIntBits(other.d)) - return false; - return true; - } - - /** - * Return a string representation of this plane. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this plane by formatting the components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "[" + Runtime.format(a, formatter) + " " + Runtime.format(b, formatter) + " " + Runtime.format(c, formatter) + " " + Runtime.format(d, formatter) + "]"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(a); - out.writeFloat(b); - out.writeFloat(c); - out.writeFloat(d); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - a = in.readFloat(); - b = in.readFloat(); - c = in.readFloat(); - d = in.readFloat(); - } - -} diff --git a/src/org/joml/Rayd.java b/src/org/joml/Rayd.java deleted file mode 100644 index dc19bf968..000000000 --- a/src/org/joml/Rayd.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a ray with a given origin and direction using double-precision floating-point numbers. - * - * @author Kai Burjack - */ -public class Rayd implements Externalizable { - - /** - * The x coordinate of the ray's origin. - */ - public double oX; - /** - * The y coordinate of the ray's origin. - */ - public double oY; - /** - * The z coordinate of the ray's origin. - */ - public double oZ; - /** - * The x coordinate of the ray's direction. - */ - public double dX; - /** - * The y coordinate of the ray's direction. - */ - public double dY; - /** - * The z coordinate of the ray's direction. - */ - public double dZ; - - /** - * Create a new {@link Rayd} with origin (0, 0, 0) and no direction. - */ - public Rayd() { - } - - /** - * Create a new {@link Rayd} as a copy of the given source. - * - * @param source - * the {@link Rayd} to copy from - */ - public Rayd(Rayd source) { - this.oX = source.oX; - this.oY = source.oY; - this.oZ = source.oZ; - this.dX = source.dX; - this.dY = source.dY; - this.dZ = source.dZ; - } - - /** - * Create a new {@link Rayd} with the given origin and direction. - * - * @param origin - * the origin of the ray - * @param direction - * the direction of the ray - */ - public Rayd(Vector3dc origin, Vector3dc direction) { - this.oX = origin.x(); - this.oY = origin.y(); - this.oZ = origin.z(); - this.dX = direction.x(); - this.dY = direction.y(); - this.dZ = direction.z(); - } - - /** - * Create a new {@link Rayd} with the given origin and direction. - * - * @param oX - * the x coordinate of the ray's origin - * @param oY - * the y coordinate of the ray's origin - * @param oZ - * the z coordinate of the ray's origin - * @param dX - * the x coordinate of the ray's direction - * @param dY - * the y coordinate of the ray's direction - * @param dZ - * the z coordinate of the ray's direction - */ - public Rayd(double oX, double oY, double oZ, double dX, double dY, double dZ) { - this.oX = oX; - this.oY = oY; - this.oZ = oZ; - this.dX = dX; - this.dY = dY; - this.dZ = dZ; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(dX); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(dY); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(dZ); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(oX); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(oY); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(oZ); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Rayd other = (Rayd) obj; - if (Double.doubleToLongBits(dX) != Double.doubleToLongBits(other.dX)) - return false; - if (Double.doubleToLongBits(dY) != Double.doubleToLongBits(other.dY)) - return false; - if (Double.doubleToLongBits(dZ) != Double.doubleToLongBits(other.dZ)) - return false; - if (Double.doubleToLongBits(oX) != Double.doubleToLongBits(other.oX)) - return false; - if (Double.doubleToLongBits(oY) != Double.doubleToLongBits(other.oY)) - return false; - if (Double.doubleToLongBits(oZ) != Double.doubleToLongBits(other.oZ)) - return false; - return true; - } - - /** - * Return a string representation of this ray. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this ray by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(oX, formatter) + " " + Runtime.format(oY, formatter) + " " + Runtime.format(oZ, formatter) + ") -> " - + "(" + Runtime.format(dX, formatter) + " " + Runtime.format(dY, formatter) + " " + Runtime.format(dZ, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeDouble(oX); - out.writeDouble(oY); - out.writeDouble(oZ); - out.writeDouble(dX); - out.writeDouble(dY); - out.writeDouble(dZ); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - oX = in.readDouble(); - oY = in.readDouble(); - oZ = in.readDouble(); - dX = in.readDouble(); - dY = in.readDouble(); - dZ = in.readDouble(); - } - -} diff --git a/src/org/joml/Rayf.java b/src/org/joml/Rayf.java deleted file mode 100644 index b7e73f755..000000000 --- a/src/org/joml/Rayf.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a ray with a given origin and direction using single-precision floating-point numbers. - * - * @author Kai Burjack - */ -public class Rayf implements Externalizable { - - /** - * The x coordinate of the ray's origin. - */ - public float oX; - /** - * The y coordinate of the ray's origin. - */ - public float oY; - /** - * The z coordinate of the ray's origin. - */ - public float oZ; - /** - * The x coordinate of the ray's direction. - */ - public float dX; - /** - * The y coordinate of the ray's direction. - */ - public float dY; - /** - * The z coordinate of the ray's direction. - */ - public float dZ; - - /** - * Create a new {@link Rayf} with origin (0, 0, 0) and no direction. - */ - public Rayf() { - } - - /** - * Create a new {@link Rayf} as a copy of the given source. - * - * @param source - * the {@link Rayf} to copy from - */ - public Rayf(Rayf source) { - this.oX = source.oX; - this.oY = source.oY; - this.oZ = source.oZ; - this.dX = source.dX; - this.dY = source.dY; - this.dZ = source.dZ; - } - - /** - * Create a new {@link Rayf} with the given origin and direction. - * - * @param origin - * the origin of the ray - * @param direction - * the direction of the ray - */ - public Rayf(Vector3fc origin, Vector3fc direction) { - this.oX = origin.x(); - this.oY = origin.y(); - this.oZ = origin.z(); - this.dX = direction.x(); - this.dY = direction.y(); - this.dZ = direction.z(); - } - - /** - * Create a new {@link Rayf} with the given origin and direction. - * - * @param oX - * the x coordinate of the ray's origin - * @param oY - * the y coordinate of the ray's origin - * @param oZ - * the z coordinate of the ray's origin - * @param dX - * the x coordinate of the ray's direction - * @param dY - * the y coordinate of the ray's direction - * @param dZ - * the z coordinate of the ray's direction - */ - public Rayf(float oX, float oY, float oZ, float dX, float dY, float dZ) { - this.oX = oX; - this.oY = oY; - this.oZ = oZ; - this.dX = dX; - this.dY = dY; - this.dZ = dZ; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(dX); - result = prime * result + Float.floatToIntBits(dY); - result = prime * result + Float.floatToIntBits(dZ); - result = prime * result + Float.floatToIntBits(oX); - result = prime * result + Float.floatToIntBits(oY); - result = prime * result + Float.floatToIntBits(oZ); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Rayf other = (Rayf) obj; - if (Float.floatToIntBits(dX) != Float.floatToIntBits(other.dX)) - return false; - if (Float.floatToIntBits(dY) != Float.floatToIntBits(other.dY)) - return false; - if (Float.floatToIntBits(dZ) != Float.floatToIntBits(other.dZ)) - return false; - if (Float.floatToIntBits(oX) != Float.floatToIntBits(other.oX)) - return false; - if (Float.floatToIntBits(oY) != Float.floatToIntBits(other.oY)) - return false; - if (Float.floatToIntBits(oZ) != Float.floatToIntBits(other.oZ)) - return false; - return true; - } - - /** - * Return a string representation of this ray. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this ray by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(oX, formatter) + " " + Runtime.format(oY, formatter) + " " + Runtime.format(oZ, formatter) + ") -> " - + "(" + Runtime.format(dX, formatter) + " " + Runtime.format(dY, formatter) + " " + Runtime.format(dZ, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(oX); - out.writeFloat(oY); - out.writeFloat(oZ); - out.writeFloat(dX); - out.writeFloat(dY); - out.writeFloat(dZ); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - oX = in.readFloat(); - oY = in.readFloat(); - oZ = in.readFloat(); - dX = in.readFloat(); - dY = in.readFloat(); - dZ = in.readFloat(); - } - -} diff --git a/src/org/joml/Rectangled.java b/src/org/joml/Rectangled.java deleted file mode 100644 index a065ff704..000000000 --- a/src/org/joml/Rectangled.java +++ /dev/null @@ -1,851 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a 2D axis-aligned rectangle. - * - * @author Kai Burjack - */ -public class Rectangled implements Externalizable { - - /** - * The x coordinate of the minimum corner. - */ - public double minX; - /** - * The y coordinate of the minimum corner. - */ - public double minY; - /** - * The x coordinate of the maximum corner. - */ - public double maxX; - /** - * The y coordinate of the maximum corner. - */ - public double maxY; - - /** - * Create a new {@link Rectangled} with a minimum and maximum corner of (0, 0). - */ - public Rectangled() { - } - - /** - * Create a new {@link Rectangled} as a copy of the given source. - * - * @param source - * the {@link Rectangled} to copy from - */ - public Rectangled(Rectangled source) { - this.minX = source.minX; - this.minY = source.minY; - this.maxX = source.maxX; - this.maxY = source.maxY; - } - - /** - * Create a new {@link Rectangled} with the given min and max corner coordinates. - * - * @param min - * the minimum coordinates - * @param max - * the maximum coordinates - */ - public Rectangled(Vector2dc min, Vector2dc max) { - this.minX = min.x(); - this.minY = min.y(); - this.maxX = max.x(); - this.maxY = max.y(); - } - - /** - * Create a new {@link Rectangled} with the given minimum and maximum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - */ - public Rectangled(double minX, double minY, double maxX, double maxY) { - this.minX = minX; - this.minY = minY; - this.maxX = maxX; - this.maxY = maxY; - } - - /** - * Set this {@link Rectangled} to be a clone of source. - * - * @param source - * the {@link Rectangled} to copy from - * @return this - */ - public Rectangled set(Rectangled source){ - this.minX = source.minX; - this.minY = source.minY; - this.maxX = source.maxX; - this.maxY = source.maxY; - return this; - } - - /** - * Set the minimum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @return this - */ - public Rectangled setMin(double minX, double minY) { - this.minX = minX; - this.minY = minY; - return this; - } - - /** - * Set the minimum corner coordinates. - * - * @param min - * the minimum coordinates - * @return this - */ - public Rectangled setMin(Vector2dc min) { - this.minX = min.x(); - this.minY = min.y(); - return this; - } - - - /** - * Set the maximum corner coordinates. - * - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - * @return this - */ - public Rectangled setMax(double maxX, double maxY) { - this.maxX = maxX; - this.maxY = maxY; - return this; - } - - /** - * Set the maximum corner coordinates. - * - * @param max - * the maximum coordinates - * @return this - */ - public Rectangled setMax(Vector2dc max) { - this.maxX = max.x(); - this.maxY = max.y(); - return this; - } - - /** - * Return the length of the rectangle in the X dimension. - * - * @return length in the X dimension - */ - public double lengthX() { - return maxX - minX; - } - - /** - * Return the length of the rectangle in the Y dimension. - * - * @return length in the Y dimension - */ - public double lengthY() { - return maxY - minY; - } - - /** - * Return the area of the rectangle - * - * @return area - */ - public double area() { - return lengthX() * lengthY(); - } - - private Rectangled validate() { - if (!isValid()) { - minX = Double.NaN; - minY = Double.NaN; - maxX = Double.NaN; - maxY = Double.NaN; - } - return this; - } - - /** - * Check whether this rectangle represents a valid rectangle. - * - * @return true iff this rectangle is valid; false otherwise - */ - public boolean isValid() { - return minX < maxX && minY < maxY; - } - - /** - * Compute the rectangle of intersection between this and the given rectangle. - *

- * If the two rectangles do not intersect, then {@link Double#NaN} is stored in each component - * of dest. - * - * @param other - * the other rectangle - * @return this - */ - public Rectangled intersection(Rectangled other) { - return intersection(other, this); - } - - /** - * Compute the rectangle of intersection between this and the given rectangle and - * store the result in dest. - *

- * If the two rectangles do not intersect, then {@link Double#NaN} is stored in each component - * of dest. - * - * @param other - * the other rectangle - * @param dest - * will hold the result - * @return dest - */ - public Rectangled intersection(Rectangled other, Rectangled dest) { - dest.minX = Math.max(minX, other.minX); - dest.minY = Math.max(minY, other.minY); - dest.maxX = Math.min(maxX, other.maxX); - dest.maxY = Math.min(maxY, other.maxY); - return dest.validate(); - } - - /** - * Compute the rectangle of intersection between this and the given rectangle and - * store the result in dest. - *

- * If the two rectangles do not intersect, then {@link Double#NaN} is stored in each component - * of dest. - * - * @param other - * the other rectangle - * @param dest - * will hold the result - * @return dest - */ - public Rectangled intersection(Rectanglef other, Rectangled dest) { - dest.minX = Math.max(minX, other.minX); - dest.minY = Math.max(minY, other.minY); - dest.maxX = Math.min(maxX, other.maxX); - dest.maxY = Math.min(maxY, other.maxY); - return dest.validate(); - } - - /** - * Compute the rectangle of intersection between this and the given rectangle and - * store the result in dest. - *

- * If the two rectangles do not intersect, then {@link Double#NaN} is stored in each component - * of dest. - * - * @param other - * the other rectangle - * @param dest - * will hold the result - * @return dest - */ - public Rectangled intersection(Rectanglei other, Rectangled dest) { - dest.minX = Math.max(minX, other.minX); - dest.minY = Math.max(minY, other.minY); - dest.maxX = Math.min(maxX, other.maxX); - dest.maxY = Math.min(maxY, other.maxY); - return dest.validate(); - } - - /** - * Return the length of this rectangle in the X and Y dimensions and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - public Vector2d lengths(Vector2d dest) { - return dest.set(lengthX(), lengthY()); - } - - /** - * Check if this rectangle contains the given rectangle. - * - * @param rectangle - * the rectangle to test - * @return true iff this rectangle contains the rectangle; false otherwise - */ - public boolean containsRectangle(Rectangled rectangle) { - return rectangle.minX >= minX && rectangle.maxX <= maxX && - rectangle.minY >= minY && rectangle.maxY <= maxY; - } - - /** - * Check if this rectangle contains the given rectangle. - * - * @param rectangle - * the rectangle to test - * @return true iff this rectangle contains the rectangle; false otherwise - */ - public boolean containsRectangle(Rectanglef rectangle) { - return rectangle.minX >= minX && rectangle.maxX <= maxX && - rectangle.minY >= minY && rectangle.maxY <= maxY; - } - - /** - * Check if this rectangle contains the given rectangle. - * - * @param rectangle - * the rectangle to test - * @return true iff this rectangle contains the rectangle; false otherwise - */ - public boolean containsRectangle(Rectanglei rectangle) { - return rectangle.minX >= minX && rectangle.maxX <= maxX && - rectangle.minY >= minY && rectangle.maxY <= maxY; - } - - /** - * Set this to the union of this and the given point p. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @return this - */ - public Rectangled union(double x, double y) { - return union(x, y, this); - } - - /** - * Set this to the union of this and the given point p. - * - * @param p - * the point - * @return this - */ - public Rectangled union(Vector2dc p) { - return union(p.x(), p.y(), this); - } - - /** - * Compute the union of this and the given point (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param dest - * will hold the result - * @return dest - */ - public Rectangled union(double x, double y, Rectangled dest) { - dest.minX = this.minX < x ? this.minX : x; - dest.minY = this.minY < y ? this.minY : y; - dest.maxX = this.maxX > x ? this.maxX : x; - dest.maxY = this.maxY > y ? this.maxY : y; - return dest; - } - - /** - * Compute the union of this and the given point p and store the result in dest. - * - * @param p - * the point - * @param dest - * will hold the result - * @return dest - */ - public Rectangled union(Vector2dc p, Rectangled dest) { - return union(p.x(), p.y(), dest); - } - - /** - * Set this to the union of this and other. - * - * @param other - * the other {@link Rectanglef} - * @return this - */ - public Rectangled union(Rectangled other) { - return this.union(other, this); - } - - /** - * Compute the union of this and other and store the result in dest. - * - * @param other - * the other {@link Rectangled} - * @param dest - * will hold the result - * @return dest - */ - public Rectangled union(Rectangled other, Rectangled dest) { - dest.minX = this.minX < other.minX ? this.minX : other.minX; - dest.minY = this.minY < other.minY ? this.minY : other.minY; - dest.maxX = this.maxX > other.maxX ? this.maxX : other.maxX; - dest.maxY = this.maxY > other.maxY ? this.maxY : other.maxY; - return dest; - } - - /** - * Check if this and the given rectangle intersect. - * - * @param other - * the other rectangle - * @return true iff both rectangles intersect; false otherwise - */ - public boolean intersectsRectangle(Rectangled other) { - return minX < other.maxX && maxX > other.minX && - maxY > other.minY && minY < other.maxY; - } - - /** - * Check if this and the given rectangle intersect. - * - * @param other - * the other rectangle - * @return true iff both rectangles intersect; false otherwise - */ - public boolean intersectsRectangle(Rectanglef other) { - return minX < other.maxX && maxX > other.minX && - maxY > other.minY && minY < other.maxY; - } - - /** - * Check if this and the given rectangle intersect. - * - * @param other - * the other rectangle - * @return true iff both rectangles intersect; false otherwise - */ - public boolean intersectsRectangle(Rectanglei other) { - return minX < other.maxX && maxX > other.minX && - maxY > other.minY && minY < other.maxY; - } - - /** - * Check if this rectangle contains the given point. - * - * @param point - * the point to test - * @return true iff this rectangle contains the point; false otherwise - */ - public boolean containsPoint(Vector2dc point) { - return containsPoint(point.x(), point.y()); - } - - /** - * Check if this rectangle contains the given point (x, y). - * - * @param x - * the x coordinate of the point to check - * @param y - * the y coordinate of the point to check - * @return true iff this rectangle contains the point; false otherwise - */ - public boolean containsPoint(double x, double y) { - return x > minX && y > minY && x < maxX && y < maxY; - } - - /** - * Translate this by the given vector xy. - * - * @param xy - * the vector to translate by - * @return this - */ - public Rectangled translate(Vector2dc xy) { - return translate(xy.x(), xy.y(), this); - } - - /** - * Translate this by the given vector xy and store the result in dest. - * - * @param xy - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public Rectangled translate(Vector2dc xy, Rectangled dest) { - return translate(xy.x(), xy.y(), dest); - } - - /** - * Translate this by the given vector xy. - * - * @param xy - * the vector to translate by - * @return this - */ - public Rectangled translate(Vector2fc xy) { - return translate(xy.x(), xy.y(), this); - } - - /** - * Translate this by the given vector xy and store the result in dest. - * - * @param xy - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public Rectangled translate(Vector2fc xy, Rectangled dest) { - return translate(xy.x(), xy.y(), dest); - } - - /** - * Translate this by the vector (x, y). - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @return this - */ - public Rectangled translate(double x, double y) { - return translate(x, y, this); - } - - /** - * Translate this by the vector (x, y) and store the result in dest. - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param dest - * will hold the result - * @return dest - */ - public Rectangled translate(double x, double y, Rectangled dest) { - dest.minX = minX + x; - dest.minY = minY + y; - dest.maxX = maxX + x; - dest.maxY = maxY + y; - return dest; - } - - /** - * Scale this about the origin. - * - * @param sf - * the scaling factor in the x and y axis. - * @return this - */ - public Rectangled scale(double sf) { - return scale(sf, sf); - } - - /** - * Scale this about the origin and store the result in dest. - * - * @param sf - * the scaling factor in the x and y axis - * @param dest - * will hold the result - * @return dest - */ - public Rectangled scale(double sf, Rectangled dest) { - return scale(sf, sf, dest); - } - - /** - * Scale this about an anchor. - *

- * This is equivalent to translate(-ax, -ay).scale(sf).translate(ax, ay) - * - * @param sf - * the scaling factor in the x and y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @return this - */ - public Rectangled scale(double sf, double ax, double ay) { - return scale(sf, sf, ax, ay); - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is equivalent to translate(-ax, -ay, dest).scale(sf).translate(ax, ay) - * - * @param sf - * the scaling factor in the x and y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectangled scale(double sf, double ax, double ay, Rectangled dest) { - return scale(sf, sf, ax, ay, dest); - } - - /** - * Scale this about an anchor. - *

- * This is equivalent to translate(anchor.negate()).scale(sf).translate(anchor.negate()) - * - * @param sf - * the scaling factor in the x and y axis - * @param anchor - * the location of the anchor - * @return this - */ - public Rectangled scale(double sf, Vector2dc anchor) { - return scale(sf, anchor.x(), anchor.y()); - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is equivalent to translate(anchor.negate(), dest).scale(sf).translate(anchor.negate()) - * - * @param sf - * the scaling factor in the x and y axis - * @param anchor - * the location of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectangled scale(double sf, Vector2dc anchor, Rectangled dest) { - return scale(sf, anchor.x(), anchor.y(), dest); - } - - /** - * Scale this about the origin. - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @return this - */ - public Rectangled scale(double sx, double sy) { - return scale(sx, sy, 0d, 0d); - } - - /** - * Scale this about the origin and store the result in dest. - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param dest - * will hold the result - * @return dest - */ - public Rectangled scale(double sx, double sy, Rectangled dest) { - return scale(sx, sy, 0d, 0d, dest); - } - - /** - * Scale this about an anchor. - *

- * This is equivalent to translate(-ax, -ay).scale(sx, sy).translate(ax, ay) - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @return this - */ - public Rectangled scale(double sx, double sy, double ax, double ay) { - minX = (minX - ax) * sx + ax; - minY = (minY - ay) * sy + ay; - maxX = (maxX - ax) * sx + ax; - maxY = (maxY - ay) * sy + ay; - return this; - } - - /** - * Scale this about an anchor. - *

- * This is equivalent to translate(anchor.negate()).scale(sx, sy).translate(anchor.negate()) - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param anchor - * the location of the anchor - * @return this - */ - public Rectangled scale(double sx, double sy, Vector2dc anchor) { - return scale(sx, sy, anchor.x(), anchor.y()); - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is equivalent to translate(-ax, -ay, dest).scale(sx, sy).translate(ax, ay) - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectangled scale(double sx, double sy, double ax, double ay, Rectangled dest) { - dest.minX = (minX - ax) * sx + ax; - dest.minY = (minY - ay) * sy + ay; - dest.maxX = (maxX - ax) * sx + ax; - dest.maxY = (maxY - ay) * sy + ay; - return dest; - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is equivalent to translate(anchor.negate(), dest).scale(sx, sy).translate(anchor.negate()) - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param anchor - * the location of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectangled scale(double sx, double sy, Vector2dc anchor, Rectangled dest) { - return scale(sx, sy, anchor.x(), anchor.y(), dest); - } - - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(maxX); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(maxY); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(minX); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(minY); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Rectangled other = (Rectangled) obj; - if (Double.doubleToLongBits(maxX) != Double.doubleToLongBits(other.maxX)) - return false; - if (Double.doubleToLongBits(maxY) != Double.doubleToLongBits(other.maxY)) - return false; - if (Double.doubleToLongBits(minX) != Double.doubleToLongBits(other.minX)) - return false; - if (Double.doubleToLongBits(minY) != Double.doubleToLongBits(other.minY)) - return false; - return true; - } - - /** - * Return a string representation of this rectangle. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this rectangle by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(minX, formatter) + " " + Runtime.format(minY, formatter) + ") < " - + "(" + Runtime.format(maxX, formatter) + " " + Runtime.format(maxY, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeDouble(minX); - out.writeDouble(minY); - out.writeDouble(maxX); - out.writeDouble(maxY); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - minX = in.readDouble(); - minY = in.readDouble(); - maxX = in.readDouble(); - maxY = in.readDouble(); - } - -} diff --git a/src/org/joml/Rectanglef.java b/src/org/joml/Rectanglef.java deleted file mode 100644 index 773d1ffad..000000000 --- a/src/org/joml/Rectanglef.java +++ /dev/null @@ -1,815 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a 2D axis-aligned rectangle. - * - * @author Kai Burjack - */ -public class Rectanglef implements Externalizable { - - /** - * The x coordinate of the minimum corner. - */ - public float minX; - /** - * The y coordinate of the minimum corner. - */ - public float minY; - /** - * The x coordinate of the maximum corner. - */ - public float maxX; - /** - * The y coordinate of the maximum corner. - */ - public float maxY; - - /** - * Create a new {@link Rectanglef} with a minimum and maximum corner of (0, 0). - */ - public Rectanglef() { - } - - /** - * Create a new {@link Rectanglef} as a copy of the given source. - * - * @param source - * the {@link Rectanglef} to copy from - */ - public Rectanglef(Rectanglef source) { - this.minX = source.minX; - this.minY = source.minY; - this.maxX = source.maxX; - this.maxY = source.maxY; - } - - /** - * Create a new {@link Rectanglef} with the given min and max corner coordinates. - * - * @param min - * the minimum coordinates - * @param max - * the maximum coordinates - */ - public Rectanglef(Vector2fc min, Vector2fc max) { - this.minX = min.x(); - this.minY = min.y(); - this.maxX = max.x(); - this.maxY = max.y(); - } - - /** - * Create a new {@link Rectanglef} with the given minimum and maximum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - */ - public Rectanglef(float minX, float minY, float maxX, float maxY) { - this.minX = minX; - this.minY = minY; - this.maxX = maxX; - this.maxY = maxY; - } - - /** - * Set this {@link Rectanglei} to be a clone of source. - * - * @param source - * the {@link Rectanglei} to copy from - * @return this - */ - public Rectanglef set(Rectanglef source){ - this.minX = source.minX; - this.minY = source.minY; - this.maxX = source.maxX; - this.maxY = source.maxY; - return this; - } - - /** - * Set the minimum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @return this - */ - public Rectanglef setMin(float minX, float minY) { - this.minX = minX; - this.minY = minY; - return this; - } - - /** - * Set the minimum corner coordinates. - * - * @param min - * the minimum coordinates - * @return this - */ - public Rectanglef setMin(Vector2fc min) { - this.minX = min.x(); - this.minY = min.y(); - return this; - } - - - /** - * Set the maximum corner coordinates. - * - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - * @return this - */ - public Rectanglef setMax(float maxX, float maxY) { - this.maxX = maxX; - this.maxY = maxY; - return this; - } - - /** - * Set the maximum corner coordinates. - * - * @param max - * the maximum coordinates - * @return this - */ - public Rectanglef setMax(Vector2fc max) { - this.maxX = max.x(); - this.maxY = max.y(); - return this; - } - - /** - * Return the length of the rectangle in the X dimension. - * - * @return length in the X dimension - */ - public float lengthX() { - return maxX - minX; - } - - /** - * Return the length of the rectangle in the Y dimension. - * - * @return length in the Y dimension - */ - public float lengthY() { - return maxY - minY; - } - - /** - * Return the area of the rectangle - * - * @return area - */ - public float area() { - return lengthX() * lengthY(); - } - - /** - * Set this to the union of this and the given point p. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @return this - */ - public Rectanglef union(float x, float y) { - return union(x, y, this); - } - - /** - * Set this to the union of this and the given point p. - * - * @param p - * the point - * @return this - */ - public Rectanglef union(Vector2fc p) { - return union(p.x(), p.y(), this); - } - - /** - * Compute the union of this and the given point (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef union(float x, float y, Rectanglef dest) { - dest.minX = this.minX < x ? this.minX : x; - dest.minY = this.minY < y ? this.minY : y; - dest.maxX = this.maxX > x ? this.maxX : x; - dest.maxY = this.maxY > y ? this.maxY : y; - return dest; - } - - /** - * Compute the union of this and the given point p and store the result in dest. - * - * @param p - * the point - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef union(Vector2ic p, Rectanglef dest) { - return union(p.x(), p.y(), dest); - } - - /** - * Set this to the union of this and other. - * - * @param other - * the other {@link Rectanglef} - * @return this - */ - public Rectanglef union(Rectanglef other) { - return this.union(other, this); - } - - /** - * Compute the union of this and other and store the result in dest. - * - * @param other - * the other {@link Rectanglef} - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef union(Rectanglef other, Rectanglef dest) { - dest.minX = this.minX < other.minX ? this.minX : other.minX; - dest.minY = this.minY < other.minY ? this.minY : other.minY; - dest.maxX = this.maxX > other.maxX ? this.maxX : other.maxX; - dest.maxY = this.maxY > other.maxY ? this.maxY : other.maxY; - return dest; - } - - /** - * Check if this and the given rectangle intersect. - * - * @param other - * the other rectangle - * @return true iff both rectangles intersect; false otherwise - */ - public boolean intersectsRectangle(Rectangled other) { - return minX < other.maxX && maxX > other.minX && - maxY > other.minY && minY < other.maxY; - } - - /** - * Check if this and the given rectangle intersect. - * - * @param other - * the other rectangle - * @return true iff both rectangles intersect; false otherwise - */ - public boolean intersectsRectangle(Rectanglef other) { - return minX < other.maxX && maxX > other.minX && - maxY > other.minY && minY < other.maxY; - } - - /** - * Check if this and the given rectangle intersect. - * - * @param other - * the other rectangle - * @return true iff both rectangles intersect; false otherwise - */ - public boolean intersectsRectangle(Rectanglei other) { - return minX < other.maxX && maxX > other.minX && - maxY > other.minY && minY < other.maxY; - } - - private Rectanglef validate() { - if (!isValid()) { - minX = Float.NaN; - minY = Float.NaN; - maxX = Float.NaN; - maxY = Float.NaN; - } - return this; - } - - /** - * Check whether this rectangle represents a valid rectangle. - * - * @return true iff this rectangle is valid; false otherwise - */ - public boolean isValid() { - return minX < maxX && minY < maxY; - } - - /** - * Compute the rectangle of intersection between this and the given rectangle. - *

- * If the two rectangles do not intersect, then {@link Float#NaN} is stored in each component - * of dest. - * - * @param other - * the other rectangle - * @return this - */ - public Rectanglef intersection(Rectanglef other) { - return intersection(other, this); - } - - /** - * Compute the rectangle of intersection between this and the given rectangle. - *

- * If the two rectangles do not intersect, then {@link Float#NaN} is stored in each component - * of dest. - * - * @param other - * the other rectangle - * @return this - */ - public Rectanglef intersection(Rectanglei other) { - return intersection(other, this); - } - - /** - * Compute the rectangle of intersection between this and the given rectangle and - * store the result in dest. - *

- * If the two rectangles do not intersect, then {@link Float#NaN} is stored in each component - * of dest. - * - * @param other - * the other rectangle - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef intersection(Rectanglef other, Rectanglef dest) { - dest.minX = Math.max(minX, other.minX); - dest.minY = Math.max(minY, other.minY); - dest.maxX = Math.min(maxX, other.maxX); - dest.maxY = Math.min(maxY, other.maxY); - return dest.validate(); - } - - /** - * Compute the rectangle of intersection between this and the given rectangle and - * store the result in dest. - *

- * If the two rectangles do not intersect, then {@link Double#NaN} is stored in each component - * of dest. - * - * @param other - * the other rectangle - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef intersection(Rectanglei other, Rectanglef dest) { - dest.minX = Math.max(minX, other.minX); - dest.minY = Math.max(minY, other.minY); - dest.maxX = Math.min(maxX, other.maxX); - dest.maxY = Math.min(maxY, other.maxY); - return dest.validate(); - } - - /** - * Return the length of this rectangle in the X and Y dimensions and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - public Vector2f lengths(Vector2f dest) { - return dest.set(lengthX(), lengthY()); - } - - /** - * Check if this rectangle contains the given rectangle. - * - * @param rectangle - * the rectangle to test - * @return true iff this rectangle contains the rectangle; false otherwise - */ - public boolean containsRectangle(Rectangled rectangle) { - return rectangle.minX >= minX && rectangle.maxX <= maxX && - rectangle.minY >= minY && rectangle.maxY <= maxY; - } - - /** - * Check if this rectangle contains the given rectangle. - * - * @param rectangle - * the rectangle to test - * @return true iff this rectangle contains the rectangle; false otherwise - */ - public boolean containsRectangle(Rectanglef rectangle) { - return rectangle.minX >= minX && rectangle.maxX <= maxX && - rectangle.minY >= minY && rectangle.maxY <= maxY; - } - - /** - * Check if this rectangle contains the given rectangle. - * - * @param rectangle - * the rectangle to test - * @return true iff this rectangle contains the rectangle; false otherwise - */ - public boolean containsRectangle(Rectanglei rectangle) { - return rectangle.minX >= minX && rectangle.maxX <= maxX && - rectangle.minY >= minY && rectangle.maxY <= maxY; - } - - /** - * Check if this rectangle contains the given point. - * - * @param point - * the point to test - * @return true iff this rectangle contains the point; false otherwise - */ - public boolean containsPoint(Vector2fc point) { - return containsPoint(point.x(), point.y()); - } - - /** - * Check if this rectangle contains the given point (x, y). - * - * @param x - * the x coordinate of the point to check - * @param y - * the y coordinate of the point to check - * @return true iff this rectangle contains the point; false otherwise - */ - public boolean containsPoint(float x, float y) { - return x > minX && y > minY && x < maxX && y < maxY; - } - - /** - * Translate this by the given vector xy. - * - * @param xy - * the vector to translate by - * @return this - */ - public Rectanglef translate(Vector2fc xy) { - return translate(xy.x(), xy.y(), this); - } - - /** - * Translate this by the given vector xy and store the result in dest. - * - * @param xy - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef translate(Vector2fc xy, Rectanglef dest) { - return translate(xy.x(), xy.y(), dest); - } - - /** - * Translate this by the vector (x, y). - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @return this - */ - public Rectanglef translate(float x, float y) { - return translate(x, y, this); - } - - /** - * Translate this by the vector (x, y) and store the result in dest. - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef translate(float x, float y, Rectanglef dest) { - dest.minX = minX + x; - dest.minY = minY + y; - dest.maxX = maxX + x; - dest.maxY = maxY + y; - return dest; - } - - /** - * Scale this about the origin. - * - * @param sf - * the scaling factor in the x and y axis - * @return this - */ - public Rectanglef scale(float sf) { - return scale(sf, sf); - } - - /** - * Scale this about the origin and store the result in dest. - * - * @param sf - * the scaling factor in the x and y axis - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef scale(float sf, Rectanglef dest) { - return scale(sf, sf, dest); - } - - /** - * Scale this about an anchor. - *

- * This is equivalent to translate(-ax, -ay).scale(sf).translate(ax, ay) - * - * @param sf - * the scaling factor in the x and y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @return this - */ - public Rectanglef scale(float sf, float ax, float ay) { - return scale(sf, sf, ax, ay); - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is equivalent to translate(-ax, -ay, dest).scale(sf).translate(ax, ay) - * - * @param sf - * the scaling factor in the x and y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef scale(float sf, float ax, float ay, Rectanglef dest) { - return scale(sf, sf, ax, ay, dest); - } - - /** - * Scale this about an anchor. - *

- * This is equivalent to translate(anchor.negate()).scale(sf).translate(anchor.negate()) - * - * @param sf - * the scaling factor in the x and y axis - * @param anchor - * the location of the anchor - * @return this - */ - public Rectanglef scale(float sf, Vector2fc anchor) { - return scale(sf, anchor.x(), anchor.y()); - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is equivalent to translate(anchor.negate(), dest).scale(sf).translate(anchor.negate()) - * - * @param sf - * the scaling factor in the x and y axis - * @param anchor - * the location of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef scale(float sf, Vector2fc anchor, Rectanglef dest) { - return scale(sf, anchor.x(), anchor.y(), dest); - } - - /** - * Scale this about the origin. - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @return this - */ - public Rectanglef scale(float sx, float sy) { - return scale(sx, sy, 0f, 0f); - } - - /** - * Scale this about the origin and store the result in dest. - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef scale(float sx, float sy, Rectanglef dest) { - return scale(sx, sy, 0f, 0f, dest); - } - - /** - * Scale this about an anchor. - *

- * This is equivalent to translate(-ax, -ay).scale(sx, sy).translate(ax, ay) - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @return this - */ - public Rectanglef scale(float sx, float sy, float ax, float ay) { - minX = (minX - ax) * sx + ax; - minY = (minY - ay) * sy + ay; - maxX = (maxX - ax) * sx + ax; - maxY = (maxY - ay) * sy + ay; - return this; - } - - /** - * Scale this about an anchor. - *

- * This is equivalent to translate(anchor.negate()).scale(sx, sy).translate(anchor.negate()) - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param anchor - * the location of the anchor - * @return this - */ - public Rectanglef scale(float sx, float sy, Vector2fc anchor) { - return scale(sx, sy, anchor.x(), anchor.y()); - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is equivalent to translate(-ax, -ay, dest).scale(sx, sy).translate(ax, ay) - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef scale(float sx, float sy, float ax, float ay, Rectanglef dest) { - dest.minX = (minX - ax) * sx + ax; - dest.minY = (minY - ay) * sy + ay; - dest.maxX = (maxX - ax) * sx + ax; - dest.maxY = (maxY - ay) * sy + ay; - return dest; - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is equivalent to translate(anchor.negate(), dest).scale(sx, sy).translate(anchor.negate()) - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param anchor - * the location of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectanglef scale(float sx, float sy, Vector2fc anchor, Rectanglef dest) { - return scale(sx, sy, anchor.x(), anchor.y(), dest); - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(maxX); - result = prime * result + Float.floatToIntBits(maxY); - result = prime * result + Float.floatToIntBits(minX); - result = prime * result + Float.floatToIntBits(minY); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Rectanglef other = (Rectanglef) obj; - if (Float.floatToIntBits(maxX) != Float.floatToIntBits(other.maxX)) - return false; - if (Float.floatToIntBits(maxY) != Float.floatToIntBits(other.maxY)) - return false; - if (Float.floatToIntBits(minX) != Float.floatToIntBits(other.minX)) - return false; - if (Float.floatToIntBits(minY) != Float.floatToIntBits(other.minY)) - return false; - return true; - } - - /** - * Return a string representation of this rectangle. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this rectangle by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(minX, formatter) + " " + Runtime.format(minY, formatter) + ") < " - + "(" + Runtime.format(maxX, formatter) + " " + Runtime.format(maxY, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(minX); - out.writeFloat(minY); - out.writeFloat(maxX); - out.writeFloat(maxY); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - minX = in.readFloat(); - minY = in.readFloat(); - maxX = in.readFloat(); - maxY = in.readFloat(); - } - -} diff --git a/src/org/joml/Rectanglei.java b/src/org/joml/Rectanglei.java deleted file mode 100644 index e276a2e34..000000000 --- a/src/org/joml/Rectanglei.java +++ /dev/null @@ -1,846 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a 2D axis-aligned rectangle. - * - * @author Kai Burjack - */ -public class Rectanglei implements Externalizable { - - /** - * The x coordinate of the minimum corner. - */ - public int minX; - /** - * The y coordinate of the minimum corner. - */ - public int minY; - /** - * The x coordinate of the maximum corner. - */ - public int maxX; - /** - * The y coordinate of the maximum corner. - */ - public int maxY; - - /** - * Create a new {@link Rectanglei} with a minimum and maximum corner of (0, 0). - */ - public Rectanglei() { - } - - /** - * Create a new {@link Rectanglei} as a copy of the given source. - * - * @param source - * the {@link Rectanglei} to copy from - */ - public Rectanglei(Rectanglei source) { - this.minX = source.minX; - this.minY = source.minY; - this.maxX = source.maxX; - this.maxY = source.maxY; - } - - /** - * Create a new {@link Rectanglei} with the given min and max corner coordinates. - * - * @param min - * the minimum coordinates - * @param max - * the maximum coordinates - */ - public Rectanglei(Vector2ic min, Vector2ic max) { - this.minX = min.x(); - this.minY = min.y(); - this.maxX = max.x(); - this.maxY = max.y(); - } - - /** - * Create a new {@link Rectanglei} with the given minimum and maximum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - */ - public Rectanglei(int minX, int minY, int maxX, int maxY) { - this.minX = minX; - this.minY = minY; - this.maxX = maxX; - this.maxY = maxY; - } - - /** - * Set this {@link Rectanglei} to be a clone of source. - * - * @param source - * the {@link Rectanglei} to copy from - * @return this - */ - public Rectanglei set(Rectanglei source){ - this.minX = source.minX; - this.minY = source.minY; - this.maxX = source.maxX; - this.maxY = source.maxY; - return this; - } - - /** - * Set the minimum corner coordinates. - * - * @param minX - * the x coordinate of the minimum corner - * @param minY - * the y coordinate of the minimum corner - * @return this - */ - public Rectanglei setMin(int minX, int minY) { - this.minX = minX; - this.minY = minY; - return this; - } - - /** - * Set the minimum corner coordinates. - * - * @param min - * the minimum coordinates - * @return this - */ - public Rectanglei setMin(Vector2ic min) { - this.minX = min.x(); - this.minY = min.y(); - return this; - } - - - /** - * Set the maximum corner coordinates. - * - * @param maxX - * the x coordinate of the maximum corner - * @param maxY - * the y coordinate of the maximum corner - * @return this - */ - public Rectanglei setMax(int maxX, int maxY) { - this.maxX = maxX; - this.maxY = maxY; - return this; - } - - /** - * Set the maximum corner coordinates. - * - * @param max - * the maximum coordinates - * @return this - */ - public Rectanglei setMax(Vector2ic max) { - this.maxX = max.x(); - this.maxY = max.y(); - return this; - } - - /** - * Return the length of the rectangle in the X dimension. - * - * @return length in the X dimension - */ - public int lengthX() { - return maxX - minX; - } - - /** - * Return the length of the rectangle in the Y dimension. - * - * @return length in the Y dimension - */ - public int lengthY() { - return maxY - minY; - } - - /** - * Return the area of the rectangle - * - * @return area - */ - public int area() { - return lengthX() * lengthY(); - } - - /** - * Set this to the union of this and the given point p. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @return this - */ - public Rectanglei union(int x, int y) { - return union(x,y, this); - } - - - /** - * Set this to the union of this and the given point p. - * - * @param p - * the point - * @return this - */ - public Rectanglei union(Vector2ic p) { - return union(p.x(), p.y(), this); - } - - /** - * Compute the union of this and the given point (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate of the point - * @param y - * the y coordinate of the point - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei union(int x, int y, Rectanglei dest) { - dest.minX = this.minX < x ? this.minX : x; - dest.minY = this.minY < y ? this.minY : y; - dest.maxX = this.maxX > x ? this.maxX : x; - dest.maxY = this.maxY > y ? this.maxY : y; - return dest; - } - - /** - * Compute the union of this and the given point p and store the result in dest. - * - * @param p - * the point - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei union(Vector2ic p, Rectanglei dest) { - return union(p.x(), p.y(), dest); - } - - /** - * Set this to the union of this and other. - * - * @param other - * the other {@link Rectanglei} - * @return this - */ - public Rectanglei union(Rectanglei other) { - return this.union(other, this); - } - - /** - * Compute the union of this and other and store the result in dest. - * - * @param other - * the other {@link Rectanglei} - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei union(Rectanglei other, Rectanglei dest) { - dest.minX = this.minX < other.minX ? this.minX : other.minX; - dest.minY = this.minY < other.minY ? this.minY : other.minY; - dest.maxX = this.maxX > other.maxX ? this.maxX : other.maxX; - dest.maxY = this.maxY > other.maxY ? this.maxY : other.maxY; - return dest; - } - - - /** - * Check if this and the given rectangle intersect. - * - * @param other - * the other rectangle - * @return true iff both rectangles intersect; false otherwise - */ - public boolean intersectsRectangle(Rectangled other) { - return minX <= other.maxX && maxX >= other.minX && - maxY >= other.minY && minY <= other.maxY; - } - - /** - * Check if this and the given rectangle intersect. - * - * @param other - * the other rectangle - * @return true iff both rectangles intersect; false otherwise - */ - public boolean intersectsRectangle(Rectanglef other) { - return minX <= other.maxX && maxX >= other.minX && - maxY >= other.minY && minY <= other.maxY; - } - - /** - * Check if this and the given rectangle intersect. - * - * @param other - * the other rectangle - * @return true iff both rectangles intersect; false otherwise - */ - public boolean intersectsRectangle(Rectanglei other) { - return minX <= other.maxX && maxX >= other.minX && - maxY >= other.minY && minY <= other.maxY; - } - - private Rectanglei validate() { - if (!isValid()) { - minX = Integer.MAX_VALUE; - minY = Integer.MAX_VALUE; - maxX = Integer.MIN_VALUE; - maxY = Integer.MIN_VALUE; - } - return this; - } - - /** - * Check whether this rectangle represents a valid rectangle. - * - * @return true iff this rectangle is valid; false otherwise - */ - public boolean isValid() { - return minX < maxX && minY < maxY; - } - - /** - * Compute the rectangle of intersection between this and the given rectangle. - *

- * If the two rectangles do not intersect, then the minimum coordinates of this - * will have a value of {@link Integer#MAX_VALUE} and the maximum coordinates will have a value of - * {@link Integer#MIN_VALUE}. - * - * @param other - * the other rectangle - * @return this - */ - public Rectanglei intersection(Rectanglei other) { - return intersection(other, this); - } - - /** - * Compute the rectangle of intersection between this and the given rectangle and - * store the result in dest. - *

- * If the two rectangles do not intersect, then the minimum coordinates of dest - * will have a value of {@link Integer#MAX_VALUE} and the maximum coordinates will have a value of - * {@link Integer#MIN_VALUE}. - * - * @param other - * the other rectangle - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei intersection(Rectanglei other, Rectanglei dest) { - dest.minX = Math.max(minX, other.minX); - dest.minY = Math.max(minY, other.minY); - dest.maxX = Math.min(maxX, other.maxX); - dest.maxY = Math.min(maxY, other.maxY); - return dest.validate(); - } - - /** - * Return the length of this rectangle in the X and Y dimensions and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - public Vector2i lengths(Vector2i dest) { - return dest.set(lengthX(), lengthY()); - } - - /** - * Check if this rectangle contains the given rectangle. - * - * @param rectangle - * the rectangle to test - * @return true iff this rectangle contains the rectangle; false otherwise - */ - public boolean containsRectangle(Rectangled rectangle) { - return rectangle.minX >= minX && rectangle.maxX <= maxX && - rectangle.minY >= minY && rectangle.maxY <= maxY; - } - - /** - * Check if this rectangle contains the given rectangle. - * - * @param rectangle - * the rectangle to test - * @return true iff this rectangle contains the rectangle; false otherwise - */ - public boolean containsRectangle(Rectanglef rectangle) { - return rectangle.minX >= minX && rectangle.maxX <= maxX && - rectangle.minY >= minY && rectangle.maxY <= maxY; - } - - /** - * Check if this rectangle contains the given rectangle. - * - * @param rectangle - * the rectangle to test - * @return true iff this rectangle contains the rectangle; false otherwise - */ - public boolean containsRectangle(Rectanglei rectangle) { - return rectangle.minX >= minX && rectangle.maxX <= maxX && - rectangle.minY >= minY && rectangle.maxY <= maxY; - } - - /** - * Check if this rectangle contains the given point. - * - * @param point - * the point to test - * @return true iff this rectangle contains the point; false otherwise - */ - public boolean containsPoint(Vector2ic point) { - return containsPoint(point.x(), point.y()); - } - - /** - * Test whether the point (x, y) lies inside this BlockRegion. - * - * @param x the x coordinate of the point - * @param y the y coordinate of the point - * @return true iff the given point lies inside this BlockRegion; false otherwise - */ - public boolean containsPoint(float x, float y) { - return x > this.minX && y > this.minY && x < this.maxX && y < this.maxY; - } - - /** - * Test whether the point (x, y) lies inside this BlockRegion. - * - * @param point - * the point to test - * @return true iff the given point lies inside this BlockRegion; false otherwise - */ - public boolean containsPoint(Vector2fc point) { - return containsPoint(point.x(), point.y()); - } - - - /** - * Check if this rectangle contains the given point (x, y). - * - * @param x - * the x coordinate of the point to check - * @param y - * the y coordinate of the point to check - * @return true iff this rectangle contains the point; false otherwise - */ - public boolean containsPoint(int x, int y) { - return x > minX && y > minY && x < maxX && y < maxY; - } - - /** - * Translate this by the given vector xy. - * - * @param xy - * the vector to translate by - * @return this - */ - public Rectanglei translate(Vector2ic xy) { - return translate(xy.x(), xy.y(), this); - } - - /** - * Translate this by the given vector xy and store the result in dest. - * - * @param xy - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei translate(Vector2ic xy, Rectanglei dest) { - return translate(xy.x(), xy.y(), dest); - } - - /** - * Translate this by the vector (x, y). - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @return this - */ - public Rectanglei translate(int x, int y) { - return translate(x, y, this); - } - - /** - * Translate this by the vector (x, y) and store the result in dest. - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei translate(int x, int y, Rectanglei dest) { - dest.minX = minX + x; - dest.minY = minY + y; - dest.maxX = maxX + x; - dest.maxY = maxY + y; - return dest; - } - - /** - * Scale this about the origin. - * - * @param sf - * the scaling factor in the x and y axis. - * @return this - */ - public Rectanglei scale(int sf) { - return scale(sf, sf); - } - - /** - * Scale this about the origin and store the result in dest. - * - * @param sf - * the scaling factor in the x and y axis - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei scale(int sf, Rectanglei dest) { - return scale(sf, sf, dest); - } - - /** - * Scale this about an anchor. - *

- * This is effectively equivalent to
- *

-     *     translate(-ax, -ay);
-     *     scale(sf);
-     *     translate(ax, ay);
-     * 
- * - * @param sf - * the scaling factor in the x and y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @return this - */ - public Rectanglei scale(int sf, int ax, int ay) { - return scale(sf, sf, ax, ay); - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is effectively equivalent to
- *

-     *     translate(-ax, -ay);
-     *     scale(sf);
-     *     translate(ax, ay);
-     * 
- * - * @param sf - * the scaling factor in the x and y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei scale(int sf, int ax, int ay, Rectanglei dest) { - return scale(sf, sf, ax, ay, dest); - } - - /** - * Scale this about an anchor. - *

- * This is effectively equivalent to
- *

-     *     translate(anchor.negate());
-     *     scale(sf);
-     *     translate(anchor.negate());
-     * 
- * - * @param sf - * the scaling factor in the x and y axis - * @param anchor - * the location of the anchor - * @return this - */ - public Rectanglei scale(int sf, Vector2ic anchor) { - return scale(sf, anchor.x(), anchor.y()); - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is effectively equivalent to
- *

-     *     translate(anchor.negate());
-     *     scale(sf);
-     *     translate(anchor.negate());
-     * 
- * - * @param sf - * the scaling factor in the x and y axis - * @param anchor - * the location of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei scale(int sf, Vector2ic anchor, Rectanglei dest) { - return scale(sf, anchor.x(), anchor.y(), dest); - } - - /** - * Scale this about the origin. - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @return this - */ - public Rectanglei scale(int sx, int sy) { - return scale(sx, sy, 0, 0); - } - - /** - * Scale this about the origin and store the result in dest. - * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei scale(int sx, int sy, Rectanglei dest) { - return scale(sx, sy, 0, 0, dest); - } - - /** - * Scale this about an anchor. - * This is equivalent to
- *
-     *     translate(-ax, -ay);
-     *     scale(sx, sy);
-     *     translate(ax, ay);
-     * 
- * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @return this - */ - public Rectanglei scale(int sx, int sy, int ax, int ay) { - minX = (minX - ax) * sx + ax; - minY = (minY - ay) * sy + ay; - maxX = (maxX - ax) * sx + ax; - maxY = (maxY - ay) * sy + ay; - return this; - } - - /** - * Scale this about an anchor. - *

- * This is equivalent to
- *

-     *     translate(anchor.negate());
-     *     scale(sx, sy);
-     *     translate(anchor.negate());
-     * 
- * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param anchor - * the location of the anchor - * @return this - */ - public Rectanglei scale(int sx, int sy, Vector2ic anchor) { - return scale(sx, sy, anchor.x(), anchor.y()); - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is equivalent to
- *

-     *     translate(-ax, -ay);
-     *     scale(sx, sy);
-     *     translate(ax, ay);
-     * 
- * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param ax - * the x coordinate of the anchor - * @param ay - * the y coordinate of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei scale(int sx, int sy, int ax, int ay, Rectanglei dest) { - dest.minX = (minX - ax) * sx + ax; - dest.minY = (minY - ay) * sy + ay; - dest.maxX = (maxX - ax) * sx + ax; - dest.maxY = (maxY - ay) * sy + ay; - return dest; - } - - /** - * Scale this about an anchor and store the result in dest. - *

- * This is equivalent to
- *

-     *     translate(anchor.negate());
-     *     scale(sx, sy);
-     *     translate(anchor.negate());
-     * 
- * - * @param sx - * the scaling factor on the x axis - * @param sy - * the scaling factor on the y axis - * @param anchor - * the location of the anchor - * @param dest - * will hold the result - * @return dest - */ - public Rectanglei scale(int sx, int sy, Vector2ic anchor, Rectanglei dest) { - return scale(sx, sy, anchor.x(), anchor.y(), dest); - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + maxX; - result = prime * result + maxY; - result = prime * result + minX; - result = prime * result + minY; - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Rectanglei other = (Rectanglei) obj; - if (maxX != other.maxX) - return false; - if (maxY != other.maxY) - return false; - if (minX != other.minX) - return false; - if (minY != other.minY) - return false; - return true; - } - - /** - * Return a string representation of this rectangle. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this rectangle by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + formatter.format(minX) + " " + formatter.format(minY) + ") < " - + "(" + formatter.format(maxX) + " " + formatter.format(maxY) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeInt(minX); - out.writeInt(minY); - out.writeInt(maxX); - out.writeInt(maxY); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - minX = in.readInt(); - minY = in.readInt(); - maxX = in.readInt(); - maxY = in.readInt(); - } - -} diff --git a/src/org/joml/Runtime.java b/src/org/joml/Runtime.java index 2460da535..b5bc998cd 100644 --- a/src/org/joml/Runtime.java +++ b/src/org/joml/Runtime.java @@ -25,7 +25,12 @@ import java.text.NumberFormat; -final class Runtime { +/** + * Internal class to detect features of the runtime. + * + * @author Kai Burjack + */ +public final class Runtime { //#ifndef __GWT__ public static final boolean HAS_floatToRawIntBits = hasFloatToRawIntBits(); @@ -128,7 +133,7 @@ public static String formatNumbers(String str) { return res.toString(); } - static String format(double number, NumberFormat format) { + public static String format(double number, NumberFormat format) { if (Double.isNaN(number)) { return padLeft(format, " NaN"); } else if (Double.isInfinite(number)) { diff --git a/src/org/joml/Sphered.java b/src/org/joml/Sphered.java deleted file mode 100644 index 5936ac78d..000000000 --- a/src/org/joml/Sphered.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a 3D sphere. - * - * @author Kai Burjack - */ -public class Sphered implements Externalizable { - - /** - * The x coordinate of the sphere's center. - */ - public double x; - /** - * The y coordinate of the sphere's center. - */ - public double y; - /** - * The z coordinate of the sphere's center. - */ - public double z; - /** - * The sphere's radius. - */ - public double r; - - /** - * Create a new {@link Sphered} with center position (0, 0, 0) and radius = 0. - */ - public Sphered() { - } - - /** - * Create a new {@link Sphered} as a copy of the given source. - * - * @param source - * the {@link Sphered} to copy from - */ - public Sphered(Sphered source) { - this.x = source.x; - this.y = source.y; - this.z = source.z; - this.r = source.r; - } - - /** - * Create a new {@link Sphered} with center position c and radius r. - * - * @param c - * the center position of the sphere - * @param r - * the radius of the sphere - */ - public Sphered(Vector3fc c, double r) { - this.x = c.x(); - this.y = c.y(); - this.z = c.z(); - this.r = r; - } - - /** - * Create a new {@link Sphered} with center position c and radius r. - * - * @param c - * the center position of the sphere - * @param r - * the radius of the sphere - */ - public Sphered(Vector3dc c, double r) { - this.x = c.x(); - this.y = c.y(); - this.z = c.z(); - this.r = r; - } - - /** - * Create a new {@link Sphered} with center position (x, y, z) and radius r. - * - * @param x - * the x coordinate of the sphere's center - * @param y - * the y coordinate of the sphere's center - * @param z - * the z coordinate of the sphere's center - * @param r - * the radius of the sphere - */ - public Sphered(double x, double y, double z, double r) { - this.x = x; - this.y = y; - this.z = z; - this.r = r; - } - - /** - * Translate this by the given vector xyz. - * - * @param xyz - * the vector to translate by - * @return this - */ - public Sphered translate(Vector3dc xyz) { - return translate(xyz.x(), xyz.y(), xyz.z(), this); - } - - /** - * Translate this by the given vector xyz and store the result in dest. - * - * @param xyz - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public Sphered translate(Vector3dc xyz, Sphered dest) { - return translate(xyz.x(), xyz.y(), xyz.z(), dest); - } - - /** - * Translate this by the given vector xyz. - * - * @param xyz - * the vector to translate by - * @return this - */ - public Sphered translate(Vector3fc xyz) { - return translate(xyz.x(), xyz.y(), xyz.z(), this); - } - - /** - * Translate this by the given vector xyz and store the result in dest. - * - * @param xyz - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public Sphered translate(Vector3fc xyz, Sphered dest) { - return translate(xyz.x(), xyz.y(), xyz.z(), dest); - } - - /** - * Translate this by the vector (x, y, z). - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param z - * the z coordinate to translate by - * @return this - */ - public Sphered translate(double x, double y, double z) { - return translate(x, y, z, this); - } - - /** - * Translate this by the vector (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param z - * the z coordinate to translate by - * @param dest - * will hold the result - * @return dest - */ - public Sphered translate(double x, double y, double z, Sphered dest) { - dest.x = this.x + x; - dest.y = this.y + y; - dest.z = this.z + z; - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(r); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(x); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(y); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(z); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Sphered other = (Sphered) obj; - if (Double.doubleToLongBits(r) != Double.doubleToLongBits(other.r)) - return false; - if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) - return false; - if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) - return false; - if (Double.doubleToLongBits(z) != Double.doubleToLongBits(other.z)) - return false; - return true; - } - - /** - * Return a string representation of this sphere. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this sphere by formatting the components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "[" + Runtime.format(x, formatter) + " " + Runtime.format(y, formatter) + " " + Runtime.format(z, formatter) + " " + Runtime.format(r, formatter) + "]"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeDouble(x); - out.writeDouble(y); - out.writeDouble(z); - out.writeDouble(r); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - x = in.readDouble(); - y = in.readDouble(); - z = in.readDouble(); - r = in.readDouble(); - } - -} diff --git a/src/org/joml/Spheref.java b/src/org/joml/Spheref.java deleted file mode 100644 index f7c0058ea..000000000 --- a/src/org/joml/Spheref.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2017-2020 JOML - * - * 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 org.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Represents a 3D sphere. - * - * @author Kai Burjack - */ -public class Spheref implements Externalizable { - - /** - * The x coordinate of the sphere's center. - */ - public float x; - /** - * The y coordinate of the sphere's center. - */ - public float y; - /** - * The z coordinate of the sphere's center. - */ - public float z; - /** - * The sphere's radius. - */ - public float r; - - /** - * Create a new {@link Spheref} with center position (0, 0, 0) and radius = 0. - */ - public Spheref() { - } - - /** - * Create a new {@link Spheref} as a copy of the given source. - * - * @param source - * the {@link Spheref} to copy from - */ - public Spheref(Spheref source) { - this.x = source.x; - this.y = source.y; - this.z = source.z; - this.r = source.r; - } - - /** - * Create a new {@link Spheref} with center position c and radius r. - * - * @param c - * the center position of the sphere - * @param r - * the radius of the sphere - */ - public Spheref(Vector3fc c, float r) { - this.x = c.x(); - this.y = c.y(); - this.z = c.z(); - this.r = r; - } - - /** - * Create a new {@link Spheref} with center position (x, y, z) and radius r. - * - * @param x - * the x coordinate of the sphere's center - * @param y - * the y coordinate of the sphere's center - * @param z - * the z coordinate of the sphere's center - * @param r - * the radius of the sphere - */ - public Spheref(float x, float y, float z, float r) { - this.x = x; - this.y = y; - this.z = z; - this.r = r; - } - - /** - * Translate this by the given vector xyz. - * - * @param xyz - * the vector to translate by - * @return this - */ - public Spheref translate(Vector3fc xyz) { - return translate(xyz.x(), xyz.y(), xyz.z(), this); - } - - /** - * Translate this by the given vector xyz and store the result in dest. - * - * @param xyz - * the vector to translate by - * @param dest - * will hold the result - * @return dest - */ - public Spheref translate(Vector3fc xyz, Spheref dest) { - return translate(xyz.x(), xyz.y(), xyz.z(), dest); - } - - /** - * Translate this by the vector (x, y, z). - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param z - * the z coordinate to translate by - * @return this - */ - public Spheref translate(float x, float y, float z) { - return translate(x, y, z, this); - } - - /** - * Translate this by the vector (x, y, z) and store the result in dest. - * - * @param x - * the x coordinate to translate by - * @param y - * the y coordinate to translate by - * @param z - * the z coordinate to translate by - * @param dest - * will hold the result - * @return dest - */ - public Spheref translate(float x, float y, float z, Spheref dest) { - dest.x = this.x + x; - dest.y = this.y + y; - dest.z = this.z + z; - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(r); - result = prime * result + Float.floatToIntBits(x); - result = prime * result + Float.floatToIntBits(y); - result = prime * result + Float.floatToIntBits(z); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Spheref other = (Spheref) obj; - if (Float.floatToIntBits(r) != Float.floatToIntBits(other.r)) - return false; - if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x)) - return false; - if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y)) - return false; - if (Float.floatToIntBits(z) != Float.floatToIntBits(other.z)) - return false; - return true; - } - - /** - * Return a string representation of this sphere. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this sphere by formatting the components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "[" + Runtime.format(x, formatter) + " " + Runtime.format(y, formatter) + " " + Runtime.format(z, formatter) + " " + Runtime.format(r, formatter) + "]"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(x); - out.writeFloat(y); - out.writeFloat(z); - out.writeFloat(r); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - x = in.readFloat(); - y = in.readFloat(); - z = in.readFloat(); - r = in.readFloat(); - } - -} diff --git a/test/org/joml/test/AABBiTest.java b/test/org/joml/test/AABBiTest.java deleted file mode 100644 index aef5e70f4..000000000 --- a/test/org/joml/test/AABBiTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML. - * - * 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 org.joml.test; - -import junit.framework.Assert; -import junit.framework.TestCase; -import org.joml.AABBi; - -public class AABBiTest extends TestCase { - public void testAABBiEdgeIntersection() { - AABBi center = new AABBi(0, 0, 0, 1, 1,1); - AABBi right = new AABBi(1, 0,0, 2, 1,1); - AABBi left = new AABBi(-1, 0, 0, 0, 1,1); - AABBi front = new AABBi(0, 1, 0, 1, 2,1); - AABBi back = new AABBi(0, -1, 0, 1, 0,1); - AABBi top = new AABBi(0, 0, 1, 1, 1,2); - AABBi bottom = new AABBi(0, 0, -1, 1, 1,0); - - - Assert.assertTrue(center.isValid()); - Assert.assertTrue(right.isValid()); - Assert.assertTrue(left.isValid()); - Assert.assertTrue(top.isValid()); - Assert.assertTrue(bottom.isValid()); - Assert.assertTrue(front.isValid()); - Assert.assertTrue(back.isValid()); - - // check contains - Assert.assertFalse(center.containsAABB(right)); - Assert.assertFalse(center.containsAABB(left)); - Assert.assertFalse(center.containsAABB(front)); - Assert.assertFalse(center.containsAABB(back)); - Assert.assertFalse(center.containsAABB(top)); - - // test intersection - Assert.assertTrue(center.intersectsAABB(right)); - Assert.assertTrue(center.intersectsAABB(left)); - Assert.assertTrue(center.intersectsAABB(front)); - Assert.assertTrue(center.intersectsAABB(back)); - Assert.assertTrue(center.intersectsAABB(top)); - - Assert.assertTrue(right.intersectsAABB(center)); - Assert.assertTrue(left.intersectsAABB(center)); - Assert.assertTrue(front.intersectsAABB(center)); - Assert.assertTrue(back.intersectsAABB(center)); - Assert.assertTrue(top.intersectsAABB(center)); - } - - - public void testAABBiCornerIntersection() { - AABBi center = new AABBi(0, 0, 0, 1, 1,1); - - AABBi frontLeft = new AABBi(-1, 1,-1, 0, 2,0); - AABBi frontRight = new AABBi(1, 1,-1, 2, 2,0); - AABBi backLeft = new AABBi(-1, -1,-1, 0, 0,0); - AABBi backRight = new AABBi(1, -1,-1, 2, 0,0); - - AABBi topFrontLeft = new AABBi(-1, 1,1, 0, 2,2); - AABBi topFrontRight = new AABBi(1, 1,1, 2, 2,2); - AABBi topBackLeft = new AABBi(-1, -1,1, 0, 0,2); - AABBi topBackRight = new AABBi(1, -1,1, 2, 0,2); - - Assert.assertTrue(center.isValid()); - - // bottom corners - Assert.assertTrue(frontLeft.isValid()); - Assert.assertTrue(frontRight.isValid()); - Assert.assertTrue(backLeft.isValid()); - Assert.assertTrue(backRight.isValid()); - - // top corners - Assert.assertTrue(topFrontLeft.isValid()); - Assert.assertTrue(topFrontRight.isValid()); - Assert.assertTrue(topBackLeft.isValid()); - Assert.assertTrue(topBackRight.isValid()); - - // test contains - // top corners intersection - Assert.assertFalse(topFrontLeft.containsAABB(center)); - Assert.assertFalse(topFrontRight.containsAABB(center)); - Assert.assertFalse(topBackLeft.containsAABB(center)); - Assert.assertFalse(topBackRight.containsAABB(center)); - - // bottom corners intersection - Assert.assertFalse(frontLeft.containsAABB(center)); - Assert.assertFalse(frontRight.containsAABB(center)); - Assert.assertFalse(backLeft.containsAABB(center)); - Assert.assertFalse(backRight.containsAABB(center)); - - // test intersection - // top corners intersection - Assert.assertTrue(topFrontLeft.intersectsAABB(center)); - Assert.assertTrue(topFrontRight.intersectsAABB(center)); - Assert.assertTrue(topBackLeft.intersectsAABB(center)); - Assert.assertTrue(topBackRight.intersectsAABB(center)); - - // bottom corners intersection - Assert.assertTrue(frontLeft.intersectsAABB(center)); - Assert.assertTrue(frontRight.intersectsAABB(center)); - Assert.assertTrue(backLeft.intersectsAABB(center)); - Assert.assertTrue(backRight.intersectsAABB(center)); - - - - } -} diff --git a/test/org/joml/test/IntersectiondTest.java b/test/org/joml/test/IntersectiondTest.java deleted file mode 100644 index b65d8cd4c..000000000 --- a/test/org/joml/test/IntersectiondTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML. - * - * 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 org.joml.test; - -import org.joml.Intersectiond; -import org.joml.Vector2d; -import org.joml.Vector3d; - -import junit.framework.TestCase; - -/** - * Tests for the {@link Intersectiond} class. - * - * @author Dmitrii Ivaniusin - */ -public class IntersectiondTest extends TestCase { - - public static void testFindClosestPointOnRectangle() { - final double EPSILON = 1E-4d; - Vector3d a = new Vector3d(0, 0, 0); - Vector3d b = new Vector3d(0, 1d, 0); - Vector3d c = new Vector3d(1d, 0, 0); - Vector3d p1 = new Vector3d(0.5d, 0.5d, 0); - Vector3d v1 = Intersectiond.findClosestPointOnRectangle(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, p1.x, p1.y, p1.z, new Vector3d()); - TestUtil.assertVector3dEquals(new Vector3d(0.5d, 0.5d, 0), v1, EPSILON); - Vector3d p2 = new Vector3d(-1d, -0.5d, 0); - Vector3d v2 = Intersectiond.findClosestPointOnRectangle(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, p2.x, p2.y, p2.z, new Vector3d()); - TestUtil.assertVector3dEquals(new Vector3d(0, 0, 0), v2, EPSILON); - Vector3d p3 = new Vector3d(-0.5d, 2d, 0); - Vector3d v3 = Intersectiond.findClosestPointOnRectangle(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, p3.x, p3.y, p3.z, new Vector3d()); - TestUtil.assertVector3dEquals(new Vector3d(0, 1d, 0), v3, EPSILON); - Vector3d p4 = new Vector3d(-1d, 0.5d, 0); - Vector3d v4 = Intersectiond.findClosestPointOnRectangle(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, p4.x, p4.y, p4.z, new Vector3d()); - TestUtil.assertVector3dEquals(new Vector3d(0, 0.5d, 0), v4, EPSILON); - Vector3d p5 = new Vector3d(0.5d, 1d, 0); - Vector3d v5 = Intersectiond.findClosestPointOnRectangle(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, p5.x, p5.y, p5.z, new Vector3d()); - TestUtil.assertVector3dEquals(new Vector3d(0.5d, 1d, 0), v5, EPSILON); - } - - public static void testLineSegmentAar() { - Vector2d p = new Vector2d(); - assertEquals(Intersectiond.ONE_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, 0, 1, 0, 0.5, -1, 1.5, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(0.5, 0.5), p, 1E-6f); - assertEquals(Intersectiond.ONE_INTERSECTION, Intersectiond.intersectLineSegmentAar(1, 0, 0, 0, 0.5, -1, 1.5, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(0.5, 0.5), p, 1E-6f); - assertEquals(Intersectiond.ONE_INTERSECTION, Intersectiond.intersectLineSegmentAar(1, 0, 2, 0, 0, -1, 2, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(1, 1), p, 1E-6f); - assertEquals(Intersectiond.INSIDE, Intersectiond.intersectLineSegmentAar(0, 0, 1, 0, -0.5, -1, 1.5, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(-0.5, 1.5), p, 1E-6f); - assertEquals(Intersectiond.INSIDE, Intersectiond.intersectLineSegmentAar(1, 0, 0, 0, -0.5, -1, 1.5, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(-0.5, 1.5), p, 1E-6f); - assertEquals(Intersectiond.OUTSIDE, Intersectiond.intersectLineSegmentAar(0, 0, 1, 0, 1.5, -1, 2.5, 1, p)); - assertEquals(Intersectiond.OUTSIDE, Intersectiond.intersectLineSegmentAar(1, 0, 0, 0, 1.5, -1, 2.5, 1, p)); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, 0, 1, 0, 0.5, -1, 0.75, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(0.5, 0.75), p, 1E-6f); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAar(1, 0, 0, 0, 0.5, -1, 0.75, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(0.25, 0.5), p, 1E-6f); - assertEquals(Intersectiond.ONE_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, 0, 1, 0, 1, -1, 2, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(1, 1), p, 1E-6f); - assertEquals(Intersectiond.ONE_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, 0, -1, 0, -2, -1, -1, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(1, 1), p, 1E-6f); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, 0, 1, 0, 0.5, -1, 1, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(0.5, 1), p, 1E-6f); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, 0, 0, 1, -0.5, 0, 0, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(0, 1), p, 1E-6f); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, 0, 1, 0, 0, 0, 1, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(0, 1), p, 1E-6f); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAar(1, 0, 0, 0, 0, 0, 1, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(0, 1), p, 1E-6f); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, 1, 0, 0, 0, 0, 1, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(0, 1), p, 1E-6f); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, 0, 0, 1, 0, 0, 1, 1, p)); - TestUtil.assertVector2dEquals(new Vector2d(0, 1), p, 1E-6f); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, -1, 0, 0, -1, -1, 0, 0, p)); - TestUtil.assertVector2dEquals(new Vector2d(0, 1), p, 1E-6f); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAar(0, -1, 0, 1, -1, -1, 0, 0, p)); - TestUtil.assertVector2dEquals(new Vector2d(0, 0.5), p, 1E-6f); - } - - public static void testLineSegmentAab() { - Vector2d p = new Vector2d(); - assertEquals(Intersectiond.ONE_INTERSECTION, Intersectiond.intersectLineSegmentAab(0, 0, 0, 0, 0, 1, -0.5, -1, 1, 0.5, 1, 2, p)); - TestUtil.assertVector2dEquals(new Vector2d(1, 1), p, 1E-6f); - assertEquals(Intersectiond.ONE_INTERSECTION, Intersectiond.intersectLineSegmentAab(1, 0, 0, 2, 0, 0, 0, -1, -1, 2, 0, 0, p)); - TestUtil.assertVector2dEquals(new Vector2d(1, 1), p, 1E-6f); - assertEquals(Intersectiond.TWO_INTERSECTION, Intersectiond.intersectLineSegmentAab(0, 0, -1, 0, 0, 0, 0, -1, -1, 1, 1, 0, p)); - TestUtil.assertVector2dEquals(new Vector2d(0, 1), p, 1E-6f); - } - -} diff --git a/test/org/joml/test/IntersectionfTest.java b/test/org/joml/test/IntersectionfTest.java deleted file mode 100644 index 0b7db4a5e..000000000 --- a/test/org/joml/test/IntersectionfTest.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2016-2020 JOML. - * - * 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 org.joml.test; - -import junit.framework.TestCase; - -import org.joml.Intersectionf; -import org.joml.Vector2f; -import org.joml.Vector3f; -import org.joml.Vector4f; -import org.joml.Math; -import org.joml.Matrix3f; - -/** - * Tests for the {@link Intersectionf} class. - * - * @author Kai Burjack - * @author Dmitrii Ivaniusin - */ -public class IntersectionfTest extends TestCase { - - public static void testIntersectRayTriangleFrontPX() { - Vector3f origin = new Vector3f(); - Vector3f dir = new Vector3f(1, 0, 0); - Vector3f v0 = new Vector3f(1, -1, -1); - Vector3f v1 = new Vector3f(1, -1, 1); - Vector3f v2 = new Vector3f(1, 1, 0); - float t = Intersectionf.intersectRayTriangleFront(origin, dir, v0, v1, v2, 0.0f); - assertEquals(1.0f, t, 0.0f); - } - - public static void testIntersectRaySphere() { - Vector3f origin = new Vector3f(); - Vector3f dir = new Vector3f(1, 0, 0); - Vector3f center = new Vector3f(5, 0, 0); - float radiusSquared = 1.0f; - Vector2f result = new Vector2f(); - boolean intersect = Intersectionf.intersectRaySphere(origin, dir, center, radiusSquared, result); - assertTrue(intersect); - assertEquals(4.0f, result.x, 1E-6f); - assertEquals(6.0f, result.y, 1E-6f); - } - - public static void testIntersectRayPlane() { - Vector3f origin = new Vector3f(); - Vector3f dir = new Vector3f(1, 1, 1); - Vector3f point = new Vector3f(2, 2, 2); - Vector3f normal = new Vector3f(-1, -1, -1); - float t = Intersectionf.intersectRayPlane(origin, dir, point, normal, 0.0f); - assertTrue(t >= 0.0f); - Vector3f intersection = new Vector3f(dir).mul(t).add(origin); - TestUtil.assertVector3fEquals(new Vector3f(2, 2, 2), intersection, 1E-6f); - normal = new Vector3f(1, 1, 1); - t = Intersectionf.intersectRayPlane(origin, dir, point, normal, 0.0f); - assertEquals(-1.0f, t, 1E-6f); - } - - public static void testNotIntersectRayPlane() { - Vector3f origin = new Vector3f(); - Vector3f dir = new Vector3f(-1, -1, -1); - Vector3f point = new Vector3f(2, 2, 2); - Vector3f normal = new Vector3f(-1, -1, -1); - float t = Intersectionf.intersectRayPlane(origin, dir, point, normal, 0.0f); - assertTrue(t == -1.0f); - } - - public static void testAabPlane() { - assertTrue(Intersectionf.testAabPlane(-1, -1, -1, 1, 1, 1, 1, 1, 1, 3.0f)); - assertFalse(Intersectionf.testAabPlane(-1, -1, -1, 1, 1, 1, 1, 1, 1, 3.1f)); - assertTrue(Intersectionf.testAabPlane(-1, -1, -1, 1, 1, 1, 1, 1, 1, -3.0f)); - assertFalse(Intersectionf.testAabPlane(-1, -1, -1, 1, 1, 1, 1, 1, 1, -3.1f)); - } - - public static void testSphereSphere() { - assertTrue(Intersectionf.testSphereSphere(0, 0, 0, 1, 0.5f, 0, 0, 1)); - Vector4f res = new Vector4f(); - assertTrue(Intersectionf.intersectSphereSphere(0, 0, 0, 1, 0.5f, 0, 0, 1, res)); - // intersection point is (0.25, 0, 0) <- middle between both spheres with equal - // radii - TestUtil.assertVector3fEquals(new Vector3f(0.25f, 0, 0), new Vector3f(res.x, res.y, res.z), 1E-6f); - // cos(a) = adjside/hyp - // cos(a) * hyp = adjside - // acos(cos(a) * hyp) = acos(adjside) - // y = sin(acos(adjside)) - float expectedRadius = (float) Math.sin(Math.acos(0.25)); - assertEquals(expectedRadius, res.w, 1E-6f); - } - - public static void testAabSphere() { - assertTrue(Intersectionf.testAabSphere(-1, -1, -1, 1, 1, 1, 2, 0, 0, 1.0f)); - } - - public static void testRayTriangleFront() { - assertTrue(Intersectionf.testRayTriangleFront(0, 0, 0, 1, 0, 0, 1, -1, -1, 1, -1, 1, 1, 1, 0, 1E-6f)); - assertFalse(Intersectionf.testRayTriangleFront(0, 0, 0, 1, 0, 0, 1, -1, 1, 1, -1, -1, 1, 1, 0, 1E-6f)); - assertFalse(Intersectionf.testRayTriangleFront(0, 0, 0, -1, 0, 0, 1, -1, -1, 1, -1, 1, 1, 1, 0, 1E-6f)); - assertFalse(Intersectionf.testRayTriangleFront(0, 0, 0, -1, 0, 0, 1, -1, 1, 1, -1, -1, 1, 1, 0, 1E-6f)); - } - - public static void testRayTriangle() { - assertTrue(Intersectionf.testRayTriangle(0, 0, 0, 1, 0, 0, 1, -1, -1, 1, -1, 1, 1, 1, 0, 1E-6f)); - assertTrue(Intersectionf.testRayTriangle(0, 0, 0, 1, 0, 0, 1, -1, 1, 1, -1, -1, 1, 1, 0, 1E-6f)); - assertFalse(Intersectionf.testRayTriangle(0, 0, 0, -1, 0, 0, 1, -1, -1, 1, -1, 1, 1, 1, 0, 1E-6f)); - assertFalse(Intersectionf.testRayTriangle(0, 0, 0, -1, 0, 0, 1, -1, 1, 1, -1, -1, 1, 1, 0, 1E-6f)); - } - - public static void testLineSegmentSphere() { - assertTrue(Intersectionf.testLineSegmentSphere(-1, 0, 0, 1, 0, 0, 0, 0, 0, 1)); - assertTrue(Intersectionf.testLineSegmentSphere(-1, 1, 0, 1, 1, 0, 0, 0, 0, 1)); - assertFalse(Intersectionf.testLineSegmentSphere(-1, 1.01f, 0, 1, 1, 0, 0, 0, 0, 1)); - assertFalse(Intersectionf.testLineSegmentSphere(1.01f, 0, 0, 2, 0, 0, 0, 0, 0, 1)); - assertFalse(Intersectionf.testLineSegmentSphere(-2, 0, 0, -1.01f, 0, 0, 0, 0, 0, 1)); - assertFalse(Intersectionf.testLineSegmentSphere(2.01f, 0, 0, 3, 0, 0, 0, 0, 0, 2 * 2)); - assertFalse(Intersectionf.testLineSegmentSphere(-3, 0, 0, -2.01f, 0, 0, 0, 0, 0, 2 * 2)); - assertTrue(Intersectionf.testLineSegmentSphere(-1, 0, 0, 1, 0, 0, -2, 0, 0, 1)); - assertTrue(Intersectionf.testLineSegmentSphere(-1, 0, 0, 1, 0, 0, 2, 0, 0, 1)); - assertFalse(Intersectionf.testLineSegmentSphere(-1, 0, 0, 1, 0, 0, -4.01f, 0, 0, 3 * 3)); - assertFalse(Intersectionf.testLineSegmentSphere(-1, 0, 0, 1, 0, 0, 4.01f, 0, 0, 3 * 3)); - } - - public static void testLineSegmentTriangle() { - assertTrue(Intersectionf.testLineSegmentTriangle(-1, 0, 0, 1, 0, 0, 1, -1, -1, 1, -1, 1, 1, 1, 0, 1E-6f)); - assertFalse(Intersectionf.testLineSegmentTriangle(-1, 0, 0, -5, 0, 0, 1, -1, -1, 1, -1, 1, 1, 1, 0, 1E-6f)); - assertFalse(Intersectionf.testLineSegmentTriangle(-5, 0, 0, -1, 0, 0, 1, -1, -1, 1, -1, 1, 1, 1, 0, 1E-6f)); - assertTrue(Intersectionf.testLineSegmentTriangle(1, 0, 0, -1, 0, 0, 1, -1, -1, 1, -1, 1, 1, 1, 0, 1E-6f)); - - assertTrue(Intersectionf.testLineSegmentTriangle(-1, 0, 0, 1, 0, 0, 1, -1, 1, 1, -1, -1, 1, 1, 0, 1E-6f)); - assertFalse(Intersectionf.testLineSegmentTriangle(-1, 0, 0, -5, 0, 0, 1, -1, 1, 1, -1, -1, 1, 1, 0, 1E-6f)); - assertFalse(Intersectionf.testLineSegmentTriangle(-5, 0, 0, -1, 0, 0, 1, -1, 1, 1, -1, -1, 1, 1, 0, 1E-6f)); - assertTrue(Intersectionf.testLineSegmentTriangle(1, 0, 0, -1, 0, 0, 1, -1, 1, 1, -1, -1, 1, 1, 0, 1E-6f)); - } - - public static void testRayAar() { - Vector2f p = new Vector2f(); - assertEquals(Intersectionf.AAR_SIDE_MINX, Intersectionf.intersectRayAar(-3, 0, 1, 0, -1, -1, 1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(-1, 0), new Vector2f(-3 + p.x * 1, 0 + p.x * 0), 1E-6f); - assertEquals(Intersectionf.AAR_SIDE_MAXX, Intersectionf.intersectRayAar(3, 0, -1, 0, -1, -1, 1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(1, 0), new Vector2f(3 + p.x * -1, 0 + p.x * 0), 1E-6f); - assertEquals(Intersectionf.AAR_SIDE_MINY, Intersectionf.intersectRayAar(0, -2, 0, 1, -1, -1, 1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, -1), new Vector2f(0 + p.x * 0, -2 + p.x * 1), 1E-6f); - assertEquals(Intersectionf.AAR_SIDE_MAXY, Intersectionf.intersectRayAar(0, 2, 0, -1, -1, -1, 1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 1), new Vector2f(0 + p.x * 0, 2 + p.x * -1), 1E-6f); - assertEquals(Intersectionf.AAR_SIDE_MINX, Intersectionf.intersectRayAar(0, 0, 0, -1, 0, -1, 1, 0, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 0), new Vector2f(0 + p.x * 0, 0 + p.x * -1), 1E-6f); - assertEquals(Intersectionf.AAR_SIDE_MINX, Intersectionf.intersectRayAar(0, 0, 0, 1, 0, 1, 1, 2, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 1), new Vector2f(0 + p.x * 0, 0 + p.x * 1), 1E-6f); - assertEquals(Intersectionf.AAR_SIDE_MINY, Intersectionf.intersectRayAar(0, 0, -1, 0, -1, 0, 0, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 0), new Vector2f(0 + p.x * -1, 0 + p.x * 0), 1E-6f); - assertEquals(Intersectionf.AAR_SIDE_MINX, Intersectionf.intersectRayAar(0, 0, 1, 0, 1, 0, 2, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(1, 0), new Vector2f(0 + p.x * 1, 0 + p.x * 0), 1E-6f); - } - - public static void testRayLineSegment() { - assertEquals(1.0f, Intersectionf.intersectRayLineSegment(0, 0, 1, 0, 1, -1, 1, 1), 1E-6f); - assertEquals(1.0f, Intersectionf.intersectRayLineSegment(0, 0, 1, 0, 1, 1, 1, -1), 1E-6f); - assertEquals(1.0f, Intersectionf.intersectRayLineSegment(0, 1, 1, 0, 1, 1, 1, -1), 1E-6f); - assertEquals(1.0f, Intersectionf.intersectRayLineSegment(0, -1, 1, 0, 1, 1, 1, -1), 1E-6f); - assertEquals(0.5f, Intersectionf.intersectRayLineSegment(0, -1, 2, 0, 1, 1, 1, -1), 1E-6f); - assertEquals(1.0f, Intersectionf.intersectRayLineSegment(0, 0, 1, 1, 0, 2, 2, 0), 1E-6f); - assertEquals(-1.0f, Intersectionf.intersectRayLineSegment(0, 0, -1, -1, 0, 2, 2, 0), 1E-6f); - assertEquals(-1.0f, Intersectionf.intersectRayLineSegment(0, 0, 1, 0, 1, 1, 1, 2), 1E-6f); - assertEquals(-1.0f, Intersectionf.intersectRayLineSegment(0, 0, 1, 0, 1, 2, 1, 1), 1E-6f); - } - - public static void testPolygonRay() { - Vector2f p = new Vector2f(); - float[] verticesXY = { 0, 0, 1, 0, 1, 1, 0, 1 }; - assertEquals(3, Intersectionf.intersectPolygonRay(verticesXY, -1, 0.5f, 1, 0, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 0.5f), p, 1E-6f); - assertEquals(0, Intersectionf.intersectPolygonRay(verticesXY, 0.1f, -0.5f, 0, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0.1f, 0), p, 1E-6f); - assertEquals(-1, Intersectionf.intersectPolygonRay(verticesXY, 0.1f, -1.1f, 1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0.1f, 0), p, 1E-6f); - assertEquals(-1, Intersectionf.intersectPolygonRay(verticesXY, 1.1f, 0f, -1, -1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0.1f, 0), p, 1E-6f); - assertEquals(-1, Intersectionf.intersectPolygonRay(verticesXY, 1.1f, 1, 0, -1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0.1f, 0), p, 1E-6f); - assertEquals(-1, Intersectionf.intersectPolygonRay(verticesXY, -0.1f, 0, 1, -1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0.1f, 0), p, 1E-6f); - } - - public static void testLineSegmentAar() { - Vector2f p = new Vector2f(); - assertEquals(Intersectionf.ONE_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, 0, 1, 0, 0.5f, -1, 1.5f, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0.5f, 0.5f), p, 1E-6f); - assertEquals(Intersectionf.ONE_INTERSECTION, Intersectionf.intersectLineSegmentAar(1, 0, 0, 0, 0.5f, -1, 1.5f, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0.5f, 0.5f), p, 1E-6f); - assertEquals(Intersectionf.ONE_INTERSECTION, Intersectionf.intersectLineSegmentAar(1, 0, 2, 0, 0, -1, 2, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(1, 1), p, 1E-6f); - assertEquals(Intersectionf.INSIDE, Intersectionf.intersectLineSegmentAar(0, 0, 1, 0, -0.5f, -1, 1.5f, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(-0.5f, 1.5f), p, 1E-6f); - assertEquals(Intersectionf.INSIDE, Intersectionf.intersectLineSegmentAar(1, 0, 0, 0, -0.5f, -1, 1.5f, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(-0.5f, 1.5f), p, 1E-6f); - assertEquals(Intersectionf.OUTSIDE, Intersectionf.intersectLineSegmentAar(0, 0, 1, 0, 1.5f, -1, 2.5f, 1, p)); - assertEquals(Intersectionf.OUTSIDE, Intersectionf.intersectLineSegmentAar(1, 0, 0, 0, 1.5f, -1, 2.5f, 1, p)); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, 0, 1, 0, 0.5f, -1, 0.75f, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0.5f, 0.75f), p, 1E-6f); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAar(1, 0, 0, 0, 0.5f, -1, 0.75f, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0.25f, 0.5f), p, 1E-6f); - assertEquals(Intersectionf.ONE_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, 0, 1, 0, 1, -1, 2, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(1, 1), p, 1E-6f); - assertEquals(Intersectionf.ONE_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, 0, -1, 0, -2, -1, -1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(1, 1), p, 1E-6f); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, 0, 1, 0, 0.5f, -1, 1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0.5f, 1), p, 1E-6f); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, 0, 0, 1, -0.5f, 0, 0, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 1), p, 1E-6f); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, 0, 1, 0, 0, 0, 1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 1), p, 1E-6f); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAar(1, 0, 0, 0, 0, 0, 1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 1), p, 1E-6f); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, 1, 0, 0, 0, 0, 1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 1), p, 1E-6f); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, 0, 0, 1, 0, 0, 1, 1, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 1), p, 1E-6f); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, -1, 0, 0, -1, -1, 0, 0, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 1), p, 1E-6f); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAar(0, -1, 0, 1, -1, -1, 0, 0, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 0.5f), p, 1E-6f); - } - - public static void testLineSegmentAab() { - Vector2f p = new Vector2f(); - assertEquals(Intersectionf.ONE_INTERSECTION, Intersectionf.intersectLineSegmentAab(0, 0, 0, 0, 0, 1, -0.5f, -1, 1, 0.5f, 1, 2, p)); - TestUtil.assertVector2fEquals(new Vector2f(1, 1), p, 1E-6f); - assertEquals(Intersectionf.ONE_INTERSECTION, Intersectionf.intersectLineSegmentAab(1, 0, 0, 2, 0, 0, 0, -1, -1, 2, 0, 0, p)); - TestUtil.assertVector2fEquals(new Vector2f(1, 1), p, 1E-6f); - assertEquals(Intersectionf.TWO_INTERSECTION, Intersectionf.intersectLineSegmentAab(0, 0, -1, 0, 0, 0, 0, -1, -1, 1, 1, 0, p)); - TestUtil.assertVector2fEquals(new Vector2f(0, 1), p, 1E-6f); - } - - public static void testObObTipToTip() { - Vector3f c0 = new Vector3f(); - float EPSILON = 1E-4f; - /* Position the second box so that they "almost" intersect */ - float a = (float) Math.sqrt(1 + 1) + (float) Math.sqrt(1 + 1); - Vector3f c1 = new Vector3f(a + EPSILON, 0, 0); - Matrix3f m = new Matrix3f().rotateXYZ(0, (float) Math.toRadians(45.0), 0); - Vector3f ux0 = m.getColumn(0, new Vector3f()); - Vector3f uy0 = m.getColumn(1, new Vector3f()); - Vector3f uz0 = m.getColumn(2, new Vector3f()); - Vector3f ux1 = m.getColumn(0, new Vector3f()); - Vector3f uy1 = m.getColumn(1, new Vector3f()); - Vector3f uz1 = m.getColumn(2, new Vector3f()); - Vector3f hs = new Vector3f(1); - boolean intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs, c1, ux1, uy1, uz1, hs); - assertFalse(intersects); // <- they do not intersect - /* Position the second box so that they do intersect */ - c1 = new Vector3f((float) Math.sqrt(2) * 2 - EPSILON, 0, 0); - intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs, c1, ux1, uy1, uz1, hs); - assertTrue(intersects); // <- they do intersect - } - - public static void testObOb45Slide() { - Vector3f c0 = new Vector3f(); - float EPSILON = 1E-4f; - /* - * Position the second box right over the first one so that they "almost" intersect/slide - */ - // 2a^2 = c^2 = (2+0.5)^2 <-- length of a (box A + box B) squared - // a^2 = (2+0.5)^2/2 -> a = 1.5/sqrt(2) - float a = (float) (2.5 / Math.sqrt(2)); - Vector3f c1 = new Vector3f(-a - EPSILON, a + EPSILON, 0); - Matrix3f m = new Matrix3f().rotateZ((float) Math.toRadians(45.0)); - Vector3f ux0 = m.getColumn(0, new Vector3f()); - Vector3f uy0 = m.getColumn(1, new Vector3f()); - Vector3f uz0 = m.getColumn(2, new Vector3f()); - Vector3f ux1 = m.getColumn(0, new Vector3f()); - Vector3f uy1 = m.getColumn(1, new Vector3f()); - Vector3f uz1 = m.getColumn(2, new Vector3f()); - Vector3f hs0 = new Vector3f(2); - Vector3f hs1 = new Vector3f(0.5f); - boolean intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs0, c1, ux1, uy1, uz1, hs1); - assertFalse(intersects); // <- they do not intersect - c1 = new Vector3f(-a + EPSILON, a - EPSILON, 0); - intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs0, c1, ux1, uy1, uz1, hs1); - assertTrue(intersects); // <- they do intersect - c1 = new Vector3f(-a - EPSILON, -a - EPSILON, 0); - intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs0, c1, ux1, uy1, uz1, hs1); - assertFalse(intersects); // <- they do intersect - c1 = new Vector3f(-a + EPSILON, -a + EPSILON, 0); - intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs0, c1, ux1, uy1, uz1, hs1); - assertTrue(intersects); // <- they do intersect - c1 = new Vector3f(a + EPSILON, -a - EPSILON, 0); - intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs0, c1, ux1, uy1, uz1, hs1); - assertFalse(intersects); // <- they do intersect - c1 = new Vector3f(a - EPSILON, -a + EPSILON, 0); - intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs0, c1, ux1, uy1, uz1, hs1); - assertTrue(intersects); // <- they do intersect - c1 = new Vector3f(a + EPSILON, a + EPSILON, 0); - intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs0, c1, ux1, uy1, uz1, hs1); - assertFalse(intersects); // <- they do intersect - c1 = new Vector3f(a - EPSILON, a - EPSILON, 0); - intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs0, c1, ux1, uy1, uz1, hs1); - assertTrue(intersects); // <- they do intersect - } - - public static void testObOb() { - float a = (float) (Math.sqrt(2.0*2.0 + 2.0*2.0) + Math.sqrt(0.5*0.5 + 0.5*0.5)); - float EPSILON = 1E-4f; - Vector3f c0 = new Vector3f(0, 0, a - EPSILON); - Vector3f hs0 = new Vector3f(0.5f, 0.5f, 0.5f); - Vector3f c1 = new Vector3f(0, 0, 0); - Vector3f hs1 = new Vector3f(2, 0.5f, 2); - Matrix3f m = new Matrix3f().rotateY((float) Math.toRadians(45)); - Vector3f ux0 = m.getColumn(0, new Vector3f()); - Vector3f uy0 = m.getColumn(1, new Vector3f()); - Vector3f uz0 = m.getColumn(2, new Vector3f()); - Vector3f ux1 = m.getColumn(0, new Vector3f()); - Vector3f uy1 = m.getColumn(1, new Vector3f()); - Vector3f uz1 = m.getColumn(2, new Vector3f()); - boolean intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs0, c1, ux1, uy1, uz1, hs1); - assertTrue(intersects); // <- they DO intersect - c0 = new Vector3f(0, 0, a + EPSILON); - intersects = Intersectionf.testObOb(c0, ux0, uy0, uz0, hs0, c1, ux1, uy1, uz1, hs1); - assertFalse(intersects); // <- they do not intersect - } - - public static void testFindClosestPointOnRectangle() { - final float EPSILON = 1E-4f; - Vector3f a = new Vector3f(0, 0, 0); - Vector3f b = new Vector3f(0, 1f, 0); - Vector3f c = new Vector3f(1f, 0, 0); - Vector3f p1 = new Vector3f(0.5f, 0.5f, 0); - Vector3f v1 = Intersectionf.findClosestPointOnRectangle(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, p1.x, p1.y, p1.z, new Vector3f()); - TestUtil.assertVector3fEquals(new Vector3f(0.5f, 0.5f, 0), v1, EPSILON); - Vector3f p2 = new Vector3f(-1f, -0.5f, 0); - Vector3f v2 = Intersectionf.findClosestPointOnRectangle(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, p2.x, p2.y, p2.z, new Vector3f()); - TestUtil.assertVector3fEquals(new Vector3f(0, 0, 0), v2, EPSILON); - Vector3f p3 = new Vector3f(-0.5f, 2f, 0); - Vector3f v3 = Intersectionf.findClosestPointOnRectangle(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, p3.x, p3.y, p3.z, new Vector3f()); - TestUtil.assertVector3fEquals(new Vector3f(0, 1f, 0), v3, EPSILON); - Vector3f p4 = new Vector3f(-1f, 0.5f, 0); - Vector3f v4 = Intersectionf.findClosestPointOnRectangle(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, p4.x, p4.y, p4.z, new Vector3f()); - TestUtil.assertVector3fEquals(new Vector3f(0, 0.5f, 0), v4, EPSILON); - Vector3f p5 = new Vector3f(0.5f, 1f, 0); - Vector3f v5 = Intersectionf.findClosestPointOnRectangle(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, p5.x, p5.y, p5.z, new Vector3f()); - TestUtil.assertVector3fEquals(new Vector3f(0.5f, 1f, 0), v5, EPSILON); - } - -} diff --git a/test/org/joml/test/RectangleScaleTest.java b/test/org/joml/test/RectangleScaleTest.java deleted file mode 100644 index 4f56e51d2..000000000 --- a/test/org/joml/test/RectangleScaleTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML. - * - * 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 org.joml.test; - -import junit.framework.TestCase; - -import org.joml.Rectangled; -import org.joml.Rectanglef; -import org.joml.Rectanglei; - -/** - * Tests of {@link Rectangled} scaling functions. - */ -public class RectangleScaleTest extends TestCase { - - public static void testNonUniformAnchoredScalingNoDestination () { - Rectangled testA = new Rectangled (-1, -1, +1, +1); - Rectanglef testB = new Rectanglef (-1, -1, +1, +1); - Rectanglei testC = new Rectanglei (-1, -1, +1, +1); - - assertEquals (new Rectangled (-1, -1, +3, +5), testA.scale (2, 3, -1, -1)); - assertEquals (new Rectanglef (-1, -1, +3, +5), testB.scale (2, 3, -1, -1)); - assertEquals (new Rectanglei (-1, -1, +3, +5), testC.scale (2, 3, -1, -1)); - } - - public static void testNonUniformAnchoredScalingWithDestination () { - Rectangled testASubject = new Rectangled (-1, -1, +1, +1); - Rectangled testATarget = new Rectangled ( 0, 0, 0, 0); - - Rectanglef testBSubject = new Rectanglef (-1, -1, +1, +1); - Rectanglef testBTarget = new Rectanglef ( 0, 0, 0, 0); - - Rectanglei testCSubject = new Rectanglei (-1, -1, +1, +1); - Rectanglei testCTarget = new Rectanglei ( 0, 0, 0, 0); - - assertEquals (new Rectangled (-1, -1, +3, +5), testASubject.scale (2, 3, -1, -1, testATarget)); - assertEquals (new Rectanglef (-1, -1, +3, +5), testBSubject.scale (2, 3, -1, -1, testBTarget)); - assertEquals (new Rectanglei (-1, -1, +3, +5), testCSubject.scale (2, 3, -1, -1, testCTarget)); - } -} diff --git a/test/org/joml/test/RectangledTest.java b/test/org/joml/test/RectangledTest.java deleted file mode 100644 index 51bb4fb3b..000000000 --- a/test/org/joml/test/RectangledTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML. - * - * 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 org.joml.test; - -import junit.framework.Assert; -import junit.framework.TestCase; -import org.joml.Rectangled; -import org.joml.Vector2d; - -public class RectangledTest extends TestCase { - - public void testRectangleContainsPoints() { - Rectangled rect = new Rectangled(0, 0, 3, 3); - - Assert.assertTrue(rect.isValid()); - Assert.assertFalse(rect.containsPoint(new Vector2d(0, 0))); - Assert.assertTrue(rect.containsPoint(new Vector2d(1, 1))); - Assert.assertFalse(rect.containsPoint(new Vector2d(-1, -1))); - Assert.assertFalse(rect.containsPoint(new Vector2d(4, 4))); - } - - public void testRectangleIntersection() { - Rectangled first = new Rectangled(0, 0, 3, 3); - Rectangled second = new Rectangled(-1, -1, 2, 2); - - // is valid - Assert.assertTrue(first.isValid()); - Assert.assertTrue(second.isValid()); - - Assert.assertFalse(first.containsRectangle(second)); - Assert.assertFalse(second.containsRectangle(first)); - - Assert.assertTrue(first.intersectsRectangle(second)); - Assert.assertTrue(second.intersectsRectangle(first)); - Assert.assertEquals(first.intersection(second, new Rectangled()), new Rectangled(0, 0, 2, 2)); - - } - - public void testRectangleContains() { - Rectangled first = new Rectangled(-1, -1, 2, 2); - Rectangled second = new Rectangled(0, 0, 1, 1); - Assert.assertTrue(first.containsRectangle(second)); - Assert.assertFalse(second.containsRectangle(first)); - - Assert.assertTrue(first.intersectsRectangle(second)); - Assert.assertTrue(second.intersectsRectangle(first)); - - Assert.assertEquals(first.intersection(second, new Rectangled()), new Rectangled(0, 0, 1, 1)); - } - - public void testZeroSizeRectangle() { - Rectangled rect = new Rectangled(0, 0, 0, 0); - Assert.assertFalse(rect.isValid()); - } -} diff --git a/test/org/joml/test/RectanglefTest.java b/test/org/joml/test/RectanglefTest.java deleted file mode 100644 index ba100c296..000000000 --- a/test/org/joml/test/RectanglefTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML. - * - * 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 org.joml.test; - -import junit.framework.Assert; -import junit.framework.TestCase; -import org.joml.Rectanglef; -import org.joml.Vector2d; -import org.joml.Vector2f; - -/** - * Tests for the {@link Rectanglef} class. - * - * @author Michael Pollind - */ -public class RectanglefTest extends TestCase { - public void testRectangleContainsPoints() { - Rectanglef rect = new Rectanglef(0, 0, 3, 3); - - Assert.assertTrue(rect.isValid()); - Assert.assertFalse(rect.containsPoint(new Vector2f(0, 0))); - Assert.assertTrue(rect.containsPoint(new Vector2f(1, 1))); - Assert.assertFalse(rect.containsPoint(new Vector2f(-1, -1))); - Assert.assertFalse(rect.containsPoint(new Vector2f(4, 4))); - } - - public void testRectangleIntersection() { - Rectanglef first = new Rectanglef(0, 0, 3, 3); - Rectanglef second = new Rectanglef(-1, -1, 2, 2); - - // is valid - Assert.assertTrue(first.isValid()); - Assert.assertTrue(second.isValid()); - - Assert.assertFalse(first.containsRectangle(second)); - Assert.assertFalse(second.containsRectangle(first)); - - Assert.assertTrue(first.intersectsRectangle(second)); - Assert.assertTrue(second.intersectsRectangle(first)); - Assert.assertEquals(first.intersection(second, new Rectanglef()), new Rectanglef(0, 0, 2, 2)); - - } - - public void testRectangleContains() { - Rectanglef first = new Rectanglef(-1, -1, 2, 2); - Rectanglef second = new Rectanglef(0, 0, 1, 1); - Assert.assertTrue(first.containsRectangle(second)); - Assert.assertFalse(second.containsRectangle(first)); - - Assert.assertTrue(first.intersectsRectangle(second)); - Assert.assertTrue(second.intersectsRectangle(first)); - - Assert.assertEquals(first.intersection(second, new Rectanglef()), new Rectanglef(0, 0, 1, 1)); - } - - public void testZeroSizeRectangle() { - Rectanglef rect = new Rectanglef(0, 0, 0, 0); - Assert.assertFalse(rect.isValid()); - } - -} diff --git a/test/org/joml/test/RectangleiTest.java b/test/org/joml/test/RectangleiTest.java deleted file mode 100644 index 47971ee50..000000000 --- a/test/org/joml/test/RectangleiTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2020 JOML. - * - * 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 org.joml.test; - -import junit.framework.Assert; -import junit.framework.TestCase; -import org.joml.Rectanglei; -import org.joml.Vector2d; -import org.joml.Vector2f; -import org.joml.Vector2i; - -/** - * Tests for the {@link Rectanglei} class. - * - * @author Michael Pollind - */ -public class RectangleiTest extends TestCase { - - public void testRectangleContainsPoints() { - Rectanglei rect = new Rectanglei(0, 0, 3, 3); - - Assert.assertTrue(rect.isValid()); - Assert.assertFalse(rect.containsPoint(new Vector2i(0, 0))); - Assert.assertTrue(rect.containsPoint(new Vector2i(1, 1))); - Assert.assertFalse(rect.containsPoint(new Vector2i(-1, -1))); - Assert.assertFalse(rect.containsPoint(new Vector2i(4, 4))); - } - - public void testRectangleIntersection() { - Rectanglei first = new Rectanglei(0, 0, 3, 3); - Rectanglei second = new Rectanglei(-1, -1, 2, 2); - - // is valid - Assert.assertTrue(first.isValid()); - Assert.assertTrue(second.isValid()); - - Assert.assertFalse(first.containsRectangle(second)); - Assert.assertFalse(second.containsRectangle(first)); - - Assert.assertTrue(first.intersectsRectangle(second)); - Assert.assertTrue(second.intersectsRectangle(first)); - Assert.assertEquals(first.intersection(second, new Rectanglei()), new Rectanglei(0, 0, 2, 2)); - - } - - public void testRectangleiEdgeIntersection() { - Rectanglei center = new Rectanglei(0, 0, 1, 1); - Rectanglei right = new Rectanglei(1, 0, 2, 1); - Rectanglei left = new Rectanglei(-1, 0, 0, 1); - Rectanglei top = new Rectanglei(0, 1, 1, 2); - Rectanglei bottom = new Rectanglei(0, -1, 1, 0); - - Assert.assertTrue(center.isValid()); - Assert.assertTrue(right.isValid()); - Assert.assertTrue(left.isValid()); - Assert.assertTrue(top.isValid()); - Assert.assertTrue(bottom.isValid()); - - Assert.assertFalse(center.containsRectangle(right)); - Assert.assertFalse(center.containsRectangle(left)); - Assert.assertFalse(center.containsRectangle(top)); - Assert.assertFalse(center.containsRectangle(bottom)); - - Assert.assertTrue(center.intersectsRectangle(right)); - Assert.assertTrue(center.intersectsRectangle(left)); - Assert.assertTrue(center.intersectsRectangle(top)); - Assert.assertTrue(center.intersectsRectangle(bottom)); - - Assert.assertTrue(right.intersectsRectangle(center)); - Assert.assertTrue(left.intersectsRectangle(center)); - Assert.assertTrue(top.intersectsRectangle(center)); - Assert.assertTrue(bottom.intersectsRectangle(center)); - } - - public void testRectangleiContainsPoint() { - Rectanglei center = new Rectanglei(0, 0, 3, 3); - - Assert.assertTrue(center.isValid()); - - Assert.assertFalse(center.containsPoint(0, 0)); - Assert.assertFalse(center.containsPoint(1, 0)); - Assert.assertFalse(center.containsPoint(0, 1)); - Assert.assertTrue(center.containsPoint(1, 1)); - } - - public void testRectangleContains() { - Rectanglei first = new Rectanglei(-1, -1, 2, 2); - Rectanglei second = new Rectanglei(0, 0, 1, 1); - Assert.assertTrue(first.containsRectangle(second)); - Assert.assertFalse(second.containsRectangle(first)); - - Assert.assertTrue(first.intersectsRectangle(second)); - Assert.assertTrue(second.intersectsRectangle(first)); - - Assert.assertEquals(first.intersection(second, new Rectanglei()), new Rectanglei(0, 0, 1, 1)); - } - - public void testZeroSizeRectangle() { - Rectanglei rect = new Rectanglei(0, 0, 0, 0); - Assert.assertFalse(rect.isValid()); - } -}