Repack JOML

This commit is contained in:
Jozufozu 2021-12-24 02:21:59 -08:00
parent f4cdbb73f7
commit 6c40b8be0b
83 changed files with 155794 additions and 2 deletions

View file

@ -101,8 +101,6 @@ repositories {
dependencies { dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
//implementation 'org.joml:joml:1.10.1'
// https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497 // https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497
// Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings // Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings
// This allows 'Settings > Build, Execution, and Deployment > Build Tools > Gradle > Build and run using' set to IntelliJ to work correctly // This allows 'Settings > Build, Execution, and Deployment > Build Tools > Gradle > Build and run using' set to IntelliJ to work correctly

View file

@ -0,0 +1,906 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.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 rotation of a given radians about an axis represented as an
* unit 3D vector.
* <p>
* This class uses double-precision components.
*
* @author Kai Burjack
*/
public class AxisAngle4d implements Externalizable, Cloneable {
private static final long serialVersionUID = 1L;
/**
* The angle in radians.
*/
public double angle;
/**
* The x-component of the rotation axis.
*/
public double x;
/**
* The y-component of the rotation axis.
*/
public double y;
/**
* The z-component of the rotation axis.
*/
public double z;
/**
* Create a new {@link AxisAngle4d} with zero rotation about <code>(0, 0, 1)</code>.
*/
public AxisAngle4d() {
z = 1.0;
}
/**
* Create a new {@link AxisAngle4d} with the same values of <code>a</code>.
*
* @param a
* the AngleAxis4d to copy the values from
*/
public AxisAngle4d(AxisAngle4d a) {
x = a.x;
y = a.y;
z = a.z;
angle = (a.angle < 0.0 ? Math.PI + Math.PI + a.angle % (Math.PI + Math.PI) : a.angle) % (Math.PI + Math.PI);
}
/**
* Create a new {@link AxisAngle4d} with the same values of <code>a</code>.
*
* @param a
* the AngleAxis4f to copy the values from
*/
public AxisAngle4d(AxisAngle4f a) {
x = a.x;
y = a.y;
z = a.z;
angle = (a.angle < 0.0 ? Math.PI + Math.PI + a.angle % (Math.PI + Math.PI) : a.angle) % (Math.PI + Math.PI);
}
/**
* Create a new {@link AxisAngle4d} from the given {@link Quaternionfc}.
* <p>
* Reference: <a href=
* "http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/"
* >http://www.euclideanspace.com</a>
*
* @param q
* the quaternion from which to create the new AngleAxis4f
*/
public AxisAngle4d(Quaternionfc q) {
float acos = Math.safeAcos(q.w());
float invSqrt = Math.invsqrt(1.0f - q.w() * q.w());
if (Float.isInfinite(invSqrt)) {
this.x = 0.0;
this.y = 0.0;
this.z = 1.0;
} else {
this.x = q.x() * invSqrt;
this.y = q.y() * invSqrt;
this.z = q.z() * invSqrt;
}
this.angle = acos + acos;
}
/**
* Create a new {@link AxisAngle4d} from the given {@link Quaterniondc}.
* <p>
* Reference: <a href=
* "http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/"
* >http://www.euclideanspace.com</a>
*
* @param q
* the quaternion from which to create the new AngleAxis4d
*/
public AxisAngle4d(Quaterniondc q) {
double acos = Math.safeAcos(q.w());
double invSqrt = Math.invsqrt(1.0 - q.w() * q.w());
if (Double.isInfinite(invSqrt)) {
this.x = 0.0;
this.y = 0.0;
this.z = 1.0;
} else {
this.x = q.x() * invSqrt;
this.y = q.y() * invSqrt;
this.z = q.z() * invSqrt;
}
this.angle = acos + acos;
}
/**
* Create a new {@link AxisAngle4d} with the given values.
*
* @param angle
* the angle in radians
* @param x
* the x-coordinate of the rotation axis
* @param y
* the y-coordinate of the rotation axis
* @param z
* the z-coordinate of the rotation axis
*/
public AxisAngle4d(double angle, double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
this.angle = (angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI);
}
/**
* Create a new {@link AxisAngle4d} with the given values.
*
* @param angle the angle in radians
* @param v the rotation axis as a {@link Vector3dc}
*/
public AxisAngle4d(double angle, Vector3dc v) {
this(angle, v.x(), v.y(), v.z());
}
/**
* Create a new {@link AxisAngle4d} with the given values.
*
* @param angle the angle in radians
* @param v the rotation axis as a {@link Vector3f}
*/
public AxisAngle4d(double angle, Vector3f v) {
this(angle, v.x, v.y, v.z);
}
/**
* Set this {@link AxisAngle4d} to the values of <code>a</code>.
*
* @param a
* the AngleAxis4f to copy the values from
* @return this
*/
public AxisAngle4d set(AxisAngle4d a) {
x = a.x;
y = a.y;
z = a.z;
angle = (a.angle < 0.0 ? Math.PI + Math.PI + a.angle % (Math.PI + Math.PI) : a.angle) % (Math.PI + Math.PI);
return this;
}
/**
* Set this {@link AxisAngle4d} to the values of <code>a</code>.
*
* @param a
* the AngleAxis4f to copy the values from
* @return this
*/
public AxisAngle4d set(AxisAngle4f a) {
x = a.x;
y = a.y;
z = a.z;
angle = (a.angle < 0.0 ? Math.PI + Math.PI + a.angle % (Math.PI + Math.PI) : a.angle) % (Math.PI + Math.PI);
return this;
}
/**
* Set this {@link AxisAngle4d} to the given values.
*
* @param angle
* the angle in radians
* @param x
* the x-coordinate of the rotation axis
* @param y
* the y-coordinate of the rotation axis
* @param z
* the z-coordinate of the rotation axis
* @return this
*/
public AxisAngle4d set(double angle, double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
this.angle = (angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI);
return this;
}
/**
* Set this {@link AxisAngle4d} to the given values.
*
* @param angle
* the angle in radians
* @param v
* the rotation axis as a {@link Vector3dc}
* @return this
*/
public AxisAngle4d set(double angle, Vector3dc v) {
return set(angle, v.x(), v.y(), v.z());
}
/**
* Set this {@link AxisAngle4d} to the given values.
*
* @param angle
* the angle in radians
* @param v
* the rotation axis as a {@link Vector3f}
* @return this
*/
public AxisAngle4d set(double angle, Vector3f v) {
return set(angle, v.x, v.y, v.z);
}
/**
* Set this {@link AxisAngle4d} to be equivalent to the given
* {@link Quaternionfc}.
*
* @param q
* the quaternion to set this AngleAxis4d from
* @return this
*/
public AxisAngle4d set(Quaternionfc q) {
float acos = Math.safeAcos(q.w());
float invSqrt = Math.invsqrt(1.0f - q.w() * q.w());
if (Float.isInfinite(invSqrt)) {
this.x = 0.0;
this.y = 0.0;
this.z = 1.0;
} else {
this.x = q.x() * invSqrt;
this.y = q.y() * invSqrt;
this.z = q.z() * invSqrt;
}
this.angle = acos + acos;
return this;
}
/**
* Set this {@link AxisAngle4d} to be equivalent to the given
* {@link Quaterniondc}.
*
* @param q
* the quaternion to set this AngleAxis4d from
* @return this
*/
public AxisAngle4d set(Quaterniondc q) {
double acos = Math.safeAcos(q.w());
double invSqrt = Math.invsqrt(1.0f - q.w() * q.w());
if (Double.isInfinite(invSqrt)) {
this.x = 0.0;
this.y = 0.0;
this.z = 1.0;
} else {
this.x = q.x() * invSqrt;
this.y = q.y() * invSqrt;
this.z = q.z() * invSqrt;
}
this.angle = acos + acos;
return this;
}
/**
* Set this {@link AxisAngle4d} to be equivalent to the rotation
* of the given {@link Matrix3fc}.
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/">http://www.euclideanspace.com</a>
*
* @param m
* the Matrix3fc to set this AngleAxis4d from
* @return this
*/
public AxisAngle4d set(Matrix3fc m) {
double nm00 = m.m00(), nm01 = m.m01(), nm02 = m.m02();
double nm10 = m.m10(), nm11 = m.m11(), nm12 = m.m12();
double nm20 = m.m20(), nm21 = m.m21(), nm22 = m.m22();
double lenX = Math.invsqrt(m.m00() * m.m00() + m.m01() * m.m01() + m.m02() * m.m02());
double lenY = Math.invsqrt(m.m10() * m.m10() + m.m11() * m.m11() + m.m12() * m.m12());
double lenZ = Math.invsqrt(m.m20() * m.m20() + m.m21() * m.m21() + m.m22() * m.m22());
nm00 *= lenX; nm01 *= lenX; nm02 *= lenX;
nm10 *= lenY; nm11 *= lenY; nm12 *= lenY;
nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ;
double epsilon = 1E-4, epsilon2 = 1E-3;
if (Math.abs(nm10 - nm01) < epsilon && Math.abs(nm20 - nm02) < epsilon && Math.abs(nm21 - nm12) < epsilon) {
if (Math.abs(nm10 + nm01) < epsilon2 && Math.abs(nm20 + nm02) < epsilon2 && Math.abs(nm21 + nm12) < epsilon2
&& Math.abs(nm00 + nm11 + nm22 - 3) < epsilon2) {
x = 0;
y = 0;
z = 1;
angle = 0;
return this;
}
angle = Math.PI;
double xx = (nm00 + 1) / 2;
double yy = (nm11 + 1) / 2;
double zz = (nm22 + 1) / 2;
double xy = (nm10 + nm01) / 4;
double xz = (nm20 + nm02) / 4;
double yz = (nm21 + nm12) / 4;
if ((xx > yy) && (xx > zz)) {
x = Math.sqrt(xx);
y = xy / x;
z = xz / x;
} else if (yy > zz) {
y = Math.sqrt(yy);
x = xy / y;
z = yz / y;
} else {
z = Math.sqrt(zz);
x = xz / z;
y = yz / z;
}
return this;
}
double s = Math.sqrt((nm12 - nm21) * (nm12 - nm21) + (nm20 - nm02) * (nm20 - nm02) + (nm01 - nm10) * (nm01 - nm10));
angle = Math.safeAcos((nm00 + nm11 + nm22 - 1) / 2);
x = (nm12 - nm21) / s;
y = (nm20 - nm02) / s;
z = (nm01 - nm10) / s;
return this;
}
/**
* Set this {@link AxisAngle4d} to be equivalent to the rotation
* of the given {@link Matrix3dc}.
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/">http://www.euclideanspace.com</a>
*
* @param m
* the Matrix3dc to set this AngleAxis4d from
* @return this
*/
public AxisAngle4d set(Matrix3dc m) {
double nm00 = m.m00(), nm01 = m.m01(), nm02 = m.m02();
double nm10 = m.m10(), nm11 = m.m11(), nm12 = m.m12();
double nm20 = m.m20(), nm21 = m.m21(), nm22 = m.m22();
double lenX = Math.invsqrt(m.m00() * m.m00() + m.m01() * m.m01() + m.m02() * m.m02());
double lenY = Math.invsqrt(m.m10() * m.m10() + m.m11() * m.m11() + m.m12() * m.m12());
double lenZ = Math.invsqrt(m.m20() * m.m20() + m.m21() * m.m21() + m.m22() * m.m22());
nm00 *= lenX; nm01 *= lenX; nm02 *= lenX;
nm10 *= lenY; nm11 *= lenY; nm12 *= lenY;
nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ;
double epsilon = 1E-4, epsilon2 = 1E-3;
if (Math.abs(nm10 - nm01) < epsilon && Math.abs(nm20 - nm02) < epsilon && Math.abs(nm21 - nm12) < epsilon) {
if (Math.abs(nm10 + nm01) < epsilon2 && Math.abs(nm20 + nm02) < epsilon2 && Math.abs(nm21 + nm12) < epsilon2
&& Math.abs(nm00 + nm11 + nm22 - 3) < epsilon2) {
x = 0;
y = 0;
z = 1;
angle = 0;
return this;
}
angle = Math.PI;
double xx = (nm00 + 1) / 2;
double yy = (nm11 + 1) / 2;
double zz = (nm22 + 1) / 2;
double xy = (nm10 + nm01) / 4;
double xz = (nm20 + nm02) / 4;
double yz = (nm21 + nm12) / 4;
if ((xx > yy) && (xx > zz)) {
x = Math.sqrt(xx);
y = xy / x;
z = xz / x;
} else if (yy > zz) {
y = Math.sqrt(yy);
x = xy / y;
z = yz / y;
} else {
z = Math.sqrt(zz);
x = xz / z;
y = yz / z;
}
return this;
}
double s = Math.sqrt((nm12 - nm21) * (nm12 - nm21) + (nm20 - nm02) * (nm20 - nm02) + (nm01 - nm10) * (nm01 - nm10));
angle = Math.safeAcos((nm00 + nm11 + nm22 - 1) / 2);
x = (nm12 - nm21) / s;
y = (nm20 - nm02) / s;
z = (nm01 - nm10) / s;
return this;
}
/**
* Set this {@link AxisAngle4d} to be equivalent to the rotational component
* of the given {@link Matrix4fc}.
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/">http://www.euclideanspace.com</a>
*
* @param m
* the Matrix4fc to set this AngleAxis4d from
* @return this
*/
public AxisAngle4d set(Matrix4fc m) {
double nm00 = m.m00(), nm01 = m.m01(), nm02 = m.m02();
double nm10 = m.m10(), nm11 = m.m11(), nm12 = m.m12();
double nm20 = m.m20(), nm21 = m.m21(), nm22 = m.m22();
double lenX = Math.invsqrt(m.m00() * m.m00() + m.m01() * m.m01() + m.m02() * m.m02());
double lenY = Math.invsqrt(m.m10() * m.m10() + m.m11() * m.m11() + m.m12() * m.m12());
double lenZ = Math.invsqrt(m.m20() * m.m20() + m.m21() * m.m21() + m.m22() * m.m22());
nm00 *= lenX; nm01 *= lenX; nm02 *= lenX;
nm10 *= lenY; nm11 *= lenY; nm12 *= lenY;
nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ;
double epsilon = 1E-4, epsilon2 = 1E-3;
if (Math.abs(nm10 - nm01) < epsilon && Math.abs(nm20 - nm02) < epsilon && Math.abs(nm21 - nm12) < epsilon) {
if (Math.abs(nm10 + nm01) < epsilon2 && Math.abs(nm20 + nm02) < epsilon2 && Math.abs(nm21 + nm12) < epsilon2
&& Math.abs(nm00 + nm11 + nm22 - 3) < epsilon2) {
x = 0;
y = 0;
z = 1;
angle = 0;
return this;
}
angle = Math.PI;
double xx = (nm00 + 1) / 2;
double yy = (nm11 + 1) / 2;
double zz = (nm22 + 1) / 2;
double xy = (nm10 + nm01) / 4;
double xz = (nm20 + nm02) / 4;
double yz = (nm21 + nm12) / 4;
if ((xx > yy) && (xx > zz)) {
x = Math.sqrt(xx);
y = xy / x;
z = xz / x;
} else if (yy > zz) {
y = Math.sqrt(yy);
x = xy / y;
z = yz / y;
} else {
z = Math.sqrt(zz);
x = xz / z;
y = yz / z;
}
return this;
}
double s = Math.sqrt((nm12 - nm21) * (nm12 - nm21) + (nm20 - nm02) * (nm20 - nm02) + (nm01 - nm10) * (nm01 - nm10));
angle = Math.safeAcos((nm00 + nm11 + nm22 - 1) / 2);
x = (nm12 - nm21) / s;
y = (nm20 - nm02) / s;
z = (nm01 - nm10) / s;
return this;
}
/**
* Set this {@link AxisAngle4d} to be equivalent to the rotational component
* of the given {@link Matrix4x3fc}.
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/">http://www.euclideanspace.com</a>
*
* @param m
* the Matrix4x3fc to set this AngleAxis4d from
* @return this
*/
public AxisAngle4d set(Matrix4x3fc m) {
double nm00 = m.m00(), nm01 = m.m01(), nm02 = m.m02();
double nm10 = m.m10(), nm11 = m.m11(), nm12 = m.m12();
double nm20 = m.m20(), nm21 = m.m21(), nm22 = m.m22();
double lenX = Math.invsqrt(m.m00() * m.m00() + m.m01() * m.m01() + m.m02() * m.m02());
double lenY = Math.invsqrt(m.m10() * m.m10() + m.m11() * m.m11() + m.m12() * m.m12());
double lenZ = Math.invsqrt(m.m20() * m.m20() + m.m21() * m.m21() + m.m22() * m.m22());
nm00 *= lenX; nm01 *= lenX; nm02 *= lenX;
nm10 *= lenY; nm11 *= lenY; nm12 *= lenY;
nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ;
double epsilon = 1E-4, epsilon2 = 1E-3;
if (Math.abs(nm10 - nm01) < epsilon && Math.abs(nm20 - nm02) < epsilon && Math.abs(nm21 - nm12) < epsilon) {
if (Math.abs(nm10 + nm01) < epsilon2 && Math.abs(nm20 + nm02) < epsilon2 && Math.abs(nm21 + nm12) < epsilon2
&& Math.abs(nm00 + nm11 + nm22 - 3) < epsilon2) {
x = 0;
y = 0;
z = 1;
angle = 0;
return this;
}
angle = Math.PI;
double xx = (nm00 + 1) / 2;
double yy = (nm11 + 1) / 2;
double zz = (nm22 + 1) / 2;
double xy = (nm10 + nm01) / 4;
double xz = (nm20 + nm02) / 4;
double yz = (nm21 + nm12) / 4;
if ((xx > yy) && (xx > zz)) {
x = Math.sqrt(xx);
y = xy / x;
z = xz / x;
} else if (yy > zz) {
y = Math.sqrt(yy);
x = xy / y;
z = yz / y;
} else {
z = Math.sqrt(zz);
x = xz / z;
y = yz / z;
}
return this;
}
double s = Math.sqrt((nm12 - nm21) * (nm12 - nm21) + (nm20 - nm02) * (nm20 - nm02) + (nm01 - nm10) * (nm01 - nm10));
angle = Math.safeAcos((nm00 + nm11 + nm22 - 1) / 2);
x = (nm12 - nm21) / s;
y = (nm20 - nm02) / s;
z = (nm01 - nm10) / s;
return this;
}
/**
* Set this {@link AxisAngle4d} to be equivalent to the rotational component
* of the given {@link Matrix4dc}.
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/">http://www.euclideanspace.com</a>
*
* @param m
* the Matrix4dc to set this AngleAxis4d from
* @return this
*/
public AxisAngle4d set(Matrix4dc m) {
double nm00 = m.m00(), nm01 = m.m01(), nm02 = m.m02();
double nm10 = m.m10(), nm11 = m.m11(), nm12 = m.m12();
double nm20 = m.m20(), nm21 = m.m21(), nm22 = m.m22();
double lenX = Math.invsqrt(m.m00() * m.m00() + m.m01() * m.m01() + m.m02() * m.m02());
double lenY = Math.invsqrt(m.m10() * m.m10() + m.m11() * m.m11() + m.m12() * m.m12());
double lenZ = Math.invsqrt(m.m20() * m.m20() + m.m21() * m.m21() + m.m22() * m.m22());
nm00 *= lenX; nm01 *= lenX; nm02 *= lenX;
nm10 *= lenY; nm11 *= lenY; nm12 *= lenY;
nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ;
double epsilon = 1E-4, epsilon2 = 1E-3;
if (Math.abs(nm10 - nm01) < epsilon && Math.abs(nm20 - nm02) < epsilon && Math.abs(nm21 - nm12) < epsilon) {
if (Math.abs(nm10 + nm01) < epsilon2 && Math.abs(nm20 + nm02) < epsilon2 && Math.abs(nm21 + nm12) < epsilon2
&& Math.abs(nm00 + nm11 + nm22 - 3) < epsilon2) {
x = 0;
y = 0;
z = 1;
angle = 0;
return this;
}
angle = Math.PI;
double xx = (nm00 + 1) / 2;
double yy = (nm11 + 1) / 2;
double zz = (nm22 + 1) / 2;
double xy = (nm10 + nm01) / 4;
double xz = (nm20 + nm02) / 4;
double yz = (nm21 + nm12) / 4;
if ((xx > yy) && (xx > zz)) {
x = Math.sqrt(xx);
y = xy / x;
z = xz / x;
} else if (yy > zz) {
y = Math.sqrt(yy);
x = xy / y;
z = yz / y;
} else {
z = Math.sqrt(zz);
x = xz / z;
y = yz / z;
}
return this;
}
double s = Math.sqrt((nm12 - nm21) * (nm12 - nm21) + (nm20 - nm02) * (nm20 - nm02) + (nm01 - nm10) * (nm01 - nm10));
angle = Math.safeAcos((nm00 + nm11 + nm22 - 1) / 2);
x = (nm12 - nm21) / s;
y = (nm20 - nm02) / s;
z = (nm01 - nm10) / s;
return this;
}
/**
* Set the given {@link Quaternionf} to be equivalent to this {@link AxisAngle4d} rotation.
*
* @see Quaternionf#set(AxisAngle4d)
*
* @param q
* the quaternion to set
* @return q
*/
public Quaternionf get(Quaternionf q) {
return q.set(this);
}
/**
* Set the given {@link Quaterniond} to be equivalent to this {@link AxisAngle4d} rotation.
*
* @see Quaterniond#set(AxisAngle4d)
*
* @param q
* the quaternion to set
* @return q
*/
public Quaterniond get(Quaterniond q) {
return q.set(this);
}
/**
* Set the given {@link Matrix4f} to a rotation transformation equivalent to this {@link AxisAngle4d}.
*
* @see Matrix4f#set(AxisAngle4d)
*
* @param m
* the matrix to set
* @return m
*/
public Matrix4f get(Matrix4f m) {
return m.set(this);
}
/**
* Set the given {@link Matrix3f} to a rotation transformation equivalent to this {@link AxisAngle4d}.
*
* @see Matrix3f#set(AxisAngle4d)
*
* @param m
* the matrix to set
* @return m
*/
public Matrix3f get(Matrix3f m) {
return m.set(this);
}
/**
* Set the given {@link Matrix4d} to a rotation transformation equivalent to this {@link AxisAngle4d}.
*
* @see Matrix4f#set(AxisAngle4d)
*
* @param m
* the matrix to set
* @return m
*/
public Matrix4d get(Matrix4d m) {
return m.set(this);
}
/**
* Set the given {@link Matrix3d} to a rotation transformation equivalent to this {@link AxisAngle4d}.
*
* @see Matrix3f#set(AxisAngle4d)
*
* @param m
* the matrix to set
* @return m
*/
public Matrix3d get(Matrix3d m) {
return m.set(this);
}
/**
* Set the given {@link AxisAngle4d} to this {@link AxisAngle4d}.
*
* @param dest
* will hold the result
* @return dest
*/
public AxisAngle4d get(AxisAngle4d dest) {
return dest.set(this);
}
/**
* Set the given {@link AxisAngle4f} to this {@link AxisAngle4d}.
*
* @param dest
* will hold the result
* @return dest
*/
public AxisAngle4f get(AxisAngle4f dest) {
return dest.set(this);
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeDouble(angle);
out.writeDouble(x);
out.writeDouble(y);
out.writeDouble(z);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
angle = in.readDouble();
x = in.readDouble();
y = in.readDouble();
z = in.readDouble();
}
/**
* Normalize the axis vector.
*
* @return this
*/
public AxisAngle4d normalize() {
double invLength = Math.invsqrt(x * x + y * y + z * z);
x *= invLength;
y *= invLength;
z *= invLength;
return this;
}
/**
* Increase the rotation angle by the given amount.
* <p>
* This method also takes care of wrapping around.
*
* @param ang
* the angle increase
* @return this
*/
public AxisAngle4d rotate(double ang) {
angle += ang;
angle = (angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI);
return this;
}
/**
* Transform the given vector by the rotation transformation described by this {@link AxisAngle4d}.
*
* @param v
* the vector to transform
* @return v
*/
public Vector3d transform(Vector3d v) {
return transform(v, v);
}
/**
* Transform the given vector by the rotation transformation described by this {@link AxisAngle4d}
* and store the result in <code>dest</code>.
*
* @param v
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
public Vector3d transform(Vector3dc v, Vector3d dest) {
double sin = Math.sin(angle);
double cos = Math.cosFromSin(sin, angle);
double dot = x * v.x() + y * v.y() + z * v.z();
dest.set(v.x() * cos + sin * (y * v.z() - z * v.y()) + (1.0 - cos) * dot * x,
v.y() * cos + sin * (z * v.x() - x * v.z()) + (1.0 - cos) * dot * y,
v.z() * cos + sin * (x * v.y() - y * v.x()) + (1.0 - cos) * dot * z);
return dest;
}
/**
* Transform the given vector by the rotation transformation described by this {@link AxisAngle4d}.
*
* @param v
* the vector to transform
* @return v
*/
public Vector3f transform(Vector3f v) {
return transform(v, v);
}
/**
* Transform the given vector by the rotation transformation described by this {@link AxisAngle4d}
* and store the result in <code>dest</code>.
*
* @param v
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
public Vector3f transform(Vector3fc v, Vector3f dest) {
double sin = Math.sin(angle);
double cos = Math.cosFromSin(sin, angle);
double dot = x * v.x() + y * v.y() + z * v.z();
dest.set((float) (v.x() * cos + sin * (y * v.z() - z * v.y()) + (1.0 - cos) * dot * x),
(float) (v.y() * cos + sin * (z * v.x() - x * v.z()) + (1.0 - cos) * dot * y),
(float) (v.z() * cos + sin * (x * v.y() - y * v.x()) + (1.0 - cos) * dot * z));
return dest;
}
/**
* Transform the given vector by the rotation transformation described by this {@link AxisAngle4d}.
*
* @param v
* the vector to transform
* @return v
*/
public Vector4d transform(Vector4d v) {
return transform(v, v);
}
/**
* Transform the given vector by the rotation transformation described by this {@link AxisAngle4d}
* and store the result in <code>dest</code>.
*
* @param v
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
public Vector4d transform(Vector4dc v, Vector4d dest) {
double sin = Math.sin(angle);
double cos = Math.cosFromSin(sin, angle);
double dot = x * v.x() + y * v.y() + z * v.z();
dest.set(v.x() * cos + sin * (y * v.z() - z * v.y()) + (1.0 - cos) * dot * x,
v.y() * cos + sin * (z * v.x() - x * v.z()) + (1.0 - cos) * dot * y,
v.z() * cos + sin * (x * v.y() - y * v.x()) + (1.0 - cos) * dot * z,
dest.w);
return dest;
}
/**
* Return a string representation of this {@link AxisAngle4d}.
* <p>
* This method creates a new {@link DecimalFormat} on every invocation with the format string "<code> 0.000E0;-</code>".
*
* @return the string representation
*/
public String toString() {
return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT));
}
/**
* Return a string representation of this {@link AxisAngle4d} by formatting the 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(x, formatter) + " " + Runtime.format(y, formatter) + " " + Runtime.format(z, formatter) + " <| " + Runtime.format(angle, formatter) + ")";
}
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits((angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI));
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;
AxisAngle4d other = (AxisAngle4d) obj;
if (Double.doubleToLongBits((angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI)) !=
Double.doubleToLongBits((other.angle < 0.0 ? Math.PI + Math.PI + other.angle % (Math.PI + Math.PI) : other.angle) % (Math.PI + Math.PI)))
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;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

View file

@ -0,0 +1,813 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.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 rotation of a given radians about an axis represented as an
* unit 3D vector.
* <p>
* This class uses single-precision components.
*
* @author Kai Burjack
*/
public class AxisAngle4f implements Externalizable, Cloneable {
private static final long serialVersionUID = 1L;
/**
* The angle in radians.
*/
public float angle;
/**
* The x-component of the rotation axis.
*/
public float x;
/**
* The y-component of the rotation axis.
*/
public float y;
/**
* The z-component of the rotation axis.
*/
public float z;
/**
* Create a new {@link AxisAngle4f} with zero rotation about <code>(0, 0, 1)</code>.
*/
public AxisAngle4f() {
z = 1.0f;
}
/**
* Create a new {@link AxisAngle4f} with the same values of <code>a</code>.
*
* @param a
* the AngleAxis4f to copy the values from
*/
public AxisAngle4f(AxisAngle4f a) {
x = a.x;
y = a.y;
z = a.z;
angle = (float) ((a.angle < 0.0 ? Math.PI + Math.PI + a.angle % (Math.PI + Math.PI) : a.angle) % (Math.PI + Math.PI));
}
/**
* Create a new {@link AxisAngle4f} from the given {@link Quaternionfc}.
* <p>
* Reference: <a href=
* "http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/"
* >http://www.euclideanspace.com</a>
*
* @param q
* the quaternion from which to create the new AngleAxis4f
*/
public AxisAngle4f(Quaternionfc q) {
float acos = Math.safeAcos(q.w());
float invSqrt = Math.invsqrt(1.0f - q.w() * q.w());
if (Float.isInfinite(invSqrt)) {
this.x = 0.0f;
this.y = 0.0f;
this.z = 1.0f;
} else {
this.x = q.x() * invSqrt;
this.y = q.y() * invSqrt;
this.z = q.z() * invSqrt;
}
this.angle = acos + acos;
}
/**
* Create a new {@link AxisAngle4f} with the given values.
*
* @param angle
* the angle in radians
* @param x
* the x-coordinate of the rotation axis
* @param y
* the y-coordinate of the rotation axis
* @param z
* the z-coordinate of the rotation axis
*/
public AxisAngle4f(float angle, float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
this.angle = (float) ((angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI));
}
/**
* Create a new {@link AxisAngle4f} with the given values.
*
* @param angle the angle in radians
* @param v the rotation axis as a {@link Vector3f}
*/
public AxisAngle4f(float angle, Vector3fc v) {
this(angle, v.x(), v.y(), v.z());
}
/**
* Set this {@link AxisAngle4f} to the values of <code>a</code>.
*
* @param a
* the AngleAxis4f to copy the values from
* @return this
*/
public AxisAngle4f set(AxisAngle4f a) {
x = a.x;
y = a.y;
z = a.z;
angle = a.angle;
angle = (float) ((angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI));
return this;
}
/**
* Set this {@link AxisAngle4f} to the values of <code>a</code>.
*
* @param a
* the AngleAxis4d to copy the values from
* @return this
*/
public AxisAngle4f set(AxisAngle4d a) {
x = (float) a.x;
y = (float) a.y;
z = (float) a.z;
angle = (float) a.angle;
angle = (float) ((angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI));
return this;
}
/**
* Set this {@link AxisAngle4f} to the given values.
*
* @param angle
* the angle in radians
* @param x
* the x-coordinate of the rotation axis
* @param y
* the y-coordinate of the rotation axis
* @param z
* the z-coordinate of the rotation axis
* @return this
*/
public AxisAngle4f set(float angle, float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
this.angle = (float) ((angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI));
return this;
}
/**
* Set this {@link AxisAngle4f} to the given values.
*
* @param angle
* the angle in radians
* @param v
* the rotation axis as a {@link Vector3f}
* @return this
*/
public AxisAngle4f set(float angle, Vector3fc v) {
return set(angle, v.x(), v.y(), v.z());
}
/**
* Set this {@link AxisAngle4f} to be equivalent to the given
* {@link Quaternionfc}.
*
* @param q
* the quaternion to set this AngleAxis4f from
* @return this
*/
public AxisAngle4f set(Quaternionfc q) {
float acos = Math.safeAcos(q.w());
float invSqrt = Math.invsqrt(1.0f - q.w() * q.w());
if (Float.isInfinite(invSqrt)) {
this.x = 0.0f;
this.y = 0.0f;
this.z = 1.0f;
} else {
this.x = q.x() * invSqrt;
this.y = q.y() * invSqrt;
this.z = q.z() * invSqrt;
}
this.angle = acos + acos;
return this;
}
/**
* Set this {@link AxisAngle4f} to be equivalent to the given
* {@link Quaterniondc}.
*
* @param q
* the quaternion to set this AngleAxis4f from
* @return this
*/
public AxisAngle4f set(Quaterniondc q) {
double acos = Math.safeAcos(q.w());
double invSqrt = Math.invsqrt(1.0 - q.w() * q.w());
if (Double.isInfinite(invSqrt)) {
this.x = 0.0f;
this.y = 0.0f;
this.z = 1.0f;
} else {
this.x = (float) (q.x() * invSqrt);
this.y = (float) (q.y() * invSqrt);
this.z = (float) (q.z() * invSqrt);
}
this.angle = (float) (acos + acos);
return this;
}
/**
* Set this {@link AxisAngle4f} to be equivalent to the rotation
* of the given {@link Matrix3fc}.
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/">http://www.euclideanspace.com</a>
*
* @param m
* the Matrix3fc to set this AngleAxis4f from
* @return this
*/
public AxisAngle4f set(Matrix3fc m) {
float nm00 = m.m00(), nm01 = m.m01(), nm02 = m.m02();
float nm10 = m.m10(), nm11 = m.m11(), nm12 = m.m12();
float nm20 = m.m20(), nm21 = m.m21(), nm22 = m.m22();
float lenX = Math.invsqrt(m.m00() * m.m00() + m.m01() * m.m01() + m.m02() * m.m02());
float lenY = Math.invsqrt(m.m10() * m.m10() + m.m11() * m.m11() + m.m12() * m.m12());
float lenZ = Math.invsqrt(m.m20() * m.m20() + m.m21() * m.m21() + m.m22() * m.m22());
nm00 *= lenX; nm01 *= lenX; nm02 *= lenX;
nm10 *= lenY; nm11 *= lenY; nm12 *= lenY;
nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ;
float epsilon = 1E-4f, epsilon2 = 1E-3f;
if (Math.abs(nm10 - nm01) < epsilon && Math.abs(nm20 - nm02) < epsilon && Math.abs(nm21 - nm12) < epsilon) {
if (Math.abs(nm10 + nm01) < epsilon2 && Math.abs(nm20 + nm02) < epsilon2 && Math.abs(nm21 + nm12) < epsilon2
&& Math.abs(nm00 + nm11 + nm22 - 3) < epsilon2) {
x = 0;
y = 0;
z = 1;
angle = 0;
return this;
}
angle = Math.PI_f;
float xx = (nm00 + 1) / 2;
float yy = (nm11 + 1) / 2;
float zz = (nm22 + 1) / 2;
float xy = (nm10 + nm01) / 4;
float xz = (nm20 + nm02) / 4;
float yz = (nm21 + nm12) / 4;
if ((xx > yy) && (xx > zz)) {
x = Math.sqrt(xx);
y = xy / x;
z = xz / x;
} else if (yy > zz) {
y = Math.sqrt(yy);
x = xy / y;
z = yz / y;
} else {
z = Math.sqrt(zz);
x = xz / z;
y = yz / z;
}
return this;
}
float s = Math.sqrt((nm12 - nm21) * (nm12 - nm21) + (nm20 - nm02) * (nm20 - nm02) + (nm01 - nm10) * (nm01 - nm10));
angle = Math.safeAcos((nm00 + nm11 + nm22 - 1) / 2);
x = (nm12 - nm21) / s;
y = (nm20 - nm02) / s;
z = (nm01 - nm10) / s;
return this;
}
/**
* Set this {@link AxisAngle4f} to be equivalent to the rotation
* of the given {@link Matrix3dc}.
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/">http://www.euclideanspace.com</a>
*
* @param m
* the Matrix3d to set this AngleAxis4f from
* @return this
*/
public AxisAngle4f set(Matrix3dc m) {
double nm00 = m.m00(), nm01 = m.m01(), nm02 = m.m02();
double nm10 = m.m10(), nm11 = m.m11(), nm12 = m.m12();
double nm20 = m.m20(), nm21 = m.m21(), nm22 = m.m22();
double lenX = Math.invsqrt(m.m00() * m.m00() + m.m01() * m.m01() + m.m02() * m.m02());
double lenY = Math.invsqrt(m.m10() * m.m10() + m.m11() * m.m11() + m.m12() * m.m12());
double lenZ = Math.invsqrt(m.m20() * m.m20() + m.m21() * m.m21() + m.m22() * m.m22());
nm00 *= lenX; nm01 *= lenX; nm02 *= lenX;
nm10 *= lenY; nm11 *= lenY; nm12 *= lenY;
nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ;
double epsilon = 1E-4, epsilon2 = 1E-3;
if (Math.abs(nm10 - nm01) < epsilon && Math.abs(nm20 - nm02) < epsilon && Math.abs(nm21 - nm12) < epsilon) {
if (Math.abs(nm10 + nm01) < epsilon2 && Math.abs(nm20 + nm02) < epsilon2 && Math.abs(nm21 + nm12) < epsilon2
&& Math.abs(nm00 + nm11 + nm22 - 3) < epsilon2) {
x = 0;
y = 0;
z = 1;
angle = 0;
return this;
}
angle = (float) Math.PI;
double xx = (nm00 + 1) / 2;
double yy = (nm11 + 1) / 2;
double zz = (nm22 + 1) / 2;
double xy = (nm10 + nm01) / 4;
double xz = (nm20 + nm02) / 4;
double yz = (nm21 + nm12) / 4;
if ((xx > yy) && (xx > zz)) {
x = (float) Math.sqrt(xx);
y = (float) (xy / x);
z = (float) (xz / x);
} else if (yy > zz) {
y = (float) Math.sqrt(yy);
x = (float) (xy / y);
z = (float) (yz / y);
} else {
z = (float) Math.sqrt(zz);
x = (float) (xz / z);
y = (float) (yz / z);
}
return this;
}
double s = Math.sqrt((nm12 - nm21) * (nm12 - nm21) + (nm20 - nm02) * (nm20 - nm02) + (nm01 - nm10) * (nm01 - nm10));
angle = (float) Math.safeAcos((nm00 + nm11 + nm22 - 1) / 2);
x = (float) ((nm12 - nm21) / s);
y = (float) ((nm20 - nm02) / s);
z = (float) ((nm01 - nm10) / s);
return this;
}
/**
* Set this {@link AxisAngle4f} to be equivalent to the rotational component
* of the given {@link Matrix4fc}.
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/">http://www.euclideanspace.com</a>
*
* @param m
* the Matrix4fc to set this AngleAxis4f from
* @return this
*/
public AxisAngle4f set(Matrix4fc m) {
float nm00 = m.m00(), nm01 = m.m01(), nm02 = m.m02();
float nm10 = m.m10(), nm11 = m.m11(), nm12 = m.m12();
float nm20 = m.m20(), nm21 = m.m21(), nm22 = m.m22();
float lenX = Math.invsqrt(m.m00() * m.m00() + m.m01() * m.m01() + m.m02() * m.m02());
float lenY = Math.invsqrt(m.m10() * m.m10() + m.m11() * m.m11() + m.m12() * m.m12());
float lenZ = Math.invsqrt(m.m20() * m.m20() + m.m21() * m.m21() + m.m22() * m.m22());
nm00 *= lenX; nm01 *= lenX; nm02 *= lenX;
nm10 *= lenY; nm11 *= lenY; nm12 *= lenY;
nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ;
float epsilon = 1E-4f, epsilon2 = 1E-3f;
if (Math.abs(nm10 - nm01) < epsilon && Math.abs(nm20 - nm02) < epsilon && Math.abs(nm21 - nm12) < epsilon) {
if (Math.abs(nm10 + nm01) < epsilon2 && Math.abs(nm20 + nm02) < epsilon2 && Math.abs(nm21 + nm12) < epsilon2
&& Math.abs(nm00 + nm11 + nm22 - 3) < epsilon2) {
x = 0;
y = 0;
z = 1;
angle = 0;
return this;
}
angle = Math.PI_f;
float xx = (nm00 + 1) / 2;
float yy = (nm11 + 1) / 2;
float zz = (nm22 + 1) / 2;
float xy = (nm10 + nm01) / 4;
float xz = (nm20 + nm02) / 4;
float yz = (nm21 + nm12) / 4;
if ((xx > yy) && (xx > zz)) {
x = Math.sqrt(xx);
y = xy / x;
z = xz / x;
} else if (yy > zz) {
y = Math.sqrt(yy);
x = xy / y;
z = yz / y;
} else {
z = Math.sqrt(zz);
x = xz / z;
y = yz / z;
}
return this;
}
float s = Math.sqrt((nm12 - nm21) * (nm12 - nm21) + (nm20 - nm02) * (nm20 - nm02) + (nm01 - nm10) * (nm01 - nm10));
angle = Math.safeAcos((nm00 + nm11 + nm22 - 1) / 2);
x = (nm12 - nm21) / s;
y = (nm20 - nm02) / s;
z = (nm01 - nm10) / s;
return this;
}
/**
* Set this {@link AxisAngle4f} to be equivalent to the rotational component
* of the given {@link Matrix4x3fc}.
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/">http://www.euclideanspace.com</a>
*
* @param m
* the Matrix4x3fc to set this AngleAxis4f from
* @return this
*/
public AxisAngle4f set(Matrix4x3fc m) {
float nm00 = m.m00(), nm01 = m.m01(), nm02 = m.m02();
float nm10 = m.m10(), nm11 = m.m11(), nm12 = m.m12();
float nm20 = m.m20(), nm21 = m.m21(), nm22 = m.m22();
float lenX = Math.invsqrt(m.m00() * m.m00() + m.m01() * m.m01() + m.m02() * m.m02());
float lenY = Math.invsqrt(m.m10() * m.m10() + m.m11() * m.m11() + m.m12() * m.m12());
float lenZ = Math.invsqrt(m.m20() * m.m20() + m.m21() * m.m21() + m.m22() * m.m22());
nm00 *= lenX; nm01 *= lenX; nm02 *= lenX;
nm10 *= lenY; nm11 *= lenY; nm12 *= lenY;
nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ;
float epsilon = 1E-4f, epsilon2 = 1E-3f;
if (Math.abs(nm10 - nm01) < epsilon && Math.abs(nm20 - nm02) < epsilon && Math.abs(nm21 - nm12) < epsilon) {
if (Math.abs(nm10 + nm01) < epsilon2 && Math.abs(nm20 + nm02) < epsilon2 && Math.abs(nm21 + nm12) < epsilon2
&& Math.abs(nm00 + nm11 + nm22 - 3) < epsilon2) {
x = 0;
y = 0;
z = 1;
angle = 0;
return this;
}
angle = Math.PI_f;
float xx = (nm00 + 1) / 2;
float yy = (nm11 + 1) / 2;
float zz = (nm22 + 1) / 2;
float xy = (nm10 + nm01) / 4;
float xz = (nm20 + nm02) / 4;
float yz = (nm21 + nm12) / 4;
if ((xx > yy) && (xx > zz)) {
x = Math.sqrt(xx);
y = xy / x;
z = xz / x;
} else if (yy > zz) {
y = Math.sqrt(yy);
x = xy / y;
z = yz / y;
} else {
z = Math.sqrt(zz);
x = xz / z;
y = yz / z;
}
return this;
}
float s = Math.sqrt((nm12 - nm21) * (nm12 - nm21) + (nm20 - nm02) * (nm20 - nm02) + (nm01 - nm10) * (nm01 - nm10));
angle = Math.safeAcos((nm00 + nm11 + nm22 - 1) / 2);
x = (nm12 - nm21) / s;
y = (nm20 - nm02) / s;
z = (nm01 - nm10) / s;
return this;
}
/**
* Set this {@link AxisAngle4f} to be equivalent to the rotational component
* of the given {@link Matrix4dc}.
* <p>
* Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/">http://www.euclideanspace.com</a>
*
* @param m
* the Matrix4dc to set this AngleAxis4f from
* @return this
*/
public AxisAngle4f set(Matrix4dc m) {
double nm00 = m.m00(), nm01 = m.m01(), nm02 = m.m02();
double nm10 = m.m10(), nm11 = m.m11(), nm12 = m.m12();
double nm20 = m.m20(), nm21 = m.m21(), nm22 = m.m22();
double lenX = Math.invsqrt(m.m00() * m.m00() + m.m01() * m.m01() + m.m02() * m.m02());
double lenY = Math.invsqrt(m.m10() * m.m10() + m.m11() * m.m11() + m.m12() * m.m12());
double lenZ = Math.invsqrt(m.m20() * m.m20() + m.m21() * m.m21() + m.m22() * m.m22());
nm00 *= lenX; nm01 *= lenX; nm02 *= lenX;
nm10 *= lenY; nm11 *= lenY; nm12 *= lenY;
nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ;
double epsilon = 1E-4, epsilon2 = 1E-3;
if (Math.abs(nm10 - nm01) < epsilon && Math.abs(nm20 - nm02) < epsilon && Math.abs(nm21 - nm12) < epsilon) {
if (Math.abs(nm10 + nm01) < epsilon2 && Math.abs(nm20 + nm02) < epsilon2 && Math.abs(nm21 + nm12) < epsilon2
&& Math.abs(nm00 + nm11 + nm22 - 3) < epsilon2) {
x = 0;
y = 0;
z = 1;
angle = 0;
return this;
}
angle = (float) Math.PI;
double xx = (nm00 + 1) / 2;
double yy = (nm11 + 1) / 2;
double zz = (nm22 + 1) / 2;
double xy = (nm10 + nm01) / 4;
double xz = (nm20 + nm02) / 4;
double yz = (nm21 + nm12) / 4;
if ((xx > yy) && (xx > zz)) {
x = (float) Math.sqrt(xx);
y = (float) (xy / x);
z = (float) (xz / x);
} else if (yy > zz) {
y = (float) Math.sqrt(yy);
x = (float) (xy / y);
z = (float) (yz / y);
} else {
z = (float) Math.sqrt(zz);
x = (float) (xz / z);
y = (float) (yz / z);
}
return this;
}
double s = Math.sqrt((nm12 - nm21) * (nm12 - nm21) + (nm20 - nm02) * (nm20 - nm02) + (nm01 - nm10) * (nm01 - nm10));
angle = (float) Math.safeAcos((nm00 + nm11 + nm22 - 1) / 2);
x = (float) ((nm12 - nm21) / s);
y = (float) ((nm20 - nm02) / s);
z = (float) ((nm01 - nm10) / s);
return this;
}
/**
* Set the given {@link Quaternionf} to be equivalent to this {@link AxisAngle4f} rotation.
*
* @see Quaternionf#set(AxisAngle4f)
*
* @param q
* the quaternion to set
* @return q
*/
public Quaternionf get(Quaternionf q) {
return q.set(this);
}
/**
* Set the given {@link Quaterniond} to be equivalent to this {@link AxisAngle4f} rotation.
*
* @see Quaterniond#set(AxisAngle4f)
*
* @param q
* the quaternion to set
* @return q
*/
public Quaterniond get(Quaterniond q) {
return q.set(this);
}
/**
* Set the given {@link Matrix4f} to a rotation transformation equivalent to this {@link AxisAngle4f}.
*
* @see Matrix4f#set(AxisAngle4f)
*
* @param m
* the matrix to set
* @return m
*/
public Matrix4f get(Matrix4f m) {
return m.set(this);
}
/**
* Set the given {@link Matrix3f} to a rotation transformation equivalent to this {@link AxisAngle4f}.
*
* @see Matrix3f#set(AxisAngle4f)
*
* @param m
* the matrix to set
* @return m
*/
public Matrix3f get(Matrix3f m) {
return m.set(this);
}
/**
* Set the given {@link Matrix4d} to a rotation transformation equivalent to this {@link AxisAngle4f}.
*
* @see Matrix4f#set(AxisAngle4f)
*
* @param m
* the matrix to set
* @return m
*/
public Matrix4d get(Matrix4d m) {
return m.set(this);
}
/**
* Set the given {@link Matrix3d} to a rotation transformation equivalent to this {@link AxisAngle4f}.
*
* @see Matrix3f#set(AxisAngle4f)
*
* @param m
* the matrix to set
* @return m
*/
public Matrix3d get(Matrix3d m) {
return m.set(this);
}
/**
* Set the given {@link AxisAngle4d} to this {@link AxisAngle4f}.
*
* @param dest
* will hold the result
* @return dest
*/
public AxisAngle4d get(AxisAngle4d dest) {
return dest.set(this);
}
/**
* Set the given {@link AxisAngle4f} to this {@link AxisAngle4f}.
*
* @param dest
* will hold the result
* @return dest
*/
public AxisAngle4f get(AxisAngle4f dest) {
return dest.set(this);
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeFloat(angle);
out.writeFloat(x);
out.writeFloat(y);
out.writeFloat(z);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
angle = in.readFloat();
x = in.readFloat();
y = in.readFloat();
z = in.readFloat();
}
/**
* Normalize the axis vector.
*
* @return this
*/
public AxisAngle4f normalize() {
float invLength = Math.invsqrt(x * x + y * y + z * z);
x *= invLength;
y *= invLength;
z *= invLength;
return this;
}
/**
* Increase the rotation angle by the given amount.
* <p>
* This method also takes care of wrapping around.
*
* @param ang
* the angle increase
* @return this
*/
public AxisAngle4f rotate(float ang) {
angle += ang;
angle = (float) ((angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI));
return this;
}
/**
* Transform the given vector by the rotation transformation described by this {@link AxisAngle4f}.
*
* @param v
* the vector to transform
* @return v
*/
public Vector3f transform(Vector3f v) {
return transform(v, v);
}
/**
* Transform the given vector by the rotation transformation described by this {@link AxisAngle4f}
* and store the result in <code>dest</code>.
*
* @param v
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
public Vector3f transform(Vector3fc v, Vector3f dest) {
double sin = Math.sin(angle);
double cos = Math.cosFromSin(sin, angle);
float dot = x * v.x() + y * v.y() + z * v.z();
dest.set((float) (v.x() * cos + sin * (y * v.z() - z * v.y()) + (1.0 - cos) * dot * x),
(float) (v.y() * cos + sin * (z * v.x() - x * v.z()) + (1.0 - cos) * dot * y),
(float) (v.z() * cos + sin * (x * v.y() - y * v.x()) + (1.0 - cos) * dot * z));
return dest;
}
/**
* Transform the given vector by the rotation transformation described by this {@link AxisAngle4f}.
*
* @param v
* the vector to transform
* @return v
*/
public Vector4f transform(Vector4f v) {
return transform(v, v);
}
/**
* Transform the given vector by the rotation transformation described by this {@link AxisAngle4f}
* and store the result in <code>dest</code>.
*
* @param v
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
public Vector4f transform(Vector4fc v, Vector4f dest) {
double sin = Math.sin(angle);
double cos = Math.cosFromSin(sin, angle);
float dot = x * v.x() + y * v.y() + z * v.z();
dest.set((float) (v.x() * cos + sin * (y * v.z() - z * v.y()) + (1.0 - cos) * dot * x),
(float) (v.y() * cos + sin * (z * v.x() - x * v.z()) + (1.0 - cos) * dot * y),
(float) (v.z() * cos + sin * (x * v.y() - y * v.x()) + (1.0 - cos) * dot * z),
dest.w);
return dest;
}
/**
* Return a string representation of this {@link AxisAngle4f}.
* <p>
* This method creates a new {@link DecimalFormat} on every invocation with the format string "<code> 0.000E0;-</code>".
*
* @return the string representation
*/
public String toString() {
return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT));
}
/**
* Return a string representation of this {@link AxisAngle4f} by formatting the 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(x, formatter) + " " + Runtime.format(y, formatter) + " " + Runtime.format(z, formatter) + " <| " + Runtime.format(angle, formatter) + ")";
}
public int hashCode() {
final int prime = 31;
int result = 1;
float nangle = (float) ((angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI));
result = prime * result + Float.floatToIntBits(nangle);
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;
AxisAngle4f other = (AxisAngle4f) obj;
float nangle = (float) ((angle < 0.0 ? Math.PI + Math.PI + angle % (Math.PI + Math.PI) : angle) % (Math.PI + Math.PI));
float nangleOther = (float) ((other.angle < 0.0 ? Math.PI + Math.PI + other.angle % (Math.PI + Math.PI) : other.angle) % (Math.PI + Math.PI));
if (Float.floatToIntBits(nangle) != Float.floatToIntBits(nangleOther))
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;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

View file

@ -0,0 +1,36 @@
/*
* The MIT License
*
* Copyright (c) 2020-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Exception thrown when using an invalid JOML runtime configuration.
*
* @author Kai Burjack
*/
public class ConfigurationException extends RuntimeException {
private static final long serialVersionUID = -7832356906364070687L;
public ConfigurationException(String message, Throwable cause) {
super(message, cause);
}
}

View file

@ -0,0 +1,971 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Efficiently performs frustum intersection tests by caching the frustum planes of an arbitrary transformation {@link Matrix4fc matrix}.
* <p>
* This class is preferred over the frustum intersection methods in {@link Matrix4fc} when many objects need to be culled by the same static frustum.
*
* @author Kai Burjack
*/
public class FrustumIntersection {
/**
* Return value of {@link #intersectAab(float, float, float, float, float, float) intersectAab()}
* and its different overloads identifying the plane with equation <code>x=-1</code> when using the identity frustum.
*/
public static final int PLANE_NX = 0;
/**
* Return value of {@link #intersectAab(float, float, float, float, float, float) intersectAab()}
* and its different overloads identifying the plane with equation <code>x=1</code> when using the identity frustum.
*/
public static final int PLANE_PX = 1;
/**
* Return value of {@link #intersectAab(float, float, float, float, float, float) intersectAab()}
* and its different overloads identifying the plane with equation <code>y=-1</code> when using the identity frustum.
*/
public static final int PLANE_NY= 2;
/**
* Return value of {@link #intersectAab(float, float, float, float, float, float) intersectAab()}
* and its different overloads identifying the plane with equation <code>y=1</code> when using the identity frustum.
*/
public static final int PLANE_PY = 3;
/**
* Return value of {@link #intersectAab(float, float, float, float, float, float) intersectAab()}
* and its different overloads identifying the plane with equation <code>z=-1</code> when using the identity frustum.
*/
public static final int PLANE_NZ = 4;
/**
* Return value of {@link #intersectAab(float, float, float, float, float, float) intersectAab()}
* and its different overloads identifying the plane with equation <code>z=1</code> when using the identity frustum.
*/
public static final int PLANE_PZ = 5;
/**
* Return value of {@link #intersectAab(float, float, float, float, float, float) intersectAab()}
* and its different overloads indicating that the axis-aligned box intersects the frustum.
*/
public static final int INTERSECT = -1;
/**
* Return value of {@link #intersectAab(float, float, float, float, float, float) intersectAab()}
* and its different overloads indicating that the axis-aligned box is fully inside of the frustum.
*/
public static final int INSIDE = -2;
/**
* Return value of {@link #intersectSphere(Vector3fc, float)} or {@link #intersectSphere(float, float, float, float)}
* indicating that the sphere is completely outside of the frustum.
*/
public static final int OUTSIDE = -3;
/**
* The value in a bitmask for
* {@link #intersectAab(float, float, float, float, float, float, int) intersectAab()}
* that identifies the plane with equation <code>x=-1</code> when using the identity frustum.
*/
public static final int PLANE_MASK_NX = 1<<PLANE_NX;
/**
* The value in a bitmask for
* {@link #intersectAab(float, float, float, float, float, float, int) intersectAab()}
* that identifies the plane with equation <code>x=1</code> when using the identity frustum.
*/
public static final int PLANE_MASK_PX = 1<<PLANE_PX;
/**
* The value in a bitmask for
* {@link #intersectAab(float, float, float, float, float, float, int) intersectAab()}
* that identifies the plane with equation <code>y=-1</code> when using the identity frustum.
*/
public static final int PLANE_MASK_NY = 1<<PLANE_NY;
/**
* The value in a bitmask for
* {@link #intersectAab(float, float, float, float, float, float, int) intersectAab()}
* that identifies the plane with equation <code>y=1</code> when using the identity frustum.
*/
public static final int PLANE_MASK_PY = 1<<PLANE_PY;
/**
* The value in a bitmask for
* {@link #intersectAab(float, float, float, float, float, float, int) intersectAab()}
* that identifies the plane with equation <code>z=-1</code> when using the identity frustum.
*/
public static final int PLANE_MASK_NZ = 1<<PLANE_NZ;
/**
* The value in a bitmask for
* {@link #intersectAab(float, float, float, float, float, float, int) intersectAab()}
* that identifies the plane with equation <code>z=1</code> when using the identity frustum.
*/
public static final int PLANE_MASK_PZ = 1<<PLANE_PZ;
private float nxX, nxY, nxZ, nxW;
private float pxX, pxY, pxZ, pxW;
private float nyX, nyY, nyZ, nyW;
private float pyX, pyY, pyZ, pyW;
private float nzX, nzY, nzZ, nzW;
private float pzX, pzY, pzZ, pzW;
private final Vector4f[] planes = new Vector4f[6];
{
for (int i = 0; i < 6; i++) {
planes[i] = new Vector4f();
}
}
/**
* Create a new {@link FrustumIntersection} with undefined frustum planes.
* <p>
* Before using any of the frustum culling methods, make sure to define the frustum planes using {@link #set(Matrix4fc)}.
*/
public FrustumIntersection() {
}
/**
* Create a new {@link FrustumIntersection} from the given {@link Matrix4fc matrix} by extracing the matrix's frustum planes.
* <p>
* In order to update the compute frustum planes later on, call {@link #set(Matrix4fc)}.
*
* @see #set(Matrix4fc)
*
* @param m
* the {@link Matrix4fc} to create the frustum culler from
*/
public FrustumIntersection(Matrix4fc m) {
set(m, true);
}
/**
* Create a new {@link FrustumIntersection} from the given {@link Matrix4fc matrix} by extracing the matrix's frustum planes.
* <p>
* In order to update the compute frustum planes later on, call {@link #set(Matrix4fc)}.
*
* @see #set(Matrix4fc)
*
* @param m
* the {@link Matrix4fc} to create the frustum culler from
* @param allowTestSpheres
* whether the methods {@link #testSphere(Vector3fc, float)}, {@link #testSphere(float, float, float, float)},
* {@link #intersectSphere(Vector3fc, float)} or {@link #intersectSphere(float, float, float, float)} will used.
* If no spheres need to be tested, then <code>false</code> should be used
*/
public FrustumIntersection(Matrix4fc m, boolean allowTestSpheres) {
set(m, allowTestSpheres);
}
/**
* Update the stored frustum planes of <code>this</code> {@link FrustumIntersection} with the given {@link Matrix4fc matrix}.
* <p>
* Reference: <a href="http://gamedevs.org/uploads/fast-extraction-viewing-frustum-planes-from-world-view-projection-matrix.pdf">
* Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix</a>
*
* @param m
* the {@link Matrix4fc matrix} to update <code>this</code> frustum culler's frustum planes from
* @return this
*/
public FrustumIntersection set(Matrix4fc m) {
return set(m, true);
}
/**
* Update the stored frustum planes of <code>this</code> {@link FrustumIntersection} with the given {@link Matrix4fc matrix} and
* allow to optimize the frustum plane extraction in the case when no intersection test is needed for spheres.
* <p>
* Reference: <a href="http://gamedevs.org/uploads/fast-extraction-viewing-frustum-planes-from-world-view-projection-matrix.pdf">
* Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix</a>
*
* @param m
* the {@link Matrix4fc matrix} to update <code>this</code> frustum culler's frustum planes from
* @param allowTestSpheres
* whether the methods {@link #testSphere(Vector3fc, float)}, {@link #testSphere(float, float, float, float)},
* {@link #intersectSphere(Vector3fc, float)} or {@link #intersectSphere(float, float, float, float)} will be used.
* If no spheres need to be tested, then <code>false</code> should be used
* @return this
*/
public FrustumIntersection set(Matrix4fc m, boolean allowTestSpheres) {
float invl;
nxX = m.m03() + m.m00(); nxY = m.m13() + m.m10(); nxZ = m.m23() + m.m20(); nxW = m.m33() + m.m30();
if (allowTestSpheres) {
invl = Math.invsqrt(nxX * nxX + nxY * nxY + nxZ * nxZ);
nxX *= invl; nxY *= invl; nxZ *= invl; nxW *= invl;
}
planes[0].set(nxX, nxY, nxZ, nxW);
pxX = m.m03() - m.m00(); pxY = m.m13() - m.m10(); pxZ = m.m23() - m.m20(); pxW = m.m33() - m.m30();
if (allowTestSpheres) {
invl = Math.invsqrt(pxX * pxX + pxY * pxY + pxZ * pxZ);
pxX *= invl; pxY *= invl; pxZ *= invl; pxW *= invl;
}
planes[1].set(pxX, pxY, pxZ, pxW);
nyX = m.m03() + m.m01(); nyY = m.m13() + m.m11(); nyZ = m.m23() + m.m21(); nyW = m.m33() + m.m31();
if (allowTestSpheres) {
invl = Math.invsqrt(nyX * nyX + nyY * nyY + nyZ * nyZ);
nyX *= invl; nyY *= invl; nyZ *= invl; nyW *= invl;
}
planes[2].set(nyX, nyY, nyZ, nyW);
pyX = m.m03() - m.m01(); pyY = m.m13() - m.m11(); pyZ = m.m23() - m.m21(); pyW = m.m33() - m.m31();
if (allowTestSpheres) {
invl = Math.invsqrt(pyX * pyX + pyY * pyY + pyZ * pyZ);
pyX *= invl; pyY *= invl; pyZ *= invl; pyW *= invl;
}
planes[3].set(pyX, pyY, pyZ, pyW);
nzX = m.m03() + m.m02(); nzY = m.m13() + m.m12(); nzZ = m.m23() + m.m22(); nzW = m.m33() + m.m32();
if (allowTestSpheres) {
invl = Math.invsqrt(nzX * nzX + nzY * nzY + nzZ * nzZ);
nzX *= invl; nzY *= invl; nzZ *= invl; nzW *= invl;
}
planes[4].set(nzX, nzY, nzZ, nzW);
pzX = m.m03() - m.m02(); pzY = m.m13() - m.m12(); pzZ = m.m23() - m.m22(); pzW = m.m33() - m.m32();
if (allowTestSpheres) {
invl = Math.invsqrt(pzX * pzX + pzY * pzY + pzZ * pzZ);
pzX *= invl; pzY *= invl; pzZ *= invl; pzW *= invl;
}
planes[5].set(pzX, pzY, pzZ, pzW);
return this;
}
/**
* Test whether the given point is within the frustum defined by <code>this</code> frustum culler.
*
* @param point
* the point to test
* @return <code>true</code> if the given point is inside the frustum; <code>false</code> otherwise
*/
public boolean testPoint(Vector3fc point) {
return testPoint(point.x(), point.y(), point.z());
}
/**
* Test whether the given point <code>(x, y, z)</code> is within the frustum defined by <code>this</code> frustum culler.
*
* @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 <code>true</code> if the given point is inside the frustum; <code>false</code> otherwise
*/
public boolean testPoint(float x, float y, float z) {
return nxX * x + nxY * y + nxZ * z + nxW >= 0 &&
pxX * x + pxY * y + pxZ * z + pxW >= 0 &&
nyX * x + nyY * y + nyZ * z + nyW >= 0 &&
pyX * x + pyY * y + pyZ * z + pyW >= 0 &&
nzX * x + nzY * y + nzZ * z + nzW >= 0 &&
pzX * x + pzY * y + pzZ * z + pzW >= 0;
}
/**
* Test whether the given sphere is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns <code>true</code> for spheres that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
*
* @param center
* the sphere's center
* @param radius
* the sphere's radius
* @return <code>true</code> if the given sphere is partly or completely inside the frustum;
* <code>false</code> otherwise
*/
public boolean testSphere(Vector3fc center, float radius) {
return testSphere(center.x(), center.y(), center.z(), radius);
}
/**
* Test whether the given sphere is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns <code>true</code> for spheres that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
*
* @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 sphere's radius
* @return <code>true</code> if the given sphere is partly or completely inside the frustum;
* <code>false</code> otherwise
*/
public boolean testSphere(float x, float y, float z, float r) {
return nxX * x + nxY * y + nxZ * z + nxW >= -r &&
pxX * x + pxY * y + pxZ * z + pxW >= -r &&
nyX * x + nyY * y + nyZ * z + nyW >= -r &&
pyX * x + pyY * y + pyZ * z + pyW >= -r &&
nzX * x + nzY * y + nzZ * z + nzW >= -r &&
pzX * x + pzY * y + pzZ * z + pzW >= -r;
}
/**
* Determine whether the given sphere is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns {@link #INTERSECT} for spheres that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
*
* @param center
* the sphere's center
* @param radius
* the sphere's radius
* @return {@link #INSIDE} if the given sphere is completely inside the frustum, or {@link #INTERSECT} if the sphere intersects
* the frustum, or {@link #OUTSIDE} if the sphere is outside of the frustum
*/
public int intersectSphere(Vector3fc center, float radius) {
return intersectSphere(center.x(), center.y(), center.z(), radius);
}
/**
* Determine whether the given sphere is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns {@link #INTERSECT} for spheres that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
*
* @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 sphere's radius
* @return {@link #INSIDE} if the given sphere is completely inside the frustum, or {@link #INTERSECT} if the sphere intersects
* the frustum, or {@link #OUTSIDE} if the sphere is outside of the frustum
*/
public int intersectSphere(float x, float y, float z, float r) {
boolean inside = true;
float dist;
dist = nxX * x + nxY * y + nxZ * z + nxW;
if (dist >= -r) {
inside &= dist >= r;
dist = pxX * x + pxY * y + pxZ * z + pxW;
if (dist >= -r) {
inside &= dist >= r;
dist = nyX * x + nyY * y + nyZ * z + nyW;
if (dist >= -r) {
inside &= dist >= r;
dist = pyX * x + pyY * y + pyZ * z + pyW;
if (dist >= -r) {
inside &= dist >= r;
dist = nzX * x + nzY * y + nzZ * z + nzW;
if (dist >= -r) {
inside &= dist >= r;
dist = pzX * x + pzY * y + pzZ * z + pzW;
if (dist >= -r) {
inside &= dist >= r;
return inside ? INSIDE : INTERSECT;
}
}
}
}
}
}
return OUTSIDE;
}
/**
* Test whether the given axis-aligned box is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler.
* The box is specified via its <code>min</code> and <code>max</code> corner coordinates.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns <code>true</code> for boxes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
*
* @param min
* the minimum corner coordinates of the axis-aligned box
* @param max
* the maximum corner coordinates of the axis-aligned box
* @return <code>true</code> if the axis-aligned box is completely or partly inside of the frustum; <code>false</code> otherwise
*/
public boolean testAab(Vector3fc min, Vector3fc max) {
return testAab(min.x(), min.y(), min.z(), max.x(), max.y(), max.z());
}
/**
* Test whether the given axis-aligned box is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler.
* The box is specified via its min and max corner coordinates.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns <code>true</code> for boxes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
* <p>
* Reference: <a href="http://old.cescg.org/CESCG-2002/DSykoraJJelinek/">Efficient View Frustum Culling</a>
*
* @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
* @return <code>true</code> if the axis-aligned box is completely or partly inside of the frustum; <code>false</code> otherwise
*/
public boolean testAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
/*
* This is an implementation of the "2.4 Basic intersection test" of the mentioned site.
* It does not distinguish between partially inside and fully inside, though, so the test with the 'p' vertex is omitted.
*/
return nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) + nxZ * (nxZ < 0 ? minZ : maxZ) >= -nxW &&
pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) + pxZ * (pxZ < 0 ? minZ : maxZ) >= -pxW &&
nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) + nyZ * (nyZ < 0 ? minZ : maxZ) >= -nyW &&
pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) + pyZ * (pyZ < 0 ? minZ : maxZ) >= -pyW &&
nzX * (nzX < 0 ? minX : maxX) + nzY * (nzY < 0 ? minY : maxY) + nzZ * (nzZ < 0 ? minZ : maxZ) >= -nzW &&
pzX * (pzX < 0 ? minX : maxX) + pzY * (pzY < 0 ? minY : maxY) + pzZ * (pzZ < 0 ? minZ : maxZ) >= -pzW;
}
/**
* Test whether the given XY-plane (at <code>Z = 0</code>) is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler.
* The plane is specified via its <code>min</code> and <code>max</code> corner coordinates.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns <code>true</code> for planes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
*
* @param min
* the minimum corner coordinates of the XY-plane
* @param max
* the maximum corner coordinates of the XY-plane
* @return <code>true</code> if the XY-plane is completely or partly inside of the frustum; <code>false</code> otherwise
*/
public boolean testPlaneXY(Vector2fc min, Vector2fc max) {
return testPlaneXY(min.x(), min.y(), max.x(), max.y());
}
/**
* Test whether the given XY-plane (at <code>Z = 0</code>) is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler.
* The plane is specified via its min and max corner coordinates.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns <code>true</code> for planes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
* <p>
* Reference: <a href="http://old.cescg.org/CESCG-2002/DSykoraJJelinek/">Efficient View Frustum Culling</a>
*
* @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
* @return <code>true</code> if the XY-plane is completely or partly inside of the frustum; <code>false</code> otherwise
*/
public boolean testPlaneXY(float minX, float minY, float maxX, float maxY) {
/*
* This is an implementation of the "2.4 Basic intersection test" of the mentioned site.
* It does not distinguish between partially inside and fully inside, though, so the test with the 'p' vertex is omitted.
*/
return nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) >= -nxW &&
pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) >= -pxW &&
nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) >= -nyW &&
pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) >= -pyW &&
nzX * (nzX < 0 ? minX : maxX) + nzY * (nzY < 0 ? minY : maxY) >= -nzW &&
pzX * (pzX < 0 ? minX : maxX) + pzY * (pzY < 0 ? minY : maxY) >= -pzW;
}
/**
* Test whether the given XZ-plane (at <code>Y = 0</code>) is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler.
* The plane is specified via its min and max corner coordinates.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns <code>true</code> for planes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
* <p>
* Reference: <a href="http://old.cescg.org/CESCG-2002/DSykoraJJelinek/">Efficient View Frustum Culling</a>
*
* @param minX
* the x-coordinate of the minimum corner
* @param minZ
* the z-coordinate of the minimum corner
* @param maxX
* the x-coordinate of the maximum corner
* @param maxZ
* the z-coordinate of the maximum corner
* @return <code>true</code> if the XZ-plane is completely or partly inside of the frustum; <code>false</code> otherwise
*/
public boolean testPlaneXZ(float minX, float minZ, float maxX, float maxZ) {
/*
* This is an implementation of the "2.4 Basic intersection test" of the mentioned site.
* It does not distinguish between partially inside and fully inside, though, so the test with the 'p' vertex is omitted.
*/
return nxX * (nxX < 0 ? minX : maxX) + nxZ * (nxZ < 0 ? minZ : maxZ) >= -nxW &&
pxX * (pxX < 0 ? minX : maxX) + pxZ * (pxZ < 0 ? minZ : maxZ) >= -pxW &&
nyX * (nyX < 0 ? minX : maxX) + nyZ * (nyZ < 0 ? minZ : maxZ) >= -nyW &&
pyX * (pyX < 0 ? minX : maxX) + pyZ * (pyZ < 0 ? minZ : maxZ) >= -pyW &&
nzX * (nzX < 0 ? minX : maxX) + nzZ * (nzZ < 0 ? minZ : maxZ) >= -nzW &&
pzX * (pzX < 0 ? minX : maxX) + pzZ * (pzZ < 0 ? minZ : maxZ) >= -pzW;
}
/**
* Determine whether the given axis-aligned box is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler
* and, if the box is not inside this frustum, return the index of the plane that culled it.
* The box is specified via its <code>min</code> and <code>max</code> corner coordinates.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
*
* @param min
* the minimum corner coordinates of the axis-aligned box
* @param max
* the maximum corner coordinates of the axis-aligned box
* @return the index of the first plane that culled the box, if the box does not intersect the frustum;
* or {@link #INTERSECT} if the box intersects the frustum, or {@link #INSIDE} if the box is fully inside of the frustum.
* The plane index is one of {@link #PLANE_NX}, {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, {@link #PLANE_NZ} and {@link #PLANE_PZ}
*/
public int intersectAab(Vector3fc min, Vector3fc max) {
return intersectAab(min.x(), min.y(), min.z(), max.x(), max.y(), max.z());
}
/**
* Determine whether the given axis-aligned box is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler
* and, if the box is not inside this frustum, return the index of the plane that culled it.
* The box is specified via its min and max corner coordinates.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
* <p>
* Reference: <a href="http://old.cescg.org/CESCG-2002/DSykoraJJelinek/">Efficient View Frustum Culling</a>
*
* @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
* @return the index of the first plane that culled the box, if the box does not intersect the frustum,
* or {@link #INTERSECT} if the box intersects the frustum, or {@link #INSIDE} if the box is fully inside of the frustum.
* The plane index is one of {@link #PLANE_NX}, {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, {@link #PLANE_NZ} and {@link #PLANE_PZ}
*/
public int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
/*
* This is an implementation of the "2.4 Basic intersection test" of the mentioned site.
*
* In addition to the algorithm in the paper, this method also returns the index of the first plane that culled the box.
*/
int plane = PLANE_NX;
boolean inside = true;
if (nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) + nxZ * (nxZ < 0 ? minZ : maxZ) >= -nxW) {
plane = PLANE_PX;
inside &= nxX * (nxX < 0 ? maxX : minX) + nxY * (nxY < 0 ? maxY : minY) + nxZ * (nxZ < 0 ? maxZ : minZ) >= -nxW;
if (pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) + pxZ * (pxZ < 0 ? minZ : maxZ) >= -pxW) {
plane = PLANE_NY;
inside &= pxX * (pxX < 0 ? maxX : minX) + pxY * (pxY < 0 ? maxY : minY) + pxZ * (pxZ < 0 ? maxZ : minZ) >= -pxW;
if (nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) + nyZ * (nyZ < 0 ? minZ : maxZ) >= -nyW) {
plane = PLANE_PY;
inside &= nyX * (nyX < 0 ? maxX : minX) + nyY * (nyY < 0 ? maxY : minY) + nyZ * (nyZ < 0 ? maxZ : minZ) >= -nyW;
if (pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) + pyZ * (pyZ < 0 ? minZ : maxZ) >= -pyW) {
plane = PLANE_NZ;
inside &= pyX * (pyX < 0 ? maxX : minX) + pyY * (pyY < 0 ? maxY : minY) + pyZ * (pyZ < 0 ? maxZ : minZ) >= -pyW;
if (nzX * (nzX < 0 ? minX : maxX) + nzY * (nzY < 0 ? minY : maxY) + nzZ * (nzZ < 0 ? minZ : maxZ) >= -nzW) {
plane = PLANE_PZ;
inside &= nzX * (nzX < 0 ? maxX : minX) + nzY * (nzY < 0 ? maxY : minY) + nzZ * (nzZ < 0 ? maxZ : minZ) >= -nzW;
if (pzX * (pzX < 0 ? minX : maxX) + pzY * (pzY < 0 ? minY : maxY) + pzZ * (pzZ < 0 ? minZ : maxZ) >= -pzW) {
inside &= pzX * (pzX < 0 ? maxX : minX) + pzY * (pzY < 0 ? maxY : minY) + pzZ * (pzZ < 0 ? maxZ : minZ) >= -pzW;
return inside ? INSIDE : INTERSECT;
}
}
}
}
}
}
return plane;
}
/**
* Compute the signed distance from the given axis-aligned box to the <code>plane</code>.
*
* @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
* @param plane
* one of
* {@link #PLANE_NX}, {@link #PLANE_PX},
* {@link #PLANE_NY}, {@link #PLANE_PY},
* {@link #PLANE_NZ} and {@link #PLANE_PZ}
* @return the signed distance of the axis-aligned box to the plane
*/
public float distanceToPlane(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, int plane) {
return planes[plane].x * (planes[plane].x < 0 ? maxX : minX) + planes[plane].y * (planes[plane].y < 0 ? maxY : minY)
+ planes[plane].z * (planes[plane].z < 0 ? maxZ : minZ) + planes[plane].w;
}
/**
* Determine whether the given axis-aligned box is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler
* and, if the box is not inside this frustum, return the index of the plane that culled it.
* The box is specified via its <code>min</code> and <code>max</code> corner coordinates.
* <p>
* This method differs from {@link #intersectAab(Vector3fc, Vector3fc)} in that
* it allows to mask-off planes that should not be calculated. For example, in order to only test a box against the
* left frustum plane, use a mask of {@link #PLANE_MASK_NX}. Or in order to test all planes <i>except</i> the left plane, use
* a mask of <code>(~0 ^ PLANE_MASK_NX)</code>.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
*
* @param min
* the minimum corner coordinates of the axis-aligned box
* @param max
* the maximum corner coordinates of the axis-aligned box
* @param mask
* contains as bitset all the planes that should be tested.
* This value can be any combination of
* {@link #PLANE_MASK_NX}, {@link #PLANE_MASK_PX},
* {@link #PLANE_MASK_NY}, {@link #PLANE_MASK_PY},
* {@link #PLANE_MASK_NZ} and {@link #PLANE_MASK_PZ}
* @return the index of the first plane that culled the box, if the box does not intersect the frustum,
* or {@link #INTERSECT} if the box intersects the frustum, or {@link #INSIDE} if the box is fully inside of the frustum.
* The plane index is one of {@link #PLANE_NX}, {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, {@link #PLANE_NZ} and {@link #PLANE_PZ}
*/
public int intersectAab(Vector3fc min, Vector3fc max, int mask) {
return intersectAab(min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), mask);
}
/**
* Determine whether the given axis-aligned box is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler
* and, if the box is not inside this frustum, return the index of the plane that culled it.
* The box is specified via its min and max corner coordinates.
* <p>
* This method differs from {@link #intersectAab(float, float, float, float, float, float)} in that
* it allows to mask-off planes that should not be calculated. For example, in order to only test a box against the
* left frustum plane, use a mask of {@link #PLANE_MASK_NX}. Or in order to test all planes <i>except</i> the left plane, use
* a mask of <code>(~0 ^ PLANE_MASK_NX)</code>.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
* <p>
* Reference: <a href="http://old.cescg.org/CESCG-2002/DSykoraJJelinek/">Efficient View Frustum Culling</a>
*
* @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
* @param mask
* contains as bitset all the planes that should be tested.
* This value can be any combination of
* {@link #PLANE_MASK_NX}, {@link #PLANE_MASK_PX},
* {@link #PLANE_MASK_NY}, {@link #PLANE_MASK_PY},
* {@link #PLANE_MASK_NZ} and {@link #PLANE_MASK_PZ}
* @return the index of the first plane that culled the box, if the box does not intersect the frustum,
* or {@link #INTERSECT} if the box intersects the frustum, or {@link #INSIDE} if the box is fully inside of the frustum.
* The plane index is one of {@link #PLANE_NX}, {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, {@link #PLANE_NZ} and {@link #PLANE_PZ}
*/
public int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, int mask) {
/*
* This is an implementation of the first algorithm in "2.5 Plane masking and coherency" of the mentioned site.
*
* In addition to the algorithm in the paper, this method also returns the index of the first plane that culled the box.
*/
int plane = PLANE_NX;
boolean inside = true;
if ((mask & PLANE_MASK_NX) == 0 || nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) + nxZ * (nxZ < 0 ? minZ : maxZ) >= -nxW) {
plane = PLANE_PX;
inside &= nxX * (nxX < 0 ? maxX : minX) + nxY * (nxY < 0 ? maxY : minY) + nxZ * (nxZ < 0 ? maxZ : minZ) >= -nxW;
if ((mask & PLANE_MASK_PX) == 0 || pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) + pxZ * (pxZ < 0 ? minZ : maxZ) >= -pxW) {
plane = PLANE_NY;
inside &= pxX * (pxX < 0 ? maxX : minX) + pxY * (pxY < 0 ? maxY : minY) + pxZ * (pxZ < 0 ? maxZ : minZ) >= -pxW;
if ((mask & PLANE_MASK_NY) == 0 || nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) + nyZ * (nyZ < 0 ? minZ : maxZ) >= -nyW) {
plane = PLANE_PY;
inside &= nyX * (nyX < 0 ? maxX : minX) + nyY * (nyY < 0 ? maxY : minY) + nyZ * (nyZ < 0 ? maxZ : minZ) >= -nyW;
if ((mask & PLANE_MASK_PY) == 0 || pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) + pyZ * (pyZ < 0 ? minZ : maxZ) >= -pyW) {
plane = PLANE_NZ;
inside &= pyX * (pyX < 0 ? maxX : minX) + pyY * (pyY < 0 ? maxY : minY) + pyZ * (pyZ < 0 ? maxZ : minZ) >= -pyW;
if ((mask & PLANE_MASK_NZ) == 0 || nzX * (nzX < 0 ? minX : maxX) + nzY * (nzY < 0 ? minY : maxY) + nzZ * (nzZ < 0 ? minZ : maxZ) >= -nzW) {
plane = PLANE_PZ;
inside &= nzX * (nzX < 0 ? maxX : minX) + nzY * (nzY < 0 ? maxY : minY) + nzZ * (nzZ < 0 ? maxZ : minZ) >= -nzW;
if ((mask & PLANE_MASK_PZ) == 0 || pzX * (pzX < 0 ? minX : maxX) + pzY * (pzY < 0 ? minY : maxY) + pzZ * (pzZ < 0 ? minZ : maxZ) >= -pzW) {
inside &= pzX * (pzX < 0 ? maxX : minX) + pzY * (pzY < 0 ? maxY : minY) + pzZ * (pzZ < 0 ? maxZ : minZ) >= -pzW;
return inside ? INSIDE : INTERSECT;
}
}
}
}
}
}
return plane;
}
/**
* Determine whether the given axis-aligned box is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler
* and, if the box is not inside this frustum, return the index of the plane that culled it.
* The box is specified via its <code>min</code> and <code>max</code> corner coordinates.
* <p>
* This method differs from {@link #intersectAab(Vector3fc, Vector3fc)} in that
* it allows to mask-off planes that should not be calculated. For example, in order to only test a box against the
* left frustum plane, use a mask of {@link #PLANE_MASK_NX}. Or in order to test all planes <i>except</i> the left plane, use
* a mask of <code>(~0 ^ PLANE_MASK_NX)</code>.
* <p>
* In addition, the <code>startPlane</code> denotes the first frustum plane to test the box against. To use this effectively means to store the
* plane that previously culled an axis-aligned box (as returned by <code>intersectAab()</code>) and in the next frame use the return value
* as the argument to the <code>startPlane</code> parameter of this method. The assumption is that the plane that culled the object previously will also
* cull it now (temporal coherency) and the culling computation is likely reduced in that case.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
*
* @param min
* the minimum corner coordinates of the axis-aligned box
* @param max
* the maximum corner coordinates of the axis-aligned box
* @param mask
* contains as bitset all the planes that should be tested.
* This value can be any combination of
* {@link #PLANE_MASK_NX}, {@link #PLANE_MASK_PX},
* {@link #PLANE_MASK_NY}, {@link #PLANE_MASK_PY},
* {@link #PLANE_MASK_NZ} and {@link #PLANE_MASK_PZ}
* @param startPlane
* the first frustum plane to test the axis-aligned box against. It is one of
* {@link #PLANE_NX}, {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, {@link #PLANE_NZ} and {@link #PLANE_PZ}
* @return the index of the first plane that culled the box, if the box does not intersect the frustum,
* or {@link #INTERSECT} if the box intersects the frustum, or {@link #INSIDE} if the box is fully inside of the frustum.
* The plane index is one of {@link #PLANE_NX}, {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, {@link #PLANE_NZ} and {@link #PLANE_PZ}
*/
public int intersectAab(Vector3fc min, Vector3fc max, int mask, int startPlane) {
return intersectAab(min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), mask, startPlane);
}
/**
* Determine whether the given axis-aligned box is partly or completely within or outside of the frustum defined by <code>this</code> frustum culler
* and, if the box is not inside this frustum, return the index of the plane that culled it.
* The box is specified via its min and max corner coordinates.
* <p>
* This method differs from {@link #intersectAab(float, float, float, float, float, float)} in that
* it allows to mask-off planes that should not be calculated. For example, in order to only test a box against the
* left frustum plane, use a mask of {@link #PLANE_MASK_NX}. Or in order to test all planes <i>except</i> the left plane, use
* a mask of <code>(~0 ^ PLANE_MASK_NX)</code>.
* <p>
* In addition, the <code>startPlane</code> denotes the first frustum plane to test the box against. To use this effectively means to store the
* plane that previously culled an axis-aligned box (as returned by <code>intersectAab()</code>) and in the next frame use the return value
* as the argument to the <code>startPlane</code> parameter of this method. The assumption is that the plane that culled the object previously will also
* cull it now (temporal coherency) and the culling computation is likely reduced in that case.
* <p>
* The algorithm implemented by this method is conservative. This means that in certain circumstances a <i>false positive</i>
* can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum.
* See <a href="http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm">iquilezles.org</a> for an examination of this problem.
* <p>
* Reference: <a href="http://old.cescg.org/CESCG-2002/DSykoraJJelinek/">Efficient View Frustum Culling</a>
*
* @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
* @param mask
* contains as bitset all the planes that should be tested.
* This value can be any combination of
* {@link #PLANE_MASK_NX}, {@link #PLANE_MASK_PX},
* {@link #PLANE_MASK_NY}, {@link #PLANE_MASK_PY},
* {@link #PLANE_MASK_NZ} and {@link #PLANE_MASK_PZ}
* @param startPlane
* the first frustum plane to test the axis-aligned box against. It is one of
* {@link #PLANE_NX}, {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, {@link #PLANE_NZ} and {@link #PLANE_PZ}
* @return the index of the first plane that culled the box, if the box does not intersect the frustum,
* or {@link #INTERSECT} if the box intersects the frustum, or {@link #INSIDE} if the box is fully inside of the frustum.
* The plane index is one of {@link #PLANE_NX}, {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, {@link #PLANE_NZ} and {@link #PLANE_PZ}
*/
public int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, int mask, int startPlane) {
/*
* This is an implementation of the second algorithm in "2.5 Plane masking and coherency" of the mentioned site.
*
* In addition to the algorithm in the paper, this method also returns the index of the first plane that culled the box.
*/
int plane = startPlane;
boolean inside = true;
Vector4f p = planes[startPlane];
if ((mask & 1<<startPlane) != 0 && p.x * (p.x < 0 ? minX : maxX) + p.y * (p.y < 0 ? minY : maxY) + p.z * (p.z < 0 ? minZ : maxZ) < -p.w) {
return plane;
}
if ((mask & PLANE_MASK_NX) == 0 || nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) + nxZ * (nxZ < 0 ? minZ : maxZ) >= -nxW) {
plane = PLANE_PX;
inside &= nxX * (nxX < 0 ? maxX : minX) + nxY * (nxY < 0 ? maxY : minY) + nxZ * (nxZ < 0 ? maxZ : minZ) >= -nxW;
if ((mask & PLANE_MASK_PX) == 0 || pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) + pxZ * (pxZ < 0 ? minZ : maxZ) >= -pxW) {
plane = PLANE_NY;
inside &= pxX * (pxX < 0 ? maxX : minX) + pxY * (pxY < 0 ? maxY : minY) + pxZ * (pxZ < 0 ? maxZ : minZ) >= -pxW;
if ((mask & PLANE_MASK_NY) == 0 || nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) + nyZ * (nyZ < 0 ? minZ : maxZ) >= -nyW) {
plane = PLANE_PY;
inside &= nyX * (nyX < 0 ? maxX : minX) + nyY * (nyY < 0 ? maxY : minY) + nyZ * (nyZ < 0 ? maxZ : minZ) >= -nyW;
if ((mask & PLANE_MASK_PY) == 0 || pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) + pyZ * (pyZ < 0 ? minZ : maxZ) >= -pyW) {
plane = PLANE_NZ;
inside &= pyX * (pyX < 0 ? maxX : minX) + pyY * (pyY < 0 ? maxY : minY) + pyZ * (pyZ < 0 ? maxZ : minZ) >= -pyW;
if ((mask & PLANE_MASK_NZ) == 0 || nzX * (nzX < 0 ? minX : maxX) + nzY * (nzY < 0 ? minY : maxY) + nzZ * (nzZ < 0 ? minZ : maxZ) >= -nzW) {
plane = PLANE_PZ;
inside &= nzX * (nzX < 0 ? maxX : minX) + nzY * (nzY < 0 ? maxY : minY) + nzZ * (nzZ < 0 ? maxZ : minZ) >= -nzW;
if ((mask & PLANE_MASK_PZ) == 0 || pzX * (pzX < 0 ? minX : maxX) + pzY * (pzY < 0 ? minY : maxY) + pzZ * (pzZ < 0 ? minZ : maxZ) >= -pzW) {
inside &= pzX * (pzX < 0 ? maxX : minX) + pzY * (pzY < 0 ? maxY : minY) + pzZ * (pzZ < 0 ? maxZ : minZ) >= -pzW;
return inside ? INSIDE : INTERSECT;
}
}
}
}
}
}
return plane;
}
/**
* Test whether the given line segment, defined by the end points <code>a</code> and <code>b</code>,
* is partly or completely within the frustum defined by <code>this</code> frustum culler.
*
* @param a
* the line segment's first end point
* @param b
* the line segment's second end point
* @return <code>true</code> if the given line segment is partly or completely inside the frustum;
* <code>false</code> otherwise
*/
public boolean testLineSegment(Vector3fc a, Vector3fc b) {
return testLineSegment(a.x(), a.y(), a.z(), b.x(), b.y(), b.z());
}
/**
* Test whether the given line segment, defined by the end points <code>(aX, aY, aZ)</code> and <code>(bX, bY, bZ)</code>,
* is partly or completely within the frustum defined by <code>this</code> frustum culler.
*
* @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
* @return <code>true</code> if the given line segment is partly or completely inside the frustum;
* <code>false</code> otherwise
*/
public boolean testLineSegment(float aX, float aY, float aZ, float bX, float bY, float bZ) {
float da, db;
da = Math.fma(nxX, aX, Math.fma(nxY, aY, Math.fma(nxZ, aZ, nxW)));
db = Math.fma(nxX, bX, Math.fma(nxY, bY, Math.fma(nxZ, bZ, nxW)));
if (da < 0.0f && db < 0.0f)
return false;
if (da * db < 0.0f) {
float p = Math.abs(da) / Math.abs(db - da);
float dx = Math.fma(bX - aX, p, aX), dy = Math.fma(bY - aY, p, aY), dz = Math.fma(bZ - aZ, p, aZ);
if (da < 0.0f) {
aX = dx; aY = dy; aZ = dz;
} else {
bX = dx; bY = dy; bZ = dz;
}
}
da = Math.fma(pxX, aX, Math.fma(pxY, aY, Math.fma(pxZ, aZ, pxW)));
db = Math.fma(pxX, bX, Math.fma(pxY, bY, Math.fma(pxZ, bZ, pxW)));
if (da < 0.0f && db < 0.0f)
return false;
if (da * db < 0.0f) {
float p = Math.abs(da) / Math.abs(db - da);
float dx = Math.fma(bX - aX, p, aX), dy = Math.fma(bY - aY, p, aY), dz = Math.fma(bZ - aZ, p, aZ);
if (da < 0.0f) {
aX = dx; aY = dy; aZ = dz;
} else {
bX = dx; bY = dy; bZ = dz;
}
}
da = Math.fma(nyX, aX, Math.fma(nyY, aY, Math.fma(nyZ, aZ, nyW)));
db = Math.fma(nyX, bX, Math.fma(nyY, bY, Math.fma(nyZ, bZ, nyW)));
if (da < 0.0f && db < 0.0f)
return false;
if (da * db < 0.0f) {
float p = Math.abs(da) / Math.abs(db - da);
float dx = Math.fma(bX - aX, p, aX), dy = Math.fma(bY - aY, p, aY), dz = Math.fma(bZ - aZ, p, aZ);
if (da < 0.0f) {
aX = dx; aY = dy; aZ = dz;
} else {
bX = dx; bY = dy; bZ = dz;
}
}
da = Math.fma(pyX, aX, Math.fma(pyY, aY, Math.fma(pyZ, aZ, pyW)));
db = Math.fma(pyX, bX, Math.fma(pyY, bY, Math.fma(pyZ, bZ, pyW)));
if (da < 0.0f && db < 0.0f)
return false;
if (da * db < 0.0f) {
float p = Math.abs(da) / Math.abs(db - da);
float dx = Math.fma(bX - aX, p, aX), dy = Math.fma(bY - aY, p, aY), dz = Math.fma(bZ - aZ, p, aZ);
if (da < 0.0f) {
aX = dx; aY = dy; aZ = dz;
} else {
bX = dx; bY = dy; bZ = dz;
}
}
da = Math.fma(nzX, aX, Math.fma(nzY, aY, Math.fma(nzZ, aZ, nzW)));
db = Math.fma(nzX, bX, Math.fma(nzY, bY, Math.fma(nzZ, bZ, nzW)));
if (da < 0.0f && db < 0.0f)
return false;
if (da * db < 0.0f) {
float p = Math.abs(da) / Math.abs(db - da);
float dx = Math.fma(bX - aX, p, aX), dy = Math.fma(bY - aY, p, aY), dz = Math.fma(bZ - aZ, p, aZ);
if (da < 0.0f) {
aX = dx; aY = dy; aZ = dz;
} else {
bX = dx; bY = dy; bZ = dz;
}
}
da = Math.fma(pzX, aX, Math.fma(pzY, aY, Math.fma(pzZ, aZ, pzW)));
db = Math.fma(pzX, bX, Math.fma(pzY, bY, Math.fma(pzZ, bZ, pzW)));
return da >= 0.0f || db >= 0.0f;
}
}

View file

@ -0,0 +1,154 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Provides methods to compute rays through an arbitrary perspective transformation defined by a {@link Matrix4fc}.
* <p>
* This can be used to compute the eye-rays in simple software-based raycasting/raytracing.
* <p>
* To obtain the origin of the rays call {@link #origin(Vector3f)}.
* Then to compute the directions of subsequent rays use {@link #dir(float, float, Vector3f)}.
*
* @author Kai Burjack
*/
public class FrustumRayBuilder {
private float nxnyX, nxnyY, nxnyZ;
private float pxnyX, pxnyY, pxnyZ;
private float pxpyX, pxpyY, pxpyZ;
private float nxpyX, nxpyY, nxpyZ;
private float cx, cy, cz;
/**
* Create a new {@link FrustumRayBuilder} with an undefined frustum.
* <p>
* Before obtaining ray directions, make sure to define the frustum using {@link #set(Matrix4fc)}.
*/
public FrustumRayBuilder() {
}
/**
* Create a new {@link FrustumRayBuilder} from the given {@link Matrix4fc matrix} by extracing the matrix's frustum.
*
* @param m
* the {@link Matrix4fc} to create the frustum from
*/
public FrustumRayBuilder(Matrix4fc m) {
set(m);
}
/**
* Update the stored frustum corner rays and origin of <code>this</code> {@link FrustumRayBuilder} with the given {@link Matrix4fc matrix}.
* <p>
* Reference: <a href="http://gamedevs.org/uploads/fast-extraction-viewing-frustum-planes-from-world-view-projection-matrix.pdf">
* Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix</a>
* <p>
* Reference: <a href="http://geomalgorithms.com/a05-_intersect-1.html">http://geomalgorithms.com</a>
*
* @param m
* the {@link Matrix4fc matrix} to update the frustum corner rays and origin with
* @return this
*/
public FrustumRayBuilder set(Matrix4fc m) {
float nxX = m.m03() + m.m00(), nxY = m.m13() + m.m10(), nxZ = m.m23() + m.m20(), d1 = m.m33() + m.m30();
float pxX = m.m03() - m.m00(), pxY = m.m13() - m.m10(), pxZ = m.m23() - m.m20(), d2 = m.m33() - m.m30();
float nyX = m.m03() + m.m01(), nyY = m.m13() + m.m11(), nyZ = m.m23() + m.m21();
float pyX = m.m03() - m.m01(), pyY = m.m13() - m.m11(), pyZ = m.m23() - m.m21(), d3 = m.m33() - m.m31();
// bottom left
nxnyX = nyY * nxZ - nyZ * nxY;
nxnyY = nyZ * nxX - nyX * nxZ;
nxnyZ = nyX * nxY - nyY * nxX;
// bottom right
pxnyX = pxY * nyZ - pxZ * nyY;
pxnyY = pxZ * nyX - pxX * nyZ;
pxnyZ = pxX * nyY - pxY * nyX;
// top left
nxpyX = nxY * pyZ - nxZ * pyY;
nxpyY = nxZ * pyX - nxX * pyZ;
nxpyZ = nxX * pyY - nxY * pyX;
// top right
pxpyX = pyY * pxZ - pyZ * pxY;
pxpyY = pyZ * pxX - pyX * pxZ;
pxpyZ = pyX * pxY - pyY * pxX;
// compute origin
float pxnxX, pxnxY, pxnxZ;
pxnxX = pxY * nxZ - pxZ * nxY;
pxnxY = pxZ * nxX - pxX * nxZ;
pxnxZ = pxX * nxY - pxY * nxX;
float invDot = 1.0f / (nxX * pxpyX + nxY * pxpyY + nxZ * pxpyZ);
cx = (-pxpyX * d1 - nxpyX * d2 - pxnxX * d3) * invDot;
cy = (-pxpyY * d1 - nxpyY * d2 - pxnxY * d3) * invDot;
cz = (-pxpyZ * d1 - nxpyZ * d2 - pxnxZ * d3) * invDot;
return this;
}
/**
* Store the eye/origin of the perspective frustum in the given <code>origin</code>.
*
* @param origin
* will hold the perspective origin
* @return the <code>origin</code> vector
*/
public Vector3fc origin(Vector3f origin) {
origin.x = cx;
origin.y = cy;
origin.z = cz;
return origin;
}
/**
* Obtain the normalized direction of a ray starting at the center of the coordinate system and going
* through the near frustum plane.
* <p>
* The parameters <code>x</code> and <code>y</code> are used to interpolate the generated ray direction
* from the bottom-left to the top-right frustum corners.
*
* @param x
* the interpolation factor along the left-to-right frustum planes, within <code>[0..1]</code>
* @param y
* the interpolation factor along the bottom-to-top frustum planes, within <code>[0..1]</code>
* @param dir
* will hold the normalized ray direction
* @return the <code>dir</code> vector
*/
public Vector3fc dir(float x, float y, Vector3f dir) {
float y1x = nxnyX + (nxpyX - nxnyX) * y;
float y1y = nxnyY + (nxpyY - nxnyY) * y;
float y1z = nxnyZ + (nxpyZ - nxnyZ) * y;
float y2x = pxnyX + (pxpyX - pxnyX) * y;
float y2y = pxnyY + (pxpyY - pxnyY) * y;
float y2z = pxnyZ + (pxpyZ - pxnyZ) * y;
float dx = y1x + (y2x - y1x) * x;
float dy = y1y + (y2y - y1y) * x;
float dz = y1z + (y2z - y1z) * x;
// normalize the vector
float invLen = Math.invsqrt(dx * dx + dy * dy + dz * dz);
dir.x = dx * invLen;
dir.y = dy * invLen;
dir.z = dz * invLen;
return dir;
}
}

View file

@ -0,0 +1,247 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Useful geometry methods.
*
* @author Kai Burjack
* @author Richard Greenlees
*/
public class GeometryUtils {
/**
* Compute two arbitrary vectors perpendicular to the given normalized vector <code>(x, y, z)</code>, and store them in <code>dest1</code> and <code>dest2</code>,
* respectively.
* <p>
* The computed vectors will themselves be perpendicular to each another and normalized. So the tree vectors <code>(x, y, z)</code>, <code>dest1</code> and
* <code>dest2</code> form an orthonormal basis.
*
* @param x
* the x coordinate of the normalized input vector
* @param y
* the y coordinate of the normalized input vector
* @param z
* the z coordinate of the normalized input vector
* @param dest1
* will hold the first perpendicular vector
* @param dest2
* will hold the second perpendicular vector
*/
public static void perpendicular(float x, float y, float z, Vector3f dest1, Vector3f dest2) {
float magX = z * z + y * y;
float magY = z * z + x * x;
float magZ = y * y + x * x;
float mag;
if (magX > magY && magX > magZ) {
dest1.x = 0;
dest1.y = z;
dest1.z = -y;
mag = magX;
} else if (magY > magZ) {
dest1.x = -z;
dest1.y = 0;
dest1.z = x;
mag = magY;
} else {
dest1.x = y;
dest1.y = -x;
dest1.z = 0;
mag = magZ;
}
float len = Math.invsqrt(mag);
dest1.x *= len;
dest1.y *= len;
dest1.z *= len;
dest2.x = y * dest1.z - z * dest1.y;
dest2.y = z * dest1.x - x * dest1.z;
dest2.z = x * dest1.y - y * dest1.x;
}
/**
* Compute two arbitrary vectors perpendicular to the given normalized vector <code>v</code>, and store them in <code>dest1</code> and <code>dest2</code>,
* respectively.
* <p>
* The computed vectors will themselves be perpendicular to each another and normalized. So the tree vectors <code>v</code>, <code>dest1</code> and
* <code>dest2</code> form an orthonormal basis.
*
* @param v
* the {@link Vector3f#normalize() normalized} input vector
* @param dest1
* will hold the first perpendicular vector
* @param dest2
* will hold the second perpendicular vector
*/
public static void perpendicular(Vector3fc v, Vector3f dest1, Vector3f dest2) {
perpendicular(v.x(), v.y(), v.z(), dest1, dest2);
}
/**
* Calculate the normal of a surface defined by points <code>v1</code>, <code>v2</code> and <code>v3</code> and store it in <code>dest</code>.
*
* @param v0
* the first position
* @param v1
* the second position
* @param v2
* the third position
* @param dest
* will hold the result
*/
public static void normal(Vector3fc v0, Vector3fc v1, Vector3fc v2, Vector3f dest) {
normal(v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z(), v2.x(), v2.y(), v2.z(), dest);
}
/**
* Calculate the normal of a surface defined by points <code>(v1X, v1Y, v1Z)</code>, <code>(v2X, v2Y, v2Z)</code> and <code>(v3X, v3Y, v3Z)</code>
* and store it in <code>dest</code>.
*
* @param v0X
* the x coordinate of the first position
* @param v0Y
* the y coordinate of the first position
* @param v0Z
* the z coordinate of the first position
* @param v1X
* the x coordinate of the second position
* @param v1Y
* the y coordinate of the second position
* @param v1Z
* the z coordinate of the second position
* @param v2X
* the x coordinate of the third position
* @param v2Y
* the y coordinate of the third position
* @param v2Z
* the z coordinate of the third position
* @param dest
* will hold the result
*/
public static void normal(float v0X, float v0Y, float v0Z, float v1X, float v1Y, float v1Z, float v2X, float v2Y, float v2Z, Vector3f dest) {
dest.x = ((v1Y - v0Y) * (v2Z - v0Z)) - ((v1Z - v0Z) * (v2Y - v0Y));
dest.y = ((v1Z - v0Z) * (v2X - v0X)) - ((v1X - v0X) * (v2Z - v0Z));
dest.z = ((v1X - v0X) * (v2Y - v0Y)) - ((v1Y - v0Y) * (v2X - v0X));
dest.normalize();
}
/**
* Calculate the surface tangent for the three supplied vertices and UV coordinates and store the result in <code>dest</code>.
*
* @param v1
* XYZ of first vertex
* @param uv1
* UV of first vertex
* @param v2
* XYZ of second vertex
* @param uv2
* UV of second vertex
* @param v3
* XYZ of third vertex
* @param uv3
* UV of third vertex
* @param dest
* the tangent will be stored here
*/
public static void tangent(Vector3fc v1, Vector2fc uv1, Vector3fc v2, Vector2fc uv2, Vector3fc v3, Vector2fc uv3, Vector3f dest) {
float DeltaV1 = uv2.y() - uv1.y();
float DeltaV2 = uv3.y() - uv1.y();
float f = 1.0f / ((uv2.x() - uv1.x()) * DeltaV2 - (uv3.x() - uv1.x()) * DeltaV1);
dest.x = f * (DeltaV2 * (v2.x() - v1.x()) - DeltaV1 * (v3.x() - v1.x()));
dest.y = f * (DeltaV2 * (v2.y() - v1.y()) - DeltaV1 * (v3.y() - v1.y()));
dest.z = f * (DeltaV2 * (v2.z() - v1.z()) - DeltaV1 * (v3.z() - v1.z()));
dest.normalize();
}
/**
* Calculate the surface bitangent for the three supplied vertices and UV coordinates and store the result in <code>dest</code>.
*
* @param v1
* XYZ of first vertex
* @param uv1
* UV of first vertex
* @param v2
* XYZ of second vertex
* @param uv2
* UV of second vertex
* @param v3
* XYZ of third vertex
* @param uv3
* UV of third vertex
* @param dest
* the binormal will be stored here
*/
public static void bitangent(Vector3fc v1, Vector2fc uv1, Vector3fc v2, Vector2fc uv2, Vector3fc v3, Vector2fc uv3, Vector3f dest) {
float DeltaU1 = uv2.x() - uv1.x();
float DeltaU2 = uv3.x() - uv1.x();
float f = 1.0f / (DeltaU1 * (uv3.y() - uv1.y()) - DeltaU2 * (uv2.y() - uv1.y()));
dest.x = f * (-DeltaU2 * (v2.x() - v1.x()) + DeltaU1 * (v3.x() - v1.x()));
dest.y = f * (-DeltaU2 * (v2.y() - v1.y()) + DeltaU1 * (v3.y() - v1.y()));
dest.z = f * (-DeltaU2 * (v2.z() - v1.z()) + DeltaU1 * (v3.z() - v1.z()));
dest.normalize();
}
/**
* Calculate the surface tangent and bitangent for the three supplied vertices and UV coordinates and store the result in <code>dest</code>.
*
* @param v1
* XYZ of first vertex
* @param uv1
* UV of first vertex
* @param v2
* XYZ of second vertex
* @param uv2
* UV of second vertex
* @param v3
* XYZ of third vertex
* @param uv3
* UV of third vertex
* @param destTangent
* the tangent will be stored here
* @param destBitangent
* the bitangent will be stored here
*/
public static void tangentBitangent(Vector3fc v1, Vector2fc uv1, Vector3fc v2, Vector2fc uv2, Vector3fc v3, Vector2fc uv3, Vector3f destTangent, Vector3f destBitangent) {
float DeltaV1 = uv2.y() - uv1.y();
float DeltaV2 = uv3.y() - uv1.y();
float DeltaU1 = uv2.x() - uv1.x();
float DeltaU2 = uv3.x() - uv1.x();
float f = 1.0f / (DeltaU1 * DeltaV2 - DeltaU2 * DeltaV1);
destTangent.x = f * (DeltaV2 * (v2.x() - v1.x()) - DeltaV1 * (v3.x() - v1.x()));
destTangent.y = f * (DeltaV2 * (v2.y() - v1.y()) - DeltaV1 * (v3.y() - v1.y()));
destTangent.z = f * (DeltaV2 * (v2.z() - v1.z()) - DeltaV1 * (v3.z() - v1.z()));
destTangent.normalize();
destBitangent.x = f * (-DeltaU2 * (v2.x() - v1.x()) + DeltaU1 * (v3.x() - v1.x()));
destBitangent.y = f * (-DeltaU2 * (v2.y() - v1.y()) + DeltaU1 * (v3.y() - v1.y()));
destBitangent.z = f * (-DeltaU2 * (v2.z() - v1.z()) + DeltaU1 * (v3.z() - v1.z()));
destBitangent.normalize();
}
}

View file

@ -0,0 +1,337 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Contains various interpolation functions.
*
* @author Kai Burjack
*/
public class Interpolationd {
/**
* Bilinearly interpolate the single scalar value <i>f</i> over the given triangle.
* <p>
* Reference: <a href="https://en.wikipedia.org/wiki/Barycentric_coordinate_system">https://en.wikipedia.org/</a>
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y coordinate of the first triangle vertex
* @param f0
* the value of <i>f</i> at the first vertex
* @param v1X
* the x coordinate of the second triangle vertex
* @param v1Y
* the y coordinate of the second triangle vertex
* @param f1
* the value of <i>f</i> at the second vertex
* @param v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param f2
* the value of <i>f</i> at the third vertex
* @param x
* the x coordinate of the point to interpolate <i>f</i> at
* @param y
* the y coordinate of the point to interpolate <i>f</i> at
* @return the interpolated value of <i>f</i>
*/
public static double interpolateTriangle(
double v0X, double v0Y, double f0,
double v1X, double v1Y, double f1,
double v2X, double v2Y, double f2,
double x, double y) {
double v12Y = v1Y - v2Y;
double v21X = v2X - v1X;
double v02X = v0X - v2X;
double yv2Y = y - v2Y;
double xv2X = x - v2X;
double v02Y = v0Y - v2Y;
double invDen = 1.0 / (v12Y * v02X + v21X * v02Y);
double l1 = (v12Y * xv2X + v21X * yv2Y) * invDen;
double l2 = (v02X * yv2Y - v02Y * xv2X) * invDen;
return l1 * f0 + l2 * f1 + (1.0f - l1 - l2) * f2;
}
/**
* Bilinearly interpolate the two-dimensional vector <i>f</i> over the given triangle and store the result in <code>dest</code>.
* <p>
* Reference: <a href="https://en.wikipedia.org/wiki/Barycentric_coordinate_system">https://en.wikipedia.org/</a>
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y coordinate of the first triangle vertex
* @param f0X
* the x component of the value of <i>f</i> at the first vertex
* @param f0Y
* the y component of the value of <i>f</i> at the first vertex
* @param v1X
* the x coordinate of the second triangle vertex
* @param v1Y
* the y coordinate of the second triangle vertex
* @param f1X
* the x component of the value of <i>f</i> at the second vertex
* @param f1Y
* the y component of the value of <i>f</i> at the second vertex
* @param v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param f2X
* the x component of the value of <i>f</i> at the third vertex
* @param f2Y
* the y component of the value of <i>f</i> at the third vertex
* @param x
* the x coordinate of the point to interpolate <i>f</i> at
* @param y
* the y coordinate of the point to interpolate <i>f</i> at
* @param dest
* will hold the interpolation result
* @return dest
*/
public static Vector2d interpolateTriangle(
double v0X, double v0Y, double f0X, double f0Y,
double v1X, double v1Y, double f1X, double f1Y,
double v2X, double v2Y, double f2X, double f2Y,
double x, double y, Vector2d dest) {
double v12Y = v1Y - v2Y;
double v21X = v2X - v1X;
double v02X = v0X - v2X;
double yv2Y = y - v2Y;
double xv2X = x - v2X;
double v02Y = v0Y - v2Y;
double invDen = 1.0 / (v12Y * v02X + v21X * v02Y);
double l1 = (v12Y * xv2X + v21X * yv2Y) * invDen;
double l2 = (v02X * yv2Y - v02Y * xv2X) * invDen;
double l3 = 1.0 - l1 - l2;
dest.x = l1 * f0X + l2 * f1X + l3 * f2X;
dest.y = l1 * f0Y + l2 * f1Y + l3 * f2Y;
return dest;
}
/**
* Compute the first-order derivative of a linear two-dimensional function <i>f</i> with respect to X
* and store the result in <code>dest</code>.
* <p>
* This method computes the constant rate of change for <i>f</i> given the three values of <i>f</i>
* at the specified three inputs <code>(v0X, v0Y)</code>, <code>(v1X, v1Y)</code> and <code>(v2X, v2Y)</code>.
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y coordinate of the first triangle vertex
* @param f0X
* the x component of the value of <i>f</i> at the first vertex
* @param f0Y
* the y component of the value of <i>f</i> at the first vertex
* @param v1X
* the x coordinate of the second triangle vertex
* @param v1Y
* the y coordinate of the second triangle vertex
* @param f1X
* the x component of the value of <i>f</i> at the second vertex
* @param f1Y
* the y component of the value of <i>f</i> at the second vertex
* @param v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param f2X
* the x component of the value of <i>f</i> at the third vertex
* @param f2Y
* the y component of the value of <i>f</i> at the third vertex
* @param dest
* will hold the result
* @return dest
*/
public static Vector2d dFdxLinear(
double v0X, double v0Y, double f0X, double f0Y,
double v1X, double v1Y, double f1X, double f1Y,
double v2X, double v2Y, double f2X, double f2Y, Vector2d dest) {
double v12Y = v1Y - v2Y;
double v02Y = v0Y - v2Y;
double den = v12Y * (v0X - v2X) + (v2X - v1X) * v02Y;
double l3_1 = den - v12Y + v02Y;
double invDen = 1.0f / den;
dest.x = invDen * (v12Y * f0X - v02Y * f1X + l3_1 * f2X) - f2X;
dest.y = invDen * (v12Y * f0Y - v02Y * f1Y + l3_1 * f2Y) - f2Y;
return dest;
}
/**
* Compute the first-order derivative of a linear two-dimensional function <i>f</i> with respect to Y
* and store the result in <code>dest</code>.
* <p>
* This method computes the constant rate of change for <i>f</i> given the three values of <i>f</i>
* at the specified three inputs <code>(v0X, v0Y)</code>, <code>(v1X, v1Y)</code> and <code>(v2X, v2Y)</code>.
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y coordinate of the first triangle vertex
* @param f0X
* the x component of the value of <i>f</i> at the first vertex
* @param f0Y
* the y component of the value of <i>f</i> at the first vertex
* @param v1X
* the x coordinate of the second triangle vertex
* @param v1Y
* the y coordinate of the second triangle vertex
* @param f1X
* the x component of the value of <i>f</i> at the second vertex
* @param f1Y
* the y component of the value of <i>f</i> at the second vertex
* @param v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param f2X
* the x component of the value of <i>f</i> at the third vertex
* @param f2Y
* the y component of the value of <i>f</i> at the third vertex
* @param dest
* will hold the result
* @return dest
*/
public static Vector2d dFdyLinear(
double v0X, double v0Y, double f0X, double f0Y,
double v1X, double v1Y, double f1X, double f1Y,
double v2X, double v2Y, double f2X, double f2Y,
Vector2d dest) {
double v21X = v2X - v1X;
double v02X = v0X - v2X;
double den = (v1Y - v2Y) * v02X + v21X * (v0Y - v2Y);
double l3_1 = den - v21X - v02X;
double invDen = 1.0f / den;
dest.x = invDen * (v21X * f0X + v02X * f1X + l3_1 * f2X) - f2X;
dest.y = invDen * (v21X * f0Y + v02X * f1Y + l3_1 * f2Y) - f2Y;
return dest;
}
/**
* Bilinearly interpolate the three-dimensional vector <i>f</i> over the given triangle and store the result in <code>dest</code>.
* <p>
* Reference: <a href="https://en.wikipedia.org/wiki/Barycentric_coordinate_system">https://en.wikipedia.org/</a>
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y coordinate of the first triangle vertex
* @param f0X
* the x component of the value of <i>f</i> at the first vertex
* @param f0Y
* the y component of the value of <i>f</i> at the first vertex
* @param f0Z
* the z component of the value of <i>f</i> at the first vertex
* @param v1X
* the x coordinate of the second triangle vertex
* @param v1Y
* the y coordinate of the second triangle vertex
* @param f1X
* the x component of the value of <i>f</i> at the second vertex
* @param f1Y
* the y component of the value of <i>f</i> at the second vertex
* @param f1Z
* the z component of the value of <i>f</i> at the second vertex
* @param v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param f2X
* the x component of the value of <i>f</i> at the third vertex
* @param f2Y
* the y component of the value of <i>f</i> at the third vertex
* @param f2Z
* the z component of the value of <i>f</i> at the third vertex
* @param x
* the x coordinate of the point to interpolate <i>f</i> at
* @param y
* the y coordinate of the point to interpolate <i>f</i> at
* @param dest
* will hold the interpolation result
* @return dest
*/
public static Vector3d interpolateTriangle(
double v0X, double v0Y, double f0X, double f0Y, double f0Z,
double v1X, double v1Y, double f1X, double f1Y, double f1Z,
double v2X, double v2Y, double f2X, double f2Y, double f2Z,
double x, double y, Vector3d dest) {
// compute interpolation factors
Vector3d t = dest;
interpolationFactorsTriangle(v0X, v0Y, v1X, v1Y, v2X, v2Y, x, y, t);
// interpolate using these factors
return dest.set(t.x * f0X + t.y * f1X + t.z * f2X,
t.x * f0Y + t.y * f1Y + t.z * f2Y,
t.x * f0Z + t.y * f1Z + t.z * f2Z);
}
/**
* Compute the interpolation factors <code>(t0, t1, t2)</code> in order to interpolate an arbitrary value over a given
* triangle at the given point <code>(x, y)</code>.
* <p>
* This method takes in the 2D vertex positions of the three vertices of a triangle and stores in <code>dest</code> the
* factors <code>(t0, t1, t2)</code> in the equation <code>v' = v0 * t0 + v1 * t1 + v2 * t2</code> where <code>(v0, v1, v2)</code> are
* arbitrary (scalar or vector) values associated with the respective vertices of the triangle. The computed value <code>v'</code>
* is the interpolated value at the given position <code>(x, y)</code>.
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y 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 v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param x
* the x coordinate of the point to interpolate at
* @param y
* the y coordinate of the point to interpolate at
* @param dest
* will hold the interpolation factors <code>(t0, t1, t2)</code>
* @return dest
*/
public static Vector3d interpolationFactorsTriangle(
double v0X, double v0Y, double v1X, double v1Y, double v2X, double v2Y,
double x, double y, Vector3d dest) {
double v12Y = v1Y - v2Y;
double v21X = v2X - v1X;
double v02X = v0X - v2X;
double yv2Y = y - v2Y;
double xv2X = x - v2X;
double v02Y = v0Y - v2Y;
double invDen = 1.0 / (v12Y * v02X + v21X * v02Y);
dest.x = (v12Y * xv2X + v21X * yv2Y) * invDen;
dest.y = (v02X * yv2Y - v02Y * xv2X) * invDen;
dest.z = 1.0 - dest.x - dest.y;
return dest;
}
}

View file

@ -0,0 +1,337 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Contains various interpolation functions.
*
* @author Kai Burjack
*/
public class Interpolationf {
/**
* Bilinearly interpolate the single scalar value <i>f</i> over the given triangle.
* <p>
* Reference: <a href="https://en.wikipedia.org/wiki/Barycentric_coordinate_system">https://en.wikipedia.org/</a>
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y coordinate of the first triangle vertex
* @param f0
* the value of <i>f</i> at the first vertex
* @param v1X
* the x coordinate of the second triangle vertex
* @param v1Y
* the y coordinate of the second triangle vertex
* @param f1
* the value of <i>f</i> at the second vertex
* @param v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param f2
* the value of <i>f</i> at the third vertex
* @param x
* the x coordinate of the point to interpolate <i>f</i> at
* @param y
* the y coordinate of the point to interpolate <i>f</i> at
* @return the interpolated value of <i>f</i>
*/
public static float interpolateTriangle(
float v0X, float v0Y, float f0,
float v1X, float v1Y, float f1,
float v2X, float v2Y, float f2,
float x, float y) {
float v12Y = v1Y - v2Y;
float v21X = v2X - v1X;
float v02X = v0X - v2X;
float yv2Y = y - v2Y;
float xv2X = x - v2X;
float v02Y = v0Y - v2Y;
float invDen = 1.0f / (v12Y * v02X + v21X * v02Y);
float l1 = (v12Y * xv2X + v21X * yv2Y) * invDen;
float l2 = (v02X * yv2Y - v02Y * xv2X) * invDen;
return l1 * f0 + l2 * f1 + (1.0f - l1 - l2) * f2;
}
/**
* Bilinearly interpolate the two-dimensional vector <i>f</i> over the given triangle and store the result in <code>dest</code>.
* <p>
* Reference: <a href="https://en.wikipedia.org/wiki/Barycentric_coordinate_system">https://en.wikipedia.org/</a>
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y coordinate of the first triangle vertex
* @param f0X
* the x component of the value of <i>f</i> at the first vertex
* @param f0Y
* the y component of the value of <i>f</i> at the first vertex
* @param v1X
* the x coordinate of the second triangle vertex
* @param v1Y
* the y coordinate of the second triangle vertex
* @param f1X
* the x component of the value of <i>f</i> at the second vertex
* @param f1Y
* the y component of the value of <i>f</i> at the second vertex
* @param v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param f2X
* the x component of the value of <i>f</i> at the third vertex
* @param f2Y
* the y component of the value of <i>f</i> at the third vertex
* @param x
* the x coordinate of the point to interpolate <i>f</i> at
* @param y
* the y coordinate of the point to interpolate <i>f</i> at
* @param dest
* will hold the interpolation result
* @return dest
*/
public static Vector2f interpolateTriangle(
float v0X, float v0Y, float f0X, float f0Y,
float v1X, float v1Y, float f1X, float f1Y,
float v2X, float v2Y, float f2X, float f2Y,
float x, float y, Vector2f dest) {
float v12Y = v1Y - v2Y;
float v21X = v2X - v1X;
float v02X = v0X - v2X;
float yv2Y = y - v2Y;
float xv2X = x - v2X;
float v02Y = v0Y - v2Y;
float invDen = 1.0f / (v12Y * v02X + v21X * v02Y);
float l1 = (v12Y * xv2X + v21X * yv2Y) * invDen;
float l2 = (v02X * yv2Y - v02Y * xv2X) * invDen;
float l3 = 1.0f - l1 - l2;
dest.x = l1 * f0X + l2 * f1X + l3 * f2X;
dest.y = l1 * f0Y + l2 * f1Y + l3 * f2Y;
return dest;
}
/**
* Compute the first-order derivative of a linear two-dimensional function <i>f</i> with respect to X
* and store the result in <code>dest</code>.
* <p>
* This method computes the constant rate of change for <i>f</i> given the three values of <i>f</i>
* at the specified three inputs <code>(v0X, v0Y)</code>, <code>(v1X, v1Y)</code> and <code>(v2X, v2Y)</code>.
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y coordinate of the first triangle vertex
* @param f0X
* the x component of the value of <i>f</i> at the first vertex
* @param f0Y
* the y component of the value of <i>f</i> at the first vertex
* @param v1X
* the x coordinate of the second triangle vertex
* @param v1Y
* the y coordinate of the second triangle vertex
* @param f1X
* the x component of the value of <i>f</i> at the second vertex
* @param f1Y
* the y component of the value of <i>f</i> at the second vertex
* @param v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param f2X
* the x component of the value of <i>f</i> at the third vertex
* @param f2Y
* the y component of the value of <i>f</i> at the third vertex
* @param dest
* will hold the result
* @return dest
*/
public static Vector2f dFdxLinear(
float v0X, float v0Y, float f0X, float f0Y,
float v1X, float v1Y, float f1X, float f1Y,
float v2X, float v2Y, float f2X, float f2Y, Vector2f dest) {
float v12Y = v1Y - v2Y;
float v02Y = v0Y - v2Y;
float den = v12Y * (v0X - v2X) + (v2X - v1X) * v02Y;
float l3_1 = den - v12Y + v02Y;
float invDen = 1.0f / den;
dest.x = invDen * (v12Y * f0X - v02Y * f1X + l3_1 * f2X) - f2X;
dest.y = invDen * (v12Y * f0Y - v02Y * f1Y + l3_1 * f2Y) - f2Y;
return dest;
}
/**
* Compute the first-order derivative of a linear two-dimensional function <i>f</i> with respect to Y
* and store the result in <code>dest</code>.
* <p>
* This method computes the constant rate of change for <i>f</i> given the three values of <i>f</i>
* at the specified three inputs <code>(v0X, v0Y)</code>, <code>(v1X, v1Y)</code> and <code>(v2X, v2Y)</code>.
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y coordinate of the first triangle vertex
* @param f0X
* the x component of the value of <i>f</i> at the first vertex
* @param f0Y
* the y component of the value of <i>f</i> at the first vertex
* @param v1X
* the x coordinate of the second triangle vertex
* @param v1Y
* the y coordinate of the second triangle vertex
* @param f1X
* the x component of the value of <i>f</i> at the second vertex
* @param f1Y
* the y component of the value of <i>f</i> at the second vertex
* @param v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param f2X
* the x component of the value of <i>f</i> at the third vertex
* @param f2Y
* the y component of the value of <i>f</i> at the third vertex
* @param dest
* will hold the result
* @return dest
*/
public static Vector2f dFdyLinear(
float v0X, float v0Y, float f0X, float f0Y,
float v1X, float v1Y, float f1X, float f1Y,
float v2X, float v2Y, float f2X, float f2Y,
Vector2f dest) {
float v21X = v2X - v1X;
float v02X = v0X - v2X;
float den = (v1Y - v2Y) * v02X + v21X * (v0Y - v2Y);
float l3_1 = den - v21X - v02X;
float invDen = 1.0f / den;
dest.x = invDen * (v21X * f0X + v02X * f1X + l3_1 * f2X) - f2X;
dest.y = invDen * (v21X * f0Y + v02X * f1Y + l3_1 * f2Y) - f2Y;
return dest;
}
/**
* Bilinearly interpolate the three-dimensional vector <i>f</i> over the given triangle and store the result in <code>dest</code>.
* <p>
* Reference: <a href="https://en.wikipedia.org/wiki/Barycentric_coordinate_system">https://en.wikipedia.org/</a>
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y coordinate of the first triangle vertex
* @param f0X
* the x component of the value of <i>f</i> at the first vertex
* @param f0Y
* the y component of the value of <i>f</i> at the first vertex
* @param f0Z
* the z component of the value of <i>f</i> at the first vertex
* @param v1X
* the x coordinate of the second triangle vertex
* @param v1Y
* the y coordinate of the second triangle vertex
* @param f1X
* the x component of the value of <i>f</i> at the second vertex
* @param f1Y
* the y component of the value of <i>f</i> at the second vertex
* @param f1Z
* the z component of the value of <i>f</i> at the second vertex
* @param v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param f2X
* the x component of the value of <i>f</i> at the third vertex
* @param f2Y
* the y component of the value of <i>f</i> at the third vertex
* @param f2Z
* the z component of the value of <i>f</i> at the third vertex
* @param x
* the x coordinate of the point to interpolate <i>f</i> at
* @param y
* the y coordinate of the point to interpolate <i>f</i> at
* @param dest
* will hold the interpolation result
* @return dest
*/
public static Vector3f interpolateTriangle(
float v0X, float v0Y, float f0X, float f0Y, float f0Z,
float v1X, float v1Y, float f1X, float f1Y, float f1Z,
float v2X, float v2Y, float f2X, float f2Y, float f2Z,
float x, float y, Vector3f dest) {
// compute interpolation factors
Vector3f t = dest;
interpolationFactorsTriangle(v0X, v0Y, v1X, v1Y, v2X, v2Y, x, y, t);
// interpolate using these factors
return dest.set(t.x * f0X + t.y * f1X + t.z * f2X,
t.x * f0Y + t.y * f1Y + t.z * f2Y,
t.x * f0Z + t.y * f1Z + t.z * f2Z);
}
/**
* Compute the interpolation factors <code>(t0, t1, t2)</code> in order to interpolate an arbitrary value over a given
* triangle at the given point <code>(x, y)</code>.
* <p>
* This method takes in the 2D vertex positions of the three vertices of a triangle and stores in <code>dest</code> the
* factors <code>(t0, t1, t2)</code> in the equation <code>v' = v0 * t0 + v1 * t1 + v2 * t2</code> where <code>(v0, v1, v2)</code> are
* arbitrary (scalar or vector) values associated with the respective vertices of the triangle. The computed value <code>v'</code>
* is the interpolated value at the given position <code>(x, y)</code>.
*
* @param v0X
* the x coordinate of the first triangle vertex
* @param v0Y
* the y 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 v2X
* the x coordinate of the third triangle vertex
* @param v2Y
* the y coordinate of the third triangle vertex
* @param x
* the x coordinate of the point to interpolate at
* @param y
* the y coordinate of the point to interpolate at
* @param dest
* will hold the interpolation factors <code>(t0, t1, t2)</code>
* @return dest
*/
public static Vector3f interpolationFactorsTriangle(
float v0X, float v0Y, float v1X, float v1Y, float v2X, float v2Y,
float x, float y, Vector3f dest) {
float v12Y = v1Y - v2Y;
float v21X = v2X - v1X;
float v02X = v0X - v2X;
float yv2Y = y - v2Y;
float xv2X = x - v2X;
float v02Y = v0Y - v2Y;
float invDen = 1.0f / (v12Y * v02X + v21X * v02Y);
dest.x = (v12Y * xv2X + v21X * yv2Y) * invDen;
dest.y = (v02X * yv2Y - v02Y * xv2X) * invDen;
dest.z = 1.0f - dest.x - dest.y;
return dest;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,566 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Contains fast approximations of some {@link java.lang.Math} operations.
* <p>
* By default, {@link java.lang.Math} methods will be used by all other JOML classes. In order to use the approximations in this class, start the JVM with the parameter <code>-Djoml.fastmath</code>.
* <p>
* There are two algorithms for approximating sin/cos:
* <ol>
* <li>arithmetic <a href="http://www.java-gaming.org/topics/joml-1-8-0-release/37491/msg/361815/view.html#msg361815">polynomial approximation</a> contributed by roquendm
* <li>theagentd's <a href="http://www.java-gaming.org/topics/extremely-fast-sine-cosine/36469/msg/346213/view.html#msg346213">linear interpolation</a> variant of Riven's algorithm from
* <a href="http://www.java-gaming.org/topics/extremely-fast-sine-cosine/36469/view.html">http://www.java-gaming.org/</a>
* </ol>
* By default, the first algorithm is being used. In order to use the second one, start the JVM with <code>-Djoml.sinLookup</code>. The lookup table bit length of the second algorithm can also be adjusted
* for improved accuracy via <code>-Djoml.sinLookup.bits=&lt;n&gt;</code>, where &lt;n&gt; is the number of bits of the lookup table.
*
* @author Kai Burjack
*/
public class Math {
/*
* The following implementation of an approximation of sine and cosine was
* thankfully donated by Riven from http://java-gaming.org/.
*
* The code for linear interpolation was gratefully donated by theagentd
* from the same site.
*/
public static final double PI = java.lang.Math.PI;
static final double PI2 = PI * 2.0;
static final float PI_f = (float) java.lang.Math.PI;
static final float PI2_f = PI_f * 2.0f;
static final double PIHalf = PI * 0.5;
static final float PIHalf_f = (float) (PI * 0.5);
static final double PI_4 = PI * 0.25;
static final double PI_INV = 1.0 / PI;
private static final int lookupBits = Options.SIN_LOOKUP_BITS;
private static final int lookupTableSize = 1 << lookupBits;
private static final int lookupTableSizeMinus1 = lookupTableSize - 1;
private static final int lookupTableSizeWithMargin = lookupTableSize + 1;
private static final float pi2OverLookupSize = PI2_f / lookupTableSize;
private static final float lookupSizeOverPi2 = lookupTableSize / PI2_f;
private static final float sinTable[];
static {
if (Options.FASTMATH && Options.SIN_LOOKUP) {
sinTable = new float[lookupTableSizeWithMargin];
for (int i = 0; i < lookupTableSizeWithMargin; i++) {
double d = i * pi2OverLookupSize;
sinTable[i] = (float) java.lang.Math.sin(d);
}
} else {
sinTable = null;
}
}
private static final double c1 = Double.longBitsToDouble(-4628199217061079772L);
private static final double c2 = Double.longBitsToDouble(4575957461383582011L);
private static final double c3 = Double.longBitsToDouble(-4671919876300759001L);
private static final double c4 = Double.longBitsToDouble(4523617214285661942L);
private static final double c5 = Double.longBitsToDouble(-4730215272828025532L);
private static final double c6 = Double.longBitsToDouble(4460272573143870633L);
private static final double c7 = Double.longBitsToDouble(-4797767418267846529L);
/**
* @author theagentd
*/
static double sin_theagentd_arith(double x){
double xi = floor((x + PI_4) * PI_INV);
double x_ = x - xi * PI;
double sign = ((int)xi & 1) * -2 + 1;
double x2 = x_ * x_;
double sin = x_;
double tx = x_ * x2;
sin += tx * c1; tx *= x2;
sin += tx * c2; tx *= x2;
sin += tx * c3; tx *= x2;
sin += tx * c4; tx *= x2;
sin += tx * c5; tx *= x2;
sin += tx * c6; tx *= x2;
sin += tx * c7;
return sign * sin;
}
/**
* Reference: <a href="http://www.java-gaming.org/topics/joml-1-8-0-release/37491/msg/361718/view.html#msg361718">http://www.java-gaming.org/</a>
*/
static double sin_roquen_arith(double x) {
double xi = Math.floor((x + PI_4) * PI_INV);
double x_ = x - xi * PI;
double sign = ((int)xi & 1) * -2 + 1;
double x2 = x_ * x_;
// code from sin_theagentd_arith:
// double sin = x_;
// double tx = x_ * x2;
// sin += tx * c1; tx *= x2;
// sin += tx * c2; tx *= x2;
// sin += tx * c3; tx *= x2;
// sin += tx * c4; tx *= x2;
// sin += tx * c5; tx *= x2;
// sin += tx * c6; tx *= x2;
// sin += tx * c7;
// return sign * sin;
double sin;
x_ = sign*x_;
sin = c7;
sin = sin*x2 + c6;
sin = sin*x2 + c5;
sin = sin*x2 + c4;
sin = sin*x2 + c3;
sin = sin*x2 + c2;
sin = sin*x2 + c1;
return x_ + x_*x2*sin;
}
private static final double s5 = Double.longBitsToDouble(4523227044276562163L);
private static final double s4 = Double.longBitsToDouble(-4671934770969572232L);
private static final double s3 = Double.longBitsToDouble(4575957211482072852L);
private static final double s2 = Double.longBitsToDouble(-4628199223918090387L);
private static final double s1 = Double.longBitsToDouble(4607182418589157889L);
/**
* Reference: <a href="http://www.java-gaming.org/topics/joml-1-8-0-release/37491/msg/361815/view.html#msg361815">http://www.java-gaming.org/</a>
*/
static double sin_roquen_9(double v) {
double i = java.lang.Math.rint(v*PI_INV);
double x = v - i * Math.PI;
double qs = 1-2*((int)i & 1);
double x2 = x*x;
double r;
x = qs*x;
r = s5;
r = r*x2 + s4;
r = r*x2 + s3;
r = r*x2 + s2;
r = r*x2 + s1;
return x*r;
}
private static final double k1 = Double.longBitsToDouble(-4628199217061079959L);
private static final double k2 = Double.longBitsToDouble(4575957461383549981L);
private static final double k3 = Double.longBitsToDouble(-4671919876307284301L);
private static final double k4 = Double.longBitsToDouble(4523617213632129738L);
private static final double k5 = Double.longBitsToDouble(-4730215344060517252L);
private static final double k6 = Double.longBitsToDouble(4460268259291226124L);
private static final double k7 = Double.longBitsToDouble(-4798040743777455072L);
/**
* Reference: <a href="http://www.java-gaming.org/topics/joml-1-8-0-release/37491/msg/361815/view.html#msg361815">http://www.java-gaming.org/</a>
*/
static double sin_roquen_newk(double v) {
double i = java.lang.Math.rint(v*PI_INV);
double x = v - i * Math.PI;
double qs = 1-2*((int)i & 1);
double x2 = x*x;
double r;
x = qs*x;
r = k7;
r = r*x2 + k6;
r = r*x2 + k5;
r = r*x2 + k4;
r = r*x2 + k3;
r = r*x2 + k2;
r = r*x2 + k1;
return x + x*x2*r;
}
/**
* Reference: <a href="http://www.java-gaming.org/topics/extremely-fast-sine-cosine/36469/msg/349515/view.html#msg349515">http://www.java-gaming.org/</a>
*/
static float sin_theagentd_lookup(float rad) {
float index = rad * lookupSizeOverPi2;
int ii = (int)java.lang.Math.floor(index);
float alpha = index - ii;
int i = ii & lookupTableSizeMinus1;
float sin1 = sinTable[i];
float sin2 = sinTable[i + 1];
return sin1 + (sin2 - sin1) * alpha;
}
public static float sin(float rad) {
return (float) java.lang.Math.sin(rad);
}
public static double sin(double rad) {
if (Options.FASTMATH) {
if (Options.SIN_LOOKUP)
return sin_theagentd_lookup((float) rad);
return sin_roquen_newk(rad);
}
return java.lang.Math.sin(rad);
}
public static float cos(float rad) {
if (Options.FASTMATH)
return sin(rad + PIHalf_f);
return (float) java.lang.Math.cos(rad);
}
public static double cos(double rad) {
if (Options.FASTMATH)
return sin(rad + PIHalf);
return java.lang.Math.cos(rad);
}
public static float cosFromSin(float sin, float angle) {
if (Options.FASTMATH)
return sin(angle + PIHalf_f);
return cosFromSinInternal(sin, angle);
}
private static float cosFromSinInternal(float sin, float angle) {
// sin(x)^2 + cos(x)^2 = 1
float cos = sqrt(1.0f - sin * sin);
float a = angle + PIHalf_f;
float b = a - (int)(a / PI2_f) * PI2_f;
if (b < 0.0)
b = PI2_f + b;
if (b >= PI_f)
return -cos;
return cos;
}
public static double cosFromSin(double sin, double angle) {
if (Options.FASTMATH)
return sin(angle + PIHalf);
// sin(x)^2 + cos(x)^2 = 1
double cos = sqrt(1.0 - sin * sin);
double a = angle + PIHalf;
double b = a - (int)(a / PI2) * PI2;
if (b < 0.0)
b = PI2 + b;
if (b >= PI)
return -cos;
return cos;
}
/* Other math functions not yet approximated */
public static float sqrt(float r) {
return (float) java.lang.Math.sqrt(r);
}
public static double sqrt(double r) {
return java.lang.Math.sqrt(r);
}
public static float invsqrt(float r) {
return 1.0f / (float) java.lang.Math.sqrt(r);
}
public static double invsqrt(double r) {
return 1.0 / java.lang.Math.sqrt(r);
}
public static float tan(float r) {
return (float) java.lang.Math.tan(r);
}
public static double tan(double r) {
return java.lang.Math.tan(r);
}
public static float acos(float r) {
return (float) java.lang.Math.acos(r);
}
public static double acos(double r) {
return java.lang.Math.acos(r);
}
public static float safeAcos(float v) {
if (v < -1.0f)
return Math.PI_f;
else if (v > +1.0f)
return 0.0f;
else
return acos(v);
}
public static double safeAcos(double v) {
if (v < -1.0)
return Math.PI;
else if (v > +1.0)
return 0.0;
else
return acos(v);
}
/**
* https://math.stackexchange.com/questions/1098487/atan2-faster-approximation/1105038#answer-1105038
*/
private static double fastAtan2(double y, double x) {
double ax = x >= 0.0 ? x : -x, ay = y >= 0.0 ? y : -y;
double a = min(ax, ay) / max(ax, ay);
double s = a * a;
double r = ((-0.0464964749 * s + 0.15931422) * s - 0.327622764) * s * a + a;
if (ay > ax)
r = 1.57079637 - r;
if (x < 0.0)
r = 3.14159274 - r;
return y >= 0 ? r : -r;
}
public static float atan2(float y, float x) {
return (float) java.lang.Math.atan2(y, x);
}
public static double atan2(double y, double x) {
if (Options.FASTMATH)
return fastAtan2(y, x);
return java.lang.Math.atan2(y, x);
}
public static float asin(float r) {
return (float) java.lang.Math.asin(r);
}
public static double asin(double r) {
return java.lang.Math.asin(r);
}
public static float safeAsin(float r) {
return r <= -1.0f ? -PIHalf_f : r >= 1.0f ? PIHalf_f : asin(r);
}
public static double safeAsin(double r) {
return r <= -1.0 ? -PIHalf : r >= 1.0 ? PIHalf : asin(r);
}
public static float abs(float r) {
return java.lang.Math.abs(r);
}
public static double abs(double r) {
return java.lang.Math.abs(r);
}
static boolean absEqualsOne(float r) {
return (Float.floatToRawIntBits(r) & 0x7FFFFFFF) == 0x3F800000;
}
static boolean absEqualsOne(double r) {
return (Double.doubleToRawLongBits(r) & 0x7FFFFFFFFFFFFFFFL) == 0x3FF0000000000000L;
}
public static int abs(int r) {
return java.lang.Math.abs(r);
}
public static int max(int x, int y) {
return java.lang.Math.max(x, y);
}
public static int min(int x, int y) {
return java.lang.Math.min(x, y);
}
public static double min(double a, double b) {
return a < b ? a : b;
}
public static float min(float a, float b) {
return a < b ? a : b;
}
public static float max(float a, float b) {
return a > b ? a : b;
}
public static double max(double a, double b) {
return a > b ? a : b;
}
public static float clamp(float a, float b, float val){
return max(a,min(b,val));
}
public static double clamp(double a, double b, double val) {
return max(a,min(b,val));
}
public static int clamp(int a, int b, int val) {
return max(a, min(b, val));
}
public static float toRadians(float angles) {
return (float) java.lang.Math.toRadians(angles);
}
public static double toRadians(double angles) {
return java.lang.Math.toRadians(angles);
}
public static double toDegrees(double angles) {
return java.lang.Math.toDegrees(angles);
}
public static double floor(double v) {
return java.lang.Math.floor(v);
}
public static float floor(float v) {
return (float) java.lang.Math.floor(v);
}
public static double ceil(double v) {
return java.lang.Math.ceil(v);
}
public static float ceil(float v) {
return (float) java.lang.Math.ceil(v);
}
public static long round(double v) {
return java.lang.Math.round(v);
}
public static int round(float v) {
return java.lang.Math.round(v);
}
public static double exp(double a) {
return java.lang.Math.exp(a);
}
public static boolean isFinite(double d) {
return abs(d) <= Double.MAX_VALUE;
}
public static boolean isFinite(float f) {
return abs(f) <= Float.MAX_VALUE;
}
public static float fma(float a, float b, float c) {
if (Runtime.HAS_Math_fma)
return java.lang.Math.fma(a, b, c);
return a * b + c;
}
public static double fma(double a, double b, double c) {
if (Runtime.HAS_Math_fma)
return java.lang.Math.fma(a, b, c);
return a * b + c;
}
public static int roundUsing(float v, int mode) {
switch (mode) {
case RoundingMode.TRUNCATE:
return (int) v;
case RoundingMode.CEILING:
return (int) java.lang.Math.ceil(v);
case RoundingMode.FLOOR:
return (int) java.lang.Math.floor(v);
case RoundingMode.HALF_DOWN:
return roundHalfDown(v);
case RoundingMode.HALF_UP:
return roundHalfUp(v);
case RoundingMode.HALF_EVEN:
return roundHalfEven(v);
default:
throw new UnsupportedOperationException();
}
}
public static int roundUsing(double v, int mode) {
switch (mode) {
case RoundingMode.TRUNCATE:
return (int) v;
case RoundingMode.CEILING:
return (int) java.lang.Math.ceil(v);
case RoundingMode.FLOOR:
return (int) java.lang.Math.floor(v);
case RoundingMode.HALF_DOWN:
return roundHalfDown(v);
case RoundingMode.HALF_UP:
return roundHalfUp(v);
case RoundingMode.HALF_EVEN:
return roundHalfEven(v);
default:
throw new UnsupportedOperationException();
}
}
public static float lerp(float a, float b, float t){
return Math.fma(b - a, t, a);
}
public static double lerp(double a, double b, double t) {
return Math.fma(b - a, t, a);
}
public static float biLerp(float q00, float q10, float q01, float q11, float tx, float ty) {
float lerpX1 = lerp(q00, q10, tx);
float lerpX2 = lerp(q01, q11, tx);
return lerp(lerpX1, lerpX2, ty);
}
public static double biLerp(double q00, double q10, double q01, double q11, double tx, double ty) {
double lerpX1 = lerp(q00, q10, tx);
double lerpX2 = lerp(q01, q11, tx);
return lerp(lerpX1, lerpX2, ty);
}
public static float triLerp(float q000, float q100, float q010, float q110, float q001, float q101, float q011, float q111, float tx, float ty, float tz) {
float x00 = lerp(q000, q100, tx);
float x10 = lerp(q010, q110, tx);
float x01 = lerp(q001, q101, tx);
float x11 = lerp(q011, q111, tx);
float y0 = lerp(x00, x10, ty);
float y1 = lerp(x01, x11, ty);
return lerp(y0, y1, tz);
}
public static double triLerp(double q000, double q100, double q010, double q110, double q001, double q101, double q011, double q111, double tx, double ty, double tz) {
double x00 = lerp(q000, q100, tx);
double x10 = lerp(q010, q110, tx);
double x01 = lerp(q001, q101, tx);
double x11 = lerp(q011, q111, tx);
double y0 = lerp(x00, x10, ty);
double y1 = lerp(x01, x11, ty);
return lerp(y0, y1, tz);
}
public static int roundHalfEven(float v) {
return (int) java.lang.Math.rint(v);
}
public static int roundHalfDown(float v) {
return (v > 0) ? (int) java.lang.Math.ceil(v - 0.5d) : (int) java.lang.Math.floor(v + 0.5d);
}
public static int roundHalfUp(float v) {
return (v > 0) ? (int) java.lang.Math.floor(v + 0.5d) : (int) java.lang.Math.ceil(v - 0.5d);
}
public static int roundHalfEven(double v) {
return (int) java.lang.Math.rint(v);
}
public static int roundHalfDown(double v) {
return (v > 0) ? (int) java.lang.Math.ceil(v - 0.5d) : (int) java.lang.Math.floor(v + 0.5d);
}
public static int roundHalfUp(double v) {
return (v > 0) ? (int) java.lang.Math.floor(v + 0.5d) : (int) java.lang.Math.ceil(v - 0.5d);
}
public static double random() {
return java.lang.Math.random();
}
public static double signum(double v) {
return java.lang.Math.signum(v);
}
public static float signum(float v) {
return java.lang.Math.signum(v);
}
public static int signum(int v) {
int r;
r = Integer.signum(v);
return r;
}
public static int signum(long v) {
int r;
r = Long.signum(v);
return r;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,725 @@
/*
* The MIT License
*
* Copyright (c) 2020-2021 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 com.jozufozu.flywheel.repack.joml;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.util.*;
/**
* Interface to a read-only view of a 2x2 matrix of double-precision floats.
*
* @author Joseph Burton
*/
public interface Matrix2dc {
/**
* Return the value of the matrix element at column 0 and row 0.
*
* @return the value of the matrix element
*/
double m00();
/**
* Return the value of the matrix element at column 0 and row 1.
*
* @return the value of the matrix element
*/
double m01();
/**
* Return the value of the matrix element at column 1 and row 0.
*
* @return the value of the matrix element
*/
double m10();
/**
* Return the value of the matrix element at column 1 and row 1.
*
* @return the value of the matrix element
*/
double m11();
/**
* Multiply this matrix by the supplied <code>right</code> matrix and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
* transformation of the right matrix will be applied first!
*
* @param right
* the right operand of the matrix multiplication
* @param dest
* will hold the result
* @return dest
*/
Matrix2d mul(Matrix2dc right, Matrix2d dest);
/**
* Multiply this matrix by the supplied <code>right</code> matrix and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
* transformation of the right matrix will be applied first!
*
* @param right
* the right operand of the matrix multiplication
* @param dest
* will hold the result
* @return dest
*/
Matrix2d mul(Matrix2fc right, Matrix2d dest);
/**
* Pre-multiply this matrix by the supplied <code>left</code> matrix and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the <code>left</code> matrix,
* then the new matrix will be <code>L * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>L * M * v</code>, the
* transformation of <code>this</code> matrix will be applied first!
*
* @param left
* the left operand of the matrix multiplication
* @param dest
* the destination matrix, which will hold the result
* @return dest
*/
Matrix2d mulLocal(Matrix2dc left, Matrix2d dest);
/**
* Return the determinant of this matrix.
*
* @return the determinant
*/
double determinant();
/**
* Invert the <code>this</code> matrix and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Matrix2d invert(Matrix2d dest);
/**
* Transpose <code>this</code> matrix and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Matrix2d transpose(Matrix2d dest);
/**
* Get the current values of <code>this</code> matrix and store them into
* <code>dest</code>.
*
* @param dest
* the destination matrix
* @return the passed in destination
*/
Matrix2d get(Matrix2d dest);
/**
* Get the current values of <code>this</code> matrix and store them as
* the rotational component of <code>dest</code>. All other values of <code>dest</code> will
* be set to 0.
*
* @see Matrix3x2d#set(Matrix2dc)
*
* @param dest
* the destination matrix
* @return the passed in destination
*/
Matrix3x2d get(Matrix3x2d dest);
/**
* Get the current values of <code>this</code> matrix and store them as
* the rotational component of <code>dest</code>. All other values of <code>dest</code> will
* be set to identity.
*
* @see Matrix3d#set(Matrix2dc)
*
* @param dest
* the destination matrix
* @return the passed in destination
*/
Matrix3d get(Matrix3d dest);
/**
* Get the angle of the rotation component of <code>this</code> matrix.
* <p>
* This method assumes that there is a valid rotation to be returned, i.e. that
* <code>atan2(-m10, m00) == atan2(m01, m11)</code>.
*
* @return the angle
*/
double getRotation();
/**
* Store this matrix in column-major order into the supplied {@link DoubleBuffer} at the current
* buffer {@link DoubleBuffer#position() position}.
* <p>
* This method will not increment the position of the given DoubleBuffer.
* <p>
* In order to specify the offset into the DoubleBuffer at which
* the matrix is stored, use {@link #get(int, DoubleBuffer)}, taking
* the absolute position as parameter.
*
* @see #get(int, DoubleBuffer)
*
* @param buffer
* will receive the values of this matrix in column-major order at its current position
* @return the passed in buffer
*/
DoubleBuffer get(DoubleBuffer buffer);
/**
* Store this matrix in column-major order into the supplied {@link DoubleBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given DoubleBuffer.
*
* @param index
* the absolute position into the DoubleBuffer
* @param buffer
* will receive the values of this matrix in column-major order
* @return the passed in buffer
*/
DoubleBuffer get(int index, DoubleBuffer buffer);
/**
* Store this matrix in column-major order into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which
* the matrix is stored, use {@link #get(int, ByteBuffer)}, taking
* the absolute position as parameter.
*
* @see #get(int, ByteBuffer)
*
* @param buffer
* will receive the values of this matrix in column-major order at its current position
* @return the passed in buffer
*/
ByteBuffer get(ByteBuffer buffer);
/**
* Store this matrix in column-major order into the supplied {@link ByteBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this matrix in column-major order
* @return the passed in buffer
*/
ByteBuffer get(int index, ByteBuffer buffer);
/**
* Store the transpose of this matrix in column-major order into the supplied {@link DoubleBuffer} at the current
* buffer {@link DoubleBuffer#position() position}.
* <p>
* This method will not increment the position of the given DoubleBuffer.
* <p>
* In order to specify the offset into the DoubleBuffer at which
* the matrix is stored, use {@link #getTransposed(int, DoubleBuffer)}, taking
* the absolute position as parameter.
*
* @see #getTransposed(int, DoubleBuffer)
*
* @param buffer
* will receive the values of this matrix in column-major order at its current position
* @return the passed in buffer
*/
DoubleBuffer getTransposed(DoubleBuffer buffer);
/**
* Store the transpose of this matrix in column-major order into the supplied {@link DoubleBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given DoubleBuffer.
*
* @param index
* the absolute position into the DoubleBuffer
* @param buffer
* will receive the values of this matrix in column-major order
* @return the passed in buffer
*/
DoubleBuffer getTransposed(int index, DoubleBuffer buffer);
/**
* Store the transpose of this matrix in column-major order into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which
* the matrix is stored, use {@link #getTransposed(int, ByteBuffer)}, taking
* the absolute position as parameter.
*
* @see #getTransposed(int, ByteBuffer)
*
* @param buffer
* will receive the values of this matrix in column-major order at its current position
* @return the passed in buffer
*/
ByteBuffer getTransposed(ByteBuffer buffer);
/**
* Store the transpose of this matrix in column-major order into the supplied {@link ByteBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this matrix in column-major order
* @return the passed in buffer
*/
ByteBuffer getTransposed(int index, ByteBuffer buffer);
/**
* Store this matrix in column-major order at the given off-heap address.
* <p>
* This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`.
* <p>
* <em>This method is unsafe as it can result in a crash of the JVM process when the specified address range does not belong to this process.</em>
*
* @param address
* the off-heap address where to store this matrix
* @return this
*/
Matrix2dc getToAddress(long address);
/**
* Store this matrix into the supplied double array in column-major order at the given offset.
*
* @param arr
* the array to write the matrix values into
* @param offset
* the offset into the array
* @return the passed in array
*/
double[] get(double[] arr, int offset);
/**
* Store this matrix into the supplied double array in column-major order.
* <p>
* In order to specify an explicit offset into the array, use the method {@link #get(double[], int)}.
*
* @see #get(double[], int)
*
* @param arr
* the array to write the matrix values into
* @return the passed in array
*/
double[] get(double[] arr);
/**
* Apply scaling to <code>this</code> matrix by scaling the base axes by the given <code>xy.x</code> and
* <code>xy.y</code> factors, respectively and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>M * S</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * S * v</code>
* , the scaling will be applied first!
*
* @param xy
* the factors of the x and y component, respectively
* @param dest
* will hold the result
* @return dest
*/
Matrix2d scale(Vector2dc xy, Matrix2d dest);
/**
* Apply scaling to this matrix by scaling the base axes by the given x and
* y factors and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>M * S</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * S * v</code>
* , the scaling will be applied first!
*
* @param x
* the factor of the x component
* @param y
* the factor of the y component
* @param dest
* will hold the result
* @return dest
*/
Matrix2d scale(double x, double y, Matrix2d dest);
/**
* Apply scaling to this matrix by uniformly scaling all base axes by the given <code>xy</code> factor
* and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>M * S</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * S * v</code>
* , the scaling will be applied first!
*
* @see #scale(double, double, Matrix2d)
*
* @param xy
* the factor for all components
* @param dest
* will hold the result
* @return dest
*/
Matrix2d scale(double xy, Matrix2d dest);
/**
* Pre-multiply scaling to <code>this</code> matrix by scaling the base axes by the given x and
* y factors and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>S * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>S * M * v</code>
* , the scaling will be applied last!
*
* @param x
* the factor of the x component
* @param y
* the factor of the y component
* @param dest
* will hold the result
* @return dest
*/
Matrix2d scaleLocal(double x, double y, Matrix2d dest);
/**
* Transform the given vector by this matrix.
*
* @param v
* the vector to transform
* @return v
*/
Vector2d transform(Vector2d v);
/**
* Transform the given vector by this matrix and store the result in <code>dest</code>.
*
* @param v
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector2d transform(Vector2dc v, Vector2d dest);
/**
* Transform the vector <code>(x, y)</code> by this matrix and store the result in <code>dest</code>.
*
* @param x
* the x coordinate of the vector to transform
* @param y
* the y coordinate of the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector2d transform(double x, double y, Vector2d dest);
/**
* Transform the given vector by the transpose of this matrix.
*
* @param v
* the vector to transform
* @return v
*/
Vector2d transformTranspose(Vector2d v);
/**
* Transform the given vector by the transpose of this matrix and store the result in <code>dest</code>.
*
* @param v
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector2d transformTranspose(Vector2dc v, Vector2d dest);
/**
* Transform the vector <code>(x, y)</code> by the transpose of this matrix and store the result in <code>dest</code>.
*
* @param x
* the x coordinate of the vector to transform
* @param y
* the y coordinate of the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector2d transformTranspose(double x, double y, Vector2d dest);
/**
* Apply rotation to this matrix by rotating the given amount of radians
* and store the result in <code>dest</code>.
* <p>
* The produced rotation will rotate a vector counter-clockwise around the origin.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>
* , the rotation will be applied first!
* <p>
* Reference: <a href="https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @param dest
* will hold the result
* @return dest
*/
Matrix2d rotate(double ang, Matrix2d dest);
/**
* Pre-multiply a rotation to this matrix by rotating the given amount of radians
* and store the result in <code>dest</code>.
* <p>
* The produced rotation will rotate a vector counter-clockwise around the origin.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>R * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
* rotation will be applied last!
* <p>
* Reference: <a href="https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @param dest
* will hold the result
* @return dest
*/
Matrix2d rotateLocal(double ang, Matrix2d dest);
/**
* Get the row at the given <code>row</code> index, starting with <code>0</code>.
*
* @param row
* the row index in <code>[0..1]</code>
* @param dest
* will hold the row components
* @return the passed in destination
* @throws IndexOutOfBoundsException if <code>row</code> is not in <code>[0..1]</code>
*/
Vector2d getRow(int row, Vector2d dest) throws IndexOutOfBoundsException;
/**
* Get the column at the given <code>column</code> index, starting with <code>0</code>.
*
* @param column
* the column index in <code>[0..1]</code>
* @param dest
* will hold the column components
* @return the passed in destination
* @throws IndexOutOfBoundsException if <code>column</code> is not in <code>[0..1]</code>
*/
Vector2d getColumn(int column, Vector2d dest) throws IndexOutOfBoundsException;
/**
* Get the matrix element value at the given column and row.
*
* @param column
* the colum index in <code>[0..1]</code>
* @param row
* the row index in <code>[0..1]</code>
* @return the element value
*/
double get(int column, int row);
/**
* Compute a normal matrix from <code>this</code> matrix and store it into <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Matrix2d normal(Matrix2d dest);
/**
* Get the scaling factors of <code>this</code> matrix for the three base axes.
*
* @param dest
* will hold the scaling factors for <code>x</code> and <code>y</code>
* @return dest
*/
Vector2d getScale(Vector2d dest);
/**
* Obtain the direction of <code>+X</code> before the transformation represented by <code>this</code> matrix is applied.
* <p>
* This method is equivalent to the following code:
* <pre>
* Matrix2d inv = new Matrix2d(this).invert();
* inv.transform(dir.set(1, 0)).normalize();
* </pre>
* If <code>this</code> is already an orthogonal matrix, then consider using {@link #normalizedPositiveX(Vector2d)} instead.
*
* @param dest
* will hold the direction of <code>+X</code>
* @return dest
*/
Vector2d positiveX(Vector2d dest);
/**
* Obtain the direction of <code>+X</code> before the transformation represented by <code>this</code> <i>orthogonal</i> matrix is applied.
* This method only produces correct results if <code>this</code> is an <i>orthogonal</i> matrix.
* <p>
* This method is equivalent to the following code:
* <pre>
* Matrix2d inv = new Matrix2d(this).transpose();
* inv.transform(dir.set(1, 0));
* </pre>
*
* @param dest
* will hold the direction of <code>+X</code>
* @return dest
*/
Vector2d normalizedPositiveX(Vector2d dest);
/**
* Obtain the direction of <code>+Y</code> before the transformation represented by <code>this</code> matrix is applied.
* <p>
* This method is equivalent to the following code:
* <pre>
* Matrix2d inv = new Matrix2d(this).invert();
* inv.transform(dir.set(0, 1)).normalize();
* </pre>
* If <code>this</code> is already an orthogonal matrix, then consider using {@link #normalizedPositiveY(Vector2d)} instead.
*
* @param dest
* will hold the direction of <code>+Y</code>
* @return dest
*/
Vector2d positiveY(Vector2d dest);
/**
* Obtain the direction of <code>+Y</code> before the transformation represented by <code>this</code> <i>orthogonal</i> matrix is applied.
* This method only produces correct results if <code>this</code> is an <i>orthogonal</i> matrix.
* <p>
* This method is equivalent to the following code:
* <pre>
* Matrix2d inv = new Matrix2d(this).transpose();
* inv.transform(dir.set(0, 1));
* </pre>
*
* @param dest
* will hold the direction of <code>+Y</code>
* @return dest
*/
Vector2d normalizedPositiveY(Vector2d dest);
/**
* Component-wise add <code>this</code> and <code>other</code> and store the result in <code>dest</code>.
*
* @param other
* the other addend
* @param dest
* will hold the result
* @return dest
*/
Matrix2d add(Matrix2dc other, Matrix2d dest);
/**
* Component-wise subtract <code>subtrahend</code> from <code>this</code> and store the result in <code>dest</code>.
*
* @param subtrahend
* the subtrahend
* @param dest
* will hold the result
* @return dest
*/
Matrix2d sub(Matrix2dc subtrahend, Matrix2d dest);
/**
* Component-wise multiply <code>this</code> by <code>other</code> and store the result in <code>dest</code>.
*
* @param other
* the other matrix
* @param dest
* will hold the result
* @return dest
*/
Matrix2d mulComponentWise(Matrix2dc other, Matrix2d dest);
/**
* Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code>
* and store the result in <code>dest</code>.
* <p>
* If <code>t</code> is <code>0.0</code> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code>
* then the result is <code>other</code>.
*
* @param other
* the other matrix
* @param t
* the interpolation factor between 0.0 and 1.0
* @param dest
* will hold the result
* @return dest
*/
Matrix2d lerp(Matrix2dc other, double t, Matrix2d dest);
/**
* Compare the matrix elements of <code>this</code> matrix with the given matrix using the given <code>delta</code>
* and return whether all of them are equal within a maximum difference of <code>delta</code>.
* <p>
* Please note that this method is not used by any data structure such as {@link ArrayList} {@link HashSet} or {@link HashMap}
* and their operations, such as {@link ArrayList#contains(Object)} or {@link HashSet#remove(Object)}, since those
* data structures only use the {@link Object#equals(Object)} and {@link Object#hashCode()} methods.
*
* @param m
* the other matrix
* @param delta
* the allowed maximum difference
* @return <code>true</code> whether all of the matrix elements are equal; <code>false</code> otherwise
*/
boolean equals(Matrix2dc m, double delta);
/**
* Determine whether all matrix elements are finite floating-point values, that
* is, they are not {@link Double#isNaN() NaN} and not
* {@link Double#isInfinite() infinity}.
*
* @return {@code true} if all components are finite floating-point values;
* {@code false} otherwise
*/
boolean isFinite();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,709 @@
/*
* The MIT License
*
* Copyright (c) 2020-2021 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 com.jozufozu.flywheel.repack.joml;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.*;
/**
* Interface to a read-only view of a 2x2 matrix of single-precision floats.
*
* @author Joseph Burton
*/
public interface Matrix2fc {
/**
* Return the value of the matrix element at column 0 and row 0.
*
* @return the value of the matrix element
*/
float m00();
/**
* Return the value of the matrix element at column 0 and row 1.
*
* @return the value of the matrix element
*/
float m01();
/**
* Return the value of the matrix element at column 1 and row 0.
*
* @return the value of the matrix element
*/
float m10();
/**
* Return the value of the matrix element at column 1 and row 1.
*
* @return the value of the matrix element
*/
float m11();
/**
* Multiply this matrix by the supplied <code>right</code> matrix and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
* transformation of the right matrix will be applied first!
*
* @param right
* the right operand of the matrix multiplication
* @param dest
* will hold the result
* @return dest
*/
Matrix2f mul(Matrix2fc right, Matrix2f dest);
/**
* Pre-multiply this matrix by the supplied <code>left</code> matrix and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>L</code> the <code>left</code> matrix,
* then the new matrix will be <code>L * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>L * M * v</code>, the
* transformation of <code>this</code> matrix will be applied first!
*
* @param left
* the left operand of the matrix multiplication
* @param dest
* the destination matrix, which will hold the result
* @return dest
*/
Matrix2f mulLocal(Matrix2fc left, Matrix2f dest);
/**
* Return the determinant of this matrix.
*
* @return the determinant
*/
float determinant();
/**
* Invert the <code>this</code> matrix and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Matrix2f invert(Matrix2f dest);
/**
* Transpose <code>this</code> matrix and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Matrix2f transpose(Matrix2f dest);
/**
* Get the current values of <code>this</code> matrix and store them into
* <code>dest</code>.
*
* @param dest
* the destination matrix
* @return the passed in destination
*/
Matrix2f get(Matrix2f dest);
/**
* Get the current values of <code>this</code> matrix and store them as
* the rotational component of <code>dest</code>. All other values of <code>dest</code> will
* be set to 0.
*
* @see Matrix3x2f#set(Matrix2fc)
*
* @param dest
* the destination matrix
* @return the passed in destination
*/
Matrix3x2f get(Matrix3x2f dest);
/**
* Get the current values of <code>this</code> matrix and store them as
* the rotational component of <code>dest</code>. All other values of <code>dest</code> will
* be set to identity.
*
* @see Matrix3f#set(Matrix2fc)
*
* @param dest
* the destination matrix
* @return the passed in destination
*/
Matrix3f get(Matrix3f dest);
/**
* Get the angle of the rotation component of <code>this</code> matrix.
* <p>
* This method assumes that there is a valid rotation to be returned, i.e. that
* <code>atan2(-m10, m00) == atan2(m01, m11)</code>.
*
* @return the angle
*/
float getRotation();
/**
* Store this matrix in column-major order into the supplied {@link FloatBuffer} at the current
* buffer {@link FloatBuffer#position() position}.
* <p>
* This method will not increment the position of the given FloatBuffer.
* <p>
* In order to specify the offset into the FloatBuffer at which
* the matrix is stored, use {@link #get(int, FloatBuffer)}, taking
* the absolute position as parameter.
*
* @see #get(int, FloatBuffer)
*
* @param buffer
* will receive the values of this matrix in column-major order at its current position
* @return the passed in buffer
*/
FloatBuffer get(FloatBuffer buffer);
/**
* Store this matrix in column-major order into the supplied {@link FloatBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given FloatBuffer.
*
* @param index
* the absolute position into the FloatBuffer
* @param buffer
* will receive the values of this matrix in column-major order
* @return the passed in buffer
*/
FloatBuffer get(int index, FloatBuffer buffer);
/**
* Store this matrix in column-major order into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which
* the matrix is stored, use {@link #get(int, ByteBuffer)}, taking
* the absolute position as parameter.
*
* @see #get(int, ByteBuffer)
*
* @param buffer
* will receive the values of this matrix in column-major order at its current position
* @return the passed in buffer
*/
ByteBuffer get(ByteBuffer buffer);
/**
* Store this matrix in column-major order into the supplied {@link ByteBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this matrix in column-major order
* @return the passed in buffer
*/
ByteBuffer get(int index, ByteBuffer buffer);
/**
* Store the transpose of this matrix in column-major order into the supplied {@link FloatBuffer} at the current
* buffer {@link FloatBuffer#position() position}.
* <p>
* This method will not increment the position of the given FloatBuffer.
* <p>
* In order to specify the offset into the FloatBuffer at which
* the matrix is stored, use {@link #getTransposed(int, FloatBuffer)}, taking
* the absolute position as parameter.
*
* @see #getTransposed(int, FloatBuffer)
*
* @param buffer
* will receive the values of this matrix in column-major order at its current position
* @return the passed in buffer
*/
FloatBuffer getTransposed(FloatBuffer buffer);
/**
* Store the transpose of this matrix in column-major order into the supplied {@link FloatBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given FloatBuffer.
*
* @param index
* the absolute position into the FloatBuffer
* @param buffer
* will receive the values of this matrix in column-major order
* @return the passed in buffer
*/
FloatBuffer getTransposed(int index, FloatBuffer buffer);
/**
* Store the transpose of this matrix in column-major order into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which
* the matrix is stored, use {@link #getTransposed(int, ByteBuffer)}, taking
* the absolute position as parameter.
*
* @see #getTransposed(int, ByteBuffer)
*
* @param buffer
* will receive the values of this matrix in column-major order at its current position
* @return the passed in buffer
*/
ByteBuffer getTransposed(ByteBuffer buffer);
/**
* Store the transpose of this matrix in column-major order into the supplied {@link ByteBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this matrix in column-major order
* @return the passed in buffer
*/
ByteBuffer getTransposed(int index, ByteBuffer buffer);
/**
* Store this matrix in column-major order at the given off-heap address.
* <p>
* This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`.
* <p>
* <em>This method is unsafe as it can result in a crash of the JVM process when the specified address range does not belong to this process.</em>
*
* @param address
* the off-heap address where to store this matrix
* @return this
*/
Matrix2fc getToAddress(long address);
/**
* Store this matrix into the supplied float array in column-major order at the given offset.
*
* @param arr
* the array to write the matrix values into
* @param offset
* the offset into the array
* @return the passed in array
*/
float[] get(float[] arr, int offset);
/**
* Store this matrix into the supplied float array in column-major order.
* <p>
* In order to specify an explicit offset into the array, use the method {@link #get(float[], int)}.
*
* @see #get(float[], int)
*
* @param arr
* the array to write the matrix values into
* @return the passed in array
*/
float[] get(float[] arr);
/**
* Apply scaling to <code>this</code> matrix by scaling the base axes by the given <code>xy.x</code> and
* <code>xy.y</code> factors, respectively and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>M * S</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * S * v</code>
* , the scaling will be applied first!
*
* @param xy
* the factors of the x and y component, respectively
* @param dest
* will hold the result
* @return dest
*/
Matrix2f scale(Vector2fc xy, Matrix2f dest);
/**
* Apply scaling to this matrix by scaling the base axes by the given x and
* y factors and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>M * S</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * S * v</code>
* , the scaling will be applied first!
*
* @param x
* the factor of the x component
* @param y
* the factor of the y component
* @param dest
* will hold the result
* @return dest
*/
Matrix2f scale(float x, float y, Matrix2f dest);
/**
* Apply scaling to this matrix by uniformly scaling all base axes by the given <code>xy</code> factor
* and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>M * S</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * S * v</code>
* , the scaling will be applied first!
*
* @see #scale(float, float, Matrix2f)
*
* @param xy
* the factor for all components
* @param dest
* will hold the result
* @return dest
*/
Matrix2f scale(float xy, Matrix2f dest);
/**
* Pre-multiply scaling to <code>this</code> matrix by scaling the base axes by the given x and
* y factors and store the result in <code>dest</code>.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
* then the new matrix will be <code>S * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>S * M * v</code>
* , the scaling will be applied last!
*
* @param x
* the factor of the x component
* @param y
* the factor of the y component
* @param dest
* will hold the result
* @return dest
*/
Matrix2f scaleLocal(float x, float y, Matrix2f dest);
/**
* Transform the given vector by this matrix.
*
* @param v
* the vector to transform
* @return v
*/
Vector2f transform(Vector2f v);
/**
* Transform the given vector by this matrix and store the result in <code>dest</code>.
*
* @param v
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector2f transform(Vector2fc v, Vector2f dest);
/**
* Transform the vector <code>(x, y)</code> by this matrix and store the result in <code>dest</code>.
*
* @param x
* the x coordinate of the vector to transform
* @param y
* the y coordinate of the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector2f transform(float x, float y, Vector2f dest);
/**
* Transform the given vector by the transpose of this matrix.
*
* @param v
* the vector to transform
* @return v
*/
Vector2f transformTranspose(Vector2f v);
/**
* Transform the given vector by the transpose of this matrix and store the result in <code>dest</code>.
*
* @param v
* the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector2f transformTranspose(Vector2fc v, Vector2f dest);
/**
* Transform the vector <code>(x, y)</code> by the transpose of this matrix and store the result in <code>dest</code>.
*
* @param x
* the x coordinate of the vector to transform
* @param y
* the y coordinate of the vector to transform
* @param dest
* will hold the result
* @return dest
*/
Vector2f transformTranspose(float x, float y, Vector2f dest);
/**
* Apply rotation to this matrix by rotating the given amount of radians
* and store the result in <code>dest</code>.
* <p>
* The produced rotation will rotate a vector counter-clockwise around the origin.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>M * R</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>M * R * v</code>
* , the rotation will be applied first!
* <p>
* Reference: <a href="https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @param dest
* will hold the result
* @return dest
*/
Matrix2f rotate(float ang, Matrix2f dest);
/**
* Pre-multiply a rotation to this matrix by rotating the given amount of radians
* and store the result in <code>dest</code>.
* <p>
* The produced rotation will rotate a vector counter-clockwise around the origin.
* <p>
* If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
* then the new matrix will be <code>R * M</code>. So when transforming a
* vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
* rotation will be applied last!
* <p>
* Reference: <a href="https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions">http://en.wikipedia.org</a>
*
* @param ang
* the angle in radians
* @param dest
* will hold the result
* @return dest
*/
Matrix2f rotateLocal(float ang, Matrix2f dest);
/**
* Get the row at the given <code>row</code> index, starting with <code>0</code>.
*
* @param row
* the row index in <code>[0..1]</code>
* @param dest
* will hold the row components
* @return the passed in destination
* @throws IndexOutOfBoundsException if <code>row</code> is not in <code>[0..1]</code>
*/
Vector2f getRow(int row, Vector2f dest) throws IndexOutOfBoundsException;
/**
* Get the column at the given <code>column</code> index, starting with <code>0</code>.
*
* @param column
* the column index in <code>[0..1]</code>
* @param dest
* will hold the column components
* @return the passed in destination
* @throws IndexOutOfBoundsException if <code>column</code> is not in <code>[0..1]</code>
*/
Vector2f getColumn(int column, Vector2f dest) throws IndexOutOfBoundsException;
/**
* Get the matrix element value at the given column and row.
*
* @param column
* the colum index in <code>[0..1]</code>
* @param row
* the row index in <code>[0..1]</code>
* @return the element value
*/
float get(int column, int row);
/**
* Compute a normal matrix from <code>this</code> matrix and store it into <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Matrix2f normal(Matrix2f dest);
/**
* Get the scaling factors of <code>this</code> matrix for the three base axes.
*
* @param dest
* will hold the scaling factors for <code>x</code> and <code>y</code>
* @return dest
*/
Vector2f getScale(Vector2f dest);
/**
* Obtain the direction of <code>+X</code> before the transformation represented by <code>this</code> matrix is applied.
* <p>
* This method is equivalent to the following code:
* <pre>
* Matrix2f inv = new Matrix2f(this).invert();
* inv.transform(dir.set(1, 0)).normalize();
* </pre>
* If <code>this</code> is already an orthogonal matrix, then consider using {@link #normalizedPositiveX(Vector2f)} instead.
*
* @param dest
* will hold the direction of <code>+X</code>
* @return dest
*/
Vector2f positiveX(Vector2f dest);
/**
* Obtain the direction of <code>+X</code> before the transformation represented by <code>this</code> <i>orthogonal</i> matrix is applied.
* This method only produces correct results if <code>this</code> is an <i>orthogonal</i> matrix.
* <p>
* This method is equivalent to the following code:
* <pre>
* Matrix2f inv = new Matrix2f(this).transpose();
* inv.transform(dir.set(1, 0));
* </pre>
*
* @param dest
* will hold the direction of <code>+X</code>
* @return dest
*/
Vector2f normalizedPositiveX(Vector2f dest);
/**
* Obtain the direction of <code>+Y</code> before the transformation represented by <code>this</code> matrix is applied.
* <p>
* This method is equivalent to the following code:
* <pre>
* Matrix2f inv = new Matrix2f(this).invert();
* inv.transform(dir.set(0, 1)).normalize();
* </pre>
* If <code>this</code> is already an orthogonal matrix, then consider using {@link #normalizedPositiveY(Vector2f)} instead.
*
* @param dest
* will hold the direction of <code>+Y</code>
* @return dest
*/
Vector2f positiveY(Vector2f dest);
/**
* Obtain the direction of <code>+Y</code> before the transformation represented by <code>this</code> <i>orthogonal</i> matrix is applied.
* This method only produces correct results if <code>this</code> is an <i>orthogonal</i> matrix.
* <p>
* This method is equivalent to the following code:
* <pre>
* Matrix2f inv = new Matrix2f(this).transpose();
* inv.transform(dir.set(0, 1));
* </pre>
*
* @param dest
* will hold the direction of <code>+Y</code>
* @return dest
*/
Vector2f normalizedPositiveY(Vector2f dest);
/**
* Component-wise add <code>this</code> and <code>other</code> and store the result in <code>dest</code>.
*
* @param other
* the other addend
* @param dest
* will hold the result
* @return dest
*/
Matrix2f add(Matrix2fc other, Matrix2f dest);
/**
* Component-wise subtract <code>subtrahend</code> from <code>this</code> and store the result in <code>dest</code>.
*
* @param subtrahend
* the subtrahend
* @param dest
* will hold the result
* @return dest
*/
Matrix2f sub(Matrix2fc subtrahend, Matrix2f dest);
/**
* Component-wise multiply <code>this</code> by <code>other</code> and store the result in <code>dest</code>.
*
* @param other
* the other matrix
* @param dest
* will hold the result
* @return dest
*/
Matrix2f mulComponentWise(Matrix2fc other, Matrix2f dest);
/**
* Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code>
* and store the result in <code>dest</code>.
* <p>
* If <code>t</code> is <code>0.0</code> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code>
* then the result is <code>other</code>.
*
* @param other
* the other matrix
* @param t
* the interpolation factor between 0.0 and 1.0
* @param dest
* will hold the result
* @return dest
*/
Matrix2f lerp(Matrix2fc other, float t, Matrix2f dest);
/**
* Compare the matrix elements of <code>this</code> matrix with the given matrix using the given <code>delta</code>
* and return whether all of them are equal within a maximum difference of <code>delta</code>.
* <p>
* Please note that this method is not used by any data structure such as {@link ArrayList} {@link HashSet} or {@link HashMap}
* and their operations, such as {@link ArrayList#contains(Object)} or {@link HashSet#remove(Object)}, since those
* data structures only use the {@link Object#equals(Object)} and {@link Object#hashCode()} methods.
*
* @param m
* the other matrix
* @param delta
* the allowed maximum difference
* @return <code>true</code> whether all of the matrix elements are equal; <code>false</code> otherwise
*/
boolean equals(Matrix2fc m, float delta);
/**
* Determine whether all matrix elements are finite floating-point values, that
* is, they are not {@link Float#isNaN() NaN} and not
* {@link Float#isInfinite() infinity}.
*
* @return {@code true} if all components are finite floating-point values;
* {@code false} otherwise
*/
boolean isFinite();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,186 @@
/*
* The MIT License
*
* Copyright (c) 2018-2021 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 com.jozufozu.flywheel.repack.joml;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* A stack of many {@link Matrix3d} instances. This resembles the matrix stack known from legacy OpenGL.
* <p>
* This {@link Matrix3dStack} class inherits from {@link Matrix3d}, so the current/top matrix is always the
* {@link Matrix3dStack}/{@link Matrix3d} itself. This affects all operations in {@link Matrix3d} that take another
* {@link Matrix3d} as parameter. If a {@link Matrix3dStack} is used as argument to those methods, the effective
* argument will always be the <i>current</i> matrix of the matrix stack.
*
* @author Kai Burjack
*/
public class Matrix3dStack extends Matrix3d {
private static final long serialVersionUID = 1L;
/**
* The matrix stack as a non-growable array. The size of the stack must be specified in the {@link #Matrix3dStack(int) constructor}.
*/
private Matrix3d[] mats;
/**
* The index of the "current" matrix within {@link #mats}.
*/
private int curr;
/**
* Create a new {@link Matrix3dStack} of the given size.
* <p>
* Initially the stack pointer is at zero and the current matrix is set to identity.
*
* @param stackSize
* the size of the stack. This must be at least 1, in which case the {@link Matrix3dStack} simply only consists of <code>this</code>
* {@link Matrix3d}
*/
public Matrix3dStack(int stackSize) {
if (stackSize < 1) {
throw new IllegalArgumentException("stackSize must be >= 1"); //$NON-NLS-1$
}
mats = new Matrix3d[stackSize - 1];
// Allocate all matrices up front to keep the promise of being "allocation-free"
for (int i = 0; i < mats.length; i++) {
mats[i] = new Matrix3d();
}
}
/**
* Do not invoke manually! Only meant for serialization.
* <p>
* Invoking this constructor from client code will result in an inconsistent state of the
* created {@link Matrix3dStack} instance.
*/
public Matrix3dStack() {
/* Empty! */
}
/**
* Set the stack pointer to zero and set the current/bottom matrix to {@link #identity() identity}.
*
* @return this
*/
public Matrix3dStack clear() {
curr = 0;
identity();
return this;
}
/**
* Increment the stack pointer by one and set the values of the new current matrix to the one directly below it.
*
* @return this
*/
public Matrix3dStack pushMatrix() {
if (curr == mats.length) {
throw new IllegalStateException("max stack size of " + (curr + 1) + " reached"); //$NON-NLS-1$ //$NON-NLS-2$
}
mats[curr++].set(this);
return this;
}
/**
* Decrement the stack pointer by one.
* <p>
* This will effectively dispose of the current matrix.
*
* @return this
*/
public Matrix3dStack popMatrix() {
if (curr == 0) {
throw new IllegalStateException("already at the bottom of the stack"); //$NON-NLS-1$
}
set(mats[--curr]);
return this;
}
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + curr;
for (int i = 0; i < curr; i++) {
result = prime * result + mats[i].hashCode();
}
return result;
}
/*
* Contract between Matrix3d and Matrix3dStack:
*
* - Matrix3d.equals(Matrix3dStack) is true iff all the 9 matrix elements are equal
* - Matrix3dStack.equals(Matrix3d) is true iff all the 9 matrix elements are equal
* - Matrix3dStack.equals(Matrix3dStack) is true iff all 9 matrix elements are equal AND the matrix arrays as well as the stack pointer are equal
* - everything else is inequal
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (obj instanceof Matrix3dStack) {
Matrix3dStack other = (Matrix3dStack) obj;
if (curr != other.curr)
return false;
for (int i = 0; i < curr; i++) {
if (!mats[i].equals(other.mats[i]))
return false;
}
}
return true;
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(curr);
for (int i = 0; i < curr; i++) {
out.writeObject(mats[i]);
}
}
public void readExternal(ObjectInput in) throws IOException {
super.readExternal(in);
curr = in.readInt();
mats = new Matrix3dStack[curr];
for (int i = 0; i < curr; i++) {
Matrix3d m = new Matrix3d();
m.readExternal(in);
mats[i] = m;
}
}
public Object clone() throws CloneNotSupportedException {
Matrix3dStack cloned = (Matrix3dStack) super.clone();
Matrix3d[] clonedMats = new Matrix3d[mats.length];
for (int i = 0; i < mats.length; i++)
clonedMats[i] = (Matrix3d) mats[i].clone();
cloned.mats = clonedMats;
return cloned;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,186 @@
/*
* The MIT License
*
* Copyright (c) 2018-2021 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 com.jozufozu.flywheel.repack.joml;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* A stack of many {@link Matrix3f} instances. This resembles the matrix stack known from legacy OpenGL.
* <p>
* This {@link Matrix3fStack} class inherits from {@link Matrix3f}, so the current/top matrix is always the
* {@link Matrix3fStack}/{@link Matrix3f} itself. This affects all operations in {@link Matrix3f} that take another
* {@link Matrix3f} as parameter. If a {@link Matrix3fStack} is used as argument to those methods, the effective
* argument will always be the <i>current</i> matrix of the matrix stack.
*
* @author Kai Burjack
*/
public class Matrix3fStack extends Matrix3f {
private static final long serialVersionUID = 1L;
/**
* The matrix stack as a non-growable array. The size of the stack must be specified in the {@link #Matrix3fStack(int) constructor}.
*/
private Matrix3f[] mats;
/**
* The index of the "current" matrix within {@link #mats}.
*/
private int curr;
/**
* Create a new {@link Matrix3fStack} of the given size.
* <p>
* Initially the stack pointer is at zero and the current matrix is set to identity.
*
* @param stackSize
* the size of the stack. This must be at least 1, in which case the {@link Matrix3fStack} simply only consists of <code>this</code>
* {@link Matrix3f}
*/
public Matrix3fStack(int stackSize) {
if (stackSize < 1) {
throw new IllegalArgumentException("stackSize must be >= 1"); //$NON-NLS-1$
}
mats = new Matrix3f[stackSize - 1];
// Allocate all matrices up front to keep the promise of being "allocation-free"
for (int i = 0; i < mats.length; i++) {
mats[i] = new Matrix3f();
}
}
/**
* Do not invoke manually! Only meant for serialization.
* <p>
* Invoking this constructor from client code will result in an inconsistent state of the
* created {@link Matrix3fStack} instance.
*/
public Matrix3fStack() {
/* Empty! */
}
/**
* Set the stack pointer to zero and set the current/bottom matrix to {@link #identity() identity}.
*
* @return this
*/
public Matrix3fStack clear() {
curr = 0;
identity();
return this;
}
/**
* Increment the stack pointer by one and set the values of the new current matrix to the one directly below it.
*
* @return this
*/
public Matrix3fStack pushMatrix() {
if (curr == mats.length) {
throw new IllegalStateException("max stack size of " + (curr + 1) + " reached"); //$NON-NLS-1$ //$NON-NLS-2$
}
mats[curr++].set(this);
return this;
}
/**
* Decrement the stack pointer by one.
* <p>
* This will effectively dispose of the current matrix.
*
* @return this
*/
public Matrix3fStack popMatrix() {
if (curr == 0) {
throw new IllegalStateException("already at the bottom of the stack"); //$NON-NLS-1$
}
set(mats[--curr]);
return this;
}
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + curr;
for (int i = 0; i < curr; i++) {
result = prime * result + mats[i].hashCode();
}
return result;
}
/*
* Contract between Matrix3f and Matrix3fStack:
*
* - Matrix3f.equals(Matrix3fStack) is true iff all the 9 matrix elements are equal
* - Matrix3fStack.equals(Matrix3f) is true iff all the 9 matrix elements are equal
* - Matrix3fStack.equals(Matrix3fStack) is true iff all 9 matrix elements are equal AND the matrix arrays as well as the stack pointer are equal
* - everything else is inequal
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (obj instanceof Matrix3fStack) {
Matrix3fStack other = (Matrix3fStack) obj;
if (curr != other.curr)
return false;
for (int i = 0; i < curr; i++) {
if (!mats[i].equals(other.mats[i]))
return false;
}
}
return true;
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(curr);
for (int i = 0; i < curr; i++) {
out.writeObject(mats[i]);
}
}
public void readExternal(ObjectInput in) throws IOException {
super.readExternal(in);
curr = in.readInt();
mats = new Matrix3fStack[curr];
for (int i = 0; i < curr; i++) {
Matrix3f m = new Matrix3f();
m.readExternal(in);
mats[i] = m;
}
}
public Object clone() throws CloneNotSupportedException {
Matrix3fStack cloned = (Matrix3fStack) super.clone();
Matrix3f[] clonedMats = new Matrix3f[mats.length];
for (int i = 0; i < mats.length; i++)
clonedMats[i] = (Matrix3f) mats[i].clone();
cloned.mats = clonedMats;
return cloned;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,186 @@
/*
* The MIT License
*
* Copyright (c) 2018-2021 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 com.jozufozu.flywheel.repack.joml;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* A stack of many {@link Matrix3x2d} instances. This resembles the matrix stack known from legacy OpenGL.
* <p>
* This {@link Matrix3x2dStack} class inherits from {@link Matrix3x2d}, so the current/top matrix is always the
* {@link Matrix3x2dStack}/{@link Matrix3x2d} itself. This affects all operations in {@link Matrix3x2d} that take
* another {@link Matrix3x2d} as parameter. If a {@link Matrix3x2dStack} is used as argument to those methods, the
* effective argument will always be the <i>current</i> matrix of the matrix stack.
*
* @author Kai Burjack
*/
public class Matrix3x2dStack extends Matrix3x2d implements Cloneable {
private static final long serialVersionUID = 1L;
/**
* The matrix stack as a non-growable array. The size of the stack must be specified in the {@link #Matrix3x2dStack(int) constructor}.
*/
private Matrix3x2d[] mats;
/**
* The index of the "current" matrix within {@link #mats}.
*/
private int curr;
/**
* Create a new {@link Matrix3x2dStack} of the given size.
* <p>
* Initially the stack pointer is at zero and the current matrix is set to identity.
*
* @param stackSize
* the size of the stack. This must be at least 1, in which case the {@link Matrix3x2dStack} simply only consists of <code>this</code>
* {@link Matrix3x2d}
*/
public Matrix3x2dStack(int stackSize) {
if (stackSize < 1) {
throw new IllegalArgumentException("stackSize must be >= 1"); //$NON-NLS-1$
}
mats = new Matrix3x2d[stackSize - 1];
// Allocate all matrices up front to keep the promise of being "allocation-free"
for (int i = 0; i < mats.length; i++) {
mats[i] = new Matrix3x2d();
}
}
/**
* Do not invoke manually! Only meant for serialization.
* <p>
* Invoking this constructor from client code will result in an inconsistent state of the
* created {@link Matrix3x2dStack} instance.
*/
public Matrix3x2dStack() {
/* Empty! */
}
/**
* Set the stack pointer to zero and set the current/bottom matrix to {@link #identity() identity}.
*
* @return this
*/
public Matrix3x2dStack clear() {
curr = 0;
identity();
return this;
}
/**
* Increment the stack pointer by one and set the values of the new current matrix to the one directly below it.
*
* @return this
*/
public Matrix3x2dStack pushMatrix() {
if (curr == mats.length) {
throw new IllegalStateException("max stack size of " + (curr + 1) + " reached"); //$NON-NLS-1$ //$NON-NLS-2$
}
mats[curr++].set(this);
return this;
}
/**
* Decrement the stack pointer by one.
* <p>
* This will effectively dispose of the current matrix.
*
* @return this
*/
public Matrix3x2dStack popMatrix() {
if (curr == 0) {
throw new IllegalStateException("already at the bottom of the stack"); //$NON-NLS-1$
}
set(mats[--curr]);
return this;
}
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + curr;
for (int i = 0; i < curr; i++) {
result = prime * result + mats[i].hashCode();
}
return result;
}
/*
* Contract between Matrix3x2d and Matrix3x2dStack:
*
* - Matrix3x2d.equals(Matrix3x2dStack) is true iff all the 6 matrix elements are equal
* - Matrix3x2dStack.equals(Matrix3x2d) is true iff all the 6 matrix elements are equal
* - Matrix3x2dStack.equals(Matrix3x2dStack) is true iff all 6 matrix elements are equal AND the matrix arrays as well as the stack pointer are equal
* - everything else is inequal
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (obj instanceof Matrix3x2dStack) {
Matrix3x2dStack other = (Matrix3x2dStack) obj;
if (curr != other.curr)
return false;
for (int i = 0; i < curr; i++) {
if (!mats[i].equals(other.mats[i]))
return false;
}
}
return true;
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(curr);
for (int i = 0; i < curr; i++) {
out.writeObject(mats[i]);
}
}
public void readExternal(ObjectInput in) throws IOException {
super.readExternal(in);
curr = in.readInt();
mats = new Matrix3x2dStack[curr];
for (int i = 0; i < curr; i++) {
Matrix3x2d m = new Matrix3x2d();
m.readExternal(in);
mats[i] = m;
}
}
public Object clone() throws CloneNotSupportedException {
Matrix3x2dStack cloned = (Matrix3x2dStack) super.clone();
Matrix3x2d[] clonedMats = new Matrix3x2d[mats.length];
for (int i = 0; i < mats.length; i++)
clonedMats[i] = (Matrix3x2d) mats[i].clone();
cloned.mats = clonedMats;
return cloned;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,186 @@
/*
* The MIT License
*
* Copyright (c) 2018-2021 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 com.jozufozu.flywheel.repack.joml;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* A stack of many {@link Matrix3x2f} instances. This resembles the matrix stack known from legacy OpenGL.
* <p>
* This {@link Matrix3x2fStack} class inherits from {@link Matrix3x2f}, so the current/top matrix is always the
* {@link Matrix3x2fStack}/{@link Matrix3x2f} itself. This affects all operations in {@link Matrix3x2f} that take
* another {@link Matrix3x2f} as parameter. If a {@link Matrix3x2fStack} is used as argument to those methods, the
* effective argument will always be the <i>current</i> matrix of the matrix stack.
*
* @author Kai Burjack
*/
public class Matrix3x2fStack extends Matrix3x2f {
private static final long serialVersionUID = 1L;
/**
* The matrix stack as a non-growable array. The size of the stack must be specified in the {@link #Matrix3x2fStack(int) constructor}.
*/
private Matrix3x2f[] mats;
/**
* The index of the "current" matrix within {@link #mats}.
*/
private int curr;
/**
* Create a new {@link Matrix3x2fStack} of the given size.
* <p>
* Initially the stack pointer is at zero and the current matrix is set to identity.
*
* @param stackSize
* the size of the stack. This must be at least 1, in which case the {@link Matrix3x2fStack} simply only consists of <code>this</code>
* {@link Matrix3x2f}
*/
public Matrix3x2fStack(int stackSize) {
if (stackSize < 1) {
throw new IllegalArgumentException("stackSize must be >= 1"); //$NON-NLS-1$
}
mats = new Matrix3x2f[stackSize - 1];
// Allocate all matrices up front to keep the promise of being "allocation-free"
for (int i = 0; i < mats.length; i++) {
mats[i] = new Matrix3x2f();
}
}
/**
* Do not invoke manually! Only meant for serialization.
* <p>
* Invoking this constructor from client code will result in an inconsistent state of the
* created {@link Matrix3x2fStack} instance.
*/
public Matrix3x2fStack() {
/* Empty! */
}
/**
* Set the stack pointer to zero and set the current/bottom matrix to {@link #identity() identity}.
*
* @return this
*/
public Matrix3x2fStack clear() {
curr = 0;
identity();
return this;
}
/**
* Increment the stack pointer by one and set the values of the new current matrix to the one directly below it.
*
* @return this
*/
public Matrix3x2fStack pushMatrix() {
if (curr == mats.length) {
throw new IllegalStateException("max stack size of " + (curr + 1) + " reached"); //$NON-NLS-1$ //$NON-NLS-2$
}
mats[curr++].set(this);
return this;
}
/**
* Decrement the stack pointer by one.
* <p>
* This will effectively dispose of the current matrix.
*
* @return this
*/
public Matrix3x2fStack popMatrix() {
if (curr == 0) {
throw new IllegalStateException("already at the bottom of the stack"); //$NON-NLS-1$
}
set(mats[--curr]);
return this;
}
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + curr;
for (int i = 0; i < curr; i++) {
result = prime * result + mats[i].hashCode();
}
return result;
}
/*
* Contract between Matrix3x2f and Matrix3x2fStack:
*
* - Matrix3x2f.equals(Matrix3x2fStack) is true iff all the 6 matrix elements are equal
* - Matrix3x2fStack.equals(Matrix3x2f) is true iff all the 6 matrix elements are equal
* - Matrix3x2fStack.equals(Matrix3x2fStack) is true iff all 6 matrix elements are equal AND the matrix arrays as well as the stack pointer are equal
* - everything else is inequal
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (obj instanceof Matrix3x2fStack) {
Matrix3x2fStack other = (Matrix3x2fStack) obj;
if (curr != other.curr)
return false;
for (int i = 0; i < curr; i++) {
if (!mats[i].equals(other.mats[i]))
return false;
}
}
return true;
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(curr);
for (int i = 0; i < curr; i++) {
out.writeObject(mats[i]);
}
}
public void readExternal(ObjectInput in) throws IOException {
super.readExternal(in);
curr = in.readInt();
mats = new Matrix3x2fStack[curr];
for (int i = 0; i < curr; i++) {
Matrix3x2f m = new Matrix3x2f();
m.readExternal(in);
mats[i] = m;
}
}
public Object clone() throws CloneNotSupportedException {
Matrix3x2fStack cloned = (Matrix3x2fStack) super.clone();
Matrix3x2f[] clonedMats = new Matrix3x2f[mats.length];
for (int i = 0; i < mats.length; i++)
clonedMats[i] = (Matrix3x2f) mats[i].clone();
cloned.mats = clonedMats;
return cloned;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,185 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.joml;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* A stack of many {@link Matrix4d} instances. This resembles the matrix stack known from legacy OpenGL.
* <p>
* This {@link Matrix4dStack} class inherits from {@link Matrix4d}, so the current/top matrix is always the {@link Matrix4dStack}/{@link Matrix4d} itself. This
* affects all operations in {@link Matrix4d} that take another {@link Matrix4d} as parameter. If a {@link Matrix4dStack} is used as argument to those methods,
* the effective argument will always be the <i>current</i> matrix of the matrix stack.
*
* @author Kai Burjack
*/
public class Matrix4dStack extends Matrix4d {
private static final long serialVersionUID = 1L;
/**
* The matrix stack as a non-growable array. The size of the stack must be specified in the {@link #Matrix4dStack(int) constructor}.
*/
private Matrix4d[] mats;
/**
* The index of the "current" matrix within {@link #mats}.
*/
private int curr;
/**
* Create a new {@link Matrix4dStack} of the given size.
* <p>
* Initially the stack pointer is at zero and the current matrix is set to identity.
*
* @param stackSize
* the size of the stack. This must be at least 1, in which case the {@link Matrix4dStack} simply only consists of <code>this</code>
* {@link Matrix4d}
*/
public Matrix4dStack(int stackSize) {
if (stackSize < 1) {
throw new IllegalArgumentException("stackSize must be >= 1"); //$NON-NLS-1$
}
mats = new Matrix4d[stackSize - 1];
// Allocate all matrices up front to keep the promise of being "allocation-free"
for (int i = 0; i < mats.length; i++) {
mats[i] = new Matrix4d();
}
}
/**
* Do not invoke manually! Only meant for serialization.
* <p>
* Invoking this constructor from client code will result in an inconsistent state of the
* created {@link Matrix4dStack} instance.
*/
public Matrix4dStack() {
/* Empty! */
}
/**
* Set the stack pointer to zero and set the current/bottom matrix to {@link #identity() identity}.
*
* @return this
*/
public Matrix4dStack clear() {
curr = 0;
identity();
return this;
}
/**
* Increment the stack pointer by one and set the values of the new current matrix to the one directly below it.
*
* @return this
*/
public Matrix4dStack pushMatrix() {
if (curr == mats.length) {
throw new IllegalStateException("max stack size of " + (curr + 1) + " reached"); //$NON-NLS-1$ //$NON-NLS-2$
}
mats[curr++].set(this);
return this;
}
/**
* Decrement the stack pointer by one.
* <p>
* This will effectively dispose of the current matrix.
*
* @return this
*/
public Matrix4dStack popMatrix() {
if (curr == 0) {
throw new IllegalStateException("already at the bottom of the stack"); //$NON-NLS-1$
}
set(mats[--curr]);
return this;
}
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + curr;
for (int i = 0; i < curr; i++) {
result = prime * result + mats[i].hashCode();
}
return result;
}
/*
* Contract between Matrix4d and Matrix4dStack:
*
* - Matrix4d.equals(Matrix4dStack) is true iff all the 16 matrix elements are equal
* - Matrix4dStack.equals(Matrix4d) is true iff all the 16 matrix elements are equal
* - Matrix4dStack.equals(Matrix4dStack) is true iff all 16 matrix elements are equal AND the matrix arrays as well as the stack pointer are equal
* - everything else is inequal
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (obj instanceof Matrix4dStack) {
Matrix4dStack other = (Matrix4dStack) obj;
if (curr != other.curr)
return false;
for (int i = 0; i < curr; i++) {
if (!mats[i].equals(other.mats[i]))
return false;
}
}
return true;
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(curr);
for (int i = 0; i < curr; i++) {
out.writeObject(mats[i]);
}
}
public void readExternal(ObjectInput in) throws IOException {
super.readExternal(in);
curr = in.readInt();
mats = new Matrix4dStack[curr];
for (int i = 0; i < curr; i++) {
Matrix4d m = new Matrix4d();
m.readExternal(in);
mats[i] = m;
}
}
public Object clone() throws CloneNotSupportedException {
Matrix4dStack cloned = (Matrix4dStack) super.clone();
Matrix4d[] clonedMats = new Matrix4d[mats.length];
for (int i = 0; i < mats.length; i++)
clonedMats[i] = (Matrix4d) mats[i].clone();
cloned.mats = clonedMats;
return cloned;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,185 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.joml;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* A stack of many {@link Matrix4f} instances. This resembles the matrix stack known from legacy OpenGL.
* <p>
* This {@link Matrix4fStack} class inherits from {@link Matrix4f}, so the current/top matrix is always the {@link Matrix4fStack}/{@link Matrix4f} itself. This
* affects all operations in {@link Matrix4f} that take another {@link Matrix4f} as parameter. If a {@link Matrix4fStack} is used as argument to those methods,
* the effective argument will always be the <i>current</i> matrix of the matrix stack.
*
* @author Kai Burjack
*/
public class Matrix4fStack extends Matrix4f {
private static final long serialVersionUID = 1L;
/**
* The matrix stack as a non-growable array. The size of the stack must be specified in the {@link #Matrix4fStack(int) constructor}.
*/
private Matrix4f[] mats;
/**
* The index of the "current" matrix within {@link #mats}.
*/
private int curr;
/**
* Create a new {@link Matrix4fStack} of the given size.
* <p>
* Initially the stack pointer is at zero and the current matrix is set to identity.
*
* @param stackSize
* the size of the stack. This must be at least 1, in which case the {@link Matrix4fStack} simply only consists of <code>this</code>
* {@link Matrix4f}
*/
public Matrix4fStack(int stackSize) {
if (stackSize < 1) {
throw new IllegalArgumentException("stackSize must be >= 1"); //$NON-NLS-1$
}
mats = new Matrix4f[stackSize - 1];
// Allocate all matrices up front to keep the promise of being "allocation-free"
for (int i = 0; i < mats.length; i++) {
mats[i] = new Matrix4f();
}
}
/**
* Do not invoke manually! Only meant for serialization.
* <p>
* Invoking this constructor from client code will result in an inconsistent state of the
* created {@link Matrix4fStack} instance.
*/
public Matrix4fStack() {
/* Empty! */
}
/**
* Set the stack pointer to zero and set the current/bottom matrix to {@link #identity() identity}.
*
* @return this
*/
public Matrix4fStack clear() {
curr = 0;
identity();
return this;
}
/**
* Increment the stack pointer by one and set the values of the new current matrix to the one directly below it.
*
* @return this
*/
public Matrix4fStack pushMatrix() {
if (curr == mats.length) {
throw new IllegalStateException("max stack size of " + (curr + 1) + " reached"); //$NON-NLS-1$ //$NON-NLS-2$
}
mats[curr++].set(this);
return this;
}
/**
* Decrement the stack pointer by one.
* <p>
* This will effectively dispose of the current matrix.
*
* @return this
*/
public Matrix4fStack popMatrix() {
if (curr == 0) {
throw new IllegalStateException("already at the bottom of the stack"); //$NON-NLS-1$
}
set(mats[--curr]);
return this;
}
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + curr;
for (int i = 0; i < curr; i++) {
result = prime * result + mats[i].hashCode();
}
return result;
}
/*
* Contract between Matrix4f and Matrix4fStack:
*
* - Matrix4f.equals(Matrix4fStack) is true iff all the 16 matrix elements are equal
* - Matrix4fStack.equals(Matrix4f) is true iff all the 16 matrix elements are equal
* - Matrix4fStack.equals(Matrix4fStack) is true iff all 16 matrix elements are equal AND the matrix arrays as well as the stack pointer are equal
* - everything else is inequal
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (obj instanceof Matrix4fStack) {
Matrix4fStack other = (Matrix4fStack) obj;
if (curr != other.curr)
return false;
for (int i = 0; i < curr; i++) {
if (!mats[i].equals(other.mats[i]))
return false;
}
}
return true;
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(curr);
for (int i = 0; i < curr; i++) {
out.writeObject(mats[i]);
}
}
public void readExternal(ObjectInput in) throws IOException {
super.readExternal(in);
curr = in.readInt();
mats = new Matrix4fStack[curr];
for (int i = 0; i < curr; i++) {
Matrix4f m = new Matrix4f();
m.readExternal(in);
mats[i] = m;
}
}
public Object clone() throws CloneNotSupportedException {
Matrix4fStack cloned = (Matrix4fStack) super.clone();
Matrix4f[] clonedMats = new Matrix4f[mats.length];
for (int i = 0; i < mats.length; i++)
clonedMats[i] = (Matrix4f) mats[i].clone();
cloned.mats = clonedMats;
return cloned;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,186 @@
/*
* The MIT License
*
* Copyright (c) 2018-2021 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 com.jozufozu.flywheel.repack.joml;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* A stack of many {@link Matrix4x3d} instances. This resembles the matrix stack known from legacy OpenGL.
* <p>
* This {@link Matrix4x3dStack} class inherits from {@link Matrix4x3d}, so the current/top matrix is always the
* {@link Matrix4x3dStack}/{@link Matrix4x3d} itself. This affects all operations in {@link Matrix4x3d} that take
* another {@link Matrix4x3d} as parameter. If a {@link Matrix4x3dStack} is used as argument to those methods, the
* effective argument will always be the <i>current</i> matrix of the matrix stack.
*
* @author Kai Burjack
*/
public class Matrix4x3dStack extends Matrix4x3d {
private static final long serialVersionUID = 1L;
/**
* The matrix stack as a non-growable array. The size of the stack must be specified in the {@link #Matrix4x3dStack(int) constructor}.
*/
private Matrix4x3d[] mats;
/**
* The index of the "current" matrix within {@link #mats}.
*/
private int curr;
/**
* Create a new {@link Matrix4x3dStack} of the given size.
* <p>
* Initially the stack pointer is at zero and the current matrix is set to identity.
*
* @param stackSize
* the size of the stack. This must be at least 1, in which case the {@link Matrix4x3dStack} simply only consists of <code>this</code>
* {@link Matrix4x3d}
*/
public Matrix4x3dStack(int stackSize) {
if (stackSize < 1) {
throw new IllegalArgumentException("stackSize must be >= 1"); //$NON-NLS-1$
}
mats = new Matrix4x3d[stackSize - 1];
// Allocate all matrices up front to keep the promise of being "allocation-free"
for (int i = 0; i < mats.length; i++) {
mats[i] = new Matrix4x3d();
}
}
/**
* Do not invoke manually! Only meant for serialization.
* <p>
* Invoking this constructor from client code will result in an inconsistent state of the
* created {@link Matrix4x3dStack} instance.
*/
public Matrix4x3dStack() {
/* Empty! */
}
/**
* Set the stack pointer to zero and set the current/bottom matrix to {@link #identity() identity}.
*
* @return this
*/
public Matrix4x3dStack clear() {
curr = 0;
identity();
return this;
}
/**
* Increment the stack pointer by one and set the values of the new current matrix to the one directly below it.
*
* @return this
*/
public Matrix4x3dStack pushMatrix() {
if (curr == mats.length) {
throw new IllegalStateException("max stack size of " + (curr + 1) + " reached"); //$NON-NLS-1$ //$NON-NLS-2$
}
mats[curr++].set(this);
return this;
}
/**
* Decrement the stack pointer by one.
* <p>
* This will effectively dispose of the current matrix.
*
* @return this
*/
public Matrix4x3dStack popMatrix() {
if (curr == 0) {
throw new IllegalStateException("already at the bottom of the stack"); //$NON-NLS-1$
}
set(mats[--curr]);
return this;
}
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + curr;
for (int i = 0; i < curr; i++) {
result = prime * result + mats[i].hashCode();
}
return result;
}
/*
* Contract between Matrix4x3d and Matrix4x3dStack:
*
* - Matrix4x3d.equals(Matrix4x3dStack) is true iff all the 12 matrix elements are equal
* - Matrix4x3dStack.equals(Matrix4x3d) is true iff all the 12 matrix elements are equal
* - Matrix4x3dStack.equals(Matrix4x3dStack) is true iff all 12 matrix elements are equal AND the matrix arrays as well as the stack pointer are equal
* - everything else is inequal
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (obj instanceof Matrix4x3dStack) {
Matrix4x3dStack other = (Matrix4x3dStack) obj;
if (curr != other.curr)
return false;
for (int i = 0; i < curr; i++) {
if (!mats[i].equals(other.mats[i]))
return false;
}
}
return true;
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(curr);
for (int i = 0; i < curr; i++) {
out.writeObject(mats[i]);
}
}
public void readExternal(ObjectInput in) throws IOException {
super.readExternal(in);
curr = in.readInt();
mats = new Matrix4x3dStack[curr];
for (int i = 0; i < curr; i++) {
Matrix4x3d m = new Matrix4x3d();
m.readExternal(in);
mats[i] = m;
}
}
public Object clone() throws CloneNotSupportedException {
Matrix4x3dStack cloned = (Matrix4x3dStack) super.clone();
Matrix4x3d[] clonedMats = new Matrix4x3d[mats.length];
for (int i = 0; i < mats.length; i++)
clonedMats[i] = (Matrix4x3d) mats[i].clone();
cloned.mats = clonedMats;
return cloned;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,186 @@
/*
* The MIT License
*
* Copyright (c) 2018-2021 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 com.jozufozu.flywheel.repack.joml;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* A stack of many {@link Matrix4x3f} instances. This resembles the matrix stack known from legacy OpenGL.
* <p>
* This {@link Matrix4x3fStack} class inherits from {@link Matrix4x3f}, so the current/top matrix is always the
* {@link Matrix4x3fStack}/{@link Matrix4x3f} itself. This affects all operations in {@link Matrix4x3f} that take
* another {@link Matrix4x3f} as parameter. If a {@link Matrix4x3fStack} is used as argument to those methods, the
* effective argument will always be the <i>current</i> matrix of the matrix stack.
*
* @author Kai Burjack
*/
public class Matrix4x3fStack extends Matrix4x3f {
private static final long serialVersionUID = 1L;
/**
* The matrix stack as a non-growable array. The size of the stack must be specified in the {@link #Matrix4x3fStack(int) constructor}.
*/
private Matrix4x3f[] mats;
/**
* The index of the "current" matrix within {@link #mats}.
*/
private int curr;
/**
* Create a new {@link Matrix4x3fStack} of the given size.
* <p>
* Initially the stack pointer is at zero and the current matrix is set to identity.
*
* @param stackSize
* the size of the stack. This must be at least 1, in which case the {@link Matrix4x3fStack} simply only consists of <code>this</code>
* {@link Matrix4x3f}
*/
public Matrix4x3fStack(int stackSize) {
if (stackSize < 1) {
throw new IllegalArgumentException("stackSize must be >= 1"); //$NON-NLS-1$
}
mats = new Matrix4x3f[stackSize - 1];
// Allocate all matrices up front to keep the promise of being "allocation-free"
for (int i = 0; i < mats.length; i++) {
mats[i] = new Matrix4x3f();
}
}
/**
* Do not invoke manually! Only meant for serialization.
* <p>
* Invoking this constructor from client code will result in an inconsistent state of the
* created {@link Matrix4x3fStack} instance.
*/
public Matrix4x3fStack() {
/* Empty! */
}
/**
* Set the stack pointer to zero and set the current/bottom matrix to {@link #identity() identity}.
*
* @return this
*/
public Matrix4x3fStack clear() {
curr = 0;
identity();
return this;
}
/**
* Increment the stack pointer by one and set the values of the new current matrix to the one directly below it.
*
* @return this
*/
public Matrix4x3fStack pushMatrix() {
if (curr == mats.length) {
throw new IllegalStateException("max stack size of " + (curr + 1) + " reached"); //$NON-NLS-1$ //$NON-NLS-2$
}
mats[curr++].set(this);
return this;
}
/**
* Decrement the stack pointer by one.
* <p>
* This will effectively dispose of the current matrix.
*
* @return this
*/
public Matrix4x3fStack popMatrix() {
if (curr == 0) {
throw new IllegalStateException("already at the bottom of the stack"); //$NON-NLS-1$
}
set(mats[--curr]);
return this;
}
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + curr;
for (int i = 0; i < curr; i++) {
result = prime * result + mats[i].hashCode();
}
return result;
}
/*
* Contract between Matrix4x3f and Matrix4x3fStack:
*
* - Matrix4x3f.equals(Matrix4x3fStack) is true iff all the 12 matrix elements are equal
* - Matrix4x3fStack.equals(Matrix4x3f) is true iff all the 12 matrix elements are equal
* - Matrix4x3fStack.equals(Matrix4x3fStack) is true iff all 12 matrix elements are equal AND the matrix arrays as well as the stack pointer are equal
* - everything else is inequal
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (obj instanceof Matrix4x3fStack) {
Matrix4x3fStack other = (Matrix4x3fStack) obj;
if (curr != other.curr)
return false;
for (int i = 0; i < curr; i++) {
if (!mats[i].equals(other.mats[i]))
return false;
}
}
return true;
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(curr);
for (int i = 0; i < curr; i++) {
out.writeObject(mats[i]);
}
}
public void readExternal(ObjectInput in) throws IOException {
super.readExternal(in);
curr = in.readInt();
mats = new Matrix4x3fStack[curr];
for (int i = 0; i < curr; i++) {
Matrix4x3f m = new Matrix4x3f();
m.readExternal(in);
mats[i] = m;
}
}
public Object clone() throws CloneNotSupportedException {
Matrix4x3fStack cloned = (Matrix4x3fStack) super.clone();
Matrix4x3f[] clonedMats = new Matrix4x3f[mats.length];
for (int i = 0; i < mats.length; i++)
clonedMats[i] = (Matrix4x3f) mats[i].clone();
cloned.mats = clonedMats;
return cloned;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,116 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Locale;
/**
* Utility class for reading system properties.
*
* @author Kai Burjack
*/
public final class Options {
/**
* Whether certain debugging checks should be made, such as that only direct NIO Buffers are used when Unsafe is active,
* and a proxy should be created on calls to readOnlyView().
*/
public static final boolean DEBUG = hasOption(System.getProperty("joml.debug", "false"));
/**
* Whether <i>not</i> to use sun.misc.Unsafe when copying memory with MemUtil.
*/
public static final boolean NO_UNSAFE = hasOption(System.getProperty("joml.nounsafe", "false"));
/**
* Whether to <i>force</i> the use of sun.misc.Unsafe when copying memory with MemUtil.
*/
public static final boolean FORCE_UNSAFE = hasOption(System.getProperty("joml.forceUnsafe", "false"));
/**
* Whether fast approximations of some java.lang.Math operations should be used.
*/
public static final boolean FASTMATH = hasOption(System.getProperty("joml.fastmath", "false"));
/**
* When {@link #FASTMATH} is <code>true</code>, whether to use a lookup table for sin/cos.
*/
public static final boolean SIN_LOOKUP = hasOption(System.getProperty("joml.sinLookup", "false"));
/**
* When {@link #SIN_LOOKUP} is <code>true</code>, this determines the table size.
*/
public static final int SIN_LOOKUP_BITS = Integer.parseInt(System.getProperty("joml.sinLookup.bits", "14"));
/**
* Whether to use a {@link NumberFormat} producing scientific notation output when formatting matrix,
* vector and quaternion components to strings.
*/
public static final boolean useNumberFormat = hasOption(System.getProperty("joml.format", "true"));
/**
* Whether to try using java.lang.Math.fma() in most matrix/vector/quaternion operations if it is available.
* If the CPU does <i>not</i> support it, it will be a lot slower than `a*b+c` and potentially generate a lot of memory allocations
* for the emulation with `java.util.BigDecimal`, though.
*/
public static final boolean USE_MATH_FMA = hasOption(System.getProperty("joml.useMathFma", "false"));
/**
* When {@link #useNumberFormat} is <code>true</code> then this determines the number of decimal digits
* produced in the formatted numbers.
*/
public static final int numberFormatDecimals = Integer.parseInt(System.getProperty("joml.format.decimals", "3"));
/**
* The {@link NumberFormat} used to format all numbers throughout all JOML classes.
*/
public static final NumberFormat NUMBER_FORMAT = decimalFormat();
private Options() {
}
private static NumberFormat decimalFormat() {
NumberFormat df;
if (useNumberFormat) {
char[] prec = new char[numberFormatDecimals];
Arrays.fill(prec, '0');
df = new DecimalFormat(" 0." + new String(prec) + "E0;-");
} else {
df = NumberFormat.getNumberInstance(Locale.ENGLISH);
df.setGroupingUsed(false);
}
return df;
}
private static boolean hasOption(String v) {
if (v == null)
return false;
if (v.trim().length() == 0)
return true;
return Boolean.valueOf(v).booleanValue();
}
}

View file

@ -0,0 +1,328 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Class for polygon/point intersection tests when testing many points against one or many static concave or convex, simple polygons.
* <p>
* This is an implementation of the algorithm described in <a href="http://alienryderflex.com/polygon/">http://alienryderflex.com</a> and augmented with using a
* custom interval tree to avoid testing all polygon edges against a point, but only those that intersect the imaginary ray along the same y co-ordinate of the
* search point. This algorithm additionally also supports multiple polygons.
* <p>
* This class is thread-safe and can be used in a multithreaded environment when testing many points against the same polygon concurrently.
* <p>
* Reference: <a href="http://alienryderflex.com/polygon/">http://alienryderflex.com</a>
*
* @author Kai Burjack
*/
public class PolygonsIntersection {
static class ByStartComparator implements Comparator {
public int compare(Object o1, Object o2) {
Interval i1 = (Interval) o1;
Interval i2 = (Interval) o2;
return Float.compare(i1.start, i2.start);
}
}
static class ByEndComparator implements Comparator {
public int compare(Object o1, Object o2) {
Interval i1 = (Interval) o1;
Interval i2 = (Interval) o2;
return Float.compare(i2.end, i1.end);
}
}
static class Interval {
float start, end;
int i, j, polyIndex;
}
static class IntervalTreeNode {
float center;
float childrenMinMax;
IntervalTreeNode left;
IntervalTreeNode right;
List/* <Interval> */ byBeginning;
List/* <Interval> */ byEnding;
static boolean computeEvenOdd(float[] verticesXY, Interval ival, float x, float y, boolean evenOdd, BitSet inPolys) {
boolean newEvenOdd = evenOdd;
int i = ival.i;
int j = ival.j;
float yi = verticesXY[2 * i + 1];
float yj = verticesXY[2 * j + 1];
float xi = verticesXY[2 * i + 0];
float xj = verticesXY[2 * j + 0];
if ((yi < y && yj >= y || yj < y && yi >= y) && (xi <= x || xj <= x)) {
float xDist = xi + (y - yi) / (yj - yi) * (xj - xi) - x;
newEvenOdd ^= xDist < 0.0f;
if (newEvenOdd != evenOdd && inPolys != null) {
inPolys.flip(ival.polyIndex);
}
}
return newEvenOdd;
}
boolean traverse(float[] verticesXY, float x, float y, boolean evenOdd, BitSet inPolys) {
boolean newEvenOdd = evenOdd;
if (y == center && byBeginning != null) {
int size = byBeginning.size();
for (int b = 0; b < size; b++) {
Interval ival = (Interval) byBeginning.get(b);
newEvenOdd = computeEvenOdd(verticesXY, ival, x, y, newEvenOdd, inPolys);
}
} else if (y < center) {
if (left != null && left.childrenMinMax >= y)
newEvenOdd = left.traverse(verticesXY, x, y, newEvenOdd, inPolys);
if (byBeginning != null) {
int size = byBeginning.size();
for (int b = 0; b < size; b++) {
Interval ival = (Interval) byBeginning.get(b);
if (ival.start > y)
break;
newEvenOdd = computeEvenOdd(verticesXY, ival, x, y, newEvenOdd, inPolys);
}
}
} else if (y > center) {
if (right != null && right.childrenMinMax <= y)
newEvenOdd = right.traverse(verticesXY, x, y, newEvenOdd, inPolys);
if (byEnding != null) {
int size = byEnding.size();
for (int b = 0; b < size; b++) {
Interval ival = (Interval) byEnding.get(b);
if (ival.end < y)
break;
newEvenOdd = computeEvenOdd(verticesXY, ival, x, y, newEvenOdd, inPolys);
}
}
}
return newEvenOdd;
}
}
private static final ByStartComparator byStartComparator = new ByStartComparator();
private static final ByEndComparator byEndComparator = new ByEndComparator();
protected final float[] verticesXY;
private float minX, minY, maxX, maxY;
private float centerX, centerY, radiusSquared;
private IntervalTreeNode tree;
/**
* Create a new {@link PolygonsIntersection} object with the given polygon vertices.
* <p>
* The <code>verticesXY</code> array contains the x and y coordinates of all vertices. This array will not be copied so its content must remain constant for
* as long as the PolygonPointIntersection is used with it.
*
* @param verticesXY
* contains the x and y coordinates of all vertices
* @param polygons
* defines the start vertices of a new polygon. The first vertex of the first polygon is always the
* vertex with index 0. In order to define a hole simply define a polygon that is completely inside another polygon
* @param count
* the number of vertices to use from the <code>verticesXY</code> array, staring with index 0
*/
public PolygonsIntersection(float[] verticesXY, int[] polygons, int count) {
this.verticesXY = verticesXY;
// Do all the allocations and initializations during this constructor
preprocess(count, polygons);
}
private IntervalTreeNode buildNode(List intervals, float center) {
List left = null;
List right = null;
List byStart = null;
List byEnd = null;
float leftMin = 1E38f, leftMax = -1E38f, rightMin = 1E38f, rightMax = -1E38f;
float thisMin = 1E38f, thisMax = -1E38f;
for (int i = 0; i < intervals.size(); i++) {
Interval ival = (Interval) intervals.get(i);
if (ival.start < center && ival.end < center) {
if (left == null)
left = new ArrayList();
left.add(ival);
leftMin = leftMin < ival.start ? leftMin : ival.start;
leftMax = leftMax > ival.end ? leftMax : ival.end;
} else if (ival.start > center && ival.end > center) {
if (right == null)
right = new ArrayList();
right.add(ival);
rightMin = rightMin < ival.start ? rightMin : ival.start;
rightMax = rightMax > ival.end ? rightMax : ival.end;
} else {
if (byStart == null || byEnd == null) {
byStart = new ArrayList();
byEnd = new ArrayList();
}
thisMin = ival.start < thisMin ? ival.start : thisMin;
thisMax = ival.end > thisMax ? ival.end : thisMax;
byStart.add(ival);
byEnd.add(ival);
}
}
if (byStart != null) {
Collections.sort(byStart, byStartComparator);
Collections.sort(byEnd, byEndComparator);
}
IntervalTreeNode tree = new IntervalTreeNode();
tree.byBeginning = byStart;
tree.byEnding = byEnd;
tree.center = center;
if (left != null) {
tree.left = buildNode(left, (leftMin + leftMax) / 2.0f);
tree.left.childrenMinMax = leftMax;
}
if (right != null) {
tree.right = buildNode(right, (rightMin + rightMax) / 2.0f);
tree.right.childrenMinMax = rightMin;
}
return tree;
}
private void preprocess(int count, int[] polygons) {
int i, j = 0;
minX = minY = 1E38f;
maxX = maxY = -1E38f;
List intervals = new ArrayList(count);
int first = 0;
int currPoly = 0;
for (i = 1; i < count; i++) {
if (polygons != null && polygons.length > currPoly && polygons[currPoly] == i) {
/* New polygon starts. End the current. */
float prevy = verticesXY[2 * (i - 1) + 1];
float firsty = verticesXY[2 * first + 1];
Interval ival = new Interval();
ival.start = prevy < firsty ? prevy : firsty;
ival.end = firsty > prevy ? firsty : prevy;
ival.i = i - 1;
ival.j = first;
ival.polyIndex = currPoly;
intervals.add(ival);
first = i;
currPoly++;
i++;
j = i - 1;
}
float yi = verticesXY[2 * i + 1];
float xi = verticesXY[2 * i + 0];
float yj = verticesXY[2 * j + 1];
minX = xi < minX ? xi : minX;
minY = yi < minY ? yi : minY;
maxX = xi > maxX ? xi : maxX;
maxY = yi > maxY ? yi : maxY;
Interval ival = new Interval();
ival.start = yi < yj ? yi : yj;
ival.end = yj > yi ? yj : yi;
ival.i = i;
ival.j = j;
ival.polyIndex = currPoly;
intervals.add(ival);
j = i;
}
// Close current polygon
float yi = verticesXY[2 * (i - 1) + 1];
float xi = verticesXY[2 * (i - 1) + 0];
float yj = verticesXY[2 * first + 1];
minX = xi < minX ? xi : minX;
minY = yi < minY ? yi : minY;
maxX = xi > maxX ? xi : maxX;
maxY = yi > maxY ? yi : maxY;
Interval ival = new Interval();
ival.start = yi < yj ? yi : yj;
ival.end = yj > yi ? yj : yi;
ival.i = i - 1;
ival.j = first;
ival.polyIndex = currPoly;
intervals.add(ival);
// compute bounding sphere and rectangle
centerX = (maxX + minX) * 0.5f;
centerY = (maxY + minY) * 0.5f;
float dx = maxX - centerX;
float dy = maxY - centerY;
radiusSquared = dx * dx + dy * dy;
// build interval tree
tree = buildNode(intervals, centerY);
}
/**
* Test whether the given point <code>(x, y)</code> lies inside any polygon stored in this {@link PolygonsIntersection} object.
* <p>
* This method is thread-safe and can be used to test many points concurrently.
* <p>
* In order to obtain the index of the polygon the point is inside of, use {@link #testPoint(float, float, BitSet)}
*
* @see #testPoint(float, float, BitSet)
*
* @param x
* the x coordinate of the point to test
* @param y
* the y coordinate of the point to test
* @return <code>true</code> iff the point lies inside any polygon; <code>false</code> otherwise
*/
public boolean testPoint(float x, float y) {
return testPoint(x, y, null);
}
/**
* Test whether the given point <code>(x, y)</code> lies inside any polygon stored in this {@link PolygonsIntersection} object.
* <p>
* This method is thread-safe and can be used to test many points concurrently.
*
* @param x
* the x coordinate of the point to test
* @param y
* the y coordinate of the point to test
* @param inPolys
* if not <code>null</code> then the <i>i</i>-th bit is set if the given point is inside the <i>i</i>-th polygon
* @return <code>true</code> iff the point lies inside the polygon and not inside a hole; <code>false</code> otherwise
*/
public boolean testPoint(float x, float y, BitSet inPolys) {
// check bounding sphere first
float dx = (x - centerX);
float dy = (y - centerY);
if (inPolys != null)
inPolys.clear();
if (dx * dx + dy * dy > radiusSquared)
return false;
// check bounding box next
if (maxX < x || maxY < y || minX > x || minY > y)
return false;
// ask interval tree for all polygon edges intersecting 'y' and perform
// the even/odd/crosscutting/raycast algorithm on them and also return
// the polygon index of the polygon the point is in by setting the appropriate
// bit in the given BitSet.
boolean res = tree.traverse(verticesXY, x, y, false, inPolys);
return res;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,354 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Computes the weighted average of multiple rotations represented as {@link Quaterniond} instances.
* <p>
* Instances of this class are <i>not</i> thread-safe.
*
* @author Kai Burjack
*/
public class QuaterniondInterpolator {
/**
* Performs singular value decomposition on {@link Matrix3d}.
* <p>
* This code was adapted from <a href="http://www.public.iastate.edu/~dicook/JSS/paper/code/svd.c">http://www.public.iastate.edu/</a>.
*
* @author Kai Burjack
*/
private static class SvdDecomposition3d {
private final double rv1[];
private final double w[];
private final double v[];
SvdDecomposition3d() {
this.rv1 = new double[3];
this.w = new double[3];
this.v = new double[9];
}
private double SIGN(double a, double b) {
return (b) >= 0.0 ? Math.abs(a) : -Math.abs(a);
}
void svd(double[] a, int maxIterations, Matrix3d destU, Matrix3d destV) {
int flag, i, its, j, jj, k, l = 0, nm = 0;
double c, f, h, s, x, y, z;
double anorm = 0.0, g = 0.0, scale = 0.0;
/* Householder reduction to bidiagonal form */
for (i = 0; i < 3; i++) {
/* left-hand reduction */
l = i + 1;
rv1[i] = scale * g;
g = s = scale = 0.0;
for (k = i; k < 3; k++)
scale += Math.abs(a[k + 3 * i]);
if (scale != 0.0) {
for (k = i; k < 3; k++) {
a[k + 3 * i] = (a[k + 3 * i] / scale);
s += (a[k + 3 * i] * a[k + 3 * i]);
}
f = a[i + 3 * i];
g = -SIGN(Math.sqrt(s), f);
h = f * g - s;
a[i + 3 * i] = f - g;
if (i != 3 - 1) {
for (j = l; j < 3; j++) {
for (s = 0.0, k = i; k < 3; k++)
s += a[k + 3 * i] * a[k + 3 * j];
f = s / h;
for (k = i; k < 3; k++)
a[k + 3 * j] += f * a[k + 3 * i];
}
}
for (k = i; k < 3; k++)
a[k + 3 * i] = a[k + 3 * i] * scale;
}
w[i] = (scale * g);
/* right-hand reduction */
g = s = scale = 0.0;
if (i < 3 && i != 3 - 1) {
for (k = l; k < 3; k++)
scale += Math.abs(a[i + 3 * k]);
if (scale != 0.0) {
for (k = l; k < 3; k++) {
a[i + 3 * k] = a[i + 3 * k] / scale;
s += a[i + 3 * k] * a[i + 3 * k];
}
f = a[i + 3 * l];
g = -SIGN(Math.sqrt(s), f);
h = f * g - s;
a[i + 3 * l] = f - g;
for (k = l; k < 3; k++)
rv1[k] = a[i + 3 * k] / h;
if (i != 3 - 1) {
for (j = l; j < 3; j++) {
for (s = 0.0, k = l; k < 3; k++)
s += a[j + 3 * k] * a[i + 3 * k];
for (k = l; k < 3; k++)
a[j + 3 * k] += s * rv1[k];
}
}
for (k = l; k < 3; k++)
a[i + 3 * k] = a[i + 3 * k] * scale;
}
}
anorm = Math.max(anorm, (Math.abs(w[i]) + Math.abs(rv1[i])));
}
/* accumulate the right-hand transformation */
for (i = 3 - 1; i >= 0; i--) {
if (i < 3 - 1) {
if (g != 0.0) {
for (j = l; j < 3; j++)
v[j + 3 * i] = (a[i + 3 * j] / a[i + 3 * l]) / g;
/* double division to avoid underflow */
for (j = l; j < 3; j++) {
for (s = 0.0, k = l; k < 3; k++)
s += a[i + 3 * k] * v[k + 3 * j];
for (k = l; k < 3; k++)
v[k + 3 * j] += s * v[k + 3 * i];
}
}
for (j = l; j < 3; j++)
v[i + 3 * j] = v[j + 3 * i] = 0.0;
}
v[i + 3 * i] = 1.0;
g = rv1[i];
l = i;
}
/* accumulate the left-hand transformation */
for (i = 3 - 1; i >= 0; i--) {
l = i + 1;
g = w[i];
if (i < 3 - 1)
for (j = l; j < 3; j++)
a[i + 3 * j] = 0.0;
if (g != 0.0) {
g = 1.0 / g;
if (i != 3 - 1) {
for (j = l; j < 3; j++) {
for (s = 0.0, k = l; k < 3; k++)
s += a[k + 3 * i] * a[k + 3 * j];
f = s / a[i + 3 * i] * g;
for (k = i; k < 3; k++)
a[k + 3 * j] += f * a[k + 3 * i];
}
}
for (j = i; j < 3; j++)
a[j + 3 * i] = a[j + 3 * i] * g;
} else {
for (j = i; j < 3; j++)
a[j + 3 * i] = 0.0;
}
++a[i + 3 * i];
}
/* diagonalize the bidiagonal form */
for (k = 3 - 1; k >= 0; k--) { /* loop over singular values */
for (its = 0; its < maxIterations; its++) { /* loop over allowed iterations */
flag = 1;
for (l = k; l >= 0; l--) { /* test for splitting */
nm = l - 1;
if (Math.abs(rv1[l]) + anorm == anorm) {
flag = 0;
break;
}
if (Math.abs(w[nm]) + anorm == anorm)
break;
}
if (flag != 0) {
c = 0.0;
s = 1.0;
for (i = l; i <= k; i++) {
f = s * rv1[i];
if (Math.abs(f) + anorm != anorm) {
g = w[i];
h = PYTHAG(f, g);
w[i] = h;
h = 1.0 / h;
c = g * h;
s = (-f * h);
for (j = 0; j < 3; j++) {
y = a[j + 3 * nm];
z = a[j + 3 * i];
a[j + 3 * nm] = y * c + z * s;
a[j + 3 * i] = z * c - y * s;
}
}
}
}
z = w[k];
if (l == k) { /* convergence */
if (z < 0.0) { /* make singular value nonnegative */
w[k] = -z;
for (j = 0; j < 3; j++)
v[j + 3 * k] = (-v[j + 3 * k]);
}
break;
}
if (its == maxIterations - 1) {
throw new RuntimeException("No convergence after " + maxIterations + " iterations");
}
/* shift from bottom 2 x 2 minor */
x = w[l];
nm = k - 1;
y = w[nm];
g = rv1[nm];
h = rv1[k];
f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
g = PYTHAG(f, 1.0);
f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x;
/* next QR transformation */
c = s = 1.0;
for (j = l; j <= nm; j++) {
i = j + 1;
g = rv1[i];
y = w[i];
h = s * g;
g = c * g;
z = PYTHAG(f, h);
rv1[j] = z;
c = f / z;
s = h / z;
f = x * c + g * s;
g = g * c - x * s;
h = y * s;
y = y * c;
for (jj = 0; jj < 3; jj++) {
x = v[jj + 3 * j];
z = v[jj + 3 * i];
v[jj + 3 * j] = x * c + z * s;
v[jj + 3 * i] = z * c - x * s;
}
z = PYTHAG(f, h);
w[j] = z;
if (z != 0.0) {
z = 1.0 / z;
c = f * z;
s = h * z;
}
f = (c * g) + (s * y);
x = (c * y) - (s * g);
for (jj = 0; jj < 3; jj++) {
y = a[jj + 3 * j];
z = a[jj + 3 * i];
a[jj + 3 * j] = y * c + z * s;
a[jj + 3 * i] = z * c - y * s;
}
}
rv1[l] = 0.0;
rv1[k] = f;
w[k] = x;
}
}
destU.set(a);
destV.set(v);
}
private static double PYTHAG(double a, double b) {
double at = Math.abs(a), bt = Math.abs(b), ct, result;
if (at > bt) {
ct = bt / at;
result = at * Math.sqrt(1.0 + ct * ct);
} else if (bt > 0.0) {
ct = at / bt;
result = bt * Math.sqrt(1.0 + ct * ct);
} else
result = 0.0;
return (result);
}
}
private final SvdDecomposition3d svdDecomposition3d = new SvdDecomposition3d();
private final double[] m = new double[9];
private final Matrix3d u = new Matrix3d();
private final Matrix3d v = new Matrix3d();
/**
* Compute the weighted average of all of the quaternions given in <code>qs</code> using the specified interpolation factors <code>weights</code>, and store the result in <code>dest</code>.
*
* @param qs
* the quaternions to interpolate over
* @param weights
* the weights of each individual quaternion in <code>qs</code>
* @param maxSvdIterations
* the maximum number of iterations in the Singular Value Decomposition step used by this method
* @param dest
* will hold the result
* @return dest
*/
public Quaterniond computeWeightedAverage(Quaterniond[] qs, double[] weights, int maxSvdIterations, Quaterniond dest) {
double m00 = 0.0, m01 = 0.0, m02 = 0.0;
double m10 = 0.0, m11 = 0.0, m12 = 0.0;
double m20 = 0.0, m21 = 0.0, m22 = 0.0;
// Sum the rotation matrices of qs
for (int i = 0; i < qs.length; i++) {
Quaterniond q = qs[i];
double dx = q.x + q.x;
double dy = q.y + q.y;
double dz = q.z + q.z;
double q00 = dx * q.x;
double q11 = dy * q.y;
double q22 = dz * q.z;
double q01 = dx * q.y;
double q02 = dx * q.z;
double q03 = dx * q.w;
double q12 = dy * q.z;
double q13 = dy * q.w;
double q23 = dz * q.w;
m00 += weights[i] * (1.0 - q11 - q22);
m01 += weights[i] * (q01 + q23);
m02 += weights[i] * (q02 - q13);
m10 += weights[i] * (q01 - q23);
m11 += weights[i] * (1.0 - q22 - q00);
m12 += weights[i] * (q12 + q03);
m20 += weights[i] * (q02 + q13);
m21 += weights[i] * (q12 - q03);
m22 += weights[i] * (1.0 - q11 - q00);
}
m[0] = m00;
m[1] = m01;
m[2] = m02;
m[3] = m10;
m[4] = m11;
m[5] = m12;
m[6] = m20;
m[7] = m21;
m[8] = m22;
// Compute the Singular Value Decomposition of 'm'
svdDecomposition3d.svd(m, maxSvdIterations, u, v);
// Compute rotation matrix
u.mul(v.transpose());
// Build quaternion from it
return dest.setFromNormalized(u).normalize();
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,354 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Computes the weighted average of multiple rotations represented as {@link Quaternionf} instances.
* <p>
* Instances of this class are <i>not</i> thread-safe.
*
* @author Kai Burjack
*/
public class QuaternionfInterpolator {
/**
* Performs singular value decomposition on {@link Matrix3f}.
* <p>
* This code was adapted from <a href="http://www.public.iastate.edu/~dicook/JSS/paper/code/svd.c">http://www.public.iastate.edu/</a>.
*
* @author Kai Burjack
*/
private static class SvdDecomposition3f {
private final float rv1[];
private final float w[];
private final float v[];
SvdDecomposition3f() {
this.rv1 = new float[3];
this.w = new float[3];
this.v = new float[9];
}
private float SIGN(float a, float b) {
return ((b) >= 0.0 ? Math.abs(a) : -Math.abs(a));
}
void svd(float[] a, int maxIterations, Matrix3f destU, Matrix3f destV) {
int flag, i, its, j, jj, k, l = 0, nm = 0;
float c, f, h, s, x, y, z;
float anorm = 0.0f, g = 0.0f, scale = 0.0f;
/* Householder reduction to bidiagonal form */
for (i = 0; i < 3; i++) {
/* left-hand reduction */
l = i + 1;
rv1[i] = scale * g;
g = s = scale = 0.0f;
for (k = i; k < 3; k++)
scale += Math.abs(a[k + 3 * i]);
if (scale != 0.0f) {
for (k = i; k < 3; k++) {
a[k + 3 * i] = (a[k + 3 * i] / scale);
s += (a[k + 3 * i] * a[k + 3 * i]);
}
f = a[i + 3 * i];
g = -SIGN((float) Math.sqrt(s), f);
h = f * g - s;
a[i + 3 * i] = f - g;
if (i != 3 - 1) {
for (j = l; j < 3; j++) {
for (s = 0.0f, k = i; k < 3; k++)
s += a[k + 3 * i] * a[k + 3 * j];
f = s / h;
for (k = i; k < 3; k++)
a[k + 3 * j] += f * a[k + 3 * i];
}
}
for (k = i; k < 3; k++)
a[k + 3 * i] = a[k + 3 * i] * scale;
}
w[i] = scale * g;
/* right-hand reduction */
g = s = scale = 0.0f;
if (i < 3 && i != 3 - 1) {
for (k = l; k < 3; k++)
scale += Math.abs(a[i + 3 * k]);
if (scale != 0.0f) {
for (k = l; k < 3; k++) {
a[i + 3 * k] = a[i + 3 * k] / scale;
s += a[i + 3 * k] * a[i + 3 * k];
}
f = a[i + 3 * l];
g = -SIGN((float) Math.sqrt(s), f);
h = f * g - s;
a[i + 3 * l] = f - g;
for (k = l; k < 3; k++)
rv1[k] = a[i + 3 * k] / h;
if (i != 3 - 1) {
for (j = l; j < 3; j++) {
for (s = 0.0f, k = l; k < 3; k++)
s += a[j + 3 * k] * a[i + 3 * k];
for (k = l; k < 3; k++)
a[j + 3 * k] += s * rv1[k];
}
}
for (k = l; k < 3; k++)
a[i + 3 * k] = a[i + 3 * k] * scale;
}
}
anorm = Math.max(anorm, (Math.abs(w[i]) + Math.abs(rv1[i])));
}
/* accumulate the right-hand transformation */
for (i = 3 - 1; i >= 0; i--) {
if (i < 3 - 1) {
if (g != 0.0f) {
for (j = l; j < 3; j++)
v[j + 3 * i] = (a[i + 3 * j] / a[i + 3 * l]) / g;
/* double division to avoid underflow */
for (j = l; j < 3; j++) {
for (s = 0.0f, k = l; k < 3; k++)
s += a[i + 3 * k] * v[k + 3 * j];
for (k = l; k < 3; k++)
v[k + 3 * j] += s * v[k + 3 * i];
}
}
for (j = l; j < 3; j++)
v[i + 3 * j] = v[j + 3 * i] = 0.0f;
}
v[i + 3 * i] = 1.0f;
g = rv1[i];
l = i;
}
/* accumulate the left-hand transformation */
for (i = 3 - 1; i >= 0; i--) {
l = i + 1;
g = w[i];
if (i < 3 - 1)
for (j = l; j < 3; j++)
a[i + 3 * j] = 0.0f;
if (g != 0.0f) {
g = 1.0f / g;
if (i != 3 - 1) {
for (j = l; j < 3; j++) {
for (s = 0.0f, k = l; k < 3; k++)
s += a[k + 3 * i] * a[k + 3 * j];
f = s / a[i + 3 * i] * g;
for (k = i; k < 3; k++)
a[k + 3 * j] += f * a[k + 3 * i];
}
}
for (j = i; j < 3; j++)
a[j + 3 * i] = a[j + 3 * i] * g;
} else {
for (j = i; j < 3; j++)
a[j + 3 * i] = 0.0f;
}
++a[i + 3 * i];
}
/* diagonalize the bidiagonal form */
for (k = 3 - 1; k >= 0; k--) { /* loop over singular values */
for (its = 0; its < maxIterations; its++) { /* loop over allowed iterations */
flag = 1;
for (l = k; l >= 0; l--) { /* test for splitting */
nm = l - 1;
if (Math.abs(rv1[l]) + anorm == anorm) {
flag = 0;
break;
}
if (Math.abs(w[nm]) + anorm == anorm)
break;
}
if (flag != 0) {
c = 0.0f;
s = 1.0f;
for (i = l; i <= k; i++) {
f = s * rv1[i];
if (Math.abs(f) + anorm != anorm) {
g = w[i];
h = PYTHAG(f, g);
w[i] = h;
h = 1.0f / h;
c = g * h;
s = (-f * h);
for (j = 0; j < 3; j++) {
y = a[j + 3 * nm];
z = a[j + 3 * i];
a[j + 3 * nm] = y * c + z * s;
a[j + 3 * i] = z * c - y * s;
}
}
}
}
z = w[k];
if (l == k) { /* convergence */
if (z < 0.0f) { /* make singular value nonnegative */
w[k] = -z;
for (j = 0; j < 3; j++)
v[j + 3 * k] = (-v[j + 3 * k]);
}
break;
}
if (its == maxIterations - 1) {
throw new RuntimeException("No convergence after " + maxIterations + " iterations");
}
/* shift from bottom 2 x 2 minor */
x = w[l];
nm = k - 1;
y = w[nm];
g = rv1[nm];
h = rv1[k];
f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0f * h * y);
g = PYTHAG(f, 1.0f);
f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x;
/* next QR transformation */
c = s = 1.0f;
for (j = l; j <= nm; j++) {
i = j + 1;
g = rv1[i];
y = w[i];
h = s * g;
g = c * g;
z = PYTHAG(f, h);
rv1[j] = z;
c = f / z;
s = h / z;
f = x * c + g * s;
g = g * c - x * s;
h = y * s;
y = y * c;
for (jj = 0; jj < 3; jj++) {
x = v[jj + 3 * j];
z = v[jj + 3 * i];
v[jj + 3 * j] = x * c + z * s;
v[jj + 3 * i] = z * c - x * s;
}
z = PYTHAG(f, h);
w[j] = z;
if (z != 0.0f) {
z = 1.0f / z;
c = f * z;
s = h * z;
}
f = (c * g) + (s * y);
x = (c * y) - (s * g);
for (jj = 0; jj < 3; jj++) {
y = a[jj + 3 * j];
z = a[jj + 3 * i];
a[jj + 3 * j] = y * c + z * s;
a[jj + 3 * i] = z * c - y * s;
}
}
rv1[l] = 0.0f;
rv1[k] = f;
w[k] = x;
}
}
destU.set(a);
destV.set(v);
}
private static float PYTHAG(float a, float b) {
float at = Math.abs(a), bt = Math.abs(b), ct, result;
if (at > bt) {
ct = bt / at;
result = at * (float) Math.sqrt(1.0 + ct * ct);
} else if (bt > 0.0f) {
ct = at / bt;
result = bt * (float) Math.sqrt(1.0 + ct * ct);
} else
result = 0.0f;
return (result);
}
}
private final SvdDecomposition3f svdDecomposition3f = new SvdDecomposition3f();
private final float[] m = new float[9];
private final Matrix3f u = new Matrix3f();
private final Matrix3f v = new Matrix3f();
/**
* Compute the weighted average of all of the quaternions given in <code>qs</code> using the specified interpolation factors <code>weights</code>, and store the result in <code>dest</code>.
*
* @param qs
* the quaternions to interpolate over
* @param weights
* the weights of each individual quaternion in <code>qs</code>
* @param maxSvdIterations
* the maximum number of iterations in the Singular Value Decomposition step used by this method
* @param dest
* will hold the result
* @return dest
*/
public Quaternionf computeWeightedAverage(Quaternionfc[] qs, float[] weights, int maxSvdIterations, Quaternionf dest) {
float m00 = 0.0f, m01 = 0.0f, m02 = 0.0f;
float m10 = 0.0f, m11 = 0.0f, m12 = 0.0f;
float m20 = 0.0f, m21 = 0.0f, m22 = 0.0f;
// Sum the rotation matrices of qs
for (int i = 0; i < qs.length; i++) {
Quaternionfc q = qs[i];
float dx = q.x() + q.x();
float dy = q.y() + q.y();
float dz = q.z() + q.z();
float q00 = dx * q.x();
float q11 = dy * q.y();
float q22 = dz * q.z();
float q01 = dx * q.y();
float q02 = dx * q.z();
float q03 = dx * q.w();
float q12 = dy * q.z();
float q13 = dy * q.w();
float q23 = dz * q.w();
m00 += weights[i] * (1.0f - q11 - q22);
m01 += weights[i] * (q01 + q23);
m02 += weights[i] * (q02 - q13);
m10 += weights[i] * (q01 - q23);
m11 += weights[i] * (1.0f - q22 - q00);
m12 += weights[i] * (q12 + q03);
m20 += weights[i] * (q02 + q13);
m21 += weights[i] * (q12 - q03);
m22 += weights[i] * (1.0f - q11 - q00);
}
m[0] = m00;
m[1] = m01;
m[2] = m02;
m[3] = m10;
m[4] = m11;
m[5] = m12;
m[6] = m20;
m[7] = m21;
m[8] = m22;
// Compute the Singular Value Decomposition of 'm'
svdDecomposition3f.svd(m, maxSvdIterations, u, v);
// Compute rotation matrix
u.mul(v.transpose());
// Build quaternion from it
return dest.setFromNormalized(u).normalize();
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,169 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Pseudo-random number generator.
*
* @author Kai Burjack
*/
public class Random {
/**
* Reference <a href="http://xoroshiro.di.unimi.it/xoroshiro128plus.c">http://xoroshiro.di.unimi.it/</a>
*/
private static final class Xorshiro128 {
/**
* = 0x1p-24f
*/
private static final float INT_TO_FLOAT = Float.intBitsToFloat(864026624);
/**
* Xorshiro128 state
*/
private long _s0;
private long _s1;
/**
* SplitMix64 State
*/
private long state;
Xorshiro128(long seed) {
this.state = seed;
this._s0 = nextSplitMix64();
this._s1 = nextSplitMix64();
}
private long nextSplitMix64() {
long z = state += 0x9e3779b97f4a7c15L;
z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L;
z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
return z ^ (z >>> 31);
}
/**
* Reference: <a href="https://github.com/roquendm/JGO-Grabbag/blob/master/src/roquen/math/rng/PRNG.java">https://github.com/roquendm/</a>
*
* @author roquendm
*/
final float nextFloat() {
return (nextInt() >>> 8) * INT_TO_FLOAT;
}
private int nextInt() {
long s0 = _s0;
long s1 = _s1;
long result = s0 + s1;
s1 ^= s0;
rotateLeft(s0, s1);
return (int) (result & 0xFFFFFFFF);
}
private static long rotl_JDK4(final long x, final int k) {
return (x << k) | (x >>> (64 - k));
}
private static long rotl_JDK5(final long x, final int k) {
return Long.rotateLeft(x, k);
}
private static long rotl(final long x, final int k) {
if (Runtime.HAS_Long_rotateLeft)
return rotl_JDK5(x, k);
return rotl_JDK4(x, k);
}
private void rotateLeft(long s0, long s1) {
_s0 = rotl(s0, 55) ^ s1 ^ (s1 << 14);
_s1 = rotl(s1, 36);
}
/**
* Reference: <a href="https://github.com/roquendm/JGO-Grabbag/blob/master/src/roquen/math/rng/PRNG.java">https://github.com/roquendm/</a>
*
* @author roquendm
*/
final int nextInt(int n) {
// See notes in nextInt. This is
// (on average) a better choice for
// 64-bit VMs.
long r = nextInt() >>> 1;
// sign doesn't matter here
r = (r * n) >> 31;
return (int) r;
}
}
private final Xorshiro128 rnd;
//8020463840 is from "Case File n_221: Kabukicho"
private static long seedHalf = 8020463840L;
public static long newSeed() {
// 3512401965023503517 is from L'Ecuyer, "Tables of Linear Congruential Generators of
// Different Sizes and Good Lattice Structure", 1999
long oldSeedHalf, newSeedHalf;
synchronized (Random.class) {
oldSeedHalf = seedHalf;
newSeedHalf = oldSeedHalf * 3512401965023503517L;
seedHalf = newSeedHalf;
}
return newSeedHalf;
}
/**
* Create a new instance of {@link Random} and initialize it with a random seed.
*/
public Random() {
this(newSeed() ^ System.nanoTime());
}
/**
* Create a new instance of {@link Random} and initialize it with the given <code>seed</code>.
*
* @param seed
* the seed number
*/
public Random(long seed) {
this.rnd = new Xorshiro128(seed);
}
/**
* Generate a uniformly distributed floating-point number in the half-open range [0, 1).
*
* @return a random float in the range [0..1)
*/
public float nextFloat() {
return rnd.nextFloat();
}
/**
* Generate a uniformly distributed integer in the half-open range [0, n).
*
* @param n
* the upper limit (exclusive) of the generated integer
* @return a random integer in the range [0..n)
*/
public int nextInt(int n) {
return rnd.nextInt(n);
}
}

View file

@ -0,0 +1,399 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* This is an implementation of the <a
* href="http://www.cg.cs.tu-bs.de/media/publications/fast-rayaxis-aligned-bounding-box-overlap-tests-using-ray-slopes.pdf">Fast Ray/Axis-Aligned Bounding Box
* Overlap Tests using Ray Slopes</a> paper.
* <p>
* It is an efficient implementation when testing many axis-aligned boxes against the same ray.
* <p>
* This class is thread-safe and can be used in a multithreaded environment when testing many axis-aligned boxes against the same ray concurrently.
*
* @author Kai Burjack
*/
public class RayAabIntersection {
private float originX, originY, originZ;
private float dirX, dirY, dirZ;
/* Needed for ray slope intersection method */
private float c_xy, c_yx, c_zy, c_yz, c_xz, c_zx;
private float s_xy, s_yx, s_zy, s_yz, s_xz, s_zx;
private byte classification;
/**
* Create a new {@link RayAabIntersection} without initializing a ray.
* <p>
* Before using the {@link #test(float, float, float, float, float, float) intersect()} method,
* the method {@link #set(float, float, float, float, float, float) set()} must be called in order to
* initialize the created RayAabIntersection instance with a ray.
*
* @see #set(float, float, float, float, float, float)
*/
public RayAabIntersection() {
}
/**
* Create a new {@link RayAabIntersection} and initialize it with a ray with origin <code>(originX, originY, originZ)</code>
* and direction <code>(dirX, dirY, dirZ)</code>.
* <p>
* In order to change the direction and/or origin of the ray later, use {@link #set(float, float, float, float, float, float) set()}.
*
* @see #set(float, float, float, float, float, float)
*
* @param originX
* the x coordinate of the origin
* @param originY
* the y coordinate of the origin
* @param originZ
* the z coordinate of the origin
* @param dirX
* the x coordinate of the direction
* @param dirY
* the y coordinate of the direction
* @param dirZ
* the z coordinate of the direction
*/
public RayAabIntersection(float originX, float originY, float originZ, float dirX, float dirY, float dirZ) {
set(originX, originY, originZ, dirX, dirY, dirZ);
}
/**
* Update the ray stored by this {@link RayAabIntersection} with the new origin <code>(originX, originY, originZ)</code>
* and direction <code>(dirX, dirY, dirZ)</code>.
*
* @param originX
* the x coordinate of the ray origin
* @param originY
* the y coordinate of the ray origin
* @param originZ
* the z coordinate of the ray origin
* @param dirX
* the x coordinate of the ray direction
* @param dirY
* the y coordinate of the ray direction
* @param dirZ
* the z coordinate of the ray direction
*/
public void set(float originX, float originY, float originZ, float dirX, float dirY, float dirZ) {
this.originX = originX;
this.originY = originY;
this.originZ = originZ;
this.dirX = dirX;
this.dirY = dirY;
this.dirZ = dirZ;
precomputeSlope();
}
private static int signum(float f) {
return (f == 0.0f || Float.isNaN(f)) ? 0 : ((1 - Float.floatToIntBits(f) >>> 31) << 1) - 1;
}
/**
* Precompute the values necessary for the ray slope algorithm.
*/
private void precomputeSlope() {
float invDirX = 1.0f / dirX;
float invDirY = 1.0f / dirY;
float invDirZ = 1.0f / dirZ;
s_yx = dirX * invDirY;
s_xy = dirY * invDirX;
s_zy = dirY * invDirZ;
s_yz = dirZ * invDirY;
s_xz = dirZ * invDirX;
s_zx = dirX * invDirZ;
c_xy = originY - s_xy * originX;
c_yx = originX - s_yx * originY;
c_zy = originY - s_zy * originZ;
c_yz = originZ - s_yz * originY;
c_xz = originZ - s_xz * originX; // <- original paper had a bug here. It switched originZ/originX
c_zx = originX - s_zx * originZ; // <- original paper had a bug here. It switched originZ/originX
int sgnX = signum(dirX);
int sgnY = signum(dirY);
int sgnZ = signum(dirZ);
classification = (byte) ((sgnZ+1) << 4 | (sgnY+1) << 2 | (sgnX+1));
}
/**
* Test whether the ray stored in this {@link RayAabIntersection} intersect the axis-aligned box
* given via its minimum corner <code>(minX, minY, minZ)</code> and its maximum corner <code>(maxX, maxY, maxZ)</code>.
* <p>
* This implementation uses a tableswitch to dispatch to the correct intersection method.
* <p>
* This method is thread-safe and can be used to test many axis-aligned boxes concurrently.
*
* @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
* @return <code>true</code> iff the ray intersects the given axis-aligned box; <code>false</code> otherwise
*/
public boolean test(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
// tableswitch with dense and consecutive cases (will be a simple jump based on the switch argument)
switch (classification) {
case 0: // 0b000000: // MMM
return MMM(minX, minY, minZ, maxX, maxY, maxZ);
case 1: // 0b000001: // OMM
return OMM(minX, minY, minZ, maxX, maxY, maxZ);
case 2: // 0b000010: // PMM
return PMM(minX, minY, minZ, maxX, maxY, maxZ);
case 3: // 0b000011: // not used
return false;
case 4: // 0b000100: // MOM
return MOM(minX, minY, minZ, maxX, maxY, maxZ);
case 5: // 0b000101: // OOM
return OOM(minX, minY, minZ, maxX, maxY);
case 6: // 0b000110: // POM
return POM(minX, minY, minZ, maxX, maxY, maxZ);
case 7: // 0b000111: // not used
return false;
case 8: // 0b001000: // MPM
return MPM(minX, minY, minZ, maxX, maxY, maxZ);
case 9: // 0b001001: // OPM
return OPM(minX, minY, minZ, maxX, maxY, maxZ);
case 10: // 0b001010: // PPM
return PPM(minX, minY, minZ, maxX, maxY, maxZ);
case 11: // 0b001011: // not used
case 12: // 0b001100: // not used
case 13: // 0b001101: // not used
case 14: // 0b001110: // not used
case 15: // 0b001111: // not used
return false;
case 16: // 0b010000: // MMO
return MMO(minX, minY, minZ, maxX, maxY, maxZ);
case 17: // 0b010001: // OMO
return OMO(minX, minY, minZ, maxX, maxZ);
case 18: // 0b010010: // PMO
return PMO(minX, minY, minZ, maxX, maxY, maxZ);
case 19: // 0b010011: // not used
return false;
case 20: // 0b010100: // MOO
return MOO(minX, minY, minZ, maxY, maxZ);
case 21: // 0b010101: // OOO
return false; // <- degenerate case
case 22: // 0b010110: // POO
return POO(minY, minZ, maxX, maxY, maxZ);
case 23: // 0b010111: // not used
return false;
case 24: // 0b011000: // MPO
return MPO(minX, minY, minZ, maxX, maxY, maxZ);
case 25: // 0b011001: // OPO
return OPO(minX, minZ, maxX, maxY, maxZ);
case 26: // 0b011010: // PPO
return PPO(minX, minY, minZ, maxX, maxY, maxZ);
case 27: // 0b011011: // not used
case 28: // 0b011100: // not used
case 29: // 0b011101: // not used
case 30: // 0b011110: // not used
case 31: // 0b011111: // not used
return false;
case 32: // 0b100000: // MMP
return MMP(minX, minY, minZ, maxX, maxY, maxZ);
case 33: // 0b100001: // OMP
return OMP(minX, minY, minZ, maxX, maxY, maxZ);
case 34: // 0b100010: // PMP
return PMP(minX, minY, minZ, maxX, maxY, maxZ);
case 35: // 0b100011: // not used
return false;
case 36: // 0b100100: // MOP
return MOP(minX, minY, minZ, maxX, maxY, maxZ);
case 37: // 0b100101: // OOP
return OOP(minX, minY, maxX, maxY, maxZ);
case 38: // 0b100110: // POP
return POP(minX, minY, minZ, maxX, maxY, maxZ);
case 39: // 0b100111: // not used
return false;
case 40: // 0b101000: // MPP
return MPP(minX, minY, minZ, maxX, maxY, maxZ);
case 41: // 0b101001: // OPP
return OPP(minX, minY, minZ, maxX, maxY, maxZ);
case 42: // 0b101010: // PPP
return PPP(minX, minY, minZ, maxX, maxY, maxZ);
default:
return false;
}
}
/* Intersection tests for all possible ray direction cases */
private boolean MMM(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX >= minX && originY >= minY && originZ >= minZ
&& s_xy * minX - maxY + c_xy <= 0.0f
&& s_yx * minY - maxX + c_yx <= 0.0f
&& s_zy * minZ - maxY + c_zy <= 0.0f
&& s_yz * minY - maxZ + c_yz <= 0.0f
&& s_xz * minX - maxZ + c_xz <= 0.0f
&& s_zx * minZ - maxX + c_zx <= 0.0f;
}
private boolean OMM(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX >= minX && originX <= maxX && originY >= minY && originZ >= minZ
&& s_zy * minZ - maxY + c_zy <= 0.0f
&& s_yz * minY - maxZ + c_yz <= 0.0f;
}
private boolean PMM(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX <= maxX && originY >= minY && originZ >= minZ
&& s_xy * maxX - maxY + c_xy <= 0.0f
&& s_yx * minY - minX + c_yx >= 0.0f
&& s_zy * minZ - maxY + c_zy <= 0.0f
&& s_yz * minY - maxZ + c_yz <= 0.0f
&& s_xz * maxX - maxZ + c_xz <= 0.0f
&& s_zx * minZ - minX + c_zx >= 0.0f;
}
private boolean MOM(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originY >= minY && originY <= maxY && originX >= minX && originZ >= minZ
&& s_xz * minX - maxZ + c_xz <= 0.0f
&& s_zx * minZ - maxX + c_zx <= 0.0f;
}
private boolean OOM(float minX, float minY, float minZ, float maxX, float maxY) {
return originZ >= minZ && originX >= minX && originX <= maxX && originY >= minY && originY <= maxY;
}
private boolean POM(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originY >= minY && originY <= maxY && originX <= maxX && originZ >= minZ
&& s_xz * maxX - maxZ + c_xz <= 0.0f
&& s_zx * minZ - minX + c_zx >= 0.0f;
}
private boolean MPM(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX >= minX && originY <= maxY && originZ >= minZ
&& s_xy * minX - minY + c_xy >= 0.0f
&& s_yx * maxY - maxX + c_yx <= 0.0f
&& s_zy * minZ - minY + c_zy >= 0.0f
&& s_yz * maxY - maxZ + c_yz <= 0.0f
&& s_xz * minX - maxZ + c_xz <= 0.0f
&& s_zx * minZ - maxX + c_zx <= 0.0f;
}
private boolean OPM(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX >= minX && originX <= maxX && originY <= maxY && originZ >= minZ
&& s_zy * minZ - minY + c_zy >= 0.0f
&& s_yz * maxY - maxZ + c_yz <= 0.0f;
}
private boolean PPM(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX <= maxX && originY <= maxY && originZ >= minZ
&& s_xy * maxX - minY + c_xy >= 0.0f
&& s_yx * maxY - minX + c_yx >= 0.0f
&& s_zy * minZ - minY + c_zy >= 0.0f
&& s_yz * maxY - maxZ + c_yz <= 0.0f
&& s_xz * maxX - maxZ + c_xz <= 0.0f
&& s_zx * minZ - minX + c_zx >= 0.0f;
}
private boolean MMO(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originZ >= minZ && originZ <= maxZ && originX >= minX && originY >= minY
&& s_xy * minX - maxY + c_xy <= 0.0f
&& s_yx * minY - maxX + c_yx <= 0.0f;
}
private boolean OMO(float minX, float minY, float minZ, float maxX, float maxZ) {
return originY >= minY && originX >= minX && originX <= maxX && originZ >= minZ && originZ <= maxZ;
}
private boolean PMO(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originZ >= minZ && originZ <= maxZ && originX <= maxX && originY >= minY
&& s_xy * maxX - maxY + c_xy <= 0.0f
&& s_yx * minY - minX + c_yx >= 0.0f;
}
private boolean MOO(float minX, float minY, float minZ, float maxY, float maxZ) {
return originX >= minX && originY >= minY && originY <= maxY && originZ >= minZ && originZ <= maxZ;
}
private boolean POO(float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX <= maxX && originY >= minY && originY <= maxY && originZ >= minZ && originZ <= maxZ;
}
private boolean MPO(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originZ >= minZ && originZ <= maxZ && originX >= minX && originY <= maxY
&& s_xy * minX - minY + c_xy >= 0.0f
&& s_yx * maxY - maxX + c_yx <= 0.0f;
}
private boolean OPO(float minX, float minZ, float maxX, float maxY, float maxZ) {
return originY <= maxY && originX >= minX && originX <= maxX && originZ >= minZ && originZ <= maxZ;
}
private boolean PPO(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originZ >= minZ && originZ <= maxZ && originX <= maxX && originY <= maxY
&& s_xy * maxX - minY + c_xy >= 0.0f
&& s_yx * maxY - minX + c_yx >= 0.0f;
}
private boolean MMP(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX >= minX && originY >= minY && originZ <= maxZ
&& s_xy * minX - maxY + c_xy <= 0.0f
&& s_yx * minY - maxX + c_yx <= 0.0f
&& s_zy * maxZ - maxY + c_zy <= 0.0f
&& s_yz * minY - minZ + c_yz >= 0.0f
&& s_xz * minX - minZ + c_xz >= 0.0f
&& s_zx * maxZ - maxX + c_zx <= 0.0f;
}
private boolean OMP(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX >= minX && originX <= maxX && originY >= minY && originZ <= maxZ
&& s_zy * maxZ - maxY + c_zy <= 0.0f
&& s_yz * minY - minZ + c_yz >= 0.0f;
}
private boolean PMP(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX <= maxX && originY >= minY && originZ <= maxZ
&& s_xy * maxX - maxY + c_xy <= 0.0f
&& s_yx * minY - minX + c_yx >= 0.0f
&& s_zy * maxZ - maxY + c_zy <= 0.0f
&& s_yz * minY - minZ + c_yz >= 0.0f
&& s_xz * maxX - minZ + c_xz >= 0.0f
&& s_zx * maxZ - minX + c_zx >= 0.0f;
}
private boolean MOP(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originY >= minY && originY <= maxY && originX >= minX && originZ <= maxZ
&& s_xz * minX - minZ + c_xz >= 0.0f
&& s_zx * maxZ - maxX + c_zx <= 0.0f;
}
private boolean OOP(float minX, float minY, float maxX, float maxY, float maxZ) {
return originZ <= maxZ && originX >= minX && originX <= maxX && originY >= minY && originY <= maxY;
}
private boolean POP(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originY >= minY && originY <= maxY && originX <= maxX && originZ <= maxZ
&& s_xz * maxX - minZ + c_xz >= 0.0f
&& s_zx * maxZ - minX + c_zx <= 0.0f;
}
private boolean MPP(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX >= minX && originY <= maxY && originZ <= maxZ
&& s_xy * minX - minY + c_xy >= 0.0f
&& s_yx * maxY - maxX + c_yx <= 0.0f
&& s_zy * maxZ - minY + c_zy >= 0.0f
&& s_yz * maxY - minZ + c_yz >= 0.0f
&& s_xz * minX - minZ + c_xz >= 0.0f
&& s_zx * maxZ - maxX + c_zx <= 0.0f;
}
private boolean OPP(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX >= minX && originX <= maxX && originY <= maxY && originZ <= maxZ
&& s_zy * maxZ - minY + c_zy <= 0.0f
&& s_yz * maxY - minZ + c_yz <= 0.0f;
}
private boolean PPP(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return originX <= maxX && originY <= maxY && originZ <= maxZ
&& s_xy * maxX - minY + c_xy >= 0.0f
&& s_yx * maxY - minX + c_yx >= 0.0f
&& s_zy * maxZ - minY + c_zy >= 0.0f
&& s_yz * maxY - minZ + c_yz >= 0.0f
&& s_xz * maxX - minZ + c_xz >= 0.0f
&& s_zx * maxZ - minX + c_zx >= 0.0f;
}
}

View file

@ -0,0 +1,60 @@
/*
* The MIT License
*
* Copyright (c) 2020-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* Rounding modes.
*
* @author Kai Burjack
*/
public class RoundingMode {
private RoundingMode() {}
/**
* Discards the fractional part.
*/
public static final int TRUNCATE = 0;
/**
* Round towards positive infinity.
*/
public static final int CEILING = 1;
/**
* Round towards negative infinity.
*/
public static final int FLOOR = 2;
/**
* Round towards the nearest neighbor. If both neighbors are equidistant, round
* towards the even neighbor.
*/
public static final int HALF_EVEN = 3;
/**
* Round towards the nearest neighbor. If both neighbors are equidistant, round
* down.
*/
public static final int HALF_DOWN = 4;
/**
* Round towards the nearest neighbor. If both neighbors are equidistant, round
* up.
*/
public static final int HALF_UP = 5;
}

View file

@ -0,0 +1,148 @@
/*
* The MIT License
*
* Copyright (c) 2017-2021 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 com.jozufozu.flywheel.repack.joml;
import java.text.NumberFormat;
/**
* Internal class to detect features of the runtime.
*
* @author Kai Burjack
*/
public final class Runtime {
public static final boolean HAS_floatToRawIntBits = hasFloatToRawIntBits();
public static final boolean HAS_doubleToRawLongBits = hasDoubleToRawLongBits();
public static final boolean HAS_Long_rotateLeft = hasLongRotateLeft();
public static final boolean HAS_Math_fma = Options.USE_MATH_FMA && hasMathFma();
private static boolean hasMathFma() {
try {
java.lang.Math.class.getDeclaredMethod("fma", new Class[] { float.class, float.class, float.class });
return true;
} catch (NoSuchMethodException e) {
return false;
}
}
private Runtime() {
}
private static boolean hasFloatToRawIntBits() {
try {
Float.class.getDeclaredMethod("floatToRawIntBits", new Class[] { float.class });
return true;
} catch (NoSuchMethodException e) {
return false;
}
}
private static boolean hasDoubleToRawLongBits() {
try {
Double.class.getDeclaredMethod("doubleToRawLongBits", new Class[] { double.class });
return true;
} catch (NoSuchMethodException e) {
return false;
}
}
private static boolean hasLongRotateLeft() {
try {
Long.class.getDeclaredMethod("rotateLeft", new Class[] { long.class, int.class });
return true;
} catch (NoSuchMethodException e) {
return false;
}
}
public static int floatToIntBits(float flt) {
if (HAS_floatToRawIntBits)
return floatToIntBits1_3(flt);
return floatToIntBits1_2(flt);
}
private static int floatToIntBits1_3(float flt) {
return Float.floatToRawIntBits(flt);
}
private static int floatToIntBits1_2(float flt) {
return Float.floatToIntBits(flt);
}
public static long doubleToLongBits(double dbl) {
if (HAS_doubleToRawLongBits)
return doubleToLongBits1_3(dbl);
return doubleToLongBits1_2(dbl);
}
private static long doubleToLongBits1_3(double dbl) {
return Double.doubleToRawLongBits(dbl);
}
private static long doubleToLongBits1_2(double dbl) {
return Double.doubleToLongBits(dbl);
}
public static String formatNumbers(String str) {
StringBuffer res = new StringBuffer();
int eIndex = Integer.MIN_VALUE;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c == 'E') {
eIndex = i;
} else if (c == ' ' && eIndex == i - 1) {
// workaround Java 1.4 DecimalFormat bug
res.append('+');
continue;
} else if (Character.isDigit(c) && eIndex == i - 1) {
res.append('+');
}
res.append(c);
}
return res.toString();
}
public static String format(double number, NumberFormat format) {
if (Double.isNaN(number)) {
return padLeft(format, " NaN");
} else if (Double.isInfinite(number)) {
return padLeft(format, number > 0.0 ? " +Inf" : " -Inf");
}
return format.format(number);
}
private static String padLeft(NumberFormat format, String str) {
int len = format.format(0.0).length();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < len - str.length() + 1; i++) {
sb.append(" ");
}
return sb.append(str).toString();
}
public static boolean equals(float a, float b, float delta) {
return Float.floatToIntBits(a) == Float.floatToIntBits(b) || Math.abs(a - b) <= delta;
}
public static boolean equals(double a, double b, double delta) {
return Double.doubleToLongBits(a) == Double.doubleToLongBits(b) || Math.abs(a - b) <= delta;
}
}

View file

@ -0,0 +1,485 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
/**
* A simplex noise algorithm for 2D, 3D and 4D input.
* <p>
* It was originally authored by Stefan Gustavson.
* <p>
* The original implementation can be found here: <a
* href="http://staffwww.itn.liu.se/~stegu/simplexnoise/SimplexNoise.java">http://http://staffwww.itn.liu.se/</a>.
*/
public class SimplexNoise {
private static class Vector3b {
byte x, y, z;
Vector3b(int x, int y, int z) {
super();
this.x = (byte) x;
this.y = (byte) y;
this.z = (byte) z;
}
}
private static class Vector4b {
byte x, y, z, w;
Vector4b(int x, int y, int z, int w) {
super();
this.x = (byte) x;
this.y = (byte) y;
this.z = (byte) z;
this.w = (byte) w;
}
}
// Kai Burjack:
// Use a three-component vector here to save memory. (instead of using 4-component 'Grad' class)
// And as the original author mentioned on the 'Grad' class, using a class to store the gradient components
// is indeed faster compared to using a simple int[] array...
private static final Vector3b[] grad3 = { new Vector3b(1, 1, 0), new Vector3b(-1, 1, 0), new Vector3b(1, -1, 0), new Vector3b(-1, -1, 0),
new Vector3b(1, 0, 1), new Vector3b(-1, 0, 1), new Vector3b(1, 0, -1), new Vector3b(-1, 0, -1), new Vector3b(0, 1, 1), new Vector3b(0, -1, 1),
new Vector3b(0, 1, -1), new Vector3b(0, -1, -1) };
// Kai Burjack:
// As the original author mentioned on the 'Grad' class, using a class to store the gradient components
// is indeed faster compared to using a simple int[] array...
private static final Vector4b[] grad4 = { new Vector4b(0, 1, 1, 1), new Vector4b(0, 1, 1, -1), new Vector4b(0, 1, -1, 1), new Vector4b(0, 1, -1, -1),
new Vector4b(0, -1, 1, 1), new Vector4b(0, -1, 1, -1), new Vector4b(0, -1, -1, 1), new Vector4b(0, -1, -1, -1), new Vector4b(1, 0, 1, 1),
new Vector4b(1, 0, 1, -1), new Vector4b(1, 0, -1, 1), new Vector4b(1, 0, -1, -1), new Vector4b(-1, 0, 1, 1), new Vector4b(-1, 0, 1, -1),
new Vector4b(-1, 0, -1, 1), new Vector4b(-1, 0, -1, -1), new Vector4b(1, 1, 0, 1), new Vector4b(1, 1, 0, -1), new Vector4b(1, -1, 0, 1),
new Vector4b(1, -1, 0, -1), new Vector4b(-1, 1, 0, 1), new Vector4b(-1, 1, 0, -1), new Vector4b(-1, -1, 0, 1), new Vector4b(-1, -1, 0, -1),
new Vector4b(1, 1, 1, 0), new Vector4b(1, 1, -1, 0), new Vector4b(1, -1, 1, 0), new Vector4b(1, -1, -1, 0), new Vector4b(-1, 1, 1, 0),
new Vector4b(-1, 1, -1, 0), new Vector4b(-1, -1, 1, 0), new Vector4b(-1, -1, -1, 0) };
// Kai Burjack:
// Use a byte[] instead of a short[] to save memory
private static final byte[] p = { -105, -96, -119, 91, 90, 15, -125, 13, -55, 95, 96, 53, -62, -23, 7, -31, -116, 36, 103, 30, 69, -114, 8, 99, 37, -16,
21, 10, 23, -66, 6, -108, -9, 120, -22, 75, 0, 26, -59, 62, 94, -4, -37, -53, 117, 35, 11, 32, 57, -79, 33, 88, -19, -107, 56, 87, -82, 20, 125,
-120, -85, -88, 68, -81, 74, -91, 71, -122, -117, 48, 27, -90, 77, -110, -98, -25, 83, 111, -27, 122, 60, -45, -123, -26, -36, 105, 92, 41, 55, 46,
-11, 40, -12, 102, -113, 54, 65, 25, 63, -95, 1, -40, 80, 73, -47, 76, -124, -69, -48, 89, 18, -87, -56, -60, -121, -126, 116, -68, -97, 86, -92,
100, 109, -58, -83, -70, 3, 64, 52, -39, -30, -6, 124, 123, 5, -54, 38, -109, 118, 126, -1, 82, 85, -44, -49, -50, 59, -29, 47, 16, 58, 17, -74,
-67, 28, 42, -33, -73, -86, -43, 119, -8, -104, 2, 44, -102, -93, 70, -35, -103, 101, -101, -89, 43, -84, 9, -127, 22, 39, -3, 19, 98, 108, 110,
79, 113, -32, -24, -78, -71, 112, 104, -38, -10, 97, -28, -5, 34, -14, -63, -18, -46, -112, 12, -65, -77, -94, -15, 81, 51, -111, -21, -7, 14, -17,
107, 49, -64, -42, 31, -75, -57, 106, -99, -72, 84, -52, -80, 115, 121, 50, 45, 127, 4, -106, -2, -118, -20, -51, 93, -34, 114, 67, 29, 24, 72,
-13, -115, -128, -61, 78, 66, -41, 61, -100, -76 };
// To remove the need for index wrapping, float the permutation table length
private static final byte[] perm = new byte[512];
private static final byte[] permMod12 = new byte[512];
static {
for (int i = 0; i < 512; i++) {
perm[i] = p[i & 255];
permMod12[i] = (byte) ((perm[i]&0xFF) % 12);
}
}
// Skewing and unskewing factors for 2, 3, and 4 dimensions
private static final float F2 = 0.3660254037844386f; // <- (float) (0.5f * (Math.sqrt(3.0f) - 1.0f));
private static final float G2 = 0.21132486540518713f; // <- (float) ((3.0f - Math.sqrt(3.0f)) / 6.0f);
private static final float F3 = 1.0f / 3.0f;
private static final float G3 = 1.0f / 6.0f;
private static final float F4 = 0.30901699437494745f; // <- (float) ((Math.sqrt(5.0f) - 1.0f) / 4.0f);
private static final float G4 = 0.1381966011250105f; // <- (float) ((5.0f - Math.sqrt(5.0f)) / 20.0f);
// This method is a *lot* faster than using (int)Math.floor(x)
private static int fastfloor(float x) {
int xi = (int) x;
return x < xi ? xi - 1 : xi;
}
private static float dot(Vector3b g, float x, float y) {
return g.x * x + g.y * y;
}
private static float dot(Vector3b g, float x, float y, float z) {
return g.x * x + g.y * y + g.z * z;
}
private static float dot(Vector4b g, float x, float y, float z, float w) {
return g.x * x + g.y * y + g.z * z + g.w * w;
}
/**
* Compute 2D simplex noise for the given input vector <code>(x, y)</code>.
* <p>
* The result is in the range <code>[-1..+1]</code>.
*
* @param x
* the x coordinate
* @param y
* the y coordinate
* @return the noise value (within <code>[-1..+1]</code>)
*/
public static float noise(float x, float y) {
float n0, n1, n2; // Noise contributions from the three corners
// Skew the input space to determine which simplex cell we're in
float s = (x + y) * F2; // Hairy factor for 2D
int i = fastfloor(x + s);
int j = fastfloor(y + s);
float t = (i + j) * G2;
float X0 = i - t; // Unskew the cell origin back to (x,y) space
float Y0 = j - t;
float x0 = x - X0; // The x,y distances from the cell origin
float y0 = y - Y0;
// For the 2D case, the simplex shape is an equilateral triangle.
// Determine which simplex we are in.
int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
if (x0 > y0) {
i1 = 1;
j1 = 0;
} // lower triangle, XY order: (0,0)->(1,0)->(1,1)
else {
i1 = 0;
j1 = 1;
} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
// A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
// a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
// c = (3-sqrt(3))/6
float x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
float y1 = y0 - j1 + G2;
float x2 = x0 - 1.0f + 2.0f * G2; // Offsets for last corner in (x,y) unskewed coords
float y2 = y0 - 1.0f + 2.0f * G2;
// Work out the hashed gradient indices of the three simplex corners
int ii = i & 255;
int jj = j & 255;
int gi0 = permMod12[ii + perm[jj]&0xFF]&0xFF;
int gi1 = permMod12[ii + i1 + perm[jj + j1]&0xFF]&0xFF;
int gi2 = permMod12[ii + 1 + perm[jj + 1]&0xFF]&0xFF;
// Calculate the contribution from the three corners
float t0 = 0.5f - x0 * x0 - y0 * y0;
if (t0 < 0.0f)
n0 = 0.0f;
else {
t0 *= t0;
n0 = t0 * t0 * dot(grad3[gi0], x0, y0); // (x,y) of grad3 used for 2D gradient
}
float t1 = 0.5f - x1 * x1 - y1 * y1;
if (t1 < 0.0f)
n1 = 0.0f;
else {
t1 *= t1;
n1 = t1 * t1 * dot(grad3[gi1], x1, y1);
}
float t2 = 0.5f - x2 * x2 - y2 * y2;
if (t2 < 0.0f)
n2 = 0.0f;
else {
t2 *= t2;
n2 = t2 * t2 * dot(grad3[gi2], x2, y2);
}
// Add contributions from each corner to get the final noise value.
// The result is scaled to return values in the interval [-1,1].
return 70.0f * (n0 + n1 + n2);
}
/**
* Compute 3D simplex noise for the given input vector <code>(x, y, z)</code>.
* <p>
* The result is in the range <code>[-1..+1]</code>.
*
* @param x
* the x coordinate
* @param y
* the y coordinate
* @param z
* the z coordinate
* @return the noise value (within <code>[-1..+1]</code>)
*/
public static float noise(float x, float y, float z) {
float n0, n1, n2, n3; // Noise contributions from the four corners
// Skew the input space to determine which simplex cell we're in
float s = (x + y + z) * F3; // Very nice and simple skew factor for 3D
int i = fastfloor(x + s);
int j = fastfloor(y + s);
int k = fastfloor(z + s);
float t = (i + j + k) * G3;
float X0 = i - t; // Unskew the cell origin back to (x,y,z) space
float Y0 = j - t;
float Z0 = k - t;
float x0 = x - X0; // The x,y,z distances from the cell origin
float y0 = y - Y0;
float z0 = z - Z0;
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
// Determine which simplex we are in.
int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
if (x0 >= y0) {
if (y0 >= z0) {
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
} // X Y Z order
else if (x0 >= z0) {
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 0;
k2 = 1;
} // X Z Y order
else {
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 0;
k2 = 1;
} // Z X Y order
} else { // x0<y0
if (y0 < z0) {
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 0;
j2 = 1;
k2 = 1;
} // Z Y X order
else if (x0 < z0) {
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 0;
j2 = 1;
k2 = 1;
} // Y Z X order
else {
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
} // Y X Z order
}
// A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
// a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
// a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
// c = 1/6.
float x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
float y1 = y0 - j1 + G3;
float z1 = z0 - k1 + G3;
float x2 = x0 - i2 + 2.0f * G3; // Offsets for third corner in (x,y,z) coords
float y2 = y0 - j2 + 2.0f * G3;
float z2 = z0 - k2 + 2.0f * G3;
float x3 = x0 - 1.0f + 3.0f * G3; // Offsets for last corner in (x,y,z) coords
float y3 = y0 - 1.0f + 3.0f * G3;
float z3 = z0 - 1.0f + 3.0f * G3;
// Work out the hashed gradient indices of the four simplex corners
int ii = i & 255;
int jj = j & 255;
int kk = k & 255;
int gi0 = permMod12[ii + perm[jj + perm[kk]&0xFF]&0xFF]&0xFF;
int gi1 = permMod12[ii + i1 + perm[jj + j1 + perm[kk + k1]&0xFF]&0xFF]&0xFF;
int gi2 = permMod12[ii + i2 + perm[jj + j2 + perm[kk + k2]&0xFF]&0xFF]&0xFF;
int gi3 = permMod12[ii + 1 + perm[jj + 1 + perm[kk + 1]&0xFF]&0xFF]&0xFF;
// Calculate the contribution from the four corners
float t0 = 0.6f - x0 * x0 - y0 * y0 - z0 * z0;
if (t0 < 0.0f)
n0 = 0.0f;
else {
t0 *= t0;
n0 = t0 * t0 * dot(grad3[gi0], x0, y0, z0);
}
float t1 = 0.6f - x1 * x1 - y1 * y1 - z1 * z1;
if (t1 < 0.0f)
n1 = 0.0f;
else {
t1 *= t1;
n1 = t1 * t1 * dot(grad3[gi1], x1, y1, z1);
}
float t2 = 0.6f - x2 * x2 - y2 * y2 - z2 * z2;
if (t2 < 0.0f)
n2 = 0.0f;
else {
t2 *= t2;
n2 = t2 * t2 * dot(grad3[gi2], x2, y2, z2);
}
float t3 = 0.6f - x3 * x3 - y3 * y3 - z3 * z3;
if (t3 < 0.0f)
n3 = 0.0f;
else {
t3 *= t3;
n3 = t3 * t3 * dot(grad3[gi3], x3, y3, z3);
}
// Add contributions from each corner to get the final noise value.
// The result is scaled to stay just inside [-1,1]
return 32.0f * (n0 + n1 + n2 + n3);
}
/**
* Compute 4D simplex noise for the given input vector <code>(x, y, z, w)</code>.
* <p>
* The result is in the range <code>[-1..+1]</code>.
*
* @param x
* the x coordinate
* @param y
* the y coordinate
* @param z
* the z coordinate
* @param w
* the w coordinate
* @return the noise value (within <code>[-1..+1]</code>)
*/
public static float noise(float x, float y, float z, float w) {
float n0, n1, n2, n3, n4; // Noise contributions from the five corners
// Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
float s = (x + y + z + w) * F4; // Factor for 4D skewing
int i = fastfloor(x + s);
int j = fastfloor(y + s);
int k = fastfloor(z + s);
int l = fastfloor(w + s);
float t = (i + j + k + l) * G4; // Factor for 4D unskewing
float X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
float Y0 = j - t;
float Z0 = k - t;
float W0 = l - t;
float x0 = x - X0; // The x,y,z,w distances from the cell origin
float y0 = y - Y0;
float z0 = z - Z0;
float w0 = w - W0;
// For the 4D case, the simplex is a 4D shape I won't even try to describe.
// To find out which of the 24 possible simplices we're in, we need to
// determine the magnitude ordering of x0, y0, z0 and w0.
// Six pair-wise comparisons are performed between each possible pair
// of the four coordinates, and the results are used to rank the numbers.
int rankx = 0;
int ranky = 0;
int rankz = 0;
int rankw = 0;
if (x0 > y0)
rankx++;
else
ranky++;
if (x0 > z0)
rankx++;
else
rankz++;
if (x0 > w0)
rankx++;
else
rankw++;
if (y0 > z0)
ranky++;
else
rankz++;
if (y0 > w0)
ranky++;
else
rankw++;
if (z0 > w0)
rankz++;
else
rankw++;
int i1, j1, k1, l1; // The integer offsets for the second simplex corner
int i2, j2, k2, l2; // The integer offsets for the third simplex corner
int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
// simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
// Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
// impossible. Only the 24 indices which have non-zero entries make any sense.
// We use a thresholding to set the coordinates in turn from the largest magnitude.
// Rank 3 denotes the largest coordinate.
i1 = rankx >= 3 ? 1 : 0;
j1 = ranky >= 3 ? 1 : 0;
k1 = rankz >= 3 ? 1 : 0;
l1 = rankw >= 3 ? 1 : 0;
// Rank 2 denotes the second largest coordinate.
i2 = rankx >= 2 ? 1 : 0;
j2 = ranky >= 2 ? 1 : 0;
k2 = rankz >= 2 ? 1 : 0;
l2 = rankw >= 2 ? 1 : 0;
// Rank 1 denotes the second smallest coordinate.
i3 = rankx >= 1 ? 1 : 0;
j3 = ranky >= 1 ? 1 : 0;
k3 = rankz >= 1 ? 1 : 0;
l3 = rankw >= 1 ? 1 : 0;
// The fifth corner has all coordinate offsets = 1, so no need to compute that.
float x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
float y1 = y0 - j1 + G4;
float z1 = z0 - k1 + G4;
float w1 = w0 - l1 + G4;
float x2 = x0 - i2 + 2.0f * G4; // Offsets for third corner in (x,y,z,w) coords
float y2 = y0 - j2 + 2.0f * G4;
float z2 = z0 - k2 + 2.0f * G4;
float w2 = w0 - l2 + 2.0f * G4;
float x3 = x0 - i3 + 3.0f * G4; // Offsets for fourth corner in (x,y,z,w) coords
float y3 = y0 - j3 + 3.0f * G4;
float z3 = z0 - k3 + 3.0f * G4;
float w3 = w0 - l3 + 3.0f * G4;
float x4 = x0 - 1.0f + 4.0f * G4; // Offsets for last corner in (x,y,z,w) coords
float y4 = y0 - 1.0f + 4.0f * G4;
float z4 = z0 - 1.0f + 4.0f * G4;
float w4 = w0 - 1.0f + 4.0f * G4;
// Work out the hashed gradient indices of the five simplex corners
int ii = i & 255;
int jj = j & 255;
int kk = k & 255;
int ll = l & 255;
int gi0 = (perm[ii + perm[jj + perm[kk + perm[ll]&0xFF]&0xFF]&0xFF]&0xFF) % 32;
int gi1 = (perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]&0xFF]&0xFF]&0xFF]&0xFF) % 32;
int gi2 = (perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]&0xFF]&0xFF]&0xFF]&0xFF) % 32;
int gi3 = (perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]&0xFF]&0xFF]&0xFF]&0xFF) % 32;
int gi4 = (perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]&0xFF]&0xFF]&0xFF]&0xFF) % 32;
// Calculate the contribution from the five corners
float t0 = 0.6f - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
if (t0 < 0.0f)
n0 = 0.0f;
else {
t0 *= t0;
n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0);
}
float t1 = 0.6f - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
if (t1 < 0.0f)
n1 = 0.0f;
else {
t1 *= t1;
n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1);
}
float t2 = 0.6f - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
if (t2 < 0.0f)
n2 = 0.0f;
else {
t2 *= t2;
n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2);
}
float t3 = 0.6f - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
if (t3 < 0.0f)
n3 = 0.0f;
else {
t3 *= t3;
n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3);
}
float t4 = 0.6f - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
if (t4 < 0.0f)
n4 = 0.0f;
else {
t4 *= t4;
n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4);
}
// Sum up and scale the result to cover the range [-1,1]
return 27.0f * (n0 + n1 + n2 + n3 + n4);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,670 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.util.*;
/**
* Interface to a read-only view of a 2-dimensional vector of double-precision floats.
*
* @author Kai Burjack
*/
public interface Vector2dc {
/**
* @return the value of the x component
*/
double x();
/**
* @return the value of the y component
*/
double y();
/**
* Store this vector into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which
* the vector is stored, use {@link #get(int, ByteBuffer)}, taking
* the absolute position as parameter.
*
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
* @see #get(int, ByteBuffer)
*/
ByteBuffer get(ByteBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
*/
ByteBuffer get(int index, ByteBuffer buffer);
/**
* Store this vector into the supplied {@link DoubleBuffer} at the current
* buffer {@link DoubleBuffer#position() position}.
* <p>
* This method will not increment the position of the given DoubleBuffer.
* <p>
* In order to specify the offset into the DoubleBuffer at which
* the vector is stored, use {@link #get(int, DoubleBuffer)}, taking
* the absolute position as parameter.
*
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
* @see #get(int, DoubleBuffer)
*/
DoubleBuffer get(DoubleBuffer buffer);
/**
* Store this vector into the supplied {@link DoubleBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given DoubleBuffer.
*
* @param index
* the absolute position into the DoubleBuffer
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
*/
DoubleBuffer get(int index, DoubleBuffer buffer);
/**
* Store this vector at the given off-heap memory address.
* <p>
* This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`.
* <p>
* <em>This method is unsafe as it can result in a crash of the JVM process when the specified address range does not belong to this process.</em>
*
* @param address
* the off-heap address where to store this vector
* @return this
*/
Vector2dc getToAddress(long address);
/**
* Subtract <code>(x, y)</code> from this vector and store the result in <code>dest</code>.
*
* @param x
* the x component to subtract
* @param y
* the y component to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector2d sub(double x, double y, Vector2d dest);
/**
* Subtract <code>v</code> from <code>this</code> vector and store the result in <code>dest</code>.
*
* @param v
* the vector to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector2d sub(Vector2dc v, Vector2d dest);
/**
* Subtract <code>v</code> from <code>this</code> vector and store the result in <code>dest</code>.
*
* @param v
* the vector to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector2d sub(Vector2fc v, Vector2d dest);
/**
* Multiply the components of this vector by the given scalar and store the result in <code>dest</code>.
*
* @param scalar
* the value to multiply this vector's components by
* @param dest
* will hold the result
* @return dest
*/
Vector2d mul(double scalar, Vector2d dest);
/**
* Multiply the components of this Vector2d by the given scalar values and store the result in <code>dest</code>.
*
* @param x
* the x component to multiply this vector by
* @param y
* the y component to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2d mul(double x, double y, Vector2d dest);
/**
* Multiply this Vector2d component-wise by another Vector2d and store the result in <code>dest</code>.
*
* @param v
* the vector to multiply by
* @param dest
* will hold the result
* @return dest
*/
Vector2d mul(Vector2dc v, Vector2d dest);
/**
* Divide this Vector2d by the given scalar value and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to divide this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2d div(double scalar, Vector2d dest);
/**
* Divide the components of this Vector3f by the given scalar values and store the result in <code>dest</code>.
*
* @param x
* the x component to divide this vector by
* @param y
* the y component to divide this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2d div(double x, double y, Vector2d dest);
/**
* Divide this Vector2d component-wise by another Vector2f and store the result in <code>dest</code>.
*
* @param v
* the vector to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector2d div(Vector2fc v, Vector2d dest);
/**
* Divide this by <code>v</code> component-wise and store the result into <code>dest</code>.
*
* @param v
* the vector to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector2d div(Vector2dc v, Vector2d dest);
/**
* Multiply the given matrix <code>mat</code> with <code>this</code> and store the
* result in <code>dest</code>.
*
* @param mat
* the matrix to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2d mul(Matrix2dc mat, Vector2d dest);
/**
* Multiply the given matrix <code>mat</code> with <code>this</code> and store the
* result in <code>dest</code>.
*
* @param mat
* the matrix to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2d mul(Matrix2fc mat, Vector2d dest);
/**
* Multiply the transpose of the given matrix with this Vector2f and store the result in <code>dest</code>.
*
* @param mat
* the matrix
* @param dest
* will hold the result
* @return dest
*/
Vector2d mulTranspose(Matrix2dc mat, Vector2d dest);
/**
* Multiply the transpose of the given matrix with this Vector2f and store the result in <code>dest</code>.
*
* @param mat
* the matrix
* @param dest
* will hold the result
* @return dest
*/
Vector2d mulTranspose(Matrix2fc mat, Vector2d dest);
/**
* Multiply the given 3x2 matrix <code>mat</code> with <code>this</code> and store the
* result in <code>dest</code>.
* <p>
* This method assumes the <code>z</code> component of <code>this</code> to be <code>1.0</code>.
*
* @param mat
* the matrix to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2d mulPosition(Matrix3x2dc mat, Vector2d dest);
/**
* Multiply the given 3x2 matrix <code>mat</code> with <code>this</code> and store the
* result in <code>dest</code>.
* <p>
* This method assumes the <code>z</code> component of <code>this</code> to be <code>0.0</code>.
*
* @param mat
* the matrix to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2d mulDirection(Matrix3x2dc mat, Vector2d dest);
/**
* Return the dot product of this vector and <code>v</code>.
*
* @param v
* the other vector
* @return the dot product
*/
double dot(Vector2dc v);
/**
* Return the angle between this vector and the supplied vector.
*
* @param v
* the other vector
* @return the angle, in radians
*/
double angle(Vector2dc v);
/**
* Return the length squared of this vector.
*
* @return the length squared
*/
double lengthSquared();
/**
* Return the length of this vector.
*
* @return the length
*/
double length();
/**
* Return the distance between this and <code>v</code>.
*
* @param v
* the other vector
* @return the distance
*/
double distance(Vector2dc v);
/**
* Return the distance squared between this and <code>v</code>.
*
* @param v
* the other vector
* @return the distance squared
*/
double distanceSquared(Vector2dc v);
/**
* Return the distance between this and <code>v</code>.
*
* @param v
* the other vector
* @return the distance
*/
double distance(Vector2fc v);
/**
* Return the distance squared between this and <code>v</code>.
*
* @param v
* the other vector
* @return the distance squared
*/
double distanceSquared(Vector2fc v);
/**
* Return the distance between <code>this</code> vector and <code>(x, y)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @return the euclidean distance
*/
double distance(double x, double y);
/**
* Return the distance squared between <code>this</code> vector and <code>(x, y)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @return the euclidean distance squared
*/
double distanceSquared(double x, double y);
/**
* Normalize this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2d normalize(Vector2d dest);
/**
* Scale this vector to have the given length and store the result in <code>dest</code>.
*
* @param length
* the desired length
* @param dest
* will hold the result
* @return dest
*/
Vector2d normalize(double length, Vector2d dest);
/**
* Add <code>(x, y)</code> to this vector and store the result in <code>dest</code>.
*
* @param x
* the x component to add
* @param y
* the y component to add
* @param dest
* will hold the result
* @return dest
*/
Vector2d add(double x, double y, Vector2d dest);
/**
* Add <code>v</code> to this vector and store the result in <code>dest</code>.
*
* @param v
* the vector to add
* @param dest
* will hold the result
* @return dest
*/
Vector2d add(Vector2dc v, Vector2d dest);
/**
* Add <code>v</code> to this vector and store the result in <code>dest</code>.
*
* @param v
* the vector to add
* @param dest
* will hold the result
* @return dest
*/
Vector2d add(Vector2fc v, Vector2d dest);
/**
* Negate this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2d negate(Vector2d dest);
/**
* Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code>
* and store the result in <code>dest</code>.
* <p>
* If <code>t</code> is <code>0.0</code> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code>
* then the result is <code>other</code>.
*
* @param other
* the other vector
* @param t
* the interpolation factor between 0.0 and 1.0
* @param dest
* will hold the result
* @return dest
*/
Vector2d lerp(Vector2dc other, double t, Vector2d dest);
/**
* Add the component-wise multiplication of <code>a * b</code> to this vector
* and store the result in <code>dest</code>.
*
* @param a
* the first multiplicand
* @param b
* the second multiplicand
* @param dest
* will hold the result
* @return dest
*/
Vector2d fma(Vector2dc a, Vector2dc b, Vector2d dest);
/**
* Add the component-wise multiplication of <code>a * b</code> to this vector
* and store the result in <code>dest</code>.
*
* @param a
* the first multiplicand
* @param b
* the second multiplicand
* @param dest
* will hold the result
* @return dest
*/
Vector2d fma(double a, Vector2dc b, Vector2d dest);
/**
* Set the components of <code>dest</code> to be the component-wise minimum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector2d min(Vector2dc v, Vector2d dest);
/**
* Set the components of <code>dest</code> to be the component-wise maximum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector2d max(Vector2dc v, Vector2d dest);
/**
* Determine the component with the biggest absolute value.
*
* @return the component index, within <code>[0..1]</code>
*/
int maxComponent();
/**
* Determine the component with the smallest (towards zero) absolute value.
*
* @return the component index, within <code>[0..1]</code>
*/
int minComponent();
/**
* Get the value of the specified component of this vector.
*
* @param component
* the component, within <code>[0..1]</code>
* @return the value
* @throws IllegalArgumentException if <code>component</code> is not within <code>[0..1]</code>
*/
double get(int component) throws IllegalArgumentException;
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector
* using the given {@link RoundingMode}.
*
* @param mode
* the {@link RoundingMode} to use
* @param dest
* will hold the result
* @return dest
*/
Vector2i get(int mode, Vector2i dest);
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2f get(Vector2f dest);
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2d get(Vector2d dest);
/**
* Compute for each component of this vector the largest (closest to positive
* infinity) {@code double} value that is less than or equal to that
* component and is equal to a mathematical integer and store the result in
* <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2d floor(Vector2d dest);
/**
* Compute for each component of this vector the smallest (closest to negative
* infinity) {@code double} value that is greater than or equal to that
* component and is equal to a mathematical integer and store the result in
* <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2d ceil(Vector2d dest);
/**
* Compute for each component of this vector the closest double that is equal to
* a mathematical integer, with ties rounding to positive infinity and store
* the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2d round(Vector2d dest);
/**
* Determine whether all components are finite floating-point values, that
* is, they are not {@link Double#isNaN() NaN} and not
* {@link Double#isInfinite() infinity}.
*
* @return {@code true} if all components are finite floating-point values;
* {@code false} otherwise
*/
boolean isFinite();
/**
* Compute the absolute of each of this vector's components
* and store the result into <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2d absolute(Vector2d dest);
/**
* Compare the vector components of <code>this</code> vector with the given vector using the given <code>delta</code>
* and return whether all of them are equal within a maximum difference of <code>delta</code>.
* <p>
* Please note that this method is not used by any data structure such as {@link ArrayList} {@link HashSet} or {@link HashMap}
* and their operations, such as {@link ArrayList#contains(Object)} or {@link HashSet#remove(Object)}, since those
* data structures only use the {@link Object#equals(Object)} and {@link Object#hashCode()} methods.
*
* @param v
* the other vector
* @param delta
* the allowed maximum difference
* @return <code>true</code> whether all of the vector components are equal; <code>false</code> otherwise
*/
boolean equals(Vector2dc v, double delta);
/**
* Compare the vector components of <code>this</code> vector with the given <code>(x, y)</code>
* and return whether all of them are equal.
*
* @param x
* the x component to compare to
* @param y
* the y component to compare to
* @return <code>true</code> if all the vector components are equal
*/
boolean equals(double x, double y);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,609 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.*;
/**
* Interface to a read-only view of a 2-dimensional vector of single-precision floats.
*
* @author Kai Burjack
*/
public interface Vector2fc {
/**
* @return the value of the x component
*/
float x();
/**
* @return the value of the y component
*/
float y();
/**
* Store this vector into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which
* the vector is stored, use {@link #get(int, ByteBuffer)}, taking
* the absolute position as parameter.
*
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
* @see #get(int, ByteBuffer)
*/
ByteBuffer get(ByteBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
*/
ByteBuffer get(int index, ByteBuffer buffer);
/**
* Store this vector into the supplied {@link FloatBuffer} at the current
* buffer {@link FloatBuffer#position() position}.
* <p>
* This method will not increment the position of the given FloatBuffer.
* <p>
* In order to specify the offset into the FloatBuffer at which
* the vector is stored, use {@link #get(int, FloatBuffer)}, taking
* the absolute position as parameter.
*
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
* @see #get(int, FloatBuffer)
*/
FloatBuffer get(FloatBuffer buffer);
/**
* Store this vector into the supplied {@link FloatBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given FloatBuffer.
*
* @param index
* the absolute position into the FloatBuffer
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
*/
FloatBuffer get(int index, FloatBuffer buffer);
/**
* Store this vector at the given off-heap memory address.
* <p>
* This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`.
* <p>
* <em>This method is unsafe as it can result in a crash of the JVM process when the specified address range does not belong to this process.</em>
*
* @param address
* the off-heap address where to store this vector
* @return this
*/
Vector2fc getToAddress(long address);
/**
* Subtract <code>v</code> from <code>this</code> vector and store the result in <code>dest</code>.
*
* @param v
* the vector to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector2f sub(Vector2fc v, Vector2f dest);
/**
* Subtract <code>(x, y)</code> from this vector and store the result in <code>dest</code>.
*
* @param x
* the x component to subtract
* @param y
* the y component to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector2f sub(float x, float y, Vector2f dest);
/**
* Return the dot product of this vector and <code>v</code>.
*
* @param v
* the other vector
* @return the dot product
*/
float dot(Vector2fc v);
/**
* Return the angle between this vector and the supplied vector.
*
* @param v
* the other vector
* @return the angle, in radians
*/
float angle(Vector2fc v);
/**
* Return the length squared of this vector.
*
* @return the length squared
*/
float lengthSquared();
/**
* Return the length of this vector.
*
* @return the length
*/
float length();
/**
* Return the distance between this and <code>v</code>.
*
* @param v
* the other vector
* @return the distance
*/
float distance(Vector2fc v);
/**
* Return the distance squared between this and <code>v</code>.
*
* @param v
* the other vector
* @return the distance squared
*/
float distanceSquared(Vector2fc v);
/**
* Return the distance between <code>this</code> vector and <code>(x, y)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @return the euclidean distance
*/
float distance(float x, float y);
/**
* Return the distance squared between <code>this</code> vector and <code>(x, y)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @return the euclidean distance squared
*/
float distanceSquared(float x, float y);
/**
* Normalize this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2f normalize(Vector2f dest);
/**
* Scale this vector to have the given length and store the result in <code>dest</code>.
*
* @param length
* the desired length
* @param dest
* will hold the result
* @return dest
*/
Vector2f normalize(float length, Vector2f dest);
/**
* Add the supplied vector to this one and store the result in
* <code>dest</code>.
*
* @param v
* the vector to add
* @param dest
* will hold the result
* @return dest
*/
Vector2f add(Vector2fc v, Vector2f dest);
/**
* Increment the components of this vector by the given values and store the result in <code>dest</code>.
*
* @param x
* the x component to add
* @param y
* the y component to add
* @param dest
* will hold the result
* @return dest
*/
Vector2f add(float x, float y, Vector2f dest);
/**
* Negate this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2f negate(Vector2f dest);
/**
* Multiply the components of this vector by the given scalar and store the result in <code>dest</code>.
*
* @param scalar
* the value to multiply this vector's components by
* @param dest
* will hold the result
* @return dest
*/
Vector2f mul(float scalar, Vector2f dest);
/**
* Multiply the components of this Vector2f by the given scalar values and store the result in <code>dest</code>.
*
* @param x
* the x component to multiply this vector by
* @param y
* the y component to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2f mul(float x, float y, Vector2f dest);
/**
* Multiply this Vector2f component-wise by another Vector2f and store the result in <code>dest</code>.
*
* @param v
* the vector to multiply by
* @param dest
* will hold the result
* @return dest
*/
Vector2f mul(Vector2fc v, Vector2f dest);
/**
* Divide all components of this {@link Vector2f} by the given scalar
* value and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector2f div(float scalar, Vector2f dest);
/**
* Divide this Vector2f component-wise by another Vector2fc
* and store the result in <code>dest</code>.
*
* @param v
* the vector to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector2f div(Vector2fc v, Vector2f dest);
/**
* Divide the components of this Vector2f by the given scalar values and store the result in <code>dest</code>.
*
* @param x
* the x component to divide this vector by
* @param y
* the y component to divide this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2f div(float x, float y, Vector2f dest);
/**
* Multiply the given matrix with this Vector2f and store the result in <code>dest</code>.
*
* @param mat
* the matrix
* @param dest
* will hold the result
* @return dest
*/
Vector2f mul(Matrix2fc mat, Vector2f dest);
/**
* Multiply the given matrix with this Vector2f and store the result in <code>dest</code>.
*
* @param mat
* the matrix
* @param dest
* will hold the result
* @return dest
*/
Vector2f mul(Matrix2dc mat, Vector2f dest);
/**
* Multiply the transpose of the given matrix with this Vector3f and store the result in <code>dest</code>.
*
* @param mat
* the matrix
* @param dest
* will hold the result
* @return dest
*/
Vector2f mulTranspose(Matrix2fc mat, Vector2f dest);
/**
* Multiply the given 3x2 matrix <code>mat</code> with <code>this</code> and store the
* result in <code>dest</code>.
* <p>
* This method assumes the <code>z</code> component of <code>this</code> to be <code>1.0</code>.
*
* @param mat
* the matrix to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2f mulPosition(Matrix3x2fc mat, Vector2f dest);
/**
* Multiply the given 3x2 matrix <code>mat</code> with <code>this</code> and store the
* result in <code>dest</code>.
* <p>
* This method assumes the <code>z</code> component of <code>this</code> to be <code>0.0</code>.
*
* @param mat
* the matrix to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2f mulDirection(Matrix3x2fc mat, Vector2f dest);
/**
* Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code>
* and store the result in <code>dest</code>.
* <p>
* If <code>t</code> is <code>0.0</code> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code>
* then the result is <code>other</code>.
*
* @param other
* the other vector
* @param t
* the interpolation factor between 0.0 and 1.0
* @param dest
* will hold the result
* @return dest
*/
Vector2f lerp(Vector2fc other, float t, Vector2f dest);
/**
* Add the component-wise multiplication of <code>a * b</code> to this vector
* and store the result in <code>dest</code>.
*
* @param a
* the first multiplicand
* @param b
* the second multiplicand
* @param dest
* will hold the result
* @return dest
*/
Vector2f fma(Vector2fc a, Vector2fc b, Vector2f dest);
/**
* Add the component-wise multiplication of <code>a * b</code> to this vector
* and store the result in <code>dest</code>.
*
* @param a
* the first multiplicand
* @param b
* the second multiplicand
* @param dest
* will hold the result
* @return dest
*/
Vector2f fma(float a, Vector2fc b, Vector2f dest);
/**
* Set the components of <code>dest</code> to be the component-wise minimum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector2f min(Vector2fc v, Vector2f dest);
/**
* Set the components of <code>dest</code> to be the component-wise maximum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector2f max(Vector2fc v, Vector2f dest);
/**
* Determine the component with the biggest absolute value.
*
* @return the component index, within <code>[0..1]</code>
*/
int maxComponent();
/**
* Determine the component with the smallest (towards zero) absolute value.
*
* @return the component index, within <code>[0..1]</code>
*/
int minComponent();
/**
* Get the value of the specified component of this vector.
*
* @param component
* the component, within <code>[0..1]</code>
* @return the value
* @throws IllegalArgumentException if <code>component</code> is not within <code>[0..1]</code>
*/
float get(int component) throws IllegalArgumentException;
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector
* using the given {@link RoundingMode}.
*
* @param mode
* the {@link RoundingMode} to use
* @param dest
* will hold the result
* @return dest
*/
Vector2i get(int mode, Vector2i dest);
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2f get(Vector2f dest);
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2d get(Vector2d dest);
/**
* Compute for each component of this vector the largest (closest to positive
* infinity) {@code float} value that is less than or equal to that
* component and is equal to a mathematical integer and store the result in
* <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2f floor(Vector2f dest);
/**
* Compute for each component of this vector the smallest (closest to negative
* infinity) {@code float} value that is greater than or equal to that
* component and is equal to a mathematical integer and store the result in
* <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2f ceil(Vector2f dest);
/**
* Compute for each component of this vector the closest float that is equal to
* a mathematical integer, with ties rounding to positive infinity and store
* the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2f round(Vector2f dest);
/**
* Determine whether all components are finite floating-point values, that
* is, they are not {@link Float#isNaN() NaN} and not
* {@link Float#isInfinite() infinity}.
*
* @return {@code true} if all components are finite floating-point values;
* {@code false} otherwise
*/
boolean isFinite();
/**
* Compute the absolute of each of this vector's components
* and store the result into <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2f absolute(Vector2f dest);
/**
* Compare the vector components of <code>this</code> vector with the given vector using the given <code>delta</code>
* and return whether all of them are equal within a maximum difference of <code>delta</code>.
* <p>
* Please note that this method is not used by any data structure such as {@link ArrayList} {@link HashSet} or {@link HashMap}
* and their operations, such as {@link ArrayList#contains(Object)} or {@link HashSet#remove(Object)}, since those
* data structures only use the {@link Object#equals(Object)} and {@link Object#hashCode()} methods.
*
* @param v
* the other vector
* @param delta
* the allowed maximum difference
* @return <code>true</code> whether all of the vector components are equal; <code>false</code> otherwise
*/
boolean equals(Vector2fc v, float delta);
/**
* Compare the vector components of <code>this</code> vector with the given <code>(x, y)</code>
* and return whether all of them are equal.
*
* @param x
* the x component to compare to
* @param y
* the y component to compare to
* @return <code>true</code> if all the vector components are equal
*/
boolean equals(float x, float y);
}

View file

@ -0,0 +1,965 @@
/*
* The MIT License
*
* Copyright (c) 2015-2021 Richard Greenlees
*
* 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 com.jozufozu.flywheel.repack.joml;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.text.DecimalFormat;
import java.text.NumberFormat;
/**
* Represents a 2D vector with single-precision.
*
* @author RGreenlees
* @author Kai Burjack
* @author Hans Uhlig
*/
public class Vector2i implements Externalizable, Cloneable, Vector2ic {
private static final long serialVersionUID = 1L;
/**
* The x component of the vector.
*/
public int x;
/**
* The y component of the vector.
*/
public int y;
/**
* Create a new {@link Vector2i} and initialize its components to zero.
*/
public Vector2i() {
}
/**
* Create a new {@link Vector2i} and initialize both of its components with
* the given value.
*
* @param s
* the value of both components
*/
public Vector2i(int s) {
this.x = s;
this.y = s;
}
/**
* Create a new {@link Vector2i} and initialize its components to the given values.
*
* @param x
* the x component
* @param y
* the y component
*/
public Vector2i(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Create a new {@link Vector2i} and initialize its component values and
* round using the given {@link RoundingMode}.
* @param x
* the x component
* @param y
* the y component
* @param mode
* the {@link RoundingMode} to use
*/
public Vector2i(float x, float y, int mode) {
this.x = Math.roundUsing(x, mode);
this.y = Math.roundUsing(y, mode);
}
/**
* Create a new {@link Vector2i} and initialize its component values and
* round using the given {@link RoundingMode}.
* @param x
* the x component
* @param y
* the y component
* @param mode
* the {@link RoundingMode} to use
*/
public Vector2i(double x, double y, int mode) {
this.x = Math.roundUsing(x, mode);
this.y = Math.roundUsing(y, mode);
}
/**
* Create a new {@link Vector2i} and initialize its components to the one of
* the given vector.
*
* @param v
* the {@link Vector2ic} to copy the values from
*/
public Vector2i(Vector2ic v) {
x = v.x();
y = v.y();
}
/**
* Create a new {@link Vector2i} and initialize its components to the rounded value of
* the given vector.
*
* @param v
* the {@link Vector2fc} to round and copy the values from
* @param mode
* the {@link RoundingMode} to use
*/
public Vector2i(Vector2fc v, int mode) {
x = Math.roundUsing(v.x(), mode);
y = Math.roundUsing(v.y(), mode);
}
/**
* Create a new {@link Vector2i} and initialize its components to the rounded value of
* the given vector.
*
* @param v
* the {@link Vector2dc} to round and copy the values from
* @param mode
* the {@link RoundingMode} to use
*/
public Vector2i(Vector2dc v, int mode) {
x = Math.roundUsing(v.x(), mode);
y = Math.roundUsing(v.y(), mode);
}
/**
* Create a new {@link Vector2i} and initialize its two components from the first
* two elements of the given array.
*
* @param xy
* the array containing at least three elements
*/
public Vector2i(int[] xy) {
this.x = xy[0];
this.y = xy[1];
}
/**
* Create a new {@link Vector2i} and read this vector from the supplied
* {@link ByteBuffer} at the current buffer
* {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which the vector is
* read, use {@link #Vector2i(int, ByteBuffer)}, taking the absolute
* position as parameter.
*
* @see #Vector2i(int, ByteBuffer)
*
* @param buffer
* values will be read in <code>x, y</code> order
*/
public Vector2i(ByteBuffer buffer) {
MemUtil.INSTANCE.get(this, buffer.position(), buffer);
}
/**
* Create a new {@link Vector2i} and read this vector from the supplied
* {@link ByteBuffer} starting at the specified absolute buffer
* position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* values will be read in <code>x, y</code> order
*/
public Vector2i(int index, ByteBuffer buffer) {
MemUtil.INSTANCE.get(this, index, buffer);
}
/**
* Create a new {@link Vector2i} and read this vector from the supplied
* {@link IntBuffer} at the current buffer
* {@link IntBuffer#position() position}.
* <p>
* This method will not increment the position of the given IntBuffer.
* <p>
* In order to specify the offset into the IntBuffer at which the vector is
* read, use {@link #Vector2i(int, IntBuffer)}, taking the absolute position
* as parameter.
*
* @see #Vector2i(int, IntBuffer)
*
* @param buffer
* values will be read in <code>x, y</code> order
*/
public Vector2i(IntBuffer buffer) {
MemUtil.INSTANCE.get(this, buffer.position(), buffer);
}
/**
* Create a new {@link Vector2i} and read this vector from the supplied
* {@link IntBuffer} starting at the specified absolute buffer
* position/index.
* <p>
* This method will not increment the position of the given IntBuffer.
*
* @param index
* the absolute position into the IntBuffer
* @param buffer
* values will be read in <code>x, y</code> order
*/
public Vector2i(int index, IntBuffer buffer) {
MemUtil.INSTANCE.get(this, index, buffer);
}
public int x() {
return this.x;
}
public int y() {
return this.y;
}
/**
* Set the x and y components to the supplied value.
*
* @param s
* scalar value of both components
* @return this
*/
public Vector2i set(int s) {
this.x = s;
this.y = s;
return this;
}
/**
* Set the x and y components to the supplied values.
*
* @param x
* the x component
* @param y
* the y component
* @return this
*/
public Vector2i set(int x, int y) {
this.x = x;
this.y = y;
return this;
}
/**
* Set this {@link Vector2i} to the values of v.
*
* @param v
* the vector to copy from
* @return this
*/
public Vector2i set(Vector2ic v) {
this.x = v.x();
this.y = v.y();
return this;
}
/**
* Set this {@link Vector2i} to the values of v using {@link RoundingMode#TRUNCATE} rounding.
* <p>
* Note that due to the given vector <code>v</code> storing the components
* in double-precision, there is the possibility to lose precision.
*
* @param v
* the vector to copy from
* @return this
*/
public Vector2i set(Vector2dc v) {
this.x = (int) v.x();
this.y = (int) v.y();
return this;
}
/**
* Set this {@link Vector2i} to the values of v using the given {@link RoundingMode}.
* <p>
* Note that due to the given vector <code>v</code> storing the components
* in double-precision, there is the possibility to lose precision.
*
* @param v
* the vector to copy from
* @param mode
* the {@link RoundingMode} to use
* @return this
*/
public Vector2i set(Vector2dc v, int mode) {
this.x = Math.roundUsing(v.x(), mode);
this.y = Math.roundUsing(v.y(), mode);
return this;
}
/**
* Set this {@link Vector2i} to the values of v using the given {@link RoundingMode}.
* <p>
* Note that due to the given vector <code>v</code> storing the components
* in double-precision, there is the possibility to lose precision.
*
* @param v
* the vector to copy from
* @param mode
* the {@link RoundingMode} to use
* @return this
*/
public Vector2i set(Vector2fc v, int mode) {
this.x = Math.roundUsing(v.x(), mode);
this.y = Math.roundUsing(v.y(), mode);
return this;
}
/**
* Set the two components of this vector to the first two elements of the given array.
*
* @param xy
* the array containing at least two elements
* @return this
*/
public Vector2i set(int[] xy) {
this.x = xy[0];
this.y = xy[1];
return this;
}
/**
* Read this vector from the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which the vector is
* read, use {@link #set(int, ByteBuffer)}, taking the absolute position as
* parameter.
*
* @see #set(int, ByteBuffer)
*
* @param buffer
* values will be read in <code>x, y</code> order
* @return this
*/
public Vector2i set(ByteBuffer buffer) {
MemUtil.INSTANCE.get(this, buffer.position(), buffer);
return this;
}
/**
* Read this vector from the supplied {@link ByteBuffer} starting at the
* specified absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* values will be read in <code>x, y</code> order
* @return this
*/
public Vector2i set(int index, ByteBuffer buffer) {
MemUtil.INSTANCE.get(this, index, buffer);
return this;
}
/**
* Read this vector from the supplied {@link IntBuffer} at the current
* buffer {@link IntBuffer#position() position}.
* <p>
* This method will not increment the position of the given IntBuffer.
* <p>
* In order to specify the offset into the IntBuffer at which the vector is
* read, use {@link #set(int, IntBuffer)}, taking the absolute position as
* parameter.
*
* @see #set(int, IntBuffer)
*
* @param buffer
* values will be read in <code>x, y</code> order
* @return this
*/
public Vector2i set(IntBuffer buffer) {
MemUtil.INSTANCE.get(this, buffer.position(), buffer);
return this;
}
/**
* Read this vector from the supplied {@link IntBuffer} starting at the
* specified absolute buffer position/index.
* <p>
* This method will not increment the position of the given IntBuffer.
*
* @param index
* the absolute position into the IntBuffer
* @param buffer
* values will be read in <code>x, y</code> order
* @return this
*/
public Vector2i set(int index, IntBuffer buffer) {
MemUtil.INSTANCE.get(this, index, buffer);
return this;
}
/**
* Set the values of this vector by reading 2 integer values from off-heap memory,
* starting at the given address.
* <p>
* This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`.
* <p>
* <em>This method is unsafe as it can result in a crash of the JVM process when the specified address range does not belong to this process.</em>
*
* @param address
* the off-heap memory address to read the vector values from
* @return this
*/
public Vector2i setFromAddress(long address) {
if (Options.NO_UNSAFE)
throw new UnsupportedOperationException("Not supported when using joml.nounsafe");
MemUtil.MemUtilUnsafe.get(this, address);
return this;
}
public int get(int component) throws IllegalArgumentException {
switch (component) {
case 0:
return x;
case 1:
return y;
default:
throw new IllegalArgumentException();
}
}
/**
* Set the value of the specified component of this vector.
*
* @param component
* the component whose value to set, within <code>[0..1]</code>
* @param value
* the value to set
* @return this
* @throws IllegalArgumentException if <code>component</code> is not within <code>[0..1]</code>
*/
public Vector2i setComponent(int component, int value) throws IllegalArgumentException {
switch (component) {
case 0:
x = value;
break;
case 1:
y = value;
break;
default:
throw new IllegalArgumentException();
}
return this;
}
public ByteBuffer get(ByteBuffer buffer) {
MemUtil.INSTANCE.put(this, buffer.position(), buffer);
return buffer;
}
public ByteBuffer get(int index, ByteBuffer buffer) {
MemUtil.INSTANCE.put(this, index, buffer);
return buffer;
}
public IntBuffer get(IntBuffer buffer) {
MemUtil.INSTANCE.put(this, buffer.position(), buffer);
return buffer;
}
public IntBuffer get(int index, IntBuffer buffer) {
MemUtil.INSTANCE.put(this, index, buffer);
return buffer;
}
public Vector2ic getToAddress(long address) {
if (Options.NO_UNSAFE)
throw new UnsupportedOperationException("Not supported when using joml.nounsafe");
MemUtil.MemUtilUnsafe.put(this, address);
return this;
}
/**
* Subtract the supplied vector from this one and store the result in
* <code>this</code>.
*
* @param v
* the vector to subtract
* @return this
*/
public Vector2i sub(Vector2ic v) {
this.x = x - v.x();
this.y = y - v.y();
return this;
}
public Vector2i sub(Vector2ic v, Vector2i dest) {
dest.x = x - v.x();
dest.y = y - v.y();
return dest;
}
/**
* Decrement the components of this vector by the given values.
*
* @param x
* the x component to subtract
* @param y
* the y component to subtract
* @return this
*/
public Vector2i sub(int x, int y) {
this.x = this.x - x;
this.y = this.y - y;
return this;
}
public Vector2i sub(int x, int y, Vector2i dest) {
dest.x = this.x - x;
dest.y = this.y - y;
return dest;
}
public long lengthSquared() {
return x * x + y * y;
}
/**
* Get the length squared of a 2-dimensional single-precision vector.
*
* @param x The vector's x component
* @param y The vector's y component
*
* @return the length squared of the given vector
*/
public static long lengthSquared(int x, int y) {
return x * x + y * y;
}
public double length() {
return Math.sqrt(x * x + y * y);
}
/**
* Get the length of a 2-dimensional single-precision vector.
*
* @param x The vector's x component
* @param y The vector's y component
*
* @return the length squared of the given vector
*/
public static double length(int x, int y) {
return Math.sqrt(x * x + y * y);
}
public double distance(Vector2ic v) {
int dx = this.x - v.x();
int dy = this.y - v.y();
return Math.sqrt(dx * dx + dy * dy);
}
public double distance(int x, int y) {
int dx = this.x - x;
int dy = this.y - y;
return Math.sqrt(dx * dx + dy * dy);
}
public long distanceSquared(Vector2ic v) {
int dx = this.x - v.x();
int dy = this.y - v.y();
return dx * dx + dy * dy;
}
public long distanceSquared(int x, int y) {
int dx = this.x - x;
int dy = this.y - y;
return dx * dx + dy * dy;
}
public long gridDistance(Vector2ic v) {
return Math.abs(v.x() - x()) + Math.abs(v.y() - y());
}
public long gridDistance(int x, int y) {
return Math.abs(x - x()) + Math.abs(y - y());
}
/**
* Return the distance between <code>(x1, y1)</code> and <code>(x2, y2)</code>.
*
* @param x1
* the x component of the first vector
* @param y1
* the y component of the first vector
* @param x2
* the x component of the second vector
* @param y2
* the y component of the second vector
* @return the euclidean distance
*/
public static double distance(int x1, int y1, int x2, int y2) {
int dx = x1 - x2;
int dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
/**
* Return the squared distance between <code>(x1, y1)</code> and <code>(x2, y2)</code>.
*
* @param x1
* the x component of the first vector
* @param y1
* the y component of the first vector
* @param x2
* the x component of the second vector
* @param y2
* the y component of the second vector
* @return the euclidean distance squared
*/
public static long distanceSquared(int x1, int y1, int x2, int y2) {
int dx = x1 - x2;
int dy = y1 - y2;
return dx * dx + dy * dy;
}
/**
* Add <code>v</code> to this vector.
*
* @param v
* the vector to add
* @return this
*/
public Vector2i add(Vector2ic v) {
this.x = x + v.x();
this.y = y + v.y();
return this;
}
public Vector2i add(Vector2ic v, Vector2i dest) {
dest.x = x + v.x();
dest.y = y + v.y();
return dest;
}
/**
* Increment the components of this vector by the given values.
*
* @param x
* the x component to add
* @param y
* the y component to add
* @return this
*/
public Vector2i add(int x, int y) {
this.x = this.x + x;
this.y = this.y + y;
return this;
}
public Vector2i add(int x, int y, Vector2i dest) {
dest.x = this.x + x;
dest.y = this.y + y;
return dest;
}
/**
* Multiply all components of this {@link Vector2i} by the given scalar
* value.
*
* @param scalar
* the scalar to multiply this vector by
* @return this
*/
public Vector2i mul(int scalar) {
this.x = x * scalar;
this.y = y * scalar;
return this;
}
public Vector2i mul(int scalar, Vector2i dest) {
dest.x = x * scalar;
dest.y = y * scalar;
return dest;
}
/**
* Add the supplied vector by this one.
*
* @param v
* the vector to multiply
* @return this
*/
public Vector2i mul(Vector2ic v) {
this.x = x * v.x();
this.y = y * v.y();
return this;
}
public Vector2i mul(Vector2ic v, Vector2i dest) {
dest.x = x * v.x();
dest.y = y * v.y();
return dest;
}
/**
* Multiply the components of this vector by the given values.
*
* @param x
* the x component to multiply
* @param y
* the y component to multiply
* @return this
*/
public Vector2i mul(int x, int y) {
this.x = this.x * x;
this.y = this.y * y;
return this;
}
public Vector2i mul(int x, int y, Vector2i dest) {
dest.x = this.x * x;
dest.y = this.y * y;
return dest;
}
/**
* Divide all components of this {@link Vector2i} by the given scalar value.
*
* @param scalar
* the scalar to divide by
* @return a vector holding the result
*/
public Vector2i div(float scalar) {
float invscalar = 1.0f / scalar;
this.x = (int) (x * invscalar);
this.y = (int) (y * invscalar);
return this;
}
public Vector2i div(float scalar, Vector2i dest) {
float invscalar = 1.0f / scalar;
dest.x = (int) (x * invscalar);
dest.y = (int) (y * invscalar);
return dest;
}
/**
* Divide all components of this {@link Vector2i} by the given scalar value.
*
* @param scalar
* the scalar to divide by
* @return a vector holding the result
*/
public Vector2i div(int scalar) {
this.x = x / scalar;
this.y = y / scalar;
return this;
}
public Vector2i div(int scalar, Vector2i dest) {
dest.x = x / scalar;
dest.y = y / scalar;
return dest;
}
/**
* Set all components to zero.
*
* @return this
*/
public Vector2i zero() {
this.x = 0;
this.y = 0;
return this;
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(x);
out.writeInt(y);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
x = in.readInt();
y = in.readInt();
}
/**
* Negate this vector.
*
* @return this
*/
public Vector2i negate() {
this.x = -x;
this.y = -y;
return this;
}
public Vector2i negate(Vector2i dest) {
dest.x = -x;
dest.y = -y;
return dest;
}
/**
* Set the components of this vector to be the component-wise minimum of this and the other vector.
*
* @param v
* the other vector
* @return this
*/
public Vector2i min(Vector2ic v) {
this.x = x < v.x() ? x : v.x();
this.y = y < v.y() ? y : v.y();
return this;
}
public Vector2i min(Vector2ic v, Vector2i dest) {
dest.x = x < v.x() ? x : v.x();
dest.y = y < v.y() ? y : v.y();
return dest;
}
/**
* Set the components of this vector to be the component-wise maximum of this and the other vector.
*
* @param v
* the other vector
* @return this
*/
public Vector2i max(Vector2ic v) {
this.x = x > v.x() ? x : v.x();
this.y = y > v.y() ? y : v.y();
return this;
}
public Vector2i max(Vector2ic v, Vector2i dest) {
dest.x = x > v.x() ? x : v.x();
dest.y = y > v.y() ? y : v.y();
return dest;
}
public int maxComponent() {
int absX = Math.abs(x);
int absY = Math.abs(y);
if (absX >= absY)
return 0;
return 1;
}
public int minComponent() {
int absX = Math.abs(x);
int absY = Math.abs(y);
if (absX < absY)
return 0;
return 1;
}
/**
* Set <code>this</code> vector's components to their respective absolute values.
*
* @return this
*/
public Vector2i absolute() {
this.x = Math.abs(this.x);
this.y = Math.abs(this.y);
return this;
}
public Vector2i absolute(Vector2i dest) {
dest.x = Math.abs(this.x);
dest.y = Math.abs(this.y);
return dest;
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Vector2i other = (Vector2i) obj;
if (x != other.x) {
return false;
}
if (y != other.y) {
return false;
}
return true;
}
public boolean equals(int x, int y) {
if (this.x != x)
return false;
if (this.y != y)
return false;
return true;
}
/**
* Return a string representation of this vector.
* <p>
* This method creates a new {@link DecimalFormat} on every invocation with the format string "<code>0.000E0;-</code>".
*
* @return the string representation
*/
public String toString() {
return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT));
}
/**
* Return a string representation of this vector 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(x) + " " + formatter.format(y) + ")";
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

View file

@ -0,0 +1,391 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
/**
* Interface to a read-only view of a 2-dimensional vector of integers.
*
* @author Kai Burjack
*/
public interface Vector2ic {
/**
* @return the value of the x component
*/
int x();
/**
* @return the value of the y component
*/
int y();
/**
* Store this vector into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which the vector is
* stored, use {@link #get(int, ByteBuffer)}, taking the absolute position
* as parameter.
*
* @see #get(int, ByteBuffer)
*
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
*/
ByteBuffer get(ByteBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} starting at the
* specified absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
*/
ByteBuffer get(int index, ByteBuffer buffer);
/**
* Store this vector into the supplied {@link IntBuffer} at the current
* buffer {@link IntBuffer#position() position}.
* <p>
* This method will not increment the position of the given IntBuffer.
* <p>
* In order to specify the offset into the IntBuffer at which the vector is
* stored, use {@link #get(int, IntBuffer)}, taking the absolute position as
* parameter.
*
* @see #get(int, IntBuffer)
*
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
*/
IntBuffer get(IntBuffer buffer);
/**
* Store this vector into the supplied {@link IntBuffer} starting at the
* specified absolute buffer position/index.
* <p>
* This method will not increment the position of the given IntBuffer.
*
* @param index
* the absolute position into the IntBuffer
* @param buffer
* will receive the values of this vector in <code>x, y</code> order
* @return the passed in buffer
*/
IntBuffer get(int index, IntBuffer buffer);
/**
* Store this vector at the given off-heap memory address.
* <p>
* This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`.
* <p>
* <em>This method is unsafe as it can result in a crash of the JVM process when the specified address range does not belong to this process.</em>
*
* @param address
* the off-heap address where to store this vector
* @return this
*/
Vector2ic getToAddress(long address);
/**
* Subtract the supplied vector from this one and store the result in
* <code>dest</code>.
*
* @param v
* the vector to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector2i sub(Vector2ic v, Vector2i dest);
/**
* Decrement the components of this vector by the given values and store the
* result in <code>dest</code>.
*
* @param x
* the x component to subtract
* @param y
* the y component to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector2i sub(int x, int y, Vector2i dest);
/**
* Return the length squared of this vector.
*
* @return the length squared
*/
long lengthSquared();
/**
* Return the length of this vector.
*
* @return the length
*/
double length();
/**
* Return the distance between this Vector and <code>v</code>.
*
* @param v
* the other vector
* @return the distance
*/
double distance(Vector2ic v);
/**
* Return the distance between <code>this</code> vector and <code>(x, y)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @return the euclidean distance
*/
double distance(int x, int y);
/**
* Return the square of the distance between this vector and <code>v</code>.
*
* @param v
* the other vector
* @return the squared of the distance
*/
long distanceSquared(Vector2ic v);
/**
* Return the square of the distance between <code>this</code> vector and
* <code>(x, y)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @return the square of the distance
*/
long distanceSquared(int x, int y);
/**
* Return the grid distance in between (aka 1-Norm, Minkowski or Manhattan distance)
* <code>(x, y)</code>.
*
* @param v
* the other vector
* @return the grid distance
*/
long gridDistance(Vector2ic v);
/**
* Return the grid distance in between (aka 1-Norm, Minkowski or Manhattan distance)
* <code>(x, y)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @return the grid distance
*/
long gridDistance(int x, int y);
/**
* Add the supplied vector to this one and store the result in
* <code>dest</code>.
*
* @param v
* the vector to add
* @param dest
* will hold the result
* @return dest
*/
Vector2i add(Vector2ic v, Vector2i dest);
/**
* Increment the components of this vector by the given values and store the
* result in <code>dest</code>.
*
* @param x
* the x component to add
* @param y
* the y component to add
* @param dest
* will hold the result
* @return dest
*/
Vector2i add(int x, int y, Vector2i dest);
/**
* Multiply all components of this {@link Vector2ic} by the given scalar
* value and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector2i mul(int scalar, Vector2i dest);
/**
* Multiply the supplied vector by this one and store the result in
* <code>dest</code>.
*
* @param v
* the vector to multiply
* @param dest
* will hold the result
* @return dest
*/
Vector2i mul(Vector2ic v, Vector2i dest);
/**
* Multiply the components of this vector by the given values and store the
* result in <code>dest</code>.
*
* @param x
* the x component to multiply
* @param y
* the y component to multiply
* @param dest
* will hold the result
* @return dest
*/
Vector2i mul(int x, int y, Vector2i dest);
/**
* Divide all components of this {@link Vector2i} by the given scalar value
* and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector2i div(float scalar, Vector2i dest);
/**
* Divide all components of this {@link Vector2i} by the given scalar value
* and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector2i div(int scalar, Vector2i dest);
/**
* Negate this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2i negate(Vector2i dest);
/**
* Set the components of <code>dest</code> to be the component-wise minimum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector2i min(Vector2ic v, Vector2i dest);
/**
* Set the components of <code>dest</code> to be the component-wise maximum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector2i max(Vector2ic v, Vector2i dest);
/**
* Determine the component with the biggest absolute value.
*
* @return the component index, within <code>[0..1]</code>
*/
int maxComponent();
/**
* Determine the component with the smallest (towards zero) absolute value.
*
* @return the component index, within <code>[0..1]</code>
*/
int minComponent();
/**
* Compute the absolute of each of this vector's components
* and store the result into <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector2i absolute(Vector2i dest);
/**
* Get the value of the specified component of this vector.
*
* @param component
* the component, within <code>[0..1]</code>
* @return the value
* @throws IllegalArgumentException if <code>component</code> is not within <code>[0..1]</code>
*/
int get(int component) throws IllegalArgumentException;
/**
* Compare the vector components of <code>this</code> vector with the given <code>(x, y)</code>
* and return whether all of them are equal.
*
* @param x
* the x component to compare to
* @param y
* the y component to compare to
* @return <code>true</code> if all the vector components are equal
*/
boolean equals(int x, int y);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,409 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
/**
* Interface to a read-only view of a 3-dimensional vector of integers.
*
* @author Kai Burjack
*/
public interface Vector3ic {
/**
* @return the value of the x component
*/
int x();
/**
* @return the value of the y component
*/
int y();
/**
* @return the value of the z component
*/
int z();
/**
* Store this vector into the supplied {@link IntBuffer} at the current
* buffer {@link IntBuffer#position() position}.
* <p>
* This method will not increment the position of the given IntBuffer.
* <p>
* In order to specify the offset into the IntBuffer at which the vector is
* stored, use {@link #get(int, IntBuffer)}, taking the absolute position as
* parameter.
*
* @see #get(int, IntBuffer)
*
* @param buffer
* will receive the values of this vector in <code>x, y, z</code> order
* @return the passed in buffer
*/
IntBuffer get(IntBuffer buffer);
/**
* Store this vector into the supplied {@link IntBuffer} starting at the
* specified absolute buffer position/index.
* <p>
* This method will not increment the position of the given IntBuffer.
*
* @param index
* the absolute position into the IntBuffer
* @param
* buffer will receive the values of this vector in <code>x, y, z</code> order
* @return the passed in buffer
*/
IntBuffer get(int index, IntBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which the vector is
* stored, use {@link #get(int, ByteBuffer)}, taking the absolute position
* as parameter.
*
* @see #get(int, ByteBuffer)
*
* @param buffer
* will receive the values of this vector in <code>x, y, z</code> order
* @return the passed in buffer
*/
ByteBuffer get(ByteBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} starting at the
* specified absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this vector in <code>x, y, z</code> order
* @return the passed in buffer
*/
ByteBuffer get(int index, ByteBuffer buffer);
/**
* Store this vector at the given off-heap memory address.
* <p>
* This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`.
* <p>
* <em>This method is unsafe as it can result in a crash of the JVM process when the specified address range does not belong to this process.</em>
*
* @param address
* the off-heap address where to store this vector
* @return this
*/
Vector3ic getToAddress(long address);
/**
* Subtract the supplied vector from this one and store the result in
* <code>dest</code>.
*
* @param v
* the vector to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector3i sub(Vector3ic v, Vector3i dest);
/**
* Decrement the components of this vector by the given values and store the
* result in <code>dest</code>.
*
* @param x
* the x component to subtract
* @param y
* the y component to subtract
* @param z
* the z component to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector3i sub(int x, int y, int z, Vector3i dest);
/**
* Add the supplied vector to this one and store the result in
* <code>dest</code>.
*
* @param v
* the vector to add
* @param dest
* will hold the result
* @return dest
*/
Vector3i add(Vector3ic v, Vector3i dest);
/**
* Increment the components of this vector by the given values and store the
* result in <code>dest</code>.
*
* @param x
* the x component to add
* @param y
* the y component to add
* @param z
* the z component to add
* @param dest
* will hold the result
* @return dest
*/
Vector3i add(int x, int y, int z, Vector3i dest);
/**
* Multiply the components of this vector by the given scalar and store the result in <code>dest</code>.
*
* @param scalar
* the value to multiply this vector's components by
* @param dest
* will hold the result
* @return dest
*/
Vector3i mul(int scalar, Vector3i dest);
/**
* Multiply the supplied vector by this one and store the result in
* <code>dest</code>.
*
* @param v
* the vector to multiply
* @param dest
* will hold the result
* @return dest
*/
Vector3i mul(Vector3ic v, Vector3i dest);
/**
* Multiply the components of this vector by the given values and store the
* result in <code>dest</code>.
*
* @param x
* the x component to multiply
* @param y
* the y component to multiply
* @param z
* the z component to multiply
* @param dest
* will hold the result
* @return dest
*/
Vector3i mul(int x, int y, int z, Vector3i dest);
/**
* Divide all components of this {@link Vector3i} by the given scalar value
* and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector3i div(float scalar, Vector3i dest);
/**
* Divide all components of this {@link Vector3i} by the given scalar value
* and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector3i div(int scalar, Vector3i dest);
/**
* Return the length squared of this vector.
*
* @return the length squared
*/
long lengthSquared();
/**
* Return the length of this vector.
*
* @return the length
*/
double length();
/**
* Return the distance between this Vector and <code>v</code>.
*
* @param v
* the other vector
* @return the distance
*/
double distance(Vector3ic v);
/**
* Return the distance between <code>this</code> vector and <code>(x, y, z)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @return the euclidean distance
*/
double distance(int x, int y, int z);
/**
* Return the grid distance in between (aka 1-Norm, Minkowski or Manhattan distance)
* <code>(x, y)</code>.
*
* @param v
* the other vector
* @return the grid distance
*/
long gridDistance(Vector3ic v);
/**
* Return the grid distance in between (aka 1-Norm, Minkowski or Manhattan distance)
* <code>(x, y)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the y component of the other vector
* @return the grid distance
*/
long gridDistance(int x, int y, int z);
/**
* Return the square of the distance between this vector and <code>v</code>.
*
* @param v
* the other vector
* @return the squared of the distance
*/
long distanceSquared(Vector3ic v);
/**
* Return the square of the distance between <code>this</code> vector and <code>(x, y, z)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @return the square of the distance
*/
long distanceSquared(int x, int y, int z);
/**
* Negate this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector3i negate(Vector3i dest);
/**
* Set the components of <code>dest</code> to be the component-wise minimum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector3i min(Vector3ic v, Vector3i dest);
/**
* Set the components of <code>dest</code> to be the component-wise maximum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector3i max(Vector3ic v, Vector3i dest);
/**
* Get the value of the specified component of this vector.
*
* @param component
* the component, within <code>[0..2]</code>
* @return the value
* @throws IllegalArgumentException if <code>component</code> is not within <code>[0..2]</code>
*/
int get(int component) throws IllegalArgumentException;
/**
* Determine the component with the biggest absolute value.
*
* @return the component index, within <code>[0..2]</code>
*/
int maxComponent();
/**
* Determine the component with the smallest (towards zero) absolute value.
*
* @return the component index, within <code>[0..2]</code>
*/
int minComponent();
/**
* Compute the absolute of each of this vector's components
* and store the result into <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector3i absolute(Vector3i dest);
/**
* Compare the vector components of <code>this</code> vector with the given <code>(x, y, z)</code>
* and return whether all of them are equal.
*
* @param x
* the x component to compare to
* @param y
* the y component to compare to
* @param z
* the z component to compare to
* @return <code>true</code> if all the vector components are equal
*/
boolean equals(int x, int y, int z);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,933 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.util.*;
/**
* Interface to a read-only view of a 4-dimensional vector of double-precision floats.
*
* @author Kai Burjack
*/
public interface Vector4dc {
/**
* @return the value of the x component
*/
double x();
/**
* @return the value of the y component
*/
double y();
/**
* @return the value of the z component
*/
double z();
/**
* @return the value of the w component
*/
double w();
/**
* Store this vector into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which
* the vector is stored, use {@link #get(int, ByteBuffer)}, taking
* the absolute position as parameter.
*
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
* @see #get(int, ByteBuffer)
*/
ByteBuffer get(ByteBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
*/
ByteBuffer get(int index, ByteBuffer buffer);
/**
* Store this vector into the supplied {@link DoubleBuffer} at the current
* buffer {@link DoubleBuffer#position() position}.
* <p>
* This method will not increment the position of the given DoubleBuffer.
* <p>
* In order to specify the offset into the DoubleBuffer at which
* the vector is stored, use {@link #get(int, DoubleBuffer)}, taking
* the absolute position as parameter.
*
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
* @see #get(int, DoubleBuffer)
*/
DoubleBuffer get(DoubleBuffer buffer);
/**
* Store this vector into the supplied {@link DoubleBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given DoubleBuffer.
*
* @param index
* the absolute position into the DoubleBuffer
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
*/
DoubleBuffer get(int index, DoubleBuffer buffer);
/**
* Store this vector into the supplied {@link FloatBuffer} at the current
* buffer {@link FloatBuffer#position() position}.
* <p>
* This method will not increment the position of the given FloatBuffer.
* <p>
* In order to specify the offset into the FloatBuffer at which
* the vector is stored, use {@link #get(int, FloatBuffer)}, taking
* the absolute position as parameter.
* <p>
* Please note that due to this vector storing double values those values will potentially
* lose precision when they are converted to float values before being put into the given FloatBuffer.
*
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
* @see #get(int, DoubleBuffer)
*/
FloatBuffer get(FloatBuffer buffer);
/**
* Store this vector into the supplied {@link FloatBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given FloatBuffer.
* <p>
* Please note that due to this vector storing double values those values will potentially
* lose precision when they are converted to float values before being put into the given FloatBuffer.
*
* @param index
* the absolute position into the FloatBuffer
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
*/
FloatBuffer get(int index, FloatBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which
* the vector is stored, use {@link #get(int, ByteBuffer)}, taking
* the absolute position as parameter.
* <p>
* Please note that due to this vector storing double values those values will potentially
* lose precision when they are converted to float values before being put into the given ByteBuffer.
*
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
* @see #get(int, ByteBuffer)
*/
ByteBuffer getf(ByteBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* Please note that due to this vector storing double values those values will potentially
* lose precision when they are converted to float values before being put into the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
*/
ByteBuffer getf(int index, ByteBuffer buffer);
/**
* Store this vector at the given off-heap memory address.
* <p>
* This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`.
* <p>
* <em>This method is unsafe as it can result in a crash of the JVM process when the specified address range does not belong to this process.</em>
*
* @param address
* the off-heap address where to store this vector
* @return this
*/
Vector4dc getToAddress(long address);
/**
* Subtract the supplied vector from this one and store the result in <code>dest</code>.
*
* @param v
* the vector to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector4d sub(Vector4dc v, Vector4d dest);
/**
* Subtract the supplied vector from this one and store the result in <code>dest</code>.
*
* @param v
* the vector to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector4d sub(Vector4fc v, Vector4d dest);
/**
* Subtract <code>(x, y, z, w)</code> from this and store the result in <code>dest</code>.
*
* @param x
* the x component to subtract
* @param y
* the y component to subtract
* @param z
* the z component to subtract
* @param w
* the w component to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector4d sub(double x, double y, double z, double w, Vector4d dest);
/**
* Add the supplied vector to this one and store the result in <code>dest</code>.
*
* @param v
* the vector to add
* @param dest
* will hold the result
* @return dest
*/
Vector4d add(Vector4dc v, Vector4d dest);
/**
* Add the supplied vector to this one and store the result in <code>dest</code>.
*
* @param v
* the vector to add
* @param dest
* will hold the result
* @return dest
*/
Vector4d add(Vector4fc v, Vector4d dest);
/**
* Add <code>(x, y, z, w)</code> to this and store the result in <code>dest</code>.
*
* @param x
* the x component to subtract
* @param y
* the y component to subtract
* @param z
* the z component to subtract
* @param w
* the w component to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector4d add(double x, double y, double z, double w, Vector4d dest);
/**
* Add the component-wise multiplication of <code>a * b</code> to this vector
* and store the result in <code>dest</code>.
*
* @param a
* the first multiplicand
* @param b
* the second multiplicand
* @param dest
* will hold the result
* @return dest
*/
Vector4d fma(Vector4dc a, Vector4dc b, Vector4d dest);
/**
* Add the component-wise multiplication of <code>a * b</code> to this vector
* and store the result in <code>dest</code>.
*
* @param a
* the first multiplicand
* @param b
* the second multiplicand
* @param dest
* will hold the result
* @return dest
*/
Vector4d fma(double a, Vector4dc b, Vector4d dest);
/**
* Multiply this {@link Vector4d} component-wise by the given {@link Vector4dc} and store the result in <code>dest</code>.
*
* @param v
* the vector to multiply this by
* @param dest
* will hold the result
* @return dest
*/
Vector4d mul(Vector4dc v, Vector4d dest);
/**
* Multiply this {@link Vector4d} component-wise by the given {@link Vector4fc} and store the result in <code>dest</code>.
*
* @param v
* the vector to multiply this by
* @param dest
* will hold the result
* @return dest
*/
Vector4d mul(Vector4fc v, Vector4d dest);
/**
* Divide this {@link Vector4d} component-wise by the given {@link Vector4dc} and store the result in <code>dest</code>.
*
* @param v
* the vector to divide this by
* @param dest
* will hold the result
* @return dest
*/
Vector4d div(Vector4dc v, Vector4d dest);
/**
* Multiply the given matrix mat with this {@link Vector4d} and store the result in <code>dest</code>.
*
* @param mat
* the matrix to multiply <code>this</code> by
* @param dest
* will hold the result
* @return dest
*/
Vector4d mul(Matrix4dc mat, Vector4d dest);
/**
* Multiply the given matrix mat with this Vector4d and store the result in
* <code>dest</code>.
*
* @param mat
* the matrix to multiply the vector with
* @param dest
* the destination vector to hold the result
* @return dest
*/
Vector4d mul(Matrix4x3dc mat, Vector4d dest);
/**
* Multiply the given matrix mat with this Vector4d and store the result in
* <code>dest</code>.
*
* @param mat
* the matrix to multiply the vector with
* @param dest
* the destination vector to hold the result
* @return dest
*/
Vector4d mul(Matrix4x3fc mat, Vector4d dest);
/**
* Multiply the given matrix mat with this Vector4d and store the result in <code>dest</code>.
*
* @param mat
* the matrix to multiply <code>this</code> by
* @param dest
* will hold the result
* @return dest
*/
Vector4d mul(Matrix4fc mat, Vector4d dest);
/**
* Multiply the transpose of the given matrix <code>mat</code> with this Vector4d and store the result in
* <code>dest</code>.
*
* @param mat
* the matrix whose transpose to multiply the vector with
* @param dest
* the destination vector to hold the result
* @return dest
*/
Vector4d mulTranspose(Matrix4dc mat, Vector4d dest);
/**
* Multiply the given affine matrix mat with this Vector4d and store the result in
* <code>dest</code>.
*
* @param mat
* the affine matrix to multiply the vector with
* @param dest
* the destination vector to hold the result
* @return dest
*/
Vector4d mulAffine(Matrix4dc mat, Vector4d dest);
/**
* Multiply the transpose of the given affine matrix <code>mat</code> with this Vector4d and store the result in
* <code>dest</code>.
*
* @param mat
* the affine matrix whose transpose to multiply the vector with
* @param dest
* the destination vector to hold the result
* @return dest
*/
Vector4d mulAffineTranspose(Matrix4dc mat, Vector4d dest);
/**
* Multiply the given matrix <code>mat</code> with this Vector4d, perform perspective division
* and store the result in <code>dest</code>.
*
* @param mat
* the matrix to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector4d mulProject(Matrix4dc mat, Vector4d dest);
/**
* Multiply the given matrix <code>mat</code> with this Vector4d, perform perspective division
* and store the <code>(x, y, z)</code> result in <code>dest</code>.
*
* @param mat
* the matrix to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector3d mulProject(Matrix4dc mat, Vector3d dest);
/**
* Add the component-wise multiplication of <code>this * a</code> to <code>b</code>
* and store the result in <code>dest</code>.
*
* @param a
* the multiplicand
* @param b
* the addend
* @param dest
* will hold the result
* @return dest
*/
Vector4d mulAdd(Vector4dc a, Vector4dc b, Vector4d dest);
/**
* Add the component-wise multiplication of <code>this * a</code> to <code>b</code>
* and store the result in <code>dest</code>.
*
* @param a
* the multiplicand
* @param b
* the addend
* @param dest
* will hold the result
* @return dest
*/
Vector4d mulAdd(double a, Vector4dc b, Vector4d dest);
/**
* Multiply this Vector4d by the given scalar value and store the result in <code>dest</code>.
*
* @param scalar
* the factor to multiply by
* @param dest
* will hold the result
* @return dest
*/
Vector4d mul(double scalar, Vector4d dest);
/**
* Divide this Vector4d by the given scalar value and store the result in <code>dest</code>.
*
* @param scalar
* the factor to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector4d div(double scalar, Vector4d dest);
/**
* Transform this vector by the given quaternion <code>quat</code> and store the result in <code>dest</code>.
*
* @see Quaterniond#transform(Vector4d)
*
* @param quat
* the quaternion to transform this vector
* @param dest
* will hold the result
* @return dest
*/
Vector4d rotate(Quaterniondc quat, Vector4d dest);
/**
* Rotate this vector the specified radians around the given rotation axis and store the result
* into <code>dest</code>.
*
* @param angle
* the angle in radians
* @param aX
* the x component of the rotation axis
* @param aY
* the y component of the rotation axis
* @param aZ
* the z component of the rotation axis
* @param dest
* will hold the result
* @return dest
*/
Vector4d rotateAxis(double angle, double aX, double aY, double aZ, Vector4d dest);
/**
* Rotate this vector the specified radians around the X axis and store the result
* into <code>dest</code>.
*
* @param angle
* the angle in radians
* @param dest
* will hold the result
* @return dest
*/
Vector4d rotateX(double angle, Vector4d dest);
/**
* Rotate this vector the specified radians around the Y axis and store the result
* into <code>dest</code>.
*
* @param angle
* the angle in radians
* @param dest
* will hold the result
* @return dest
*/
Vector4d rotateY(double angle, Vector4d dest);
/**
* Rotate this vector the specified radians around the Z axis and store the result
* into <code>dest</code>.
*
* @param angle
* the angle in radians
* @param dest
* will hold the result
* @return dest
*/
Vector4d rotateZ(double angle, Vector4d dest);
/**
* Return the length squared of this vector.
*
* @return the length squared
*/
double lengthSquared();
/**
* Return the length of this vector.
*
* @return the length
*/
double length();
/**
* Normalizes this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4d normalize(Vector4d dest);
/**
* Scale this vector to have the given length and store the result in <code>dest</code>.
*
* @param length
* the desired length
* @param dest
* will hold the result
* @return dest
*/
Vector4d normalize(double length, Vector4d dest);
/**
* Normalize this vector by computing only the norm of <code>(x, y, z)</code> and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4d normalize3(Vector4d dest);
/**
* Return the distance between this Vector and <code>v</code>.
*
* @param v
* the other vector
* @return the distance
*/
double distance(Vector4dc v);
/**
* Return the distance between <code>this</code> vector and <code>(x, y, z, w)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @param w
* the w component of the other vector
* @return the euclidean distance
*/
double distance(double x, double y, double z, double w);
/**
* Return the square of the distance between this vector and <code>v</code>.
*
* @param v
* the other vector
* @return the squared of the distance
*/
double distanceSquared(Vector4dc v);
/**
* Return the square of the distance between <code>this</code> vector and
* <code>(x, y, z, w)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @param w
* the w component of the other vector
* @return the square of the distance
*/
double distanceSquared(double x, double y, double z, double w);
/**
* Compute the dot product (inner product) of this vector and <code>v</code>.
*
* @param v
* the other vector
* @return the dot product
*/
double dot(Vector4dc v);
/**
* Compute the dot product (inner product) of this vector and <code>(x, y, z, w)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @param w
* the w component of the other vector
* @return the dot product
*/
double dot(double x, double y, double z, double w);
/**
* Return the cosine of the angle between this vector and the supplied vector.
* <p>
* Use this instead of <code>Math.cos(angle(v))</code>.
*
* @see #angle(Vector4dc)
*
* @param v
* the other vector
* @return the cosine of the angle
*/
double angleCos(Vector4dc v);
/**
* Return the angle between this vector and the supplied vector.
*
* @see #angleCos(Vector4dc)
*
* @param v
* the other vector
* @return the angle, in radians
*/
double angle(Vector4dc v);
/**
* Negate this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4d negate(Vector4d dest);
/**
* Set the components of <code>dest</code> to be the component-wise minimum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector4d min(Vector4dc v, Vector4d dest);
/**
* Set the components of <code>dest</code> to be the component-wise maximum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector4d max(Vector4dc v, Vector4d dest);
/**
* Compute a smooth-step (i.e. hermite with zero tangents) interpolation
* between <code>this</code> vector and the given vector <code>v</code> and
* store the result in <code>dest</code>.
*
* @param v
* the other vector
* @param t
* the interpolation factor, within <code>[0..1]</code>
* @param dest
* will hold the result
* @return dest
*/
Vector4d smoothStep(Vector4dc v, double t, Vector4d dest);
/**
* Compute a hermite interpolation between <code>this</code> vector and its
* associated tangent <code>t0</code> and the given vector <code>v</code>
* with its tangent <code>t1</code> and store the result in
* <code>dest</code>.
*
* @param t0
* the tangent of <code>this</code> vector
* @param v1
* the other vector
* @param t1
* the tangent of the other vector
* @param t
* the interpolation factor, within <code>[0..1]</code>
* @param dest
* will hold the result
* @return dest
*/
Vector4d hermite(Vector4dc t0, Vector4dc v1, Vector4dc t1, double t, Vector4d dest);
/**
* Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code>
* and store the result in <code>dest</code>.
* <p>
* If <code>t</code> is <code>0.0</code> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code>
* then the result is <code>other</code>.
*
* @param other
* the other vector
* @param t
* the interpolation factor between 0.0 and 1.0
* @param dest
* will hold the result
* @return dest
*/
Vector4d lerp(Vector4dc other, double t, Vector4d dest);
/**
* Get the value of the specified component of this vector.
*
* @param component
* the component, within <code>[0..3]</code>
* @return the value
* @throws IllegalArgumentException if <code>component</code> is not within <code>[0..3]</code>
*/
double get(int component) throws IllegalArgumentException;
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector
* using the given {@link RoundingMode}.
*
* @param mode
* the {@link RoundingMode} to use
* @param dest
* will hold the result
* @return dest
*/
Vector4i get(int mode, Vector4i dest);
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4f get(Vector4f dest);
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4d get(Vector4d dest);
/**
* Determine the component with the biggest absolute value.
*
* @return the component index, within <code>[0..3]</code>
*/
int maxComponent();
/**
* Determine the component with the smallest (towards zero) absolute value.
*
* @return the component index, within <code>[0..3]</code>
*/
int minComponent();
/**
* Compute for each component of this vector the largest (closest to positive
* infinity) {@code double} value that is less than or equal to that
* component and is equal to a mathematical integer and store the result in
* <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4d floor(Vector4d dest);
/**
* Compute for each component of this vector the smallest (closest to negative
* infinity) {@code double} value that is greater than or equal to that
* component and is equal to a mathematical integer and store the result in
* <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4d ceil(Vector4d dest);
/**
* Compute for each component of this vector the closest double that is equal to
* a mathematical integer, with ties rounding to positive infinity and store
* the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4d round(Vector4d dest);
/**
* Determine whether all components are finite floating-point values, that
* is, they are not {@link Double#isNaN() NaN} and not
* {@link Double#isInfinite() infinity}.
*
* @return {@code true} if all components are finite floating-point values;
* {@code false} otherwise
*/
boolean isFinite();
/**
* Compute the absolute of each of this vector's components
* and store the result into <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4d absolute(Vector4d dest);
/**
* Compare the vector components of <code>this</code> vector with the given vector using the given <code>delta</code>
* and return whether all of them are equal within a maximum difference of <code>delta</code>.
* <p>
* Please note that this method is not used by any data structure such as {@link ArrayList} {@link HashSet} or {@link HashMap}
* and their operations, such as {@link ArrayList#contains(Object)} or {@link HashSet#remove(Object)}, since those
* data structures only use the {@link Object#equals(Object)} and {@link Object#hashCode()} methods.
*
* @param v
* the other vector
* @param delta
* the allowed maximum difference
* @return <code>true</code> whether all of the vector components are equal; <code>false</code> otherwise
*/
boolean equals(Vector4dc v, double delta);
/**
* Compare the vector components of <code>this</code> vector with the given <code>(x, y, z, w)</code>
* and return whether all of them are equal.
*
* @param x
* the x component to compare to
* @param y
* the y component to compare to
* @param z
* the z component to compare to
* @param w
* the w component to compare to
* @return <code>true</code> if all the vector components are equal
*/
boolean equals(double x, double y, double z, double w);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,838 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.*;
/**
* Interface to a read-only view of a 4-dimensional vector of single-precision floats.
*
* @author Kai Burjack
*/
public interface Vector4fc {
/**
* @return the value of the x component
*/
float x();
/**
* @return the value of the y component
*/
float y();
/**
* @return the value of the z component
*/
float z();
/**
* @return the value of the w component
*/
float w();
/**
* Store this vector into the supplied {@link FloatBuffer} at the current
* buffer {@link FloatBuffer#position() position}.
* <p>
* This method will not increment the position of the given FloatBuffer.
* <p>
* In order to specify the offset into the FloatBuffer at which
* the vector is stored, use {@link #get(int, FloatBuffer)}, taking
* the absolute position as parameter.
*
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
* @see #get(int, FloatBuffer)
*/
FloatBuffer get(FloatBuffer buffer);
/**
* Store this vector into the supplied {@link FloatBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given FloatBuffer.
*
* @param index
* the absolute position into the FloatBuffer
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
*/
FloatBuffer get(int index, FloatBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which
* the vector is stored, use {@link #get(int, ByteBuffer)}, taking
* the absolute position as parameter.
*
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
* @see #get(int, ByteBuffer)
*/
ByteBuffer get(ByteBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} starting at the specified
* absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
*/
ByteBuffer get(int index, ByteBuffer buffer);
/**
* Store this vector at the given off-heap memory address.
* <p>
* This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`.
* <p>
* <em>This method is unsafe as it can result in a crash of the JVM process when the specified address range does not belong to this process.</em>
*
* @param address
* the off-heap address where to store this vector
* @return this
*/
Vector4fc getToAddress(long address);
/**
* Subtract the supplied vector from this one and store the result in <code>dest</code>.
*
* @param v
* the vector to subtract from <code>this</code>
* @param dest
* will hold the result
* @return dest
*/
Vector4f sub(Vector4fc v, Vector4f dest);
/**
* Subtract <code>(x, y, z, w)</code> from this and store the result in <code>dest</code>.
*
* @param x
* the x component to subtract
* @param y
* the y component to subtract
* @param z
* the z component to subtract
* @param w
* the w component to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector4f sub(float x, float y, float z, float w, Vector4f dest);
/**
* Add the supplied vector to this one and store the result in <code>dest</code>.
*
* @param v
* the vector to add
* @param dest
* will hold the result
* @return dest
*/
Vector4f add(Vector4fc v, Vector4f dest);
/**
* Increment the components of this vector by the given values and store the result in <code>dest</code>.
*
* @param x
* the x component to add
* @param y
* the y component to add
* @param z
* the z component to add
* @param w
* the w component to add
* @param dest
* will hold the result
* @return dest
*/
Vector4f add(float x, float y, float z, float w, Vector4f dest);
/**
* Add the component-wise multiplication of <code>a * b</code> to this vector
* and store the result in <code>dest</code>.
*
* @param a
* the first multiplicand
* @param b
* the second multiplicand
* @param dest
* will hold the result
* @return dest
*/
Vector4f fma(Vector4fc a, Vector4fc b, Vector4f dest);
/**
* Add the component-wise multiplication of <code>a * b</code> to this vector
* and store the result in <code>dest</code>.
*
* @param a
* the first multiplicand
* @param b
* the second multiplicand
* @param dest
* will hold the result
* @return dest
*/
Vector4f fma(float a, Vector4fc b, Vector4f dest);
/**
* Add the component-wise multiplication of <code>this * a</code> to <code>b</code>
* and store the result in <code>dest</code>.
*
* @param a
* the multiplicand
* @param b
* the addend
* @param dest
* will hold the result
* @return dest
*/
Vector4f mulAdd(Vector4fc a, Vector4fc b, Vector4f dest);
/**
* Add the component-wise multiplication of <code>this * a</code> to <code>b</code>
* and store the result in <code>dest</code>.
*
* @param a
* the multiplicand
* @param b
* the addend
* @param dest
* will hold the result
* @return dest
*/
Vector4f mulAdd(float a, Vector4fc b, Vector4f dest);
/**
* Multiply this Vector4f component-wise by another Vector4f and store the result in <code>dest</code>.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector4f mul(Vector4fc v, Vector4f dest);
/**
* Divide this Vector4f component-wise by another Vector4f and store the result in <code>dest</code>.
*
* @param v
* the vector to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector4f div(Vector4fc v, Vector4f dest);
/**
* Multiply the given matrix mat with this Vector4f and store the result in
* <code>dest</code>.
*
* @param mat
* the matrix to multiply the vector with
* @param dest
* the destination vector to hold the result
* @return dest
*/
Vector4f mul(Matrix4fc mat, Vector4f dest);
/**
* Multiply the transpose of the given matrix <code>mat</code> with this Vector4f and store the result in
* <code>dest</code>.
*
* @param mat
* the matrix whose transpose to multiply the vector with
* @param dest
* the destination vector to hold the result
* @return dest
*/
Vector4f mulTranspose(Matrix4fc mat, Vector4f dest);
/**
* Multiply the given affine matrix mat with this Vector4f and store the result in
* <code>dest</code>.
*
* @param mat
* the affine matrix to multiply the vector with
* @param dest
* the destination vector to hold the result
* @return dest
*/
Vector4f mulAffine(Matrix4fc mat, Vector4f dest);
/**
* Multiply the transpose of the given affine matrix <code>mat</code> with this Vector4f and store the result in
* <code>dest</code>.
*
* @param mat
* the affine matrix whose transpose to multiply the vector with
* @param dest
* the destination vector to hold the result
* @return dest
*/
Vector4f mulAffineTranspose(Matrix4fc mat, Vector4f dest);
/**
* Multiply the given matrix mat with this Vector4f and store the result in
* <code>dest</code>.
*
* @param mat
* the matrix to multiply the vector with
* @param dest
* the destination vector to hold the result
* @return dest
*/
Vector4f mul(Matrix4x3fc mat, Vector4f dest);
/**
* Multiply the given matrix <code>mat</code> with this Vector4f, perform perspective division
* and store the result in <code>dest</code>.
*
* @param mat
* the matrix to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector4f mulProject(Matrix4fc mat, Vector4f dest);
/**
* Multiply the given matrix <code>mat</code> with this Vector4f, perform perspective division
* and store the <code>(x, y, z)</code> result in <code>dest</code>.
*
* @param mat
* the matrix to multiply this vector by
* @param dest
* will hold the result
* @return dest
*/
Vector3f mulProject(Matrix4fc mat, Vector3f dest);
/**
* Multiply all components of this {@link Vector4f} by the given scalar
* value and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to multiply by
* @param dest
* will hold the result
* @return dest
*/
Vector4f mul(float scalar, Vector4f dest);
/**
* Multiply the components of this Vector4f by the given scalar values and store the result in <code>dest</code>.
*
* @param x
* the x component to multiply by
* @param y
* the y component to multiply by
* @param z
* the z component to multiply by
* @param w
* the w component to multiply by
* @param dest
* will hold the result
* @return dest
*/
Vector4f mul(float x, float y, float z, float w, Vector4f dest);
/**
* Divide all components of this {@link Vector4f} by the given scalar
* value and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector4f div(float scalar, Vector4f dest);
/**
* Divide the components of this Vector4f by the given scalar values and store the result in <code>dest</code>.
*
* @param x
* the x component to divide by
* @param y
* the y component to divide by
* @param z
* the z component to divide by
* @param w
* the w component to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector4f div(float x, float y, float z, float w, Vector4f dest);
/**
* Rotate this vector by the given quaternion <code>quat</code> and store the result in <code>dest</code>.
*
* @see Quaternionf#transform(Vector4f)
*
* @param quat
* the quaternion to rotate this vector
* @param dest
* will hold the result
* @return dest
*/
Vector4f rotate(Quaternionfc quat, Vector4f dest);
/**
* Rotate this vector the specified radians around the given rotation axis and store the result
* into <code>dest</code>.
*
* @param angle
* the angle in radians
* @param aX
* the x component of the rotation axis
* @param aY
* the y component of the rotation axis
* @param aZ
* the z component of the rotation axis
* @param dest
* will hold the result
* @return dest
*/
Vector4f rotateAxis(float angle, float aX, float aY, float aZ, Vector4f dest);
/**
* Rotate this vector the specified radians around the X axis and store the result
* into <code>dest</code>.
*
* @param angle
* the angle in radians
* @param dest
* will hold the result
* @return dest
*/
Vector4f rotateX(float angle, Vector4f dest);
/**
* Rotate this vector the specified radians around the Y axis and store the result
* into <code>dest</code>.
*
* @param angle
* the angle in radians
* @param dest
* will hold the result
* @return dest
*/
Vector4f rotateY(float angle, Vector4f dest);
/**
* Rotate this vector the specified radians around the Z axis and store the result
* into <code>dest</code>.
*
* @param angle
* the angle in radians
* @param dest
* will hold the result
* @return dest
*/
Vector4f rotateZ(float angle, Vector4f dest);
/**
* Return the length squared of this vector.
*
* @return the length squared
*/
float lengthSquared();
/**
* Return the length of this vector.
*
* @return the length
*/
float length();
/**
* Normalizes this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4f normalize(Vector4f dest);
/**
* Scale this vector to have the given length and store the result in <code>dest</code>.
*
* @param length
* the desired length
* @param dest
* will hold the result
* @return dest
*/
Vector4f normalize(float length, Vector4f dest);
/**
* Normalize this vector by computing only the norm of <code>(x, y, z)</code> and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4f normalize3(Vector4f dest);
/**
* Return the distance between this Vector and <code>v</code>.
*
* @param v
* the other vector
* @return the distance
*/
float distance(Vector4fc v);
/**
* Return the distance between <code>this</code> vector and <code>(x, y, z, w)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @param w
* the w component of the other vector
* @return the euclidean distance
*/
float distance(float x, float y, float z, float w);
/**
* Return the square of the distance between this vector and <code>v</code>.
*
* @param v
* the other vector
* @return the squared of the distance
*/
float distanceSquared(Vector4fc v);
/**
* Return the square of the distance between <code>this</code> vector and
* <code>(x, y, z, w)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @param w
* the w component of the other vector
* @return the square of the distance
*/
float distanceSquared(float x, float y, float z, float w);
/**
* Compute the dot product (inner product) of this vector and <code>v</code>
* .
*
* @param v
* the other vector
* @return the dot product
*/
float dot(Vector4fc v);
/**
* Compute the dot product (inner product) of this vector and <code>(x, y, z, w)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @param w
* the w component of the other vector
* @return the dot product
*/
float dot(float x, float y, float z, float w);
/**
* Return the cosine of the angle between this vector and the supplied vector. Use this instead of <code>Math.cos(angle(v))</code>.
*
* @see #angle(Vector4fc)
*
* @param v
* the other vector
* @return the cosine of the angle
*/
float angleCos(Vector4fc v);
/**
* Return the angle between this vector and the supplied vector.
*
* @see #angleCos(Vector4fc)
*
* @param v
* the other vector
* @return the angle, in radians
*/
float angle(Vector4fc v);
/**
* Negate this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4f negate(Vector4f dest);
/**
* Set the components of <code>dest</code> to be the component-wise minimum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector4f min(Vector4fc v, Vector4f dest);
/**
* Set the components of <code>dest</code> to be the component-wise maximum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector4f max(Vector4fc v, Vector4f dest);
/**
* Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code>
* and store the result in <code>dest</code>.
* <p>
* If <code>t</code> is <code>0.0</code> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code>
* then the result is <code>other</code>.
*
* @param other
* the other vector
* @param t
* the interpolation factor between 0.0 and 1.0
* @param dest
* will hold the result
* @return dest
*/
Vector4f lerp(Vector4fc other, float t, Vector4f dest);
/**
* Compute a smooth-step (i.e. hermite with zero tangents) interpolation
* between <code>this</code> vector and the given vector <code>v</code> and
* store the result in <code>dest</code>.
*
* @param v
* the other vector
* @param t
* the interpolation factor, within <code>[0..1]</code>
* @param dest
* will hold the result
* @return dest
*/
Vector4f smoothStep(Vector4fc v, float t, Vector4f dest);
/**
* Compute a hermite interpolation between <code>this</code> vector and its
* associated tangent <code>t0</code> and the given vector <code>v</code>
* with its tangent <code>t1</code> and store the result in
* <code>dest</code>.
*
* @param t0
* the tangent of <code>this</code> vector
* @param v1
* the other vector
* @param t1
* the tangent of the other vector
* @param t
* the interpolation factor, within <code>[0..1]</code>
* @param dest
* will hold the result
* @return dest
*/
Vector4f hermite(Vector4fc t0, Vector4fc v1, Vector4fc t1, float t, Vector4f dest);
/**
* Get the value of the specified component of this vector.
*
* @param component
* the component, within <code>[0..3]</code>
* @return the value
* @throws IllegalArgumentException if <code>component</code> is not within <code>[0..3]</code>
*/
float get(int component) throws IllegalArgumentException;
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector
* using the given {@link RoundingMode}.
*
* @param mode
* the {@link RoundingMode} to use
* @param dest
* will hold the result
* @return dest
*/
Vector4i get(int mode, Vector4i dest);
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4f get(Vector4f dest);
/**
* Set the components of the given vector <code>dest</code> to those of <code>this</code> vector.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4d get(Vector4d dest);
/**
* Determine the component with the biggest absolute value.
*
* @return the component index, within <code>[0..3]</code>
*/
int maxComponent();
/**
* Determine the component with the smallest (towards zero) absolute value.
*
* @return the component index, within <code>[0..3]</code>
*/
int minComponent();
/**
* Compute for each component of this vector the largest (closest to positive
* infinity) {@code float} value that is less than or equal to that
* component and is equal to a mathematical integer and store the result in
* <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4f floor(Vector4f dest);
/**
* Compute for each component of this vector the smallest (closest to negative
* infinity) {@code float} value that is greater than or equal to that
* component and is equal to a mathematical integer and store the result in
* <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4f ceil(Vector4f dest);
/**
* Compute for each component of this vector the closest float that is equal to
* a mathematical integer, with ties rounding to positive infinity and store
* the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4f round(Vector4f dest);
/**
* Determine whether all components are finite floating-point values, that
* is, they are not {@link Float#isNaN() NaN} and not
* {@link Float#isInfinite() infinity}.
*
* @return {@code true} if all components are finite floating-point values;
* {@code false} otherwise
*/
boolean isFinite();
/**
* Compute the absolute of each of this vector's components
* and store the result into <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4f absolute(Vector4f dest);
/**
* Compare the vector components of <code>this</code> vector with the given vector using the given <code>delta</code>
* and return whether all of them are equal within a maximum difference of <code>delta</code>.
* <p>
* Please note that this method is not used by any data structure such as {@link ArrayList} {@link HashSet} or {@link HashMap}
* and their operations, such as {@link ArrayList#contains(Object)} or {@link HashSet#remove(Object)}, since those
* data structures only use the {@link Object#equals(Object)} and {@link Object#hashCode()} methods.
*
* @param v
* the other vector
* @param delta
* the allowed maximum difference
* @return <code>true</code> whether all of the vector components are equal; <code>false</code> otherwise
*/
boolean equals(Vector4fc v, float delta);
/**
* Compare the vector components of <code>this</code> vector with the given <code>(x, y, z, w)</code>
* and return whether all of them are equal.
*
* @param x
* the x component to compare to
* @param y
* the y component to compare to
* @param z
* the z component to compare to
* @param w
* the w component to compare to
* @return <code>true</code> if all the vector components are equal
*/
boolean equals(float x, float y, float z, float w);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,432 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
/**
* Interface to a read-only view of a 4-dimensional vector of integers.
*
* @author Kai Burjack
*/
public interface Vector4ic {
/**
* @return the value of the x component
*/
int x();
/**
* @return the value of the y component
*/
int y();
/**
* @return the value of the z component
*/
int z();
/**
* @return the value of the w component
*/
int w();
/**
* Store this vector into the supplied {@link IntBuffer} at the current
* buffer {@link IntBuffer#position() position}.
* <p>
* This method will not increment the position of the given IntBuffer.
* <p>
* In order to specify the offset into the IntBuffer at which the vector is
* stored, use {@link #get(int, IntBuffer)}, taking the absolute position as
* parameter.
*
* @see #get(int, IntBuffer)
*
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
*/
IntBuffer get(IntBuffer buffer);
/**
* Store this vector into the supplied {@link IntBuffer} starting at the
* specified absolute buffer position/index.
* <p>
* This method will not increment the position of the given IntBuffer.
*
* @param index
* the absolute position into the IntBuffer
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
*/
IntBuffer get(int index, IntBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} at the current
* buffer {@link ByteBuffer#position() position}.
* <p>
* This method will not increment the position of the given ByteBuffer.
* <p>
* In order to specify the offset into the ByteBuffer at which the vector is
* stored, use {@link #get(int, ByteBuffer)}, taking the absolute position
* as parameter.
*
* @see #get(int, ByteBuffer)
*
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
*/
ByteBuffer get(ByteBuffer buffer);
/**
* Store this vector into the supplied {@link ByteBuffer} starting at the
* specified absolute buffer position/index.
* <p>
* This method will not increment the position of the given ByteBuffer.
*
* @param index
* the absolute position into the ByteBuffer
* @param buffer
* will receive the values of this vector in <code>x, y, z, w</code> order
* @return the passed in buffer
*/
ByteBuffer get(int index, ByteBuffer buffer);
/**
* Store this vector at the given off-heap memory address.
* <p>
* This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`.
* <p>
* <em>This method is unsafe as it can result in a crash of the JVM process when the specified address range does not belong to this process.</em>
*
* @param address
* the off-heap address where to store this vector
* @return this
*/
Vector4ic getToAddress(long address);
/**
* Subtract the supplied vector from this one and store the result in
* <code>dest</code>.
*
* @param v
* the vector to subtract from <code>this</code>
* @param dest
* will hold the result
* @return dest
*/
Vector4i sub(Vector4ic v, Vector4i dest);
/**
* Subtract <code>(x, y, z, w)</code> from this and store the result in
* <code>dest</code>.
*
* @param x
* the x component to subtract
* @param y
* the y component to subtract
* @param z
* the z component to subtract
* @param w
* the w component to subtract
* @param dest
* will hold the result
* @return dest
*/
Vector4i sub(int x, int y, int z, int w, Vector4i dest);
/**
* Add the supplied vector to this one and store the result in
* <code>dest</code>.
*
* @param v
* the vector to add
* @param dest
* will hold the result
* @return dest
*/
Vector4i add(Vector4ic v, Vector4i dest);
/**
* Increment the components of this vector by the given values and store the
* result in <code>dest</code>.
*
* @param x
* the x component to add
* @param y
* the y component to add
* @param z
* the z component to add
* @param w
* the w component to add
* @param dest
* will hold the result
* @return dest
*/
Vector4i add(int x, int y, int z, int w, Vector4i dest);
/**
* Multiply this Vector4i component-wise by another Vector4ic and store the
* result in <code>dest</code>.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector4i mul(Vector4ic v, Vector4i dest);
/**
* Divide this Vector4i component-wise by another Vector4ic and store the
* result in <code>dest</code>.
*
* @param v
* the vector to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector4i div(Vector4ic v, Vector4i dest);
/**
* Multiply all components of this {@link Vector4i} by the given scalar
* value and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to multiply by
* @param dest
* will hold the result
* @return dest
*/
Vector4i mul(int scalar, Vector4i dest);
/**
* Divide all components of this {@link Vector4i} by the given scalar value
* and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector4i div(float scalar, Vector4i dest);
/**
* Divide all components of this {@link Vector4i} by the given scalar value
* and store the result in <code>dest</code>.
*
* @param scalar
* the scalar to divide by
* @param dest
* will hold the result
* @return dest
*/
Vector4i div(int scalar, Vector4i dest);
/**
* Return the length squared of this vector.
*
* @return the length squared
*/
long lengthSquared();
/**
* Return the length of this vector.
*
* @return the length
*/
double length();
/**
* Return the distance between this Vector and <code>v</code>.
*
* @param v
* the other vector
* @return the distance
*/
double distance(Vector4ic v);
/**
* Return the distance between <code>this</code> vector and <code>(x, y, z, w)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @param w
* the w component of the other vector
* @return the euclidean distance
*/
double distance(int x, int y, int z, int w);
/**
* Return the grid distance in between (aka 1-Norm, Minkowski or Manhattan distance)
* <code>(x, y)</code>.
*
* @param v
* the other vector
* @return the grid distance
*/
long gridDistance(Vector4ic v);
/**
* Return the grid distance in between (aka 1-Norm, Minkowski or Manhattan distance)
* <code>(x, y)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @param w
* the w component of the other vector
* @return the grid distance
*/
long gridDistance(int x, int y, int z, int w);
/**
* Return the square of the distance between this vector and <code>v</code>.
*
* @param v
* the other vector
* @return the squared of the distance
*/
int distanceSquared(Vector4ic v);
/**
* Return the square of the distance between <code>this</code> vector and
* <code>(x, y, z, w)</code>.
*
* @param x
* the x component of the other vector
* @param y
* the y component of the other vector
* @param z
* the z component of the other vector
* @param w
* the w component of the other vector
* @return the square of the distance
*/
int distanceSquared(int x, int y, int z, int w);
/**
* Compute the dot product (inner product) of this vector and <code>v</code>.
*
* @param v
* the other vector
* @return the dot product
*/
int dot(Vector4ic v);
/**
* Negate this vector and store the result in <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4i negate(Vector4i dest);
/**
* Set the components of <code>dest</code> to be the component-wise minimum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector4i min(Vector4ic v, Vector4i dest);
/**
* Set the components of <code>dest</code> to be the component-wise maximum of this and the other vector.
*
* @param v
* the other vector
* @param dest
* will hold the result
* @return dest
*/
Vector4i max(Vector4ic v, Vector4i dest);
/**
* Get the value of the specified component of this vector.
*
* @param component
* the component, within <code>[0..3]</code>
* @return the value
* @throws IllegalArgumentException if <code>component</code> is not within <code>[0..3]</code>
*/
int get(int component) throws IllegalArgumentException;
/**
* Determine the component with the biggest absolute value.
*
* @return the component index, within <code>[0..3]</code>
*/
int maxComponent();
/**
* Determine the component with the smallest (towards zero) absolute value.
*
* @return the component index, within <code>[0..3]</code>
*/
int minComponent();
/**
* Compute the absolute of each of this vector's components
* and store the result into <code>dest</code>.
*
* @param dest
* will hold the result
* @return dest
*/
Vector4i absolute(Vector4i dest);
/**
* Compare the vector components of <code>this</code> vector with the given <code>(x, y, z, w)</code>
* and return whether all of them are equal.
*
* @param x
* the x component to compare to
* @param y
* the y component to compare to
* @param z
* the z component to compare to
* @param w
* the w component to compare to
* @return <code>true</code> if all the vector components are equal
*/
boolean equals(int x, int y, int z, int w);
}

View file

@ -0,0 +1,14 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
</head>
<body bgcolor="white">
<p>Contains all classes of JOML.</p>
<p>If you like to know more about JOML, please visit:</p>
<ul>
<li><a href="https://github.com/JOML-CI/JOML">Its GitHub project page</a></li>
<li><a href="http://joml-ci.github.io/JOML">Its site on GitHub Pages</a></li>
<li><a href="http://joml-ci.github.io/JOML/apidocs/index.html">The HTML version of this JavaDoc</a></li>
</ul>
</body>
</html>

View file

@ -0,0 +1,41 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml.sampling;
/**
* Callback used for notifying about a new generated 2D sample.
*
* @author Kai Burjack
*/
public interface Callback2d {
/**
* Will be called whenever a new sample with the given coordinates <code>(x, y)</code> is generated.
*
* @param x
* the x coordinate of the new sample point
* @param y
* the y coordinate of the new sample point
*/
void onNewSample(float x, float y);
}

View file

@ -0,0 +1,43 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml.sampling;
/**
* Callback used for notifying about a new generated 3D sample.
*
* @author Kai Burjack
*/
public interface Callback3d {
/**
* Will be called whenever a new sample with the given coordinates <code>(x, y, z)</code> is generated.
*
* @param x
* the x coordinate of the new sample point
* @param y
* the y coordinate of the new sample point
* @param z
* the z coordinate of the new sample point
*/
void onNewSample(float x, float y, float z);
}

View file

@ -0,0 +1,116 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml.sampling;
import java.nio.FloatBuffer;
import com.jozufozu.flywheel.repack.joml.Math;
/**
* Generates various convolution kernels.
*
* @author Kai Burjack
*/
public class Convolution {
/**
* Generate a Gaussian convolution kernel with the given number of rows and columns, and store
* the factors in row-major order in <code>dest</code>.
*
* @param rows
* the number of rows (must be an odd number)
* @param cols
* the number of columns (must be an odd number)
* @param sigma
* the standard deviation of the filter kernel values
* @param dest
* will hold the kernel factors in row-major order
*/
public static void gaussianKernel(int rows, int cols, float sigma, FloatBuffer dest) {
if ((rows & 1) == 0) {
throw new IllegalArgumentException("rows must be an odd number");
}
if ((cols & 1) == 0) {
throw new IllegalArgumentException("cols must be an odd number");
}
if (dest == null) {
throw new IllegalArgumentException("dest must not be null");
}
if (dest.remaining() < rows * cols) {
throw new IllegalArgumentException("dest must have at least " + (rows * cols) + " remaining values");
}
float sum = 0.0f;
int pos = dest.position();
for (int i = 0, y = -(rows - 1) / 2; y <= (rows - 1) / 2; y++) {
for (int x = -(cols - 1) / 2; x <= (cols - 1) / 2; x++, i++) {
float k = (float) Math.exp(-(y * y + x * x) / (2.0 * sigma * sigma));
dest.put(pos + i, k);
sum += k;
}
}
for (int i = 0; i < rows * cols; i++) {
dest.put(pos + i, dest.get(pos + i) / sum);
}
}
/**
* Generate a Gaussian convolution kernel with the given number of rows and columns, and store
* the factors in row-major order in <code>dest</code>.
*
* @param rows
* the number of rows (must be an odd number)
* @param cols
* the number of columns (must be an odd number)
* @param sigma
* the standard deviation of the filter kernel values
* @param dest
* will hold the kernel factors in row-major order
*/
public static void gaussianKernel(int rows, int cols, float sigma, float[] dest) {
if ((rows & 1) == 0) {
throw new IllegalArgumentException("rows must be an odd number");
}
if ((cols & 1) == 0) {
throw new IllegalArgumentException("cols must be an odd number");
}
if (dest == null) {
throw new IllegalArgumentException("dest must not be null");
}
if (dest.length < rows * cols) {
throw new IllegalArgumentException("dest must have a size of at least " + (rows * cols));
}
float sum = 0.0f;
for (int i = 0, y = -(rows - 1) / 2; y <= (rows - 1) / 2; y++) {
for (int x = -(cols - 1) / 2; x <= (cols - 1) / 2; x++, i++) {
float k = (float) Math.exp(-(y * y + x * x) / (2.0 * sigma * sigma));
dest[i] = k;
sum += k;
}
}
for (int i = 0; i < rows * cols; i++) {
dest[i] = dest[i] / sum;
}
}
}

View file

@ -0,0 +1,64 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml.sampling;
/**
* Internal Math class used by the sampling package.
*
* @author Kai Burjack
*/
class Math extends com.jozufozu.flywheel.repack.joml.Math {
static final double PI = java.lang.Math.PI;
static final double PI2 = PI * 2.0;
static final double PIHalf = PI * 0.5;
private static final double ONE_OVER_PI = 1.0 / PI;
private static final double s5 = Double.longBitsToDouble(4523227044276562163L);
private static final double s4 = Double.longBitsToDouble(-4671934770969572232L);
private static final double s3 = Double.longBitsToDouble(4575957211482072852L);
private static final double s2 = Double.longBitsToDouble(-4628199223918090387L);
private static final double s1 = Double.longBitsToDouble(4607182418589157889L);
/**
* Reference: <a href=
* "http://www.java-gaming.org/topics/joml-1-8-0-release/37491/msg/361815/view.html#msg361815">http://www.java-gaming.org/</a>
*
* @author roquendm
*/
static double sin_roquen_9(double v) {
double i = java.lang.Math.rint(v * ONE_OVER_PI);
double x = v - i * Math.PI;
double qs = 1 - 2 * ((int) i & 1);
double x2 = x * x;
double r;
x = qs * x;
r = s5;
r = r * x2 + s4;
r = r * x2 + s3;
r = r * x2 + s2;
r = r * x2 + s1;
return x * r;
}
}

View file

@ -0,0 +1,161 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml.sampling;
import java.util.ArrayList;
import com.jozufozu.flywheel.repack.joml.Random;
import com.jozufozu.flywheel.repack.joml.Vector2f;
/**
* Generates Poisson samples.
* <p>
* The algorithm implemented here is based on <a href= "http://www.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf">Fast Poisson Disk Sampling in Arbitrary
* Dimensions</a>.
*
* @author Kai Burjack
*/
public class PoissonSampling {
/**
* Generates Poisson samples on a disk.
* <p>
* The algorithm implemented here is based on <a href= "http://www.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf">Fast Poisson Disk Sampling in Arbitrary
* Dimensions</a>.
*
* @author Kai Burjack
*/
public static class Disk {
private final Vector2f[] grid;
private final float diskRadius;
private final float diskRadiusSquared;
private final float minDist;
private final float minDistSquared;
private final float cellSize;
private final int numCells;
private final Random rnd;
private final ArrayList processList;
/**
* Create a new instance of {@link Disk} which computes poisson-distributed samples on a disk with the given radius <code>diskRadius</code> and notifies the given
* <code>callback</code> for each found sample point.
* <p>
* The samples are distributed evenly on the disk with a minimum distance to one another of at least <code>minDist</code>.
*
* @param seed
* the seed to initialize the random number generator with
* @param diskRadius
* the disk radius
* @param minDist
* the minimum distance between any two generated samples
* @param k
* determines how many samples are tested before rejection. Higher values produce better results. Typical values are 20 to 30
* @param callback
* will be notified about each sample point
*/
public Disk(long seed, float diskRadius, float minDist, int k, Callback2d callback) {
this.diskRadius = diskRadius;
this.diskRadiusSquared = diskRadius * diskRadius;
this.minDist = minDist;
this.minDistSquared = minDist * minDist;
this.rnd = new Random(seed);
this.cellSize = minDist / (float) Math.sqrt(2.0);
this.numCells = (int) ((diskRadius * 2) / cellSize) + 1;
this.grid = new Vector2f[numCells * numCells];
this.processList = new ArrayList();
compute(k, callback);
}
private void compute(int k, Callback2d callback) {
float x, y;
do {
x = rnd.nextFloat() * 2.0f - 1.0f;
y = rnd.nextFloat() * 2.0f - 1.0f;
} while (x * x + y * y > 1.0f);
Vector2f initial = new Vector2f(x, y);
processList.add(initial);
callback.onNewSample(initial.x, initial.y);
insert(initial);
while (!processList.isEmpty()) {
int i = rnd.nextInt(processList.size());
Vector2f sample = (Vector2f) processList.get(i);
boolean found = false;
search: for (int s = 0; s < k; s++) {
float angle = rnd.nextFloat() * (float) Math.PI2;
float radius = minDist * (rnd.nextFloat() + 1.0f);
x = (float) (radius * Math.sin_roquen_9(angle + Math.PIHalf));
y = (float) (radius * Math.sin_roquen_9(angle));
x += sample.x;
y += sample.y;
if (x * x + y * y > diskRadiusSquared)
continue search;
if (!searchNeighbors(x, y)) {
found = true;
callback.onNewSample(x, y);
Vector2f f = new Vector2f(x, y);
processList.add(f);
insert(f);
break;
}
}
if (!found) {
processList.remove(i);
}
}
}
private boolean searchNeighbors(float px, float py) {
int row = (int) ((py + diskRadius) / cellSize);
int col = (int) ((px + diskRadius) / cellSize);
if (grid[row * numCells + col] != null)
return true;
int minX = Math.max(0, col - 1);
int minY = Math.max(0, row - 1);
int maxX = Math.min(col + 1, numCells - 1);
int maxY = Math.min(row + 1, numCells - 1);
for (int y = minY; y <= maxY; y++) {
for (int x = minX; x <= maxX; x++) {
Vector2f v = grid[y * numCells + x];
if (v != null) {
float dx = v.x - px;
float dy = v.y - py;
if (dx * dx + dy * dy < minDistSquared) {
return true;
}
}
}
}
return false;
}
private void insert(Vector2f p) {
int row = (int) ((p.y + diskRadius) / cellSize);
int col = (int) ((p.x + diskRadius) / cellSize);
grid[row * numCells + col] = p;
}
}
}

View file

@ -0,0 +1,101 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml.sampling;
import com.jozufozu.flywheel.repack.joml.Random;
/**
* Creates samples on a spiral around a center point.
*
* @author Kai Burjack
*/
public class SpiralSampling {
private final Random rnd;
/**
* Create a new instance of {@link SpiralSampling} and initialize the random number generator with the given <code>seed</code>.
*
* @param seed
* the seed to initialize the random number generator with
*/
public SpiralSampling(long seed) {
rnd = new Random(seed);
}
/**
* Create <code>numSamples</code> number of samples on a spiral with maximum radius <code>radius</code> around the center using <code>numRotations</code> number of rotations
* along the spiral, and call the given <code>callback</code> for each sample generated.
* <p>
* The generated sample points are distributed with equal angle differences around the spiral, so they concentrate towards the center.
*
* @param radius
* the maximum radius of the spiral
* @param numRotations
* the number of rotations of the spiral
* @param numSamples
* the number of samples to generate
* @param callback
* will be called for each sample generated
*/
public void createEquiAngle(float radius, int numRotations, int numSamples, Callback2d callback) {
for (int sample = 0; sample < numSamples; sample++) {
float angle = 2.0f * (float) Math.PI * (sample * numRotations) / numSamples;
float r = radius * sample / (numSamples - 1);
float x = (float) Math.sin_roquen_9(angle + 0.5f * (float) Math.PI) * r;
float y = (float) Math.sin_roquen_9(angle) * r;
callback.onNewSample(x, y);
}
}
/**
* Create <code>numSamples</code> number of samples on a spiral with maximum radius <code>radius</code> around the center using <code>numRotations</code> number of rotations
* along the spiral, and call the given <code>callback</code> for each sample generated.
* <p>
* The generated sample points are distributed with equal angle differences around the spiral, so they concentrate towards the center.
* <p>
* Additionally, the radius of each sample point is jittered by the given <code>jitter</code> factor.
*
* @param radius
* the maximum radius of the spiral
* @param numRotations
* the number of rotations of the spiral
* @param numSamples
* the number of samples to generate
* @param jitter
* the factor by which the radius of each sample point is jittered. Possible values are <code>[0..1]</code>
* @param callback
* will be called for each sample generated
*/
public void createEquiAngle(float radius, int numRotations, int numSamples, float jitter, Callback2d callback) {
float spacing = radius / numRotations;
for (int sample = 0; sample < numSamples; sample++) {
float angle = 2.0f * (float) Math.PI * (sample * numRotations) / numSamples;
float r = radius * sample / (numSamples - 1) + (rnd.nextFloat() * 2.0f - 1.0f) * spacing * jitter;
float x = (float) Math.sin_roquen_9(angle + 0.5f * (float) Math.PI) * r;
float y = (float) Math.sin_roquen_9(angle) * r;
callback.onNewSample(x, y);
}
}
}

View file

@ -0,0 +1,93 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml.sampling;
import com.jozufozu.flywheel.repack.joml.Random;
/**
* Creates samples on a unit quad using an NxN strata grid.
*
* @author Kai Burjack
*/
public class StratifiedSampling {
private final Random rnd;
/**
* Create a new instance of {@link StratifiedSampling} and initialize the random number generator with the given
* <code>seed</code>.
*
* @param seed
* the seed to initialize the random number generator with
*/
public StratifiedSampling(long seed) {
this.rnd = new Random(seed);
}
/**
* Generate <code>n * n</code> random sample positions in the unit square of <code>x, y = [-1..+1]</code>.
* <p>
* Each sample within its stratum is distributed randomly.
*
* @param n
* the number of strata in each dimension
* @param callback
* will be called for each generated sample position
*/
public void generateRandom(int n, Callback2d callback) {
for (int y = 0; y < n; y++) {
for (int x = 0; x < n; x++) {
float sampleX = (rnd.nextFloat() / n + (float) x / n) * 2.0f - 1.0f;
float sampleY = (rnd.nextFloat() / n + (float) y / n) * 2.0f - 1.0f;
callback.onNewSample(sampleX, sampleY);
}
}
}
/**
* Generate <code>n * n</code> random sample positions in the unit square of <code>x, y = [-1..+1]</code>.
* <p>
* Each sample within its stratum is confined to be within <code>[-centering/2..1-centering]</code> of its stratum.
*
* @param n
* the number of strata in each dimension
* @param centering
* determines how much the random samples in each stratum are confined to be near the center of the
* stratum. Possible values are <code>[0..1]</code>
* @param callback
* will be called for each generated sample position
*/
public void generateCentered(int n, float centering, Callback2d callback) {
float start = centering * 0.5f;
float end = 1.0f - centering;
for (int y = 0; y < n; y++) {
for (int x = 0; x < n; x++) {
float sampleX = ((start + rnd.nextFloat() * end) / n + (float) x / n) * 2.0f - 1.0f;
float sampleY = ((start + rnd.nextFloat() * end) / n + (float) y / n) * 2.0f - 1.0f;
callback.onNewSample(sampleX, sampleY);
}
}
}
}

View file

@ -0,0 +1,121 @@
/*
* The MIT License
*
* Copyright (c) 2016-2021 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 com.jozufozu.flywheel.repack.joml.sampling;
import com.jozufozu.flywheel.repack.joml.Random;
/**
* Generates uniform samples.
*
* @author Kai Burjack
*/
public class UniformSampling {
/**
* Generates uniform samples on a unit disk.
*
* @author Kai Burjack
*/
public static class Disk {
private final Random rnd;
/**
* Create a new instance of {@link Disk}, initialize the random number generator with the given <code>seed</code> and generate <code>numSamples</code> number of sample
* positions on the unit disk, and call the given <code>callback</code> for each sample generate.
*
* @param seed
* the seed to initialize the random number generator with
* @param numSamples
* the number of samples to generate
* @param callback
* will be called for each sample generated
*/
public Disk(long seed, int numSamples, Callback2d callback) {
this.rnd = new Random(seed);
generate(numSamples, callback);
}
private void generate(int numSamples, Callback2d callback) {
for (int i = 0; i < numSamples; i++) {
float r = rnd.nextFloat();
float a = rnd.nextFloat() * 2.0f * (float) Math.PI;
float sqrtR = (float) Math.sqrt(r);
float x = sqrtR * (float) Math.sin_roquen_9(a + 0.5 * Math.PI);
float y = sqrtR * (float) Math.sin_roquen_9(a);
callback.onNewSample(x, y);
}
}
}
/**
* Generates uniform samples on a unit sphere.
*
* @author Kai Burjack
*/
public static class Sphere {
private final Random rnd;
/**
* Create a new instance of {@link Sphere}, initialize the random number generator with the given <code>seed</code> and generate <code>numSamples</code> number of sample
* positions on the unit sphere, and call the given <code>callback</code> for each sample generate.
*
* @param seed
* the seed to initialize the random number generator with
* @param numSamples
* the number of samples to generate
* @param callback
* will be called for each sample generated
*/
public Sphere(long seed, int numSamples, Callback3d callback) {
this.rnd = new Random(seed);
generate(numSamples, callback);
}
/**
* Create <code>numSamples</code> number of samples which are uniformly distributed on a unit sphere, and call the given <code>callback</code> for each sample generated.
* <p>
* Reference: <a href="http://mathworld.wolfram.com/SpherePointPicking.html">http://mathworld.wolfram.com/</a>
*
* @param numSamples
* the number of samples to generate
* @param callback
* will be called for each sample generated
*/
public void generate(int numSamples, Callback3d callback) {
for (int i = 0; i < numSamples;) {
float x1 = rnd.nextFloat() * 2.0f - 1.0f;
float x2 = rnd.nextFloat() * 2.0f - 1.0f;
if (x1 * x1 + x2 * x2 >= 1.0f)
continue;
float sqrt = (float) Math.sqrt(1.0 - x1 * x1 - x2 * x2);
float x = 2 * x1 * sqrt;
float y = 2 * x2 * sqrt;
float z = 1.0f - 2.0f * (x1 * x1 + x2 * x2);
callback.onNewSample(x, y, z);
i++;
}
}
}
}

View file

@ -0,0 +1,8 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
</head>
<body bgcolor="white">
<p>Contains classes for generating sampling patterns.</p>
</body>
</html>