mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-06 04:16:36 +01:00
Use external JOML
- Use JOML from its official Maven source instead of bundling classes - Organize imports
This commit is contained in:
parent
3900297186
commit
e7fd1c6178
43 changed files with 71 additions and 43462 deletions
14
build.gradle
14
build.gradle
|
@ -113,7 +113,7 @@ repositories {
|
|||
mavenCentral()
|
||||
}
|
||||
|
||||
// Fix for loading non-mod libraries in dev-env, used for miniball.
|
||||
// Fix for loading non-mod libraries in dev-env, used for JOML and Miniball.
|
||||
// https://gist.github.com/SizableShrimp/66b22f1b24c255e1491c8d98d3f11f83
|
||||
// v--------------------------------------------------------------------v
|
||||
configurations {
|
||||
|
@ -131,14 +131,18 @@ minecraft.runs.all {
|
|||
dependencies {
|
||||
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
|
||||
|
||||
jarJar(group: 'com.dreizak', name: 'miniball', version: "1.0.3") {
|
||||
jarJar.ranged(it, "[1.0,2.0)")
|
||||
jarJar('org.joml:joml:1.10.5') {
|
||||
jarJar.ranged(it, '[1.10.0,1.11.0)')
|
||||
}
|
||||
library "com.dreizak:miniball:1.0.3"
|
||||
library 'org.joml:joml:1.10.5'
|
||||
|
||||
jarJar('com.dreizak:miniball:1.0.3') {
|
||||
jarJar.ranged(it, '[1.0,2.0)')
|
||||
}
|
||||
library 'com.dreizak:miniball:1.0.3'
|
||||
|
||||
// switch to implementation for debugging
|
||||
compileOnly fg.deobf("maven.modrinth:starlight-forge:1.0.2+1.18.2")
|
||||
|
||||
compileOnly fg.deobf("maven.modrinth:rubidium:0.5.3a")
|
||||
compileOnly fg.deobf("maven.modrinth:oculus:1.18.2-1.2.5a")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.jozufozu.flywheel.api.instance;
|
||||
|
||||
import com.jozufozu.flywheel.util.joml.FrustumIntersection;
|
||||
import org.joml.FrustumIntersection;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.jozufozu.flywheel.backend.gl.shader;
|
||||
|
||||
import static org.lwjgl.opengl.GL20.*;
|
||||
import static org.lwjgl.opengl.GL20.glDeleteProgram;
|
||||
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
|
||||
import static org.lwjgl.opengl.GL20.glUniform1i;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.GlObject;
|
||||
|
|
|
@ -7,6 +7,8 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.joml.FrustumIntersection;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
|
@ -16,7 +18,6 @@ import com.jozufozu.flywheel.backend.instancing.ratelimit.NonLimiter;
|
|||
import com.jozufozu.flywheel.config.FlwConfig;
|
||||
import com.jozufozu.flywheel.core.RenderContext;
|
||||
import com.jozufozu.flywheel.light.LightUpdater;
|
||||
import com.jozufozu.flywheel.util.joml.FrustumIntersection;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend.instancing;
|
|||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
||||
import com.jozufozu.flywheel.backend.instancing.effect.Effect;
|
||||
import com.jozufozu.flywheel.config.FlwCommands;
|
||||
import com.jozufozu.flywheel.config.FlwConfig;
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.jozufozu.flywheel.backend.instancing.blockentity;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.FrustumIntersection;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
|
@ -10,7 +12,6 @@ import com.jozufozu.flywheel.api.instancer.InstancerManager;
|
|||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||
import com.jozufozu.flywheel.util.joml.FrustumIntersection;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.compile;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_TRUE;
|
||||
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
|
||||
import static org.lwjgl.opengl.GL20.GL_TRUE;
|
||||
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
|
||||
import static org.lwjgl.opengl.GL20.glGetProgrami;
|
||||
import static org.lwjgl.opengl.GL20.glLinkProgram;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.entity;
|
||||
|
||||
import org.joml.FrustumIntersection;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerManager;
|
||||
|
@ -8,7 +10,6 @@ import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceM
|
|||
import com.jozufozu.flywheel.light.LightListener;
|
||||
import com.jozufozu.flywheel.light.TickingLightListener;
|
||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||
import com.jozufozu.flywheel.util.joml.FrustumIntersection;
|
||||
import com.mojang.math.Vector3f;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
|
|
@ -1,7 +1,22 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.indirect;
|
||||
|
||||
import static org.lwjgl.opengl.GL15.glBindBuffer;
|
||||
import static org.lwjgl.opengl.GL15.glDeleteBuffers;
|
||||
import static org.lwjgl.opengl.GL15.nglDeleteBuffers;
|
||||
import static org.lwjgl.opengl.GL30.GL_MAP_FLUSH_EXPLICIT_BIT;
|
||||
import static org.lwjgl.opengl.GL30.GL_MAP_WRITE_BIT;
|
||||
import static org.lwjgl.opengl.GL40.GL_DRAW_INDIRECT_BUFFER;
|
||||
import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER;
|
||||
import static org.lwjgl.opengl.GL44.GL_DYNAMIC_STORAGE_BIT;
|
||||
import static org.lwjgl.opengl.GL44.GL_MAP_PERSISTENT_BIT;
|
||||
import static org.lwjgl.opengl.GL44.nglBindBuffersRange;
|
||||
import static org.lwjgl.opengl.GL45.glCopyNamedBufferSubData;
|
||||
import static org.lwjgl.opengl.GL45.glCreateBuffers;
|
||||
import static org.lwjgl.opengl.GL46.*;
|
||||
import static org.lwjgl.opengl.GL45.glFlushMappedNamedBufferRange;
|
||||
import static org.lwjgl.opengl.GL45.glNamedBufferStorage;
|
||||
import static org.lwjgl.opengl.GL45.nglCreateBuffers;
|
||||
import static org.lwjgl.opengl.GL45.nglMapNamedBufferRange;
|
||||
import static org.lwjgl.opengl.GL45.nglNamedBufferSubData;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
import org.lwjgl.system.Pointer;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.indirect;
|
||||
|
||||
import static org.lwjgl.opengl.GL30.glBindVertexArray;
|
||||
import static org.lwjgl.opengl.GL30.glDeleteVertexArrays;
|
||||
import static org.lwjgl.opengl.GL42.GL_COMMAND_BARRIER_BIT;
|
||||
import static org.lwjgl.opengl.GL42.glMemoryBarrier;
|
||||
import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BARRIER_BIT;
|
||||
import static org.lwjgl.opengl.GL46.glBindVertexArray;
|
||||
import static org.lwjgl.opengl.GL46.glCreateVertexArrays;
|
||||
import static org.lwjgl.opengl.GL46.glDeleteVertexArrays;
|
||||
import static org.lwjgl.opengl.GL46.glDispatchCompute;
|
||||
import static org.lwjgl.opengl.GL46.glEnableVertexArrayAttrib;
|
||||
import static org.lwjgl.opengl.GL46.glVertexArrayElementBuffer;
|
||||
import static org.lwjgl.opengl.GL46.glVertexArrayVertexBuffer;
|
||||
import static org.lwjgl.opengl.GL43.glDispatchCompute;
|
||||
import static org.lwjgl.opengl.GL45.glCreateVertexArrays;
|
||||
import static org.lwjgl.opengl.GL45.glEnableVertexArrayAttrib;
|
||||
import static org.lwjgl.opengl.GL45.glVertexArrayElementBuffer;
|
||||
import static org.lwjgl.opengl.GL45.glVertexArrayVertexBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
|
|
|
@ -16,9 +16,9 @@ import com.jozufozu.flywheel.backend.instancing.Engine;
|
|||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.TaskExecutor;
|
||||
import com.jozufozu.flywheel.core.RenderContext;
|
||||
import com.jozufozu.flywheel.core.context.SimpleContext;
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
import com.jozufozu.flywheel.util.FlwUtil;
|
||||
import com.jozufozu.flywheel.core.context.SimpleContext;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.Camera;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.FrustumIntersection;
|
||||
|
||||
import com.jozufozu.flywheel.util.MatrixUtil;
|
||||
import com.jozufozu.flywheel.util.joml.FrustumIntersection;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
|
@ -23,7 +23,7 @@ public record RenderContext(LevelRenderer renderer, ClientLevel level, PoseStack
|
|||
}
|
||||
|
||||
public static FrustumIntersection createCuller(Matrix4f viewProjection, float camX, float camY, float camZ) {
|
||||
com.jozufozu.flywheel.util.joml.Matrix4f proj = MatrixUtil.toJoml(viewProjection);
|
||||
org.joml.Matrix4f proj = MatrixUtil.toJoml(viewProjection);
|
||||
|
||||
proj.translate(camX, camY, camZ);
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@ package com.jozufozu.flywheel.core.hardcoded;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
|
@ -9,8 +12,6 @@ import com.jozufozu.flywheel.core.model.Mesh;
|
|||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||
|
||||
public class ModelPart implements Mesh {
|
||||
private final int vertexCount;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
||||
import com.jozufozu.flywheel.core.QuadConverter;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||
|
||||
/**
|
||||
* A holder for arbitrary vertex data that can be written to memory or a vertex list.
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.lang.reflect.Field;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.dreizak.miniball.highdim.Miniball;
|
||||
|
@ -17,7 +18,6 @@ import com.jozufozu.flywheel.api.vertex.VertexType;
|
|||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||
|
||||
public class SimpleMesh implements Mesh {
|
||||
private final VertexType vertexType;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package com.jozufozu.flywheel.core.source;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
|
|
@ -6,10 +6,10 @@ import java.util.Set;
|
|||
import java.util.WeakHashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.joml.Math;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.util.joml.Math;
|
||||
import com.jozufozu.flywheel.util.joml.Matrix4f;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
public class FlwUtil {
|
||||
|
|
|
@ -63,7 +63,7 @@ public class MatrixUtil {
|
|||
buf.putFloat(m.flywheel$m22());
|
||||
}
|
||||
|
||||
public static void store(Matrix4f matrix, com.jozufozu.flywheel.util.joml.Matrix4f jomlMatrix) {
|
||||
public static void store(Matrix4f matrix, org.joml.Matrix4f jomlMatrix) {
|
||||
Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix;
|
||||
jomlMatrix.set(
|
||||
m.flywheel$m00(), m.flywheel$m10(), m.flywheel$m20(), m.flywheel$m30(),
|
||||
|
@ -73,9 +73,9 @@ public class MatrixUtil {
|
|||
);
|
||||
}
|
||||
|
||||
public static com.jozufozu.flywheel.util.joml.Matrix4f toJoml(Matrix4f matrix) {
|
||||
public static org.joml.Matrix4f toJoml(Matrix4f matrix) {
|
||||
Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix;
|
||||
return new com.jozufozu.flywheel.util.joml.Matrix4f(
|
||||
return new org.joml.Matrix4f(
|
||||
m.flywheel$m00(), m.flywheel$m10(), m.flywheel$m20(), m.flywheel$m30(),
|
||||
m.flywheel$m01(), m.flywheel$m11(), m.flywheel$m21(), m.flywheel$m31(),
|
||||
m.flywheel$m02(), m.flywheel$m12(), m.flywheel$m22(), m.flywheel$m32(),
|
||||
|
@ -96,7 +96,7 @@ public class MatrixUtil {
|
|||
MemoryUtil.memPutFloat(ptr + 32, m.flywheel$m22());
|
||||
}
|
||||
|
||||
public static void store(Matrix3f matrix, com.jozufozu.flywheel.util.joml.Matrix3f jomlMatrix) {
|
||||
public static void store(Matrix3f matrix, org.joml.Matrix3f jomlMatrix) {
|
||||
Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix;
|
||||
jomlMatrix.set(
|
||||
m.flywheel$m00(), m.flywheel$m10(), m.flywheel$m20(),
|
||||
|
@ -105,9 +105,9 @@ public class MatrixUtil {
|
|||
);
|
||||
}
|
||||
|
||||
public static com.jozufozu.flywheel.util.joml.Matrix3f toJoml(Matrix3f matrix) {
|
||||
public static org.joml.Matrix3f toJoml(Matrix3f matrix) {
|
||||
Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix;
|
||||
return new com.jozufozu.flywheel.util.joml.Matrix3f(
|
||||
return new org.joml.Matrix3f(
|
||||
m.flywheel$m00(), m.flywheel$m10(), m.flywheel$m20(),
|
||||
m.flywheel$m01(), m.flywheel$m11(), m.flywheel$m21(),
|
||||
m.flywheel$m02(), m.flywheel$m12(), m.flywheel$m22()
|
||||
|
|
|
@ -1,543 +0,0 @@
|
|||
/*
|
||||
* 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.util.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 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 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 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 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 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 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* 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.util.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);
|
||||
}
|
||||
}
|
|
@ -1,992 +0,0 @@
|
|||
/*
|
||||
* 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.util.joml;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
/**
|
||||
* 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 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;
|
||||
}
|
||||
|
||||
public void getCorners(ByteBuffer buffer) {
|
||||
|
||||
Vector3f scratch = new Vector3f();
|
||||
Vector3f result = new Vector3f();
|
||||
|
||||
long addr = MemoryUtil.memAddress(buffer);
|
||||
planeIntersect(planes[0], planes[2], planes[4], result, scratch); result.getToAddress(addr);
|
||||
planeIntersect(planes[0], planes[2], planes[5], result, scratch); result.getToAddress(addr + 12);
|
||||
planeIntersect(planes[0], planes[3], planes[4], result, scratch); result.getToAddress(addr + 24);
|
||||
planeIntersect(planes[0], planes[3], planes[5], result, scratch); result.getToAddress(addr + 36);
|
||||
planeIntersect(planes[1], planes[2], planes[4], result, scratch); result.getToAddress(addr + 48);
|
||||
planeIntersect(planes[1], planes[2], planes[5], result, scratch); result.getToAddress(addr + 60);
|
||||
planeIntersect(planes[1], planes[3], planes[4], result, scratch); result.getToAddress(addr + 72);
|
||||
planeIntersect(planes[1], planes[3], planes[5], result, scratch); result.getToAddress(addr + 84);
|
||||
}
|
||||
|
||||
private Vector3f planeIntersect(Vector4f a, Vector4f b, Vector4f c, Vector3f result, Vector3f scratch) {
|
||||
// Formula used
|
||||
// d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
|
||||
//P = ---------------------------------------------------------------------
|
||||
// N1 . ( N2 * N3 )
|
||||
//
|
||||
// Note: N refers to the normal, d refers to the displacement. '.' means dot product. '*' means cross product
|
||||
|
||||
float f = result.set(b.x, b.y, b.z).cross(c.x, c.y, c.z).dot(a.x, a.y, a.z);
|
||||
|
||||
result.set(0);
|
||||
scratch.set(b.x, b.y, b.z).cross(c.x, c.y, c.z).mul(a.z);
|
||||
result.add(scratch);
|
||||
scratch.set(c.x, c.y, c.z).cross(a.x, a.y, a.z).mul(b.z);
|
||||
result.add(scratch);
|
||||
scratch.set(a.x, a.y, a.z).cross(b.x, b.y, b.z).mul(c.z);
|
||||
result.add(scratch);
|
||||
|
||||
return result.div(f);
|
||||
}
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
/*
|
||||
* 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.util.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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,571 +0,0 @@
|
|||
/*
|
||||
* 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.util.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=<n></code>, where <n> 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) {
|
||||
if (Options.FASTMATH) {
|
||||
if (Options.SIN_LOOKUP)
|
||||
return sin_theagentd_lookup(rad);
|
||||
return (float) sin_roquen_newk(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
|
@ -1,186 +0,0 @@
|
|||
/*
|
||||
* 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.util.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
|
@ -1,185 +0,0 @@
|
|||
/*
|
||||
* 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.util.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
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* 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.util.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();
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,354 +0,0 @@
|
|||
/*
|
||||
* 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.util.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
|
@ -1,399 +0,0 @@
|
|||
/*
|
||||
* 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.util.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;
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* 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.util.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;
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* 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.util.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;
|
||||
}
|
||||
|
||||
}
|
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
|
@ -1,805 +0,0 @@
|
|||
/*
|
||||
* 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.util.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 <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.
|
||||
*
|
||||
* @param dest
|
||||
* will hold the result
|
||||
* @return dest
|
||||
*/
|
||||
Vector4f get(Vector4f 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);
|
||||
|
||||
}
|
|
@ -5,6 +5,9 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.FrustumIntersection;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import com.jozufozu.flywheel.api.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
|
@ -19,8 +22,6 @@ import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
|||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||
import com.jozufozu.flywheel.util.joml.FrustumIntersection;
|
||||
import com.jozufozu.flywheel.util.joml.Vector3f;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
|
Loading…
Reference in a new issue