From e7fd1c617802907c7b9438f5d93fb3120798bd06 Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Wed, 29 Mar 2023 22:03:28 -0700 Subject: [PATCH] Use external JOML - Use JOML from its official Maven source instead of bundling classes - Organize imports --- build.gradle | 14 +- .../flywheel/api/instance/Instance.java | 2 +- .../flywheel/backend/gl/shader/GlProgram.java | 4 +- .../backend/instancing/InstanceManager.java | 3 +- .../instancing/InstancedRenderDispatcher.java | 1 - .../blockentity/BlockEntityInstance.java | 3 +- .../instancing/compile/CompileUtil.java | 2 +- .../instancing/entity/EntityInstance.java | 3 +- .../instancing/indirect/IndirectBuffers.java | 17 +- .../indirect/IndirectCullingGroup.java | 14 +- .../instancing/indirect/IndirectEngine.java | 2 +- .../jozufozu/flywheel/core/RenderContext.java | 4 +- .../flywheel/core/hardcoded/ModelPart.java | 5 +- .../jozufozu/flywheel/core/model/Mesh.java | 3 +- .../flywheel/core/model/ModelUtil.java | 2 +- .../flywheel/core/model/SimpleMesh.java | 5 +- .../flywheel/core/source/SourceFile.java | 6 +- .../com/jozufozu/flywheel/util/FlwUtil.java | 4 +- .../jozufozu/flywheel/util/MatrixUtil.java | 12 +- .../flywheel/util/joml/AxisAngle4f.java | 543 - .../util/joml/ConfigurationException.java | 36 - .../util/joml/FrustumIntersection.java | 992 - .../flywheel/util/joml/FrustumRayBuilder.java | 154 - .../com/jozufozu/flywheel/util/joml/Math.java | 571 - .../jozufozu/flywheel/util/joml/Matrix3f.java | 4788 ----- .../flywheel/util/joml/Matrix3fStack.java | 186 - .../flywheel/util/joml/Matrix3fc.java | 2169 --- .../jozufozu/flywheel/util/joml/Matrix4f.java | 15320 ---------------- .../flywheel/util/joml/Matrix4fStack.java | 185 - .../flywheel/util/joml/Matrix4fc.java | 5926 ------ .../jozufozu/flywheel/util/joml/MemUtil.java | 2034 -- .../jozufozu/flywheel/util/joml/Options.java | 116 - .../flywheel/util/joml/Quaternionf.java | 2565 --- .../util/joml/QuaternionfInterpolator.java | 354 - .../flywheel/util/joml/Quaternionfc.java | 1500 -- .../util/joml/RayAabIntersection.java | 399 - .../flywheel/util/joml/RoundingMode.java | 60 - .../jozufozu/flywheel/util/joml/Runtime.java | 148 - .../jozufozu/flywheel/util/joml/Vector3f.java | 1827 -- .../flywheel/util/joml/Vector3fc.java | 1003 - .../jozufozu/flywheel/util/joml/Vector4f.java | 1741 -- .../flywheel/util/joml/Vector4fc.java | 805 - .../vanilla/effect/ExampleEffect.java | 5 +- 43 files changed, 71 insertions(+), 43462 deletions(-) delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/AxisAngle4f.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/ConfigurationException.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/FrustumIntersection.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/FrustumRayBuilder.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Math.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Matrix3f.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Matrix3fStack.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Matrix3fc.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Matrix4f.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Matrix4fStack.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Matrix4fc.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/MemUtil.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Options.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Quaternionf.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/QuaternionfInterpolator.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Quaternionfc.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/RayAabIntersection.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/RoundingMode.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Runtime.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Vector3f.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Vector3fc.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Vector4f.java delete mode 100644 src/main/java/com/jozufozu/flywheel/util/joml/Vector4fc.java diff --git a/build.gradle b/build.gradle index c7f9b0696..60cd5e602 100644 --- a/build.gradle +++ b/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") diff --git a/src/main/java/com/jozufozu/flywheel/api/instance/Instance.java b/src/main/java/com/jozufozu/flywheel/api/instance/Instance.java index c52837e45..89ab8e959 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instance/Instance.java +++ b/src/main/java/com/jozufozu/flywheel/api/instance/Instance.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java index edc21b543..2a8c387d5 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java index b38db6b34..7b92033c2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index 2695ac4d2..ac962230d 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java index 7cda44ec0..630a3b830 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/CompileUtil.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/CompileUtil.java index 14a4631a4..bbf16226c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/CompileUtil.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/compile/CompileUtil.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java index 352aa832b..125fc6718 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectBuffers.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectBuffers.java index 2c9f5f7d1..a76b661fb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectBuffers.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectBuffers.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java index 1e042eaff..acfd540ad 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectCullingGroup.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java index 3b17cd3e4..5a30d526a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/core/RenderContext.java b/src/main/java/com/jozufozu/flywheel/core/RenderContext.java index f6c99b41a..21125364a 100644 --- a/src/main/java/com/jozufozu/flywheel/core/RenderContext.java +++ b/src/main/java/com/jozufozu/flywheel/core/RenderContext.java @@ -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); diff --git a/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java b/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java index 8e29f75ee..d633b074a 100644 --- a/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java +++ b/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java b/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java index bfa7adb55..7abae09cb 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java @@ -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. diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java index 546846c60..bb2deb571 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java b/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java index 5d2a6236c..cd901b6ad 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java b/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java index 4e6e33c1d..7c30d67c8 100644 --- a/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java +++ b/src/main/java/com/jozufozu/flywheel/core/source/SourceFile.java @@ -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; diff --git a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java index c8e31702a..a1d8ec095 100644 --- a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java @@ -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 { diff --git a/src/main/java/com/jozufozu/flywheel/util/MatrixUtil.java b/src/main/java/com/jozufozu/flywheel/util/MatrixUtil.java index dbd1c7b12..57b96de79 100644 --- a/src/main/java/com/jozufozu/flywheel/util/MatrixUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/MatrixUtil.java @@ -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() diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/AxisAngle4f.java b/src/main/java/com/jozufozu/flywheel/util/joml/AxisAngle4f.java deleted file mode 100644 index 9c565514c..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/AxisAngle4f.java +++ /dev/null @@ -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. - *

- * 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 (0, 0, 1). - */ - public AxisAngle4f() { - z = 1.0f; - } - - /** - * Create a new {@link AxisAngle4f} with the same values of a. - * - * @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}. - *

- * Reference: http://www.euclideanspace.com - * - * @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 a. - * - * @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}. - *

- * Reference: http://www.euclideanspace.com - * - * @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}. - *

- * Reference: http://www.euclideanspace.com - * - * @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. - *

- * 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 dest. - * - * @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 dest. - * - * @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}. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string " 0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this {@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(); - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/ConfigurationException.java b/src/main/java/com/jozufozu/flywheel/util/joml/ConfigurationException.java deleted file mode 100644 index 134865954..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/ConfigurationException.java +++ /dev/null @@ -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); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/FrustumIntersection.java b/src/main/java/com/jozufozu/flywheel/util/joml/FrustumIntersection.java deleted file mode 100644 index 30e9dc05a..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/FrustumIntersection.java +++ /dev/null @@ -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}. - *

- * 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 x=-1 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 x=1 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 y=-1 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 y=1 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 z=-1 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 z=1 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 x=-1 when using the identity frustum. - */ - public static final int PLANE_MASK_NX = 1<x=1 when using the identity frustum. - */ - public static final int PLANE_MASK_PX = 1<y=-1 when using the identity frustum. - */ - public static final int PLANE_MASK_NY = 1<y=1 when using the identity frustum. - */ - public static final int PLANE_MASK_PY = 1<z=-1 when using the identity frustum. - */ - public static final int PLANE_MASK_NZ = 1<z=1 when using the identity frustum. - */ - public static final int PLANE_MASK_PZ = 1< - * 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. - *

- * 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. - *

- * 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 false should be used - */ - public FrustumIntersection(Matrix4fc m, boolean allowTestSpheres) { - set(m, allowTestSpheres); - } - - /** - * Update the stored frustum planes of this {@link FrustumIntersection} with the given {@link Matrix4fc matrix}. - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @param m - * the {@link Matrix4fc matrix} to update this frustum culler's frustum planes from - * @return this - */ - public FrustumIntersection set(Matrix4fc m) { - return set(m, true); - } - - /** - * Update the stored frustum planes of this {@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. - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @param m - * the {@link Matrix4fc matrix} to update this 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 false 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 this frustum culler. - * - * @param point - * the point to test - * @return true if the given point is inside the frustum; false otherwise - */ - public boolean testPoint(Vector3fc point) { - return testPoint(point.x(), point.y(), point.z()); - } - - /** - * Test whether the given point (x, y, z) is within the frustum defined by this 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 true if the given point is inside the frustum; false 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 this frustum culler. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns true for spheres that do not intersect the frustum. - * See iquilezles.org for an examination of this problem. - * - * @param center - * the sphere's center - * @param radius - * the sphere's radius - * @return true if the given sphere is partly or completely inside the frustum; - * false 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 this frustum culler. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns true for spheres that do not intersect the frustum. - * See iquilezles.org 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 true if the given sphere is partly or completely inside the frustum; - * false 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 this frustum culler. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns {@link #INTERSECT} for spheres that do not intersect the frustum. - * See iquilezles.org 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 this frustum culler. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns {@link #INTERSECT} for spheres that do not intersect the frustum. - * See iquilezles.org 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 this frustum culler. - * The box is specified via its min and max corner coordinates. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns true for boxes that do not intersect the frustum. - * See iquilezles.org 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 true if the axis-aligned box is completely or partly inside of the frustum; false 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 this frustum culler. - * The box is specified via its min and max corner coordinates. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns true for boxes that do not intersect the frustum. - * See iquilezles.org for an examination of this problem. - *

- * Reference: Efficient View Frustum Culling - * - * @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 true if the axis-aligned box is completely or partly inside of the frustum; false 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 Z = 0) is partly or completely within or outside of the frustum defined by this frustum culler. - * The plane is specified via its min and max corner coordinates. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns true for planes that do not intersect the frustum. - * See iquilezles.org for an examination of this problem. - *

- * Reference: Efficient View Frustum Culling - * - * @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 true if the XY-plane is completely or partly inside of the frustum; false 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 Y = 0) is partly or completely within or outside of the frustum defined by this frustum culler. - * The plane is specified via its min and max corner coordinates. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns true for planes that do not intersect the frustum. - * See iquilezles.org for an examination of this problem. - *

- * Reference: Efficient View Frustum Culling - * - * @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 true if the XZ-plane is completely or partly inside of the frustum; false 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 this 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. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum. - * See iquilezles.org 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 this 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. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum. - * See iquilezles.org for an examination of this problem. - *

- * Reference: Efficient View Frustum Culling - * - * @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 plane. - * - * @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 this 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. - *

- * 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 except the left plane, use - * a mask of (~0 ^ PLANE_MASK_NX). - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum. - * See iquilezles.org 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 this 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. - *

- * 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 except the left plane, use - * a mask of (~0 ^ PLANE_MASK_NX). - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum. - * See iquilezles.org for an examination of this problem. - *

- * Reference: Efficient View Frustum Culling - * - * @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 this 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. - *

- * 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 except the left plane, use - * a mask of (~0 ^ PLANE_MASK_NX). - *

- * In addition, the startPlane 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 intersectAab()) and in the next frame use the return value - * as the argument to the startPlane 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. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum. - * See iquilezles.org 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 this 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. - *

- * 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 except the left plane, use - * a mask of (~0 ^ PLANE_MASK_NX). - *

- * In addition, the startPlane 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 intersectAab()) and in the next frame use the return value - * as the argument to the startPlane 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. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns {@link #INTERSECT} for boxes that do not intersect the frustum. - * See iquilezles.org for an examination of this problem. - *

- * Reference: Efficient View Frustum Culling - * - * @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<= -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 a and b, - * is partly or completely within the frustum defined by this frustum culler. - * - * @param a - * the line segment's first end point - * @param b - * the line segment's second end point - * @return true if the given line segment is partly or completely inside the frustum; - * false 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 (aX, aY, aZ) and (bX, bY, bZ), - * is partly or completely within the frustum defined by this 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 true if the given line segment is partly or completely inside the frustum; - * false 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); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/FrustumRayBuilder.java b/src/main/java/com/jozufozu/flywheel/util/joml/FrustumRayBuilder.java deleted file mode 100644 index d2b17a09f..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/FrustumRayBuilder.java +++ /dev/null @@ -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}. - *

- * This can be used to compute the eye-rays in simple software-based raycasting/raytracing. - *

- * 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. - *

- * 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 this {@link FrustumRayBuilder} with the given {@link Matrix4fc matrix}. - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - *

- * Reference: http://geomalgorithms.com - * - * @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 origin. - * - * @param origin - * will hold the perspective origin - * @return the origin 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. - *

- * The parameters x and y 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 [0..1] - * @param y - * the interpolation factor along the bottom-to-top frustum planes, within [0..1] - * @param dir - * will hold the normalized ray direction - * @return the dir 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; - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Math.java b/src/main/java/com/jozufozu/flywheel/util/joml/Math.java deleted file mode 100644 index b67177d4c..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Math.java +++ /dev/null @@ -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. - *

- * 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 -Djoml.fastmath. - *

- * There are two algorithms for approximating sin/cos: - *

    - *
  1. arithmetic polynomial approximation contributed by roquendm - *
  2. theagentd's linear interpolation variant of Riven's algorithm from - * http://www.java-gaming.org/ - *
- * By default, the first algorithm is being used. In order to use the second one, start the JVM with -Djoml.sinLookup. The lookup table bit length of the second algorithm can also be adjusted - * for improved accuracy via -Djoml.sinLookup.bits=<n>, 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: http://www.java-gaming.org/ - */ - 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: http://www.java-gaming.org/ - */ - 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: http://www.java-gaming.org/ - */ - 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: http://www.java-gaming.org/ - */ - 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; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix3f.java b/src/main/java/com/jozufozu/flywheel/util/joml/Matrix3f.java deleted file mode 100644 index f30068383..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix3f.java +++ /dev/null @@ -1,4788 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2015-2021 Richard Greenlees - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.jozufozu.flywheel.util.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.text.DecimalFormat; -import java.text.NumberFormat; - - -/** - * Contains the definition of a 3x3 matrix of floats, and associated functions to transform - * it. The matrix is column-major to match OpenGL's interpretation, and it looks like this: - *

- * m00 m10 m20
- * m01 m11 m21
- * m02 m12 m22
- * - * @author Richard Greenlees - * @author Kai Burjack - */ -public class Matrix3f implements Externalizable, Cloneable, Matrix3fc { - - private static final long serialVersionUID = 1L; - - public float m00, m01, m02; - public float m10, m11, m12; - public float m20, m21, m22; - - /** - * Create a new {@link Matrix3f} and set it to {@link #identity() identity}. - */ - public Matrix3f() { - m00 = 1.0f; - m11 = 1.0f; - m22 = 1.0f; - } - - /** - * Create a new {@link Matrix3f} and make it a copy of the given matrix. - * - * @param mat - * the {@link Matrix3fc} to copy the values from - */ - public Matrix3f(Matrix3fc mat) { - set(mat); - } - - /** - * Create a new {@link Matrix3f} and make it a copy of the upper left 3x3 of the given {@link Matrix4fc}. - * - * @param mat - * the {@link Matrix4fc} to copy the values from - */ - public Matrix3f(Matrix4fc mat) { - set(mat); - } - - /** - * Create a new 3x3 matrix using the supplied float values. The order of the parameter is column-major, - * so the first three parameters specify the three elements of the first column. - * - * @param m00 - * the value of m00 - * @param m01 - * the value of m01 - * @param m02 - * the value of m02 - * @param m10 - * the value of m10 - * @param m11 - * the value of m11 - * @param m12 - * the value of m12 - * @param m20 - * the value of m20 - * @param m21 - * the value of m21 - * @param m22 - * the value of m22 - */ - public Matrix3f(float m00, float m01, float m02, - float m10, float m11, float m12, - float m20, float m21, float m22) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m10 = m10; - this.m11 = m11; - this.m12 = m12; - this.m20 = m20; - this.m21 = m21; - this.m22 = m22; - } - - /** - * Create a new {@link Matrix3f} by reading its 9 float components from the given {@link FloatBuffer} - * at the buffer's current position. - *

- * That FloatBuffer is expected to hold the values in column-major order. - *

- * The buffer's position will not be changed by this method. - * - * @param buffer - * the {@link FloatBuffer} to read the matrix values from - */ - public Matrix3f(FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - } - - /** - * Create a new {@link Matrix3f} and initialize its three columns using the supplied vectors. - * - * @param col0 - * the first column - * @param col1 - * the second column - * @param col2 - * the third column - */ - public Matrix3f(Vector3fc col0, Vector3fc col1, Vector3fc col2) { - set(col0, col1, col2); - } - - public float m00() { - return m00; - } - public float m01() { - return m01; - } - public float m02() { - return m02; - } - public float m10() { - return m10; - } - public float m11() { - return m11; - } - public float m12() { - return m12; - } - public float m20() { - return m20; - } - public float m21() { - return m21; - } - public float m22() { - return m22; - } - - /** - * Set the value of the matrix element at column 0 and row 0. - * - * @param m00 - * the new value - * @return this - */ - public Matrix3f m00(float m00) { - this.m00 = m00; - return this; - } - /** - * Set the value of the matrix element at column 0 and row 1. - * - * @param m01 - * the new value - * @return this - */ - public Matrix3f m01(float m01) { - this.m01 = m01; - return this; - } - /** - * Set the value of the matrix element at column 0 and row 2. - * - * @param m02 - * the new value - * @return this - */ - public Matrix3f m02(float m02) { - this.m02 = m02; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 0. - * - * @param m10 - * the new value - * @return this - */ - public Matrix3f m10(float m10) { - this.m10 = m10; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 1. - * - * @param m11 - * the new value - * @return this - */ - public Matrix3f m11(float m11) { - this.m11 = m11; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 2. - * - * @param m12 - * the new value - * @return this - */ - public Matrix3f m12(float m12) { - this.m12 = m12; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 0. - * - * @param m20 - * the new value - * @return this - */ - public Matrix3f m20(float m20) { - this.m20 = m20; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 1. - * - * @param m21 - * the new value - * @return this - */ - public Matrix3f m21(float m21) { - this.m21 = m21; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 2. - * - * @param m22 - * the new value - * @return this - */ - public Matrix3f m22(float m22) { - this.m22 = m22; - return this; - } - - /** - * Set the value of the matrix element at column 0 and row 0. - * - * @param m00 - * the new value - * @return this - */ - Matrix3f _m00(float m00) { - this.m00 = m00; - return this; - } - /** - * Set the value of the matrix element at column 0 and row 1. - * - * @param m01 - * the new value - * @return this - */ - Matrix3f _m01(float m01) { - this.m01 = m01; - return this; - } - /** - * Set the value of the matrix element at column 0 and row 2. - * - * @param m02 - * the new value - * @return this - */ - Matrix3f _m02(float m02) { - this.m02 = m02; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 0. - * - * @param m10 - * the new value - * @return this - */ - Matrix3f _m10(float m10) { - this.m10 = m10; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 1. - * - * @param m11 - * the new value - * @return this - */ - Matrix3f _m11(float m11) { - this.m11 = m11; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 2. - * - * @param m12 - * the new value - * @return this - */ - Matrix3f _m12(float m12) { - this.m12 = m12; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 0. - * - * @param m20 - * the new value - * @return this - */ - Matrix3f _m20(float m20) { - this.m20 = m20; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 1. - * - * @param m21 - * the new value - * @return this - */ - Matrix3f _m21(float m21) { - this.m21 = m21; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 2. - * - * @param m22 - * the new value - * @return this - */ - Matrix3f _m22(float m22) { - this.m22 = m22; - return this; - } - - /** - * Set the elements of this matrix to the ones in m. - * - * @param m - * the matrix to copy the elements from - * @return this - */ - public Matrix3f set(Matrix3fc m) { - return - _m00(m.m00()). - _m01(m.m01()). - _m02(m.m02()). - _m10(m.m10()). - _m11(m.m11()). - _m12(m.m12()). - _m20(m.m20()). - _m21(m.m21()). - _m22(m.m22()); - } - - /** - * Store the values of the transpose of the given matrix m into this matrix. - * - * @param m - * the matrix to copy the transposed values from - * @return this - */ - public Matrix3f setTransposed(Matrix3fc m) { - float nm10 = m.m01(), nm12 = m.m21(); - float nm20 = m.m02(), nm21 = m.m12(); - return this - ._m00(m.m00())._m01(m.m10())._m02(m.m20()) - ._m10(nm10)._m11(m.m11())._m12(nm12) - ._m20(nm20)._m21(nm21)._m22(m.m22()); - } - - /** - * Set the elements of this matrix to the upper left 3x3 of the given {@link Matrix4fc}. - * - * @param mat - * the {@link Matrix4fc} to copy the values from - * @return this - */ - public Matrix3f set(Matrix4fc mat) { - m00 = mat.m00(); - m01 = mat.m01(); - m02 = mat.m02(); - m10 = mat.m10(); - m11 = mat.m11(); - m12 = mat.m12(); - m20 = mat.m20(); - m21 = mat.m21(); - m22 = mat.m22(); - return this; - } - - /** - * Set this matrix to be equivalent to the rotation specified by the given {@link AxisAngle4f}. - * - * @param axisAngle - * the {@link AxisAngle4f} - * @return this - */ - public Matrix3f set(AxisAngle4f axisAngle) { - float x = axisAngle.x; - float y = axisAngle.y; - float z = axisAngle.z; - float angle = axisAngle.angle; - float invLength = Math.invsqrt(x*x + y*y + z*z); - x *= invLength; - y *= invLength; - z *= invLength; - float s = Math.sin(angle); - float c = Math.cosFromSin(s, angle); - float omc = 1.0f - c; - m00 = c + x*x*omc; - m11 = c + y*y*omc; - m22 = c + z*z*omc; - float tmp1 = x*y*omc; - float tmp2 = z*s; - m10 = tmp1 - tmp2; - m01 = tmp1 + tmp2; - tmp1 = x*z*omc; - tmp2 = y*s; - m20 = tmp1 + tmp2; - m02 = tmp1 - tmp2; - tmp1 = y*z*omc; - tmp2 = x*s; - m21 = tmp1 - tmp2; - m12 = tmp1 + tmp2; - return this; - } - - /** - * Set this matrix to be equivalent to the rotation - and possibly scaling - specified by the given {@link Quaternionfc}. - *

- * This method is equivalent to calling: rotation(q) - *

- * Reference: http://www.euclideanspace.com/ - * - * @see #rotation(Quaternionfc) - * - * @param q - * the {@link Quaternionfc} - * @return this - */ - public Matrix3f set(Quaternionfc q) { - return rotation(q); - } - - /** - * Multiply this matrix by the supplied right matrix. - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param right - * the right operand of the matrix multiplication - * @return this - */ - public Matrix3f mul(Matrix3fc right) { - return mul(right, this); - } - - public Matrix3f mul(Matrix3fc right, Matrix3f dest) { - float nm00 = Math.fma(m00, right.m00(), Math.fma(m10, right.m01(), m20 * right.m02())); - float nm01 = Math.fma(m01, right.m00(), Math.fma(m11, right.m01(), m21 * right.m02())); - float nm02 = Math.fma(m02, right.m00(), Math.fma(m12, right.m01(), m22 * right.m02())); - float nm10 = Math.fma(m00, right.m10(), Math.fma(m10, right.m11(), m20 * right.m12())); - float nm11 = Math.fma(m01, right.m10(), Math.fma(m11, right.m11(), m21 * right.m12())); - float nm12 = Math.fma(m02, right.m10(), Math.fma(m12, right.m11(), m22 * right.m12())); - float nm20 = Math.fma(m00, right.m20(), Math.fma(m10, right.m21(), m20 * right.m22())); - float nm21 = Math.fma(m01, right.m20(), Math.fma(m11, right.m21(), m21 * right.m22())); - float nm22 = Math.fma(m02, right.m20(), Math.fma(m12, right.m21(), m22 * right.m22())); - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - dest.m20 = nm20; - dest.m21 = nm21; - dest.m22 = nm22; - return dest; - } - - /** - * Pre-multiply this matrix by the supplied left matrix and store the result in this. - *

- * If M is this matrix and L the left matrix, - * then the new matrix will be L * M. So when transforming a - * vector v with the new matrix by using L * M * v, the - * transformation of this matrix will be applied first! - * - * @param left - * the left operand of the matrix multiplication - * @return this - */ - public Matrix3f mulLocal(Matrix3fc left) { - return mulLocal(left, this); - } - - public Matrix3f mulLocal(Matrix3fc left, Matrix3f dest) { - float nm00 = left.m00() * m00 + left.m10() * m01 + left.m20() * m02; - float nm01 = left.m01() * m00 + left.m11() * m01 + left.m21() * m02; - float nm02 = left.m02() * m00 + left.m12() * m01 + left.m22() * m02; - float nm10 = left.m00() * m10 + left.m10() * m11 + left.m20() * m12; - float nm11 = left.m01() * m10 + left.m11() * m11 + left.m21() * m12; - float nm12 = left.m02() * m10 + left.m12() * m11 + left.m22() * m12; - float nm20 = left.m00() * m20 + left.m10() * m21 + left.m20() * m22; - float nm21 = left.m01() * m20 + left.m11() * m21 + left.m21() * m22; - float nm22 = left.m02() * m20 + left.m12() * m21 + left.m22() * m22; - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - dest.m20 = nm20; - dest.m21 = nm21; - dest.m22 = nm22; - return dest; - } - - /** - * Set the values within this matrix to the supplied float values. The result looks like this: - *

- * m00, m10, m20
- * m01, m11, m21
- * m02, m12, m22
- * - * @param m00 - * the new value of m00 - * @param m01 - * the new value of m01 - * @param m02 - * the new value of m02 - * @param m10 - * the new value of m10 - * @param m11 - * the new value of m11 - * @param m12 - * the new value of m12 - * @param m20 - * the new value of m20 - * @param m21 - * the new value of m21 - * @param m22 - * the new value of m22 - * @return this - */ - public Matrix3f set(float m00, float m01, float m02, - float m10, float m11, float m12, - float m20, float m21, float m22) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m10 = m10; - this.m11 = m11; - this.m12 = m12; - this.m20 = m20; - this.m21 = m21; - this.m22 = m22; - return this; - } - - /** - * Set the values in this matrix based on the supplied float array. The result looks like this: - *

- * 0, 3, 6
- * 1, 4, 7
- * 2, 5, 8
- * - * This method only uses the first 9 values, all others are ignored. - * - * @param m - * the array to read the matrix values from - * @return this - */ - public Matrix3f set(float m[]) { - MemUtil.INSTANCE.copy(m, 0, this); - return this; - } - - /** - * Set the three columns of this matrix to the supplied vectors, respectively. - * - * @param col0 - * the first column - * @param col1 - * the second column - * @param col2 - * the third column - * @return this - */ - public Matrix3f set(Vector3fc col0, Vector3fc col1, Vector3fc col2) { - this.m00 = col0.x(); - this.m01 = col0.y(); - this.m02 = col0.z(); - this.m10 = col1.x(); - this.m11 = col1.y(); - this.m12 = col1.z(); - this.m20 = col2.x(); - this.m21 = col2.y(); - this.m22 = col2.z(); - return this; - } - - public float determinant() { - return (m00 * m11 - m01 * m10) * m22 - + (m02 * m10 - m00 * m12) * m21 - + (m01 * m12 - m02 * m11) * m20; - } - - /** - * Invert this matrix. - * - * @return this - */ - public Matrix3f invert() { - return invert(this); - } - - public Matrix3f invert(Matrix3f dest) { - float a = Math.fma(m00, m11, -m01 * m10); - float b = Math.fma(m02, m10, -m00 * m12); - float c = Math.fma(m01, m12, -m02 * m11); - float d = Math.fma(a, m22, Math.fma(b, m21, c * m20)); - float s = 1.0f / d; - float nm00 = Math.fma(m11, m22, -m21 * m12) * s; - float nm01 = Math.fma(m21, m02, -m01 * m22) * s; - float nm02 = c * s; - float nm10 = Math.fma(m20, m12, -m10 * m22) * s; - float nm11 = Math.fma(m00, m22, -m20 * m02) * s; - float nm12 = b * s; - float nm20 = Math.fma(m10, m21, -m20 * m11) * s; - float nm21 = Math.fma(m20, m01, -m00 * m21) * s; - float nm22 = a * s; - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - dest.m20 = nm20; - dest.m21 = nm21; - dest.m22 = nm22; - return dest; - } - - /** - * Transpose this matrix. - * - * @return this - */ - public Matrix3f transpose() { - return transpose(this); - } - - public Matrix3f transpose(Matrix3f dest) { - return dest.set(m00, m10, m20, - m01, m11, m21, - m02, m12, m22); - } - - /** - * Return a string representation of this matrix. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - String str = toString(Options.NUMBER_FORMAT); - 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(); - } - - /** - * Return a string representation of this matrix by formatting the matrix elements with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the matrix values with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return Runtime.format(m00, formatter) + " " + Runtime.format(m10, formatter) + " " + Runtime.format(m20, formatter) + "\n" - + Runtime.format(m01, formatter) + " " + Runtime.format(m11, formatter) + " " + Runtime.format(m21, formatter) + "\n" - + Runtime.format(m02, formatter) + " " + Runtime.format(m12, formatter) + " " + Runtime.format(m22, formatter) + "\n"; - } - - /** - * Get the current values of this matrix and store them into - * dest. - *

- * This is the reverse method of {@link #set(Matrix3fc)} and allows to obtain - * intermediate calculation results when chaining multiple transformations. - * - * @see #set(Matrix3fc) - * - * @param dest - * the destination matrix - * @return the passed in destination - */ - public Matrix3f get(Matrix3f dest) { - return dest.set(this); - } - - public Matrix4f get(Matrix4f dest) { - return dest.set(this); - } - - public AxisAngle4f getRotation(AxisAngle4f dest) { - return dest.set(this); - } - - public Quaternionf getUnnormalizedRotation(Quaternionf dest) { - return dest.setFromUnnormalized(this); - } - - public Quaternionf getNormalizedRotation(Quaternionf dest) { - return dest.setFromNormalized(this); - } - - public FloatBuffer get(FloatBuffer buffer) { - return get(buffer.position(), buffer); - } - - public FloatBuffer get(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.put(this, index, buffer); - return buffer; - } - - public ByteBuffer get(ByteBuffer buffer) { - return get(buffer.position(), buffer); - } - - public ByteBuffer get(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.put(this, index, buffer); - return buffer; - } - - public FloatBuffer get3x4(FloatBuffer buffer) { - return get3x4(buffer.position(), buffer); - } - - public FloatBuffer get3x4(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.put3x4(this, index, buffer); - return buffer; - } - - public ByteBuffer get3x4(ByteBuffer buffer) { - return get3x4(buffer.position(), buffer); - } - - public ByteBuffer get3x4(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.put3x4(this, index, buffer); - return buffer; - } - - public FloatBuffer getTransposed(FloatBuffer buffer) { - return getTransposed(buffer.position(), buffer); - } - - public FloatBuffer getTransposed(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.putTransposed(this, index, buffer); - return buffer; - } - - public ByteBuffer getTransposed(ByteBuffer buffer) { - return getTransposed(buffer.position(), buffer); - } - - public ByteBuffer getTransposed(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.putTransposed(this, index, buffer); - return buffer; - } - - public Matrix3fc getToAddress(long address) { - if (Options.NO_UNSAFE) - throw new UnsupportedOperationException("Not supported when using joml.nounsafe"); - MemUtil.MemUtilUnsafe.put(this, address); - return this; - } - - public float[] get(float[] arr, int offset) { - MemUtil.INSTANCE.copy(this, arr, offset); - return arr; - } - - public float[] get(float[] arr) { - return get(arr, 0); - } - - /** - * Set the values of this matrix by reading 9 float values from the given {@link FloatBuffer} in column-major order, - * starting at its current position. - *

- * The FloatBuffer is expected to contain the values in column-major order. - *

- * The position of the FloatBuffer will not be changed by this method. - * - * @param buffer - * the FloatBuffer to read the matrix values from in column-major order - * @return this - */ - public Matrix3f set(FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - return this; - } - - /** - * Set the values of this matrix by reading 9 float values from the given {@link ByteBuffer} in column-major order, - * starting at its current position. - *

- * The ByteBuffer is expected to contain the values in column-major order. - *

- * The position of the ByteBuffer will not be changed by this method. - * - * @param buffer - * the ByteBuffer to read the matrix values from in column-major order - * @return this - */ - public Matrix3f set(ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - return this; - } - - /** - * Set the values of this matrix by reading 9 float values from the given {@link FloatBuffer} in column-major order, - * starting at the specified absolute buffer position/index. - *

- * The FloatBuffer is expected to contain the values in column-major order. - *

- * The position of the FloatBuffer will not be changed by this method. - * - * @param index - * the absolute position into the FloatBuffer - * @param buffer - * the FloatBuffer to read the matrix values from in column-major order - * @return this - */ - public Matrix3f set(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - return this; - } - - /** - * Set the values of this matrix by reading 9 float values from the given {@link ByteBuffer} in column-major order, - * starting at the specified absolute buffer position/index. - *

- * The ByteBuffer is expected to contain the values in column-major order. - *

- * The position of the ByteBuffer will not be changed by this method. - * - * @param index - * the absolute position into the ByteBuffer - * @param buffer - * the ByteBuffer to read the matrix values from in column-major order - * @return this - */ - public Matrix3f set(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - return this; - } - /** - * Set the values of this matrix by reading 9 float values from off-heap memory in column-major order, - * starting at the given address. - *

- * This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`. - *

- * 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. - * - * @param address - * the off-heap memory address to read the matrix values from in column-major order - * @return this - */ - public Matrix3f setFromAddress(long address) { - if (Options.NO_UNSAFE) - throw new UnsupportedOperationException("Not supported when using joml.nounsafe"); - MemUtil.MemUtilUnsafe.get(this, address); - return this; - } - - /** - * Set all values within this matrix to zero. - * - * @return this - */ - public Matrix3f zero() { - MemUtil.INSTANCE.zero(this); - return this; - } - - /** - * Set this matrix to the identity. - * - * @return this - */ - public Matrix3f identity() { - MemUtil.INSTANCE.identity(this); - return this; - } - - public Matrix3f scale(Vector3fc xyz, Matrix3f dest) { - return scale(xyz.x(), xyz.y(), xyz.z(), dest); - } - - /** - * Apply scaling to this matrix by scaling the base axes by the given xyz.x, - * xyz.y and xyz.z factors, respectively. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * scaling will be applied first! - * - * @param xyz - * the factors of the x, y and z component, respectively - * @return this - */ - public Matrix3f scale(Vector3fc xyz) { - return scale(xyz.x(), xyz.y(), xyz.z(), this); - } - - public Matrix3f scale(float x, float y, float z, Matrix3f dest) { - // scale matrix elements: - // m00 = x, m11 = y, m22 = z - // all others = 0 - dest.m00 = m00 * x; - dest.m01 = m01 * x; - dest.m02 = m02 * x; - dest.m10 = m10 * y; - dest.m11 = m11 * y; - dest.m12 = m12 * y; - dest.m20 = m20 * z; - dest.m21 = m21 * z; - dest.m22 = m22 * z; - return dest; - } - - /** - * Apply scaling to this matrix by scaling the base axes by the given x, - * y and z factors. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v - * , the scaling will be applied first! - * - * @param x - * the factor of the x component - * @param y - * the factor of the y component - * @param z - * the factor of the z component - * @return this - */ - public Matrix3f scale(float x, float y, float z) { - return scale(x, y, z, this); - } - - public Matrix3f scale(float xyz, Matrix3f dest) { - return scale(xyz, xyz, xyz, dest); - } - - /** - * Apply scaling to this matrix by uniformly scaling all base axes by the given xyz factor. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v - * , the scaling will be applied first! - * - * @see #scale(float, float, float) - * - * @param xyz - * the factor for all components - * @return this - */ - public Matrix3f scale(float xyz) { - return scale(xyz, xyz, xyz); - } - - public Matrix3f scaleLocal(float x, float y, float z, Matrix3f dest) { - float nm00 = x * m00; - float nm01 = y * m01; - float nm02 = z * m02; - float nm10 = x * m10; - float nm11 = y * m11; - float nm12 = z * m12; - float nm20 = x * m20; - float nm21 = y * m21; - float nm22 = z * m22; - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - dest.m20 = nm20; - dest.m21 = nm21; - dest.m22 = nm22; - return dest; - } - - /** - * Pre-multiply scaling to this matrix by scaling the base axes by the given x, - * y and z factors. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be S * M. So when transforming a - * vector v with the new matrix by using S * M * v, the - * scaling will be applied last! - * - * @param x - * the factor of the x component - * @param y - * the factor of the y component - * @param z - * the factor of the z component - * @return this - */ - public Matrix3f scaleLocal(float x, float y, float z) { - return scaleLocal(x, y, z, this); - } - - /** - * Set this matrix to be a simple scale matrix, which scales all axes uniformly by the given factor. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional scaling. - *

- * In order to post-multiply a scaling transformation directly to a - * matrix, use {@link #scale(float) scale()} instead. - * - * @see #scale(float) - * - * @param factor - * the scale factor in x, y and z - * @return this - */ - public Matrix3f scaling(float factor) { - MemUtil.INSTANCE.zero(this); - m00 = factor; - m11 = factor; - m22 = factor; - return this; - } - - /** - * Set this matrix to be a simple scale matrix. - * - * @param x - * the scale in x - * @param y - * the scale in y - * @param z - * the scale in z - * @return this - */ - public Matrix3f scaling(float x, float y, float z) { - MemUtil.INSTANCE.zero(this); - m00 = x; - m11 = y; - m22 = z; - return this; - } - - /** - * Set this matrix to be a simple scale matrix which scales the base axes by xyz.x, xyz.y and xyz.z respectively. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional scaling. - *

- * In order to post-multiply a scaling transformation directly to a - * matrix use {@link #scale(Vector3fc) scale()} instead. - * - * @see #scale(Vector3fc) - * - * @param xyz - * the scale in x, y and z respectively - * @return this - */ - public Matrix3f scaling(Vector3fc xyz) { - return scaling(xyz.x(), xyz.y(), xyz.z()); - } - - /** - * Set this matrix to a rotation matrix which rotates the given radians about a given axis. - *

- * The axis described by the axis vector needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional rotation. - *

- * In order to post-multiply a rotation transformation directly to a - * matrix, use {@link #rotate(float, Vector3fc) rotate()} instead. - * - * @see #rotate(float, Vector3fc) - * - * @param angle - * the angle in radians - * @param axis - * the axis to rotate about (needs to be {@link Vector3f#normalize() normalized}) - * @return this - */ - public Matrix3f rotation(float angle, Vector3fc axis) { - return rotation(angle, axis.x(), axis.y(), axis.z()); - } - - /** - * Set this matrix to a rotation transformation using the given {@link AxisAngle4f}. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional rotation. - *

- * In order to apply the rotation transformation to an existing transformation, - * use {@link #rotate(AxisAngle4f) rotate()} instead. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(AxisAngle4f) - * - * @param axisAngle - * the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized}) - * @return this - */ - public Matrix3f rotation(AxisAngle4f axisAngle) { - return rotation(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z); - } - - /** - * Set this matrix to a rotation matrix which rotates the given radians about a given axis. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional rotation. - *

- * In order to apply the rotation transformation to an existing transformation, - * use {@link #rotate(float, float, float, float) rotate()} instead. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float) - * - * @param angle - * the angle in radians - * @param x - * the x-component of the rotation axis - * @param y - * the y-component of the rotation axis - * @param z - * the z-component of the rotation axis - * @return this - */ - public Matrix3f rotation(float angle, float x, float y, float z) { - float sin = Math.sin(angle); - float cos = Math.cosFromSin(sin, angle); - float C = 1.0f - cos; - float xy = x * y, xz = x * z, yz = y * z; - m00 = cos + x * x * C; - m10 = xy * C - z * sin; - m20 = xz * C + y * sin; - m01 = xy * C + z * sin; - m11 = cos + y * y * C; - m21 = yz * C - x * sin; - m02 = xz * C - y * sin; - m12 = yz * C + x * sin; - m22 = cos + z * z * C; - return this; - } - - /** - * Set this matrix to a rotation transformation about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix3f rotationX(float ang) { - float sin, cos; - sin = Math.sin(ang); - cos = Math.cosFromSin(sin, ang); - m00 = 1.0f; - m01 = 0.0f; - m02 = 0.0f; - m10 = 0.0f; - m11 = cos; - m12 = sin; - m20 = 0.0f; - m21 = -sin; - m22 = cos; - return this; - } - - /** - * Set this matrix to a rotation transformation about the Y axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix3f rotationY(float ang) { - float sin, cos; - sin = Math.sin(ang); - cos = Math.cosFromSin(sin, ang); - m00 = cos; - m01 = 0.0f; - m02 = -sin; - m10 = 0.0f; - m11 = 1.0f; - m12 = 0.0f; - m20 = sin; - m21 = 0.0f; - m22 = cos; - return this; - } - - /** - * Set this matrix to a rotation transformation about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix3f rotationZ(float ang) { - float sin, cos; - sin = Math.sin(ang); - cos = Math.cosFromSin(sin, ang); - m00 = cos; - m01 = sin; - m02 = 0.0f; - m10 = -sin; - m11 = cos; - m12 = 0.0f; - m20 = 0.0f; - m21 = 0.0f; - m22 = 1.0f; - return this; - } - - /** - * Set this matrix to a rotation of angleX radians about the X axis, followed by a rotation - * of angleY radians about the Y axis and followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: rotationX(angleX).rotateY(angleY).rotateZ(angleZ) - * - * @param angleX - * the angle to rotate about X - * @param angleY - * the angle to rotate about Y - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix3f rotationXYZ(float angleX, float angleY, float angleZ) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinX = -sinX; - float m_sinY = -sinY; - float m_sinZ = -sinZ; - - // rotateX - float nm11 = cosX; - float nm12 = sinX; - float nm21 = m_sinX; - float nm22 = cosX; - // rotateY - float nm00 = cosY; - float nm01 = nm21 * m_sinY; - float nm02 = nm22 * m_sinY; - m20 = sinY; - m21 = nm21 * cosY; - m22 = nm22 * cosY; - // rotateZ - m00 = nm00 * cosZ; - m01 = nm01 * cosZ + nm11 * sinZ; - m02 = nm02 * cosZ + nm12 * sinZ; - m10 = nm00 * m_sinZ; - m11 = nm01 * m_sinZ + nm11 * cosZ; - m12 = nm02 * m_sinZ + nm12 * cosZ; - return this; - } - - /** - * Set this matrix to a rotation of angleZ radians about the Z axis, followed by a rotation - * of angleY radians about the Y axis and followed by a rotation of angleX radians about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: rotationZ(angleZ).rotateY(angleY).rotateX(angleX) - * - * @param angleZ - * the angle to rotate about Z - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @return this - */ - public Matrix3f rotationZYX(float angleZ, float angleY, float angleX) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinZ = -sinZ; - float m_sinY = -sinY; - float m_sinX = -sinX; - - // rotateZ - float nm00 = cosZ; - float nm01 = sinZ; - float nm10 = m_sinZ; - float nm11 = cosZ; - // rotateY - float nm20 = nm00 * sinY; - float nm21 = nm01 * sinY; - float nm22 = cosY; - m00 = nm00 * cosY; - m01 = nm01 * cosY; - m02 = m_sinY; - // rotateX - m10 = nm10 * cosX + nm20 * sinX; - m11 = nm11 * cosX + nm21 * sinX; - m12 = nm22 * sinX; - m20 = nm10 * m_sinX + nm20 * cosX; - m21 = nm11 * m_sinX + nm21 * cosX; - m22 = nm22 * cosX; - return this; - } - - /** - * Set this matrix to a rotation of angleY radians about the Y axis, followed by a rotation - * of angleX radians about the X axis and followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: rotationY(angleY).rotateX(angleX).rotateZ(angleZ) - * - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix3f rotationYXZ(float angleY, float angleX, float angleZ) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinY = -sinY; - float m_sinX = -sinX; - float m_sinZ = -sinZ; - - // rotateY - float nm00 = cosY; - float nm02 = m_sinY; - float nm20 = sinY; - float nm22 = cosY; - // rotateX - float nm10 = nm20 * sinX; - float nm11 = cosX; - float nm12 = nm22 * sinX; - m20 = nm20 * cosX; - m21 = m_sinX; - m22 = nm22 * cosX; - // rotateZ - m00 = nm00 * cosZ + nm10 * sinZ; - m01 = nm11 * sinZ; - m02 = nm02 * cosZ + nm12 * sinZ; - m10 = nm00 * m_sinZ + nm10 * cosZ; - m11 = nm11 * cosZ; - m12 = nm02 * m_sinZ + nm12 * cosZ; - return this; - } - - /** - * Set this matrix to the rotation - and possibly scaling - transformation of the given {@link Quaternionfc}. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional rotation. - *

- * In order to apply the rotation transformation to an existing transformation, - * use {@link #rotate(Quaternionfc) rotate()} instead. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @return this - */ - public Matrix3f rotation(Quaternionfc quat) { - float w2 = quat.w() * quat.w(); - float x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(); - float z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw; - float xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz; - float yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz; - float xw = quat.x() * quat.w(), dxw = xw + xw; - m00 = w2 + x2 - z2 - y2; - m01 = dxy + dzw; - m02 = dxz - dyw; - m10 = -dzw + dxy; - m11 = y2 - z2 + w2 - x2; - m12 = dyz + dxw; - m20 = dyw + dxz; - m21 = dyz - dxw; - m22 = z2 - y2 - x2 + w2; - return this; - } - - public Vector3f transform(Vector3f v) { - return v.mul(this); - } - - public Vector3f transform(Vector3fc v, Vector3f dest) { - return v.mul(this, dest); - } - - public Vector3f transform(float x, float y, float z, Vector3f dest) { - return dest.set(Math.fma(m00, x, Math.fma(m10, y, m20 * z)), - Math.fma(m01, x, Math.fma(m11, y, m21 * z)), - Math.fma(m02, x, Math.fma(m12, y, m22 * z))); - } - - public Vector3f transformTranspose(Vector3f v) { - return v.mulTranspose(this); - } - - public Vector3f transformTranspose(Vector3fc v, Vector3f dest) { - return v.mulTranspose(this, dest); - } - - public Vector3f transformTranspose(float x, float y, float z, Vector3f dest) { - return dest.set(Math.fma(m00, x, Math.fma(m01, y, m02 * z)), - Math.fma(m10, x, Math.fma(m11, y, m12 * z)), - Math.fma(m20, x, Math.fma(m21, y, m22 * z))); - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(m00); - out.writeFloat(m01); - out.writeFloat(m02); - out.writeFloat(m10); - out.writeFloat(m11); - out.writeFloat(m12); - out.writeFloat(m20); - out.writeFloat(m21); - out.writeFloat(m22); - } - - public void readExternal(ObjectInput in) throws IOException { - m00 = in.readFloat(); - m01 = in.readFloat(); - m02 = in.readFloat(); - m10 = in.readFloat(); - m11 = in.readFloat(); - m12 = in.readFloat(); - m20 = in.readFloat(); - m21 = in.readFloat(); - m22 = in.readFloat(); - } - - public Matrix3f rotateX(float ang, Matrix3f dest) { - float sin, cos; - sin = Math.sin(ang); - cos = Math.cosFromSin(sin, ang); - float rm11 = cos; - float rm21 = -sin; - float rm12 = sin; - float rm22 = cos; - - // add temporaries for dependent values - float nm10 = m10 * rm11 + m20 * rm12; - float nm11 = m11 * rm11 + m21 * rm12; - float nm12 = m12 * rm11 + m22 * rm12; - // set non-dependent values directly - dest.m20 = m10 * rm21 + m20 * rm22; - dest.m21 = m11 * rm21 + m21 * rm22; - dest.m22 = m12 * rm21 + m22 * rm22; - // set other values - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - dest.m00 = m00; - dest.m01 = m01; - dest.m02 = m02; - return dest; - } - - /** - * Apply rotation about the X axis to this matrix by rotating the given amount of radians. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v - * , the rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix3f rotateX(float ang) { - return rotateX(ang, this); - } - - public Matrix3f rotateY(float ang, Matrix3f dest) { - float sin, cos; - sin = Math.sin(ang); - cos = Math.cosFromSin(sin, ang); - float rm00 = cos; - float rm20 = sin; - float rm02 = -sin; - float rm22 = cos; - - // add temporaries for dependent values - float nm00 = m00 * rm00 + m20 * rm02; - float nm01 = m01 * rm00 + m21 * rm02; - float nm02 = m02 * rm00 + m22 * rm02; - // set non-dependent values directly - dest.m20 = m00 * rm20 + m20 * rm22; - dest.m21 = m01 * rm20 + m21 * rm22; - dest.m22 = m02 * rm20 + m22 * rm22; - // set other values - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = m10; - dest.m11 = m11; - dest.m12 = m12; - return dest; - } - - /** - * Apply rotation about the Y axis to this matrix by rotating the given amount of radians. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v - * , the rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix3f rotateY(float ang) { - return rotateY(ang, this); - } - - public Matrix3f rotateZ(float ang, Matrix3f dest) { - float sin, cos; - sin = Math.sin(ang); - cos = Math.cosFromSin(sin, ang); - float rm00 = cos; - float rm10 = -sin; - float rm01 = sin; - float rm11 = cos; - - // add temporaries for dependent values - float nm00 = m00 * rm00 + m10 * rm01; - float nm01 = m01 * rm00 + m11 * rm01; - float nm02 = m02 * rm00 + m12 * rm01; - // set non-dependent values directly - dest.m10 = m00 * rm10 + m10 * rm11; - dest.m11 = m01 * rm10 + m11 * rm11; - dest.m12 = m02 * rm10 + m12 * rm11; - // set other values - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m20 = m20; - dest.m21 = m21; - dest.m22 = m22; - return dest; - } - - /** - * Apply rotation about the Z axis to this matrix by rotating the given amount of radians. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v - * , the rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix3f rotateZ(float ang) { - return rotateZ(ang, this); - } - - /** - * Apply rotation of angles.x radians about the X axis, followed by a rotation of angles.y radians about the Y axis and - * followed by a rotation of angles.z radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateX(angles.x).rotateY(angles.y).rotateZ(angles.z) - * - * @param angles - * the Euler angles - * @return this - */ - public Matrix3f rotateXYZ(Vector3f angles) { - return rotateXYZ(angles.x, angles.y, angles.z); - } - - /** - * Apply rotation of angleX radians about the X axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateX(angleX).rotateY(angleY).rotateZ(angleZ) - * - * @param angleX - * the angle to rotate about X - * @param angleY - * the angle to rotate about Y - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix3f rotateXYZ(float angleX, float angleY, float angleZ) { - return rotateXYZ(angleX, angleY, angleZ, this); - } - - public Matrix3f rotateXYZ(float angleX, float angleY, float angleZ, Matrix3f dest) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinX = -sinX; - float m_sinY = -sinY; - float m_sinZ = -sinZ; - - // rotateX - float nm10 = m10 * cosX + m20 * sinX; - float nm11 = m11 * cosX + m21 * sinX; - float nm12 = m12 * cosX + m22 * sinX; - float nm20 = m10 * m_sinX + m20 * cosX; - float nm21 = m11 * m_sinX + m21 * cosX; - float nm22 = m12 * m_sinX + m22 * cosX; - // rotateY - float nm00 = m00 * cosY + nm20 * m_sinY; - float nm01 = m01 * cosY + nm21 * m_sinY; - float nm02 = m02 * cosY + nm22 * m_sinY; - dest.m20 = m00 * sinY + nm20 * cosY; - dest.m21 = m01 * sinY + nm21 * cosY; - dest.m22 = m02 * sinY + nm22 * cosY; - // rotateZ - dest.m00 = nm00 * cosZ + nm10 * sinZ; - dest.m01 = nm01 * cosZ + nm11 * sinZ; - dest.m02 = nm02 * cosZ + nm12 * sinZ; - dest.m10 = nm00 * m_sinZ + nm10 * cosZ; - dest.m11 = nm01 * m_sinZ + nm11 * cosZ; - dest.m12 = nm02 * m_sinZ + nm12 * cosZ; - return dest; - } - - /** - * Apply rotation of angles.z radians about the Z axis, followed by a rotation of angles.y radians about the Y axis and - * followed by a rotation of angles.x radians about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateZ(angles.z).rotateY(angles.y).rotateX(angles.x) - * - * @param angles - * the Euler angles - * @return this - */ - public Matrix3f rotateZYX(Vector3f angles) { - return rotateZYX(angles.z, angles.y, angles.x); - } - - /** - * Apply rotation of angleZ radians about the Z axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleX radians about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateZ(angleZ).rotateY(angleY).rotateX(angleX) - * - * @param angleZ - * the angle to rotate about Z - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @return this - */ - public Matrix3f rotateZYX(float angleZ, float angleY, float angleX) { - return rotateZYX(angleZ, angleY, angleX, this); - } - - public Matrix3f rotateZYX(float angleZ, float angleY, float angleX, Matrix3f dest) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinZ = -sinZ; - float m_sinY = -sinY; - float m_sinX = -sinX; - - // rotateZ - float nm00 = m00 * cosZ + m10 * sinZ; - float nm01 = m01 * cosZ + m11 * sinZ; - float nm02 = m02 * cosZ + m12 * sinZ; - float nm10 = m00 * m_sinZ + m10 * cosZ; - float nm11 = m01 * m_sinZ + m11 * cosZ; - float nm12 = m02 * m_sinZ + m12 * cosZ; - // rotateY - float nm20 = nm00 * sinY + m20 * cosY; - float nm21 = nm01 * sinY + m21 * cosY; - float nm22 = nm02 * sinY + m22 * cosY; - dest.m00 = nm00 * cosY + m20 * m_sinY; - dest.m01 = nm01 * cosY + m21 * m_sinY; - dest.m02 = nm02 * cosY + m22 * m_sinY; - // rotateX - dest.m10 = nm10 * cosX + nm20 * sinX; - dest.m11 = nm11 * cosX + nm21 * sinX; - dest.m12 = nm12 * cosX + nm22 * sinX; - dest.m20 = nm10 * m_sinX + nm20 * cosX; - dest.m21 = nm11 * m_sinX + nm21 * cosX; - dest.m22 = nm12 * m_sinX + nm22 * cosX; - return dest; - } - - /** - * Apply rotation of angles.y radians about the Y axis, followed by a rotation of angles.x radians about the X axis and - * followed by a rotation of angles.z radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateY(angles.y).rotateX(angles.x).rotateZ(angles.z) - * - * @param angles - * the Euler angles - * @return this - */ - public Matrix3f rotateYXZ(Vector3f angles) { - return rotateYXZ(angles.y, angles.x, angles.z); - } - - /** - * Apply rotation of angleY radians about the Y axis, followed by a rotation of angleX radians about the X axis and - * followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateY(angleY).rotateX(angleX).rotateZ(angleZ) - * - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix3f rotateYXZ(float angleY, float angleX, float angleZ) { - return rotateYXZ(angleY, angleX, angleZ, this); - } - - public Matrix3f rotateYXZ(float angleY, float angleX, float angleZ, Matrix3f dest) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinY = -sinY; - float m_sinX = -sinX; - float m_sinZ = -sinZ; - - // rotateY - float nm20 = m00 * sinY + m20 * cosY; - float nm21 = m01 * sinY + m21 * cosY; - float nm22 = m02 * sinY + m22 * cosY; - float nm00 = m00 * cosY + m20 * m_sinY; - float nm01 = m01 * cosY + m21 * m_sinY; - float nm02 = m02 * cosY + m22 * m_sinY; - // rotateX - float nm10 = m10 * cosX + nm20 * sinX; - float nm11 = m11 * cosX + nm21 * sinX; - float nm12 = m12 * cosX + nm22 * sinX; - dest.m20 = m10 * m_sinX + nm20 * cosX; - dest.m21 = m11 * m_sinX + nm21 * cosX; - dest.m22 = m12 * m_sinX + nm22 * cosX; - // rotateZ - dest.m00 = nm00 * cosZ + nm10 * sinZ; - dest.m01 = nm01 * cosZ + nm11 * sinZ; - dest.m02 = nm02 * cosZ + nm12 * sinZ; - dest.m10 = nm00 * m_sinZ + nm10 * cosZ; - dest.m11 = nm01 * m_sinZ + nm11 * cosZ; - dest.m12 = nm02 * m_sinZ + nm12 * cosZ; - return dest; - } - - /** - * Apply rotation to this matrix by rotating the given amount of radians - * about the given axis specified as x, y and z components. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v - * , the rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @return this - */ - public Matrix3f rotate(float ang, float x, float y, float z) { - return rotate(ang, x, y, z, this); - } - - public Matrix3f rotate(float ang, float x, float y, float z, Matrix3f dest) { - float s = Math.sin(ang); - float c = Math.cosFromSin(s, ang); - float C = 1.0f - c; - - // rotation matrix elements: - // m30, m31, m32, m03, m13, m23 = 0 - float xx = x * x, xy = x * y, xz = x * z; - float yy = y * y, yz = y * z; - float zz = z * z; - float rm00 = xx * C + c; - float rm01 = xy * C + z * s; - float rm02 = xz * C - y * s; - float rm10 = xy * C - z * s; - float rm11 = yy * C + c; - float rm12 = yz * C + x * s; - float rm20 = xz * C + y * s; - float rm21 = yz * C - x * s; - float rm22 = zz * C + c; - - // add temporaries for dependent values - float nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; - float nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; - float nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; - float nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; - float nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; - float nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; - // set non-dependent values directly - dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; - dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; - dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; - // set other values - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - return dest; - } - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians - * about the specified (x, y, z) axis and store the result in dest. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotation(float, float, float, float) rotation()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(float, float, float, float) - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f rotateLocal(float ang, float x, float y, float z, Matrix3f dest) { - float s = Math.sin(ang); - float c = Math.cosFromSin(s, ang); - float C = 1.0f - c; - float xx = x * x, xy = x * y, xz = x * z; - float yy = y * y, yz = y * z; - float zz = z * z; - float lm00 = xx * C + c; - float lm01 = xy * C + z * s; - float lm02 = xz * C - y * s; - float lm10 = xy * C - z * s; - float lm11 = yy * C + c; - float lm12 = yz * C + x * s; - float lm20 = xz * C + y * s; - float lm21 = yz * C - x * s; - float lm22 = zz * C + c; - float nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02; - float nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02; - float nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02; - float nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12; - float nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12; - float nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12; - float nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22; - float nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22; - float nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22; - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - dest.m20 = nm20; - dest.m21 = nm21; - dest.m22 = nm22; - return dest; - } - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians - * about the specified (x, y, z) axis. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotation(float, float, float, float) rotation()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(float, float, float, float) - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @return this - */ - public Matrix3f rotateLocal(float ang, float x, float y, float z) { - return rotateLocal(ang, x, y, z, this); - } - - /** - * Pre-multiply a rotation around the X axis to this matrix by rotating the given amount of radians - * about the X axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationX(float) rotationX()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationX(float) - * - * @param ang - * the angle in radians to rotate about the X axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f rotateLocalX(float ang, Matrix3f dest) { - float sin = Math.sin(ang); - float cos = Math.cosFromSin(sin, ang); - float nm01 = cos * m01 - sin * m02; - float nm02 = sin * m01 + cos * m02; - float nm11 = cos * m11 - sin * m12; - float nm12 = sin * m11 + cos * m12; - float nm21 = cos * m21 - sin * m22; - float nm22 = sin * m21 + cos * m22; - dest.m00 = m00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = m10; - dest.m11 = nm11; - dest.m12 = nm12; - dest.m20 = m20; - dest.m21 = nm21; - dest.m22 = nm22; - return dest; - } - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationX(float) rotationX()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationX(float) - * - * @param ang - * the angle in radians to rotate about the X axis - * @return this - */ - public Matrix3f rotateLocalX(float ang) { - return rotateLocalX(ang, this); - } - - /** - * Pre-multiply a rotation around the Y axis to this matrix by rotating the given amount of radians - * about the Y axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationY(float) rotationY()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationY(float) - * - * @param ang - * the angle in radians to rotate about the Y axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f rotateLocalY(float ang, Matrix3f dest) { - float sin = Math.sin(ang); - float cos = Math.cosFromSin(sin, ang); - float nm00 = cos * m00 + sin * m02; - float nm02 = -sin * m00 + cos * m02; - float nm10 = cos * m10 + sin * m12; - float nm12 = -sin * m10 + cos * m12; - float nm20 = cos * m20 + sin * m22; - float nm22 = -sin * m20 + cos * m22; - dest.m00 = nm00; - dest.m01 = m01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = m11; - dest.m12 = nm12; - dest.m20 = nm20; - dest.m21 = m21; - dest.m22 = nm22; - return dest; - } - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Y axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationY(float) rotationY()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationY(float) - * - * @param ang - * the angle in radians to rotate about the Y axis - * @return this - */ - public Matrix3f rotateLocalY(float ang) { - return rotateLocalY(ang, this); - } - - /** - * Pre-multiply a rotation around the Z axis to this matrix by rotating the given amount of radians - * about the Z axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationZ(float) rotationZ()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationZ(float) - * - * @param ang - * the angle in radians to rotate about the Z axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f rotateLocalZ(float ang, Matrix3f dest) { - float sin = Math.sin(ang); - float cos = Math.cosFromSin(sin, ang); - float nm00 = cos * m00 - sin * m01; - float nm01 = sin * m00 + cos * m01; - float nm10 = cos * m10 - sin * m11; - float nm11 = sin * m10 + cos * m11; - float nm20 = cos * m20 - sin * m21; - float nm21 = sin * m20 + cos * m21; - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = m02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = m12; - dest.m20 = nm20; - dest.m21 = nm21; - dest.m22 = m22; - return dest; - } - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationZ(float) rotationY()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationY(float) - * - * @param ang - * the angle in radians to rotate about the Z axis - * @return this - */ - public Matrix3f rotateLocalZ(float ang) { - return rotateLocalZ(ang, this); - } - - /** - * Apply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @return this - */ - public Matrix3f rotate(Quaternionfc quat) { - return rotate(quat, this); - } - - /** - * Apply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix and store - * the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f rotate(Quaternionfc quat, Matrix3f dest) { - float w2 = quat.w() * quat.w(), x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(), z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw, xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz, yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz, xw = quat.x() * quat.w(), dxw = xw + xw; - float rm00 = w2 + x2 - z2 - y2; - float rm01 = dxy + dzw; - float rm02 = dxz - dyw; - float rm10 = dxy - dzw; - float rm11 = y2 - z2 + w2 - x2; - float rm12 = dyz + dxw; - float rm20 = dyw + dxz; - float rm21 = dyz - dxw; - float rm22 = z2 - y2 - x2 + w2; - float nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; - float nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; - float nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; - float nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; - float nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; - float nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; - dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; - dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; - dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - return dest; - } - - /** - * Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix and store - * the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be Q * M. So when transforming a - * vector v with the new matrix by using Q * M * v, - * the quaternion rotation will be applied last! - *

- * In order to set the matrix to a rotation transformation without pre-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f rotateLocal(Quaternionfc quat, Matrix3f dest) { - float w2 = quat.w() * quat.w(), x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(), z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw, xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz, yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz, xw = quat.x() * quat.w(), dxw = xw + xw; - float lm00 = w2 + x2 - z2 - y2; - float lm01 = dxy + dzw; - float lm02 = dxz - dyw; - float lm10 = dxy - dzw; - float lm11 = y2 - z2 + w2 - x2; - float lm12 = dyz + dxw; - float lm20 = dyw + dxz; - float lm21 = dyz - dxw; - float lm22 = z2 - y2 - x2 + w2; - float nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02; - float nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02; - float nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02; - float nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12; - float nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12; - float nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12; - float nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22; - float nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22; - float nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22; - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - dest.m20 = nm20; - dest.m21 = nm21; - dest.m22 = nm22; - return dest; - } - - /** - * Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be Q * M. So when transforming a - * vector v with the new matrix by using Q * M * v, - * the quaternion rotation will be applied last! - *

- * In order to set the matrix to a rotation transformation without pre-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @return this - */ - public Matrix3f rotateLocal(Quaternionfc quat) { - return rotateLocal(quat, this); - } - - /** - * Apply a rotation transformation, rotating about the given {@link AxisAngle4f}, to this matrix. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given {@link AxisAngle4f}, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the {@link AxisAngle4f} rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(AxisAngle4f)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float) - * @see #rotation(AxisAngle4f) - * - * @param axisAngle - * the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized}) - * @return this - */ - public Matrix3f rotate(AxisAngle4f axisAngle) { - return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z); - } - - /** - * Apply a rotation transformation, rotating about the given {@link AxisAngle4f} and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given {@link AxisAngle4f}, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the {@link AxisAngle4f} rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(AxisAngle4f)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float) - * @see #rotation(AxisAngle4f) - * - * @param axisAngle - * the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized}) - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f rotate(AxisAngle4f axisAngle, Matrix3f dest) { - return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z, dest); - } - - /** - * Apply a rotation transformation, rotating the given radians about the specified axis, to this matrix. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given angle and axis, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the axis-angle rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(float, Vector3fc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float) - * @see #rotation(float, Vector3fc) - * - * @param angle - * the angle in radians - * @param axis - * the rotation axis (needs to be {@link Vector3f#normalize() normalized}) - * @return this - */ - public Matrix3f rotate(float angle, Vector3fc axis) { - return rotate(angle, axis.x(), axis.y(), axis.z()); - } - - /** - * Apply a rotation transformation, rotating the given radians about the specified axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given angle and axis, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the axis-angle rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(float, Vector3fc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float) - * @see #rotation(float, Vector3fc) - * - * @param angle - * the angle in radians - * @param axis - * the rotation axis (needs to be {@link Vector3f#normalize() normalized}) - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f rotate(float angle, Vector3fc axis, Matrix3f dest) { - return rotate(angle, axis.x(), axis.y(), axis.z(), dest); - } - - /** - * Apply a rotation transformation to this matrix to make -z point along dir. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - *

- * In order to set the matrix to a lookalong transformation without post-multiplying it, - * use {@link #setLookAlong(Vector3fc, Vector3fc) setLookAlong()}. - * - * @see #lookAlong(float, float, float, float, float, float) - * @see #setLookAlong(Vector3fc, Vector3fc) - * - * @param dir - * the direction in space to look along - * @param up - * the direction of 'up' - * @return this - */ - public Matrix3f lookAlong(Vector3fc dir, Vector3fc up) { - return lookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z(), this); - } - - /** - * Apply a rotation transformation to this matrix to make -z point along dir - * and store the result in dest. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - *

- * In order to set the matrix to a lookalong transformation without post-multiplying it, - * use {@link #setLookAlong(Vector3fc, Vector3fc) setLookAlong()}. - * - * @see #lookAlong(float, float, float, float, float, float) - * @see #setLookAlong(Vector3fc, Vector3fc) - * - * @param dir - * the direction in space to look along - * @param up - * the direction of 'up' - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f lookAlong(Vector3fc dir, Vector3fc up, Matrix3f dest) { - return lookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z(), dest); - } - - /** - * Apply a rotation transformation to this matrix to make -z point along dir - * and store the result in dest. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - *

- * In order to set the matrix to a lookalong transformation without post-multiplying it, - * use {@link #setLookAlong(float, float, float, float, float, float) setLookAlong()} - * - * @see #setLookAlong(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to look along - * @param dirY - * the y-coordinate of the direction to look along - * @param dirZ - * the z-coordinate of the direction to look along - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f lookAlong(float dirX, float dirY, float dirZ, - float upX, float upY, float upZ, Matrix3f dest) { - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= -invDirLength; - dirY *= -invDirLength; - dirZ *= -invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * dirZ - upZ * dirY; - leftY = upZ * dirX - upX * dirZ; - leftZ = upX * dirY - upY * dirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = dirY * leftZ - dirZ * leftY; - float upnY = dirZ * leftX - dirX * leftZ; - float upnZ = dirX * leftY - dirY * leftX; - - // calculate right matrix elements - float rm00 = leftX; - float rm01 = upnX; - float rm02 = dirX; - float rm10 = leftY; - float rm11 = upnY; - float rm12 = dirY; - float rm20 = leftZ; - float rm21 = upnZ; - float rm22 = dirZ; - - // perform optimized matrix multiplication - // introduce temporaries for dependent results - float nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; - float nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; - float nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; - float nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; - float nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; - float nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; - dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; - dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; - dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; - // set the rest of the matrix elements - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - return dest; - } - - /** - * Apply a rotation transformation to this matrix to make -z point along dir. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - *

- * In order to set the matrix to a lookalong transformation without post-multiplying it, - * use {@link #setLookAlong(float, float, float, float, float, float) setLookAlong()} - * - * @see #setLookAlong(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to look along - * @param dirY - * the y-coordinate of the direction to look along - * @param dirZ - * the z-coordinate of the direction to look along - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix3f lookAlong(float dirX, float dirY, float dirZ, - float upX, float upY, float upZ) { - return lookAlong(dirX, dirY, dirZ, upX, upY, upZ, this); - } - - /** - * Set this matrix to a rotation transformation to make -z - * point along dir. - *

- * In order to apply the lookalong transformation to any previous existing transformation, - * use {@link #lookAlong(Vector3fc, Vector3fc)}. - * - * @see #setLookAlong(Vector3fc, Vector3fc) - * @see #lookAlong(Vector3fc, Vector3fc) - * - * @param dir - * the direction in space to look along - * @param up - * the direction of 'up' - * @return this - */ - public Matrix3f setLookAlong(Vector3fc dir, Vector3fc up) { - return setLookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z()); - } - - /** - * Set this matrix to a rotation transformation to make -z - * point along dir. - *

- * In order to apply the lookalong transformation to any previous existing transformation, - * use {@link #lookAlong(float, float, float, float, float, float) lookAlong()} - * - * @see #setLookAlong(float, float, float, float, float, float) - * @see #lookAlong(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to look along - * @param dirY - * the y-coordinate of the direction to look along - * @param dirZ - * the z-coordinate of the direction to look along - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix3f setLookAlong(float dirX, float dirY, float dirZ, - float upX, float upY, float upZ) { - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= -invDirLength; - dirY *= -invDirLength; - dirZ *= -invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * dirZ - upZ * dirY; - leftY = upZ * dirX - upX * dirZ; - leftZ = upX * dirY - upY * dirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = dirY * leftZ - dirZ * leftY; - float upnY = dirZ * leftX - dirX * leftZ; - float upnZ = dirX * leftY - dirY * leftX; - - m00 = leftX; - m01 = upnX; - m02 = dirX; - m10 = leftY; - m11 = upnY; - m12 = dirY; - m20 = leftZ; - m21 = upnZ; - m22 = dirZ; - - return this; - } - - public Vector3f getRow(int row, Vector3f dest) throws IndexOutOfBoundsException { - switch (row) { - case 0: - return dest.set(m00, m10, m20); - case 1: - return dest.set(m01, m11, m21); - case 2: - return dest.set(m02, m12, m22); - default: - throw new IndexOutOfBoundsException(); - } - } - - /** - * Set the row at the given row index, starting with 0. - * - * @param row - * the row index in [0..2] - * @param src - * the row components to set - * @return this - * @throws IndexOutOfBoundsException if row is not in [0..2] - */ - public Matrix3f setRow(int row, Vector3fc src) throws IndexOutOfBoundsException { - return setRow(row, src.x(), src.y(), src.z()); - } - - /** - * Set the row at the given row index, starting with 0. - * - * @param row - * the row index in [0..2] - * @param x - * the first element in the row - * @param y - * the second element in the row - * @param z - * the third element in the row - * @return this - * @throws IndexOutOfBoundsException if row is not in [0..2] - */ - public Matrix3f setRow(int row, float x, float y, float z) throws IndexOutOfBoundsException { - switch (row) { - case 0: - this.m00 = x; - this.m10 = y; - this.m20 = z; - break; - case 1: - this.m01 = x; - this.m11 = y; - this.m21 = z; - break; - case 2: - this.m02 = x; - this.m12 = y; - this.m22 = z; - break; - default: - throw new IndexOutOfBoundsException(); - } - return this; - } - - public Vector3f getColumn(int column, Vector3f dest) throws IndexOutOfBoundsException { - switch (column) { - case 0: - return dest.set(m00, m01, m02); - case 1: - return dest.set(m10, m11, m12); - case 2: - return dest.set(m20, m21, m22); - default: - throw new IndexOutOfBoundsException(); - } - } - - /** - * Set the column at the given column index, starting with 0. - * - * @param column - * the column index in [0..2] - * @param src - * the column components to set - * @return this - * @throws IndexOutOfBoundsException if column is not in [0..2] - */ - public Matrix3f setColumn(int column, Vector3fc src) throws IndexOutOfBoundsException { - return setColumn(column, src.x(), src.y(), src.z()); - } - - /** - * Set the column at the given column index, starting with 0. - * - * @param column - * the column index in [0..2] - * @param x - * the first element in the column - * @param y - * the second element in the column - * @param z - * the third element in the column - * @return this - * @throws IndexOutOfBoundsException if column is not in [0..2] - */ - public Matrix3f setColumn(int column, float x, float y, float z) throws IndexOutOfBoundsException { - switch (column) { - case 0: - this.m00 = x; - this.m01 = y; - this.m02 = z; - break; - case 1: - this.m10 = x; - this.m11 = y; - this.m12 = z; - break; - case 2: - this.m20 = x; - this.m21 = y; - this.m22 = z; - break; - default: - throw new IndexOutOfBoundsException(); - } - return this; - } - - public float get(int column, int row) { - return MemUtil.INSTANCE.get(this, column, row); - } - - /** - * Set the matrix element at the given column and row to the specified value. - * - * @param column - * the colum index in [0..2] - * @param row - * the row index in [0..2] - * @param value - * the value - * @return this - */ - public Matrix3f set(int column, int row, float value) { - return MemUtil.INSTANCE.set(this, column, row, value); - } - - public float getRowColumn(int row, int column) { - return MemUtil.INSTANCE.get(this, column, row); - } - - /** - * Set the matrix element at the given row and column to the specified value. - * - * @param row - * the row index in [0..2] - * @param column - * the colum index in [0..2] - * @param value - * the value - * @return this - */ - public Matrix3f setRowColumn(int row, int column, float value) { - return MemUtil.INSTANCE.set(this, column, row, value); - } - - /** - * Set this matrix to its own normal matrix. - *

- * The normal matrix of m is the transpose of the inverse of m. - *

- * Please note that, if this is an orthogonal matrix or a matrix whose columns are orthogonal vectors, - * then this method need not be invoked, since in that case this itself is its normal matrix. - * In this case, use {@link #set(Matrix3fc)} to set a given Matrix3f to this matrix. - * - * @see #set(Matrix3fc) - * - * @return this - */ - public Matrix3f normal() { - return normal(this); - } - - /** - * Compute a normal matrix from this matrix and store it into dest. - *

- * The normal matrix of m is the transpose of the inverse of m. - *

- * Please note that, if this is an orthogonal matrix or a matrix whose columns are orthogonal vectors, - * then this method need not be invoked, since in that case this itself is its normal matrix. - * In this case, use {@link #set(Matrix3fc)} to set a given Matrix3f to this matrix. - * - * @see #set(Matrix3fc) - * - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f normal(Matrix3f dest) { - float m00m11 = m00 * m11; - float m01m10 = m01 * m10; - float m02m10 = m02 * m10; - float m00m12 = m00 * m12; - float m01m12 = m01 * m12; - float m02m11 = m02 * m11; - float det = (m00m11 - m01m10) * m22 + (m02m10 - m00m12) * m21 + (m01m12 - m02m11) * m20; - float s = 1.0f / det; - /* Invert and transpose in one go */ - float nm00 = (m11 * m22 - m21 * m12) * s; - float nm01 = (m20 * m12 - m10 * m22) * s; - float nm02 = (m10 * m21 - m20 * m11) * s; - float nm10 = (m21 * m02 - m01 * m22) * s; - float nm11 = (m00 * m22 - m20 * m02) * s; - float nm12 = (m20 * m01 - m00 * m21) * s; - float nm20 = (m01m12 - m02m11) * s; - float nm21 = (m02m10 - m00m12) * s; - float nm22 = (m00m11 - m01m10) * s; - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - dest.m20 = nm20; - dest.m21 = nm21; - dest.m22 = nm22; - return dest; - } - - /** - * Compute the cofactor matrix of this. - *

- * The cofactor matrix can be used instead of {@link #normal()} to transform normals - * when the orientation of the normals with respect to the surface should be preserved. - * - * @return this - */ - public Matrix3f cofactor() { - return cofactor(this); - } - - /** - * Compute the cofactor matrix of this and store it into dest. - *

- * The cofactor matrix can be used instead of {@link #normal(Matrix3f)} to transform normals - * when the orientation of the normals with respect to the surface should be preserved. - * - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f cofactor(Matrix3f dest) { - float nm00 = m11 * m22 - m21 * m12; - float nm01 = m20 * m12 - m10 * m22; - float nm02 = m10 * m21 - m20 * m11; - float nm10 = m21 * m02 - m01 * m22; - float nm11 = m00 * m22 - m20 * m02; - float nm12 = m20 * m01 - m00 * m21; - float nm20 = m01 * m12 - m11 * m02; - float nm21 = m02 * m10 - m12 * m00; - float nm22 = m00 * m11 - m10 * m01; - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - dest.m20 = nm20; - dest.m21 = nm21; - dest.m22 = nm22; - return dest; - } - - public Vector3f getScale(Vector3f dest) { - return dest.set(Math.sqrt(m00 * m00 + m01 * m01 + m02 * m02), - Math.sqrt(m10 * m10 + m11 * m11 + m12 * m12), - Math.sqrt(m20 * m20 + m21 * m21 + m22 * m22)); - } - - public Vector3f positiveZ(Vector3f dir) { - dir.x = m10 * m21 - m11 * m20; - dir.y = m20 * m01 - m21 * m00; - dir.z = m00 * m11 - m01 * m10; - return dir.normalize(dir); - } - - public Vector3f normalizedPositiveZ(Vector3f dir) { - dir.x = m02; - dir.y = m12; - dir.z = m22; - return dir; - } - - public Vector3f positiveX(Vector3f dir) { - dir.x = m11 * m22 - m12 * m21; - dir.y = m02 * m21 - m01 * m22; - dir.z = m01 * m12 - m02 * m11; - return dir.normalize(dir); - } - - public Vector3f normalizedPositiveX(Vector3f dir) { - dir.x = m00; - dir.y = m10; - dir.z = m20; - return dir; - } - - public Vector3f positiveY(Vector3f dir) { - dir.x = m12 * m20 - m10 * m22; - dir.y = m00 * m22 - m02 * m20; - dir.z = m02 * m10 - m00 * m12; - return dir.normalize(dir); - } - - public Vector3f normalizedPositiveY(Vector3f dir) { - dir.x = m01; - dir.y = m11; - dir.z = m21; - return dir; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(m00); - result = prime * result + Float.floatToIntBits(m01); - result = prime * result + Float.floatToIntBits(m02); - result = prime * result + Float.floatToIntBits(m10); - result = prime * result + Float.floatToIntBits(m11); - result = prime * result + Float.floatToIntBits(m12); - result = prime * result + Float.floatToIntBits(m20); - result = prime * result + Float.floatToIntBits(m21); - result = prime * result + Float.floatToIntBits(m22); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Matrix3f other = (Matrix3f) obj; - if (Float.floatToIntBits(m00) != Float.floatToIntBits(other.m00)) - return false; - if (Float.floatToIntBits(m01) != Float.floatToIntBits(other.m01)) - return false; - if (Float.floatToIntBits(m02) != Float.floatToIntBits(other.m02)) - return false; - if (Float.floatToIntBits(m10) != Float.floatToIntBits(other.m10)) - return false; - if (Float.floatToIntBits(m11) != Float.floatToIntBits(other.m11)) - return false; - if (Float.floatToIntBits(m12) != Float.floatToIntBits(other.m12)) - return false; - if (Float.floatToIntBits(m20) != Float.floatToIntBits(other.m20)) - return false; - if (Float.floatToIntBits(m21) != Float.floatToIntBits(other.m21)) - return false; - if (Float.floatToIntBits(m22) != Float.floatToIntBits(other.m22)) - return false; - return true; - } - - public boolean equals(Matrix3fc m, float delta) { - if (this == m) - return true; - if (m == null) - return false; - if (!(m instanceof Matrix3f)) - return false; - if (!Runtime.equals(m00, m.m00(), delta)) - return false; - if (!Runtime.equals(m01, m.m01(), delta)) - return false; - if (!Runtime.equals(m02, m.m02(), delta)) - return false; - if (!Runtime.equals(m10, m.m10(), delta)) - return false; - if (!Runtime.equals(m11, m.m11(), delta)) - return false; - if (!Runtime.equals(m12, m.m12(), delta)) - return false; - if (!Runtime.equals(m20, m.m20(), delta)) - return false; - if (!Runtime.equals(m21, m.m21(), delta)) - return false; - if (!Runtime.equals(m22, m.m22(), delta)) - return false; - return true; - } - - /** - * Exchange the values of this matrix with the given other matrix. - * - * @param other - * the other matrix to exchange the values with - * @return this - */ - public Matrix3f swap(Matrix3f other) { - MemUtil.INSTANCE.swap(this, other); - return this; - } - - /** - * Component-wise add this and other. - * - * @param other - * the other addend - * @return this - */ - public Matrix3f add(Matrix3fc other) { - return add(other, this); - } - - public Matrix3f add(Matrix3fc other, Matrix3f dest) { - dest.m00 = m00 + other.m00(); - dest.m01 = m01 + other.m01(); - dest.m02 = m02 + other.m02(); - dest.m10 = m10 + other.m10(); - dest.m11 = m11 + other.m11(); - dest.m12 = m12 + other.m12(); - dest.m20 = m20 + other.m20(); - dest.m21 = m21 + other.m21(); - dest.m22 = m22 + other.m22(); - return dest; - } - - /** - * Component-wise subtract subtrahend from this. - * - * @param subtrahend - * the subtrahend - * @return this - */ - public Matrix3f sub(Matrix3fc subtrahend) { - return sub(subtrahend, this); - } - - public Matrix3f sub(Matrix3fc subtrahend, Matrix3f dest) { - dest.m00 = m00 - subtrahend.m00(); - dest.m01 = m01 - subtrahend.m01(); - dest.m02 = m02 - subtrahend.m02(); - dest.m10 = m10 - subtrahend.m10(); - dest.m11 = m11 - subtrahend.m11(); - dest.m12 = m12 - subtrahend.m12(); - dest.m20 = m20 - subtrahend.m20(); - dest.m21 = m21 - subtrahend.m21(); - dest.m22 = m22 - subtrahend.m22(); - return dest; - } - - /** - * Component-wise multiply this by other. - * - * @param other - * the other matrix - * @return this - */ - public Matrix3f mulComponentWise(Matrix3fc other) { - return mulComponentWise(other, this); - } - - public Matrix3f mulComponentWise(Matrix3fc other, Matrix3f dest) { - dest.m00 = m00 * other.m00(); - dest.m01 = m01 * other.m01(); - dest.m02 = m02 * other.m02(); - dest.m10 = m10 * other.m10(); - dest.m11 = m11 * other.m11(); - dest.m12 = m12 * other.m12(); - dest.m20 = m20 * other.m20(); - dest.m21 = m21 * other.m21(); - dest.m22 = m22 * other.m22(); - return dest; - } - - /** - * Set this matrix to a skew-symmetric matrix using the following layout: - *

-     *  0,  a, -b
-     * -a,  0,  c
-     *  b, -c,  0
-     * 
- * - * Reference: https://en.wikipedia.org - * - * @param a - * the value used for the matrix elements m01 and m10 - * @param b - * the value used for the matrix elements m02 and m20 - * @param c - * the value used for the matrix elements m12 and m21 - * @return this - */ - public Matrix3f setSkewSymmetric(float a, float b, float c) { - m00 = m11 = m22 = 0; - m01 = -a; - m02 = b; - m10 = a; - m12 = -c; - m20 = -b; - m21 = c; - return this; - } - - /** - * Linearly interpolate this and other using the given interpolation factor t - * and store the result in this. - *

- * If t is 0.0 then the result is this. If the interpolation factor is 1.0 - * then the result is other. - * - * @param other - * the other matrix - * @param t - * the interpolation factor between 0.0 and 1.0 - * @return this - */ - public Matrix3f lerp(Matrix3fc other, float t) { - return lerp(other, t, this); - } - - public Matrix3f lerp(Matrix3fc other, float t, Matrix3f dest) { - dest.m00 = Math.fma(other.m00() - m00, t, m00); - dest.m01 = Math.fma(other.m01() - m01, t, m01); - dest.m02 = Math.fma(other.m02() - m02, t, m02); - dest.m10 = Math.fma(other.m10() - m10, t, m10); - dest.m11 = Math.fma(other.m11() - m11, t, m11); - dest.m12 = Math.fma(other.m12() - m12, t, m12); - dest.m20 = Math.fma(other.m20() - m20, t, m20); - dest.m21 = Math.fma(other.m21() - m21, t, m21); - dest.m22 = Math.fma(other.m22() - m22, t, m22); - return dest; - } - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with direction - * and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying it, - * use {@link #rotationTowards(Vector3fc, Vector3fc) rotationTowards()}. - *

- * This method is equivalent to calling: mul(new Matrix3f().lookAlong(new Vector3f(dir).negate(), up).invert(), dest) - * - * @see #rotateTowards(float, float, float, float, float, float, Matrix3f) - * @see #rotationTowards(Vector3fc, Vector3fc) - * - * @param direction - * the direction to rotate towards - * @param up - * the model's up vector - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f rotateTowards(Vector3fc direction, Vector3fc up, Matrix3f dest) { - return rotateTowards(direction.x(), direction.y(), direction.z(), up.x(), up.y(), up.z(), dest); - } - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with direction. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying it, - * use {@link #rotationTowards(Vector3fc, Vector3fc) rotationTowards()}. - *

- * This method is equivalent to calling: mul(new Matrix3f().lookAlong(new Vector3f(dir).negate(), up).invert()) - * - * @see #rotateTowards(float, float, float, float, float, float) - * @see #rotationTowards(Vector3fc, Vector3fc) - * - * @param direction - * the direction to orient towards - * @param up - * the up vector - * @return this - */ - public Matrix3f rotateTowards(Vector3fc direction, Vector3fc up) { - return rotateTowards(direction.x(), direction.y(), direction.z(), up.x(), up.y(), up.z(), this); - } - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with direction. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying it, - * use {@link #rotationTowards(float, float, float, float, float, float) rotationTowards()}. - *

- * This method is equivalent to calling: mul(new Matrix3f().lookAlong(-dirX, -dirY, -dirZ, upX, upY, upZ).invert()) - * - * @see #rotateTowards(Vector3fc, Vector3fc) - * @see #rotationTowards(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to rotate towards - * @param dirY - * the y-coordinate of the direction to rotate towards - * @param dirZ - * the z-coordinate of the direction to rotate towards - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix3f rotateTowards(float dirX, float dirY, float dirZ, float upX, float upY, float upZ) { - return rotateTowards(dirX, dirY, dirZ, upX, upY, upZ, this); - } - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with dir - * and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying it, - * use {@link #rotationTowards(float, float, float, float, float, float) rotationTowards()}. - *

- * This method is equivalent to calling: mul(new Matrix3f().lookAlong(-dirX, -dirY, -dirZ, upX, upY, upZ).invert(), dest) - * - * @see #rotateTowards(Vector3fc, Vector3fc) - * @see #rotationTowards(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to rotate towards - * @param dirY - * the y-coordinate of the direction to rotate towards - * @param dirZ - * the z-coordinate of the direction to rotate towards - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f rotateTowards(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Matrix3f dest) { - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - float ndirX = dirX * invDirLength; - float ndirY = dirY * invDirLength; - float ndirZ = dirZ * invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * ndirZ - upZ * ndirY; - leftY = upZ * ndirX - upX * ndirZ; - leftZ = upX * ndirY - upY * ndirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = ndirY * leftZ - ndirZ * leftY; - float upnY = ndirZ * leftX - ndirX * leftZ; - float upnZ = ndirX * leftY - ndirY * leftX; - float rm00 = leftX; - float rm01 = leftY; - float rm02 = leftZ; - float rm10 = upnX; - float rm11 = upnY; - float rm12 = upnZ; - float rm20 = ndirX; - float rm21 = ndirY; - float rm22 = ndirZ; - float nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; - float nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; - float nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; - float nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; - float nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; - float nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; - dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; - dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; - dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; - dest.m00 = nm00; - dest.m01 = nm01; - dest.m02 = nm02; - dest.m10 = nm10; - dest.m11 = nm11; - dest.m12 = nm12; - return dest; - } - - /** - * Set this matrix to a model transformation for a right-handed coordinate system, - * that aligns the local -z axis with center - eye. - *

- * In order to apply the rotation transformation to a previous existing transformation, - * use {@link #rotateTowards(float, float, float, float, float, float) rotateTowards}. - *

- * This method is equivalent to calling: setLookAlong(new Vector3f(dir).negate(), up).invert() - * - * @see #rotationTowards(Vector3fc, Vector3fc) - * @see #rotateTowards(float, float, float, float, float, float) - * - * @param dir - * the direction to orient the local -z axis towards - * @param up - * the up vector - * @return this - */ - public Matrix3f rotationTowards(Vector3fc dir, Vector3fc up) { - return rotationTowards(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z()); - } - - /** - * Set this matrix to a model transformation for a right-handed coordinate system, - * that aligns the local -z axis with center - eye. - *

- * In order to apply the rotation transformation to a previous existing transformation, - * use {@link #rotateTowards(float, float, float, float, float, float) rotateTowards}. - *

- * This method is equivalent to calling: setLookAlong(-dirX, -dirY, -dirZ, upX, upY, upZ).invert() - * - * @see #rotateTowards(Vector3fc, Vector3fc) - * @see #rotationTowards(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to rotate towards - * @param dirY - * the y-coordinate of the direction to rotate towards - * @param dirZ - * the z-coordinate of the direction to rotate towards - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix3f rotationTowards(float dirX, float dirY, float dirZ, float upX, float upY, float upZ) { - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - float ndirX = dirX * invDirLength; - float ndirY = dirY * invDirLength; - float ndirZ = dirZ * invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * ndirZ - upZ * ndirY; - leftY = upZ * ndirX - upX * ndirZ; - leftZ = upX * ndirY - upY * ndirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = ndirY * leftZ - ndirZ * leftY; - float upnY = ndirZ * leftX - ndirX * leftZ; - float upnZ = ndirX * leftY - ndirY * leftX; - this.m00 = leftX; - this.m01 = leftY; - this.m02 = leftZ; - this.m10 = upnX; - this.m11 = upnY; - this.m12 = upnZ; - this.m20 = ndirX; - this.m21 = ndirY; - this.m22 = ndirZ; - return this; - } - - public Vector3f getEulerAnglesZYX(Vector3f dest) { - dest.x = Math.atan2(m12, m22); - dest.y = Math.atan2(-m02, Math.sqrt(1.0f - m02 * m02)); - dest.z = Math.atan2(m01, m00); - return dest; - } - - public Vector3f getEulerAnglesXYZ(Vector3f dest) { - dest.x = Math.atan2(-m21, m22); - dest.y = Math.atan2(m20, Math.sqrt(1.0f - m20 * m20)); - dest.z = Math.atan2(-m10, m00); - return dest; - } - - /** - * Apply an oblique projection transformation to this matrix with the given values for a and - * b. - *

- * If M is this matrix and O the oblique transformation matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * oblique transformation will be applied first! - *

- * The oblique transformation is defined as: - *

-     * x' = x + a*z
-     * y' = y + a*z
-     * z' = z
-     * 
- * or in matrix form: - *
-     * 1 0 a
-     * 0 1 b
-     * 0 0 1
-     * 
- * - * @param a - * the value for the z factor that applies to x - * @param b - * the value for the z factor that applies to y - * @return this - */ - public Matrix3f obliqueZ(float a, float b) { - this.m20 = m00 * a + m10 * b + m20; - this.m21 = m01 * a + m11 * b + m21; - this.m22 = m02 * a + m12 * b + m22; - return this; - } - - /** - * Apply an oblique projection transformation to this matrix with the given values for a and - * b and store the result in dest. - *

- * If M is this matrix and O the oblique transformation matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * oblique transformation will be applied first! - *

- * The oblique transformation is defined as: - *

-     * x' = x + a*z
-     * y' = y + a*z
-     * z' = z
-     * 
- * or in matrix form: - *
-     * 1 0 a
-     * 0 1 b
-     * 0 0 1
-     * 
- * - * @param a - * the value for the z factor that applies to x - * @param b - * the value for the z factor that applies to y - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f obliqueZ(float a, float b, Matrix3f dest) { - dest.m00 = m00; - dest.m01 = m01; - dest.m02 = m02; - dest.m10 = m10; - dest.m11 = m11; - dest.m12 = m12; - dest.m20 = m00 * a + m10 * b + m20; - dest.m21 = m01 * a + m11 * b + m21; - dest.m22 = m02 * a + m12 * b + m22; - return dest; - } - - public Matrix3f reflect(float nx, float ny, float nz, Matrix3f dest) { - float da = nx + nx, db = ny + ny, dc = nz + nz; - float rm00 = 1.0f - da * nx; - float rm01 = -da * ny; - float rm02 = -da * nz; - float rm10 = -db * nx; - float rm11 = 1.0f - db * ny; - float rm12 = -db * nz; - float rm20 = -dc * nx; - float rm21 = -dc * ny; - float rm22 = 1.0f - dc * nz; - float nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; - float nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; - float nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; - float nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; - float nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; - float nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; - return dest - ._m20(m00 * rm20 + m10 * rm21 + m20 * rm22) - ._m21(m01 * rm20 + m11 * rm21 + m21 * rm22) - ._m22(m02 * rm20 + m12 * rm21 + m22 * rm22) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12); - } - - /** - * Apply a mirror/reflection transformation to this matrix that reflects through the given plane - * specified via the plane normal. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param nx - * the x-coordinate of the plane normal - * @param ny - * the y-coordinate of the plane normal - * @param nz - * the z-coordinate of the plane normal - * @return this - */ - public Matrix3f reflect(float nx, float ny, float nz) { - return reflect(nx, ny, nz, this); - } - - /** - * Apply a mirror/reflection transformation to this matrix that reflects through the given plane - * specified via the plane normal. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param normal - * the plane normal - * @return this - */ - public Matrix3f reflect(Vector3fc normal) { - return reflect(normal.x(), normal.y(), normal.z()); - } - - /** - * Apply a mirror/reflection transformation to this matrix that reflects about a plane - * specified via the plane orientation. - *

- * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. - * It is assumed that the default mirror plane's normal is (0, 0, 1). So, if the given {@link Quaternionfc} is - * the identity (does not apply any additional rotation), the reflection plane will be z=0. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param orientation - * the plane orientation - * @return this - */ - public Matrix3f reflect(Quaternionfc orientation) { - return reflect(orientation, this); - } - - public Matrix3f reflect(Quaternionfc orientation, Matrix3f dest) { - float num1 = orientation.x() + orientation.x(); - float num2 = orientation.y() + orientation.y(); - float num3 = orientation.z() + orientation.z(); - float normalX = orientation.x() * num3 + orientation.w() * num2; - float normalY = orientation.y() * num3 - orientation.w() * num1; - float normalZ = 1.0f - (orientation.x() * num1 + orientation.y() * num2); - return reflect(normalX, normalY, normalZ, dest); - } - - public Matrix3f reflect(Vector3fc normal, Matrix3f dest) { - return reflect(normal.x(), normal.y(), normal.z(), dest); - } - - /** - * Set this matrix to a mirror/reflection transformation that reflects through the given plane - * specified via the plane normal. - * - * @param nx - * the x-coordinate of the plane normal - * @param ny - * the y-coordinate of the plane normal - * @param nz - * the z-coordinate of the plane normal - * @return this - */ - public Matrix3f reflection(float nx, float ny, float nz) { - float da = nx + nx, db = ny + ny, dc = nz + nz; - this._m00(1.0f - da * nx); - this._m01(-da * ny); - this._m02(-da * nz); - this._m10(-db * nx); - this._m11(1.0f - db * ny); - this._m12(-db * nz); - this._m20(-dc * nx); - this._m21(-dc * ny); - this._m22(1.0f - dc * nz); - return this; - } - - /** - * Set this matrix to a mirror/reflection transformation that reflects through the given plane - * specified via the plane normal. - * - * @param normal - * the plane normal - * @return this - */ - public Matrix3f reflection(Vector3fc normal) { - return reflection(normal.x(), normal.y(), normal.z()); - } - - /** - * Set this matrix to a mirror/reflection transformation that reflects through a plane - * specified via the plane orientation. - *

- * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. - * It is assumed that the default mirror plane's normal is (0, 0, 1). So, if the given {@link Quaternionfc} is - * the identity (does not apply any additional rotation), the reflection plane will be z=0, offset by the given point. - * - * @param orientation - * the plane orientation - * @return this - */ - public Matrix3f reflection(Quaternionfc orientation) { - float num1 = orientation.x() + orientation.x(); - float num2 = orientation.y() + orientation.y(); - float num3 = orientation.z() + orientation.z(); - float normalX = orientation.x() * num3 + orientation.w() * num2; - float normalY = orientation.y() * num3 - orientation.w() * num1; - float normalZ = 1.0f - (orientation.x() * num1 + orientation.y() * num2); - return reflection(normalX, normalY, normalZ); - } - - public boolean isFinite() { - return Math.isFinite(m00) && Math.isFinite(m01) && Math.isFinite(m02) && - Math.isFinite(m10) && Math.isFinite(m11) && Math.isFinite(m12) && - Math.isFinite(m20) && Math.isFinite(m21) && Math.isFinite(m22); - } - - public float quadraticFormProduct(float x, float y, float z) { - float Axx = m00 * x + m10 * y + m20 * z; - float Axy = m01 * x + m11 * y + m21 * z; - float Axz = m02 * x + m12 * y + m22 * z; - return x * Axx + y * Axy + z * Axz; - } - - public float quadraticFormProduct(Vector3fc v) { - return quadraticFormProduct(v.x(), v.y(), v.z()); - } - - /** - * Multiply this by the matrix - *

-     * 1 0 0
-     * 0 0 1
-     * 0 1 0
-     * 
- * - * @return this - */ - public Matrix3f mapXZY() { - return mapXZY(this); - } - public Matrix3f mapXZY(Matrix3f dest) { - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(m00)._m01(m01)._m02(m02)._m10(m20)._m11(m21)._m12(m22)._m20(m10)._m21(m11)._m22(m12); - } - /** - * Multiply this by the matrix - *
-     * 1 0  0
-     * 0 0 -1
-     * 0 1  0
-     * 
- * - * @return this - */ - public Matrix3f mapXZnY() { - return mapXZnY(this); - } - public Matrix3f mapXZnY(Matrix3f dest) { - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(m00)._m01(m01)._m02(m02)._m10(m20)._m11(m21)._m12(m22)._m20(-m10)._m21(-m11)._m22(-m12); - } - /** - * Multiply this by the matrix - *
-     * 1  0  0
-     * 0 -1  0
-     * 0  0 -1
-     * 
- * - * @return this - */ - public Matrix3f mapXnYnZ() { - return mapXnYnZ(this); - } - public Matrix3f mapXnYnZ(Matrix3f dest) { - return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-m20)._m21(-m21)._m22(-m22); - } - /** - * Multiply this by the matrix - *
-     * 1  0 0
-     * 0  0 1
-     * 0 -1 0
-     * 
- * - * @return this - */ - public Matrix3f mapXnZY() { - return mapXnZY(this); - } - public Matrix3f mapXnZY(Matrix3f dest) { - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(m10)._m21(m11)._m22(m12); - } - /** - * Multiply this by the matrix - *
-     * 1  0  0
-     * 0  0 -1
-     * 0 -1  0
-     * 
- * - * @return this - */ - public Matrix3f mapXnZnY() { - return mapXnZnY(this); - } - public Matrix3f mapXnZnY(Matrix3f dest) { - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-m10)._m21(-m11)._m22(-m12); - } - /** - * Multiply this by the matrix - *
-     * 0 1 0
-     * 1 0 0
-     * 0 0 1
-     * 
- * - * @return this - */ - public Matrix3f mapYXZ() { - return mapYXZ(this); - } - public Matrix3f mapYXZ(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m10)._m01(m11)._m02(m12)._m10(m00)._m11(m01)._m12(m02)._m20(m20)._m21(m21)._m22(m22); - } - /** - * Multiply this by the matrix - *
-     * 0 1  0
-     * 1 0  0
-     * 0 0 -1
-     * 
- * - * @return this - */ - public Matrix3f mapYXnZ() { - return mapYXnZ(this); - } - public Matrix3f mapYXnZ(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m10)._m01(m11)._m02(m12)._m10(m00)._m11(m01)._m12(m02)._m20(-m20)._m21(-m21)._m22(-m22); - } - /** - * Multiply this by the matrix - *
-     * 0 0 1
-     * 1 0 0
-     * 0 1 0
-     * 
- * - * @return this - */ - public Matrix3f mapYZX() { - return mapYZX(this); - } - public Matrix3f mapYZX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m10)._m01(m11)._m02(m12)._m10(m20)._m11(m21)._m12(m22)._m20(m00)._m21(m01)._m22(m02); - } - /** - * Multiply this by the matrix - *
-     * 0 0 -1
-     * 1 0  0
-     * 0 1  0
-     * 
- * - * @return this - */ - public Matrix3f mapYZnX() { - return mapYZnX(this); - } - public Matrix3f mapYZnX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m10)._m01(m11)._m02(m12)._m10(m20)._m11(m21)._m12(m22)._m20(-m00)._m21(-m01)._m22(-m02); - } - /** - * Multiply this by the matrix - *
-     * 0 -1 0
-     * 1  0 0
-     * 0  0 1
-     * 
- * - * @return this - */ - public Matrix3f mapYnXZ() { - return mapYnXZ(this); - } - public Matrix3f mapYnXZ(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m10)._m01(m11)._m02(m12)._m10(-m00)._m11(-m01)._m12(-m02)._m20(m20)._m21(m21)._m22(m22); - } - /** - * Multiply this by the matrix - *
-     * 0 -1  0
-     * 1  0  0
-     * 0  0 -1
-     * 
- * - * @return this - */ - public Matrix3f mapYnXnZ() { - return mapYnXnZ(this); - } - public Matrix3f mapYnXnZ(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m10)._m01(m11)._m02(m12)._m10(-m00)._m11(-m01)._m12(-m02)._m20(-m20)._m21(-m21)._m22(-m22); - } - /** - * Multiply this by the matrix - *
-     * 0  0 1
-     * 1  0 0
-     * 0 -1 0
-     * 
- * - * @return this - */ - public Matrix3f mapYnZX() { - return mapYnZX(this); - } - public Matrix3f mapYnZX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m10)._m01(m11)._m02(m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(m00)._m21(m01)._m22(m02); - } - /** - * Multiply this by the matrix - *
-     * 0  0 -1
-     * 1  0  0
-     * 0 -1  0
-     * 
- * - * @return this - */ - public Matrix3f mapYnZnX() { - return mapYnZnX(this); - } - public Matrix3f mapYnZnX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m10)._m01(m11)._m02(m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-m00)._m21(-m01)._m22(-m02); - } - /** - * Multiply this by the matrix - *
-     * 0 1 0
-     * 0 0 1
-     * 1 0 0
-     * 
- * - * @return this - */ - public Matrix3f mapZXY() { - return mapZXY(this); - } - public Matrix3f mapZXY(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(m20)._m01(m21)._m02(m22)._m10(m00)._m11(m01)._m12(m02)._m20(m10)._m21(m11)._m22(m12); - } - /** - * Multiply this by the matrix - *
-     * 0 1  0
-     * 0 0 -1
-     * 1 0  0
-     * 
- * - * @return this - */ - public Matrix3f mapZXnY() { - return mapZXnY(this); - } - public Matrix3f mapZXnY(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(m20)._m01(m21)._m02(m22)._m10(m00)._m11(m01)._m12(m02)._m20(-m10)._m21(-m11)._m22(-m12); - } - /** - * Multiply this by the matrix - *
-     * 0 0 1
-     * 0 1 0
-     * 1 0 0
-     * 
- * - * @return this - */ - public Matrix3f mapZYX() { - return mapZYX(this); - } - public Matrix3f mapZYX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m20)._m01(m21)._m02(m22)._m10(m10)._m11(m11)._m12(m12)._m20(m00)._m21(m01)._m22(m02); - } - /** - * Multiply this by the matrix - *
-     * 0 0 -1
-     * 0 1  0
-     * 1 0  0
-     * 
- * - * @return this - */ - public Matrix3f mapZYnX() { - return mapZYnX(this); - } - public Matrix3f mapZYnX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m20)._m01(m21)._m02(m22)._m10(m10)._m11(m11)._m12(m12)._m20(-m00)._m21(-m01)._m22(-m02); - } - /** - * Multiply this by the matrix - *
-     * 0 -1 0
-     * 0  0 1
-     * 1  0 0
-     * 
- * - * @return this - */ - public Matrix3f mapZnXY() { - return mapZnXY(this); - } - public Matrix3f mapZnXY(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(m20)._m01(m21)._m02(m22)._m10(-m00)._m11(-m01)._m12(-m02)._m20(m10)._m21(m11)._m22(m12); - } - /** - * Multiply this by the matrix - *
-     * 0 -1  0
-     * 0  0 -1
-     * 1  0  0
-     * 
- * - * @return this - */ - public Matrix3f mapZnXnY() { - return mapZnXnY(this); - } - public Matrix3f mapZnXnY(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(m20)._m01(m21)._m02(m22)._m10(-m00)._m11(-m01)._m12(-m02)._m20(-m10)._m21(-m11)._m22(-m12); - } - /** - * Multiply this by the matrix - *
-     * 0  0 1
-     * 0 -1 0
-     * 1  0 0
-     * 
- * - * @return this - */ - public Matrix3f mapZnYX() { - return mapZnYX(this); - } - public Matrix3f mapZnYX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m20)._m01(m21)._m02(m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(m00)._m21(m01)._m22(m02); - } - /** - * Multiply this by the matrix - *
-     * 0  0 -1
-     * 0 -1  0
-     * 1  0  0
-     * 
- * - * @return this - */ - public Matrix3f mapZnYnX() { - return mapZnYnX(this); - } - public Matrix3f mapZnYnX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(m20)._m01(m21)._m02(m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-m00)._m21(-m01)._m22(-m02); - } - /** - * Multiply this by the matrix - *
-     * -1 0  0
-     *  0 1  0
-     *  0 0 -1
-     * 
- * - * @return this - */ - public Matrix3f mapnXYnZ() { - return mapnXYnZ(this); - } - public Matrix3f mapnXYnZ(Matrix3f dest) { - return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m10)._m11(m11)._m12(m12)._m20(-m20)._m21(-m21)._m22(-m22); - } - /** - * Multiply this by the matrix - *
-     * -1 0 0
-     *  0 0 1
-     *  0 1 0
-     * 
- * - * @return this - */ - public Matrix3f mapnXZY() { - return mapnXZY(this); - } - public Matrix3f mapnXZY(Matrix3f dest) { - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m20)._m11(m21)._m12(m22)._m20(m10)._m21(m11)._m22(m12); - } - /** - * Multiply this by the matrix - *
-     * -1 0  0
-     *  0 0 -1
-     *  0 1  0
-     * 
- * - * @return this - */ - public Matrix3f mapnXZnY() { - return mapnXZnY(this); - } - public Matrix3f mapnXZnY(Matrix3f dest) { - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m20)._m11(m21)._m12(m22)._m20(-m10)._m21(-m11)._m22(-m12); - } - /** - * Multiply this by the matrix - *
-     * -1  0 0
-     *  0 -1 0
-     *  0  0 1
-     * 
- * - * @return this - */ - public Matrix3f mapnXnYZ() { - return mapnXnYZ(this); - } - public Matrix3f mapnXnYZ(Matrix3f dest) { - return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(m20)._m21(m21)._m22(m22); - } - /** - * Multiply this by the matrix - *
-     * -1  0  0
-     *  0 -1  0
-     *  0  0 -1
-     * 
- * - * @return this - */ - public Matrix3f mapnXnYnZ() { - return mapnXnYnZ(this); - } - public Matrix3f mapnXnYnZ(Matrix3f dest) { - return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-m20)._m21(-m21)._m22(-m22); - } - /** - * Multiply this by the matrix - *
-     * -1  0 0
-     *  0  0 1
-     *  0 -1 0
-     * 
- * - * @return this - */ - public Matrix3f mapnXnZY() { - return mapnXnZY(this); - } - public Matrix3f mapnXnZY(Matrix3f dest) { - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(m10)._m21(m11)._m22(m12); - } - /** - * Multiply this by the matrix - *
-     * -1  0  0
-     *  0  0 -1
-     *  0 -1  0
-     * 
- * - * @return this - */ - public Matrix3f mapnXnZnY() { - return mapnXnZnY(this); - } - public Matrix3f mapnXnZnY(Matrix3f dest) { - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-m10)._m21(-m11)._m22(-m12); - } - /** - * Multiply this by the matrix - *
-     *  0 1 0
-     * -1 0 0
-     *  0 0 1
-     * 
- * - * @return this - */ - public Matrix3f mapnYXZ() { - return mapnYXZ(this); - } - public Matrix3f mapnYXZ(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(m00)._m11(m01)._m12(m02)._m20(m20)._m21(m21)._m22(m22); - } - /** - * Multiply this by the matrix - *
-     *  0 1  0
-     * -1 0  0
-     *  0 0 -1
-     * 
- * - * @return this - */ - public Matrix3f mapnYXnZ() { - return mapnYXnZ(this); - } - public Matrix3f mapnYXnZ(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(m00)._m11(m01)._m12(m02)._m20(-m20)._m21(-m21)._m22(-m22); - } - /** - * Multiply this by the matrix - *
-     *  0 0 1
-     * -1 0 0
-     *  0 1 0
-     * 
- * - * @return this - */ - public Matrix3f mapnYZX() { - return mapnYZX(this); - } - public Matrix3f mapnYZX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(m20)._m11(m21)._m12(m22)._m20(m00)._m21(m01)._m22(m02); - } - /** - * Multiply this by the matrix - *
-     *  0 0 -1
-     * -1 0  0
-     *  0 1  0
-     * 
- * - * @return this - */ - public Matrix3f mapnYZnX() { - return mapnYZnX(this); - } - public Matrix3f mapnYZnX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(m20)._m11(m21)._m12(m22)._m20(-m00)._m21(-m01)._m22(-m02); - } - /** - * Multiply this by the matrix - *
-     *  0 -1 0
-     * -1  0 0
-     *  0  0 1
-     * 
- * - * @return this - */ - public Matrix3f mapnYnXZ() { - return mapnYnXZ(this); - } - public Matrix3f mapnYnXZ(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-m00)._m11(-m01)._m12(-m02)._m20(m20)._m21(m21)._m22(m22); - } - /** - * Multiply this by the matrix - *
-     *  0 -1  0
-     * -1  0  0
-     *  0  0 -1
-     * 
- * - * @return this - */ - public Matrix3f mapnYnXnZ() { - return mapnYnXnZ(this); - } - public Matrix3f mapnYnXnZ(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-m00)._m11(-m01)._m12(-m02)._m20(-m20)._m21(-m21)._m22(-m22); - } - /** - * Multiply this by the matrix - *
-     *  0  0 1
-     * -1  0 0
-     *  0 -1 0
-     * 
- * - * @return this - */ - public Matrix3f mapnYnZX() { - return mapnYnZX(this); - } - public Matrix3f mapnYnZX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(m00)._m21(m01)._m22(m02); - } - /** - * Multiply this by the matrix - *
-     *  0  0 -1
-     * -1  0  0
-     *  0 -1  0
-     * 
- * - * @return this - */ - public Matrix3f mapnYnZnX() { - return mapnYnZnX(this); - } - public Matrix3f mapnYnZnX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-m00)._m21(-m01)._m22(-m02); - } - /** - * Multiply this by the matrix - *
-     *  0 1 0
-     *  0 0 1
-     * -1 0 0
-     * 
- * - * @return this - */ - public Matrix3f mapnZXY() { - return mapnZXY(this); - } - public Matrix3f mapnZXY(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(m00)._m11(m01)._m12(m02)._m20(m10)._m21(m11)._m22(m12); - } - /** - * Multiply this by the matrix - *
-     *  0 1  0
-     *  0 0 -1
-     * -1 0  0
-     * 
- * - * @return this - */ - public Matrix3f mapnZXnY() { - return mapnZXnY(this); - } - public Matrix3f mapnZXnY(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(m00)._m11(m01)._m12(m02)._m20(-m10)._m21(-m11)._m22(-m12); - } - /** - * Multiply this by the matrix - *
-     *  0 0 1
-     *  0 1 0
-     * -1 0 0
-     * 
- * - * @return this - */ - public Matrix3f mapnZYX() { - return mapnZYX(this); - } - public Matrix3f mapnZYX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(m10)._m11(m11)._m12(m12)._m20(m00)._m21(m01)._m22(m02); - } - /** - * Multiply this by the matrix - *
-     *  0 0 -1
-     *  0 1  0
-     * -1 0  0
-     * 
- * - * @return this - */ - public Matrix3f mapnZYnX() { - return mapnZYnX(this); - } - public Matrix3f mapnZYnX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(m10)._m11(m11)._m12(m12)._m20(-m00)._m21(-m01)._m22(-m02); - } - /** - * Multiply this by the matrix - *
-     *  0 -1 0
-     *  0  0 1
-     * -1  0 0
-     * 
- * - * @return this - */ - public Matrix3f mapnZnXY() { - return mapnZnXY(this); - } - public Matrix3f mapnZnXY(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-m00)._m11(-m01)._m12(-m02)._m20(m10)._m21(m11)._m22(m12); - } - /** - * Multiply this by the matrix - *
-     *  0 -1  0
-     *  0  0 -1
-     * -1  0  0
-     * 
- * - * @return this - */ - public Matrix3f mapnZnXnY() { - return mapnZnXnY(this); - } - public Matrix3f mapnZnXnY(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - float m10 = this.m10, m11 = this.m11, m12 = this.m12; - return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-m00)._m11(-m01)._m12(-m02)._m20(-m10)._m21(-m11)._m22(-m12); - } - /** - * Multiply this by the matrix - *
-     *  0  0 1
-     *  0 -1 0
-     * -1  0 0
-     * 
- * - * @return this - */ - public Matrix3f mapnZnYX() { - return mapnZnYX(this); - } - public Matrix3f mapnZnYX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(m00)._m21(m01)._m22(m02); - } - /** - * Multiply this by the matrix - *
-     *  0  0 -1
-     *  0 -1  0
-     * -1  0  0
-     * 
- * - * @return this - */ - public Matrix3f mapnZnYnX() { - return mapnZnYnX(this); - } - public Matrix3f mapnZnYnX(Matrix3f dest) { - float m00 = this.m00, m01 = this.m01, m02 = this.m02; - return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-m00)._m21(-m01)._m22(-m02); - } - - /** - * Multiply this by the matrix - *
-     * -1 0 0
-     *  0 1 0
-     *  0 0 1
-     * 
- * - * @return this - */ - public Matrix3f negateX() { - return _m00(-m00)._m01(-m01)._m02(-m02); - } - public Matrix3f negateX(Matrix3f dest) { - return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m10)._m11(m11)._m12(m12)._m20(m20)._m21(m21)._m22(m22); - } - - /** - * Multiply this by the matrix - *
-     * 1  0 0
-     * 0 -1 0
-     * 0  0 1
-     * 
- * - * @return this - */ - public Matrix3f negateY() { - return _m10(-m10)._m11(-m11)._m12(-m12); - } - public Matrix3f negateY(Matrix3f dest) { - return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(m20)._m21(m21)._m22(m22); - } - - /** - * Multiply this by the matrix - *
-     * 1 0  0
-     * 0 1  0
-     * 0 0 -1
-     * 
- * - * @return this - */ - public Matrix3f negateZ() { - return _m20(-m20)._m21(-m21)._m22(-m22); - } - public Matrix3f negateZ(Matrix3f dest) { - return dest._m00(m00)._m01(m01)._m02(m02)._m10(m10)._m11(m11)._m12(m12)._m20(-m20)._m21(-m21)._m22(-m22); - } - - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix3fStack.java b/src/main/java/com/jozufozu/flywheel/util/joml/Matrix3fStack.java deleted file mode 100644 index f2484fc61..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix3fStack.java +++ /dev/null @@ -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. - *

- * 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 current 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. - *

- * 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 this - * {@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. - *

- * 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. - *

- * 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; - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix3fc.java b/src/main/java/com/jozufozu/flywheel/util/joml/Matrix3fc.java deleted file mode 100644 index 1e42fa041..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix3fc.java +++ /dev/null @@ -1,2169 +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 3x3 matrix of single-precision floats. - * - * @author Kai Burjack - */ -public interface Matrix3fc { - - /** - * Return the value of the matrix element at column 0 and row 0. - * - * @return the value of the matrix element - */ - float m00(); - - /** - * Return the value of the matrix element at column 0 and row 1. - * - * @return the value of the matrix element - */ - float m01(); - - /** - * Return the value of the matrix element at column 0 and row 2. - * - * @return the value of the matrix element - */ - float m02(); - - /** - * Return the value of the matrix element at column 1 and row 0. - * - * @return the value of the matrix element - */ - float m10(); - - /** - * Return the value of the matrix element at column 1 and row 1. - * - * @return the value of the matrix element - */ - float m11(); - - /** - * Return the value of the matrix element at column 1 and row 2. - * - * @return the value of the matrix element - */ - float m12(); - - /** - * Return the value of the matrix element at column 2 and row 0. - * - * @return the value of the matrix element - */ - float m20(); - - /** - * Return the value of the matrix element at column 2 and row 1. - * - * @return the value of the matrix element - */ - float m21(); - - /** - * Return the value of the matrix element at column 2 and row 2. - * - * @return the value of the matrix element - */ - float m22(); - - /** - * Multiply this matrix by the supplied right matrix and store the result in dest. - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param right - * the right operand of the matrix multiplication - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mul(Matrix3fc right, Matrix3f dest); - - /** - * Pre-multiply this matrix by the supplied left matrix and store the result in dest. - *

- * If M is this matrix and L the left matrix, - * then the new matrix will be L * M. So when transforming a - * vector v with the new matrix by using L * M * v, the - * transformation of this matrix will be applied first! - * - * @param left - * the left operand of the matrix multiplication - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix3f mulLocal(Matrix3fc left, Matrix3f dest); - - /** - * Return the determinant of this matrix. - * - * @return the determinant - */ - float determinant(); - - /** - * Invert the this matrix and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f invert(Matrix3f dest); - - /** - * Transpose this matrix and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f transpose(Matrix3f dest); - - /** - * Get the current values of this matrix and store them into - * dest. - * - * @param dest - * the destination matrix - * @return the passed in destination - */ - Matrix3f get(Matrix3f dest); - - /** - * Get the current values of this matrix and store them as - * the rotational component of dest. All other values of dest will - * be set to identity. - * - * @see Matrix4f#set(Matrix3fc) - * - * @param dest - * the destination matrix - * @return the passed in destination - */ - Matrix4f get(Matrix4f dest); - - /** - * Get the current values of this matrix and store the represented rotation - * into the given {@link AxisAngle4f}. - * - * @see AxisAngle4f#set(Matrix3fc) - * - * @param dest - * the destination {@link AxisAngle4f} - * @return the passed in destination - */ - AxisAngle4f getRotation(AxisAngle4f dest); - - /** - * Get the current values of this matrix and store the represented rotation - * into the given {@link Quaternionf}. - *

- * This method assumes that the three column vectors of this matrix are not normalized and - * thus allows to ignore any additional scaling factor that is applied to the matrix. - * - * @see Quaternionf#setFromUnnormalized(Matrix3fc) - * - * @param dest - * the destination {@link Quaternionf} - * @return the passed in destination - */ - Quaternionf getUnnormalizedRotation(Quaternionf dest); - - /** - * Get the current values of this matrix and store the represented rotation - * into the given {@link Quaternionf}. - *

- * This method assumes that the three column vectors of this matrix are normalized. - * - * @see Quaternionf#setFromNormalized(Matrix3fc) - * - * @param dest - * the destination {@link Quaternionf} - * @return the passed in destination - */ - Quaternionf getNormalizedRotation(Quaternionf dest); - - /** - * Store this matrix in column-major order into the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the matrix is stored, use {@link #get(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @see #get(int, FloatBuffer) - * - * @param buffer - * will receive the values of this matrix in column-major order at its current position - * @return the passed in buffer - */ - FloatBuffer get(FloatBuffer buffer); - - /** - * Store this matrix in column-major order into the supplied {@link FloatBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given FloatBuffer. - * - * @param index - * the absolute position into the FloatBuffer - * @param buffer - * will receive the values of this matrix in column-major order - * @return the passed in buffer - */ - FloatBuffer get(int index, FloatBuffer buffer); - - /** - * Store this matrix in column-major order into the supplied {@link ByteBuffer} at the current - * buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the matrix is stored, use {@link #get(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @see #get(int, ByteBuffer) - * - * @param buffer - * will receive the values of this matrix in column-major order at its current position - * @return the passed in buffer - */ - ByteBuffer get(ByteBuffer buffer); - - /** - * Store this matrix in column-major order into the supplied {@link ByteBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given ByteBuffer. - * - * @param index - * the absolute position into the ByteBuffer - * @param buffer - * will receive the values of this matrix in column-major order - * @return the passed in buffer - */ - ByteBuffer get(int index, ByteBuffer buffer); - - /** - * Store this matrix as 3x4 matrix in column-major order into the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}, with the m03, m13 and m23 components being zero. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the matrix is stored, use {@link #get3x4(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @see #get3x4(int, FloatBuffer) - * - * @param buffer - * will receive the values of this 3x3 matrix as 3x4 matrix in column-major order at its current position - * @return the passed in buffer - */ - FloatBuffer get3x4(FloatBuffer buffer); - - /** - * Store this matrix as 3x4 matrix in column-major order into the supplied {@link FloatBuffer} starting at the specified - * absolute buffer position/index, with the m03, m13 and m23 components being zero. - *

- * 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 3x3 matrix as 3x4 matrix in column-major order - * @return the passed in buffer - */ - FloatBuffer get3x4(int index, FloatBuffer buffer); - - /** - * Store this matrix as 3x4 matrix in column-major order into the supplied {@link ByteBuffer} at the current - * buffer {@link ByteBuffer#position() position}, with the m03, m13 and m23 components being zero. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the matrix is stored, use {@link #get3x4(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @see #get3x4(int, ByteBuffer) - * - * @param buffer - * will receive the values of this 3x3 matrix as 3x4 matrix in column-major order at its current position - * @return the passed in buffer - */ - ByteBuffer get3x4(ByteBuffer buffer); - - /** - * Store this matrix as 3x4 matrix in column-major order into the supplied {@link ByteBuffer} starting at the specified - * absolute buffer position/index, with the m03, m13 and m23 components being zero. - *

- * 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 3x3 matrix as 3x4 matrix in column-major order - * @return the passed in buffer - */ - ByteBuffer get3x4(int index, ByteBuffer buffer); - - /** - * Store the transpose of this matrix in column-major order into the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the matrix is stored, use {@link #getTransposed(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @see #getTransposed(int, FloatBuffer) - * - * @param buffer - * will receive the values of this matrix in column-major order at its current position - * @return the passed in buffer - */ - FloatBuffer getTransposed(FloatBuffer buffer); - - /** - * Store the transpose of this matrix in column-major order into the supplied {@link FloatBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given FloatBuffer. - * - * @param index - * the absolute position into the FloatBuffer - * @param buffer - * will receive the values of this matrix in column-major order - * @return the passed in buffer - */ - FloatBuffer getTransposed(int index, FloatBuffer buffer); - - /** - * Store the transpose of this matrix in column-major order into the supplied {@link ByteBuffer} at the current - * buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the matrix is stored, use {@link #getTransposed(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @see #getTransposed(int, ByteBuffer) - * - * @param buffer - * will receive the values of this matrix in column-major order at its current position - * @return the passed in buffer - */ - ByteBuffer getTransposed(ByteBuffer buffer); - - /** - * Store the transpose of this matrix in column-major order into the supplied {@link ByteBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given ByteBuffer. - * - * @param index - * the absolute position into the ByteBuffer - * @param buffer - * will receive the values of this matrix in column-major order - * @return the passed in buffer - */ - ByteBuffer getTransposed(int index, ByteBuffer buffer); - - /** - * Store this matrix in column-major order at the given off-heap address. - *

- * This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`. - *

- * 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. - * - * @param address - * the off-heap address where to store this matrix - * @return this - */ - Matrix3fc getToAddress(long address); - - /** - * Store this matrix into the supplied float array in column-major order at the given offset. - * - * @param arr - * the array to write the matrix values into - * @param offset - * the offset into the array - * @return the passed in array - */ - float[] get(float[] arr, int offset); - - /** - * Store this matrix into the supplied float array in column-major order. - *

- * In order to specify an explicit offset into the array, use the method {@link #get(float[], int)}. - * - * @see #get(float[], int) - * - * @param arr - * the array to write the matrix values into - * @return the passed in array - */ - float[] get(float[] arr); - - /** - * Apply scaling to this matrix by scaling the base axes by the given xyz.x, - * xyz.y and xyz.z factors, respectively and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v - * , the scaling will be applied first! - * - * @param xyz - * the factors of the x, y and z component, respectively - * @param dest - * will hold the result - * @return dest - */ - Matrix3f scale(Vector3fc xyz, Matrix3f dest); - - /** - * Apply scaling to this matrix by scaling the base axes by the given x, - * y and z factors and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v - * , the scaling will be applied first! - * - * @param x - * the factor of the x component - * @param y - * the factor of the y component - * @param z - * the factor of the z component - * @param dest - * will hold the result - * @return dest - */ - Matrix3f scale(float x, float y, float z, Matrix3f dest); - - /** - * Apply scaling to this matrix by uniformly scaling all base axes by the given xyz factor - * and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v - * , the scaling will be applied first! - * - * @see #scale(float, float, float, Matrix3f) - * - * @param xyz - * the factor for all components - * @param dest - * will hold the result - * @return dest - */ - Matrix3f scale(float xyz, Matrix3f dest); - - /** - * Pre-multiply scaling to this matrix by scaling the base axes by the given x, - * y and z factors and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be S * M. So when transforming a - * vector v with the new matrix by using S * M * v - * , the scaling will be applied last! - * - * @param x - * the factor of the x component - * @param y - * the factor of the y component - * @param z - * the factor of the z component - * @param dest - * will hold the result - * @return dest - */ - Matrix3f scaleLocal(float x, float y, float z, Matrix3f dest); - - /** - * Transform the given vector by this matrix. - * - * @param v - * the vector to transform - * @return v - */ - Vector3f transform(Vector3f v); - - /** - * Transform the given vector by this matrix and store the result in dest. - * - * @param v - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transform(Vector3fc v, Vector3f dest); - - /** - * Transform the vector (x, y, z) by this matrix and store the result in dest. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transform(float x, float y, float z, Vector3f dest); - - /** - * Transform the given vector by the transpose of this matrix. - * - * @param v - * the vector to transform - * @return v - */ - Vector3f transformTranspose(Vector3f v); - - /** - * Transform the given vector by the transpose of this matrix and store the result in dest. - * - * @param v - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformTranspose(Vector3fc v, Vector3f dest); - - /** - * Transform the vector (x, y, z) by the transpose of this matrix and store the result in dest. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformTranspose(float x, float y, float z, Vector3f dest); - - /** - * Apply rotation about the X axis to this matrix by rotating the given amount of radians - * and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v - * , the rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateX(float ang, Matrix3f dest); - - /** - * Apply rotation about the Y axis to this matrix by rotating the given amount of radians - * and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v - * , the rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateY(float ang, Matrix3f dest); - - /** - * Apply rotation about the Z axis to this matrix by rotating the given amount of radians - * and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v - * , the rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateZ(float ang, Matrix3f dest); - - /** - * Apply rotation of angleX radians about the X axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleZ radians about the Z axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateX(angleX, dest).rotateY(angleY).rotateZ(angleZ) - * - * @param angleX - * the angle to rotate about X - * @param angleY - * the angle to rotate about Y - * @param angleZ - * the angle to rotate about Z - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateXYZ(float angleX, float angleY, float angleZ, Matrix3f dest); - - /** - * Apply rotation of angleZ radians about the Z axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleX radians about the X axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateZ(angleZ, dest).rotateY(angleY).rotateX(angleX) - * - * @param angleZ - * the angle to rotate about Z - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateZYX(float angleZ, float angleY, float angleX, Matrix3f dest); - - /** - * Apply rotation of angleY radians about the Y axis, followed by a rotation of angleX radians about the X axis and - * followed by a rotation of angleZ radians about the Z axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateY(angleY, dest).rotateX(angleX).rotateZ(angleZ) - * - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param angleZ - * the angle to rotate about Z - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateYXZ(float angleY, float angleX, float angleZ, Matrix3f dest); - - /** - * Apply rotation to this matrix by rotating the given amount of radians - * about the given axis specified as x, y and z components, and store the result in dest. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v - * , the rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotate(float ang, float x, float y, float z, Matrix3f dest); - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians - * about the specified (x, y, z) axis and store the result in dest. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateLocal(float ang, float x, float y, float z, Matrix3f dest); - - /** - * Pre-multiply a rotation around the X axis to this matrix by rotating the given amount of radians - * about the X axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians to rotate about the X axis - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateLocalX(float ang, Matrix3f dest); - - /** - * Pre-multiply a rotation around the Y axis to this matrix by rotating the given amount of radians - * about the Y axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians to rotate about the Y axis - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateLocalY(float ang, Matrix3f dest); - - /** - * Pre-multiply a rotation around the Z axis to this matrix by rotating the given amount of radians - * about the Z axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians to rotate about the Z axis - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateLocalZ(float ang, Matrix3f dest); - - /** - * Apply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix and store - * the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotate(Quaternionfc quat, Matrix3f dest); - - /** - * Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix and store - * the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be Q * M. So when transforming a - * vector v with the new matrix by using Q * M * v, - * the quaternion rotation will be applied last! - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateLocal(Quaternionfc quat, Matrix3f dest); - - /** - * Apply a rotation transformation, rotating about the given {@link AxisAngle4f} and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given {@link AxisAngle4f}, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the {@link AxisAngle4f} rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float, Matrix3f) - * - * @param axisAngle - * the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized}) - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotate(AxisAngle4f axisAngle, Matrix3f dest); - - /** - * Apply a rotation transformation, rotating the given radians about the specified axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given angle and axis, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the axis-angle rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float, Matrix3f) - * - * @param angle - * the angle in radians - * @param axis - * the rotation axis (needs to be {@link Vector3f#normalize() normalized}) - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotate(float angle, Vector3fc axis, Matrix3f dest); - - /** - * Apply a rotation transformation to this matrix to make -z point along dir - * and store the result in dest. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - * - * @see #lookAlong(float, float, float, float, float, float, Matrix3f) - * - * @param dir - * the direction in space to look along - * @param up - * the direction of 'up' - * @param dest - * will hold the result - * @return dest - */ - Matrix3f lookAlong(Vector3fc dir, Vector3fc up, Matrix3f dest); - - /** - * Apply a rotation transformation to this matrix to make -z point along dir - * and store the result in dest. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - * - * @param dirX - * the x-coordinate of the direction to look along - * @param dirY - * the y-coordinate of the direction to look along - * @param dirZ - * the z-coordinate of the direction to look along - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - Matrix3f lookAlong(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Matrix3f dest); - - /** - * Get the row at the given row index, starting with 0. - * - * @param row - * the row index in [0..2] - * @param dest - * will hold the row components - * @return the passed in destination - * @throws IndexOutOfBoundsException if row is not in [0..2] - */ - Vector3f getRow(int row, Vector3f dest) throws IndexOutOfBoundsException; - - /** - * Get the column at the given column index, starting with 0. - * - * @param column - * the column index in [0..2] - * @param dest - * will hold the column components - * @return the passed in destination - * @throws IndexOutOfBoundsException if column is not in [0..2] - */ - Vector3f getColumn(int column, Vector3f dest) throws IndexOutOfBoundsException; - - /** - * Get the matrix element value at the given column and row. - * - * @param column - * the colum index in [0..2] - * @param row - * the row index in [0..2] - * @return the element value - */ - float get(int column, int row); - - /** - * Get the matrix element value at the given row and column. - * - * @param row - * the row index in [0..2] - * @param column - * the colum index in [0..2] - * @return the element value - */ - float getRowColumn(int row, int column); - - /** - * Compute a normal matrix from this matrix and store it into dest. - *

- * The normal matrix of m is the transpose of the inverse of m. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f normal(Matrix3f dest); - - /** - * Compute the cofactor matrix of this and store it into dest. - *

- * The cofactor matrix can be used instead of {@link #normal(Matrix3f)} to transform normals - * when the orientation of the normals with respect to the surface should be preserved. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f cofactor(Matrix3f dest); - - /** - * Get the scaling factors of this matrix for the three base axes. - * - * @param dest - * will hold the scaling factors for x, y and z - * @return dest - */ - Vector3f getScale(Vector3f dest); - - /** - * Obtain the direction of +Z before the transformation represented by this matrix is applied. - *

- * This method is equivalent to the following code: - *

-     * Matrix3f inv = new Matrix3f(this).invert();
-     * inv.transform(dir.set(0, 0, 1)).normalize();
-     * 
- * If this is already an orthogonal matrix, then consider using {@link #normalizedPositiveZ(Vector3f)} instead. - *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +Z - * @return dir - */ - Vector3f positiveZ(Vector3f dir); - - /** - * Obtain the direction of +Z before the transformation represented by this orthogonal matrix is applied. - * This method only produces correct results if this is an orthogonal matrix. - *

- * This method is equivalent to the following code: - *

-     * Matrix3f inv = new Matrix3f(this).transpose();
-     * inv.transform(dir.set(0, 0, 1));
-     * 
- *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +Z - * @return dir - */ - Vector3f normalizedPositiveZ(Vector3f dir); - - /** - * Obtain the direction of +X before the transformation represented by this matrix is applied. - *

- * This method is equivalent to the following code: - *

-     * Matrix3f inv = new Matrix3f(this).invert();
-     * inv.transform(dir.set(1, 0, 0)).normalize();
-     * 
- * If this is already an orthogonal matrix, then consider using {@link #normalizedPositiveX(Vector3f)} instead. - *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +X - * @return dir - */ - Vector3f positiveX(Vector3f dir); - - /** - * Obtain the direction of +X before the transformation represented by this orthogonal matrix is applied. - * This method only produces correct results if this is an orthogonal matrix. - *

- * This method is equivalent to the following code: - *

-     * Matrix3f inv = new Matrix3f(this).transpose();
-     * inv.transform(dir.set(1, 0, 0));
-     * 
- *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +X - * @return dir - */ - Vector3f normalizedPositiveX(Vector3f dir); - - /** - * Obtain the direction of +Y before the transformation represented by this matrix is applied. - *

- * This method is equivalent to the following code: - *

-     * Matrix3f inv = new Matrix3f(this).invert();
-     * inv.transform(dir.set(0, 1, 0)).normalize();
-     * 
- * If this is already an orthogonal matrix, then consider using {@link #normalizedPositiveY(Vector3f)} instead. - *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +Y - * @return dir - */ - Vector3f positiveY(Vector3f dir); - - /** - * Obtain the direction of +Y before the transformation represented by this orthogonal matrix is applied. - * This method only produces correct results if this is an orthogonal matrix. - *

- * This method is equivalent to the following code: - *

-     * Matrix3f inv = new Matrix3f(this).transpose();
-     * inv.transform(dir.set(0, 1, 0));
-     * 
- *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +Y - * @return dir - */ - Vector3f normalizedPositiveY(Vector3f dir); - - /** - * Component-wise add this and other and store the result in dest. - * - * @param other - * the other addend - * @param dest - * will hold the result - * @return dest - */ - Matrix3f add(Matrix3fc other, Matrix3f dest); - - /** - * Component-wise subtract subtrahend from this and store the result in dest. - * - * @param subtrahend - * the subtrahend - * @param dest - * will hold the result - * @return dest - */ - Matrix3f sub(Matrix3fc subtrahend, Matrix3f dest); - - /** - * Component-wise multiply this by other and store the result in dest. - * - * @param other - * the other matrix - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mulComponentWise(Matrix3fc other, Matrix3f dest); - - /** - * Linearly interpolate this and other using the given interpolation factor t - * and store the result in dest. - *

- * If t is 0.0 then the result is this. If the interpolation factor is 1.0 - * then the result is other. - * - * @param other - * the other matrix - * @param t - * the interpolation factor between 0.0 and 1.0 - * @param dest - * will hold the result - * @return dest - */ - Matrix3f lerp(Matrix3fc other, float t, Matrix3f dest); - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with direction - * and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * This method is equivalent to calling: mul(new Matrix3f().lookAlong(new Vector3f(dir).negate(), up).invert(), dest) - * - * @see #rotateTowards(float, float, float, float, float, float, Matrix3f) - * - * @param direction - * the direction to rotate towards - * @param up - * the model's up vector - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateTowards(Vector3fc direction, Vector3fc up, Matrix3f dest); - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with dir - * and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * This method is equivalent to calling: mul(new Matrix3f().lookAlong(-dirX, -dirY, -dirZ, upX, upY, upZ).invert(), dest) - * - * @see #rotateTowards(Vector3fc, Vector3fc, Matrix3f) - * - * @param dirX - * the x-coordinate of the direction to rotate towards - * @param dirY - * the y-coordinate of the direction to rotate towards - * @param dirZ - * the z-coordinate of the direction to rotate towards - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - Matrix3f rotateTowards(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Matrix3f dest); - - /** - * Extract the Euler angles from the rotation represented by this matrix and store the extracted Euler angles in dest. - *

- * This method assumes that this matrix only represents a rotation without scaling. - *

- * The Euler angles are always returned as the angle around X in the {@link Vector3f#x} field, the angle around Y in the {@link Vector3f#y} - * field and the angle around Z in the {@link Vector3f#z} field of the supplied {@link Vector3f} instance. - *

- * Note that the returned Euler angles must be applied in the order X * Y * Z to obtain the identical matrix. - * This means that calling {@link Matrix3fc#rotateXYZ(float, float, float, Matrix3f)} using the obtained Euler angles will yield - * the same rotation as the original matrix from which the Euler angles were obtained, so in the below code the matrix - * m2 should be identical to m (disregarding possible floating-point inaccuracies). - *

-     * Matrix3f m = ...; // <- matrix only representing rotation
-     * Matrix3f n = new Matrix3f();
-     * n.rotateXYZ(m.getEulerAnglesXYZ(new Vector3f()));
-     * 
- *

- * Reference: http://en.wikipedia.org/ - * - * @param dest - * will hold the extracted Euler angles - * @return dest - */ - Vector3f getEulerAnglesXYZ(Vector3f dest); - - /** - * Extract the Euler angles from the rotation represented by this matrix and store the extracted Euler angles in dest. - *

- * This method assumes that this matrix only represents a rotation without scaling. - *

- * The Euler angles are always returned as the angle around X in the {@link Vector3f#x} field, the angle around Y in the {@link Vector3f#y} - * field and the angle around Z in the {@link Vector3f#z} field of the supplied {@link Vector3f} instance. - *

- * Note that the returned Euler angles must be applied in the order Z * Y * X to obtain the identical matrix. - * This means that calling {@link Matrix3fc#rotateZYX(float, float, float, Matrix3f)} using the obtained Euler angles will yield - * the same rotation as the original matrix from which the Euler angles were obtained, so in the below code the matrix - * m2 should be identical to m (disregarding possible floating-point inaccuracies). - *

-     * Matrix3f m = ...; // <- matrix only representing rotation
-     * Matrix3f n = new Matrix3f();
-     * n.rotateZYX(m.getEulerAnglesZYX(new Vector3f()));
-     * 
- *

- * Reference: http://en.wikipedia.org/ - * - * @param dest - * will hold the extracted Euler angles - * @return dest - */ - Vector3f getEulerAnglesZYX(Vector3f dest); - - /** - * Apply an oblique projection transformation to this matrix with the given values for a and - * b and store the result in dest. - *

- * If M is this matrix and O the oblique transformation matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * oblique transformation will be applied first! - *

- * The oblique transformation is defined as: - *

-     * x' = x + a*z
-     * y' = y + a*z
-     * z' = z
-     * 
- * or in matrix form: - *
-     * 1 0 a
-     * 0 1 b
-     * 0 0 1
-     * 
- * - * @param a - * the value for the z factor that applies to x - * @param b - * the value for the z factor that applies to y - * @param dest - * will hold the result - * @return dest - */ - Matrix3f obliqueZ(float a, float b, Matrix3f dest); - - /** - * Compare the matrix elements of this matrix with the given matrix using the given delta - * and return whether all of them are equal within a maximum difference of delta. - *

- * Please note that this method is not used by any data structure such as {@link ArrayList} {@link HashSet} or {@link HashMap} - * and their operations, such as {@link ArrayList#contains(Object)} or {@link HashSet#remove(Object)}, since those - * data structures only use the {@link Object#equals(Object)} and {@link Object#hashCode()} methods. - * - * @param m - * the other matrix - * @param delta - * the allowed maximum difference - * @return true whether all of the matrix elements are equal; false otherwise - */ - boolean equals(Matrix3fc m, float delta); - - /** - * Apply a mirror/reflection transformation to this matrix that reflects through the given plane - * specified via the plane normal (nx, ny, nz), and store the result in dest. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param nx - * the x-coordinate of the plane normal - * @param ny - * the y-coordinate of the plane normal - * @param nz - * the z-coordinate of the plane normal - * @param dest - * will hold the result - * @return this - */ - Matrix3f reflect(float nx, float ny, float nz, Matrix3f dest); - - /** - * Apply a mirror/reflection transformation to this matrix that reflects through a plane - * specified via the plane orientation, and store the result in dest. - *

- * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. - * It is assumed that the default mirror plane's normal is (0, 0, 1). So, if the given {@link Quaternionfc} is - * the identity (does not apply any additional rotation), the reflection plane will be z=0. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param orientation - * the plane orientation - * @param dest - * will hold the result - * @return this - */ - Matrix3f reflect(Quaternionfc orientation, Matrix3f dest); - - /** - * Apply a mirror/reflection transformation to this matrix that reflects through the given plane - * specified via the plane normal, and store the result in dest. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param normal - * the plane normal - * @param dest - * will hold the result - * @return this - */ - Matrix3f reflect(Vector3fc normal, Matrix3f dest); - - /** - * Determine whether all matrix elements are finite floating-point values, that - * is, they are not {@link Float#isNaN() NaN} and not - * {@link Float#isInfinite() infinity}. - * - * @return {@code true} if all components are finite floating-point values; - * {@code false} otherwise - */ - boolean isFinite(); - - /** - * Compute (x, y, z)^T * this * (x, y, z). - * - * @param x - * the x coordinate of the vector to multiply - * @param y - * the y coordinate of the vector to multiply - * @param z - * the z coordinate of the vector to multiply - * @return the result - */ - float quadraticFormProduct(float x, float y, float z); - - /** - * Compute v^T * this * v. - * - * @param v - * the vector to multiply - * @return the result - */ - float quadraticFormProduct(Vector3fc v); - - /** - * Multiply this by the matrix - *

-     * 1 0 0
-     * 0 0 1
-     * 0 1 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapXZY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 1 0  0
-     * 0 0 -1
-     * 0 1  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapXZnY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 1  0  0
-     * 0 -1  0
-     * 0  0 -1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapXnYnZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 1  0 0
-     * 0  0 1
-     * 0 -1 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapXnZY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 1  0  0
-     * 0  0 -1
-     * 0 -1  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapXnZnY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 1 0
-     * 1 0 0
-     * 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapYXZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 1  0
-     * 1 0  0
-     * 0 0 -1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapYXnZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 0 1
-     * 1 0 0
-     * 0 1 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapYZX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 0 -1
-     * 1 0  0
-     * 0 1  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapYZnX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 -1 0
-     * 1  0 0
-     * 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapYnXZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 -1  0
-     * 1  0  0
-     * 0  0 -1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapYnXnZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0  0 1
-     * 1  0 0
-     * 0 -1 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapYnZX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0  0 -1
-     * 1  0  0
-     * 0 -1  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapYnZnX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 1 0
-     * 0 0 1
-     * 1 0 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapZXY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 1  0
-     * 0 0 -1
-     * 1 0  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapZXnY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 0 1
-     * 0 1 0
-     * 1 0 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapZYX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 0 -1
-     * 0 1  0
-     * 1 0  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapZYnX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 -1 0
-     * 0  0 1
-     * 1  0 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapZnXY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0 -1  0
-     * 0  0 -1
-     * 1  0  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapZnXnY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0  0 1
-     * 0 -1 0
-     * 1  0 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapZnYX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * 0  0 -1
-     * 0 -1  0
-     * 1  0  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapZnYnX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * -1 0  0
-     *  0 1  0
-     *  0 0 -1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnXYnZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * -1 0 0
-     *  0 0 1
-     *  0 1 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnXZY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * -1 0  0
-     *  0 0 -1
-     *  0 1  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnXZnY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * -1  0 0
-     *  0 -1 0
-     *  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnXnYZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * -1  0  0
-     *  0 -1  0
-     *  0  0 -1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnXnYnZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * -1  0 0
-     *  0  0 1
-     *  0 -1 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnXnZY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     * -1  0  0
-     *  0  0 -1
-     *  0 -1  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnXnZnY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 1 0
-     * -1 0 0
-     *  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnYXZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 1  0
-     * -1 0  0
-     *  0 0 -1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnYXnZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 0 1
-     * -1 0 0
-     *  0 1 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnYZX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 0 -1
-     * -1 0  0
-     *  0 1  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnYZnX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 -1 0
-     * -1  0 0
-     *  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnYnXZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 -1  0
-     * -1  0  0
-     *  0  0 -1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnYnXnZ(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0  0 1
-     * -1  0 0
-     *  0 -1 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnYnZX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0  0 -1
-     * -1  0  0
-     *  0 -1  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnYnZnX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 1 0
-     *  0 0 1
-     * -1 0 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnZXY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 1  0
-     *  0 0 -1
-     * -1 0  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnZXnY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 0 1
-     *  0 1 0
-     * -1 0 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnZYX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 0 -1
-     *  0 1  0
-     * -1 0  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnZYnX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 -1 0
-     *  0  0 1
-     * -1  0 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnZnXY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0 -1  0
-     *  0  0 -1
-     * -1  0  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnZnXnY(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0  0 1
-     *  0 -1 0
-     * -1  0 0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnZnYX(Matrix3f dest); - /** - * Multiply this by the matrix - *
-     *  0  0 -1
-     *  0 -1  0
-     * -1  0  0
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f mapnZnYnX(Matrix3f dest); - - /** - * Multiply this by the matrix - *
-     * -1 0 0
-     *  0 1 0
-     *  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f negateX(Matrix3f dest); - - /** - * Multiply this by the matrix - *
-     * 1  0 0
-     * 0 -1 0
-     * 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f negateY(Matrix3f dest); - - /** - * Multiply this by the matrix - *
-     * 1 0  0
-     * 0 1  0
-     * 0 0 -1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f negateZ(Matrix3f dest); - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix4f.java b/src/main/java/com/jozufozu/flywheel/util/joml/Matrix4f.java deleted file mode 100644 index 394db3726..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix4f.java +++ /dev/null @@ -1,15320 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2015-2021 Richard Greenlees - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.jozufozu.flywheel.util.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.text.DecimalFormat; -import java.text.NumberFormat; - - -/** - * Contains the definition of a 4x4 matrix of floats, and associated functions to transform - * it. The matrix is column-major to match OpenGL's interpretation, and it looks like this: - *

- * m00 m10 m20 m30
- * m01 m11 m21 m31
- * m02 m12 m22 m32
- * m03 m13 m23 m33
- * - * @author Richard Greenlees - * @author Kai Burjack - */ -public class Matrix4f implements Externalizable, Cloneable, Matrix4fc { - - private static final long serialVersionUID = 1L; - - float m00, m01, m02, m03; - float m10, m11, m12, m13; - float m20, m21, m22, m23; - float m30, m31, m32, m33; - - int properties; - - /** - * Create a new {@link Matrix4f} and set it to {@link #identity() identity}. - */ - public Matrix4f() { - this._m00(1.0f) - ._m11(1.0f) - ._m22(1.0f) - ._m33(1.0f) - ._properties(PROPERTY_IDENTITY | PROPERTY_AFFINE | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); - } - - /** - * Create a new {@link Matrix4f} by setting its uppper left 3x3 submatrix to the values of the given {@link Matrix3fc} - * and the rest to identity. - * - * @param mat - * the {@link Matrix3fc} - */ - public Matrix4f(Matrix3fc mat) { - set(mat); - } - - /** - * Create a new {@link Matrix4f} and make it a copy of the given matrix. - * - * @param mat - * the {@link Matrix4fc} to copy the values from - */ - public Matrix4f(Matrix4fc mat) { - set(mat); - } - - /** - * Create a new 4x4 matrix using the supplied float values. - *

- * The matrix layout will be:

- * m00, m10, m20, m30
- * m01, m11, m21, m31
- * m02, m12, m22, m32
- * m03, m13, m23, m33 - * - * @param m00 - * the value of m00 - * @param m01 - * the value of m01 - * @param m02 - * the value of m02 - * @param m03 - * the value of m03 - * @param m10 - * the value of m10 - * @param m11 - * the value of m11 - * @param m12 - * the value of m12 - * @param m13 - * the value of m13 - * @param m20 - * the value of m20 - * @param m21 - * the value of m21 - * @param m22 - * the value of m22 - * @param m23 - * the value of m23 - * @param m30 - * the value of m30 - * @param m31 - * the value of m31 - * @param m32 - * the value of m32 - * @param m33 - * the value of m33 - */ - public Matrix4f(float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23, - float m30, float m31, float m32, float m33) { - this._m00(m00) - ._m01(m01) - ._m02(m02) - ._m03(m03) - ._m10(m10) - ._m11(m11) - ._m12(m12) - ._m13(m13) - ._m20(m20) - ._m21(m21) - ._m22(m22) - ._m23(m23) - ._m30(m30) - ._m31(m31) - ._m32(m32) - ._m33(m33) - .determineProperties(); - } - - /** - * Create a new {@link Matrix4f} by reading its 16 float components from the given {@link FloatBuffer} - * at the buffer's current position. - *

- * That FloatBuffer is expected to hold the values in column-major order. - *

- * The buffer's position will not be changed by this method. - * - * @param buffer - * the {@link FloatBuffer} to read the matrix values from - */ - public Matrix4f(FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - determineProperties(); - } - - /** - * Create a new {@link Matrix4f} and initialize its four columns using the supplied vectors. - * - * @param col0 - * the first column - * @param col1 - * the second column - * @param col2 - * the third column - * @param col3 - * the fourth column - */ - public Matrix4f(Vector4fc col0, Vector4fc col1, Vector4fc col2, Vector4fc col3) { - set(col0, col1, col2, col3); - } - - Matrix4f _properties(int properties) { - this.properties = properties; - return this; - } - - /** - * Assume the given properties about this matrix. - *

- * Use one or multiple of 0, {@link Matrix4fc#PROPERTY_IDENTITY}, - * {@link Matrix4fc#PROPERTY_TRANSLATION}, {@link Matrix4fc#PROPERTY_AFFINE}, - * {@link Matrix4fc#PROPERTY_PERSPECTIVE}, {@link Matrix4fc#PROPERTY_ORTHONORMAL}. - * - * @param properties - * bitset of the properties to assume about this matrix - * @return this - */ - public Matrix4f assume(int properties) { - this._properties(properties); - return this; - } - - /** - * Compute and set the matrix properties returned by {@link #properties()} based - * on the current matrix element values. - * - * @return this - */ - public Matrix4f determineProperties() { - int properties = 0; - if (m03() == 0.0f && m13() == 0.0f) { - if (m23() == 0.0f && m33() == 1.0f) { - properties |= PROPERTY_AFFINE; - if (m00() == 1.0f && m01() == 0.0f && m02() == 0.0f && m10() == 0.0f && m11() == 1.0f && m12() == 0.0f - && m20() == 0.0f && m21() == 0.0f && m22() == 1.0f) { - properties |= PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL; - if (m30() == 0.0f && m31() == 0.0f && m32() == 0.0f) - properties |= PROPERTY_IDENTITY; - } - /* - * We do not determine orthogonality, since it would require arbitrary epsilons - * and is rather expensive (6 dot products) in the worst case. - */ - } else if (m01() == 0.0f && m02() == 0.0f && m10() == 0.0f && m12() == 0.0f && m20() == 0.0f && m21() == 0.0f - && m30() == 0.0f && m31() == 0.0f && m33() == 0.0f) { - properties |= PROPERTY_PERSPECTIVE; - } - } - this.properties = properties; - return this; - } - - public int properties() { - return properties; - } - - public float m00() { - return m00; - } - public float m01() { - return m01; - } - public float m02() { - return m02; - } - public float m03() { - return m03; - } - public float m10() { - return m10; - } - public float m11() { - return m11; - } - public float m12() { - return m12; - } - public float m13() { - return m13; - } - public float m20() { - return m20; - } - public float m21() { - return m21; - } - public float m22() { - return m22; - } - public float m23() { - return m23; - } - public float m30() { - return m30; - } - public float m31() { - return m31; - } - public float m32() { - return m32; - } - public float m33() { - return m33; - } - - /** - * Set the value of the matrix element at column 0 and row 0. - * - * @param m00 - * the new value - * @return this - */ - public Matrix4f m00(float m00) { - this.m00 = m00; - properties &= ~PROPERTY_ORTHONORMAL; - if (m00 != 1.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); - return this; - } - /** - * Set the value of the matrix element at column 0 and row 1. - * - * @param m01 - * the new value - * @return this - */ - public Matrix4f m01(float m01) { - this.m01 = m01; - properties &= ~PROPERTY_ORTHONORMAL; - if (m01 != 0.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_PERSPECTIVE | PROPERTY_TRANSLATION); - return this; - } - /** - * Set the value of the matrix element at column 0 and row 2. - * - * @param m02 - * the new value - * @return this - */ - public Matrix4f m02(float m02) { - this.m02 = m02; - properties &= ~PROPERTY_ORTHONORMAL; - if (m02 != 0.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_PERSPECTIVE | PROPERTY_TRANSLATION); - return this; - } - /** - * Set the value of the matrix element at column 0 and row 3. - * - * @param m03 - * the new value - * @return this - */ - public Matrix4f m03(float m03) { - this.m03 = m03; - if (m03 != 0.0f) - properties = 0; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 0. - * - * @param m10 - * the new value - * @return this - */ - public Matrix4f m10(float m10) { - this.m10 = m10; - properties &= ~PROPERTY_ORTHONORMAL; - if (m10 != 0.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_PERSPECTIVE | PROPERTY_TRANSLATION); - return this; - } - /** - * Set the value of the matrix element at column 1 and row 1. - * - * @param m11 - * the new value - * @return this - */ - public Matrix4f m11(float m11) { - this.m11 = m11; - properties &= ~PROPERTY_ORTHONORMAL; - if (m11 != 1.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); - return this; - } - /** - * Set the value of the matrix element at column 1 and row 2. - * - * @param m12 - * the new value - * @return this - */ - public Matrix4f m12(float m12) { - this.m12 = m12; - properties &= ~PROPERTY_ORTHONORMAL; - if (m12 != 0.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_PERSPECTIVE | PROPERTY_TRANSLATION); - return this; - } - /** - * Set the value of the matrix element at column 1 and row 3. - * - * @param m13 - * the new value - * @return this - */ - public Matrix4f m13(float m13) { - this.m13 = m13; - if (m13 != 0.0f) - properties = 0; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 0. - * - * @param m20 - * the new value - * @return this - */ - public Matrix4f m20(float m20) { - this.m20 = m20; - properties &= ~PROPERTY_ORTHONORMAL; - if (m20 != 0.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_PERSPECTIVE | PROPERTY_TRANSLATION); - return this; - } - /** - * Set the value of the matrix element at column 2 and row 1. - * - * @param m21 - * the new value - * @return this - */ - public Matrix4f m21(float m21) { - this.m21 = m21; - properties &= ~PROPERTY_ORTHONORMAL; - if (m21 != 0.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_PERSPECTIVE | PROPERTY_TRANSLATION); - return this; - } - /** - * Set the value of the matrix element at column 2 and row 2. - * - * @param m22 - * the new value - * @return this - */ - public Matrix4f m22(float m22) { - this.m22 = m22; - properties &= ~PROPERTY_ORTHONORMAL; - if (m22 != 1.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); - return this; - } - /** - * Set the value of the matrix element at column 2 and row 3. - * - * @param m23 - * the new value - * @return this - */ - public Matrix4f m23(float m23) { - this.m23 = m23; - if (m23 != 0.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_AFFINE | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); - return this; - } - /** - * Set the value of the matrix element at column 3 and row 0. - * - * @param m30 - * the new value - * @return this - */ - public Matrix4f m30(float m30) { - this.m30 = m30; - if (m30 != 0.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_PERSPECTIVE); - return this; - } - /** - * Set the value of the matrix element at column 3 and row 1. - * - * @param m31 - * the new value - * @return this - */ - public Matrix4f m31(float m31) { - this.m31 = m31; - if (m31 != 0.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_PERSPECTIVE); - return this; - } - /** - * Set the value of the matrix element at column 3 and row 2. - * - * @param m32 - * the new value - * @return this - */ - public Matrix4f m32(float m32) { - this.m32 = m32; - if (m32 != 0.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_PERSPECTIVE); - return this; - } - /** - * Set the value of the matrix element at column 3 and row 3. - * - * @param m33 - * the new value - * @return this - */ - public Matrix4f m33(float m33) { - this.m33 = m33; - if (m33 != 0.0f) - properties &= ~(PROPERTY_PERSPECTIVE); - if (m33 != 1.0f) - properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL | PROPERTY_AFFINE); - return this; - } - - /** - * Set the value of the matrix element at column 0 and row 0 without updating the properties of the matrix. - * - * @param m00 - * the new value - * @return this - */ - Matrix4f _m00(float m00) { - this.m00 = m00; - return this; - } - /** - * Set the value of the matrix element at column 0 and row 1 without updating the properties of the matrix. - * - * @param m01 - * the new value - * @return this - */ - Matrix4f _m01(float m01) { - this.m01 = m01; - return this; - } - /** - * Set the value of the matrix element at column 0 and row 2 without updating the properties of the matrix. - * - * @param m02 - * the new value - * @return this - */ - Matrix4f _m02(float m02) { - this.m02 = m02; - return this; - } - /** - * Set the value of the matrix element at column 0 and row 3 without updating the properties of the matrix. - * - * @param m03 - * the new value - * @return this - */ - Matrix4f _m03(float m03) { - this.m03 = m03; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 0 without updating the properties of the matrix. - * - * @param m10 - * the new value - * @return this - */ - Matrix4f _m10(float m10) { - this.m10 = m10; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 1 without updating the properties of the matrix. - * - * @param m11 - * the new value - * @return this - */ - Matrix4f _m11(float m11) { - this.m11 = m11; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 2 without updating the properties of the matrix. - * - * @param m12 - * the new value - * @return this - */ - Matrix4f _m12(float m12) { - this.m12 = m12; - return this; - } - /** - * Set the value of the matrix element at column 1 and row 3 without updating the properties of the matrix. - * - * @param m13 - * the new value - * @return this - */ - Matrix4f _m13(float m13) { - this.m13 = m13; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 0 without updating the properties of the matrix. - * - * @param m20 - * the new value - * @return this - */ - Matrix4f _m20(float m20) { - this.m20 = m20; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 1 without updating the properties of the matrix. - * - * @param m21 - * the new value - * @return this - */ - Matrix4f _m21(float m21) { - this.m21 = m21; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 2 without updating the properties of the matrix. - * - * @param m22 - * the new value - * @return this - */ - Matrix4f _m22(float m22) { - this.m22 = m22; - return this; - } - /** - * Set the value of the matrix element at column 2 and row 3 without updating the properties of the matrix. - * - * @param m23 - * the new value - * @return this - */ - Matrix4f _m23(float m23) { - this.m23 = m23; - return this; - } - /** - * Set the value of the matrix element at column 3 and row 0 without updating the properties of the matrix. - * - * @param m30 - * the new value - * @return this - */ - Matrix4f _m30(float m30) { - this.m30 = m30; - return this; - } - /** - * Set the value of the matrix element at column 3 and row 1 without updating the properties of the matrix. - * - * @param m31 - * the new value - * @return this - */ - Matrix4f _m31(float m31) { - this.m31 = m31; - return this; - } - /** - * Set the value of the matrix element at column 3 and row 2 without updating the properties of the matrix. - * - * @param m32 - * the new value - * @return this - */ - Matrix4f _m32(float m32) { - this.m32 = m32; - return this; - } - - /** - * Set the value of the matrix element at column 3 and row 3 without updating the properties of the matrix. - * - * @param m33 - * the new value - * @return this - */ - Matrix4f _m33(float m33) { - this.m33 = m33; - return this; - } - - /** - * Reset this matrix to the identity. - *

- * Please note that if a call to {@link #identity()} is immediately followed by a call to: - * {@link #translate(float, float, float) translate}, - * {@link #rotate(float, float, float, float) rotate}, - * {@link #scale(float, float, float) scale}, - * {@link #perspective(float, float, float, float) perspective}, - * {@link #frustum(float, float, float, float, float, float) frustum}, - * {@link #ortho(float, float, float, float, float, float) ortho}, - * {@link #ortho2D(float, float, float, float) ortho2D}, - * {@link #lookAt(float, float, float, float, float, float, float, float, float) lookAt}, - * {@link #lookAlong(float, float, float, float, float, float) lookAlong}, - * or any of their overloads, then the call to {@link #identity()} can be omitted and the subsequent call replaced with: - * {@link #translation(float, float, float) translation}, - * {@link #rotation(float, float, float, float) rotation}, - * {@link #scaling(float, float, float) scaling}, - * {@link #setPerspective(float, float, float, float) setPerspective}, - * {@link #setFrustum(float, float, float, float, float, float) setFrustum}, - * {@link #setOrtho(float, float, float, float, float, float) setOrtho}, - * {@link #setOrtho2D(float, float, float, float) setOrtho2D}, - * {@link #setLookAt(float, float, float, float, float, float, float, float, float) setLookAt}, - * {@link #setLookAlong(float, float, float, float, float, float) setLookAlong}, - * or any of their overloads. - * - * @return this - */ - public Matrix4f identity() { - if ((properties & PROPERTY_IDENTITY) != 0) - return this; - return - _m00(1.0f). - _m01(0.0f). - _m02(0.0f). - _m03(0.0f). - _m10(0.0f). - _m11(1.0f). - _m12(0.0f). - _m13(0.0f). - _m20(0.0f). - _m21(0.0f). - _m22(1.0f). - _m23(0.0f). - _m30(0.0f). - _m31(0.0f). - _m32(0.0f). - _m33(1.0f). - _properties(PROPERTY_IDENTITY | PROPERTY_AFFINE | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); - } - - /** - * Store the values of the given matrix m into this matrix. - * - * @see #Matrix4f(Matrix4fc) - * @see #get(Matrix4f) - * - * @param m - * the matrix to copy the values from - * @return this - */ - public Matrix4f set(Matrix4fc m) { - return - _m00(m.m00()). - _m01(m.m01()). - _m02(m.m02()). - _m03(m.m03()). - _m10(m.m10()). - _m11(m.m11()). - _m12(m.m12()). - _m13(m.m13()). - _m20(m.m20()). - _m21(m.m21()). - _m22(m.m22()). - _m23(m.m23()). - _m30(m.m30()). - _m31(m.m31()). - _m32(m.m32()). - _m33(m.m33()). - _properties(m.properties()); - } - - /** - * Store the values of the transpose of the given matrix m into this matrix. - * - * @param m - * the matrix to copy the transposed values from - * @return this - */ - public Matrix4f setTransposed(Matrix4fc m) { - if ((m.properties() & PROPERTY_IDENTITY) != 0) - return this.identity(); - return setTransposedInternal(m); - } - private Matrix4f setTransposedInternal(Matrix4fc m) { - float nm10 = m.m01(), nm12 = m.m21(), nm13 = m.m31(); - float nm20 = m.m02(), nm21 = m.m12(), nm30 = m.m03(); - float nm31 = m.m13(), nm32 = m.m23(); - return this - ._m00(m.m00())._m01(m.m10())._m02(m.m20())._m03(m.m30()) - ._m10(nm10)._m11(m.m11())._m12(nm12)._m13(nm13) - ._m20(nm20)._m21(nm21)._m22(m.m22())._m23(m.m32()) - ._m30(nm30)._m31(nm31)._m32(nm32)._m33(m.m33()) - ._properties(m.properties() & PROPERTY_IDENTITY); - } - - /** - * Set the upper left 3x3 submatrix of this {@link Matrix4f} to the given {@link Matrix3fc} - * and the rest to identity. - * - * @see #Matrix4f(Matrix3fc) - * - * @param mat - * the {@link Matrix3fc} - * @return this - */ - public Matrix4f set(Matrix3fc mat) { - return this - ._m00(mat.m00()) - ._m01(mat.m01()) - ._m02(mat.m02()) - ._m03(0.0f) - ._m10(mat.m10()) - ._m11(mat.m11()) - ._m12(mat.m12()) - ._m13(0.0f) - ._m20(mat.m20()) - ._m21(mat.m21()) - ._m22(mat.m22()) - ._m23(0.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(0.0f) - ._m33(1.0f). - _properties(PROPERTY_AFFINE); - } - - /** - * Set this matrix to be equivalent to the rotation specified by the given {@link AxisAngle4f}. - * - * @param axisAngle - * the {@link AxisAngle4f} - * @return this - */ - public Matrix4f set(AxisAngle4f axisAngle) { - float x = axisAngle.x; - float y = axisAngle.y; - float z = axisAngle.z; - float angle = axisAngle.angle; - double n = Math.sqrt(x*x + y*y + z*z); - n = 1/n; - x *= n; - y *= n; - z *= n; - float s = Math.sin(angle); - float c = Math.cosFromSin(s, angle); - float omc = 1.0f - c; - this._m00((float)(c + x*x*omc)) - ._m11((float)(c + y*y*omc)) - ._m22((float)(c + z*z*omc)); - float tmp1 = x*y*omc; - float tmp2 = z*s; - this._m10((float)(tmp1 - tmp2)) - ._m01((float)(tmp1 + tmp2)); - tmp1 = x*z*omc; - tmp2 = y*s; - this._m20((float)(tmp1 + tmp2)) - ._m02((float)(tmp1 - tmp2)); - tmp1 = y*z*omc; - tmp2 = x*s; - return this - ._m21((float)(tmp1 - tmp2)) - ._m12((float)(tmp1 + tmp2)) - ._m03(0.0f) - ._m13(0.0f) - ._m23(0.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(0.0f) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Set this matrix to be equivalent to the rotation specified by the given {@link Quaternionfc}. - *

- * This method is equivalent to calling: rotation(q) - *

- * Reference: http://www.euclideanspace.com/ - * - * @see #rotation(Quaternionfc) - * - * @param q - * the {@link Quaternionfc} - * @return this - */ - public Matrix4f set(Quaternionfc q) { - return rotation(q); - } - - /** - * Set the upper left 3x3 submatrix of this {@link Matrix4f} to that of the given {@link Matrix4f} - * and don't change the other elements. - * - * @param mat - * the {@link Matrix4f} - * @return this - */ - public Matrix4f set3x3(Matrix4f mat) { - MemUtil.INSTANCE.copy3x3(mat, this); - return _properties(properties & mat.properties & ~(PROPERTY_PERSPECTIVE)); - } - - /** - * Set the upper 4x3 submatrix of this {@link Matrix4f} to the upper 4x3 submatrix of the given {@link Matrix4f} - * and don't change the other elements. - * - * @param mat - * the {@link Matrix4f} - * @return this - */ - public Matrix4f set4x3(Matrix4f mat) { - MemUtil.INSTANCE.copy4x3(mat, this); - return _properties(properties & mat.properties & ~(PROPERTY_PERSPECTIVE)); - } - - /** - * Multiply this matrix by the supplied right matrix and store the result in this. - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param right - * the right operand of the matrix multiplication - * @return this - */ - public Matrix4f mul(Matrix4fc right) { - return mul(right, this); - } - - public Matrix4f mul(Matrix4fc right, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.set(right); - else if ((right.properties() & PROPERTY_IDENTITY) != 0) - return dest.set(this); - else if ((properties & PROPERTY_TRANSLATION) != 0 && (right.properties() & PROPERTY_AFFINE) != 0) - return mulTranslationAffine(right, dest); - else if ((properties & PROPERTY_AFFINE) != 0 && (right.properties() & PROPERTY_AFFINE) != 0) - return mulAffine(right, dest); - else if ((properties & PROPERTY_PERSPECTIVE) != 0 && (right.properties() & PROPERTY_AFFINE) != 0) - return mulPerspectiveAffine(right, dest); - else if ((right.properties() & PROPERTY_AFFINE) != 0) - return mulAffineR(right, dest); - return mul0(right, dest); - } - - /** - * Multiply this matrix by the supplied right matrix. - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - *

- * This method neither assumes nor checks for any matrix properties of this or right - * and will always perform a complete 4x4 matrix multiplication. This method should only be used whenever the - * multiplied matrices do not have any properties for which there are optimized multiplication methods available. - * - * @param right - * the right operand of the matrix multiplication - * @return this - */ - public Matrix4f mul0(Matrix4fc right) { - return mul0(right, this); - } - - public Matrix4f mul0(Matrix4fc right, Matrix4f dest) { - float nm00 = Math.fma(m00(), right.m00(), Math.fma(m10(), right.m01(), Math.fma(m20(), right.m02(), m30() * right.m03()))); - float nm01 = Math.fma(m01(), right.m00(), Math.fma(m11(), right.m01(), Math.fma(m21(), right.m02(), m31() * right.m03()))); - float nm02 = Math.fma(m02(), right.m00(), Math.fma(m12(), right.m01(), Math.fma(m22(), right.m02(), m32() * right.m03()))); - float nm03 = Math.fma(m03(), right.m00(), Math.fma(m13(), right.m01(), Math.fma(m23(), right.m02(), m33() * right.m03()))); - float nm10 = Math.fma(m00(), right.m10(), Math.fma(m10(), right.m11(), Math.fma(m20(), right.m12(), m30() * right.m13()))); - float nm11 = Math.fma(m01(), right.m10(), Math.fma(m11(), right.m11(), Math.fma(m21(), right.m12(), m31() * right.m13()))); - float nm12 = Math.fma(m02(), right.m10(), Math.fma(m12(), right.m11(), Math.fma(m22(), right.m12(), m32() * right.m13()))); - float nm13 = Math.fma(m03(), right.m10(), Math.fma(m13(), right.m11(), Math.fma(m23(), right.m12(), m33() * right.m13()))); - float nm20 = Math.fma(m00(), right.m20(), Math.fma(m10(), right.m21(), Math.fma(m20(), right.m22(), m30() * right.m23()))); - float nm21 = Math.fma(m01(), right.m20(), Math.fma(m11(), right.m21(), Math.fma(m21(), right.m22(), m31() * right.m23()))); - float nm22 = Math.fma(m02(), right.m20(), Math.fma(m12(), right.m21(), Math.fma(m22(), right.m22(), m32() * right.m23()))); - float nm23 = Math.fma(m03(), right.m20(), Math.fma(m13(), right.m21(), Math.fma(m23(), right.m22(), m33() * right.m23()))); - float nm30 = Math.fma(m00(), right.m30(), Math.fma(m10(), right.m31(), Math.fma(m20(), right.m32(), m30() * right.m33()))); - float nm31 = Math.fma(m01(), right.m30(), Math.fma(m11(), right.m31(), Math.fma(m21(), right.m32(), m31() * right.m33()))); - float nm32 = Math.fma(m02(), right.m30(), Math.fma(m12(), right.m31(), Math.fma(m22(), right.m32(), m32() * right.m33()))); - float nm33 = Math.fma(m03(), right.m30(), Math.fma(m13(), right.m31(), Math.fma(m23(), right.m32(), m33() * right.m33()))); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(nm33) - ._properties(0); - } - - /** - * Multiply this matrix by the matrix with the supplied elements. - *

- * If M is this matrix and R the right matrix whose - * elements are supplied via the parameters, then the new matrix will be M * R. - * So when transforming a vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param r00 - * the m00 element of the right matrix - * @param r01 - * the m01 element of the right matrix - * @param r02 - * the m02 element of the right matrix - * @param r03 - * the m03 element of the right matrix - * @param r10 - * the m10 element of the right matrix - * @param r11 - * the m11 element of the right matrix - * @param r12 - * the m12 element of the right matrix - * @param r13 - * the m13 element of the right matrix - * @param r20 - * the m20 element of the right matrix - * @param r21 - * the m21 element of the right matrix - * @param r22 - * the m22 element of the right matrix - * @param r23 - * the m23 element of the right matrix - * @param r30 - * the m30 element of the right matrix - * @param r31 - * the m31 element of the right matrix - * @param r32 - * the m32 element of the right matrix - * @param r33 - * the m33 element of the right matrix - * @return this - */ - public Matrix4f mul( - float r00, float r01, float r02, float r03, - float r10, float r11, float r12, float r13, - float r20, float r21, float r22, float r23, - float r30, float r31, float r32, float r33) { - return mul(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33, this); - } - - public Matrix4f mul( - float r00, float r01, float r02, float r03, - float r10, float r11, float r12, float r13, - float r20, float r21, float r22, float r23, - float r30, float r31, float r32, float r33, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.set(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); - else if ((properties & PROPERTY_AFFINE) != 0) - return mulAffineL(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33, dest); - return mulGeneric(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33, dest); - } - private Matrix4f mulAffineL( - float r00, float r01, float r02, float r03, - float r10, float r11, float r12, float r13, - float r20, float r21, float r22, float r23, - float r30, float r31, float r32, float r33, Matrix4f dest) { - float nm00 = Math.fma(m00(), r00, Math.fma(m10(), r01, Math.fma(m20(), r02, m30() * r03))); - float nm01 = Math.fma(m01(), r00, Math.fma(m11(), r01, Math.fma(m21(), r02, m31() * r03))); - float nm02 = Math.fma(m02(), r00, Math.fma(m12(), r01, Math.fma(m22(), r02, m32() * r03))); - float nm03 = r03; - float nm10 = Math.fma(m00(), r10, Math.fma(m10(), r11, Math.fma(m20(), r12, m30() * r13))); - float nm11 = Math.fma(m01(), r10, Math.fma(m11(), r11, Math.fma(m21(), r12, m31() * r13))); - float nm12 = Math.fma(m02(), r10, Math.fma(m12(), r11, Math.fma(m22(), r12, m32() * r13))); - float nm13 = r13; - float nm20 = Math.fma(m00(), r20, Math.fma(m10(), r21, Math.fma(m20(), r22, m30() * r23))); - float nm21 = Math.fma(m01(), r20, Math.fma(m11(), r21, Math.fma(m21(), r22, m31() * r23))); - float nm22 = Math.fma(m02(), r20, Math.fma(m12(), r21, Math.fma(m22(), r22, m32() * r23))); - float nm23 = r23; - float nm30 = Math.fma(m00(), r30, Math.fma(m10(), r31, Math.fma(m20(), r32, m30() * r33))); - float nm31 = Math.fma(m01(), r30, Math.fma(m11(), r31, Math.fma(m21(), r32, m31() * r33))); - float nm32 = Math.fma(m02(), r30, Math.fma(m12(), r31, Math.fma(m22(), r32, m32() * r33))); - float nm33 = r33; - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(nm33) - ._properties(PROPERTY_AFFINE); - } - private Matrix4f mulGeneric( - float r00, float r01, float r02, float r03, - float r10, float r11, float r12, float r13, - float r20, float r21, float r22, float r23, - float r30, float r31, float r32, float r33, Matrix4f dest) { - float nm00 = Math.fma(m00(), r00, Math.fma(m10(), r01, Math.fma(m20(), r02, m30() * r03))); - float nm01 = Math.fma(m01(), r00, Math.fma(m11(), r01, Math.fma(m21(), r02, m31() * r03))); - float nm02 = Math.fma(m02(), r00, Math.fma(m12(), r01, Math.fma(m22(), r02, m32() * r03))); - float nm03 = Math.fma(m03(), r00, Math.fma(m13(), r01, Math.fma(m23(), r02, m33() * r03))); - float nm10 = Math.fma(m00(), r10, Math.fma(m10(), r11, Math.fma(m20(), r12, m30() * r13))); - float nm11 = Math.fma(m01(), r10, Math.fma(m11(), r11, Math.fma(m21(), r12, m31() * r13))); - float nm12 = Math.fma(m02(), r10, Math.fma(m12(), r11, Math.fma(m22(), r12, m32() * r13))); - float nm13 = Math.fma(m03(), r10, Math.fma(m13(), r11, Math.fma(m23(), r12, m33() * r13))); - float nm20 = Math.fma(m00(), r20, Math.fma(m10(), r21, Math.fma(m20(), r22, m30() * r23))); - float nm21 = Math.fma(m01(), r20, Math.fma(m11(), r21, Math.fma(m21(), r22, m31() * r23))); - float nm22 = Math.fma(m02(), r20, Math.fma(m12(), r21, Math.fma(m22(), r22, m32() * r23))); - float nm23 = Math.fma(m03(), r20, Math.fma(m13(), r21, Math.fma(m23(), r22, m33() * r23))); - float nm30 = Math.fma(m00(), r30, Math.fma(m10(), r31, Math.fma(m20(), r32, m30() * r33))); - float nm31 = Math.fma(m01(), r30, Math.fma(m11(), r31, Math.fma(m21(), r32, m31() * r33))); - float nm32 = Math.fma(m02(), r30, Math.fma(m12(), r31, Math.fma(m22(), r32, m32() * r33))); - float nm33 = Math.fma(m03(), r30, Math.fma(m13(), r31, Math.fma(m23(), r32, m33() * r33))); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(nm33) - ._properties(0); - } - - /** - * Multiply this matrix by the 3x3 matrix with the supplied elements expanded to a 4x4 matrix with - * all other matrix elements set to identity. - *

- * If M is this matrix and R the right matrix whose - * elements are supplied via the parameters, then the new matrix will be M * R. - * So when transforming a vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param r00 - * the m00 element of the right matrix - * @param r01 - * the m01 element of the right matrix - * @param r02 - * the m02 element of the right matrix - * @param r10 - * the m10 element of the right matrix - * @param r11 - * the m11 element of the right matrix - * @param r12 - * the m12 element of the right matrix - * @param r20 - * the m20 element of the right matrix - * @param r21 - * the m21 element of the right matrix - * @param r22 - * the m22 element of the right matrix - * @return this - */ - public Matrix4f mul3x3( - float r00, float r01, float r02, - float r10, float r11, float r12, - float r20, float r21, float r22) { - return mul3x3(r00, r01, r02, r10, r11, r12, r20, r21, r22, this); - } - public Matrix4f mul3x3( - float r00, float r01, float r02, - float r10, float r11, float r12, - float r20, float r21, float r22, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.set(r00, r01, r02, 0, r10, r11, r12, 0, r20, r21, r22, 0, 0, 0, 0, 1); - return mulGeneric3x3(r00, r01, r02, r10, r11, r12, r20, r21, r22, dest); - } - private Matrix4f mulGeneric3x3( - float r00, float r01, float r02, - float r10, float r11, float r12, - float r20, float r21, float r22, Matrix4f dest) { - float nm00 = Math.fma(m00(), r00, Math.fma(m10(), r01, m20() * r02)); - float nm01 = Math.fma(m01(), r00, Math.fma(m11(), r01, m21() * r02)); - float nm02 = Math.fma(m02(), r00, Math.fma(m12(), r01, m22() * r02)); - float nm03 = Math.fma(m03(), r00, Math.fma(m13(), r01, m23() * r02)); - float nm10 = Math.fma(m00(), r10, Math.fma(m10(), r11, m20() * r12)); - float nm11 = Math.fma(m01(), r10, Math.fma(m11(), r11, m21() * r12)); - float nm12 = Math.fma(m02(), r10, Math.fma(m12(), r11, m22() * r12)); - float nm13 = Math.fma(m03(), r10, Math.fma(m13(), r11, m23() * r12)); - float nm20 = Math.fma(m00(), r20, Math.fma(m10(), r21, m20() * r22)); - float nm21 = Math.fma(m01(), r20, Math.fma(m11(), r21, m21() * r22)); - float nm22 = Math.fma(m02(), r20, Math.fma(m12(), r21, m22() * r22)); - float nm23 = Math.fma(m03(), r20, Math.fma(m13(), r21, m23() * r22)); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(this.properties & PROPERTY_AFFINE); - } - - /** - * Pre-multiply this matrix by the supplied left matrix and store the result in this. - *

- * If M is this matrix and L the left matrix, - * then the new matrix will be L * M. So when transforming a - * vector v with the new matrix by using L * M * v, the - * transformation of this matrix will be applied first! - * - * @param left - * the left operand of the matrix multiplication - * @return this - */ - public Matrix4f mulLocal(Matrix4fc left) { - return mulLocal(left, this); - } - - public Matrix4f mulLocal(Matrix4fc left, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.set(left); - else if ((left.properties() & PROPERTY_IDENTITY) != 0) - return dest.set(this); - else if ((properties & PROPERTY_AFFINE) != 0 && (left.properties() & PROPERTY_AFFINE) != 0) - return mulLocalAffine(left, dest); - return mulLocalGeneric(left, dest); - } - private Matrix4f mulLocalGeneric(Matrix4fc left, Matrix4f dest) { - float nm00 = Math.fma(left.m00(), m00(), Math.fma(left.m10(), m01(), Math.fma(left.m20(), m02(), left.m30() * m03()))); - float nm01 = Math.fma(left.m01(), m00(), Math.fma(left.m11(), m01(), Math.fma(left.m21(), m02(), left.m31() * m03()))); - float nm02 = Math.fma(left.m02(), m00(), Math.fma(left.m12(), m01(), Math.fma(left.m22(), m02(), left.m32() * m03()))); - float nm03 = Math.fma(left.m03(), m00(), Math.fma(left.m13(), m01(), Math.fma(left.m23(), m02(), left.m33() * m03()))); - float nm10 = Math.fma(left.m00(), m10(), Math.fma(left.m10(), m11(), Math.fma(left.m20(), m12(), left.m30() * m13()))); - float nm11 = Math.fma(left.m01(), m10(), Math.fma(left.m11(), m11(), Math.fma(left.m21(), m12(), left.m31() * m13()))); - float nm12 = Math.fma(left.m02(), m10(), Math.fma(left.m12(), m11(), Math.fma(left.m22(), m12(), left.m32() * m13()))); - float nm13 = Math.fma(left.m03(), m10(), Math.fma(left.m13(), m11(), Math.fma(left.m23(), m12(), left.m33() * m13()))); - float nm20 = Math.fma(left.m00(), m20(), Math.fma(left.m10(), m21(), Math.fma(left.m20(), m22(), left.m30() * m23()))); - float nm21 = Math.fma(left.m01(), m20(), Math.fma(left.m11(), m21(), Math.fma(left.m21(), m22(), left.m31() * m23()))); - float nm22 = Math.fma(left.m02(), m20(), Math.fma(left.m12(), m21(), Math.fma(left.m22(), m22(), left.m32() * m23()))); - float nm23 = Math.fma(left.m03(), m20(), Math.fma(left.m13(), m21(), Math.fma(left.m23(), m22(), left.m33() * m23()))); - float nm30 = Math.fma(left.m00(), m30(), Math.fma(left.m10(), m31(), Math.fma(left.m20(), m32(), left.m30() * m33()))); - float nm31 = Math.fma(left.m01(), m30(), Math.fma(left.m11(), m31(), Math.fma(left.m21(), m32(), left.m31() * m33()))); - float nm32 = Math.fma(left.m02(), m30(), Math.fma(left.m12(), m31(), Math.fma(left.m22(), m32(), left.m32() * m33()))); - float nm33 = Math.fma(left.m03(), m30(), Math.fma(left.m13(), m31(), Math.fma(left.m23(), m32(), left.m33() * m33()))); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(nm33) - ._properties(0); - } - - /** - * Pre-multiply this matrix by the supplied left matrix, both of which are assumed to be {@link #isAffine() affine}, and store the result in this. - *

- * This method assumes that this matrix and the given left matrix both represent an {@link #isAffine() affine} transformation - * (i.e. their last rows are equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrices only represent affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * This method will not modify either the last row of this or the last row of left. - *

- * If M is this matrix and L the left matrix, - * then the new matrix will be L * M. So when transforming a - * vector v with the new matrix by using L * M * v, the - * transformation of this matrix will be applied first! - * - * @param left - * the left operand of the matrix multiplication (the last row is assumed to be (0, 0, 0, 1)) - * @return this - */ - public Matrix4f mulLocalAffine(Matrix4fc left) { - return mulLocalAffine(left, this); - } - - public Matrix4f mulLocalAffine(Matrix4fc left, Matrix4f dest) { - float nm00 = left.m00() * m00() + left.m10() * m01() + left.m20() * m02(); - float nm01 = left.m01() * m00() + left.m11() * m01() + left.m21() * m02(); - float nm02 = left.m02() * m00() + left.m12() * m01() + left.m22() * m02(); - float nm03 = left.m03(); - float nm10 = left.m00() * m10() + left.m10() * m11() + left.m20() * m12(); - float nm11 = left.m01() * m10() + left.m11() * m11() + left.m21() * m12(); - float nm12 = left.m02() * m10() + left.m12() * m11() + left.m22() * m12(); - float nm13 = left.m13(); - float nm20 = left.m00() * m20() + left.m10() * m21() + left.m20() * m22(); - float nm21 = left.m01() * m20() + left.m11() * m21() + left.m21() * m22(); - float nm22 = left.m02() * m20() + left.m12() * m21() + left.m22() * m22(); - float nm23 = left.m23(); - float nm30 = left.m00() * m30() + left.m10() * m31() + left.m20() * m32() + left.m30(); - float nm31 = left.m01() * m30() + left.m11() * m31() + left.m21() * m32() + left.m31(); - float nm32 = left.m02() * m30() + left.m12() * m31() + left.m22() * m32() + left.m32(); - float nm33 = left.m33(); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(nm33) - ._properties(PROPERTY_AFFINE | (this.properties() & left.properties() & PROPERTY_ORTHONORMAL)); - } - - /** - * Multiply this symmetric perspective projection matrix by the supplied {@link #isAffine() affine} view matrix. - *

- * If P is this matrix and V the view matrix, - * then the new matrix will be P * V. So when transforming a - * vector v with the new matrix by using P * V * v, the - * transformation of the view matrix will be applied first! - * - * @param view - * the {@link #isAffine() affine} matrix to multiply this symmetric perspective projection matrix by - * @return this - */ - public Matrix4f mulPerspectiveAffine(Matrix4fc view) { - return mulPerspectiveAffine(view, this); - } - - public Matrix4f mulPerspectiveAffine(Matrix4fc view, Matrix4f dest) { - float nm00 = m00() * view.m00(), nm01 = m11() * view.m01(), nm02 = m22() * view.m02(), nm03 = m23() * view.m02(); - float nm10 = m00() * view.m10(), nm11 = m11() * view.m11(), nm12 = m22() * view.m12(), nm13 = m23() * view.m12(); - float nm20 = m00() * view.m20(), nm21 = m11() * view.m21(), nm22 = m22() * view.m22(), nm23 = m23() * view.m22(); - float nm30 = m00() * view.m30(), nm31 = m11() * view.m31(), nm32 = m22() * view.m32() + m32(), nm33 = m23() * view.m32(); - return dest - ._m00(nm00)._m01(nm01)._m02(nm02)._m03(nm03) - ._m10(nm10)._m11(nm11)._m12(nm12)._m13(nm13) - ._m20(nm20)._m21(nm21)._m22(nm22)._m23(nm23) - ._m30(nm30)._m31(nm31)._m32(nm32)._m33(nm33) - ._properties(0); - } - - /** - * Multiply this matrix by the supplied right matrix, which is assumed to be {@link #isAffine() affine}, and store the result in this. - *

- * This method assumes that the given right matrix represents an {@link #isAffine() affine} transformation (i.e. its last row is equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrix only represents affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param right - * the right operand of the matrix multiplication (the last row is assumed to be (0, 0, 0, 1)) - * @return this - */ - public Matrix4f mulAffineR(Matrix4fc right) { - return mulAffineR(right, this); - } - - public Matrix4f mulAffineR(Matrix4fc right, Matrix4f dest) { - float nm00 = Math.fma(m00(), right.m00(), Math.fma(m10(), right.m01(), m20() * right.m02())); - float nm01 = Math.fma(m01(), right.m00(), Math.fma(m11(), right.m01(), m21() * right.m02())); - float nm02 = Math.fma(m02(), right.m00(), Math.fma(m12(), right.m01(), m22() * right.m02())); - float nm03 = Math.fma(m03(), right.m00(), Math.fma(m13(), right.m01(), m23() * right.m02())); - float nm10 = Math.fma(m00(), right.m10(), Math.fma(m10(), right.m11(), m20() * right.m12())); - float nm11 = Math.fma(m01(), right.m10(), Math.fma(m11(), right.m11(), m21() * right.m12())); - float nm12 = Math.fma(m02(), right.m10(), Math.fma(m12(), right.m11(), m22() * right.m12())); - float nm13 = Math.fma(m03(), right.m10(), Math.fma(m13(), right.m11(), m23() * right.m12())); - float nm20 = Math.fma(m00(), right.m20(), Math.fma(m10(), right.m21(), m20() * right.m22())); - float nm21 = Math.fma(m01(), right.m20(), Math.fma(m11(), right.m21(), m21() * right.m22())); - float nm22 = Math.fma(m02(), right.m20(), Math.fma(m12(), right.m21(), m22() * right.m22())); - float nm23 = Math.fma(m03(), right.m20(), Math.fma(m13(), right.m21(), m23() * right.m22())); - float nm30 = Math.fma(m00(), right.m30(), Math.fma(m10(), right.m31(), Math.fma(m20(), right.m32(), m30()))); - float nm31 = Math.fma(m01(), right.m30(), Math.fma(m11(), right.m31(), Math.fma(m21(), right.m32(), m31()))); - float nm32 = Math.fma(m02(), right.m30(), Math.fma(m12(), right.m31(), Math.fma(m22(), right.m32(), m32()))); - float nm33 = Math.fma(m03(), right.m30(), Math.fma(m13(), right.m31(), Math.fma(m23(), right.m32(), m33()))); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(nm33) - ._properties(properties & ~(PROPERTY_IDENTITY | PROPERTY_PERSPECTIVE | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - } - - /** - * Multiply this matrix by the supplied right matrix, both of which are assumed to be {@link #isAffine() affine}, and store the result in this. - *

- * This method assumes that this matrix and the given right matrix both represent an {@link #isAffine() affine} transformation - * (i.e. their last rows are equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrices only represent affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * This method will not modify either the last row of this or the last row of right. - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param right - * the right operand of the matrix multiplication (the last row is assumed to be (0, 0, 0, 1)) - * @return this - */ - public Matrix4f mulAffine(Matrix4fc right) { - return mulAffine(right, this); - } - - public Matrix4f mulAffine(Matrix4fc right, Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - float m20 = this.m20(), m21 = this.m21(), m22 = this.m22(); - float rm00 = right.m00(), rm01 = right.m01(), rm02 = right.m02(); - float rm10 = right.m10(), rm11 = right.m11(), rm12 = right.m12(); - float rm20 = right.m20(), rm21 = right.m21(), rm22 = right.m22(); - float rm30 = right.m30(), rm31 = right.m31(), rm32 = right.m32(); - return dest - ._m00(Math.fma(m00, rm00, Math.fma(m10, rm01, m20 * rm02))) - ._m01(Math.fma(m01, rm00, Math.fma(m11, rm01, m21 * rm02))) - ._m02(Math.fma(m02, rm00, Math.fma(m12, rm01, m22 * rm02))) - ._m03(m03()) - ._m10(Math.fma(m00, rm10, Math.fma(m10, rm11, m20 * rm12))) - ._m11(Math.fma(m01, rm10, Math.fma(m11, rm11, m21 * rm12))) - ._m12(Math.fma(m02, rm10, Math.fma(m12, rm11, m22 * rm12))) - ._m13(m13()) - ._m20(Math.fma(m00, rm20, Math.fma(m10, rm21, m20 * rm22))) - ._m21(Math.fma(m01, rm20, Math.fma(m11, rm21, m21 * rm22))) - ._m22(Math.fma(m02, rm20, Math.fma(m12, rm21, m22 * rm22))) - ._m23(m23()) - ._m30(Math.fma(m00, rm30, Math.fma(m10, rm31, Math.fma(m20, rm32, m30())))) - ._m31(Math.fma(m01, rm30, Math.fma(m11, rm31, Math.fma(m21, rm32, m31())))) - ._m32(Math.fma(m02, rm30, Math.fma(m12, rm31, Math.fma(m22, rm32, m32())))) - ._m33(m33()) - ._properties(PROPERTY_AFFINE | (this.properties & right.properties() & PROPERTY_ORTHONORMAL)); - } - - public Matrix4f mulTranslationAffine(Matrix4fc right, Matrix4f dest) { - return dest - ._m00(right.m00()) - ._m01(right.m01()) - ._m02(right.m02()) - ._m03(m03()) - ._m10(right.m10()) - ._m11(right.m11()) - ._m12(right.m12()) - ._m13(m13()) - ._m20(right.m20()) - ._m21(right.m21()) - ._m22(right.m22()) - ._m23(m23()) - ._m30(right.m30() + m30()) - ._m31(right.m31() + m31()) - ._m32(right.m32() + m32()) - ._m33(m33()) - ._properties(PROPERTY_AFFINE | (right.properties() & PROPERTY_ORTHONORMAL)); - } - - /** - * Multiply this orthographic projection matrix by the supplied {@link #isAffine() affine} view matrix. - *

- * If M is this matrix and V the view matrix, - * then the new matrix will be M * V. So when transforming a - * vector v with the new matrix by using M * V * v, the - * transformation of the view matrix will be applied first! - * - * @param view - * the affine matrix which to multiply this with - * @return this - */ - public Matrix4f mulOrthoAffine(Matrix4fc view) { - return mulOrthoAffine(view, this); - } - - public Matrix4f mulOrthoAffine(Matrix4fc view, Matrix4f dest) { - float nm00 = m00() * view.m00(); - float nm01 = m11() * view.m01(); - float nm02 = m22() * view.m02(); - float nm10 = m00() * view.m10(); - float nm11 = m11() * view.m11(); - float nm12 = m22() * view.m12(); - float nm20 = m00() * view.m20(); - float nm21 = m11() * view.m21(); - float nm22 = m22() * view.m22(); - float nm30 = m00() * view.m30() + m30(); - float nm31 = m11() * view.m31() + m31(); - float nm32 = m22() * view.m32() + m32(); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(0.0f) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(0.0f) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(0.0f) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE); - } - - /** - * Component-wise add the upper 4x3 submatrices of this and other - * by first multiplying each component of other's 4x3 submatrix by otherFactor and - * adding that result to this. - *

- * The matrix other will not be changed. - * - * @param other - * the other matrix - * @param otherFactor - * the factor to multiply each of the other matrix's 4x3 components - * @return this - */ - public Matrix4f fma4x3(Matrix4fc other, float otherFactor) { - return fma4x3(other, otherFactor, this); - } - - public Matrix4f fma4x3(Matrix4fc other, float otherFactor, Matrix4f dest) { - dest._m00(Math.fma(other.m00(), otherFactor, m00())) - ._m01(Math.fma(other.m01(), otherFactor, m01())) - ._m02(Math.fma(other.m02(), otherFactor, m02())) - ._m03(m03()) - ._m10(Math.fma(other.m10(), otherFactor, m10())) - ._m11(Math.fma(other.m11(), otherFactor, m11())) - ._m12(Math.fma(other.m12(), otherFactor, m12())) - ._m13(m13()) - ._m20(Math.fma(other.m20(), otherFactor, m20())) - ._m21(Math.fma(other.m21(), otherFactor, m21())) - ._m22(Math.fma(other.m22(), otherFactor, m22())) - ._m23(m23()) - ._m30(Math.fma(other.m30(), otherFactor, m30())) - ._m31(Math.fma(other.m31(), otherFactor, m31())) - ._m32(Math.fma(other.m32(), otherFactor, m32())) - ._m33(m33()) - ._properties(0); - return dest; - } - - /** - * Component-wise add this and other. - * - * @param other - * the other addend - * @return this - */ - public Matrix4f add(Matrix4fc other) { - return add(other, this); - } - - public Matrix4f add(Matrix4fc other, Matrix4f dest) { - dest._m00(m00() + other.m00()) - ._m01(m01() + other.m01()) - ._m02(m02() + other.m02()) - ._m03(m03() + other.m03()) - ._m10(m10() + other.m10()) - ._m11(m11() + other.m11()) - ._m12(m12() + other.m12()) - ._m13(m13() + other.m13()) - ._m20(m20() + other.m20()) - ._m21(m21() + other.m21()) - ._m22(m22() + other.m22()) - ._m23(m23() + other.m23()) - ._m30(m30() + other.m30()) - ._m31(m31() + other.m31()) - ._m32(m32() + other.m32()) - ._m33(m33() + other.m33()) - ._properties(0); - return dest; - } - - /** - * Component-wise subtract subtrahend from this. - * - * @param subtrahend - * the subtrahend - * @return this - */ - public Matrix4f sub(Matrix4fc subtrahend) { - return sub(subtrahend, this); - } - - public Matrix4f sub(Matrix4fc subtrahend, Matrix4f dest) { - dest._m00(m00() - subtrahend.m00()) - ._m01(m01() - subtrahend.m01()) - ._m02(m02() - subtrahend.m02()) - ._m03(m03() - subtrahend.m03()) - ._m10(m10() - subtrahend.m10()) - ._m11(m11() - subtrahend.m11()) - ._m12(m12() - subtrahend.m12()) - ._m13(m13() - subtrahend.m13()) - ._m20(m20() - subtrahend.m20()) - ._m21(m21() - subtrahend.m21()) - ._m22(m22() - subtrahend.m22()) - ._m23(m23() - subtrahend.m23()) - ._m30(m30() - subtrahend.m30()) - ._m31(m31() - subtrahend.m31()) - ._m32(m32() - subtrahend.m32()) - ._m33(m33() - subtrahend.m33()) - ._properties(0); - return dest; - } - - /** - * Component-wise multiply this by other. - * - * @param other - * the other matrix - * @return this - */ - public Matrix4f mulComponentWise(Matrix4fc other) { - return mulComponentWise(other, this); - } - - public Matrix4f mulComponentWise(Matrix4fc other, Matrix4f dest) { - dest._m00(m00() * other.m00()) - ._m01(m01() * other.m01()) - ._m02(m02() * other.m02()) - ._m03(m03() * other.m03()) - ._m10(m10() * other.m10()) - ._m11(m11() * other.m11()) - ._m12(m12() * other.m12()) - ._m13(m13() * other.m13()) - ._m20(m20() * other.m20()) - ._m21(m21() * other.m21()) - ._m22(m22() * other.m22()) - ._m23(m23() * other.m23()) - ._m30(m30() * other.m30()) - ._m31(m31() * other.m31()) - ._m32(m32() * other.m32()) - ._m33(m33() * other.m33()) - ._properties(0); - return dest; - } - - /** - * Component-wise add the upper 4x3 submatrices of this and other. - * - * @param other - * the other addend - * @return this - */ - public Matrix4f add4x3(Matrix4fc other) { - return add4x3(other, this); - } - - public Matrix4f add4x3(Matrix4fc other, Matrix4f dest) { - dest._m00(m00() + other.m00()) - ._m01(m01() + other.m01()) - ._m02(m02() + other.m02()) - ._m03(m03()) - ._m10(m10() + other.m10()) - ._m11(m11() + other.m11()) - ._m12(m12() + other.m12()) - ._m13(m13()) - ._m20(m20() + other.m20()) - ._m21(m21() + other.m21()) - ._m22(m22() + other.m22()) - ._m23(m23()) - ._m30(m30() + other.m30()) - ._m31(m31() + other.m31()) - ._m32(m32() + other.m32()) - ._m33(m33()) - ._properties(0); - return dest; - } - - /** - * Component-wise subtract the upper 4x3 submatrices of subtrahend from this. - * - * @param subtrahend - * the subtrahend - * @return this - */ - public Matrix4f sub4x3(Matrix4f subtrahend) { - return sub4x3(subtrahend, this); - } - - public Matrix4f sub4x3(Matrix4fc subtrahend, Matrix4f dest) { - dest._m00(m00() - subtrahend.m00()) - ._m01(m01() - subtrahend.m01()) - ._m02(m02() - subtrahend.m02()) - ._m03(m03()) - ._m10(m10() - subtrahend.m10()) - ._m11(m11() - subtrahend.m11()) - ._m12(m12() - subtrahend.m12()) - ._m13(m13()) - ._m20(m20() - subtrahend.m20()) - ._m21(m21() - subtrahend.m21()) - ._m22(m22() - subtrahend.m22()) - ._m23(m23()) - ._m30(m30() - subtrahend.m30()) - ._m31(m31() - subtrahend.m31()) - ._m32(m32() - subtrahend.m32()) - ._m33(m33()) - ._properties(0); - return dest; - } - - /** - * Component-wise multiply the upper 4x3 submatrices of this by other. - * - * @param other - * the other matrix - * @return this - */ - public Matrix4f mul4x3ComponentWise(Matrix4fc other) { - return mul4x3ComponentWise(other, this); - } - - public Matrix4f mul4x3ComponentWise(Matrix4fc other, Matrix4f dest) { - dest._m00(m00() * other.m00()) - ._m01(m01() * other.m01()) - ._m02(m02() * other.m02()) - ._m03(m03()) - ._m10(m10() * other.m10()) - ._m11(m11() * other.m11()) - ._m12(m12() * other.m12()) - ._m13(m13()) - ._m20(m20() * other.m20()) - ._m21(m21() * other.m21()) - ._m22(m22() * other.m22()) - ._m23(m23()) - ._m30(m30() * other.m30()) - ._m31(m31() * other.m31()) - ._m32(m32() * other.m32()) - ._m33(m33()) - ._properties(0); - return dest; - } - - /** - * Set the values within this matrix to the supplied float values. The matrix will look like this:

- * - * m00, m10, m20, m30
- * m01, m11, m21, m31
- * m02, m12, m22, m32
- * m03, m13, m23, m33 - * - * @param m00 - * the new value of m00 - * @param m01 - * the new value of m01 - * @param m02 - * the new value of m02 - * @param m03 - * the new value of m03 - * @param m10 - * the new value of m10 - * @param m11 - * the new value of m11 - * @param m12 - * the new value of m12 - * @param m13 - * the new value of m13 - * @param m20 - * the new value of m20 - * @param m21 - * the new value of m21 - * @param m22 - * the new value of m22 - * @param m23 - * the new value of m23 - * @param m30 - * the new value of m30 - * @param m31 - * the new value of m31 - * @param m32 - * the new value of m32 - * @param m33 - * the new value of m33 - * @return this - */ - public Matrix4f set(float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23, - float m30, float m31, float m32, float m33) { - return this - ._m00(m00) - ._m10(m10) - ._m20(m20) - ._m30(m30) - ._m01(m01) - ._m11(m11) - ._m21(m21) - ._m31(m31) - ._m02(m02) - ._m12(m12) - ._m22(m22) - ._m32(m32) - ._m03(m03) - ._m13(m13) - ._m23(m23) - ._m33(m33) - .determineProperties(); - } - - /** - * Set the values in the matrix using a float array that contains the matrix elements in column-major order. - *

- * The results will look like this:

- * - * 0, 4, 8, 12
- * 1, 5, 9, 13
- * 2, 6, 10, 14
- * 3, 7, 11, 15
- * - * @see #set(float[]) - * - * @param m - * the array to read the matrix values from - * @param off - * the offset into the array - * @return this - */ - public Matrix4f set(float m[], int off) { - MemUtil.INSTANCE.copy(m, off, this); - return determineProperties(); - } - - /** - * Set the values in the matrix using a float array that contains the matrix elements in column-major order. - *

- * The results will look like this:

- * - * 0, 4, 8, 12
- * 1, 5, 9, 13
- * 2, 6, 10, 14
- * 3, 7, 11, 15
- * - * @see #set(float[], int) - * - * @param m - * the array to read the matrix values from - * @return this - */ - public Matrix4f set(float m[]) { - return set(m, 0); - } - - /** - * Set the values in the matrix using a float array that contains the matrix elements in row-major order. - *

- * The results will look like this:

- * - * 0, 1, 2, 3
- * 4, 5, 6, 7
- * 8, 9, 10, 11
- * 12, 13, 14, 15
- * - * @see #setTransposed(float[]) - * - * @param m - * the array to read the matrix values from - * @param off - * the offset into the array - * @return this - */ - public Matrix4f setTransposed(float m[], int off) { - MemUtil.INSTANCE.copyTransposed(m, off, this); - return determineProperties(); - } - - /** - * Set the values in the matrix using a float array that contains the matrix elements in row-major order. - *

- * The results will look like this:

- * - * 0, 1, 2, 3
- * 4, 5, 6, 7
- * 8, 9, 10, 11
- * 12, 13, 14, 15
- * - * @see #setTransposed(float[], int) - * - * @param m - * the array to read the matrix values from - * @return this - */ - public Matrix4f setTransposed(float m[]) { - return setTransposed(m, 0); - } - - /** - * Set the values of this matrix by reading 16 float values from the given {@link FloatBuffer} in column-major order, - * starting at its current position. - *

- * The FloatBuffer is expected to contain the values in column-major order. - *

- * The position of the FloatBuffer will not be changed by this method. - * - * @param buffer - * the FloatBuffer to read the matrix values from in column-major order - * @return this - */ - public Matrix4f set(FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - return determineProperties(); - } - - /** - * Set the values of this matrix by reading 16 float values from the given {@link ByteBuffer} in column-major order, - * starting at its current position. - *

- * The ByteBuffer is expected to contain the values in column-major order. - *

- * The position of the ByteBuffer will not be changed by this method. - * - * @param buffer - * the ByteBuffer to read the matrix values from in column-major order - * @return this - */ - public Matrix4f set(ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - return determineProperties(); - } - - /** - * Set the values of this matrix by reading 16 float values from the given {@link FloatBuffer} in column-major order, - * starting at the specified absolute buffer position/index. - *

- * The FloatBuffer is expected to contain the values in column-major order. - *

- * The position of the FloatBuffer will not be changed by this method. - * - * @param index - * the absolute position into the FloatBuffer - * @param buffer - * the FloatBuffer to read the matrix values from in column-major order - * @return this - */ - public Matrix4f set(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - return determineProperties(); - } - - /** - * Set the values of this matrix by reading 16 float values from the given {@link ByteBuffer} in column-major order, - * starting at the specified absolute buffer position/index. - *

- * The ByteBuffer is expected to contain the values in column-major order. - *

- * The position of the ByteBuffer will not be changed by this method. - * - * @param index - * the absolute position into the ByteBuffer - * @param buffer - * the ByteBuffer to read the matrix values from in column-major order - * @return this - */ - public Matrix4f set(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - return determineProperties(); - } - - /** - * Set the values of this matrix by reading 16 float values from the given {@link FloatBuffer} in row-major order, - * starting at its current position. - *

- * The FloatBuffer is expected to contain the values in row-major order. - *

- * The position of the FloatBuffer will not be changed by this method. - * - * @param buffer - * the FloatBuffer to read the matrix values from in row-major order - * @return this - */ - public Matrix4f setTransposed(FloatBuffer buffer) { - MemUtil.INSTANCE.getTransposed(this, buffer.position(), buffer); - return determineProperties(); - } - - /** - * Set the values of this matrix by reading 16 float values from the given {@link ByteBuffer} in row-major order, - * starting at its current position. - *

- * The ByteBuffer is expected to contain the values in row-major order. - *

- * The position of the ByteBuffer will not be changed by this method. - * - * @param buffer - * the ByteBuffer to read the matrix values from in row-major order - * @return this - */ - public Matrix4f setTransposed(ByteBuffer buffer) { - MemUtil.INSTANCE.getTransposed(this, buffer.position(), buffer); - return determineProperties(); - } - - /** - * Set the values of this matrix by reading 16 float values from off-heap memory in column-major order, - * starting at the given address. - *

- * This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`. - *

- * 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. - * - * @param address - * the off-heap memory address to read the matrix values from in column-major order - * @return this - */ - public Matrix4f setFromAddress(long address) { - if (Options.NO_UNSAFE) - throw new UnsupportedOperationException("Not supported when using joml.nounsafe"); - MemUtil.MemUtilUnsafe.get(this, address); - return determineProperties(); - } - - /** - * Set the values of this matrix by reading 16 float values from off-heap memory in row-major order, - * starting at the given address. - *

- * This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`. - *

- * 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. - * - * @param address - * the off-heap memory address to read the matrix values from in row-major order - * @return this - */ - public Matrix4f setTransposedFromAddress(long address) { - if (Options.NO_UNSAFE) - throw new UnsupportedOperationException("Not supported when using joml.nounsafe"); - MemUtil.MemUtilUnsafe.getTransposed(this, address); - return determineProperties(); - } - - /** - * Set the four columns of this matrix to the supplied vectors, respectively. - * - * @param col0 - * the first column - * @param col1 - * the second column - * @param col2 - * the third column - * @param col3 - * the fourth column - * @return this - */ - public Matrix4f set(Vector4fc col0, Vector4fc col1, Vector4fc col2, Vector4fc col3) { - return - _m00(col0.x()). - _m01(col0.y()). - _m02(col0.z()). - _m03(col0.w()). - _m10(col1.x()). - _m11(col1.y()). - _m12(col1.z()). - _m13(col1.w()). - _m20(col2.x()). - _m21(col2.y()). - _m22(col2.z()). - _m23(col2.w()). - _m30(col3.x()). - _m31(col3.y()). - _m32(col3.z()). - _m33(col3.w()). - determineProperties(); - } - - public float determinant() { - if ((properties & PROPERTY_AFFINE) != 0) - return determinantAffine(); - return (m00() * m11() - m01() * m10()) * (m22() * m33() - m23() * m32()) - + (m02() * m10() - m00() * m12()) * (m21() * m33() - m23() * m31()) - + (m00() * m13() - m03() * m10()) * (m21() * m32() - m22() * m31()) - + (m01() * m12() - m02() * m11()) * (m20() * m33() - m23() * m30()) - + (m03() * m11() - m01() * m13()) * (m20() * m32() - m22() * m30()) - + (m02() * m13() - m03() * m12()) * (m20() * m31() - m21() * m30()); - } - - public float determinant3x3() { - return (m00() * m11() - m01() * m10()) * m22() - + (m02() * m10() - m00() * m12()) * m21() - + (m01() * m12() - m02() * m11()) * m20(); - } - - public float determinantAffine() { - return (m00() * m11() - m01() * m10()) * m22() - + (m02() * m10() - m00() * m12()) * m21() - + (m01() * m12() - m02() * m11()) * m20(); - } - - public Matrix4f invert(Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) { - return dest.identity(); - } else if ((properties & PROPERTY_TRANSLATION) != 0) - return invertTranslation(dest); - else if ((properties & PROPERTY_ORTHONORMAL) != 0) - return invertOrthonormal(dest); - else if ((properties & PROPERTY_AFFINE) != 0) - return invertAffine(dest); - else if ((properties & PROPERTY_PERSPECTIVE) != 0) - return invertPerspective(dest); - return invertGeneric(dest); - } - private Matrix4f invertTranslation(Matrix4f dest) { - if (dest != this) - dest.set(this); - return dest._m30(-m30())._m31(-m31())._m32(-m32())._properties(PROPERTY_AFFINE | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); - } - private Matrix4f invertOrthonormal(Matrix4f dest) { - float nm30 = -(m00() * m30() + m01() * m31() + m02() * m32()); - float nm31 = -(m10() * m30() + m11() * m31() + m12() * m32()); - float nm32 = -(m20() * m30() + m21() * m31() + m22() * m32()); - float m01 = this.m01(); - float m02 = this.m02(); - float m12 = this.m12(); - return dest - ._m00(m00()) - ._m01(m10()) - ._m02(m20()) - ._m03(0.0f) - ._m10(m01) - ._m11(m11()) - ._m12(m21()) - ._m13(0.0f) - ._m20(m02) - ._m21(m12) - ._m22(m22()) - ._m23(0.0f) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - private Matrix4f invertGeneric(Matrix4f dest) { - if (this != dest) - return invertGenericNonThis(dest); - return invertGenericThis(dest); - } - private Matrix4f invertGenericNonThis(Matrix4f dest) { - float a = m00() * m11() - m01() * m10(); - float b = m00() * m12() - m02() * m10(); - float c = m00() * m13() - m03() * m10(); - float d = m01() * m12() - m02() * m11(); - float e = m01() * m13() - m03() * m11(); - float f = m02() * m13() - m03() * m12(); - float g = m20() * m31() - m21() * m30(); - float h = m20() * m32() - m22() * m30(); - float i = m20() * m33() - m23() * m30(); - float j = m21() * m32() - m22() * m31(); - float k = m21() * m33() - m23() * m31(); - float l = m22() * m33() - m23() * m32(); - float det = a * l - b * k + c * j + d * i - e * h + f * g; - det = 1.0f / det; - return dest - ._m00(Math.fma( m11(), l, Math.fma(-m12(), k, m13() * j)) * det) - ._m01(Math.fma(-m01(), l, Math.fma( m02(), k, -m03() * j)) * det) - ._m02(Math.fma( m31(), f, Math.fma(-m32(), e, m33() * d)) * det) - ._m03(Math.fma(-m21(), f, Math.fma( m22(), e, -m23() * d)) * det) - ._m10(Math.fma(-m10(), l, Math.fma( m12(), i, -m13() * h)) * det) - ._m11(Math.fma( m00(), l, Math.fma(-m02(), i, m03() * h)) * det) - ._m12(Math.fma(-m30(), f, Math.fma( m32(), c, -m33() * b)) * det) - ._m13(Math.fma( m20(), f, Math.fma(-m22(), c, m23() * b)) * det) - ._m20(Math.fma( m10(), k, Math.fma(-m11(), i, m13() * g)) * det) - ._m21(Math.fma(-m00(), k, Math.fma( m01(), i, -m03() * g)) * det) - ._m22(Math.fma( m30(), e, Math.fma(-m31(), c, m33() * a)) * det) - ._m23(Math.fma(-m20(), e, Math.fma( m21(), c, -m23() * a)) * det) - ._m30(Math.fma(-m10(), j, Math.fma( m11(), h, -m12() * g)) * det) - ._m31(Math.fma( m00(), j, Math.fma(-m01(), h, m02() * g)) * det) - ._m32(Math.fma(-m30(), d, Math.fma( m31(), b, -m32() * a)) * det) - ._m33(Math.fma( m20(), d, Math.fma(-m21(), b, m22() * a)) * det) - ._properties(0); - } - private Matrix4f invertGenericThis(Matrix4f dest) { - float a = m00() * m11() - m01() * m10(); - float b = m00() * m12() - m02() * m10(); - float c = m00() * m13() - m03() * m10(); - float d = m01() * m12() - m02() * m11(); - float e = m01() * m13() - m03() * m11(); - float f = m02() * m13() - m03() * m12(); - float g = m20() * m31() - m21() * m30(); - float h = m20() * m32() - m22() * m30(); - float i = m20() * m33() - m23() * m30(); - float j = m21() * m32() - m22() * m31(); - float k = m21() * m33() - m23() * m31(); - float l = m22() * m33() - m23() * m32(); - float det = a * l - b * k + c * j + d * i - e * h + f * g; - det = 1.0f / det; - float nm00 = Math.fma( m11(), l, Math.fma(-m12(), k, m13() * j)) * det; - float nm01 = Math.fma(-m01(), l, Math.fma( m02(), k, -m03() * j)) * det; - float nm02 = Math.fma( m31(), f, Math.fma(-m32(), e, m33() * d)) * det; - float nm03 = Math.fma(-m21(), f, Math.fma( m22(), e, -m23() * d)) * det; - float nm10 = Math.fma(-m10(), l, Math.fma( m12(), i, -m13() * h)) * det; - float nm11 = Math.fma( m00(), l, Math.fma(-m02(), i, m03() * h)) * det; - float nm12 = Math.fma(-m30(), f, Math.fma( m32(), c, -m33() * b)) * det; - float nm13 = Math.fma( m20(), f, Math.fma(-m22(), c, m23() * b)) * det; - float nm20 = Math.fma( m10(), k, Math.fma(-m11(), i, m13() * g)) * det; - float nm21 = Math.fma(-m00(), k, Math.fma( m01(), i, -m03() * g)) * det; - float nm22 = Math.fma( m30(), e, Math.fma(-m31(), c, m33() * a)) * det; - float nm23 = Math.fma(-m20(), e, Math.fma( m21(), c, -m23() * a)) * det; - float nm30 = Math.fma(-m10(), j, Math.fma( m11(), h, -m12() * g)) * det; - float nm31 = Math.fma( m00(), j, Math.fma(-m01(), h, m02() * g)) * det; - float nm32 = Math.fma(-m30(), d, Math.fma( m31(), b, -m32() * a)) * det; - float nm33 = Math.fma( m20(), d, Math.fma(-m21(), b, m22() * a)) * det; - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(nm33) - ._properties(0); - } - - /** - * Invert this matrix. - *

- * If this matrix represents an {@link #isAffine() affine} transformation, such as translation, rotation, scaling and shearing, - * and thus its last row is equal to (0, 0, 0, 1), then {@link #invertAffine()} can be used instead of this method. - * - * @see #invertAffine() - * - * @return this - */ - public Matrix4f invert() { - return invert(this); - } - - /** - * If this is a perspective projection matrix obtained via one of the {@link #perspective(float, float, float, float) perspective()} methods - * or via {@link #setPerspective(float, float, float, float) setPerspective()}, that is, if this is a symmetrical perspective frustum transformation, - * then this method builds the inverse of this and stores it into the given dest. - *

- * This method can be used to quickly obtain the inverse of a perspective projection matrix when being obtained via {@link #perspective(float, float, float, float) perspective()}. - * - * @see #perspective(float, float, float, float) - * - * @param dest - * will hold the inverse of this - * @return dest - */ - public Matrix4f invertPerspective(Matrix4f dest) { - float a = 1.0f / (m00() * m11()); - float l = -1.0f / (m23() * m32()); - return dest - .set(m11() * a, 0, 0, 0, - 0, m00() * a, 0, 0, - 0, 0, 0, -m23() * l, - 0, 0, -m32() * l, m22() * l) - ._properties(0); - } - - /** - * If this is a perspective projection matrix obtained via one of the {@link #perspective(float, float, float, float) perspective()} methods - * or via {@link #setPerspective(float, float, float, float) setPerspective()}, that is, if this is a symmetrical perspective frustum transformation, - * then this method builds the inverse of this. - *

- * This method can be used to quickly obtain the inverse of a perspective projection matrix when being obtained via {@link #perspective(float, float, float, float) perspective()}. - * - * @see #perspective(float, float, float, float) - * - * @return this - */ - public Matrix4f invertPerspective() { - return invertPerspective(this); - } - - /** - * If this is an arbitrary perspective projection matrix obtained via one of the {@link #frustum(float, float, float, float, float, float) frustum()} methods - * or via {@link #setFrustum(float, float, float, float, float, float) setFrustum()}, - * then this method builds the inverse of this and stores it into the given dest. - *

- * This method can be used to quickly obtain the inverse of a perspective projection matrix. - *

- * If this matrix represents a symmetric perspective frustum transformation, as obtained via {@link #perspective(float, float, float, float) perspective()}, then - * {@link #invertPerspective(Matrix4f)} should be used instead. - * - * @see #frustum(float, float, float, float, float, float) - * @see #invertPerspective(Matrix4f) - * - * @param dest - * will hold the inverse of this - * @return dest - */ - public Matrix4f invertFrustum(Matrix4f dest) { - float invM00 = 1.0f / m00(); - float invM11 = 1.0f / m11(); - float invM23 = 1.0f / m23(); - float invM32 = 1.0f / m32(); - return dest - .set(invM00, 0, 0, 0, - 0, invM11, 0, 0, - 0, 0, 0, invM32, - -m20() * invM00 * invM23, -m21() * invM11 * invM23, invM23, -m22() * invM23 * invM32); - } - - /** - * If this is an arbitrary perspective projection matrix obtained via one of the {@link #frustum(float, float, float, float, float, float) frustum()} methods - * or via {@link #setFrustum(float, float, float, float, float, float) setFrustum()}, - * then this method builds the inverse of this. - *

- * This method can be used to quickly obtain the inverse of a perspective projection matrix. - *

- * If this matrix represents a symmetric perspective frustum transformation, as obtained via {@link #perspective(float, float, float, float) perspective()}, then - * {@link #invertPerspective()} should be used instead. - * - * @see #frustum(float, float, float, float, float, float) - * @see #invertPerspective() - * - * @return this - */ - public Matrix4f invertFrustum() { - return invertFrustum(this); - } - - public Matrix4f invertOrtho(Matrix4f dest) { - float invM00 = 1.0f / m00(); - float invM11 = 1.0f / m11(); - float invM22 = 1.0f / m22(); - return dest - .set(invM00, 0, 0, 0, - 0, invM11, 0, 0, - 0, 0, invM22, 0, - -m30() * invM00, -m31() * invM11, -m32() * invM22, 1) - ._properties(PROPERTY_AFFINE | (this.properties & PROPERTY_ORTHONORMAL)); - } - - /** - * Invert this orthographic projection matrix. - *

- * This method can be used to quickly obtain the inverse of an orthographic projection matrix. - * - * @return this - */ - public Matrix4f invertOrtho() { - return invertOrtho(this); - } - - /** - * If this is a perspective projection matrix obtained via one of the {@link #perspective(float, float, float, float) perspective()} methods - * or via {@link #setPerspective(float, float, float, float) setPerspective()}, that is, if this is a symmetrical perspective frustum transformation - * and the given view matrix is {@link #isAffine() affine} and has unit scaling (for example by being obtained via {@link #lookAt(float, float, float, float, float, float, float, float, float) lookAt()}), - * then this method builds the inverse of this * view and stores it into the given dest. - *

- * This method can be used to quickly obtain the inverse of the combination of the view and projection matrices, when both were obtained - * via the common methods {@link #perspective(float, float, float, float) perspective()} and {@link #lookAt(float, float, float, float, float, float, float, float, float) lookAt()} or - * other methods, that build affine matrices, such as {@link #translate(float, float, float) translate} and {@link #rotate(float, float, float, float)}, except for {@link #scale(float, float, float) scale()}. - *

- * For the special cases of the matrices this and view mentioned above, this method is equivalent to the following code: - *

-     * dest.set(this).mul(view).invert();
-     * 
- * - * @param view - * the view transformation (must be {@link #isAffine() affine} and have unit scaling) - * @param dest - * will hold the inverse of this * view - * @return dest - */ - public Matrix4f invertPerspectiveView(Matrix4fc view, Matrix4f dest) { - float a = 1.0f / (m00() * m11()); - float l = -1.0f / (m23() * m32()); - float pm00 = m11() * a; - float pm11 = m00() * a; - float pm23 = -m23() * l; - float pm32 = -m32() * l; - float pm33 = m22() * l; - float vm30 = -view.m00() * view.m30() - view.m01() * view.m31() - view.m02() * view.m32(); - float vm31 = -view.m10() * view.m30() - view.m11() * view.m31() - view.m12() * view.m32(); - float vm32 = -view.m20() * view.m30() - view.m21() * view.m31() - view.m22() * view.m32(); - float nm10 = view.m01() * pm11; - float nm30 = view.m02() * pm32 + vm30 * pm33; - float nm31 = view.m12() * pm32 + vm31 * pm33; - float nm32 = view.m22() * pm32 + vm32 * pm33; - return dest - ._m00(view.m00() * pm00) - ._m01(view.m10() * pm00) - ._m02(view.m20() * pm00) - ._m03(0.0f) - ._m10(nm10) - ._m11(view.m11() * pm11) - ._m12(view.m21() * pm11) - ._m13(0.0f) - ._m20(vm30 * pm23) - ._m21(vm31 * pm23) - ._m22(vm32 * pm23) - ._m23(pm23) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(pm33) - ._properties(0); - } - - public Matrix4f invertAffine(Matrix4f dest) { - float m11m00 = m00() * m11(), m10m01 = m01() * m10(), m10m02 = m02() * m10(); - float m12m00 = m00() * m12(), m12m01 = m01() * m12(), m11m02 = m02() * m11(); - float det = (m11m00 - m10m01) * m22() + (m10m02 - m12m00) * m21() + (m12m01 - m11m02) * m20(); - float s = 1.0f / det; - float m10m22 = m10() * m22(), m10m21 = m10() * m21(), m11m22 = m11() * m22(); - float m11m20 = m11() * m20(), m12m21 = m12() * m21(), m12m20 = m12() * m20(); - float m20m02 = m20() * m02(), m20m01 = m20() * m01(), m21m02 = m21() * m02(); - float m21m00 = m21() * m00(), m22m01 = m22() * m01(), m22m00 = m22() * m00(); - float nm31 = (m20m02 * m31() - m20m01 * m32() + m21m00 * m32() - m21m02 * m30() + m22m01 * m30() - m22m00 * m31()) * s; - float nm32 = (m11m02 * m30() - m12m01 * m30() + m12m00 * m31() - m10m02 * m31() + m10m01 * m32() - m11m00 * m32()) * s; - return dest - ._m00((m11m22 - m12m21) * s) - ._m01((m21m02 - m22m01) * s) - ._m02((m12m01 - m11m02) * s) - ._m03(0.0f) - ._m10((m12m20 - m10m22) * s) - ._m11((m22m00 - m20m02) * s) - ._m12((m10m02 - m12m00) * s) - ._m13(0.0f) - ._m20((m10m21 - m11m20) * s) - ._m21((m20m01 - m21m00) * s) - ._m22((m11m00 - m10m01) * s) - ._m23(0.0f) - ._m30((m10m22 * m31() - m10m21 * m32() + m11m20 * m32() - m11m22 * m30() + m12m21 * m30() - m12m20 * m31()) * s) - ._m31(nm31) - ._m32(nm32) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE); - } - - /** - * Invert this matrix by assuming that it is an {@link #isAffine() affine} transformation (i.e. its last row is equal to (0, 0, 0, 1)). - * - * @return this - */ - public Matrix4f invertAffine() { - return invertAffine(this); - } - - public Matrix4f transpose(Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.identity(); - else if (this != dest) - return transposeNonThisGeneric(dest); - return transposeThisGeneric(dest); - } - private Matrix4f transposeNonThisGeneric(Matrix4f dest) { - return dest - ._m00(m00()) - ._m01(m10()) - ._m02(m20()) - ._m03(m30()) - ._m10(m01()) - ._m11(m11()) - ._m12(m21()) - ._m13(m31()) - ._m20(m02()) - ._m21(m12()) - ._m22(m22()) - ._m23(m32()) - ._m30(m03()) - ._m31(m13()) - ._m32(m23()) - ._m33(m33()) - ._properties(0); - } - private Matrix4f transposeThisGeneric(Matrix4f dest) { - float nm10 = m01(); - float nm20 = m02(); - float nm21 = m12(); - float nm30 = m03(); - float nm31 = m13(); - float nm32 = m23(); - return dest - ._m01(m10()) - ._m02(m20()) - ._m03(m30()) - ._m10(nm10) - ._m12(m21()) - ._m13(m31()) - ._m20(nm20) - ._m21(nm21) - ._m23(m32()) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._properties(0); - } - - /** - * Transpose only the upper left 3x3 submatrix of this matrix. - *

- * All other matrix elements are left unchanged. - * - * @return this - */ - public Matrix4f transpose3x3() { - return transpose3x3(this); - } - - public Matrix4f transpose3x3(Matrix4f dest) { - float nm10 = m01(), nm20 = m02(), nm21 = m12(); - return dest - ._m00(m00()) - ._m01(m10()) - ._m02(m20()) - ._m10(nm10) - ._m11(m11()) - ._m12(m21()) - ._m20(nm20) - ._m21(nm21) - ._m22(m22()) - ._properties(this.properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - public Matrix3f transpose3x3(Matrix3f dest) { - return dest - ._m00(m00()) - ._m01(m10()) - ._m02(m20()) - ._m10(m01()) - ._m11(m11()) - ._m12(m21()) - ._m20(m02()) - ._m21(m12()) - ._m22(m22()); - } - - /** - * Transpose this matrix. - * - * @return this - */ - public Matrix4f transpose() { - return transpose(this); - } - - /** - * Set this matrix to be a simple translation matrix. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional translation. - *

- * In order to post-multiply a translation transformation directly to a - * matrix, use {@link #translate(float, float, float) translate()} instead. - * - * @see #translate(float, float, float) - * - * @param x - * the offset to translate in x - * @param y - * the offset to translate in y - * @param z - * the offset to translate in z - * @return this - */ - public Matrix4f translation(float x, float y, float z) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - return this._m30(x)._m31(y)._m32(z)._properties(PROPERTY_AFFINE | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); - } - - /** - * Set this matrix to be a simple translation matrix. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional translation. - *

- * In order to post-multiply a translation transformation directly to a - * matrix, use {@link #translate(Vector3fc) translate()} instead. - * - * @see #translate(float, float, float) - * - * @param offset - * the offsets in x, y and z to translate - * @return this - */ - public Matrix4f translation(Vector3fc offset) { - return translation(offset.x(), offset.y(), offset.z()); - } - - /** - * Set only the translation components (m30, m31, m32) of this matrix to the given values (x, y, z). - *

- * Note that this will only work properly for orthogonal matrices (without any perspective). - *

- * To build a translation matrix instead, use {@link #translation(float, float, float)}. - * To apply a translation, use {@link #translate(float, float, float)}. - * - * @see #translation(float, float, float) - * @see #translate(float, float, float) - * - * @param x - * the offset to translate in x - * @param y - * the offset to translate in y - * @param z - * the offset to translate in z - * @return this - */ - public Matrix4f setTranslation(float x, float y, float z) { - return this._m30(x)._m31(y)._m32(z)._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY)); - } - - /** - * Set only the translation components (m30, m31, m32) of this matrix to the values (xyz.x, xyz.y, xyz.z). - *

- * Note that this will only work properly for orthogonal matrices (without any perspective). - *

- * To build a translation matrix instead, use {@link #translation(Vector3fc)}. - * To apply a translation, use {@link #translate(Vector3fc)}. - * - * @see #translation(Vector3fc) - * @see #translate(Vector3fc) - * - * @param xyz - * the units to translate in (x, y, z) - * @return this - */ - public Matrix4f setTranslation(Vector3fc xyz) { - return setTranslation(xyz.x(), xyz.y(), xyz.z()); - } - - public Vector3f getTranslation(Vector3f dest) { - dest.x = m30(); - dest.y = m31(); - dest.z = m32(); - return dest; - } - - public Vector3f getScale(Vector3f dest) { - dest.x = Math.sqrt(m00() * m00() + m01() * m01() + m02() * m02()); - dest.y = Math.sqrt(m10() * m10() + m11() * m11() + m12() * m12()); - dest.z = Math.sqrt(m20() * m20() + m21() * m21() + m22() * m22()); - return dest; - } - - /** - * Return a string representation of this matrix. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - String str = toString(Options.NUMBER_FORMAT); - 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(); - } - - /** - * Return a string representation of this matrix by formatting the matrix elements with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the matrix values with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return Runtime.format(m00(), formatter) + " " + Runtime.format(m10(), formatter) + " " + Runtime.format(m20(), formatter) + " " + Runtime.format(m30(), formatter) + "\n" - + Runtime.format(m01(), formatter) + " " + Runtime.format(m11(), formatter) + " " + Runtime.format(m21(), formatter) + " " + Runtime.format(m31(), formatter) + "\n" - + Runtime.format(m02(), formatter) + " " + Runtime.format(m12(), formatter) + " " + Runtime.format(m22(), formatter) + " " + Runtime.format(m32(), formatter) + "\n" - + Runtime.format(m03(), formatter) + " " + Runtime.format(m13(), formatter) + " " + Runtime.format(m23(), formatter) + " " + Runtime.format(m33(), formatter) + "\n"; - } - - /** - * Get the current values of this matrix and store them into - * dest. - *

- * This is the reverse method of {@link #set(Matrix4fc)} and allows to obtain - * intermediate calculation results when chaining multiple transformations. - * - * @see #set(Matrix4fc) - * - * @param dest - * the destination matrix - * @return the passed in destination - */ - public Matrix4f get(Matrix4f dest) { - return dest.set(this); - } - - public Matrix3f get3x3(Matrix3f dest) { - return dest.set(this); - } - - public AxisAngle4f getRotation(AxisAngle4f dest) { - return dest.set(this); - } - - public Quaternionf getUnnormalizedRotation(Quaternionf dest) { - return dest.setFromUnnormalized(this); - } - - public Quaternionf getNormalizedRotation(Quaternionf dest) { - return dest.setFromNormalized(this); - } - - public FloatBuffer get(FloatBuffer buffer) { - MemUtil.INSTANCE.put(this, buffer.position(), buffer); - return buffer; - } - - public FloatBuffer get(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.put(this, index, buffer); - return buffer; - } - - public ByteBuffer get(ByteBuffer buffer) { - MemUtil.INSTANCE.put(this, buffer.position(), buffer); - return buffer; - } - - public ByteBuffer get(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.put(this, index, buffer); - return buffer; - } - - public FloatBuffer get4x3(FloatBuffer buffer) { - MemUtil.INSTANCE.put4x3(this, buffer.position(), buffer); - return buffer; - } - - public FloatBuffer get4x3(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.put4x3(this, index, buffer); - return buffer; - } - - public ByteBuffer get4x3(ByteBuffer buffer) { - MemUtil.INSTANCE.put4x3(this, buffer.position(), buffer); - return buffer; - } - - public ByteBuffer get4x3(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.put4x3(this, index, buffer); - return buffer; - } - - public FloatBuffer get3x4(FloatBuffer buffer) { - MemUtil.INSTANCE.put3x4(this, buffer.position(), buffer); - return buffer; - } - - public FloatBuffer get3x4(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.put3x4(this, index, buffer); - return buffer; - } - - public ByteBuffer get3x4(ByteBuffer buffer) { - MemUtil.INSTANCE.put3x4(this, buffer.position(), buffer); - return buffer; - } - - public ByteBuffer get3x4(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.put3x4(this, index, buffer); - return buffer; - } - - public FloatBuffer getTransposed(FloatBuffer buffer) { - MemUtil.INSTANCE.putTransposed(this, buffer.position(), buffer); - return buffer; - } - - public FloatBuffer getTransposed(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.putTransposed(this, index, buffer); - return buffer; - } - - public ByteBuffer getTransposed(ByteBuffer buffer) { - MemUtil.INSTANCE.putTransposed(this, buffer.position(), buffer); - return buffer; - } - - public ByteBuffer getTransposed(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.putTransposed(this, index, buffer); - return buffer; - } - - public FloatBuffer get4x3Transposed(FloatBuffer buffer) { - MemUtil.INSTANCE.put4x3Transposed(this, buffer.position(), buffer); - return buffer; - } - - public FloatBuffer get4x3Transposed(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.put4x3Transposed(this, index, buffer); - return buffer; - } - - public ByteBuffer get4x3Transposed(ByteBuffer buffer) { - MemUtil.INSTANCE.put4x3Transposed(this, buffer.position(), buffer); - return buffer; - } - - public ByteBuffer get4x3Transposed(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.put4x3Transposed(this, index, buffer); - return buffer; - } - public Matrix4fc getToAddress(long address) { - if (Options.NO_UNSAFE) - throw new UnsupportedOperationException("Not supported when using joml.nounsafe"); - MemUtil.MemUtilUnsafe.put(this, address); - return this; - } - - public float[] get(float[] arr, int offset) { - MemUtil.INSTANCE.copy(this, arr, offset); - return arr; - } - - public float[] get(float[] arr) { - MemUtil.INSTANCE.copy(this, arr, 0); - return arr; - } - - /** - * Set all the values within this matrix to 0. - * - * @return this - */ - public Matrix4f zero() { - MemUtil.INSTANCE.zero(this); - return _properties(0); - } - - /** - * Set this matrix to be a simple scale matrix, which scales all axes uniformly by the given factor. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional scaling. - *

- * In order to post-multiply a scaling transformation directly to a - * matrix, use {@link #scale(float) scale()} instead. - * - * @see #scale(float) - * - * @param factor - * the scale factor in x, y and z - * @return this - */ - public Matrix4f scaling(float factor) { - return scaling(factor, factor, factor); - } - - /** - * Set this matrix to be a simple scale matrix. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional scaling. - *

- * In order to post-multiply a scaling transformation directly to a - * matrix, use {@link #scale(float, float, float) scale()} instead. - * - * @see #scale(float, float, float) - * - * @param x - * the scale in x - * @param y - * the scale in y - * @param z - * the scale in z - * @return this - */ - public Matrix4f scaling(float x, float y, float z) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - boolean one = Math.absEqualsOne(x) && Math.absEqualsOne(y) && Math.absEqualsOne(z); - return this - ._m00(x) - ._m11(y) - ._m22(z) - ._properties(PROPERTY_AFFINE | (one ? PROPERTY_ORTHONORMAL : 0)); - } - - /** - * Set this matrix to be a simple scale matrix which scales the base axes by xyz.x, xyz.y and xyz.z respectively. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional scaling. - *

- * In order to post-multiply a scaling transformation directly to a - * matrix use {@link #scale(Vector3fc) scale()} instead. - * - * @see #scale(Vector3fc) - * - * @param xyz - * the scale in x, y and z respectively - * @return this - */ - public Matrix4f scaling(Vector3fc xyz) { - return scaling(xyz.x(), xyz.y(), xyz.z()); - } - - /** - * Set this matrix to a rotation matrix which rotates the given radians about a given axis. - *

- * The axis described by the axis vector needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional rotation. - *

- * In order to post-multiply a rotation transformation directly to a - * matrix, use {@link #rotate(float, Vector3fc) rotate()} instead. - * - * @see #rotate(float, Vector3fc) - * - * @param angle - * the angle in radians - * @param axis - * the axis to rotate about (needs to be {@link Vector3f#normalize() normalized}) - * @return this - */ - public Matrix4f rotation(float angle, Vector3fc axis) { - return rotation(angle, axis.x(), axis.y(), axis.z()); - } - - /** - * Set this matrix to a rotation transformation using the given {@link AxisAngle4f}. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional rotation. - *

- * In order to apply the rotation transformation to an existing transformation, - * use {@link #rotate(AxisAngle4f) rotate()} instead. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(AxisAngle4f) - * - * @param axisAngle - * the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized}) - * @return this - */ - public Matrix4f rotation(AxisAngle4f axisAngle) { - return rotation(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z); - } - - /** - * Set this matrix to a rotation matrix which rotates the given radians about a given axis. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional rotation. - *

- * In order to apply the rotation transformation to an existing transformation, - * use {@link #rotate(float, float, float, float) rotate()} instead. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float) - * - * @param angle - * the angle in radians - * @param x - * the x-component of the rotation axis - * @param y - * the y-component of the rotation axis - * @param z - * the z-component of the rotation axis - * @return this - */ - public Matrix4f rotation(float angle, float x, float y, float z) { - if (y == 0.0f && z == 0.0f && Math.absEqualsOne(x)) - return rotationX(x * angle); - else if (x == 0.0f && z == 0.0f && Math.absEqualsOne(y)) - return rotationY(y * angle); - else if (x == 0.0f && y == 0.0f && Math.absEqualsOne(z)) - return rotationZ(z * angle); - return rotationInternal(angle, x, y, z); - } - private Matrix4f rotationInternal(float angle, float x, float y, float z) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float C = 1.0f - cos, xy = x * y, xz = x * z, yz = y * z; - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - return this - ._m00(cos + x * x * C) - ._m10(xy * C - z * sin) - ._m20(xz * C + y * sin) - ._m01(xy * C + z * sin) - ._m11(cos + y * y * C) - ._m21(yz * C - x * sin) - ._m02(xz * C - y * sin) - ._m12(yz * C + x * sin) - ._m22(cos + z * z * C) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Set this matrix to a rotation transformation about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix4f rotationX(float ang) { - float sin = Math.sin(ang), cos = Math.cosFromSin(sin, ang); - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m11(cos)._m12(sin)._m21(-sin)._m22(cos)._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - /** - * Set this matrix to a rotation transformation about the Y axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix4f rotationY(float ang) { - float sin = Math.sin(ang), cos = Math.cosFromSin(sin, ang); - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m00(cos)._m02(-sin)._m20(sin)._m22(cos)._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - /** - * Set this matrix to a rotation transformation about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix4f rotationZ(float ang) { - float sin = Math.sin(ang), cos = Math.cosFromSin(sin, ang); - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - return this._m00(cos)._m01(sin)._m10(-sin)._m11(cos)._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Set this matrix to a rotation transformation about the Z axis to align the local +X towards (dirX, dirY). - *

- * The vector (dirX, dirY) must be a unit vector. - * - * @param dirX - * the x component of the normalized direction - * @param dirY - * the y component of the normalized direction - * @return this - */ - public Matrix4f rotationTowardsXY(float dirX, float dirY) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - return this._m00(dirY)._m01(dirX)._m10(-dirX)._m11(dirY)._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Set this matrix to a rotation of angleX radians about the X axis, followed by a rotation - * of angleY radians about the Y axis and followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: rotationX(angleX).rotateY(angleY).rotateZ(angleZ) - * - * @param angleX - * the angle to rotate about X - * @param angleY - * the angle to rotate about Y - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix4f rotationXYZ(float angleX, float angleY, float angleZ) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - float nm01 = -sinX * -sinY, nm02 = cosX * -sinY; - return this - ._m20(sinY) - ._m21(-sinX * cosY) - ._m22(cosX * cosY) - ._m00(cosY * cosZ) - ._m01(nm01 * cosZ + cosX * sinZ) - ._m02(nm02 * cosZ + sinX * sinZ) - ._m10(cosY * -sinZ) - ._m11(nm01 * -sinZ + cosX * cosZ) - ._m12(nm02 * -sinZ + sinX * cosZ) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Set this matrix to a rotation of angleZ radians about the Z axis, followed by a rotation - * of angleY radians about the Y axis and followed by a rotation of angleX radians about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: rotationZ(angleZ).rotateY(angleY).rotateX(angleX) - * - * @param angleZ - * the angle to rotate about Z - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @return this - */ - public Matrix4f rotationZYX(float angleZ, float angleY, float angleX) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float nm20 = cosZ * sinY; - float nm21 = sinZ * sinY; - return this - ._m00(cosZ * cosY) - ._m01(sinZ * cosY) - ._m02(-sinY) - ._m03(0.0f) - ._m10(-sinZ * cosX + nm20 * sinX) - ._m11(cosZ * cosX + nm21 * sinX) - ._m12(cosY * sinX) - ._m13(0.0f) - ._m20(-sinZ * -sinX + nm20 * cosX) - ._m21(cosZ * -sinX + nm21 * cosX) - ._m22(cosY * cosX) - ._m23(0.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(0.0f) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Set this matrix to a rotation of angleY radians about the Y axis, followed by a rotation - * of angleX radians about the X axis and followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: rotationY(angleY).rotateX(angleX).rotateZ(angleZ) - * - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix4f rotationYXZ(float angleY, float angleX, float angleZ) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float nm10 = sinY * sinX, nm12 = cosY * sinX; - return this - ._m20(sinY * cosX) - ._m21(-sinX) - ._m22(cosY * cosX) - ._m23(0.0f) - ._m00(cosY * cosZ + nm10 * sinZ) - ._m01(cosX * sinZ) - ._m02(-sinY * cosZ + nm12 * sinZ) - ._m03(0.0f) - ._m10(cosY * -sinZ + nm10 * cosZ) - ._m11(cosX * cosZ) - ._m12(-sinY * -sinZ + nm12 * cosZ) - ._m13(0.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(0.0f) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Set only the upper left 3x3 submatrix of this matrix to a rotation of angleX radians about the X axis, followed by a rotation - * of angleY radians about the Y axis and followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - * - * @param angleX - * the angle to rotate about X - * @param angleY - * the angle to rotate about Y - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix4f setRotationXYZ(float angleX, float angleY, float angleZ) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float nm01 = -sinX * -sinY; - float nm02 = cosX * -sinY; - return this - ._m20(sinY) - ._m21(-sinX * cosY) - ._m22(cosX * cosY) - ._m00(cosY * cosZ) - ._m01(nm01 * cosZ + cosX * sinZ) - ._m02(nm02 * cosZ + sinX * sinZ) - ._m10(cosY * -sinZ) - ._m11(nm01 * -sinZ + cosX * cosZ) - ._m12(nm02 * -sinZ + sinX * cosZ) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Set only the upper left 3x3 submatrix of this matrix to a rotation of angleZ radians about the Z axis, followed by a rotation - * of angleY radians about the Y axis and followed by a rotation of angleX radians about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - * - * @param angleZ - * the angle to rotate about Z - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @return this - */ - public Matrix4f setRotationZYX(float angleZ, float angleY, float angleX) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float nm20 = cosZ * sinY, nm21 = sinZ * sinY; - return this - ._m00(cosZ * cosY) - ._m01(sinZ * cosY) - ._m02(-sinY) - ._m10(-sinZ * cosX + nm20 * sinX) - ._m11(cosZ * cosX + nm21 * sinX) - ._m12(cosY * sinX) - ._m20(-sinZ * -sinX + nm20 * cosX) - ._m21(cosZ * -sinX + nm21 * cosX) - ._m22(cosY * cosX) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Set only the upper left 3x3 submatrix of this matrix to a rotation of angleY radians about the Y axis, followed by a rotation - * of angleX radians about the X axis and followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - * - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix4f setRotationYXZ(float angleY, float angleX, float angleZ) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float nm10 = sinY * sinX, nm12 = cosY * sinX; - return this - ._m20(sinY * cosX) - ._m21(-sinX) - ._m22(cosY * cosX) - ._m00(cosY * cosZ + nm10 * sinZ) - ._m01(cosX * sinZ) - ._m02(-sinY * cosZ + nm12 * sinZ) - ._m10(cosY * -sinZ + nm10 * cosZ) - ._m11(cosX * cosZ) - ._m12(-sinY * -sinZ + nm12 * cosZ) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Set this matrix to the rotation transformation of the given {@link Quaternionfc}. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * The resulting matrix can be multiplied against another transformation - * matrix to obtain an additional rotation. - *

- * In order to apply the rotation transformation to an existing transformation, - * use {@link #rotate(Quaternionfc) rotate()} instead. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @return this - */ - public Matrix4f rotation(Quaternionfc quat) { - float w2 = quat.w() * quat.w(); - float x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(); - float z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw; - float xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz; - float yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz; - float xw = quat.x() * quat.w(), dxw = xw + xw; - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - return this - ._m00(w2 + x2 - z2 - y2) - ._m01(dxy + dzw) - ._m02(dxz - dyw) - ._m10(-dzw + dxy) - ._m11(y2 - z2 + w2 - x2) - ._m12(dyz + dxw) - ._m20(dyw + dxz) - ._m21(dyz - dxw) - ._m22(z2 - y2 - x2 + w2) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Set this matrix to T * R * S, where T is a translation by the given (tx, ty, tz), - * R is a rotation transformation specified by the quaternion (qx, qy, qz, qw), and S is a scaling transformation - * which scales the three axes x, y and z by (sx, sy, sz). - *

- * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and - * at last the translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: translation(tx, ty, tz).rotate(quat).scale(sx, sy, sz) - * - * @see #translation(float, float, float) - * @see #rotate(Quaternionfc) - * @see #scale(float, float, float) - * - * @param tx - * the number of units by which to translate the x-component - * @param ty - * the number of units by which to translate the y-component - * @param tz - * the number of units by which to translate the z-component - * @param qx - * the x-coordinate of the vector part of the quaternion - * @param qy - * the y-coordinate of the vector part of the quaternion - * @param qz - * the z-coordinate of the vector part of the quaternion - * @param qw - * the scalar part of the quaternion - * @param sx - * the scaling factor for the x-axis - * @param sy - * the scaling factor for the y-axis - * @param sz - * the scaling factor for the z-axis - * @return this - */ - public Matrix4f translationRotateScale(float tx, float ty, float tz, - float qx, float qy, float qz, float qw, - float sx, float sy, float sz) { - float dqx = qx + qx; - float dqy = qy + qy; - float dqz = qz + qz; - float q00 = dqx * qx; - float q11 = dqy * qy; - float q22 = dqz * qz; - float q01 = dqx * qy; - float q02 = dqx * qz; - float q03 = dqx * qw; - float q12 = dqy * qz; - float q13 = dqy * qw; - float q23 = dqz * qw; - boolean one = Math.absEqualsOne(sx) && Math.absEqualsOne(sy) && Math.absEqualsOne(sz); - return this - ._m00(sx - (q11 + q22) * sx) - ._m01((q01 + q23) * sx) - ._m02((q02 - q13) * sx) - ._m03(0.0f) - ._m10((q01 - q23) * sy) - ._m11(sy - (q22 + q00) * sy) - ._m12((q12 + q03) * sy) - ._m13(0.0f) - ._m20((q02 + q13) * sz) - ._m21((q12 - q03) * sz) - ._m22(sz - (q11 + q00) * sz) - ._m23(0.0f) - ._m30(tx) - ._m31(ty) - ._m32(tz) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | (one ? PROPERTY_ORTHONORMAL : 0)); - } - - /** - * Set this matrix to T * R * S, where T is the given translation, - * R is a rotation transformation specified by the given quaternion, and S is a scaling transformation - * which scales the axes by scale. - *

- * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and - * at last the translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: translation(translation).rotate(quat).scale(scale) - * - * @see #translation(Vector3fc) - * @see #rotate(Quaternionfc) - * @see #scale(Vector3fc) - * - * @param translation - * the translation - * @param quat - * the quaternion representing a rotation - * @param scale - * the scaling factors - * @return this - */ - public Matrix4f translationRotateScale(Vector3fc translation, - Quaternionfc quat, - Vector3fc scale) { - return translationRotateScale(translation.x(), translation.y(), translation.z(), quat.x(), quat.y(), quat.z(), quat.w(), scale.x(), scale.y(), scale.z()); - } - - /** - * Set this matrix to T * R * S, where T is a translation by the given (tx, ty, tz), - * R is a rotation transformation specified by the quaternion (qx, qy, qz, qw), and S is a scaling transformation - * which scales all three axes by scale. - *

- * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and - * at last the translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: translation(tx, ty, tz).rotate(quat).scale(scale) - * - * @see #translation(float, float, float) - * @see #rotate(Quaternionfc) - * @see #scale(float) - * - * @param tx - * the number of units by which to translate the x-component - * @param ty - * the number of units by which to translate the y-component - * @param tz - * the number of units by which to translate the z-component - * @param qx - * the x-coordinate of the vector part of the quaternion - * @param qy - * the y-coordinate of the vector part of the quaternion - * @param qz - * the z-coordinate of the vector part of the quaternion - * @param qw - * the scalar part of the quaternion - * @param scale - * the scaling factor for all three axes - * @return this - */ - public Matrix4f translationRotateScale(float tx, float ty, float tz, - float qx, float qy, float qz, float qw, - float scale) { - return translationRotateScale(tx, ty, tz, qx, qy, qz, qw, scale, scale, scale); - } - - /** - * Set this matrix to T * R * S, where T is the given translation, - * R is a rotation transformation specified by the given quaternion, and S is a scaling transformation - * which scales all three axes by scale. - *

- * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and - * at last the translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: translation(translation).rotate(quat).scale(scale) - * - * @see #translation(Vector3fc) - * @see #rotate(Quaternionfc) - * @see #scale(float) - * - * @param translation - * the translation - * @param quat - * the quaternion representing a rotation - * @param scale - * the scaling factors - * @return this - */ - public Matrix4f translationRotateScale(Vector3fc translation, - Quaternionfc quat, - float scale) { - return translationRotateScale(translation.x(), translation.y(), translation.z(), quat.x(), quat.y(), quat.z(), quat.w(), scale, scale, scale); - } - - /** - * Set this matrix to (T * R * S)-1, where T is a translation by the given (tx, ty, tz), - * R is a rotation transformation specified by the quaternion (qx, qy, qz, qw), and S is a scaling transformation - * which scales the three axes x, y and z by (sx, sy, sz). - *

- * This method is equivalent to calling: translationRotateScale(...).invert() - * - * @see #translationRotateScale(float, float, float, float, float, float, float, float, float, float) - * @see #invert() - * - * @param tx - * the number of units by which to translate the x-component - * @param ty - * the number of units by which to translate the y-component - * @param tz - * the number of units by which to translate the z-component - * @param qx - * the x-coordinate of the vector part of the quaternion - * @param qy - * the y-coordinate of the vector part of the quaternion - * @param qz - * the z-coordinate of the vector part of the quaternion - * @param qw - * the scalar part of the quaternion - * @param sx - * the scaling factor for the x-axis - * @param sy - * the scaling factor for the y-axis - * @param sz - * the scaling factor for the z-axis - * @return this - */ - public Matrix4f translationRotateScaleInvert(float tx, float ty, float tz, - float qx, float qy, float qz, float qw, - float sx, float sy, float sz) { - boolean one = Math.absEqualsOne(sx) && Math.absEqualsOne(sy) && Math.absEqualsOne(sz); - if (one) - return translationRotateInvert(tx, ty, tz, qx, qy, qz, qw); - float nqx = -qx, nqy = -qy, nqz = -qz; - float dqx = nqx + nqx; - float dqy = nqy + nqy; - float dqz = nqz + nqz; - float q00 = dqx * nqx; - float q11 = dqy * nqy; - float q22 = dqz * nqz; - float q01 = dqx * nqy; - float q02 = dqx * nqz; - float q03 = dqx * qw; - float q12 = dqy * nqz; - float q13 = dqy * qw; - float q23 = dqz * qw; - float isx = 1/sx, isy = 1/sy, isz = 1/sz; - return this - ._m00(isx * (1.0f - q11 - q22)) - ._m01(isy * (q01 + q23)) - ._m02(isz * (q02 - q13)) - ._m03(0.0f) - ._m10(isx * (q01 - q23)) - ._m11(isy * (1.0f - q22 - q00)) - ._m12(isz * (q12 + q03)) - ._m13(0.0f) - ._m20(isx * (q02 + q13)) - ._m21(isy * (q12 - q03)) - ._m22(isz * (1.0f - q11 - q00)) - ._m23(0.0f) - ._m30(-m00() * tx - m10() * ty - m20() * tz) - ._m31(-m01() * tx - m11() * ty - m21() * tz) - ._m32(-m02() * tx - m12() * ty - m22() * tz) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE); - } - - /** - * Set this matrix to (T * R * S)-1, where T is the given translation, - * R is a rotation transformation specified by the given quaternion, and S is a scaling transformation - * which scales the axes by scale. - *

- * This method is equivalent to calling: translationRotateScale(...).invert() - * - * @see #translationRotateScale(Vector3fc, Quaternionfc, Vector3fc) - * @see #invert() - * - * @param translation - * the translation - * @param quat - * the quaternion representing a rotation - * @param scale - * the scaling factors - * @return this - */ - public Matrix4f translationRotateScaleInvert(Vector3fc translation, - Quaternionfc quat, - Vector3fc scale) { - return translationRotateScaleInvert(translation.x(), translation.y(), translation.z(), quat.x(), quat.y(), quat.z(), quat.w(), scale.x(), scale.y(), scale.z()); - } - - /** - * Set this matrix to (T * R * S)-1, where T is the given translation, - * R is a rotation transformation specified by the given quaternion, and S is a scaling transformation - * which scales all three axes by scale. - *

- * This method is equivalent to calling: translationRotateScale(...).invert() - * - * @see #translationRotateScale(Vector3fc, Quaternionfc, float) - * @see #invert() - * - * @param translation - * the translation - * @param quat - * the quaternion representing a rotation - * @param scale - * the scaling factors - * @return this - */ - public Matrix4f translationRotateScaleInvert(Vector3fc translation, - Quaternionfc quat, - float scale) { - return translationRotateScaleInvert(translation.x(), translation.y(), translation.z(), quat.x(), quat.y(), quat.z(), quat.w(), scale, scale, scale); - } - - /** - * Set this matrix to T * R * S * M, where T is a translation by the given (tx, ty, tz), - * R is a rotation - and possibly scaling - transformation specified by the quaternion (qx, qy, qz, qw), S is a scaling transformation - * which scales the three axes x, y and z by (sx, sy, sz) and M is an {@link #isAffine() affine} matrix. - *

- * When transforming a vector by the resulting matrix the transformation described by M will be applied first, then the scaling, then rotation and - * at last the translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: translation(tx, ty, tz).rotate(quat).scale(sx, sy, sz).mulAffine(m) - * - * @see #translation(float, float, float) - * @see #rotate(Quaternionfc) - * @see #scale(float, float, float) - * @see #mulAffine(Matrix4fc) - * - * @param tx - * the number of units by which to translate the x-component - * @param ty - * the number of units by which to translate the y-component - * @param tz - * the number of units by which to translate the z-component - * @param qx - * the x-coordinate of the vector part of the quaternion - * @param qy - * the y-coordinate of the vector part of the quaternion - * @param qz - * the z-coordinate of the vector part of the quaternion - * @param qw - * the scalar part of the quaternion - * @param sx - * the scaling factor for the x-axis - * @param sy - * the scaling factor for the y-axis - * @param sz - * the scaling factor for the z-axis - * @param m - * the {@link #isAffine() affine} matrix to multiply by - * @return this - */ - public Matrix4f translationRotateScaleMulAffine(float tx, float ty, float tz, - float qx, float qy, float qz, float qw, - float sx, float sy, float sz, - Matrix4f m) { - float w2 = qw * qw; - float x2 = qx * qx; - float y2 = qy * qy; - float z2 = qz * qz; - float zw = qz * qw; - float xy = qx * qy; - float xz = qx * qz; - float yw = qy * qw; - float yz = qy * qz; - float xw = qx * qw; - float nm00 = w2 + x2 - z2 - y2; - float nm01 = xy + zw + zw + xy; - float nm02 = xz - yw + xz - yw; - float nm10 = -zw + xy - zw + xy; - float nm11 = y2 - z2 + w2 - x2; - float nm12 = yz + yz + xw + xw; - float nm20 = yw + xz + xz + yw; - float nm21 = yz + yz - xw - xw; - float nm22 = z2 - y2 - x2 + w2; - float m00 = nm00 * m.m00() + nm10 * m.m01() + nm20 * m.m02(); - float m01 = nm01 * m.m00() + nm11 * m.m01() + nm21 * m.m02(); - this._m02(nm02 * m.m00() + nm12 * m.m01() + nm22 * m.m02()) - ._m00(m00) - ._m01(m01) - ._m03(0.0f); - float m10 = nm00 * m.m10() + nm10 * m.m11() + nm20 * m.m12(); - float m11 = nm01 * m.m10() + nm11 * m.m11() + nm21 * m.m12(); - this._m12(nm02 * m.m10() + nm12 * m.m11() + nm22 * m.m12()) - ._m10(m10) - ._m11(m11) - ._m13(0.0f); - float m20 = nm00 * m.m20() + nm10 * m.m21() + nm20 * m.m22(); - float m21 = nm01 * m.m20() + nm11 * m.m21() + nm21 * m.m22(); - this._m22(nm02 * m.m20() + nm12 * m.m21() + nm22 * m.m22()) - ._m20(m20) - ._m21(m21) - ._m23(0.0f); - float m30 = nm00 * m.m30() + nm10 * m.m31() + nm20 * m.m32() + tx; - float m31 = nm01 * m.m30() + nm11 * m.m31() + nm21 * m.m32() + ty; - this._m32(nm02 * m.m30() + nm12 * m.m31() + nm22 * m.m32() + tz) - ._m30(m30) - ._m31(m31) - ._m33(1.0f); - boolean one = Math.absEqualsOne(sx) && Math.absEqualsOne(sy) && Math.absEqualsOne(sz); - return _properties(PROPERTY_AFFINE | (one && (m.properties & PROPERTY_ORTHONORMAL) != 0 ? PROPERTY_ORTHONORMAL : 0)); - } - - /** - * Set this matrix to T * R * S * M, where T is the given translation, - * R is a rotation - and possibly scaling - transformation specified by the given quaternion, S is a scaling transformation - * which scales the axes by scale and M is an {@link #isAffine() affine} matrix. - *

- * When transforming a vector by the resulting matrix the transformation described by M will be applied first, then the scaling, then rotation and - * at last the translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: translation(translation).rotate(quat).scale(scale).mulAffine(m) - * - * @see #translation(Vector3fc) - * @see #rotate(Quaternionfc) - * @see #mulAffine(Matrix4fc) - * - * @param translation - * the translation - * @param quat - * the quaternion representing a rotation - * @param scale - * the scaling factors - * @param m - * the {@link #isAffine() affine} matrix to multiply by - * @return this - */ - public Matrix4f translationRotateScaleMulAffine(Vector3fc translation, - Quaternionfc quat, - Vector3fc scale, - Matrix4f m) { - return translationRotateScaleMulAffine(translation.x(), translation.y(), translation.z(), quat.x(), quat.y(), quat.z(), quat.w(), scale.x(), scale.y(), scale.z(), m); - } - - /** - * Set this matrix to T * R, where T is a translation by the given (tx, ty, tz) and - * R is a rotation - and possibly scaling - transformation specified by the quaternion (qx, qy, qz, qw). - *

- * When transforming a vector by the resulting matrix the rotation - and possibly scaling - transformation will be applied first and then the translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: translation(tx, ty, tz).rotate(quat) - * - * @see #translation(float, float, float) - * @see #rotate(Quaternionfc) - * - * @param tx - * the number of units by which to translate the x-component - * @param ty - * the number of units by which to translate the y-component - * @param tz - * the number of units by which to translate the z-component - * @param qx - * the x-coordinate of the vector part of the quaternion - * @param qy - * the y-coordinate of the vector part of the quaternion - * @param qz - * the z-coordinate of the vector part of the quaternion - * @param qw - * the scalar part of the quaternion - * @return this - */ - public Matrix4f translationRotate(float tx, float ty, float tz, float qx, float qy, float qz, float qw) { - float w2 = qw * qw; - float x2 = qx * qx; - float y2 = qy * qy; - float z2 = qz * qz; - float zw = qz * qw; - float xy = qx * qy; - float xz = qx * qz; - float yw = qy * qw; - float yz = qy * qz; - float xw = qx * qw; - return this - ._m00(w2 + x2 - z2 - y2) - ._m01(xy + zw + zw + xy) - ._m02(xz - yw + xz - yw) - ._m10(-zw + xy - zw + xy) - ._m11(y2 - z2 + w2 - x2) - ._m12(yz + yz + xw + xw) - ._m20(yw + xz + xz + yw) - ._m21(yz + yz - xw - xw) - ._m22(z2 - y2 - x2 + w2) - ._m30(tx) - ._m31(ty) - ._m32(tz) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Set this matrix to T * R, where T is a translation by the given (tx, ty, tz) and - * R is a rotation - and possibly scaling - transformation specified by the given quaternion. - *

- * When transforming a vector by the resulting matrix the rotation - and possibly scaling - transformation will be applied first and then the translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: translation(tx, ty, tz).rotate(quat) - * - * @see #translation(float, float, float) - * @see #rotate(Quaternionfc) - * - * @param tx - * the number of units by which to translate the x-component - * @param ty - * the number of units by which to translate the y-component - * @param tz - * the number of units by which to translate the z-component - * @param quat - * the quaternion representing a rotation - * @return this - */ - public Matrix4f translationRotate(float tx, float ty, float tz, Quaternionfc quat) { - return translationRotate(tx, ty, tz, quat.x(), quat.y(), quat.z(), quat.w()); - } - - /** - * Set this matrix to T * R, where T is the given translation and - * R is a rotation transformation specified by the given quaternion. - *

- * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and - * at last the translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: translation(translation).rotate(quat) - * - * @see #translation(Vector3fc) - * @see #rotate(Quaternionfc) - * - * @param translation - * the translation - * @param quat - * the quaternion representing a rotation - * @return this - */ - public Matrix4f translationRotate(Vector3fc translation, - Quaternionfc quat) { - return translationRotate(translation.x(), translation.y(), translation.z(), quat.x(), quat.y(), quat.z(), quat.w()); - } - - /** - * Set this matrix to (T * R)-1, where T is a translation by the given (tx, ty, tz) and - * R is a rotation transformation specified by the quaternion (qx, qy, qz, qw). - *

- * This method is equivalent to calling: translationRotate(...).invert() - * - * @see #translationRotate(float, float, float, float, float, float, float) - * @see #invert() - * - * @param tx - * the number of units by which to translate the x-component - * @param ty - * the number of units by which to translate the y-component - * @param tz - * the number of units by which to translate the z-component - * @param qx - * the x-coordinate of the vector part of the quaternion - * @param qy - * the y-coordinate of the vector part of the quaternion - * @param qz - * the z-coordinate of the vector part of the quaternion - * @param qw - * the scalar part of the quaternion - * @return this - */ - public Matrix4f translationRotateInvert(float tx, float ty, float tz, float qx, float qy, float qz, float qw) { - float nqx = -qx, nqy = -qy, nqz = -qz; - float dqx = nqx + nqx; - float dqy = nqy + nqy; - float dqz = nqz + nqz; - float q00 = dqx * nqx; - float q11 = dqy * nqy; - float q22 = dqz * nqz; - float q01 = dqx * nqy; - float q02 = dqx * nqz; - float q03 = dqx * qw; - float q12 = dqy * nqz; - float q13 = dqy * qw; - float q23 = dqz * qw; - return this - ._m00(1.0f - q11 - q22) - ._m01(q01 + q23) - ._m02(q02 - q13) - ._m03(0.0f) - ._m10(q01 - q23) - ._m11(1.0f - q22 - q00) - ._m12(q12 + q03) - ._m13(0.0f) - ._m20(q02 + q13) - ._m21(q12 - q03) - ._m22(1.0f - q11 - q00) - ._m23(0.0f) - ._m30(-m00() * tx - m10() * ty - m20() * tz) - ._m31(-m01() * tx - m11() * ty - m21() * tz) - ._m32(-m02() * tx - m12() * ty - m22() * tz) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Set this matrix to (T * R)-1, where T is the given translation and - * R is a rotation transformation specified by the given quaternion. - *

- * This method is equivalent to calling: translationRotate(...).invert() - * - * @see #translationRotate(Vector3fc, Quaternionfc) - * @see #invert() - * - * @param translation - * the translation - * @param quat - * the quaternion representing a rotation - * @return this - */ - public Matrix4f translationRotateInvert(Vector3fc translation, - Quaternionfc quat) { - return translationRotateInvert(translation.x(), translation.y(), translation.z(), quat.x(), quat.y(), quat.z(), quat.w()); - } - - /** - * Set the upper left 3x3 submatrix of this {@link Matrix4f} to the given {@link Matrix3fc} and don't change the other elements. - * - * @param mat - * the 3x3 matrix - * @return this - */ - public Matrix4f set3x3(Matrix3fc mat) { - return - set3x3Matrix3fc(mat). - _properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - } - private Matrix4f set3x3Matrix3fc(Matrix3fc mat) { - return this - ._m00(mat.m00()) - ._m01(mat.m01()) - ._m02(mat.m02()) - ._m10(mat.m10()) - ._m11(mat.m11()) - ._m12(mat.m12()) - ._m20(mat.m20()) - ._m21(mat.m21()) - ._m22(mat.m22()); - } - - public Vector4f transform(Vector4f v) { - return v.mul(this); - } - - public Vector4f transform(Vector4fc v, Vector4f dest) { - return v.mul(this, dest); - } - - public Vector4f transform(float x, float y, float z, float w, Vector4f dest) { - return dest.set(x, y, z, w).mul(this); - } - - public Vector4f transformTranspose(Vector4f v) { - return v.mulTranspose(this); - } - public Vector4f transformTranspose(Vector4fc v, Vector4f dest) { - return v.mulTranspose(this, dest); - } - public Vector4f transformTranspose(float x, float y, float z, float w, Vector4f dest) { - return dest.set(x, y, z, w).mulTranspose(this); - } - - public Vector4f transformProject(Vector4f v) { - return v.mulProject(this); - } - - public Vector4f transformProject(Vector4fc v, Vector4f dest) { - return v.mulProject(this, dest); - } - - public Vector4f transformProject(float x, float y, float z, float w, Vector4f dest) { - return dest.set(x, y, z, w).mulProject(this); - } - - public Vector3f transformProject(Vector4fc v, Vector3f dest) { - return v.mulProject(this, dest); - } - - public Vector3f transformProject(float x, float y, float z, float w, Vector3f dest) { - return dest.set(x, y, z).mulProject(this, w, dest); - } - - public Vector3f transformProject(Vector3f v) { - return v.mulProject(this); - } - - public Vector3f transformProject(Vector3fc v, Vector3f dest) { - return v.mulProject(this, dest); - } - - public Vector3f transformProject(float x, float y, float z, Vector3f dest) { - return dest.set(x, y, z).mulProject(this); - } - - public Vector3f transformPosition(Vector3f v) { - return v.mulPosition(this); - } - - public Vector3f transformPosition(Vector3fc v, Vector3f dest) { - return transformPosition(v.x(), v.y(), v.z(), dest); - } - - public Vector3f transformPosition(float x, float y, float z, Vector3f dest) { - return dest.set(x, y, z).mulPosition(this); - } - - public Vector3f transformDirection(Vector3f v) { - return transformDirection(v.x, v.y, v.z, v); - } - - public Vector3f transformDirection(Vector3fc v, Vector3f dest) { - return transformDirection(v.x(), v.y(), v.z(), dest); - } - - public Vector3f transformDirection(float x, float y, float z, Vector3f dest) { - return dest.set(x, y, z).mulDirection(this); - } - - public Vector4f transformAffine(Vector4f v) { - return v.mulAffine(this, v); - } - - public Vector4f transformAffine(Vector4fc v, Vector4f dest) { - return transformAffine(v.x(), v.y(), v.z(), v.w(), dest); - } - - public Vector4f transformAffine(float x, float y, float z, float w, Vector4f dest) { - return dest.set(x, y, z, w).mulAffine(this, dest); - } - - public Matrix4f scale(Vector3fc xyz, Matrix4f dest) { - return scale(xyz.x(), xyz.y(), xyz.z(), dest); - } - - /** - * Apply scaling to this matrix by scaling the base axes by the given xyz.x, - * xyz.y and xyz.z factors, respectively. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * scaling will be applied first! - * - * @param xyz - * the factors of the x, y and z component, respectively - * @return this - */ - public Matrix4f scale(Vector3fc xyz) { - return scale(xyz.x(), xyz.y(), xyz.z(), this); - } - - public Matrix4f scale(float xyz, Matrix4f dest) { - return scale(xyz, xyz, xyz, dest); - } - - /** - * Apply scaling to this matrix by uniformly scaling all base axes by the given xyz factor. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * scaling will be applied first! - *

- * Individual scaling of all three axes can be applied using {@link #scale(float, float, float)}. - * - * @see #scale(float, float, float) - * - * @param xyz - * the factor for all components - * @return this - */ - public Matrix4f scale(float xyz) { - return scale(xyz, xyz, xyz); - } - - public Matrix4f scaleXY(float x, float y, Matrix4f dest) { - return scale(x, y, 1.0f, dest); - } - - /** - * Apply scaling to this matrix by scaling the X axis by x and the Y axis by y. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * scaling will be applied first! - * - * @param x - * the factor of the x component - * @param y - * the factor of the y component - * @return this - */ - public Matrix4f scaleXY(float x, float y) { - return scale(x, y, 1.0f); - } - - public Matrix4f scale(float x, float y, float z, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.scaling(x, y, z); - return scaleGeneric(x, y, z, dest); - } - private Matrix4f scaleGeneric(float x, float y, float z, Matrix4f dest) { - boolean one = Math.absEqualsOne(x) && Math.absEqualsOne(y) && Math.absEqualsOne(z); - return dest - ._m00(m00() * x) - ._m01(m01() * x) - ._m02(m02() * x) - ._m03(m03() * x) - ._m10(m10() * y) - ._m11(m11() * y) - ._m12(m12() * y) - ._m13(m13() * y) - ._m20(m20() * z) - ._m21(m21() * z) - ._m22(m22() * z) - ._m23(m23() * z) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION - | (one ? 0 : PROPERTY_ORTHONORMAL))); - } - - /** - * Apply scaling to this matrix by scaling the base axes by the given sx, - * sy and sz factors. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * scaling will be applied first! - * - * @param x - * the factor of the x component - * @param y - * the factor of the y component - * @param z - * the factor of the z component - * @return this - */ - public Matrix4f scale(float x, float y, float z) { - return scale(x, y, z, this); - } - - public Matrix4f scaleAround(float sx, float sy, float sz, float ox, float oy, float oz, Matrix4f dest) { - float nm30 = m00() * ox + m10() * oy + m20() * oz + m30(); - float nm31 = m01() * ox + m11() * oy + m21() * oz + m31(); - float nm32 = m02() * ox + m12() * oy + m22() * oz + m32(); - float nm33 = m03() * ox + m13() * oy + m23() * oz + m33(); - boolean one = Math.absEqualsOne(sx) && Math.absEqualsOne(sy) && Math.absEqualsOne(sz); - return dest - ._m00(m00() * sx) - ._m01(m01() * sx) - ._m02(m02() * sx) - ._m03(m03() * sx) - ._m10(m10() * sy) - ._m11(m11() * sy) - ._m12(m12() * sy) - ._m13(m13() * sy) - ._m20(m20() * sz) - ._m21(m21() * sz) - ._m22(m22() * sz) - ._m23(m23() * sz) - ._m30(-dest.m00() * ox - dest.m10() * oy - dest.m20() * oz + nm30) - ._m31(-dest.m01() * ox - dest.m11() * oy - dest.m21() * oz + nm31) - ._m32(-dest.m02() * ox - dest.m12() * oy - dest.m22() * oz + nm32) - ._m33(-dest.m03() * ox - dest.m13() * oy - dest.m23() * oz + nm33) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION - | (one ? 0 : PROPERTY_ORTHONORMAL))); - } - - /** - * Apply scaling to this matrix by scaling the base axes by the given sx, - * sy and sz factors while using (ox, oy, oz) as the scaling origin. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * scaling will be applied first! - *

- * This method is equivalent to calling: translate(ox, oy, oz).scale(sx, sy, sz).translate(-ox, -oy, -oz) - * - * @param sx - * the scaling factor of the x component - * @param sy - * the scaling factor of the y component - * @param sz - * the scaling factor of the z component - * @param ox - * the x coordinate of the scaling origin - * @param oy - * the y coordinate of the scaling origin - * @param oz - * the z coordinate of the scaling origin - * @return this - */ - public Matrix4f scaleAround(float sx, float sy, float sz, float ox, float oy, float oz) { - return scaleAround(sx, sy, sz, ox, oy, oz, this); - } - - /** - * Apply scaling to this matrix by scaling all three base axes by the given factor - * while using (ox, oy, oz) as the scaling origin. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * scaling will be applied first! - *

- * This method is equivalent to calling: translate(ox, oy, oz).scale(factor).translate(-ox, -oy, -oz) - * - * @param factor - * the scaling factor for all three axes - * @param ox - * the x coordinate of the scaling origin - * @param oy - * the y coordinate of the scaling origin - * @param oz - * the z coordinate of the scaling origin - * @return this - */ - public Matrix4f scaleAround(float factor, float ox, float oy, float oz) { - return scaleAround(factor, factor, factor, ox, oy, oz, this); - } - - public Matrix4f scaleAround(float factor, float ox, float oy, float oz, Matrix4f dest) { - return scaleAround(factor, factor, factor, ox, oy, oz, dest); - } - - public Matrix4f scaleLocal(float x, float y, float z, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.scaling(x, y, z); - return scaleLocalGeneric(x, y, z, dest); - } - private Matrix4f scaleLocalGeneric(float x, float y, float z, Matrix4f dest) { - float nm00 = x * m00(); - float nm01 = y * m01(); - float nm02 = z * m02(); - float nm10 = x * m10(); - float nm11 = y * m11(); - float nm12 = z * m12(); - float nm20 = x * m20(); - float nm21 = y * m21(); - float nm22 = z * m22(); - float nm30 = x * m30(); - float nm31 = y * m31(); - float nm32 = z * m32(); - boolean one = Math.absEqualsOne(x) && Math.absEqualsOne(y) && Math.absEqualsOne(z); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(m03()) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(m13()) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(m23()) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION - | (one ? 0 : PROPERTY_ORTHONORMAL))); - } - - public Matrix4f scaleLocal(float xyz, Matrix4f dest) { - return scaleLocal(xyz, xyz, xyz, dest); - } - - /** - * Pre-multiply scaling to this matrix by scaling the base axes by the given xyz factor. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be S * M. So when transforming a - * vector v with the new matrix by using S * M * v, the - * scaling will be applied last! - * - * @param xyz - * the factor of the x, y and z component - * @return this - */ - public Matrix4f scaleLocal(float xyz) { - return scaleLocal(xyz, this); - } - - /** - * Pre-multiply scaling to this matrix by scaling the base axes by the given x, - * y and z factors. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be S * M. So when transforming a - * vector v with the new matrix by using S * M * v, the - * scaling will be applied last! - * - * @param x - * the factor of the x component - * @param y - * the factor of the y component - * @param z - * the factor of the z component - * @return this - */ - public Matrix4f scaleLocal(float x, float y, float z) { - return scaleLocal(x, y, z, this); - } - - public Matrix4f scaleAroundLocal(float sx, float sy, float sz, float ox, float oy, float oz, Matrix4f dest) { - boolean one = Math.absEqualsOne(sx) && Math.absEqualsOne(sy) && Math.absEqualsOne(sz); - return dest - ._m00(sx * (m00() - ox * m03()) + ox * m03()) - ._m01(sy * (m01() - oy * m03()) + oy * m03()) - ._m02(sz * (m02() - oz * m03()) + oz * m03()) - ._m03(m03()) - ._m10(sx * (m10() - ox * m13()) + ox * m13()) - ._m11(sy * (m11() - oy * m13()) + oy * m13()) - ._m12(sz * (m12() - oz * m13()) + oz * m13()) - ._m13(m13()) - ._m20(sx * (m20() - ox * m23()) + ox * m23()) - ._m21(sy * (m21() - oy * m23()) + oy * m23()) - ._m22(sz * (m22() - oz * m23()) + oz * m23()) - ._m23(m23()) - ._m30(sx * (m30() - ox * m33()) + ox * m33()) - ._m31(sy * (m31() - oy * m33()) + oy * m33()) - ._m32(sz * (m32() - oz * m33()) + oz * m33()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION - | (one ? 0 : PROPERTY_ORTHONORMAL))); - } - - /** - * Pre-multiply scaling to this matrix by scaling the base axes by the given sx, - * sy and sz factors while using (ox, oy, oz) as the scaling origin. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be S * M. So when transforming a - * vector v with the new matrix by using S * M * v, the - * scaling will be applied last! - *

- * This method is equivalent to calling: new Matrix4f().translate(ox, oy, oz).scale(sx, sy, sz).translate(-ox, -oy, -oz).mul(this, this) - * - * @param sx - * the scaling factor of the x component - * @param sy - * the scaling factor of the y component - * @param sz - * the scaling factor of the z component - * @param ox - * the x coordinate of the scaling origin - * @param oy - * the y coordinate of the scaling origin - * @param oz - * the z coordinate of the scaling origin - * @return this - */ - public Matrix4f scaleAroundLocal(float sx, float sy, float sz, float ox, float oy, float oz) { - return scaleAroundLocal(sx, sy, sz, ox, oy, oz, this); - } - - /** - * Pre-multiply scaling to this matrix by scaling all three base axes by the given factor - * while using (ox, oy, oz) as the scaling origin. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be S * M. So when transforming a - * vector v with the new matrix by using S * M * v, the - * scaling will be applied last! - *

- * This method is equivalent to calling: new Matrix4f().translate(ox, oy, oz).scale(factor).translate(-ox, -oy, -oz).mul(this, this) - * - * @param factor - * the scaling factor for all three axes - * @param ox - * the x coordinate of the scaling origin - * @param oy - * the y coordinate of the scaling origin - * @param oz - * the z coordinate of the scaling origin - * @return this - */ - public Matrix4f scaleAroundLocal(float factor, float ox, float oy, float oz) { - return scaleAroundLocal(factor, factor, factor, ox, oy, oz, this); - } - - public Matrix4f scaleAroundLocal(float factor, float ox, float oy, float oz, Matrix4f dest) { - return scaleAroundLocal(factor, factor, factor, ox, oy, oz, dest); - } - - public Matrix4f rotateX(float ang, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotationX(ang); - else if ((properties & PROPERTY_TRANSLATION) != 0) { - float x = m30(), y = m31(), z = m32(); - return dest.rotationX(ang).setTranslation(x, y, z); - } - return rotateXInternal(ang, dest); - } - private Matrix4f rotateXInternal(float ang, Matrix4f dest) { - float sin = Math.sin(ang), cos = Math.cosFromSin(sin, ang); - float lm10 = m10(), lm11 = m11(), lm12 = m12(), lm13 = m13(), lm20 = m20(), lm21 = m21(), lm22 = m22(), lm23 = m23(); - return dest - ._m20(Math.fma(lm10, -sin, lm20 * cos)) - ._m21(Math.fma(lm11, -sin, lm21 * cos)) - ._m22(Math.fma(lm12, -sin, lm22 * cos)) - ._m23(Math.fma(lm13, -sin, lm23 * cos)) - ._m10(Math.fma(lm10, cos, lm20 * sin)) - ._m11(Math.fma(lm11, cos, lm21 * sin)) - ._m12(Math.fma(lm12, cos, lm22 * sin)) - ._m13(Math.fma(lm13, cos, lm23 * sin)) - ._m00(m00()) - ._m01(m01()) - ._m02(m02()) - ._m03(m03()) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation about the X axis to this matrix by rotating the given amount of radians. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix4f rotateX(float ang) { - return rotateX(ang, this); - } - - public Matrix4f rotateY(float ang, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotationY(ang); - else if ((properties & PROPERTY_TRANSLATION) != 0) { - float x = m30(), y = m31(), z = m32(); - return dest.rotationY(ang).setTranslation(x, y, z); - } - return rotateYInternal(ang, dest); - } - private Matrix4f rotateYInternal(float ang, Matrix4f dest) { - float sin = Math.sin(ang); - float cos = Math.cosFromSin(sin, ang); - // add temporaries for dependent values - float nm00 = Math.fma(m00(), cos, m20() * -sin); - float nm01 = Math.fma(m01(), cos, m21() * -sin); - float nm02 = Math.fma(m02(), cos, m22() * -sin); - float nm03 = Math.fma(m03(), cos, m23() * -sin); - // set non-dependent values directly - return dest - ._m20(Math.fma(m00(), sin, m20() * cos)) - ._m21(Math.fma(m01(), sin, m21() * cos)) - ._m22(Math.fma(m02(), sin, m22() * cos)) - ._m23(Math.fma(m03(), sin, m23() * cos)) - // set other values - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(m10()) - ._m11(m11()) - ._m12(m12()) - ._m13(m13()) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation about the Y axis to this matrix by rotating the given amount of radians. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix4f rotateY(float ang) { - return rotateY(ang, this); - } - - public Matrix4f rotateZ(float ang, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotationZ(ang); - else if ((properties & PROPERTY_TRANSLATION) != 0) { - float x = m30(), y = m31(), z = m32(); - return dest.rotationZ(ang).setTranslation(x, y, z); - } - return rotateZInternal(ang, dest); - } - private Matrix4f rotateZInternal(float ang, Matrix4f dest) { - float sin = Math.sin(ang); - float cos = Math.cosFromSin(sin, ang); - return rotateTowardsXY(sin, cos, dest); - } - - /** - * Apply rotation about the Z axis to this matrix by rotating the given amount of radians. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @return this - */ - public Matrix4f rotateZ(float ang) { - return rotateZ(ang, this); - } - - /** - * Apply rotation about the Z axis to align the local +X towards (dirX, dirY). - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * The vector (dirX, dirY) must be a unit vector. - * - * @param dirX - * the x component of the normalized direction - * @param dirY - * the y component of the normalized direction - * @return this - */ - public Matrix4f rotateTowardsXY(float dirX, float dirY) { - return rotateTowardsXY(dirX, dirY, this); - } - - public Matrix4f rotateTowardsXY(float dirX, float dirY, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotationTowardsXY(dirX, dirY); - float nm00 = Math.fma(m00(), dirY, m10() * dirX); - float nm01 = Math.fma(m01(), dirY, m11() * dirX); - float nm02 = Math.fma(m02(), dirY, m12() * dirX); - float nm03 = Math.fma(m03(), dirY, m13() * dirX); - return dest - ._m10(Math.fma(m00(), -dirX, m10() * dirY)) - ._m11(Math.fma(m01(), -dirX, m11() * dirY)) - ._m12(Math.fma(m02(), -dirX, m12() * dirY)) - ._m13(Math.fma(m03(), -dirX, m13() * dirY)) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m20(m20()) - ._m21(m21()) - ._m22(m22()) - ._m23(m23()) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation of angles.x radians about the X axis, followed by a rotation of angles.y radians about the Y axis and - * followed by a rotation of angles.z radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateX(angles.x()).rotateY(angles.y()).rotateZ(angles.z()) - * - * @param angles - * the Euler angles - * @return this - */ - public Matrix4f rotateXYZ(Vector3fc angles) { - return rotateXYZ(angles.x(), angles.y(), angles.z()); - } - - /** - * Apply rotation of angleX radians about the X axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateX(angleX).rotateY(angleY).rotateZ(angleZ) - * - * @param angleX - * the angle to rotate about X - * @param angleY - * the angle to rotate about Y - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix4f rotateXYZ(float angleX, float angleY, float angleZ) { - return rotateXYZ(angleX, angleY, angleZ, this); - } - - public Matrix4f rotateXYZ(float angleX, float angleY, float angleZ, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotationXYZ(angleX, angleY, angleZ); - else if ((properties & PROPERTY_TRANSLATION) != 0) { - float tx = m30(), ty = m31(), tz = m32(); - return dest.rotationXYZ(angleX, angleY, angleZ).setTranslation(tx, ty, tz); - } else if ((properties & PROPERTY_AFFINE) != 0) - return dest.rotateAffineXYZ(angleX, angleY, angleZ); - return rotateXYZInternal(angleX, angleY, angleZ, dest); - } - private Matrix4f rotateXYZInternal(float angleX, float angleY, float angleZ, Matrix4f dest) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinX = -sinX; - float m_sinY = -sinY; - float m_sinZ = -sinZ; - - // rotateX - float nm10 = Math.fma(m10(), cosX, m20() * sinX); - float nm11 = Math.fma(m11(), cosX, m21() * sinX); - float nm12 = Math.fma(m12(), cosX, m22() * sinX); - float nm13 = Math.fma(m13(), cosX, m23() * sinX); - float nm20 = Math.fma(m10(), m_sinX, m20() * cosX); - float nm21 = Math.fma(m11(), m_sinX, m21() * cosX); - float nm22 = Math.fma(m12(), m_sinX, m22() * cosX); - float nm23 = Math.fma(m13(), m_sinX, m23() * cosX); - // rotateY - float nm00 = Math.fma(m00(), cosY, nm20 * m_sinY); - float nm01 = Math.fma(m01(), cosY, nm21 * m_sinY); - float nm02 = Math.fma(m02(), cosY, nm22 * m_sinY); - float nm03 = Math.fma(m03(), cosY, nm23 * m_sinY); - return dest - ._m20(Math.fma(m00(), sinY, nm20 * cosY)) - ._m21(Math.fma(m01(), sinY, nm21 * cosY)) - ._m22(Math.fma(m02(), sinY, nm22 * cosY)) - ._m23(Math.fma(m03(), sinY, nm23 * cosY)) - // rotateZ - ._m00(Math.fma(nm00, cosZ, nm10 * sinZ)) - ._m01(Math.fma(nm01, cosZ, nm11 * sinZ)) - ._m02(Math.fma(nm02, cosZ, nm12 * sinZ)) - ._m03(Math.fma(nm03, cosZ, nm13 * sinZ)) - ._m10(Math.fma(nm00, m_sinZ, nm10 * cosZ)) - ._m11(Math.fma(nm01, m_sinZ, nm11 * cosZ)) - ._m12(Math.fma(nm02, m_sinZ, nm12 * cosZ)) - ._m13(Math.fma(nm03, m_sinZ, nm13 * cosZ)) - // copy last column from 'this' - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation of angleX radians about the X axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method assumes that this matrix represents an {@link #isAffine() affine} transformation (i.e. its last row is equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrix only represents affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateX(angleX).rotateY(angleY).rotateZ(angleZ) - * - * @param angleX - * the angle to rotate about X - * @param angleY - * the angle to rotate about Y - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix4f rotateAffineXYZ(float angleX, float angleY, float angleZ) { - return rotateAffineXYZ(angleX, angleY, angleZ, this); - } - - public Matrix4f rotateAffineXYZ(float angleX, float angleY, float angleZ, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotationXYZ(angleX, angleY, angleZ); - else if ((properties & PROPERTY_TRANSLATION) != 0) { - float tx = m30(), ty = m31(), tz = m32(); - return dest.rotationXYZ(angleX, angleY, angleZ).setTranslation(tx, ty, tz); - } - return rotateAffineXYZInternal(angleX, angleY, angleZ, dest); - } - private Matrix4f rotateAffineXYZInternal(float angleX, float angleY, float angleZ, Matrix4f dest) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinX = -sinX; - float m_sinY = -sinY; - float m_sinZ = -sinZ; - - // rotateX - float nm10 = Math.fma(m10(), cosX, m20() * sinX); - float nm11 = Math.fma(m11(), cosX, m21() * sinX); - float nm12 = Math.fma(m12(), cosX, m22() * sinX); - float nm20 = Math.fma(m10(), m_sinX, m20() * cosX); - float nm21 = Math.fma(m11(), m_sinX, m21() * cosX); - float nm22 = Math.fma(m12(), m_sinX, m22() * cosX); - // rotateY - float nm00 = Math.fma(m00(), cosY, nm20 * m_sinY); - float nm01 = Math.fma(m01(), cosY, nm21 * m_sinY); - float nm02 = Math.fma(m02(), cosY, nm22 * m_sinY); - return dest - ._m20(Math.fma(m00(), sinY, nm20 * cosY)) - ._m21(Math.fma(m01(), sinY, nm21 * cosY)) - ._m22(Math.fma(m02(), sinY, nm22 * cosY)) - ._m23(0.0f) - // rotateZ - ._m00(Math.fma(nm00, cosZ, nm10 * sinZ)) - ._m01(Math.fma(nm01, cosZ, nm11 * sinZ)) - ._m02(Math.fma(nm02, cosZ, nm12 * sinZ)) - ._m03(0.0f) - ._m10(Math.fma(nm00, m_sinZ, nm10 * cosZ)) - ._m11(Math.fma(nm01, m_sinZ, nm11 * cosZ)) - ._m12(Math.fma(nm02, m_sinZ, nm12 * cosZ)) - ._m13(0.0f) - // copy last column from 'this' - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation of angles.z radians about the Z axis, followed by a rotation of angles.y radians about the Y axis and - * followed by a rotation of angles.x radians about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateZ(angles.z).rotateY(angles.y).rotateX(angles.x) - * - * @param angles - * the Euler angles - * @return this - */ - public Matrix4f rotateZYX(Vector3f angles) { - return rotateZYX(angles.z, angles.y, angles.x); - } - - /** - * Apply rotation of angleZ radians about the Z axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleX radians about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateZ(angleZ).rotateY(angleY).rotateX(angleX) - * - * @param angleZ - * the angle to rotate about Z - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @return this - */ - public Matrix4f rotateZYX(float angleZ, float angleY, float angleX) { - return rotateZYX(angleZ, angleY, angleX, this); - } - - public Matrix4f rotateZYX(float angleZ, float angleY, float angleX, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotationZYX(angleZ, angleY, angleX); - else if ((properties & PROPERTY_TRANSLATION) != 0) { - float tx = m30(), ty = m31(), tz = m32(); - return dest.rotationZYX(angleZ, angleY, angleX).setTranslation(tx, ty, tz); - } else if ((properties & PROPERTY_AFFINE) != 0) - return dest.rotateAffineZYX(angleZ, angleY, angleX); - return rotateZYXInternal(angleZ, angleY, angleX, dest); - } - private Matrix4f rotateZYXInternal(float angleZ, float angleY, float angleX, Matrix4f dest) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinZ = -sinZ; - float m_sinY = -sinY; - float m_sinX = -sinX; - - // rotateZ - float nm00 = m00() * cosZ + m10() * sinZ; - float nm01 = m01() * cosZ + m11() * sinZ; - float nm02 = m02() * cosZ + m12() * sinZ; - float nm03 = m03() * cosZ + m13() * sinZ; - float nm10 = m00() * m_sinZ + m10() * cosZ; - float nm11 = m01() * m_sinZ + m11() * cosZ; - float nm12 = m02() * m_sinZ + m12() * cosZ; - float nm13 = m03() * m_sinZ + m13() * cosZ; - // rotateY - float nm20 = nm00 * sinY + m20() * cosY; - float nm21 = nm01 * sinY + m21() * cosY; - float nm22 = nm02 * sinY + m22() * cosY; - float nm23 = nm03 * sinY + m23() * cosY; - return dest - ._m00(nm00 * cosY + m20() * m_sinY) - ._m01(nm01 * cosY + m21() * m_sinY) - ._m02(nm02 * cosY + m22() * m_sinY) - ._m03(nm03 * cosY + m23() * m_sinY) - ._m10(nm10 * cosX + nm20 * sinX) - ._m11(nm11 * cosX + nm21 * sinX) - ._m12(nm12 * cosX + nm22 * sinX) - ._m13(nm13 * cosX + nm23 * sinX) - ._m20(nm10 * m_sinX + nm20 * cosX) - ._m21(nm11 * m_sinX + nm21 * cosX) - ._m22(nm12 * m_sinX + nm22 * cosX) - ._m23(nm13 * m_sinX + nm23 * cosX) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation of angleZ radians about the Z axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleX radians about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method assumes that this matrix represents an {@link #isAffine() affine} transformation (i.e. its last row is equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrix only represents affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - * - * @param angleZ - * the angle to rotate about Z - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @return this - */ - public Matrix4f rotateAffineZYX(float angleZ, float angleY, float angleX) { - return rotateAffineZYX(angleZ, angleY, angleX, this); - } - - public Matrix4f rotateAffineZYX(float angleZ, float angleY, float angleX, Matrix4f dest) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinZ = -sinZ; - float m_sinY = -sinY; - float m_sinX = -sinX; - - // rotateZ - float nm00 = m00() * cosZ + m10() * sinZ; - float nm01 = m01() * cosZ + m11() * sinZ; - float nm02 = m02() * cosZ + m12() * sinZ; - float nm10 = m00() * m_sinZ + m10() * cosZ; - float nm11 = m01() * m_sinZ + m11() * cosZ; - float nm12 = m02() * m_sinZ + m12() * cosZ; - // rotateY - float nm20 = nm00 * sinY + m20() * cosY; - float nm21 = nm01 * sinY + m21() * cosY; - float nm22 = nm02 * sinY + m22() * cosY; - return dest - ._m00(nm00 * cosY + m20() * m_sinY) - ._m01(nm01 * cosY + m21() * m_sinY) - ._m02(nm02 * cosY + m22() * m_sinY) - ._m03(0.0f) - ._m10(nm10 * cosX + nm20 * sinX) - ._m11(nm11 * cosX + nm21 * sinX) - ._m12(nm12 * cosX + nm22 * sinX) - ._m13(0.0f) - ._m20(nm10 * m_sinX + nm20 * cosX) - ._m21(nm11 * m_sinX + nm21 * cosX) - ._m22(nm12 * m_sinX + nm22 * cosX) - ._m23(0.0f) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation of angles.y radians about the Y axis, followed by a rotation of angles.x radians about the X axis and - * followed by a rotation of angles.z radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateY(angles.y).rotateX(angles.x).rotateZ(angles.z) - * - * @param angles - * the Euler angles - * @return this - */ - public Matrix4f rotateYXZ(Vector3f angles) { - return rotateYXZ(angles.y, angles.x, angles.z); - } - - /** - * Apply rotation of angleY radians about the Y axis, followed by a rotation of angleX radians about the X axis and - * followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateY(angleY).rotateX(angleX).rotateZ(angleZ) - * - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix4f rotateYXZ(float angleY, float angleX, float angleZ) { - return rotateYXZ(angleY, angleX, angleZ, this); - } - - public Matrix4f rotateYXZ(float angleY, float angleX, float angleZ, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotationYXZ(angleY, angleX, angleZ); - else if ((properties & PROPERTY_TRANSLATION) != 0) { - float tx = m30(), ty = m31(), tz = m32(); - return dest.rotationYXZ(angleY, angleX, angleZ).setTranslation(tx, ty, tz); - } else if ((properties & PROPERTY_AFFINE) != 0) - return dest.rotateAffineYXZ(angleY, angleX, angleZ); - return rotateYXZInternal(angleY, angleX, angleZ, dest); - } - private Matrix4f rotateYXZInternal(float angleY, float angleX, float angleZ, Matrix4f dest) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinY = -sinY; - float m_sinX = -sinX; - float m_sinZ = -sinZ; - - // rotateY - float nm20 = m00() * sinY + m20() * cosY; - float nm21 = m01() * sinY + m21() * cosY; - float nm22 = m02() * sinY + m22() * cosY; - float nm23 = m03() * sinY + m23() * cosY; - float nm00 = m00() * cosY + m20() * m_sinY; - float nm01 = m01() * cosY + m21() * m_sinY; - float nm02 = m02() * cosY + m22() * m_sinY; - float nm03 = m03() * cosY + m23() * m_sinY; - // rotateX - float nm10 = m10() * cosX + nm20 * sinX; - float nm11 = m11() * cosX + nm21 * sinX; - float nm12 = m12() * cosX + nm22 * sinX; - float nm13 = m13() * cosX + nm23 * sinX; - return dest - ._m20(m10() * m_sinX + nm20 * cosX) - ._m21(m11() * m_sinX + nm21 * cosX) - ._m22(m12() * m_sinX + nm22 * cosX) - ._m23(m13() * m_sinX + nm23 * cosX) - ._m00(nm00 * cosZ + nm10 * sinZ) - ._m01(nm01 * cosZ + nm11 * sinZ) - ._m02(nm02 * cosZ + nm12 * sinZ) - ._m03(nm03 * cosZ + nm13 * sinZ) - ._m10(nm00 * m_sinZ + nm10 * cosZ) - ._m11(nm01 * m_sinZ + nm11 * cosZ) - ._m12(nm02 * m_sinZ + nm12 * cosZ) - ._m13(nm03 * m_sinZ + nm13 * cosZ) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation of angleY radians about the Y axis, followed by a rotation of angleX radians about the X axis and - * followed by a rotation of angleZ radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method assumes that this matrix represents an {@link #isAffine() affine} transformation (i.e. its last row is equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrix only represents affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - * - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param angleZ - * the angle to rotate about Z - * @return this - */ - public Matrix4f rotateAffineYXZ(float angleY, float angleX, float angleZ) { - return rotateAffineYXZ(angleY, angleX, angleZ, this); - } - - public Matrix4f rotateAffineYXZ(float angleY, float angleX, float angleZ, Matrix4f dest) { - float sinX = Math.sin(angleX); - float cosX = Math.cosFromSin(sinX, angleX); - float sinY = Math.sin(angleY); - float cosY = Math.cosFromSin(sinY, angleY); - float sinZ = Math.sin(angleZ); - float cosZ = Math.cosFromSin(sinZ, angleZ); - float m_sinY = -sinY; - float m_sinX = -sinX; - float m_sinZ = -sinZ; - - // rotateY - float nm20 = m00() * sinY + m20() * cosY; - float nm21 = m01() * sinY + m21() * cosY; - float nm22 = m02() * sinY + m22() * cosY; - float nm00 = m00() * cosY + m20() * m_sinY; - float nm01 = m01() * cosY + m21() * m_sinY; - float nm02 = m02() * cosY + m22() * m_sinY; - // rotateX - float nm10 = m10() * cosX + nm20 * sinX; - float nm11 = m11() * cosX + nm21 * sinX; - float nm12 = m12() * cosX + nm22 * sinX; - return dest - ._m20(m10() * m_sinX + nm20 * cosX) - ._m21(m11() * m_sinX + nm21 * cosX) - ._m22(m12() * m_sinX + nm22 * cosX) - ._m23(0.0f) - ._m00(nm00 * cosZ + nm10 * sinZ) - ._m01(nm01 * cosZ + nm11 * sinZ) - ._m02(nm02 * cosZ + nm12 * sinZ) - ._m03(0.0f) - ._m10(nm00 * m_sinZ + nm10 * cosZ) - ._m11(nm01 * m_sinZ + nm11 * cosZ) - ._m12(nm02 * m_sinZ + nm12 * cosZ) - ._m13(0.0f) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation to this matrix by rotating the given amount of radians - * about the specified (x, y, z) axis and store the result in dest. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * In order to set the matrix to a rotation matrix without post-multiplying the rotation - * transformation, use {@link #rotation(float, float, float, float) rotation()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(float, float, float, float) - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotate(float ang, float x, float y, float z, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotation(ang, x, y, z); - else if ((properties & PROPERTY_TRANSLATION) != 0) - return rotateTranslation(ang, x, y, z, dest); - else if ((properties & PROPERTY_AFFINE) != 0) - return rotateAffine(ang, x, y, z, dest); - return rotateGeneric(ang, x, y, z, dest); - } - private Matrix4f rotateGeneric(float ang, float x, float y, float z, Matrix4f dest) { - if (y == 0.0f && z == 0.0f && Math.absEqualsOne(x)) - return rotateX(x * ang, dest); - else if (x == 0.0f && z == 0.0f && Math.absEqualsOne(y)) - return rotateY(y * ang, dest); - else if (x == 0.0f && y == 0.0f && Math.absEqualsOne(z)) - return rotateZ(z * ang, dest); - return rotateGenericInternal(ang, x, y, z, dest); - } - private Matrix4f rotateGenericInternal(float ang, float x, float y, float z, Matrix4f dest) { - float s = Math.sin(ang); - float c = Math.cosFromSin(s, ang); - float C = 1.0f - c; - float xx = x * x, xy = x * y, xz = x * z; - float yy = y * y, yz = y * z; - float zz = z * z; - float rm00 = xx * C + c; - float rm01 = xy * C + z * s; - float rm02 = xz * C - y * s; - float rm10 = xy * C - z * s; - float rm11 = yy * C + c; - float rm12 = yz * C + x * s; - float rm20 = xz * C + y * s; - float rm21 = yz * C - x * s; - float rm22 = zz * C + c; - float nm00 = m00() * rm00 + m10() * rm01 + m20() * rm02; - float nm01 = m01() * rm00 + m11() * rm01 + m21() * rm02; - float nm02 = m02() * rm00 + m12() * rm01 + m22() * rm02; - float nm03 = m03() * rm00 + m13() * rm01 + m23() * rm02; - float nm10 = m00() * rm10 + m10() * rm11 + m20() * rm12; - float nm11 = m01() * rm10 + m11() * rm11 + m21() * rm12; - float nm12 = m02() * rm10 + m12() * rm11 + m22() * rm12; - float nm13 = m03() * rm10 + m13() * rm11 + m23() * rm12; - return dest - ._m20(m00() * rm20 + m10() * rm21 + m20() * rm22) - ._m21(m01() * rm20 + m11() * rm21 + m21() * rm22) - ._m22(m02() * rm20 + m12() * rm21 + m22() * rm22) - ._m23(m03() * rm20 + m13() * rm21 + m23() * rm22) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation to this matrix by rotating the given amount of radians - * about the specified (x, y, z) axis. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * In order to set the matrix to a rotation matrix without post-multiplying the rotation - * transformation, use {@link #rotation(float, float, float, float) rotation()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(float, float, float, float) - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @return this - */ - public Matrix4f rotate(float ang, float x, float y, float z) { - return rotate(ang, x, y, z, this); - } - - /** - * Apply rotation to this matrix, which is assumed to only contain a translation, by rotating the given amount of radians - * about the specified (x, y, z) axis and store the result in dest. - *

- * This method assumes this to only contain a translation. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * In order to set the matrix to a rotation matrix without post-multiplying the rotation - * transformation, use {@link #rotation(float, float, float, float) rotation()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(float, float, float, float) - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateTranslation(float ang, float x, float y, float z, Matrix4f dest) { - float tx = m30(), ty = m31(), tz = m32(); - if (y == 0.0f && z == 0.0f && Math.absEqualsOne(x)) - return dest.rotationX(x * ang).setTranslation(tx, ty, tz); - else if (x == 0.0f && z == 0.0f && Math.absEqualsOne(y)) - return dest.rotationY(y * ang).setTranslation(tx, ty, tz); - else if (x == 0.0f && y == 0.0f && Math.absEqualsOne(z)) - return dest.rotationZ(z * ang).setTranslation(tx, ty, tz); - return rotateTranslationInternal(ang, x, y, z, dest); - } - private Matrix4f rotateTranslationInternal(float ang, float x, float y, float z, Matrix4f dest) { - float s = Math.sin(ang); - float c = Math.cosFromSin(s, ang); - float C = 1.0f - c; - float xx = x * x, xy = x * y, xz = x * z; - float yy = y * y, yz = y * z; - float zz = z * z; - float rm00 = xx * C + c; - float rm01 = xy * C + z * s; - float rm02 = xz * C - y * s; - float rm10 = xy * C - z * s; - float rm11 = yy * C + c; - float rm12 = yz * C + x * s; - float rm20 = xz * C + y * s; - float rm21 = yz * C - x * s; - float rm22 = zz * C + c; - return dest - ._m20(rm20) - ._m21(rm21) - ._m22(rm22) - ._m23(0.0f) - ._m00(rm00) - ._m01(rm01) - ._m02(rm02) - ._m03(0.0f) - ._m10(rm10) - ._m11(rm11) - ._m12(rm12) - ._m13(0.0f) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(1.0f) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation to this {@link #isAffine() affine} matrix by rotating the given amount of radians - * about the specified (x, y, z) axis and store the result in dest. - *

- * This method assumes this to be {@link #isAffine() affine}. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * In order to set the matrix to a rotation matrix without post-multiplying the rotation - * transformation, use {@link #rotation(float, float, float, float) rotation()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(float, float, float, float) - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateAffine(float ang, float x, float y, float z, Matrix4f dest) { - if (y == 0.0f && z == 0.0f && Math.absEqualsOne(x)) - return rotateX(x * ang, dest); - else if (x == 0.0f && z == 0.0f && Math.absEqualsOne(y)) - return rotateY(y * ang, dest); - else if (x == 0.0f && y == 0.0f && Math.absEqualsOne(z)) - return rotateZ(z * ang, dest); - return rotateAffineInternal(ang, x, y, z, dest); - } - private Matrix4f rotateAffineInternal(float ang, float x, float y, float z, Matrix4f dest) { - float s = Math.sin(ang); - float c = Math.cosFromSin(s, ang); - float C = 1.0f - c; - float xx = x * x, xy = x * y, xz = x * z; - float yy = y * y, yz = y * z; - float zz = z * z; - float rm00 = xx * C + c; - float rm01 = xy * C + z * s; - float rm02 = xz * C - y * s; - float rm10 = xy * C - z * s; - float rm11 = yy * C + c; - float rm12 = yz * C + x * s; - float rm20 = xz * C + y * s; - float rm21 = yz * C - x * s; - float rm22 = zz * C + c; - // add temporaries for dependent values - float nm00 = m00() * rm00 + m10() * rm01 + m20() * rm02; - float nm01 = m01() * rm00 + m11() * rm01 + m21() * rm02; - float nm02 = m02() * rm00 + m12() * rm01 + m22() * rm02; - float nm10 = m00() * rm10 + m10() * rm11 + m20() * rm12; - float nm11 = m01() * rm10 + m11() * rm11 + m21() * rm12; - float nm12 = m02() * rm10 + m12() * rm11 + m22() * rm12; - // set non-dependent values directly - return dest - ._m20(m00() * rm20 + m10() * rm21 + m20() * rm22) - ._m21(m01() * rm20 + m11() * rm21 + m21() * rm22) - ._m22(m02() * rm20 + m12() * rm21 + m22() * rm22) - ._m23(0.0f) - // set other values - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(0.0f) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(0.0f) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(1.0f) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply rotation to this {@link #isAffine() affine} matrix by rotating the given amount of radians - * about the specified (x, y, z) axis. - *

- * This method assumes this to be {@link #isAffine() affine}. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * In order to set the matrix to a rotation matrix without post-multiplying the rotation - * transformation, use {@link #rotation(float, float, float, float) rotation()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(float, float, float, float) - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @return this - */ - public Matrix4f rotateAffine(float ang, float x, float y, float z) { - return rotateAffine(ang, x, y, z, this); - } - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians - * about the specified (x, y, z) axis and store the result in dest. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotation(float, float, float, float) rotation()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(float, float, float, float) - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateLocal(float ang, float x, float y, float z, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotation(ang, x, y, z); - return rotateLocalGeneric(ang, x, y, z, dest); - } - private Matrix4f rotateLocalGeneric(float ang, float x, float y, float z, Matrix4f dest) { - if (y == 0.0f && z == 0.0f && Math.absEqualsOne(x)) - return rotateLocalX(x * ang, dest); - else if (x == 0.0f && z == 0.0f && Math.absEqualsOne(y)) - return rotateLocalY(y * ang, dest); - else if (x == 0.0f && y == 0.0f && Math.absEqualsOne(z)) - return rotateLocalZ(z * ang, dest); - return rotateLocalGenericInternal(ang, x, y, z, dest); - } - private Matrix4f rotateLocalGenericInternal(float ang, float x, float y, float z, Matrix4f dest) { - float s = Math.sin(ang); - float c = Math.cosFromSin(s, ang); - float C = 1.0f - c; - float xx = x * x, xy = x * y, xz = x * z; - float yy = y * y, yz = y * z; - float zz = z * z; - float lm00 = xx * C + c; - float lm01 = xy * C + z * s; - float lm02 = xz * C - y * s; - float lm10 = xy * C - z * s; - float lm11 = yy * C + c; - float lm12 = yz * C + x * s; - float lm20 = xz * C + y * s; - float lm21 = yz * C - x * s; - float lm22 = zz * C + c; - float nm00 = lm00 * m00() + lm10 * m01() + lm20 * m02(); - float nm01 = lm01 * m00() + lm11 * m01() + lm21 * m02(); - float nm02 = lm02 * m00() + lm12 * m01() + lm22 * m02(); - float nm10 = lm00 * m10() + lm10 * m11() + lm20 * m12(); - float nm11 = lm01 * m10() + lm11 * m11() + lm21 * m12(); - float nm12 = lm02 * m10() + lm12 * m11() + lm22 * m12(); - float nm20 = lm00 * m20() + lm10 * m21() + lm20 * m22(); - float nm21 = lm01 * m20() + lm11 * m21() + lm21 * m22(); - float nm22 = lm02 * m20() + lm12 * m21() + lm22 * m22(); - float nm30 = lm00 * m30() + lm10 * m31() + lm20 * m32(); - float nm31 = lm01 * m30() + lm11 * m31() + lm21 * m32(); - float nm32 = lm02 * m30() + lm12 * m31() + lm22 * m32(); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(m03()) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(m13()) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(m23()) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians - * about the specified (x, y, z) axis. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotation(float, float, float, float) rotation()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(float, float, float, float) - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @return this - */ - public Matrix4f rotateLocal(float ang, float x, float y, float z) { - return rotateLocal(ang, x, y, z, this); - } - - /** - * Pre-multiply a rotation around the X axis to this matrix by rotating the given amount of radians - * about the X axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationX(float) rotationX()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationX(float) - * - * @param ang - * the angle in radians to rotate about the X axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateLocalX(float ang, Matrix4f dest) { - float sin = Math.sin(ang); - float cos = Math.cosFromSin(sin, ang); - float nm02 = sin * m01() + cos * m02(); - float nm12 = sin * m11() + cos * m12(); - float nm22 = sin * m21() + cos * m22(); - float nm32 = sin * m31() + cos * m32(); - return dest - ._m00(m00()) - ._m01(cos * m01() - sin * m02()) - ._m02(nm02) - ._m03(m03()) - ._m10(m10()) - ._m11(cos * m11() - sin * m12()) - ._m12(nm12) - ._m13(m13()) - ._m20(m20()) - ._m21(cos * m21() - sin * m22()) - ._m22(nm22) - ._m23(m23()) - ._m30(m30()) - ._m31(cos * m31() - sin * m32()) - ._m32(nm32) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the X axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationX(float) rotationX()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationX(float) - * - * @param ang - * the angle in radians to rotate about the X axis - * @return this - */ - public Matrix4f rotateLocalX(float ang) { - return rotateLocalX(ang, this); - } - - /** - * Pre-multiply a rotation around the Y axis to this matrix by rotating the given amount of radians - * about the Y axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationY(float) rotationY()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationY(float) - * - * @param ang - * the angle in radians to rotate about the Y axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateLocalY(float ang, Matrix4f dest) { - float sin = Math.sin(ang); - float cos = Math.cosFromSin(sin, ang); - float nm02 = -sin * m00() + cos * m02(); - float nm12 = -sin * m10() + cos * m12(); - float nm22 = -sin * m20() + cos * m22(); - float nm32 = -sin * m30() + cos * m32(); - return dest - ._m00(cos * m00() + sin * m02()) - ._m01(m01()) - ._m02(nm02) - ._m03(m03()) - ._m10(cos * m10() + sin * m12()) - ._m11(m11()) - ._m12(nm12) - ._m13(m13()) - ._m20(cos * m20() + sin * m22()) - ._m21(m21()) - ._m22(nm22) - ._m23(m23()) - ._m30(cos * m30() + sin * m32()) - ._m31(m31()) - ._m32(nm32) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Y axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationY(float) rotationY()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationY(float) - * - * @param ang - * the angle in radians to rotate about the Y axis - * @return this - */ - public Matrix4f rotateLocalY(float ang) { - return rotateLocalY(ang, this); - } - - /** - * Pre-multiply a rotation around the Z axis to this matrix by rotating the given amount of radians - * about the Z axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationZ(float) rotationZ()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationZ(float) - * - * @param ang - * the angle in radians to rotate about the Z axis - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateLocalZ(float ang, Matrix4f dest) { - float sin = Math.sin(ang); - float cos = Math.cosFromSin(sin, ang); - float nm01 = sin * m00() + cos * m01(); - float nm11 = sin * m10() + cos * m11(); - float nm21 = sin * m20() + cos * m21(); - float nm31 = sin * m30() + cos * m31(); - return dest - ._m00(cos * m00() - sin * m01()) - ._m01(nm01) - ._m02(m02()) - ._m03(m03()) - ._m10(cos * m10() - sin * m11()) - ._m11(nm11) - ._m12(m12()) - ._m13(m13()) - ._m20(cos * m20() - sin * m21()) - ._m21(nm21) - ._m22(m22()) - ._m23(m23()) - ._m30(cos * m30() - sin * m31()) - ._m31(nm31) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Z axis. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * In order to set the matrix to a rotation matrix without pre-multiplying the rotation - * transformation, use {@link #rotationZ(float) rotationY()}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotationY(float) - * - * @param ang - * the angle in radians to rotate about the Z axis - * @return this - */ - public Matrix4f rotateLocalZ(float ang) { - return rotateLocalZ(ang, this); - } - - /** - * Apply a translation to this matrix by translating by the given number of - * units in x, y and z. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be M * T. So when - * transforming a vector v with the new matrix by using - * M * T * v, the translation will be applied first! - *

- * In order to set the matrix to a translation transformation without post-multiplying - * it, use {@link #translation(Vector3fc)}. - * - * @see #translation(Vector3fc) - * - * @param offset - * the number of units in x, y and z by which to translate - * @return this - */ - public Matrix4f translate(Vector3fc offset) { - return translate(offset.x(), offset.y(), offset.z()); - } - - /** - * Apply a translation to this matrix by translating by the given number of - * units in x, y and z and store the result in dest. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be M * T. So when - * transforming a vector v with the new matrix by using - * M * T * v, the translation will be applied first! - *

- * In order to set the matrix to a translation transformation without post-multiplying - * it, use {@link #translation(Vector3fc)}. - * - * @see #translation(Vector3fc) - * - * @param offset - * the number of units in x, y and z by which to translate - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f translate(Vector3fc offset, Matrix4f dest) { - return translate(offset.x(), offset.y(), offset.z(), dest); - } - - /** - * Apply a translation to this matrix by translating by the given number of - * units in x, y and z and store the result in dest. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be M * T. So when - * transforming a vector v with the new matrix by using - * M * T * v, the translation will be applied first! - *

- * In order to set the matrix to a translation transformation without post-multiplying - * it, use {@link #translation(float, float, float)}. - * - * @see #translation(float, float, float) - * - * @param x - * the offset to translate in x - * @param y - * the offset to translate in y - * @param z - * the offset to translate in z - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f translate(float x, float y, float z, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.translation(x, y, z); - return translateGeneric(x, y, z, dest); - } - private Matrix4f translateGeneric(float x, float y, float z, Matrix4f dest) { - MemUtil.INSTANCE.copy(this, dest); - return dest - ._m30(Math.fma(m00(), x, Math.fma(m10(), y, Math.fma(m20(), z, m30())))) - ._m31(Math.fma(m01(), x, Math.fma(m11(), y, Math.fma(m21(), z, m31())))) - ._m32(Math.fma(m02(), x, Math.fma(m12(), y, Math.fma(m22(), z, m32())))) - ._m33(Math.fma(m03(), x, Math.fma(m13(), y, Math.fma(m23(), z, m33())))) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY)); - } - - /** - * Apply a translation to this matrix by translating by the given number of - * units in x, y and z. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be M * T. So when - * transforming a vector v with the new matrix by using - * M * T * v, the translation will be applied first! - *

- * In order to set the matrix to a translation transformation without post-multiplying - * it, use {@link #translation(float, float, float)}. - * - * @see #translation(float, float, float) - * - * @param x - * the offset to translate in x - * @param y - * the offset to translate in y - * @param z - * the offset to translate in z - * @return this - */ - public Matrix4f translate(float x, float y, float z) { - if ((properties & PROPERTY_IDENTITY) != 0) - return translation(x, y, z); - return translateGeneric(x, y, z); - } - private Matrix4f translateGeneric(float x, float y, float z) { - return this - ._m30(Math.fma(m00(), x, Math.fma(m10(), y, Math.fma(m20(), z, m30())))) - ._m31(Math.fma(m01(), x, Math.fma(m11(), y, Math.fma(m21(), z, m31())))) - ._m32(Math.fma(m02(), x, Math.fma(m12(), y, Math.fma(m22(), z, m32())))) - ._m33(Math.fma(m03(), x, Math.fma(m13(), y, Math.fma(m23(), z, m33())))) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY)); - } - - /** - * Pre-multiply a translation to this matrix by translating by the given number of - * units in x, y and z. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be T * M. So when - * transforming a vector v with the new matrix by using - * T * M * v, the translation will be applied last! - *

- * In order to set the matrix to a translation transformation without pre-multiplying - * it, use {@link #translation(Vector3fc)}. - * - * @see #translation(Vector3fc) - * - * @param offset - * the number of units in x, y and z by which to translate - * @return this - */ - public Matrix4f translateLocal(Vector3fc offset) { - return translateLocal(offset.x(), offset.y(), offset.z()); - } - - /** - * Pre-multiply a translation to this matrix by translating by the given number of - * units in x, y and z and store the result in dest. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be T * M. So when - * transforming a vector v with the new matrix by using - * T * M * v, the translation will be applied last! - *

- * In order to set the matrix to a translation transformation without pre-multiplying - * it, use {@link #translation(Vector3fc)}. - * - * @see #translation(Vector3fc) - * - * @param offset - * the number of units in x, y and z by which to translate - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f translateLocal(Vector3fc offset, Matrix4f dest) { - return translateLocal(offset.x(), offset.y(), offset.z(), dest); - } - - /** - * Pre-multiply a translation to this matrix by translating by the given number of - * units in x, y and z and store the result in dest. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be T * M. So when - * transforming a vector v with the new matrix by using - * T * M * v, the translation will be applied last! - *

- * In order to set the matrix to a translation transformation without pre-multiplying - * it, use {@link #translation(float, float, float)}. - * - * @see #translation(float, float, float) - * - * @param x - * the offset to translate in x - * @param y - * the offset to translate in y - * @param z - * the offset to translate in z - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f translateLocal(float x, float y, float z, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.translation(x, y, z); - return translateLocalGeneric(x, y, z, dest); - } - private Matrix4f translateLocalGeneric(float x, float y, float z, Matrix4f dest) { - float nm00 = m00() + x * m03(); - float nm01 = m01() + y * m03(); - float nm02 = m02() + z * m03(); - float nm10 = m10() + x * m13(); - float nm11 = m11() + y * m13(); - float nm12 = m12() + z * m13(); - float nm20 = m20() + x * m23(); - float nm21 = m21() + y * m23(); - float nm22 = m22() + z * m23(); - float nm30 = m30() + x * m33(); - float nm31 = m31() + y * m33(); - float nm32 = m32() + z * m33(); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(m03()) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(m13()) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(m23()) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY)); - } - - /** - * Pre-multiply a translation to this matrix by translating by the given number of - * units in x, y and z. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be T * M. So when - * transforming a vector v with the new matrix by using - * T * M * v, the translation will be applied last! - *

- * In order to set the matrix to a translation transformation without pre-multiplying - * it, use {@link #translation(float, float, float)}. - * - * @see #translation(float, float, float) - * - * @param x - * the offset to translate in x - * @param y - * the offset to translate in y - * @param z - * the offset to translate in z - * @return this - */ - public Matrix4f translateLocal(float x, float y, float z) { - return translateLocal(x, y, z, this); - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(m00()); - out.writeFloat(m01()); - out.writeFloat(m02()); - out.writeFloat(m03()); - out.writeFloat(m10()); - out.writeFloat(m11()); - out.writeFloat(m12()); - out.writeFloat(m13()); - out.writeFloat(m20()); - out.writeFloat(m21()); - out.writeFloat(m22()); - out.writeFloat(m23()); - out.writeFloat(m30()); - out.writeFloat(m31()); - out.writeFloat(m32()); - out.writeFloat(m33()); - } - - public void readExternal(ObjectInput in) throws IOException { - this._m00(in.readFloat()) - ._m01(in.readFloat()) - ._m02(in.readFloat()) - ._m03(in.readFloat()) - ._m10(in.readFloat()) - ._m11(in.readFloat()) - ._m12(in.readFloat()) - ._m13(in.readFloat()) - ._m20(in.readFloat()) - ._m21(in.readFloat()) - ._m22(in.readFloat()) - ._m23(in.readFloat()) - ._m30(in.readFloat()) - ._m31(in.readFloat()) - ._m32(in.readFloat()) - ._m33(in.readFloat()) - .determineProperties(); - } - - /** - * Apply an orthographic projection transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrtho(float, float, float, float, float, float, boolean) setOrtho()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrtho(float, float, float, float, float, float, boolean) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f ortho(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setOrtho(left, right, bottom, top, zNear, zFar, zZeroToOne); - return orthoGeneric(left, right, bottom, top, zNear, zFar, zZeroToOne, dest); - } - private Matrix4f orthoGeneric(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - // calculate right matrix elements - float rm00 = 2.0f / (right - left); - float rm11 = 2.0f / (top - bottom); - float rm22 = (zZeroToOne ? 1.0f : 2.0f) / (zNear - zFar); - float rm30 = (left + right) / (left - right); - float rm31 = (top + bottom) / (bottom - top); - float rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); - // perform optimized multiplication - // compute the last column first, because other columns do not depend on it - dest._m30(m00() * rm30 + m10() * rm31 + m20() * rm32 + m30()) - ._m31(m01() * rm30 + m11() * rm31 + m21() * rm32 + m31()) - ._m32(m02() * rm30 + m12() * rm31 + m22() * rm32 + m32()) - ._m33(m03() * rm30 + m13() * rm31 + m23() * rm32 + m33()) - ._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m20(m20() * rm22) - ._m21(m21() * rm22) - ._m22(m22() * rm22) - ._m23(m23() * rm22) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - /** - * Apply an orthographic projection transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrtho(float, float, float, float, float, float) setOrtho()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrtho(float, float, float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f ortho(float left, float right, float bottom, float top, float zNear, float zFar, Matrix4f dest) { - return ortho(left, right, bottom, top, zNear, zFar, false, dest); - } - - /** - * Apply an orthographic projection transformation for a right-handed coordinate system using the given NDC z range to this matrix. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrtho(float, float, float, float, float, float, boolean) setOrtho()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrtho(float, float, float, float, float, float, boolean) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f ortho(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne) { - return ortho(left, right, bottom, top, zNear, zFar, zZeroToOne, this); - } - - /** - * Apply an orthographic projection transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrtho(float, float, float, float, float, float) setOrtho()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrtho(float, float, float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @return this - */ - public Matrix4f ortho(float left, float right, float bottom, float top, float zNear, float zFar) { - return ortho(left, right, bottom, top, zNear, zFar, false); - } - - /** - * Apply an orthographic projection transformation for a left-handed coordiante system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrthoLH(float, float, float, float, float, float, boolean) setOrthoLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoLH(float, float, float, float, float, float, boolean) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f orthoLH(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setOrthoLH(left, right, bottom, top, zNear, zFar, zZeroToOne); - return orthoLHGeneric(left, right, bottom, top, zNear, zFar, zZeroToOne, dest); - } - private Matrix4f orthoLHGeneric(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - // calculate right matrix elements - float rm00 = 2.0f / (right - left); - float rm11 = 2.0f / (top - bottom); - float rm22 = (zZeroToOne ? 1.0f : 2.0f) / (zFar - zNear); - float rm30 = (left + right) / (left - right); - float rm31 = (top + bottom) / (bottom - top); - float rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); - - // perform optimized multiplication - // compute the last column first, because other columns do not depend on it - dest._m30(m00() * rm30 + m10() * rm31 + m20() * rm32 + m30()) - ._m31(m01() * rm30 + m11() * rm31 + m21() * rm32 + m31()) - ._m32(m02() * rm30 + m12() * rm31 + m22() * rm32 + m32()) - ._m33(m03() * rm30 + m13() * rm31 + m23() * rm32 + m33()) - ._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m20(m20() * rm22) - ._m21(m21() * rm22) - ._m22(m22() * rm22) - ._m23(m23() * rm22) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - /** - * Apply an orthographic projection transformation for a left-handed coordiante system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrthoLH(float, float, float, float, float, float) setOrthoLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoLH(float, float, float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f orthoLH(float left, float right, float bottom, float top, float zNear, float zFar, Matrix4f dest) { - return orthoLH(left, right, bottom, top, zNear, zFar, false, dest); - } - - /** - * Apply an orthographic projection transformation for a left-handed coordiante system - * using the given NDC z range to this matrix. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrthoLH(float, float, float, float, float, float, boolean) setOrthoLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoLH(float, float, float, float, float, float, boolean) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f orthoLH(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne) { - return orthoLH(left, right, bottom, top, zNear, zFar, zZeroToOne, this); - } - - /** - * Apply an orthographic projection transformation for a left-handed coordiante system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrthoLH(float, float, float, float, float, float) setOrthoLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoLH(float, float, float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @return this - */ - public Matrix4f orthoLH(float left, float right, float bottom, float top, float zNear, float zFar) { - return orthoLH(left, right, bottom, top, zNear, zFar, false); - } - - /** - * Set this matrix to be an orthographic projection transformation for a right-handed coordinate system - * using the given NDC z range. - *

- * In order to apply the orthographic projection to an already existing transformation, - * use {@link #ortho(float, float, float, float, float, float, boolean) ortho()}. - *

- * Reference: http://www.songho.ca - * - * @see #ortho(float, float, float, float, float, float, boolean) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setOrtho(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m00(2.0f / (right - left)) - ._m11(2.0f / (top - bottom)) - ._m22((zZeroToOne ? 1.0f : 2.0f) / (zNear - zFar)) - ._m30((right + left) / (left - right)) - ._m31((top + bottom) / (bottom - top)) - ._m32((zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar)) - ._properties(PROPERTY_AFFINE); - return this; - } - - /** - * Set this matrix to be an orthographic projection transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1]. - *

- * In order to apply the orthographic projection to an already existing transformation, - * use {@link #ortho(float, float, float, float, float, float) ortho()}. - *

- * Reference: http://www.songho.ca - * - * @see #ortho(float, float, float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @return this - */ - public Matrix4f setOrtho(float left, float right, float bottom, float top, float zNear, float zFar) { - return setOrtho(left, right, bottom, top, zNear, zFar, false); - } - - /** - * Set this matrix to be an orthographic projection transformation for a left-handed coordinate system - * using the given NDC z range. - *

- * In order to apply the orthographic projection to an already existing transformation, - * use {@link #orthoLH(float, float, float, float, float, float, boolean) orthoLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #orthoLH(float, float, float, float, float, float, boolean) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setOrthoLH(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m00(2.0f / (right - left)) - ._m11(2.0f / (top - bottom)) - ._m22((zZeroToOne ? 1.0f : 2.0f) / (zFar - zNear)) - ._m30((right + left) / (left - right)) - ._m31((top + bottom) / (bottom - top)) - ._m32((zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar)) - ._properties(PROPERTY_AFFINE); - return this; - } - - /** - * Set this matrix to be an orthographic projection transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1]. - *

- * In order to apply the orthographic projection to an already existing transformation, - * use {@link #orthoLH(float, float, float, float, float, float) orthoLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #orthoLH(float, float, float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @return this - */ - public Matrix4f setOrthoLH(float left, float right, float bottom, float top, float zNear, float zFar) { - return setOrthoLH(left, right, bottom, top, zNear, zFar, false); - } - - /** - * Apply a symmetric orthographic projection transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * This method is equivalent to calling {@link #ortho(float, float, float, float, float, float, boolean, Matrix4f) ortho()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, - * use {@link #setOrthoSymmetric(float, float, float, float, boolean) setOrthoSymmetric()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoSymmetric(float, float, float, float, boolean) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return dest - */ - public Matrix4f orthoSymmetric(float width, float height, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setOrthoSymmetric(width, height, zNear, zFar, zZeroToOne); - return orthoSymmetricGeneric(width, height, zNear, zFar, zZeroToOne, dest); - } - private Matrix4f orthoSymmetricGeneric(float width, float height, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - // calculate right matrix elements - float rm00 = 2.0f / width; - float rm11 = 2.0f / height; - float rm22 = (zZeroToOne ? 1.0f : 2.0f) / (zNear - zFar); - float rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); - // perform optimized multiplication - // compute the last column first, because other columns do not depend on it - dest._m30(m20() * rm32 + m30()) - ._m31(m21() * rm32 + m31()) - ._m32(m22() * rm32 + m32()) - ._m33(m23() * rm32 + m33()) - ._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m20(m20() * rm22) - ._m21(m21() * rm22) - ._m22(m22() * rm22) - ._m23(m23() * rm22) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - /** - * Apply a symmetric orthographic projection transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * This method is equivalent to calling {@link #ortho(float, float, float, float, float, float, Matrix4f) ortho()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, - * use {@link #setOrthoSymmetric(float, float, float, float) setOrthoSymmetric()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoSymmetric(float, float, float, float) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f orthoSymmetric(float width, float height, float zNear, float zFar, Matrix4f dest) { - return orthoSymmetric(width, height, zNear, zFar, false, dest); - } - - /** - * Apply a symmetric orthographic projection transformation for a right-handed coordinate system - * using the given NDC z range to this matrix. - *

- * This method is equivalent to calling {@link #ortho(float, float, float, float, float, float, boolean) ortho()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, - * use {@link #setOrthoSymmetric(float, float, float, float, boolean) setOrthoSymmetric()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoSymmetric(float, float, float, float, boolean) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f orthoSymmetric(float width, float height, float zNear, float zFar, boolean zZeroToOne) { - return orthoSymmetric(width, height, zNear, zFar, zZeroToOne, this); - } - - /** - * Apply a symmetric orthographic projection transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * This method is equivalent to calling {@link #ortho(float, float, float, float, float, float) ortho()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, - * use {@link #setOrthoSymmetric(float, float, float, float) setOrthoSymmetric()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoSymmetric(float, float, float, float) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @return this - */ - public Matrix4f orthoSymmetric(float width, float height, float zNear, float zFar) { - return orthoSymmetric(width, height, zNear, zFar, false, this); - } - - /** - * Apply a symmetric orthographic projection transformation for a left-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * This method is equivalent to calling {@link #orthoLH(float, float, float, float, float, float, boolean, Matrix4f) orthoLH()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, - * use {@link #setOrthoSymmetricLH(float, float, float, float, boolean) setOrthoSymmetricLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoSymmetricLH(float, float, float, float, boolean) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return dest - */ - public Matrix4f orthoSymmetricLH(float width, float height, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setOrthoSymmetricLH(width, height, zNear, zFar, zZeroToOne); - return orthoSymmetricLHGeneric(width, height, zNear, zFar, zZeroToOne, dest); - } - private Matrix4f orthoSymmetricLHGeneric(float width, float height, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - // calculate right matrix elements - float rm00 = 2.0f / width; - float rm11 = 2.0f / height; - float rm22 = (zZeroToOne ? 1.0f : 2.0f) / (zFar - zNear); - float rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); - // perform optimized multiplication - // compute the last column first, because other columns do not depend on it - dest._m30(m20() * rm32 + m30()) - ._m31(m21() * rm32 + m31()) - ._m32(m22() * rm32 + m32()) - ._m33(m23() * rm32 + m33()) - ._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m20(m20() * rm22) - ._m21(m21() * rm22) - ._m22(m22() * rm22) - ._m23(m23() * rm22) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - /** - * Apply a symmetric orthographic projection transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * This method is equivalent to calling {@link #orthoLH(float, float, float, float, float, float, Matrix4f) orthoLH()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, - * use {@link #setOrthoSymmetricLH(float, float, float, float) setOrthoSymmetricLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoSymmetricLH(float, float, float, float) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f orthoSymmetricLH(float width, float height, float zNear, float zFar, Matrix4f dest) { - return orthoSymmetricLH(width, height, zNear, zFar, false, dest); - } - - /** - * Apply a symmetric orthographic projection transformation for a left-handed coordinate system - * using the given NDC z range to this matrix. - *

- * This method is equivalent to calling {@link #orthoLH(float, float, float, float, float, float, boolean) orthoLH()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, - * use {@link #setOrthoSymmetricLH(float, float, float, float, boolean) setOrthoSymmetricLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoSymmetricLH(float, float, float, float, boolean) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f orthoSymmetricLH(float width, float height, float zNear, float zFar, boolean zZeroToOne) { - return orthoSymmetricLH(width, height, zNear, zFar, zZeroToOne, this); - } - - /** - * Apply a symmetric orthographic projection transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * This method is equivalent to calling {@link #orthoLH(float, float, float, float, float, float) orthoLH()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, - * use {@link #setOrthoSymmetricLH(float, float, float, float) setOrthoSymmetricLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoSymmetricLH(float, float, float, float) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @return this - */ - public Matrix4f orthoSymmetricLH(float width, float height, float zNear, float zFar) { - return orthoSymmetricLH(width, height, zNear, zFar, false, this); - } - - /** - * Set this matrix to be a symmetric orthographic projection transformation for a right-handed coordinate system using the given NDC z range. - *

- * This method is equivalent to calling {@link #setOrtho(float, float, float, float, float, float, boolean) setOrtho()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * In order to apply the symmetric orthographic projection to an already existing transformation, - * use {@link #orthoSymmetric(float, float, float, float, boolean) orthoSymmetric()}. - *

- * Reference: http://www.songho.ca - * - * @see #orthoSymmetric(float, float, float, float, boolean) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setOrthoSymmetric(float width, float height, float zNear, float zFar, boolean zZeroToOne) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m00(2.0f / width) - ._m11(2.0f / height) - ._m22((zZeroToOne ? 1.0f : 2.0f) / (zNear - zFar)) - ._m32((zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar)) - ._properties(PROPERTY_AFFINE); - return this; - } - - /** - * Set this matrix to be a symmetric orthographic projection transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1]. - *

- * This method is equivalent to calling {@link #setOrtho(float, float, float, float, float, float) setOrtho()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * In order to apply the symmetric orthographic projection to an already existing transformation, - * use {@link #orthoSymmetric(float, float, float, float) orthoSymmetric()}. - *

- * Reference: http://www.songho.ca - * - * @see #orthoSymmetric(float, float, float, float) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @return this - */ - public Matrix4f setOrthoSymmetric(float width, float height, float zNear, float zFar) { - return setOrthoSymmetric(width, height, zNear, zFar, false); - } - - /** - * Set this matrix to be a symmetric orthographic projection transformation for a left-handed coordinate system using the given NDC z range. - *

- * This method is equivalent to calling {@link #setOrtho(float, float, float, float, float, float, boolean) setOrtho()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * In order to apply the symmetric orthographic projection to an already existing transformation, - * use {@link #orthoSymmetricLH(float, float, float, float, boolean) orthoSymmetricLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #orthoSymmetricLH(float, float, float, float, boolean) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setOrthoSymmetricLH(float width, float height, float zNear, float zFar, boolean zZeroToOne) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m00(2.0f / width) - ._m11(2.0f / height) - ._m22((zZeroToOne ? 1.0f : 2.0f) / (zFar - zNear)) - ._m32((zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar)) - ._properties(PROPERTY_AFFINE); - return this; - } - - /** - * Set this matrix to be a symmetric orthographic projection transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1]. - *

- * This method is equivalent to calling {@link #setOrthoLH(float, float, float, float, float, float) setOrthoLH()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * In order to apply the symmetric orthographic projection to an already existing transformation, - * use {@link #orthoSymmetricLH(float, float, float, float) orthoSymmetricLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #orthoSymmetricLH(float, float, float, float) - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @return this - */ - public Matrix4f setOrthoSymmetricLH(float width, float height, float zNear, float zFar) { - return setOrthoSymmetricLH(width, height, zNear, zFar, false); - } - - /** - * Apply an orthographic projection transformation for a right-handed coordinate system to this matrix - * and store the result in dest. - *

- * This method is equivalent to calling {@link #ortho(float, float, float, float, float, float, Matrix4f) ortho()} with - * zNear=-1 and zFar=+1. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrtho2D(float, float, float, float) setOrtho()}. - *

- * Reference: http://www.songho.ca - * - * @see #ortho(float, float, float, float, float, float, Matrix4f) - * @see #setOrtho2D(float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f ortho2D(float left, float right, float bottom, float top, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setOrtho2D(left, right, bottom, top); - return ortho2DGeneric(left, right, bottom, top, dest); - } - private Matrix4f ortho2DGeneric(float left, float right, float bottom, float top, Matrix4f dest) { - // calculate right matrix elements - float rm00 = 2.0f / (right - left); - float rm11 = 2.0f / (top - bottom); - float rm30 = (right + left) / (left - right); - float rm31 = (top + bottom) / (bottom - top); - // perform optimized multiplication - // compute the last column first, because other columns do not depend on it - dest._m30(m00() * rm30 + m10() * rm31 + m30()) - ._m31(m01() * rm30 + m11() * rm31 + m31()) - ._m32(m02() * rm30 + m12() * rm31 + m32()) - ._m33(m03() * rm30 + m13() * rm31 + m33()) - ._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m20(-m20()) - ._m21(-m21()) - ._m22(-m22()) - ._m23(-m23()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - /** - * Apply an orthographic projection transformation for a right-handed coordinate system to this matrix. - *

- * This method is equivalent to calling {@link #ortho(float, float, float, float, float, float) ortho()} with - * zNear=-1 and zFar=+1. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrtho2D(float, float, float, float) setOrtho2D()}. - *

- * Reference: http://www.songho.ca - * - * @see #ortho(float, float, float, float, float, float) - * @see #setOrtho2D(float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @return this - */ - public Matrix4f ortho2D(float left, float right, float bottom, float top) { - return ortho2D(left, right, bottom, top, this); - } - - /** - * Apply an orthographic projection transformation for a left-handed coordinate system to this matrix and store the result in dest. - *

- * This method is equivalent to calling {@link #orthoLH(float, float, float, float, float, float, Matrix4f) orthoLH()} with - * zNear=-1 and zFar=+1. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrtho2DLH(float, float, float, float) setOrthoLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #orthoLH(float, float, float, float, float, float, Matrix4f) - * @see #setOrtho2DLH(float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f ortho2DLH(float left, float right, float bottom, float top, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setOrtho2DLH(left, right, bottom, top); - return ortho2DLHGeneric(left, right, bottom, top, dest); - } - private Matrix4f ortho2DLHGeneric(float left, float right, float bottom, float top, Matrix4f dest) { - // calculate right matrix elements - float rm00 = 2.0f / (right - left); - float rm11 = 2.0f / (top - bottom); - float rm30 = (right + left) / (left - right); - float rm31 = (top + bottom) / (bottom - top); - - // perform optimized multiplication - // compute the last column first, because other columns do not depend on it - dest._m30(m00() * rm30 + m10() * rm31 + m30()) - ._m31(m01() * rm30 + m11() * rm31 + m31()) - ._m32(m02() * rm30 + m12() * rm31 + m32()) - ._m33(m03() * rm30 + m13() * rm31 + m33()) - ._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m20(m20()) - ._m21(m21()) - ._m22(m22()) - ._m23(m23()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - /** - * Apply an orthographic projection transformation for a left-handed coordinate system to this matrix. - *

- * This method is equivalent to calling {@link #orthoLH(float, float, float, float, float, float) orthoLH()} with - * zNear=-1 and zFar=+1. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * In order to set the matrix to an orthographic projection without post-multiplying it, - * use {@link #setOrtho2DLH(float, float, float, float) setOrtho2DLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #orthoLH(float, float, float, float, float, float) - * @see #setOrtho2DLH(float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @return this - */ - public Matrix4f ortho2DLH(float left, float right, float bottom, float top) { - return ortho2DLH(left, right, bottom, top, this); - } - - /** - * Set this matrix to be an orthographic projection transformation for a right-handed coordinate system. - *

- * This method is equivalent to calling {@link #setOrtho(float, float, float, float, float, float) setOrtho()} with - * zNear=-1 and zFar=+1. - *

- * In order to apply the orthographic projection to an already existing transformation, - * use {@link #ortho2D(float, float, float, float) ortho2D()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrtho(float, float, float, float, float, float) - * @see #ortho2D(float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @return this - */ - public Matrix4f setOrtho2D(float left, float right, float bottom, float top) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m00(2.0f / (right - left)) - ._m11(2.0f / (top - bottom)) - ._m22(-1.0f) - ._m30((right + left) / (left - right)) - ._m31((top + bottom) / (bottom - top)) - ._properties(PROPERTY_AFFINE); - return this; - } - - /** - * Set this matrix to be an orthographic projection transformation for a left-handed coordinate system. - *

- * This method is equivalent to calling {@link #setOrtho(float, float, float, float, float, float) setOrthoLH()} with - * zNear=-1 and zFar=+1. - *

- * In order to apply the orthographic projection to an already existing transformation, - * use {@link #ortho2DLH(float, float, float, float) ortho2DLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setOrthoLH(float, float, float, float, float, float) - * @see #ortho2DLH(float, float, float, float) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @return this - */ - public Matrix4f setOrtho2DLH(float left, float right, float bottom, float top) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m00(2.0f / (right - left)) - ._m11(2.0f / (top - bottom)) - ._m30((right + left) / (left - right)) - ._m31((top + bottom) / (bottom - top)) - ._properties(PROPERTY_AFFINE); - return this; - } - - /** - * Apply a rotation transformation to this matrix to make -z point along dir. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - *

- * This is equivalent to calling - * {@link #lookAt(Vector3fc, Vector3fc, Vector3fc) lookAt} - * with eye = (0, 0, 0) and center = dir. - *

- * In order to set the matrix to a lookalong transformation without post-multiplying it, - * use {@link #setLookAlong(Vector3fc, Vector3fc) setLookAlong()}. - * - * @see #lookAlong(float, float, float, float, float, float) - * @see #lookAt(Vector3fc, Vector3fc, Vector3fc) - * @see #setLookAlong(Vector3fc, Vector3fc) - * - * @param dir - * the direction in space to look along - * @param up - * the direction of 'up' - * @return this - */ - public Matrix4f lookAlong(Vector3fc dir, Vector3fc up) { - return lookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z(), this); - } - - /** - * Apply a rotation transformation to this matrix to make -z point along dir - * and store the result in dest. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - *

- * This is equivalent to calling - * {@link #lookAt(Vector3fc, Vector3fc, Vector3fc) lookAt} - * with eye = (0, 0, 0) and center = dir. - *

- * In order to set the matrix to a lookalong transformation without post-multiplying it, - * use {@link #setLookAlong(Vector3fc, Vector3fc) setLookAlong()}. - * - * @see #lookAlong(float, float, float, float, float, float) - * @see #lookAt(Vector3fc, Vector3fc, Vector3fc) - * @see #setLookAlong(Vector3fc, Vector3fc) - * - * @param dir - * the direction in space to look along - * @param up - * the direction of 'up' - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f lookAlong(Vector3fc dir, Vector3fc up, Matrix4f dest) { - return lookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z(), dest); - } - - /** - * Apply a rotation transformation to this matrix to make -z point along dir - * and store the result in dest. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - *

- * This is equivalent to calling - * {@link #lookAt(float, float, float, float, float, float, float, float, float) lookAt()} - * with eye = (0, 0, 0) and center = dir. - *

- * In order to set the matrix to a lookalong transformation without post-multiplying it, - * use {@link #setLookAlong(float, float, float, float, float, float) setLookAlong()} - * - * @see #lookAt(float, float, float, float, float, float, float, float, float) - * @see #setLookAlong(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to look along - * @param dirY - * the y-coordinate of the direction to look along - * @param dirZ - * the z-coordinate of the direction to look along - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f lookAlong(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setLookAlong(dirX, dirY, dirZ, upX, upY, upZ); - return lookAlongGeneric(dirX, dirY, dirZ, upX, upY, upZ, dest); - } - - private Matrix4f lookAlongGeneric(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Matrix4f dest) { - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= -invDirLength; - dirY *= -invDirLength; - dirZ *= -invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * dirZ - upZ * dirY; - leftY = upZ * dirX - upX * dirZ; - leftZ = upX * dirY - upY * dirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = dirY * leftZ - dirZ * leftY; - float upnY = dirZ * leftX - dirX * leftZ; - float upnZ = dirX * leftY - dirY * leftX; - // perform optimized matrix multiplication - // introduce temporaries for dependent results - float nm00 = m00() * leftX + m10() * upnX + m20() * dirX; - float nm01 = m01() * leftX + m11() * upnX + m21() * dirX; - float nm02 = m02() * leftX + m12() * upnX + m22() * dirX; - float nm03 = m03() * leftX + m13() * upnX + m23() * dirX; - float nm10 = m00() * leftY + m10() * upnY + m20() * dirY; - float nm11 = m01() * leftY + m11() * upnY + m21() * dirY; - float nm12 = m02() * leftY + m12() * upnY + m22() * dirY; - float nm13 = m03() * leftY + m13() * upnY + m23() * dirY; - return dest - ._m20(m00() * leftZ + m10() * upnZ + m20() * dirZ) - ._m21(m01() * leftZ + m11() * upnZ + m21() * dirZ) - ._m22(m02() * leftZ + m12() * upnZ + m22() * dirZ) - ._m23(m03() * leftZ + m13() * upnZ + m23() * dirZ) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply a rotation transformation to this matrix to make -z point along dir. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - *

- * This is equivalent to calling - * {@link #lookAt(float, float, float, float, float, float, float, float, float) lookAt()} - * with eye = (0, 0, 0) and center = dir. - *

- * In order to set the matrix to a lookalong transformation without post-multiplying it, - * use {@link #setLookAlong(float, float, float, float, float, float) setLookAlong()} - * - * @see #lookAt(float, float, float, float, float, float, float, float, float) - * @see #setLookAlong(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to look along - * @param dirY - * the y-coordinate of the direction to look along - * @param dirZ - * the z-coordinate of the direction to look along - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix4f lookAlong(float dirX, float dirY, float dirZ, - float upX, float upY, float upZ) { - return lookAlong(dirX, dirY, dirZ, upX, upY, upZ, this); - } - - /** - * Set this matrix to a rotation transformation to make -z - * point along dir. - *

- * This is equivalent to calling - * {@link #setLookAt(Vector3fc, Vector3fc, Vector3fc) setLookAt()} - * with eye = (0, 0, 0) and center = dir. - *

- * In order to apply the lookalong transformation to any previous existing transformation, - * use {@link #lookAlong(Vector3fc, Vector3fc)}. - * - * @see #setLookAlong(Vector3fc, Vector3fc) - * @see #lookAlong(Vector3fc, Vector3fc) - * - * @param dir - * the direction in space to look along - * @param up - * the direction of 'up' - * @return this - */ - public Matrix4f setLookAlong(Vector3fc dir, Vector3fc up) { - return setLookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z()); - } - - /** - * Set this matrix to a rotation transformation to make -z - * point along dir. - *

- * This is equivalent to calling - * {@link #setLookAt(float, float, float, float, float, float, float, float, float) - * setLookAt()} with eye = (0, 0, 0) and center = dir. - *

- * In order to apply the lookalong transformation to any previous existing transformation, - * use {@link #lookAlong(float, float, float, float, float, float) lookAlong()} - * - * @see #setLookAlong(float, float, float, float, float, float) - * @see #lookAlong(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to look along - * @param dirY - * the y-coordinate of the direction to look along - * @param dirZ - * the z-coordinate of the direction to look along - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix4f setLookAlong(float dirX, float dirY, float dirZ, - float upX, float upY, float upZ) { - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= -invDirLength; - dirY *= -invDirLength; - dirZ *= -invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * dirZ - upZ * dirY; - leftY = upZ * dirX - upX * dirZ; - leftZ = upX * dirY - upY * dirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - this._m00(leftX) - ._m01(dirY * leftZ - dirZ * leftY) - ._m02(dirX) - ._m03(0.0f) - ._m10(leftY) - ._m11(dirZ * leftX - dirX * leftZ) - ._m12(dirY) - ._m13(0.0f) - ._m20(leftZ) - ._m21(dirX * leftY - dirY * leftX) - ._m22(dirZ) - ._m23(0.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(0.0f) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - /** - * Set this matrix to be a "lookat" transformation for a right-handed coordinate system, that aligns - * -z with center - eye. - *

- * In order to not make use of vectors to specify eye, center and up but use primitives, - * like in the GLU function, use {@link #setLookAt(float, float, float, float, float, float, float, float, float) setLookAt()} - * instead. - *

- * In order to apply the lookat transformation to a previous existing transformation, - * use {@link #lookAt(Vector3fc, Vector3fc, Vector3fc) lookAt()}. - * - * @see #setLookAt(float, float, float, float, float, float, float, float, float) - * @see #lookAt(Vector3fc, Vector3fc, Vector3fc) - * - * @param eye - * the position of the camera - * @param center - * the point in space to look at - * @param up - * the direction of 'up' - * @return this - */ - public Matrix4f setLookAt(Vector3fc eye, Vector3fc center, Vector3fc up) { - return setLookAt(eye.x(), eye.y(), eye.z(), center.x(), center.y(), center.z(), up.x(), up.y(), up.z()); - } - - /** - * Set this matrix to be a "lookat" transformation for a right-handed coordinate system, - * that aligns -z with center - eye. - *

- * In order to apply the lookat transformation to a previous existing transformation, - * use {@link #lookAt(float, float, float, float, float, float, float, float, float) lookAt}. - * - * @see #setLookAt(Vector3fc, Vector3fc, Vector3fc) - * @see #lookAt(float, float, float, float, float, float, float, float, float) - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix4f setLookAt(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - // Compute direction from position to lookAt - float dirX, dirY, dirZ; - dirX = eyeX - centerX; - dirY = eyeY - centerY; - dirZ = eyeZ - centerZ; - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= invDirLength; - dirY *= invDirLength; - dirZ *= invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * dirZ - upZ * dirY; - leftY = upZ * dirX - upX * dirZ; - leftZ = upX * dirY - upY * dirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = dirY * leftZ - dirZ * leftY; - float upnY = dirZ * leftX - dirX * leftZ; - float upnZ = dirX * leftY - dirY * leftX; - return this - ._m00(leftX) - ._m01(upnX) - ._m02(dirX) - ._m03(0.0f) - ._m10(leftY) - ._m11(upnY) - ._m12(dirY) - ._m13(0.0f) - ._m20(leftZ) - ._m21(upnZ) - ._m22(dirZ) - ._m23(0.0f) - ._m30(-(leftX * eyeX + leftY * eyeY + leftZ * eyeZ)) - ._m31(-(upnX * eyeX + upnY * eyeY + upnZ * eyeZ)) - ._m32(-(dirX * eyeX + dirY * eyeY + dirZ * eyeZ)) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - - /** - * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, - * that aligns -z with center - eye and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a lookat transformation without post-multiplying it, - * use {@link #setLookAt(Vector3fc, Vector3fc, Vector3fc)}. - * - * @see #lookAt(float, float, float, float, float, float, float, float, float) - * @see #setLookAlong(Vector3fc, Vector3fc) - * - * @param eye - * the position of the camera - * @param center - * the point in space to look at - * @param up - * the direction of 'up' - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f lookAt(Vector3fc eye, Vector3fc center, Vector3fc up, Matrix4f dest) { - return lookAt(eye.x(), eye.y(), eye.z(), center.x(), center.y(), center.z(), up.x(), up.y(), up.z(), dest); - } - - /** - * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, - * that aligns -z with center - eye. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a lookat transformation without post-multiplying it, - * use {@link #setLookAt(Vector3fc, Vector3fc, Vector3fc)}. - * - * @see #lookAt(float, float, float, float, float, float, float, float, float) - * @see #setLookAlong(Vector3fc, Vector3fc) - * - * @param eye - * the position of the camera - * @param center - * the point in space to look at - * @param up - * the direction of 'up' - * @return this - */ - public Matrix4f lookAt(Vector3fc eye, Vector3fc center, Vector3fc up) { - return lookAt(eye.x(), eye.y(), eye.z(), center.x(), center.y(), center.z(), up.x(), up.y(), up.z(), this); - } - - /** - * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, - * that aligns -z with center - eye and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a lookat transformation without post-multiplying it, - * use {@link #setLookAt(float, float, float, float, float, float, float, float, float) setLookAt()}. - * - * @see #lookAt(Vector3fc, Vector3fc, Vector3fc) - * @see #setLookAt(float, float, float, float, float, float, float, float, float) - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f lookAt(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); - else if ((properties & PROPERTY_PERSPECTIVE) != 0) - return lookAtPerspective(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, dest); - return lookAtGeneric(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, dest); - } - private Matrix4f lookAtGeneric(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ, Matrix4f dest) { - // Compute direction from position to lookAt - float dirX, dirY, dirZ; - dirX = eyeX - centerX; - dirY = eyeY - centerY; - dirZ = eyeZ - centerZ; - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= invDirLength; - dirY *= invDirLength; - dirZ *= invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * dirZ - upZ * dirY; - leftY = upZ * dirX - upX * dirZ; - leftZ = upX * dirY - upY * dirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = dirY * leftZ - dirZ * leftY; - float upnY = dirZ * leftX - dirX * leftZ; - float upnZ = dirX * leftY - dirY * leftX; - - // calculate right matrix elements - float rm30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); - float rm31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); - float rm32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); - // introduce temporaries for dependent results - float nm00 = m00() * leftX + m10() * upnX + m20() * dirX; - float nm01 = m01() * leftX + m11() * upnX + m21() * dirX; - float nm02 = m02() * leftX + m12() * upnX + m22() * dirX; - float nm03 = m03() * leftX + m13() * upnX + m23() * dirX; - float nm10 = m00() * leftY + m10() * upnY + m20() * dirY; - float nm11 = m01() * leftY + m11() * upnY + m21() * dirY; - float nm12 = m02() * leftY + m12() * upnY + m22() * dirY; - float nm13 = m03() * leftY + m13() * upnY + m23() * dirY; - - // perform optimized matrix multiplication - // compute last column first, because others do not depend on it - return dest - ._m30(m00() * rm30 + m10() * rm31 + m20() * rm32 + m30()) - ._m31(m01() * rm30 + m11() * rm31 + m21() * rm32 + m31()) - ._m32(m02() * rm30 + m12() * rm31 + m22() * rm32 + m32()) - ._m33(m03() * rm30 + m13() * rm31 + m23() * rm32 + m33()) - ._m20(m00() * leftZ + m10() * upnZ + m20() * dirZ) - ._m21(m01() * leftZ + m11() * upnZ + m21() * dirZ) - ._m22(m02() * leftZ + m12() * upnZ + m22() * dirZ) - ._m23(m03() * leftZ + m13() * upnZ + m23() * dirZ) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, - * that aligns -z with center - eye and store the result in dest. - *

- * This method assumes this to be a perspective transformation, obtained via - * {@link #frustum(float, float, float, float, float, float) frustum()} or {@link #perspective(float, float, float, float) perspective()} or - * one of their overloads. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a lookat transformation without post-multiplying it, - * use {@link #setLookAt(float, float, float, float, float, float, float, float, float) setLookAt()}. - * - * @see #setLookAt(float, float, float, float, float, float, float, float, float) - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f lookAtPerspective(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ, Matrix4f dest) { - // Compute direction from position to lookAt - float dirX, dirY, dirZ; - dirX = eyeX - centerX; - dirY = eyeY - centerY; - dirZ = eyeZ - centerZ; - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= invDirLength; - dirY *= invDirLength; - dirZ *= invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * dirZ - upZ * dirY; - leftY = upZ * dirX - upX * dirZ; - leftZ = upX * dirY - upY * dirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = dirY * leftZ - dirZ * leftY; - float upnY = dirZ * leftX - dirX * leftZ; - float upnZ = dirX * leftY - dirY * leftX; - float rm30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); - float rm31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); - float rm32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); - float nm10 = m00() * leftY; - float nm20 = m00() * leftZ; - float nm21 = m11() * upnZ; - float nm30 = m00() * rm30; - float nm31 = m11() * rm31; - float nm32 = m22() * rm32 + m32(); - float nm33 = m23() * rm32; - return dest - ._m00(m00() * leftX) - ._m01(m11() * upnX) - ._m02(m22() * dirX) - ._m03(m23() * dirX) - ._m10(nm10) - ._m11(m11() * upnY) - ._m12(m22() * dirY) - ._m13(m23() * dirY) - ._m20(nm20) - ._m21(nm21) - ._m22(m22() * dirZ) - ._m23(m23() * dirZ) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(nm33) - ._properties(0); - } - - /** - * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, - * that aligns -z with center - eye. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a lookat transformation without post-multiplying it, - * use {@link #setLookAt(float, float, float, float, float, float, float, float, float) setLookAt()}. - * - * @see #lookAt(Vector3fc, Vector3fc, Vector3fc) - * @see #setLookAt(float, float, float, float, float, float, float, float, float) - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix4f lookAt(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - return lookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, this); - } - - /** - * Set this matrix to be a "lookat" transformation for a left-handed coordinate system, that aligns - * +z with center - eye. - *

- * In order to not make use of vectors to specify eye, center and up but use primitives, - * like in the GLU function, use {@link #setLookAtLH(float, float, float, float, float, float, float, float, float) setLookAtLH()} - * instead. - *

- * In order to apply the lookat transformation to a previous existing transformation, - * use {@link #lookAtLH(Vector3fc, Vector3fc, Vector3fc) lookAt()}. - * - * @see #setLookAtLH(float, float, float, float, float, float, float, float, float) - * @see #lookAtLH(Vector3fc, Vector3fc, Vector3fc) - * - * @param eye - * the position of the camera - * @param center - * the point in space to look at - * @param up - * the direction of 'up' - * @return this - */ - public Matrix4f setLookAtLH(Vector3fc eye, Vector3fc center, Vector3fc up) { - return setLookAtLH(eye.x(), eye.y(), eye.z(), center.x(), center.y(), center.z(), up.x(), up.y(), up.z()); - } - - /** - * Set this matrix to be a "lookat" transformation for a left-handed coordinate system, - * that aligns +z with center - eye. - *

- * In order to apply the lookat transformation to a previous existing transformation, - * use {@link #lookAtLH(float, float, float, float, float, float, float, float, float) lookAtLH}. - * - * @see #setLookAtLH(Vector3fc, Vector3fc, Vector3fc) - * @see #lookAtLH(float, float, float, float, float, float, float, float, float) - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix4f setLookAtLH(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - // Compute direction from position to lookAt - float dirX, dirY, dirZ; - dirX = centerX - eyeX; - dirY = centerY - eyeY; - dirZ = centerZ - eyeZ; - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= invDirLength; - dirY *= invDirLength; - dirZ *= invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * dirZ - upZ * dirY; - leftY = upZ * dirX - upX * dirZ; - leftZ = upX * dirY - upY * dirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = dirY * leftZ - dirZ * leftY; - float upnY = dirZ * leftX - dirX * leftZ; - float upnZ = dirX * leftY - dirY * leftX; - this._m00(leftX) - ._m01(upnX) - ._m02(dirX) - ._m03(0.0f) - ._m10(leftY) - ._m11(upnY) - ._m12(dirY) - ._m13(0.0f) - ._m20(leftZ) - ._m21(upnZ) - ._m22(dirZ) - ._m23(0.0f) - ._m30(-(leftX * eyeX + leftY * eyeY + leftZ * eyeZ)) - ._m31(-(upnX * eyeX + upnY * eyeY + upnZ * eyeZ)) - ._m32(-(dirX * eyeX + dirY * eyeY + dirZ * eyeZ)) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - /** - * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, - * that aligns +z with center - eye and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a lookat transformation without post-multiplying it, - * use {@link #setLookAtLH(Vector3fc, Vector3fc, Vector3fc)}. - * - * @see #lookAtLH(float, float, float, float, float, float, float, float, float) - * - * @param eye - * the position of the camera - * @param center - * the point in space to look at - * @param up - * the direction of 'up' - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f lookAtLH(Vector3fc eye, Vector3fc center, Vector3fc up, Matrix4f dest) { - return lookAtLH(eye.x(), eye.y(), eye.z(), center.x(), center.y(), center.z(), up.x(), up.y(), up.z(), dest); - } - - /** - * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, - * that aligns +z with center - eye. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a lookat transformation without post-multiplying it, - * use {@link #setLookAtLH(Vector3fc, Vector3fc, Vector3fc)}. - * - * @see #lookAtLH(float, float, float, float, float, float, float, float, float) - * - * @param eye - * the position of the camera - * @param center - * the point in space to look at - * @param up - * the direction of 'up' - * @return this - */ - public Matrix4f lookAtLH(Vector3fc eye, Vector3fc center, Vector3fc up) { - return lookAtLH(eye.x(), eye.y(), eye.z(), center.x(), center.y(), center.z(), up.x(), up.y(), up.z(), this); - } - - /** - * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, - * that aligns +z with center - eye and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a lookat transformation without post-multiplying it, - * use {@link #setLookAtLH(float, float, float, float, float, float, float, float, float) setLookAtLH()}. - * - * @see #lookAtLH(Vector3fc, Vector3fc, Vector3fc) - * @see #setLookAtLH(float, float, float, float, float, float, float, float, float) - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f lookAtLH(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setLookAtLH(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); - else if ((properties & PROPERTY_PERSPECTIVE) != 0) - return lookAtPerspectiveLH(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, dest); - return lookAtLHGeneric(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, dest); - } - private Matrix4f lookAtLHGeneric(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ, Matrix4f dest) { - // Compute direction from position to lookAt - float dirX, dirY, dirZ; - dirX = centerX - eyeX; - dirY = centerY - eyeY; - dirZ = centerZ - eyeZ; - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= invDirLength; - dirY *= invDirLength; - dirZ *= invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * dirZ - upZ * dirY; - leftY = upZ * dirX - upX * dirZ; - leftZ = upX * dirY - upY * dirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = dirY * leftZ - dirZ * leftY; - float upnY = dirZ * leftX - dirX * leftZ; - float upnZ = dirX * leftY - dirY * leftX; - - // calculate right matrix elements - float rm30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); - float rm31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); - float rm32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); - // introduce temporaries for dependent results - float nm00 = m00() * leftX + m10() * upnX + m20() * dirX; - float nm01 = m01() * leftX + m11() * upnX + m21() * dirX; - float nm02 = m02() * leftX + m12() * upnX + m22() * dirX; - float nm03 = m03() * leftX + m13() * upnX + m23() * dirX; - float nm10 = m00() * leftY + m10() * upnY + m20() * dirY; - float nm11 = m01() * leftY + m11() * upnY + m21() * dirY; - float nm12 = m02() * leftY + m12() * upnY + m22() * dirY; - float nm13 = m03() * leftY + m13() * upnY + m23() * dirY; - - // perform optimized matrix multiplication - // compute last column first, because others do not depend on it - return dest - ._m30(m00() * rm30 + m10() * rm31 + m20() * rm32 + m30()) - ._m31(m01() * rm30 + m11() * rm31 + m21() * rm32 + m31()) - ._m32(m02() * rm30 + m12() * rm31 + m22() * rm32 + m32()) - ._m33(m03() * rm30 + m13() * rm31 + m23() * rm32 + m33()) - ._m20(m00() * leftZ + m10() * upnZ + m20() * dirZ) - ._m21(m01() * leftZ + m11() * upnZ + m21() * dirZ) - ._m22(m02() * leftZ + m12() * upnZ + m22() * dirZ) - ._m23(m03() * leftZ + m13() * upnZ + m23() * dirZ) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, - * that aligns +z with center - eye. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a lookat transformation without post-multiplying it, - * use {@link #setLookAtLH(float, float, float, float, float, float, float, float, float) setLookAtLH()}. - * - * @see #lookAtLH(Vector3fc, Vector3fc, Vector3fc) - * @see #setLookAtLH(float, float, float, float, float, float, float, float, float) - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix4f lookAtLH(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - return lookAtLH(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, this); - } - - /** - * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, - * that aligns +z with center - eye and store the result in dest. - *

- * This method assumes this to be a perspective transformation, obtained via - * {@link #frustumLH(float, float, float, float, float, float) frustumLH()} or {@link #perspectiveLH(float, float, float, float) perspectiveLH()} or - * one of their overloads. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a lookat transformation without post-multiplying it, - * use {@link #setLookAtLH(float, float, float, float, float, float, float, float, float) setLookAtLH()}. - * - * @see #setLookAtLH(float, float, float, float, float, float, float, float, float) - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f lookAtPerspectiveLH(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ, Matrix4f dest) { - // Compute direction from position to lookAt - float dirX, dirY, dirZ; - dirX = centerX - eyeX; - dirY = centerY - eyeY; - dirZ = centerZ - eyeZ; - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= invDirLength; - dirY *= invDirLength; - dirZ *= invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * dirZ - upZ * dirY; - leftY = upZ * dirX - upX * dirZ; - leftZ = upX * dirY - upY * dirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = dirY * leftZ - dirZ * leftY; - float upnY = dirZ * leftX - dirX * leftZ; - float upnZ = dirX * leftY - dirY * leftX; - - // calculate right matrix elements - float rm30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); - float rm31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); - float rm32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); - - float nm00 = m00() * leftX; - float nm01 = m11() * upnX; - float nm02 = m22() * dirX; - float nm03 = m23() * dirX; - float nm10 = m00() * leftY; - float nm11 = m11() * upnY; - float nm12 = m22() * dirY; - float nm13 = m23() * dirY; - float nm20 = m00() * leftZ; - float nm21 = m11() * upnZ; - float nm22 = m22() * dirZ; - float nm23 = m23() * dirZ; - float nm30 = m00() * rm30; - float nm31 = m11() * rm31; - float nm32 = m22() * rm32 + m32(); - float nm33 = m23() * rm32; - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(nm33) - ._properties(0); - } - - /** - * This method is equivalent to calling: translate(w-1-2*x, h-1-2*y, 0).scale(w, h, 1) - *

- * If M is this matrix and T the created transformation matrix, - * then the new matrix will be M * T. So when transforming a - * vector v with the new matrix by using M * T * v, the - * created transformation will be applied first! - * - * @param x - * the tile's x coordinate/index (should be in [0..w)) - * @param y - * the tile's y coordinate/index (should be in [0..h)) - * @param w - * the number of tiles along the x axis - * @param h - * the number of tiles along the y axis - * @return this - */ - public Matrix4f tile(int x, int y, int w, int h) { - return tile(x, y, w, h, this); - } - public Matrix4f tile(int x, int y, int w, int h, Matrix4f dest) { - float tx = w - 1 - (x<<1), ty = h - 1 - (y<<1); - return dest - ._m30(Math.fma(m00(), tx, Math.fma(m10(), ty, m30()))) - ._m31(Math.fma(m01(), tx, Math.fma(m11(), ty, m31()))) - ._m32(Math.fma(m02(), tx, Math.fma(m12(), ty, m32()))) - ._m33(Math.fma(m03(), tx, Math.fma(m13(), ty, m33()))) - ._m00(m00() * w) - ._m01(m01() * w) - ._m02(m02() * w) - ._m03(m03() * w) - ._m10(m10() * h) - ._m11(m11() * h) - ._m12(m12() * h) - ._m13(m13() * h) - ._m20(m20()) - ._m21(m21()) - ._m22(m22()) - ._m23(m23()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - } - - /** - * Apply a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspective(float, float, float, float, boolean) setPerspective}. - * - * @see #setPerspective(float, float, float, float, boolean) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return dest - */ - public Matrix4f perspective(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setPerspective(fovy, aspect, zNear, zFar, zZeroToOne); - return perspectiveGeneric(fovy, aspect, zNear, zFar, zZeroToOne, dest); - } - private Matrix4f perspectiveGeneric(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - float h = Math.tan(fovy * 0.5f); - // calculate right matrix elements - float rm00 = 1.0f / (h * aspect); - float rm11 = 1.0f / h; - float rm22; - float rm32; - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - rm22 = e - 1.0f; - rm32 = (e - (zZeroToOne ? 1.0f : 2.0f)) * zNear; - } else if (nearInf) { - float e = 1E-6f; - rm22 = (zZeroToOne ? 0.0f : 1.0f) - e; - rm32 = ((zZeroToOne ? 1.0f : 2.0f) - e) * zFar; - } else { - rm22 = (zZeroToOne ? zFar : zFar + zNear) / (zNear - zFar); - rm32 = (zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar); - } - // perform optimized matrix multiplication - float nm20 = m20() * rm22 - m30(); - float nm21 = m21() * rm22 - m31(); - float nm22 = m22() * rm22 - m32(); - float nm23 = m23() * rm22 - m33(); - dest._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m30(m20() * rm32) - ._m31(m21() * rm32) - ._m32(m22() * rm32) - ._m33(m23() * rm32) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._properties(properties & ~(PROPERTY_AFFINE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - /** - * Apply a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspective(float, float, float, float) setPerspective}. - * - * @see #setPerspective(float, float, float, float) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f perspective(float fovy, float aspect, float zNear, float zFar, Matrix4f dest) { - return perspective(fovy, aspect, zNear, zFar, false, dest); - } - - /** - * Apply a symmetric perspective projection frustum transformation using for a right-handed coordinate system - * using the given NDC z range to this matrix. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspective(float, float, float, float, boolean) setPerspective}. - * - * @see #setPerspective(float, float, float, float, boolean) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f perspective(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne) { - return perspective(fovy, aspect, zNear, zFar, zZeroToOne, this); - } - - /** - * Apply a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspective(float, float, float, float) setPerspective}. - * - * @see #setPerspective(float, float, float, float) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f perspective(float fovy, float aspect, float zNear, float zFar) { - return perspective(fovy, aspect, zNear, zFar, this); - } - - /** - * Apply a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveRect(float, float, float, float, boolean) setPerspectiveRect}. - * - * @see #setPerspectiveRect(float, float, float, float, boolean) - * - * @param width - * the width of the near frustum plane - * @param height - * the height of the near frustum plane - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return dest - */ - public Matrix4f perspectiveRect(float width, float height, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setPerspectiveRect(width, height, zNear, zFar, zZeroToOne); - return perspectiveRectGeneric(width, height, zNear, zFar, zZeroToOne, dest); - } - private Matrix4f perspectiveRectGeneric(float width, float height, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - float rm00 = (zNear + zNear) / width; - float rm11 = (zNear + zNear) / height; - float rm22, rm32; - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - rm22 = e - 1.0f; - rm32 = (e - (zZeroToOne ? 1.0f : 2.0f)) * zNear; - } else if (nearInf) { - float e = 1E-6f; - rm22 = (zZeroToOne ? 0.0f : 1.0f) - e; - rm32 = ((zZeroToOne ? 1.0f : 2.0f) - e) * zFar; - } else { - rm22 = (zZeroToOne ? zFar : zFar + zNear) / (zNear - zFar); - rm32 = (zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar); - } - // perform optimized matrix multiplication - float nm20 = m20() * rm22 - m30(); - float nm21 = m21() * rm22 - m31(); - float nm22 = m22() * rm22 - m32(); - float nm23 = m23() * rm22 - m33(); - dest._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m30(m20() * rm32) - ._m31(m21() * rm32) - ._m32(m22() * rm32) - ._m33(m23() * rm32) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._properties(properties & ~(PROPERTY_AFFINE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - /** - * Apply a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveRect(float, float, float, float) setPerspectiveRect}. - * - * @see #setPerspectiveRect(float, float, float, float) - * - * @param width - * the width of the near frustum plane - * @param height - * the height of the near frustum plane - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f perspectiveRect(float width, float height, float zNear, float zFar, Matrix4f dest) { - return perspectiveRect(width, height, zNear, zFar, false, dest); - } - - /** - * Apply a symmetric perspective projection frustum transformation using for a right-handed coordinate system - * using the given NDC z range to this matrix. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveRect(float, float, float, float, boolean) setPerspectiveRect}. - * - * @see #setPerspectiveRect(float, float, float, float, boolean) - * - * @param width - * the width of the near frustum plane - * @param height - * the height of the near frustum plane - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f perspectiveRect(float width, float height, float zNear, float zFar, boolean zZeroToOne) { - return perspectiveRect(width, height, zNear, zFar, zZeroToOne, this); - } - - /** - * Apply a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveRect(float, float, float, float) setPerspectiveRect}. - * - * @see #setPerspectiveRect(float, float, float, float) - * - * @param width - * the width of the near frustum plane - * @param height - * the height of the near frustum plane - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f perspectiveRect(float width, float height, float zNear, float zFar) { - return perspectiveRect(width, height, zNear, zFar, this); - } - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * The given angles offAngleX and offAngleY are the horizontal and vertical angles between - * the line of sight and the line given by the center of the near and far frustum planes. So, when offAngleY - * is just fovy/2 then the projection frustum is rotated towards +Y and the bottom frustum plane - * is parallel to the XZ-plane. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveOffCenter(float, float, float, float, float, float, boolean) setPerspectiveOffCenter}. - * - * @see #setPerspectiveOffCenter(float, float, float, float, float, float, boolean) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param offAngleX - * the horizontal angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param offAngleY - * the vertical angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return dest - */ - public Matrix4f perspectiveOffCenter(float fovy, float offAngleX, float offAngleY, float aspect, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setPerspectiveOffCenter(fovy, offAngleX, offAngleY, aspect, zNear, zFar, zZeroToOne); - return perspectiveOffCenterGeneric(fovy, offAngleX, offAngleY, aspect, zNear, zFar, zZeroToOne, dest); - } - private Matrix4f perspectiveOffCenterGeneric(float fovy, float offAngleX, float offAngleY, float aspect, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - float h = Math.tan(fovy * 0.5f); - // calculate right matrix elements - float xScale = 1.0f / (h * aspect); - float yScale = 1.0f / h; - float offX = Math.tan(offAngleX), offY = Math.tan(offAngleY); - float rm20 = offX * xScale; - float rm21 = offY * yScale; - float rm22; - float rm32; - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - rm22 = e - 1.0f; - rm32 = (e - (zZeroToOne ? 1.0f : 2.0f)) * zNear; - } else if (nearInf) { - float e = 1E-6f; - rm22 = (zZeroToOne ? 0.0f : 1.0f) - e; - rm32 = ((zZeroToOne ? 1.0f : 2.0f) - e) * zFar; - } else { - rm22 = (zZeroToOne ? zFar : zFar + zNear) / (zNear - zFar); - rm32 = (zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar); - } - // perform optimized matrix multiplication - float nm20 = m00() * rm20 + m10() * rm21 + m20() * rm22 - m30(); - float nm21 = m01() * rm20 + m11() * rm21 + m21() * rm22 - m31(); - float nm22 = m02() * rm20 + m12() * rm21 + m22() * rm22 - m32(); - float nm23 = m03() * rm20 + m13() * rm21 + m23() * rm22 - m33(); - dest._m00(m00() * xScale) - ._m01(m01() * xScale) - ._m02(m02() * xScale) - ._m03(m03() * xScale) - ._m10(m10() * yScale) - ._m11(m11() * yScale) - ._m12(m12() * yScale) - ._m13(m13() * yScale) - ._m30(m20() * rm32) - ._m31(m21() * rm32) - ._m32(m22() * rm32) - ._m33(m23() * rm32) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._properties(properties & ~(PROPERTY_AFFINE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION - | PROPERTY_ORTHONORMAL | (rm20 == 0.0f && rm21 == 0.0f ? 0 : PROPERTY_PERSPECTIVE))); - return dest; - } - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * The given angles offAngleX and offAngleY are the horizontal and vertical angles between - * the line of sight and the line given by the center of the near and far frustum planes. So, when offAngleY - * is just fovy/2 then the projection frustum is rotated towards +Y and the bottom frustum plane - * is parallel to the XZ-plane. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveOffCenter(float, float, float, float, float, float) setPerspectiveOffCenter}. - * - * @see #setPerspectiveOffCenter(float, float, float, float, float, float) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param offAngleX - * the horizontal angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param offAngleY - * the vertical angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f perspectiveOffCenter(float fovy, float offAngleX, float offAngleY, float aspect, float zNear, float zFar, Matrix4f dest) { - return perspectiveOffCenter(fovy, offAngleX, offAngleY, aspect, zNear, zFar, false, dest); - } - - /** - * Apply an asymmetric off-center perspective projection frustum transformation using for a right-handed coordinate system - * using the given NDC z range to this matrix. - *

- * The given angles offAngleX and offAngleY are the horizontal and vertical angles between - * the line of sight and the line given by the center of the near and far frustum planes. So, when offAngleY - * is just fovy/2 then the projection frustum is rotated towards +Y and the bottom frustum plane - * is parallel to the XZ-plane. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveOffCenter(float, float, float, float, float, float, boolean) setPerspectiveOffCenter}. - * - * @see #setPerspectiveOffCenter(float, float, float, float, float, float, boolean) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param offAngleX - * the horizontal angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param offAngleY - * the vertical angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f perspectiveOffCenter(float fovy, float offAngleX, float offAngleY, float aspect, float zNear, float zFar, boolean zZeroToOne) { - return perspectiveOffCenter(fovy, offAngleX, offAngleY, aspect, zNear, zFar, zZeroToOne, this); - } - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * The given angles offAngleX and offAngleY are the horizontal and vertical angles between - * the line of sight and the line given by the center of the near and far frustum planes. So, when offAngleY - * is just fovy/2 then the projection frustum is rotated towards +Y and the bottom frustum plane - * is parallel to the XZ-plane. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveOffCenter(float, float, float, float, float, float) setPerspectiveOffCenter}. - * - * @see #setPerspectiveOffCenter(float, float, float, float, float, float) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param offAngleX - * the horizontal angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param offAngleY - * the vertical angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f perspectiveOffCenter(float fovy, float offAngleX, float offAngleY, float aspect, float zNear, float zFar) { - return perspectiveOffCenter(fovy, offAngleX, offAngleY, aspect, zNear, zFar, this); - } - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveOffCenterFov(float, float, float, float, float, float, boolean) setPerspectiveOffCenterFov}. - * - * @see #setPerspectiveOffCenterFov(float, float, float, float, float, float, boolean) - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f perspectiveOffCenterFov(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, boolean zZeroToOne) { - return perspectiveOffCenterFov(angleLeft, angleRight, angleDown, angleUp, zNear, zFar, zZeroToOne, this); - } - public Matrix4f perspectiveOffCenterFov(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - return frustum(Math.tan(angleLeft)*zNear, Math.tan(angleRight)*zNear, Math.tan(angleDown)*zNear, Math.tan(angleUp)*zNear, zNear, zFar, zZeroToOne, dest); - } - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveOffCenterFov(float, float, float, float, float, float) setPerspectiveOffCenterFov}. - * - * @see #setPerspectiveOffCenterFov(float, float, float, float, float, float) - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f perspectiveOffCenterFov(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar) { - return perspectiveOffCenterFov(angleLeft, angleRight, angleDown, angleUp, zNear, zFar, this); - } - public Matrix4f perspectiveOffCenterFov(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, Matrix4f dest) { - return frustum(Math.tan(angleLeft)*zNear, Math.tan(angleRight)*zNear, Math.tan(angleDown)*zNear, Math.tan(angleUp)*zNear, zNear, zFar, dest); - } - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range to this matrix. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveOffCenterFovLH(float, float, float, float, float, float, boolean) setPerspectiveOffCenterFovLH}. - * - * @see #setPerspectiveOffCenterFovLH(float, float, float, float, float, float, boolean) - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f perspectiveOffCenterFovLH(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, boolean zZeroToOne) { - return perspectiveOffCenterFovLH(angleLeft, angleRight, angleDown, angleUp, zNear, zFar, zZeroToOne, this); - } - public Matrix4f perspectiveOffCenterFovLH(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - return frustumLH(Math.tan(angleLeft)*zNear, Math.tan(angleRight)*zNear, Math.tan(angleDown)*zNear, Math.tan(angleUp)*zNear, zNear, zFar, zZeroToOne, dest); - } - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveOffCenterFovLH(float, float, float, float, float, float) setPerspectiveOffCenterFovLH}. - * - * @see #setPerspectiveOffCenterFovLH(float, float, float, float, float, float) - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f perspectiveOffCenterFovLH(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar) { - return perspectiveOffCenterFovLH(angleLeft, angleRight, angleDown, angleUp, zNear, zFar, this); - } - public Matrix4f perspectiveOffCenterFovLH(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, Matrix4f dest) { - return frustumLH(Math.tan(angleLeft)*zNear, Math.tan(angleRight)*zNear, Math.tan(angleDown)*zNear, Math.tan(angleUp)*zNear, zNear, zFar, dest); - } - - /** - * Set this matrix to be a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspective(float, float, float, float, boolean) perspective()}. - * - * @see #perspective(float, float, float, float, boolean) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setPerspective(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne) { - MemUtil.INSTANCE.zero(this); - float h = Math.tan(fovy * 0.5f); - this._m00(1.0f / (h * aspect)) - ._m11(1.0f / h); - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - this._m22(e - 1.0f) - ._m32((e - (zZeroToOne ? 1.0f : 2.0f)) * zNear); - } else if (nearInf) { - float e = 1E-6f; - this._m22((zZeroToOne ? 0.0f : 1.0f) - e) - ._m32(((zZeroToOne ? 1.0f : 2.0f) - e) * zFar); - } else { - this._m22((zZeroToOne ? zFar : zFar + zNear) / (zNear - zFar)) - ._m32((zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar)); - } - return this - ._m23(-1.0f) - ._properties(PROPERTY_PERSPECTIVE); - } - - /** - * Set this matrix to be a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1]. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspective(float, float, float, float) perspective()}. - * - * @see #perspective(float, float, float, float) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f setPerspective(float fovy, float aspect, float zNear, float zFar) { - return setPerspective(fovy, aspect, zNear, zFar, false); - } - - /** - * Set this matrix to be a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspectiveRect(float, float, float, float, boolean) perspectiveRect()}. - * - * @see #perspectiveRect(float, float, float, float, boolean) - * - * @param width - * the width of the near frustum plane - * @param height - * the height of the near frustum plane - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setPerspectiveRect(float width, float height, float zNear, float zFar, boolean zZeroToOne) { - MemUtil.INSTANCE.zero(this); - this._m00((zNear + zNear) / width) - ._m11((zNear + zNear) / height); - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - this._m22(e - 1.0f) - ._m32((e - (zZeroToOne ? 1.0f : 2.0f)) * zNear); - } else if (nearInf) { - float e = 1E-6f; - this._m22((zZeroToOne ? 0.0f : 1.0f) - e) - ._m32(((zZeroToOne ? 1.0f : 2.0f) - e) * zFar); - } else { - this._m22((zZeroToOne ? zFar : zFar + zNear) / (zNear - zFar)) - ._m32((zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar)); - } - this._m23(-1.0f) - ._properties(PROPERTY_PERSPECTIVE); - return this; - } - - /** - * Set this matrix to be a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1]. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspectiveRect(float, float, float, float) perspectiveRect()}. - * - * @see #perspectiveRect(float, float, float, float) - * - * @param width - * the width of the near frustum plane - * @param height - * the height of the near frustum plane - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f setPerspectiveRect(float width, float height, float zNear, float zFar) { - return setPerspectiveRect(width, height, zNear, zFar, false); - } - - /** - * Set this matrix to be an asymmetric off-center perspective projection frustum transformation for a right-handed - * coordinate system using OpenGL's NDC z range of [-1..+1]. - *

- * The given angles offAngleX and offAngleY are the horizontal and vertical angles between - * the line of sight and the line given by the center of the near and far frustum planes. So, when offAngleY - * is just fovy/2 then the projection frustum is rotated towards +Y and the bottom frustum plane - * is parallel to the XZ-plane. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspectiveOffCenter(float, float, float, float, float, float) perspectiveOffCenter()}. - * - * @see #perspectiveOffCenter(float, float, float, float, float, float) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param offAngleX - * the horizontal angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param offAngleY - * the vertical angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f setPerspectiveOffCenter(float fovy, float offAngleX, float offAngleY, - float aspect, float zNear, float zFar) { - return setPerspectiveOffCenter(fovy, offAngleX, offAngleY, aspect, zNear, zFar, false); - } - /** - * Set this matrix to be an asymmetric off-center perspective projection frustum transformation for a right-handed - * coordinate system using the given NDC z range. - *

- * The given angles offAngleX and offAngleY are the horizontal and vertical angles between - * the line of sight and the line given by the center of the near and far frustum planes. So, when offAngleY - * is just fovy/2 then the projection frustum is rotated towards +Y and the bottom frustum plane - * is parallel to the XZ-plane. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspectiveOffCenter(float, float, float, float, float, float) perspectiveOffCenter()}. - * - * @see #perspectiveOffCenter(float, float, float, float, float, float) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param offAngleX - * the horizontal angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param offAngleY - * the vertical angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setPerspectiveOffCenter(float fovy, float offAngleX, float offAngleY, - float aspect, float zNear, float zFar, boolean zZeroToOne) { - MemUtil.INSTANCE.zero(this); - float h = Math.tan(fovy * 0.5f); - float xScale = 1.0f / (h * aspect), yScale = 1.0f / h; - float offX = Math.tan(offAngleX), offY = Math.tan(offAngleY); - this._m00(xScale) - ._m11(yScale) - ._m20(offX * xScale) - ._m21(offY * yScale); - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - this._m22(e - 1.0f) - ._m32((e - (zZeroToOne ? 1.0f : 2.0f)) * zNear); - } else if (nearInf) { - float e = 1E-6f; - this._m22((zZeroToOne ? 0.0f : 1.0f) - e) - ._m32(((zZeroToOne ? 1.0f : 2.0f) - e) * zFar); - } else { - this._m22((zZeroToOne ? zFar : zFar + zNear) / (zNear - zFar)) - ._m32((zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar)); - } - this._m23(-1.0f) - ._properties(offAngleX == 0.0f && offAngleY == 0.0f ? PROPERTY_PERSPECTIVE : 0); - return this; - } - - /** - * Set this matrix to be an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate - * system using OpenGL's NDC z range of [-1..+1]. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspectiveOffCenterFov(float, float, float, float, float, float) perspectiveOffCenterFov()}. - * - * @see #perspectiveOffCenterFov(float, float, float, float, float, float) - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f setPerspectiveOffCenterFov(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar) { - return setPerspectiveOffCenterFov(angleLeft, angleRight, angleDown, angleUp, zNear, zFar, false); - } - /** - * Set this matrix to be an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspectiveOffCenterFov(float, float, float, float, float, float, boolean) perspectiveOffCenterFov()}. - * - * @see #perspectiveOffCenterFov(float, float, float, float, float, float, boolean) - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setPerspectiveOffCenterFov(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, boolean zZeroToOne) { - return setFrustum(Math.tan(angleLeft)*zNear, Math.tan(angleRight)*zNear, Math.tan(angleDown)*zNear, Math.tan(angleUp)*zNear, zNear, zFar, zZeroToOne); - } - - /** - * Set this matrix to be an asymmetric off-center perspective projection frustum transformation for a left-handed coordinate - * system using OpenGL's NDC z range of [-1..+1]. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspectiveOffCenterFovLH(float, float, float, float, float, float) perspectiveOffCenterFovLH()}. - * - * @see #perspectiveOffCenterFovLH(float, float, float, float, float, float) - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f setPerspectiveOffCenterFovLH(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar) { - return setPerspectiveOffCenterFovLH(angleLeft, angleRight, angleDown, angleUp, zNear, zFar, false); - } - /** - * Set this matrix to be an asymmetric off-center perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspectiveOffCenterFovLH(float, float, float, float, float, float, boolean) perspectiveOffCenterFovLH()}. - * - * @see #perspectiveOffCenterFovLH(float, float, float, float, float, float, boolean) - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setPerspectiveOffCenterFovLH(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, boolean zZeroToOne) { - return setFrustumLH(Math.tan(angleLeft)*zNear, Math.tan(angleRight)*zNear, Math.tan(angleDown)*zNear, Math.tan(angleUp)*zNear, zNear, zFar, zZeroToOne); - } - - /** - * Apply a symmetric perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveLH(float, float, float, float, boolean) setPerspectiveLH}. - * - * @see #setPerspectiveLH(float, float, float, float, boolean) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f perspectiveLH(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setPerspectiveLH(fovy, aspect, zNear, zFar, zZeroToOne); - return perspectiveLHGeneric(fovy, aspect, zNear, zFar, zZeroToOne, dest); - } - private Matrix4f perspectiveLHGeneric(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - float h = Math.tan(fovy * 0.5f); - // calculate right matrix elements - float rm00 = 1.0f / (h * aspect); - float rm11 = 1.0f / h; - float rm22; - float rm32; - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - rm22 = 1.0f - e; - rm32 = (e - (zZeroToOne ? 1.0f : 2.0f)) * zNear; - } else if (nearInf) { - float e = 1E-6f; - rm22 = (zZeroToOne ? 0.0f : 1.0f) - e; - rm32 = ((zZeroToOne ? 1.0f : 2.0f) - e) * zFar; - } else { - rm22 = (zZeroToOne ? zFar : zFar + zNear) / (zFar - zNear); - rm32 = (zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar); - } - // perform optimized matrix multiplication - float nm20 = m20() * rm22 + m30(); - float nm21 = m21() * rm22 + m31(); - float nm22 = m22() * rm22 + m32(); - float nm23 = m23() * rm22 + m33(); - dest._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m30(m20() * rm32) - ._m31(m21() * rm32) - ._m32(m22() * rm32) - ._m33(m23() * rm32) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._properties(properties & ~(PROPERTY_AFFINE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - /** - * Apply a symmetric perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range to this matrix. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveLH(float, float, float, float, boolean) setPerspectiveLH}. - * - * @see #setPerspectiveLH(float, float, float, float, boolean) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f perspectiveLH(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne) { - return perspectiveLH(fovy, aspect, zNear, zFar, zZeroToOne, this); - } - - /** - * Apply a symmetric perspective projection frustum transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveLH(float, float, float, float) setPerspectiveLH}. - * - * @see #setPerspectiveLH(float, float, float, float) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f perspectiveLH(float fovy, float aspect, float zNear, float zFar, Matrix4f dest) { - return perspectiveLH(fovy, aspect, zNear, zFar, false, dest); - } - - /** - * Apply a symmetric perspective projection frustum transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setPerspectiveLH(float, float, float, float) setPerspectiveLH}. - * - * @see #setPerspectiveLH(float, float, float, float) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f perspectiveLH(float fovy, float aspect, float zNear, float zFar) { - return perspectiveLH(fovy, aspect, zNear, zFar, this); - } - - /** - * Set this matrix to be a symmetric perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range of [-1..+1]. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspectiveLH(float, float, float, float, boolean) perspectiveLH()}. - * - * @see #perspectiveLH(float, float, float, float, boolean) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setPerspectiveLH(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne) { - MemUtil.INSTANCE.zero(this); - float h = Math.tan(fovy * 0.5f); - this._m00(1.0f / (h * aspect)) - ._m11(1.0f / h); - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - this._m22(1.0f - e) - ._m32((e - (zZeroToOne ? 1.0f : 2.0f)) * zNear); - } else if (nearInf) { - float e = 1E-6f; - this._m22((zZeroToOne ? 0.0f : 1.0f) - e) - ._m32(((zZeroToOne ? 1.0f : 2.0f) - e) * zFar); - } else { - this._m22((zZeroToOne ? zFar : zFar + zNear) / (zFar - zNear)) - ._m32((zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar)); - } - this._m23(1.0f) - ._properties(PROPERTY_PERSPECTIVE); - return this; - } - - /** - * Set this matrix to be a symmetric perspective projection frustum transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1]. - *

- * In order to apply the perspective projection transformation to an existing transformation, - * use {@link #perspectiveLH(float, float, float, float) perspectiveLH()}. - * - * @see #perspectiveLH(float, float, float, float) - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f setPerspectiveLH(float fovy, float aspect, float zNear, float zFar) { - return setPerspectiveLH(fovy, aspect, zNear, zFar, false); - } - - /** - * Apply an arbitrary perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setFrustum(float, float, float, float, float, float, boolean) setFrustum()}. - *

- * Reference: http://www.songho.ca - * - * @see #setFrustum(float, float, float, float, float, float, boolean) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f frustum(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setFrustum(left, right, bottom, top, zNear, zFar, zZeroToOne); - return frustumGeneric(left, right, bottom, top, zNear, zFar, zZeroToOne, dest); - } - private Matrix4f frustumGeneric(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - // calculate right matrix elements - float rm00 = (zNear + zNear) / (right - left); - float rm11 = (zNear + zNear) / (top - bottom); - float rm20 = (right + left) / (right - left); - float rm21 = (top + bottom) / (top - bottom); - float rm22; - float rm32; - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - rm22 = e - 1.0f; - rm32 = (e - (zZeroToOne ? 1.0f : 2.0f)) * zNear; - } else if (nearInf) { - float e = 1E-6f; - rm22 = (zZeroToOne ? 0.0f : 1.0f) - e; - rm32 = ((zZeroToOne ? 1.0f : 2.0f) - e) * zFar; - } else { - rm22 = (zZeroToOne ? zFar : zFar + zNear) / (zNear - zFar); - rm32 = (zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar); - } - // perform optimized matrix multiplication - float nm20 = m00() * rm20 + m10() * rm21 + m20() * rm22 - m30(); - float nm21 = m01() * rm20 + m11() * rm21 + m21() * rm22 - m31(); - float nm22 = m02() * rm20 + m12() * rm21 + m22() * rm22 - m32(); - float nm23 = m03() * rm20 + m13() * rm21 + m23() * rm22 - m33(); - dest._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m30(m20() * rm32) - ._m31(m21() * rm32) - ._m32(m22() * rm32) - ._m33(m23() * rm32) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._properties(0); - return dest; - } - - /** - * Apply an arbitrary perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setFrustum(float, float, float, float, float, float) setFrustum()}. - *

- * Reference: http://www.songho.ca - * - * @see #setFrustum(float, float, float, float, float, float) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f frustum(float left, float right, float bottom, float top, float zNear, float zFar, Matrix4f dest) { - return frustum(left, right, bottom, top, zNear, zFar, false, dest); - } - - /** - * Apply an arbitrary perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setFrustum(float, float, float, float, float, float, boolean) setFrustum()}. - *

- * Reference: http://www.songho.ca - * - * @see #setFrustum(float, float, float, float, float, float, boolean) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f frustum(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne) { - return frustum(left, right, bottom, top, zNear, zFar, zZeroToOne, this); - } - - /** - * Apply an arbitrary perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setFrustum(float, float, float, float, float, float) setFrustum()}. - *

- * Reference: http://www.songho.ca - * - * @see #setFrustum(float, float, float, float, float, float) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f frustum(float left, float right, float bottom, float top, float zNear, float zFar) { - return frustum(left, right, bottom, top, zNear, zFar, this); - } - - /** - * Set this matrix to be an arbitrary perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range. - *

- * In order to apply the perspective frustum transformation to an existing transformation, - * use {@link #frustum(float, float, float, float, float, float, boolean) frustum()}. - *

- * Reference: http://www.songho.ca - * - * @see #frustum(float, float, float, float, float, float, boolean) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setFrustum(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m00((zNear + zNear) / (right - left)) - ._m11((zNear + zNear) / (top - bottom)) - ._m20((right + left) / (right - left)) - ._m21((top + bottom) / (top - bottom)); - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - this._m22(e - 1.0f) - ._m32((e - (zZeroToOne ? 1.0f : 2.0f)) * zNear); - } else if (nearInf) { - float e = 1E-6f; - this._m22((zZeroToOne ? 0.0f : 1.0f) - e) - ._m32(((zZeroToOne ? 1.0f : 2.0f) - e) * zFar); - } else { - this._m22((zZeroToOne ? zFar : zFar + zNear) / (zNear - zFar)) - ._m32((zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar)); - } - this._m23(-1.0f) - ._m33(0.0f) - ._properties(this.m20() == 0.0f && this.m21() == 0.0f ? PROPERTY_PERSPECTIVE : 0); - return this; - } - - /** - * Set this matrix to be an arbitrary perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1]. - *

- * In order to apply the perspective frustum transformation to an existing transformation, - * use {@link #frustum(float, float, float, float, float, float) frustum()}. - *

- * Reference: http://www.songho.ca - * - * @see #frustum(float, float, float, float, float, float) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f setFrustum(float left, float right, float bottom, float top, float zNear, float zFar) { - return setFrustum(left, right, bottom, top, zNear, zFar, false); - } - - /** - * Apply an arbitrary perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setFrustumLH(float, float, float, float, float, float, boolean) setFrustumLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setFrustumLH(float, float, float, float, float, float, boolean) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f frustumLH(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.setFrustumLH(left, right, bottom, top, zNear, zFar, zZeroToOne); - return frustumLHGeneric(left, right, bottom, top, zNear, zFar, zZeroToOne, dest); - } - private Matrix4f frustumLHGeneric(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest) { - // calculate right matrix elements - float rm00 = (zNear + zNear) / (right - left); - float rm11 = (zNear + zNear) / (top - bottom); - float rm20 = (right + left) / (right - left); - float rm21 = (top + bottom) / (top - bottom); - float rm22; - float rm32; - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - rm22 = 1.0f - e; - rm32 = (e - (zZeroToOne ? 1.0f : 2.0f)) * zNear; - } else if (nearInf) { - float e = 1E-6f; - rm22 = (zZeroToOne ? 0.0f : 1.0f) - e; - rm32 = ((zZeroToOne ? 1.0f : 2.0f) - e) * zFar; - } else { - rm22 = (zZeroToOne ? zFar : zFar + zNear) / (zFar - zNear); - rm32 = (zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar); - } - // perform optimized matrix multiplication - float nm20 = m00() * rm20 + m10() * rm21 + m20() * rm22 + m30(); - float nm21 = m01() * rm20 + m11() * rm21 + m21() * rm22 + m31(); - float nm22 = m02() * rm20 + m12() * rm21 + m22() * rm22 + m32(); - float nm23 = m03() * rm20 + m13() * rm21 + m23() * rm22 + m33(); - dest._m00(m00() * rm00) - ._m01(m01() * rm00) - ._m02(m02() * rm00) - ._m03(m03() * rm00) - ._m10(m10() * rm11) - ._m11(m11() * rm11) - ._m12(m12() * rm11) - ._m13(m13() * rm11) - ._m30(m20() * rm32) - ._m31(m21() * rm32) - ._m32(m22() * rm32) - ._m33(m23() * rm32) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._properties(0); - return dest; - } - - /** - * Apply an arbitrary perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range to this matrix. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setFrustumLH(float, float, float, float, float, float, boolean) setFrustumLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setFrustumLH(float, float, float, float, float, float, boolean) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f frustumLH(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne) { - return frustumLH(left, right, bottom, top, zNear, zFar, zZeroToOne, this); - } - - /** - * Apply an arbitrary perspective projection frustum transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setFrustumLH(float, float, float, float, float, float) setFrustumLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setFrustumLH(float, float, float, float, float, float) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f frustumLH(float left, float right, float bottom, float top, float zNear, float zFar, Matrix4f dest) { - return frustumLH(left, right, bottom, top, zNear, zFar, false, dest); - } - - /** - * Apply an arbitrary perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range to this matrix. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * In order to set the matrix to a perspective frustum transformation without post-multiplying, - * use {@link #setFrustumLH(float, float, float, float, float, float) setFrustumLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #setFrustumLH(float, float, float, float, float, float) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f frustumLH(float left, float right, float bottom, float top, float zNear, float zFar) { - return frustumLH(left, right, bottom, top, zNear, zFar, this); - } - - /** - * Set this matrix to be an arbitrary perspective projection frustum transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1]. - *

- * In order to apply the perspective frustum transformation to an existing transformation, - * use {@link #frustumLH(float, float, float, float, float, float, boolean) frustumLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #frustumLH(float, float, float, float, float, float, boolean) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return this - */ - public Matrix4f setFrustumLH(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne) { - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m00((zNear + zNear) / (right - left)) - ._m11((zNear + zNear) / (top - bottom)) - ._m20((right + left) / (right - left)) - ._m21((top + bottom) / (top - bottom)); - boolean farInf = zFar > 0 && Float.isInfinite(zFar); - boolean nearInf = zNear > 0 && Float.isInfinite(zNear); - if (farInf) { - // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf) - float e = 1E-6f; - this._m22(1.0f - e) - ._m32((e - (zZeroToOne ? 1.0f : 2.0f)) * zNear); - } else if (nearInf) { - float e = 1E-6f; - this._m22((zZeroToOne ? 0.0f : 1.0f) - e) - ._m32(((zZeroToOne ? 1.0f : 2.0f) - e) * zFar); - } else { - this._m22((zZeroToOne ? zFar : zFar + zNear) / (zFar - zNear)) - ._m32((zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar)); - } - return this - ._m23(1.0f) - ._m33(0.0f) - ._properties(0); - } - - /** - * Set this matrix to be an arbitrary perspective projection frustum transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1]. - *

- * In order to apply the perspective frustum transformation to an existing transformation, - * use {@link #frustumLH(float, float, float, float, float, float) frustumLH()}. - *

- * Reference: http://www.songho.ca - * - * @see #frustumLH(float, float, float, float, float, float) - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @return this - */ - public Matrix4f setFrustumLH(float left, float right, float bottom, float top, float zNear, float zFar) { - return setFrustumLH(left, right, bottom, top, zNear, zFar, false); - } - - /** - * Set this matrix to represent a perspective projection equivalent to the given intrinsic camera calibration parameters. - * The resulting matrix will be suited for a right-handed coordinate system using OpenGL's NDC z range of [-1..+1]. - *

- * See: https://en.wikipedia.org/ - *

- * Reference: http://ksimek.github.io/ - * - * @param alphaX - * specifies the focal length and scale along the X axis - * @param alphaY - * specifies the focal length and scale along the Y axis - * @param gamma - * the skew coefficient between the X and Y axis (may be 0) - * @param u0 - * the X coordinate of the principal point in image/sensor units - * @param v0 - * the Y coordinate of the principal point in image/sensor units - * @param imgWidth - * the width of the sensor/image image/sensor units - * @param imgHeight - * the height of the sensor/image image/sensor units - * @param near - * the distance to the near plane - * @param far - * the distance to the far plane - * @return this - */ - public Matrix4f setFromIntrinsic(float alphaX, float alphaY, float gamma, float u0, float v0, int imgWidth, int imgHeight, float near, float far) { - float l00 = 2.0f / imgWidth; - float l11 = 2.0f / imgHeight; - float l22 = 2.0f / (near - far); - return this - ._m00(l00 * alphaX) - ._m01(0.0f) - ._m02(0.0f) - ._m03(0.0f) - ._m10(l00 * gamma) - ._m11(l11 * alphaY) - ._m12(0.0f) - ._m13(0.0f) - ._m20(l00 * u0 - 1.0f) - ._m21(l11 * v0 - 1.0f) - ._m22(l22 * -(near + far) + (far + near) / (near - far)) - ._m23(-1.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(l22 * -near * far) - ._m33(0.0f) - ._properties(PROPERTY_PERSPECTIVE); - } - - /** - * Apply the rotation transformation of the given {@link Quaternionfc} to this matrix and store - * the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotate(Quaternionfc quat, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.rotation(quat); - else if ((properties & PROPERTY_TRANSLATION) != 0) - return rotateTranslation(quat, dest); - else if ((properties & PROPERTY_AFFINE) != 0) - return rotateAffine(quat, dest); - return rotateGeneric(quat, dest); - } - private Matrix4f rotateGeneric(Quaternionfc quat, Matrix4f dest) { - float w2 = quat.w() * quat.w(), x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(), z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw, xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz, yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz, xw = quat.x() * quat.w(), dxw = xw + xw; - float rm00 = w2 + x2 - z2 - y2; - float rm01 = dxy + dzw; - float rm02 = dxz - dyw; - float rm10 = -dzw + dxy; - float rm11 = y2 - z2 + w2 - x2; - float rm12 = dyz + dxw; - float rm20 = dyw + dxz; - float rm21 = dyz - dxw; - float rm22 = z2 - y2 - x2 + w2; - float nm00 = m00() * rm00 + m10() * rm01 + m20() * rm02; - float nm01 = m01() * rm00 + m11() * rm01 + m21() * rm02; - float nm02 = m02() * rm00 + m12() * rm01 + m22() * rm02; - float nm03 = m03() * rm00 + m13() * rm01 + m23() * rm02; - float nm10 = m00() * rm10 + m10() * rm11 + m20() * rm12; - float nm11 = m01() * rm10 + m11() * rm11 + m21() * rm12; - float nm12 = m02() * rm10 + m12() * rm11 + m22() * rm12; - float nm13 = m03() * rm10 + m13() * rm11 + m23() * rm12; - return dest - ._m20(m00() * rm20 + m10() * rm21 + m20() * rm22) - ._m21(m01() * rm20 + m11() * rm21 + m21() * rm22) - ._m22(m02() * rm20 + m12() * rm21 + m22() * rm22) - ._m23(m03() * rm20 + m13() * rm21 + m23() * rm22) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply the rotation transformation of the given {@link Quaternionfc} to this matrix. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @return this - */ - public Matrix4f rotate(Quaternionfc quat) { - return rotate(quat, this); - } - - /** - * Apply the rotation transformation of the given {@link Quaternionfc} to this {@link #isAffine() affine} matrix and store - * the result in dest. - *

- * This method assumes this to be {@link #isAffine() affine}. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateAffine(Quaternionfc quat, Matrix4f dest) { - float w2 = quat.w() * quat.w(), x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(), z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw, xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz, yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz, xw = quat.x() * quat.w(), dxw = xw + xw; - float rm00 = w2 + x2 - z2 - y2; - float rm01 = dxy + dzw; - float rm02 = dxz - dyw; - float rm10 = -dzw + dxy; - float rm11 = y2 - z2 + w2 - x2; - float rm12 = dyz + dxw; - float rm20 = dyw + dxz; - float rm21 = dyz - dxw; - float rm22 = z2 - y2 - x2 + w2; - float nm00 = m00() * rm00 + m10() * rm01 + m20() * rm02; - float nm01 = m01() * rm00 + m11() * rm01 + m21() * rm02; - float nm02 = m02() * rm00 + m12() * rm01 + m22() * rm02; - float nm10 = m00() * rm10 + m10() * rm11 + m20() * rm12; - float nm11 = m01() * rm10 + m11() * rm11 + m21() * rm12; - float nm12 = m02() * rm10 + m12() * rm11 + m22() * rm12; - return dest - ._m20(m00() * rm20 + m10() * rm21 + m20() * rm22) - ._m21(m01() * rm20 + m11() * rm21 + m21() * rm22) - ._m22(m02() * rm20 + m12() * rm21 + m22() * rm22) - ._m23(0.0f) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(0.0f) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(0.0f) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply the rotation transformation of the given {@link Quaternionfc} to this matrix. - *

- * This method assumes this to be {@link #isAffine() affine}. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @return this - */ - public Matrix4f rotateAffine(Quaternionfc quat) { - return rotateAffine(quat, this); - } - - /** - * Apply the rotation transformation of the given {@link Quaternionfc} to this matrix, which is assumed to only contain a translation, and store - * the result in dest. - *

- * This method assumes this to only contain a translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateTranslation(Quaternionfc quat, Matrix4f dest) { - float w2 = quat.w() * quat.w(), x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(), z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw, xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz, yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz, xw = quat.x() * quat.w(), dxw = xw + xw; - float rm00 = w2 + x2 - z2 - y2; - float rm01 = dxy + dzw; - float rm02 = dxz - dyw; - float rm10 = -dzw + dxy; - float rm11 = y2 - z2 + w2 - x2; - float rm12 = dyz + dxw; - float rm20 = dyw + dxz; - float rm21 = dyz - dxw; - float rm22 = z2 - y2 - x2 + w2; - return dest - ._m20(rm20) - ._m21(rm21) - ._m22(rm22) - ._m23(0.0f) - ._m00(rm00) - ._m01(rm01) - ._m02(rm02) - ._m03(0.0f) - ._m10(rm10) - ._m11(rm11) - ._m12(rm12) - ._m13(0.0f) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Apply the rotation transformation of the given {@link Quaternionfc} to this matrix while using (ox, oy, oz) as the rotation origin. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * This method is equivalent to calling: translate(ox, oy, oz).rotate(quat).translate(-ox, -oy, -oz) - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param ox - * the x coordinate of the rotation origin - * @param oy - * the y coordinate of the rotation origin - * @param oz - * the z coordinate of the rotation origin - * @return this - */ - public Matrix4f rotateAround(Quaternionfc quat, float ox, float oy, float oz) { - return rotateAround(quat, ox, oy, oz, this); - } - - public Matrix4f rotateAroundAffine(Quaternionfc quat, float ox, float oy, float oz, Matrix4f dest) { - float w2 = quat.w() * quat.w(), x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(), z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw, xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz, yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz, xw = quat.x() * quat.w(), dxw = xw + xw; - float rm00 = w2 + x2 - z2 - y2; - float rm01 = dxy + dzw; - float rm02 = dxz - dyw; - float rm10 = -dzw + dxy; - float rm11 = y2 - z2 + w2 - x2; - float rm12 = dyz + dxw; - float rm20 = dyw + dxz; - float rm21 = dyz - dxw; - float rm22 = z2 - y2 - x2 + w2; - float tm30 = m00() * ox + m10() * oy + m20() * oz + m30(); - float tm31 = m01() * ox + m11() * oy + m21() * oz + m31(); - float tm32 = m02() * ox + m12() * oy + m22() * oz + m32(); - float nm00 = m00() * rm00 + m10() * rm01 + m20() * rm02; - float nm01 = m01() * rm00 + m11() * rm01 + m21() * rm02; - float nm02 = m02() * rm00 + m12() * rm01 + m22() * rm02; - float nm10 = m00() * rm10 + m10() * rm11 + m20() * rm12; - float nm11 = m01() * rm10 + m11() * rm11 + m21() * rm12; - float nm12 = m02() * rm10 + m12() * rm11 + m22() * rm12; - dest._m20(m00() * rm20 + m10() * rm21 + m20() * rm22) - ._m21(m01() * rm20 + m11() * rm21 + m21() * rm22) - ._m22(m02() * rm20 + m12() * rm21 + m22() * rm22) - ._m23(0.0f) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(0.0f) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(0.0f) - ._m30(-nm00 * ox - nm10 * oy - m20() * oz + tm30) - ._m31(-nm01 * ox - nm11 * oy - m21() * oz + tm31) - ._m32(-nm02 * ox - nm12 * oy - m22() * oz + tm32) - ._m33(1.0f) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - return dest; - } - - public Matrix4f rotateAround(Quaternionfc quat, float ox, float oy, float oz, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return rotationAround(quat, ox, oy, oz); - else if ((properties & PROPERTY_AFFINE) != 0) - return rotateAroundAffine(quat, ox, oy, oz, dest); - return rotateAroundGeneric(quat, ox, oy, oz, dest); - } - private Matrix4f rotateAroundGeneric(Quaternionfc quat, float ox, float oy, float oz, Matrix4f dest) { - float w2 = quat.w() * quat.w(), x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(), z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw, xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz, yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz, xw = quat.x() * quat.w(), dxw = xw + xw; - float rm00 = w2 + x2 - z2 - y2; - float rm01 = dxy + dzw; - float rm02 = dxz - dyw; - float rm10 = -dzw + dxy; - float rm11 = y2 - z2 + w2 - x2; - float rm12 = dyz + dxw; - float rm20 = dyw + dxz; - float rm21 = dyz - dxw; - float rm22 = z2 - y2 - x2 + w2; - float tm30 = m00() * ox + m10() * oy + m20() * oz + m30(); - float tm31 = m01() * ox + m11() * oy + m21() * oz + m31(); - float tm32 = m02() * ox + m12() * oy + m22() * oz + m32(); - float nm00 = m00() * rm00 + m10() * rm01 + m20() * rm02; - float nm01 = m01() * rm00 + m11() * rm01 + m21() * rm02; - float nm02 = m02() * rm00 + m12() * rm01 + m22() * rm02; - float nm03 = m03() * rm00 + m13() * rm01 + m23() * rm02; - float nm10 = m00() * rm10 + m10() * rm11 + m20() * rm12; - float nm11 = m01() * rm10 + m11() * rm11 + m21() * rm12; - float nm12 = m02() * rm10 + m12() * rm11 + m22() * rm12; - float nm13 = m03() * rm10 + m13() * rm11 + m23() * rm12; - dest._m20(m00() * rm20 + m10() * rm21 + m20() * rm22) - ._m21(m01() * rm20 + m11() * rm21 + m21() * rm22) - ._m22(m02() * rm20 + m12() * rm21 + m22() * rm22) - ._m23(m03() * rm20 + m13() * rm21 + m23() * rm22) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m30(-nm00 * ox - nm10 * oy - m20() * oz + tm30) - ._m31(-nm01 * ox - nm11 * oy - m21() * oz + tm31) - ._m32(-nm02 * ox - nm12 * oy - m22() * oz + tm32) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - return dest; - } - - /** - * Set this matrix to a transformation composed of a rotation of the specified {@link Quaternionfc} while using (ox, oy, oz) as the rotation origin. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method is equivalent to calling: translation(ox, oy, oz).rotate(quat).translate(-ox, -oy, -oz) - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param ox - * the x coordinate of the rotation origin - * @param oy - * the y coordinate of the rotation origin - * @param oz - * the z coordinate of the rotation origin - * @return this - */ - public Matrix4f rotationAround(Quaternionfc quat, float ox, float oy, float oz) { - float w2 = quat.w() * quat.w(), x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(), z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw, xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz, yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz, xw = quat.x() * quat.w(), dxw = xw + xw; - this._m20(dyw + dxz) - ._m21(dyz - dxw) - ._m22(z2 - y2 - x2 + w2) - ._m23(0.0f) - ._m00(w2 + x2 - z2 - y2) - ._m01(dxy + dzw) - ._m02(dxz - dyw) - ._m03(0.0f) - ._m10(-dzw + dxy) - ._m11(y2 - z2 + w2 - x2) - ._m12(dyz + dxw) - ._m13(0.0f) - ._m30(-m00() * ox - m10() * oy - m20() * oz + ox) - ._m31(-m01() * ox - m11() * oy - m21() * oz + oy) - ._m32(-m02() * ox - m12() * oy - m22() * oz + oz) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - /** - * Pre-multiply the rotation transformation of the given {@link Quaternionfc} to this matrix and store - * the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be Q * M. So when transforming a - * vector v with the new matrix by using Q * M * v, - * the quaternion rotation will be applied last! - *

- * In order to set the matrix to a rotation transformation without pre-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateLocal(Quaternionfc quat, Matrix4f dest) { - float w2 = quat.w() * quat.w(), x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(), z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(), dzw = zw + zw, xy = quat.x() * quat.y(), dxy = xy + xy; - float xz = quat.x() * quat.z(), dxz = xz + xz, yw = quat.y() * quat.w(), dyw = yw + yw; - float yz = quat.y() * quat.z(), dyz = yz + yz, xw = quat.x() * quat.w(), dxw = xw + xw; - float lm00 = w2 + x2 - z2 - y2; - float lm01 = dxy + dzw; - float lm02 = dxz - dyw; - float lm10 = -dzw + dxy; - float lm11 = y2 - z2 + w2 - x2; - float lm12 = dyz + dxw; - float lm20 = dyw + dxz; - float lm21 = dyz - dxw; - float lm22 = z2 - y2 - x2 + w2; - float nm00 = lm00 * m00() + lm10 * m01() + lm20 * m02(); - float nm01 = lm01 * m00() + lm11 * m01() + lm21 * m02(); - float nm02 = lm02 * m00() + lm12 * m01() + lm22 * m02(); - float nm10 = lm00 * m10() + lm10 * m11() + lm20 * m12(); - float nm11 = lm01 * m10() + lm11 * m11() + lm21 * m12(); - float nm12 = lm02 * m10() + lm12 * m11() + lm22 * m12(); - float nm20 = lm00 * m20() + lm10 * m21() + lm20 * m22(); - float nm21 = lm01 * m20() + lm11 * m21() + lm21 * m22(); - float nm22 = lm02 * m20() + lm12 * m21() + lm22 * m22(); - float nm30 = lm00 * m30() + lm10 * m31() + lm20 * m32(); - float nm31 = lm01 * m30() + lm11 * m31() + lm21 * m32(); - float nm32 = lm02 * m30() + lm12 * m31() + lm22 * m32(); - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(m03()) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(m13()) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(m23()) - ._m30(nm30) - ._m31(nm31) - ._m32(nm32) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - } - - /** - * Pre-multiply the rotation transformation of the given {@link Quaternionfc} to this matrix. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be Q * M. So when transforming a - * vector v with the new matrix by using Q * M * v, - * the quaternion rotation will be applied last! - *

- * In order to set the matrix to a rotation transformation without pre-multiplying, - * use {@link #rotation(Quaternionfc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotation(Quaternionfc) - * - * @param quat - * the {@link Quaternionfc} - * @return this - */ - public Matrix4f rotateLocal(Quaternionfc quat) { - return rotateLocal(quat, this); - } - - public Matrix4f rotateAroundLocal(Quaternionfc quat, float ox, float oy, float oz, Matrix4f dest) { - float w2 = quat.w() * quat.w(); - float x2 = quat.x() * quat.x(); - float y2 = quat.y() * quat.y(); - float z2 = quat.z() * quat.z(); - float zw = quat.z() * quat.w(); - float xy = quat.x() * quat.y(); - float xz = quat.x() * quat.z(); - float yw = quat.y() * quat.w(); - float yz = quat.y() * quat.z(); - float xw = quat.x() * quat.w(); - float lm00 = w2 + x2 - z2 - y2; - float lm01 = xy + zw + zw + xy; - float lm02 = xz - yw + xz - yw; - float lm10 = -zw + xy - zw + xy; - float lm11 = y2 - z2 + w2 - x2; - float lm12 = yz + yz + xw + xw; - float lm20 = yw + xz + xz + yw; - float lm21 = yz + yz - xw - xw; - float lm22 = z2 - y2 - x2 + w2; - float tm00 = m00() - ox * m03(); - float tm01 = m01() - oy * m03(); - float tm02 = m02() - oz * m03(); - float tm10 = m10() - ox * m13(); - float tm11 = m11() - oy * m13(); - float tm12 = m12() - oz * m13(); - float tm20 = m20() - ox * m23(); - float tm21 = m21() - oy * m23(); - float tm22 = m22() - oz * m23(); - float tm30 = m30() - ox * m33(); - float tm31 = m31() - oy * m33(); - float tm32 = m32() - oz * m33(); - dest._m00(lm00 * tm00 + lm10 * tm01 + lm20 * tm02 + ox * m03()) - ._m01(lm01 * tm00 + lm11 * tm01 + lm21 * tm02 + oy * m03()) - ._m02(lm02 * tm00 + lm12 * tm01 + lm22 * tm02 + oz * m03()) - ._m03(m03()) - ._m10(lm00 * tm10 + lm10 * tm11 + lm20 * tm12 + ox * m13()) - ._m11(lm01 * tm10 + lm11 * tm11 + lm21 * tm12 + oy * m13()) - ._m12(lm02 * tm10 + lm12 * tm11 + lm22 * tm12 + oz * m13()) - ._m13(m13()) - ._m20(lm00 * tm20 + lm10 * tm21 + lm20 * tm22 + ox * m23()) - ._m21(lm01 * tm20 + lm11 * tm21 + lm21 * tm22 + oy * m23()) - ._m22(lm02 * tm20 + lm12 * tm21 + lm22 * tm22 + oz * m23()) - ._m23(m23()) - ._m30(lm00 * tm30 + lm10 * tm31 + lm20 * tm32 + ox * m33()) - ._m31(lm01 * tm30 + lm11 * tm31 + lm21 * tm32 + oy * m33()) - ._m32(lm02 * tm30 + lm12 * tm31 + lm22 * tm32 + oz * m33()) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - return dest; - } - - /** - * Pre-multiply the rotation transformation of the given {@link Quaternionfc} to this matrix while using (ox, oy, oz) - * as the rotation origin. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be Q * M. So when transforming a - * vector v with the new matrix by using Q * M * v, - * the quaternion rotation will be applied last! - *

- * This method is equivalent to calling: translateLocal(-ox, -oy, -oz).rotateLocal(quat).translateLocal(ox, oy, oz) - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param ox - * the x coordinate of the rotation origin - * @param oy - * the y coordinate of the rotation origin - * @param oz - * the z coordinate of the rotation origin - * @return this - */ - public Matrix4f rotateAroundLocal(Quaternionfc quat, float ox, float oy, float oz) { - return rotateAroundLocal(quat, ox, oy, oz, this); - } - - /** - * Apply a rotation transformation, rotating about the given {@link AxisAngle4f}, to this matrix. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given {@link AxisAngle4f}, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the {@link AxisAngle4f} rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(AxisAngle4f)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float) - * @see #rotation(AxisAngle4f) - * - * @param axisAngle - * the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized}) - * @return this - */ - public Matrix4f rotate(AxisAngle4f axisAngle) { - return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z); - } - - /** - * Apply a rotation transformation, rotating about the given {@link AxisAngle4f} and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given {@link AxisAngle4f}, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the {@link AxisAngle4f} rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(AxisAngle4f)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float) - * @see #rotation(AxisAngle4f) - * - * @param axisAngle - * the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized}) - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotate(AxisAngle4f axisAngle, Matrix4f dest) { - return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z, dest); - } - - /** - * Apply a rotation transformation, rotating the given radians about the specified axis, to this matrix. - *

- * The axis described by the axis vector needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given axis-angle, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the axis-angle rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(float, Vector3fc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float) - * @see #rotation(float, Vector3fc) - * - * @param angle - * the angle in radians - * @param axis - * the rotation axis (needs to be {@link Vector3f#normalize() normalized}) - * @return this - */ - public Matrix4f rotate(float angle, Vector3fc axis) { - return rotate(angle, axis.x(), axis.y(), axis.z()); - } - - /** - * Apply a rotation transformation, rotating the given radians about the specified axis and store the result in dest. - *

- * The axis described by the axis vector needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given axis-angle, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the axis-angle rotation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying, - * use {@link #rotation(float, Vector3fc)}. - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float) - * @see #rotation(float, Vector3fc) - * - * @param angle - * the angle in radians - * @param axis - * the rotation axis (needs to be {@link Vector3f#normalize() normalized}) - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotate(float angle, Vector3fc axis, Matrix4f dest) { - return rotate(angle, axis.x(), axis.y(), axis.z(), dest); - } - - public Vector4f unproject(float winX, float winY, float winZ, int[] viewport, Vector4f dest) { - float a = m00() * m11() - m01() * m10(); - float b = m00() * m12() - m02() * m10(); - float c = m00() * m13() - m03() * m10(); - float d = m01() * m12() - m02() * m11(); - float e = m01() * m13() - m03() * m11(); - float f = m02() * m13() - m03() * m12(); - float g = m20() * m31() - m21() * m30(); - float h = m20() * m32() - m22() * m30(); - float i = m20() * m33() - m23() * m30(); - float j = m21() * m32() - m22() * m31(); - float k = m21() * m33() - m23() * m31(); - float l = m22() * m33() - m23() * m32(); - float det = a * l - b * k + c * j + d * i - e * h + f * g; - det = 1.0f / det; - float im00 = ( m11() * l - m12() * k + m13() * j) * det; - float im01 = (-m01() * l + m02() * k - m03() * j) * det; - float im02 = ( m31() * f - m32() * e + m33() * d) * det; - float im03 = (-m21() * f + m22() * e - m23() * d) * det; - float im10 = (-m10() * l + m12() * i - m13() * h) * det; - float im11 = ( m00() * l - m02() * i + m03() * h) * det; - float im12 = (-m30() * f + m32() * c - m33() * b) * det; - float im13 = ( m20() * f - m22() * c + m23() * b) * det; - float im20 = ( m10() * k - m11() * i + m13() * g) * det; - float im21 = (-m00() * k + m01() * i - m03() * g) * det; - float im22 = ( m30() * e - m31() * c + m33() * a) * det; - float im23 = (-m20() * e + m21() * c - m23() * a) * det; - float im30 = (-m10() * j + m11() * h - m12() * g) * det; - float im31 = ( m00() * j - m01() * h + m02() * g) * det; - float im32 = (-m30() * d + m31() * b - m32() * a) * det; - float im33 = ( m20() * d - m21() * b + m22() * a) * det; - float ndcX = (winX-viewport[0])/viewport[2]*2.0f-1.0f; - float ndcY = (winY-viewport[1])/viewport[3]*2.0f-1.0f; - float ndcZ = winZ+winZ-1.0f; - float invW = 1.0f / (im03 * ndcX + im13 * ndcY + im23 * ndcZ + im33); - return dest.set((im00 * ndcX + im10 * ndcY + im20 * ndcZ + im30) * invW, - (im01 * ndcX + im11 * ndcY + im21 * ndcZ + im31) * invW, - (im02 * ndcX + im12 * ndcY + im22 * ndcZ + im32) * invW, - 1.0f); - } - - public Vector3f unproject(float winX, float winY, float winZ, int[] viewport, Vector3f dest) { - float a = m00() * m11() - m01() * m10(); - float b = m00() * m12() - m02() * m10(); - float c = m00() * m13() - m03() * m10(); - float d = m01() * m12() - m02() * m11(); - float e = m01() * m13() - m03() * m11(); - float f = m02() * m13() - m03() * m12(); - float g = m20() * m31() - m21() * m30(); - float h = m20() * m32() - m22() * m30(); - float i = m20() * m33() - m23() * m30(); - float j = m21() * m32() - m22() * m31(); - float k = m21() * m33() - m23() * m31(); - float l = m22() * m33() - m23() * m32(); - float det = a * l - b * k + c * j + d * i - e * h + f * g; - det = 1.0f / det; - float im00 = ( m11() * l - m12() * k + m13() * j) * det; - float im01 = (-m01() * l + m02() * k - m03() * j) * det; - float im02 = ( m31() * f - m32() * e + m33() * d) * det; - float im03 = (-m21() * f + m22() * e - m23() * d) * det; - float im10 = (-m10() * l + m12() * i - m13() * h) * det; - float im11 = ( m00() * l - m02() * i + m03() * h) * det; - float im12 = (-m30() * f + m32() * c - m33() * b) * det; - float im13 = ( m20() * f - m22() * c + m23() * b) * det; - float im20 = ( m10() * k - m11() * i + m13() * g) * det; - float im21 = (-m00() * k + m01() * i - m03() * g) * det; - float im22 = ( m30() * e - m31() * c + m33() * a) * det; - float im23 = (-m20() * e + m21() * c - m23() * a) * det; - float im30 = (-m10() * j + m11() * h - m12() * g) * det; - float im31 = ( m00() * j - m01() * h + m02() * g) * det; - float im32 = (-m30() * d + m31() * b - m32() * a) * det; - float im33 = ( m20() * d - m21() * b + m22() * a) * det; - float ndcX = (winX-viewport[0])/viewport[2]*2.0f-1.0f; - float ndcY = (winY-viewport[1])/viewport[3]*2.0f-1.0f; - float ndcZ = winZ+winZ-1.0f; - float invW = 1.0f / (im03 * ndcX + im13 * ndcY + im23 * ndcZ + im33); - return dest.set((im00 * ndcX + im10 * ndcY + im20 * ndcZ + im30) * invW, - (im01 * ndcX + im11 * ndcY + im21 * ndcZ + im31) * invW, - (im02 * ndcX + im12 * ndcY + im22 * ndcZ + im32) * invW); - } - - public Vector4f unproject(Vector3fc winCoords, int[] viewport, Vector4f dest) { - return unproject(winCoords.x(), winCoords.y(), winCoords.z(), viewport, dest); - } - - public Vector3f unproject(Vector3fc winCoords, int[] viewport, Vector3f dest) { - return unproject(winCoords.x(), winCoords.y(), winCoords.z(), viewport, dest); - } - - public Matrix4f unprojectRay(float winX, float winY, int[] viewport, Vector3f originDest, Vector3f dirDest) { - float a = m00() * m11() - m01() * m10(); - float b = m00() * m12() - m02() * m10(); - float c = m00() * m13() - m03() * m10(); - float d = m01() * m12() - m02() * m11(); - float e = m01() * m13() - m03() * m11(); - float f = m02() * m13() - m03() * m12(); - float g = m20() * m31() - m21() * m30(); - float h = m20() * m32() - m22() * m30(); - float i = m20() * m33() - m23() * m30(); - float j = m21() * m32() - m22() * m31(); - float k = m21() * m33() - m23() * m31(); - float l = m22() * m33() - m23() * m32(); - float det = a * l - b * k + c * j + d * i - e * h + f * g; - det = 1.0f / det; - float im00 = ( m11() * l - m12() * k + m13() * j) * det; - float im01 = (-m01() * l + m02() * k - m03() * j) * det; - float im02 = ( m31() * f - m32() * e + m33() * d) * det; - float im03 = (-m21() * f + m22() * e - m23() * d) * det; - float im10 = (-m10() * l + m12() * i - m13() * h) * det; - float im11 = ( m00() * l - m02() * i + m03() * h) * det; - float im12 = (-m30() * f + m32() * c - m33() * b) * det; - float im13 = ( m20() * f - m22() * c + m23() * b) * det; - float im20 = ( m10() * k - m11() * i + m13() * g) * det; - float im21 = (-m00() * k + m01() * i - m03() * g) * det; - float im22 = ( m30() * e - m31() * c + m33() * a) * det; - float im23 = (-m20() * e + m21() * c - m23() * a) * det; - float im30 = (-m10() * j + m11() * h - m12() * g) * det; - float im31 = ( m00() * j - m01() * h + m02() * g) * det; - float im32 = (-m30() * d + m31() * b - m32() * a) * det; - float im33 = ( m20() * d - m21() * b + m22() * a) * det; - float ndcX = (winX-viewport[0])/viewport[2]*2.0f-1.0f; - float ndcY = (winY-viewport[1])/viewport[3]*2.0f-1.0f; - float px = im00 * ndcX + im10 * ndcY + im30; - float py = im01 * ndcX + im11 * ndcY + im31; - float pz = im02 * ndcX + im12 * ndcY + im32; - float invNearW = 1.0f / (im03 * ndcX + im13 * ndcY - im23 + im33); - float nearX = (px - im20) * invNearW; - float nearY = (py - im21) * invNearW; - float nearZ = (pz - im22) * invNearW; - float invW0 = 1.0f / (im03 * ndcX + im13 * ndcY + im33); - float x0 = px * invW0; - float y0 = py * invW0; - float z0 = pz * invW0; - originDest.x = nearX; originDest.y = nearY; originDest.z = nearZ; - dirDest.x = x0 - nearX; dirDest.y = y0 - nearY; dirDest.z = z0 - nearZ; - return this; - } - - public Vector4f unprojectInv(Vector3fc winCoords, int[] viewport, Vector4f dest) { - return unprojectInv(winCoords.x(), winCoords.y(), winCoords.z(), viewport, dest); - } - - public Vector4f unprojectInv(float winX, float winY, float winZ, int[] viewport, Vector4f dest) { - float ndcX = (winX-viewport[0])/viewport[2]*2.0f-1.0f; - float ndcY = (winY-viewport[1])/viewport[3]*2.0f-1.0f; - float ndcZ = winZ+winZ-1.0f; - float invW = 1.0f / (m03() * ndcX + m13() * ndcY + m23() * ndcZ + m33()); - return dest.set((m00() * ndcX + m10() * ndcY + m20() * ndcZ + m30()) * invW, - (m01() * ndcX + m11() * ndcY + m21() * ndcZ + m31()) * invW, - (m02() * ndcX + m12() * ndcY + m22() * ndcZ + m32()) * invW, - 1.0f); - } - - public Matrix4f unprojectInvRay(float winX, float winY, int[] viewport, Vector3f originDest, Vector3f dirDest) { - float ndcX = (winX-viewport[0])/viewport[2]*2.0f-1.0f; - float ndcY = (winY-viewport[1])/viewport[3]*2.0f-1.0f; - float px = m00() * ndcX + m10() * ndcY + m30(); - float py = m01() * ndcX + m11() * ndcY + m31(); - float pz = m02() * ndcX + m12() * ndcY + m32(); - float invNearW = 1.0f / (m03() * ndcX + m13() * ndcY - m23() + m33()); - float nearX = (px - m20()) * invNearW; - float nearY = (py - m21()) * invNearW; - float nearZ = (pz - m22()) * invNearW; - float invW0 = 1.0f / (m03() * ndcX + m13() * ndcY + m33()); - float x0 = px * invW0; - float y0 = py * invW0; - float z0 = pz * invW0; - originDest.x = nearX; originDest.y = nearY; originDest.z = nearZ; - dirDest.x = x0 - nearX; dirDest.y = y0 - nearY; dirDest.z = z0 - nearZ; - return this; - } - - public Vector3f unprojectInv(Vector3fc winCoords, int[] viewport, Vector3f dest) { - return unprojectInv(winCoords.x(), winCoords.y(), winCoords.z(), viewport, dest); - } - - public Vector3f unprojectInv(float winX, float winY, float winZ, int[] viewport, Vector3f dest) { - float ndcX = (winX-viewport[0])/viewport[2]*2.0f-1.0f; - float ndcY = (winY-viewport[1])/viewport[3]*2.0f-1.0f; - float ndcZ = winZ+winZ-1.0f; - float invW = 1.0f / (m03() * ndcX + m13() * ndcY + m23() * ndcZ + m33()); - return dest.set((m00() * ndcX + m10() * ndcY + m20() * ndcZ + m30()) * invW, - (m01() * ndcX + m11() * ndcY + m21() * ndcZ + m31()) * invW, - (m02() * ndcX + m12() * ndcY + m22() * ndcZ + m32()) * invW); - } - - public Vector4f project(float x, float y, float z, int[] viewport, Vector4f winCoordsDest) { - float invW = 1.0f / Math.fma(m03(), x, Math.fma(m13(), y, Math.fma(m23(), z, m33()))); - float nx = Math.fma(m00(), x, Math.fma(m10(), y, Math.fma(m20(), z, m30()))) * invW; - float ny = Math.fma(m01(), x, Math.fma(m11(), y, Math.fma(m21(), z, m31()))) * invW; - float nz = Math.fma(m02(), x, Math.fma(m12(), y, Math.fma(m22(), z, m32()))) * invW; - return winCoordsDest.set(Math.fma(Math.fma(nx, 0.5f, 0.5f), viewport[2], viewport[0]), - Math.fma(Math.fma(ny, 0.5f, 0.5f), viewport[3], viewport[1]), - Math.fma(0.5f, nz, 0.5f), - 1.0f); - } - - public Vector3f project(float x, float y, float z, int[] viewport, Vector3f winCoordsDest) { - float invW = 1.0f / Math.fma(m03(), x, Math.fma(m13(), y, Math.fma(m23(), z, m33()))); - float nx = Math.fma(m00(), x, Math.fma(m10(), y, Math.fma(m20(), z, m30()))) * invW; - float ny = Math.fma(m01(), x, Math.fma(m11(), y, Math.fma(m21(), z, m31()))) * invW; - float nz = Math.fma(m02(), x, Math.fma(m12(), y, Math.fma(m22(), z, m32()))) * invW; - winCoordsDest.x = Math.fma(Math.fma(nx, 0.5f, 0.5f), viewport[2], viewport[0]); - winCoordsDest.y = Math.fma(Math.fma(ny, 0.5f, 0.5f), viewport[3], viewport[1]); - winCoordsDest.z = Math.fma(0.5f, nz, 0.5f); - return winCoordsDest; - } - - public Vector4f project(Vector3fc position, int[] viewport, Vector4f winCoordsDest) { - return project(position.x(), position.y(), position.z(), viewport, winCoordsDest); - } - - public Vector3f project(Vector3fc position, int[] viewport, Vector3f winCoordsDest) { - return project(position.x(), position.y(), position.z(), viewport, winCoordsDest); - } - - public Matrix4f reflect(float a, float b, float c, float d, Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.reflection(a, b, c, d); - else if ((properties & PROPERTY_AFFINE) != 0) - return reflectAffine(a, b, c, d, dest); - return reflectGeneric(a, b, c, d, dest); - } - private Matrix4f reflectAffine(float a, float b, float c, float d, Matrix4f dest) { - float da = a + a, db = b + b, dc = c + c, dd = d + d; - float rm00 = 1.0f - da * a; - float rm01 = -da * b; - float rm02 = -da * c; - float rm10 = -db * a; - float rm11 = 1.0f - db * b; - float rm12 = -db * c; - float rm20 = -dc * a; - float rm21 = -dc * b; - float rm22 = 1.0f - dc * c; - float rm30 = -dd * a; - float rm31 = -dd * b; - float rm32 = -dd * c; - // matrix multiplication - dest._m30(m00() * rm30 + m10() * rm31 + m20() * rm32 + m30()) - ._m31(m01() * rm30 + m11() * rm31 + m21() * rm32 + m31()) - ._m32(m02() * rm30 + m12() * rm31 + m22() * rm32 + m32()) - ._m33(m33()); - float nm00 = m00() * rm00 + m10() * rm01 + m20() * rm02; - float nm01 = m01() * rm00 + m11() * rm01 + m21() * rm02; - float nm02 = m02() * rm00 + m12() * rm01 + m22() * rm02; - float nm10 = m00() * rm10 + m10() * rm11 + m20() * rm12; - float nm11 = m01() * rm10 + m11() * rm11 + m21() * rm12; - float nm12 = m02() * rm10 + m12() * rm11 + m22() * rm12; - dest._m20(m00() * rm20 + m10() * rm21 + m20() * rm22) - ._m21(m01() * rm20 + m11() * rm21 + m21() * rm22) - ._m22(m02() * rm20 + m12() * rm21 + m22() * rm22) - ._m23(0.0f) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(0.0f) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(0.0f) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - return dest; - } - private Matrix4f reflectGeneric(float a, float b, float c, float d, Matrix4f dest) { - float da = a + a, db = b + b, dc = c + c, dd = d + d; - float rm00 = 1.0f - da * a; - float rm01 = -da * b; - float rm02 = -da * c; - float rm10 = -db * a; - float rm11 = 1.0f - db * b; - float rm12 = -db * c; - float rm20 = -dc * a; - float rm21 = -dc * b; - float rm22 = 1.0f - dc * c; - float rm30 = -dd * a; - float rm31 = -dd * b; - float rm32 = -dd * c; - // matrix multiplication - dest._m30(m00() * rm30 + m10() * rm31 + m20() * rm32 + m30()) - ._m31(m01() * rm30 + m11() * rm31 + m21() * rm32 + m31()) - ._m32(m02() * rm30 + m12() * rm31 + m22() * rm32 + m32()) - ._m33(m03() * rm30 + m13() * rm31 + m23() * rm32 + m33()); - float nm00 = m00() * rm00 + m10() * rm01 + m20() * rm02; - float nm01 = m01() * rm00 + m11() * rm01 + m21() * rm02; - float nm02 = m02() * rm00 + m12() * rm01 + m22() * rm02; - float nm03 = m03() * rm00 + m13() * rm01 + m23() * rm02; - float nm10 = m00() * rm10 + m10() * rm11 + m20() * rm12; - float nm11 = m01() * rm10 + m11() * rm11 + m21() * rm12; - float nm12 = m02() * rm10 + m12() * rm11 + m22() * rm12; - float nm13 = m03() * rm10 + m13() * rm11 + m23() * rm12; - dest._m20(m00() * rm20 + m10() * rm21 + m20() * rm22) - ._m21(m01() * rm20 + m11() * rm21 + m21() * rm22) - ._m22(m02() * rm20 + m12() * rm21 + m22() * rm22) - ._m23(m03() * rm20 + m13() * rm21 + m23() * rm22) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - return dest; - } - - /** - * Apply a mirror/reflection transformation to this matrix that reflects about the given plane - * specified via the equation x*a + y*b + z*c + d = 0. - *

- * The vector (a, b, c) must be a unit vector. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - *

- * Reference: msdn.microsoft.com - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return this - */ - public Matrix4f reflect(float a, float b, float c, float d) { - return reflect(a, b, c, d, this); - } - - /** - * Apply a mirror/reflection transformation to this matrix that reflects about the given plane - * specified via the plane normal and a point on the plane. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param nx - * the x-coordinate of the plane normal - * @param ny - * the y-coordinate of the plane normal - * @param nz - * the z-coordinate of the plane normal - * @param px - * the x-coordinate of a point on the plane - * @param py - * the y-coordinate of a point on the plane - * @param pz - * the z-coordinate of a point on the plane - * @return this - */ - public Matrix4f reflect(float nx, float ny, float nz, float px, float py, float pz) { - return reflect(nx, ny, nz, px, py, pz, this); - } - - public Matrix4f reflect(float nx, float ny, float nz, float px, float py, float pz, Matrix4f dest) { - float invLength = Math.invsqrt(nx * nx + ny * ny + nz * nz); - float nnx = nx * invLength; - float nny = ny * invLength; - float nnz = nz * invLength; - /* See: http://mathworld.wolfram.com/Plane.html */ - return reflect(nnx, nny, nnz, -nnx * px - nny * py - nnz * pz, dest); - } - - /** - * Apply a mirror/reflection transformation to this matrix that reflects about the given plane - * specified via the plane normal and a point on the plane. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param normal - * the plane normal - * @param point - * a point on the plane - * @return this - */ - public Matrix4f reflect(Vector3fc normal, Vector3fc point) { - return reflect(normal.x(), normal.y(), normal.z(), point.x(), point.y(), point.z()); - } - - /** - * Apply a mirror/reflection transformation to this matrix that reflects about a plane - * specified via the plane orientation and a point on the plane. - *

- * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. - * It is assumed that the default mirror plane's normal is (0, 0, 1). So, if the given {@link Quaternionfc} is - * the identity (does not apply any additional rotation), the reflection plane will be z=0, offset by the given point. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param orientation - * the plane orientation - * @param point - * a point on the plane - * @return this - */ - public Matrix4f reflect(Quaternionfc orientation, Vector3fc point) { - return reflect(orientation, point, this); - } - - public Matrix4f reflect(Quaternionfc orientation, Vector3fc point, Matrix4f dest) { - double num1 = orientation.x() + orientation.x(); - double num2 = orientation.y() + orientation.y(); - double num3 = orientation.z() + orientation.z(); - float normalX = (float) (orientation.x() * num3 + orientation.w() * num2); - float normalY = (float) (orientation.y() * num3 - orientation.w() * num1); - float normalZ = (float) (1.0 - (orientation.x() * num1 + orientation.y() * num2)); - return reflect(normalX, normalY, normalZ, point.x(), point.y(), point.z(), dest); - } - - public Matrix4f reflect(Vector3fc normal, Vector3fc point, Matrix4f dest) { - return reflect(normal.x(), normal.y(), normal.z(), point.x(), point.y(), point.z(), dest); - } - - /** - * Set this matrix to a mirror/reflection transformation that reflects about the given plane - * specified via the equation x*a + y*b + z*c + d = 0. - *

- * The vector (a, b, c) must be a unit vector. - *

- * Reference: msdn.microsoft.com - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return this - */ - public Matrix4f reflection(float a, float b, float c, float d) { - float da = a + a, db = b + b, dc = c + c, dd = d + d; - this._m00(1.0f - da * a) - ._m01(-da * b) - ._m02(-da * c) - ._m03(0.0f) - ._m10(-db * a) - ._m11(1.0f - db * b) - ._m12(-db * c) - ._m13(0.0f) - ._m20(-dc * a) - ._m21(-dc * b) - ._m22(1.0f - dc * c) - ._m23(0.0f) - ._m30(-dd * a) - ._m31(-dd * b) - ._m32(-dd * c) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - /** - * Set this matrix to a mirror/reflection transformation that reflects about the given plane - * specified via the plane normal and a point on the plane. - * - * @param nx - * the x-coordinate of the plane normal - * @param ny - * the y-coordinate of the plane normal - * @param nz - * the z-coordinate of the plane normal - * @param px - * the x-coordinate of a point on the plane - * @param py - * the y-coordinate of a point on the plane - * @param pz - * the z-coordinate of a point on the plane - * @return this - */ - public Matrix4f reflection(float nx, float ny, float nz, float px, float py, float pz) { - float invLength = Math.invsqrt(nx * nx + ny * ny + nz * nz); - float nnx = nx * invLength; - float nny = ny * invLength; - float nnz = nz * invLength; - /* See: http://mathworld.wolfram.com/Plane.html */ - return reflection(nnx, nny, nnz, -nnx * px - nny * py - nnz * pz); - } - - /** - * Set this matrix to a mirror/reflection transformation that reflects about the given plane - * specified via the plane normal and a point on the plane. - * - * @param normal - * the plane normal - * @param point - * a point on the plane - * @return this - */ - public Matrix4f reflection(Vector3fc normal, Vector3fc point) { - return reflection(normal.x(), normal.y(), normal.z(), point.x(), point.y(), point.z()); - } - - /** - * Set this matrix to a mirror/reflection transformation that reflects about a plane - * specified via the plane orientation and a point on the plane. - *

- * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. - * It is assumed that the default mirror plane's normal is (0, 0, 1). So, if the given {@link Quaternionfc} is - * the identity (does not apply any additional rotation), the reflection plane will be z=0, offset by the given point. - * - * @param orientation - * the plane orientation - * @param point - * a point on the plane - * @return this - */ - public Matrix4f reflection(Quaternionfc orientation, Vector3fc point) { - double num1 = orientation.x() + orientation.x(); - double num2 = orientation.y() + orientation.y(); - double num3 = orientation.z() + orientation.z(); - float normalX = (float) (orientation.x() * num3 + orientation.w() * num2); - float normalY = (float) (orientation.y() * num3 - orientation.w() * num1); - float normalZ = (float) (1.0 - (orientation.x() * num1 + orientation.y() * num2)); - return reflection(normalX, normalY, normalZ, point.x(), point.y(), point.z()); - } - - public Vector4f getRow(int row, Vector4f dest) throws IndexOutOfBoundsException { - switch (row) { - case 0: - return dest.set(m00(), m10(), m20(), m30()); - case 1: - return dest.set(m01(), m11(), m21(), m31()); - case 2: - return dest.set(m02(), m12(), m22(), m32()); - case 3: - return dest.set(m03(), m13(), m23(), m33()); - default: - throw new IndexOutOfBoundsException(); - } - } - - public Vector3f getRow(int row, Vector3f dest) throws IndexOutOfBoundsException { - switch (row) { - case 0: - return dest.set(m00(), m10(), m20()); - case 1: - return dest.set(m01(), m11(), m21()); - case 2: - return dest.set(m02(), m12(), m22()); - case 3: - return dest.set(m03(), m13(), m23()); - default: - throw new IndexOutOfBoundsException(); - } - } - - /** - * Set the row at the given row index, starting with 0. - * - * @param row - * the row index in [0..3] - * @param src - * the row components to set - * @return this - * @throws IndexOutOfBoundsException if row is not in [0..3] - */ - public Matrix4f setRow(int row, Vector4fc src) throws IndexOutOfBoundsException { - switch (row) { - case 0: - return _m00(src.x())._m10(src.y())._m20(src.z())._m30(src.w())._properties(0); - case 1: - return _m01(src.x())._m11(src.y())._m21(src.z())._m31(src.w())._properties(0); - case 2: - return _m02(src.x())._m12(src.y())._m22(src.z())._m32(src.w())._properties(0); - case 3: - return _m03(src.x())._m13(src.y())._m23(src.z())._m33(src.w())._properties(0); - default: - throw new IndexOutOfBoundsException(); - } - } - - public Vector4f getColumn(int column, Vector4f dest) throws IndexOutOfBoundsException { - return MemUtil.INSTANCE.getColumn(this, column, dest); - } - - public Vector3f getColumn(int column, Vector3f dest) throws IndexOutOfBoundsException { - switch (column) { - case 0: - return dest.set(m00(), m01(), m02()); - case 1: - return dest.set(m10(), m11(), m12()); - case 2: - return dest.set(m20(), m21(), m22()); - case 3: - return dest.set(m30(), m31(), m32()); - default: - throw new IndexOutOfBoundsException(); - } - } - - /** - * Set the column at the given column index, starting with 0. - * - * @param column - * the column index in [0..3] - * @param src - * the column components to set - * @return this - * @throws IndexOutOfBoundsException if column is not in [0..3] - */ - public Matrix4f setColumn(int column, Vector4fc src) throws IndexOutOfBoundsException { - if (src instanceof Vector4f) - return MemUtil.INSTANCE.setColumn((Vector4f) src, column, this)._properties(0); - return MemUtil.INSTANCE.setColumn(src, column, this)._properties(0); - } - - public float get(int column, int row) { - return MemUtil.INSTANCE.get(this, column, row); - } - - /** - * Set the matrix element at the given column and row to the specified value. - * - * @param column - * the colum index in [0..3] - * @param row - * the row index in [0..3] - * @param value - * the value - * @return this - */ - public Matrix4f set(int column, int row, float value) { - return MemUtil.INSTANCE.set(this, column, row, value); - } - - public float getRowColumn(int row, int column) { - return MemUtil.INSTANCE.get(this, column, row); - } - - /** - * Set the matrix element at the given row and column to the specified value. - * - * @param row - * the row index in [0..3] - * @param column - * the colum index in [0..3] - * @param value - * the value - * @return this - */ - public Matrix4f setRowColumn(int row, int column, float value) { - return MemUtil.INSTANCE.set(this, column, row, value); - } - - /** - * Compute a normal matrix from the upper left 3x3 submatrix of this - * and store it into the upper left 3x3 submatrix of this. - * All other values of this will be set to {@link #identity() identity}. - *

- * The normal matrix of m is the transpose of the inverse of m. - *

- * Please note that, if this is an orthogonal matrix or a matrix whose columns are orthogonal vectors, - * then this method need not be invoked, since in that case this itself is its normal matrix. - * In that case, use {@link #set3x3(Matrix4f)} to set a given Matrix4f to only the upper left 3x3 submatrix - * of this matrix. - * - * @see #set3x3(Matrix4f) - * - * @return this - */ - public Matrix4f normal() { - return normal(this); - } - - /** - * Compute a normal matrix from the upper left 3x3 submatrix of this - * and store it into the upper left 3x3 submatrix of dest. - * All other values of dest will be set to {@link #identity() identity}. - *

- * The normal matrix of m is the transpose of the inverse of m. - *

- * Please note that, if this is an orthogonal matrix or a matrix whose columns are orthogonal vectors, - * then this method need not be invoked, since in that case this itself is its normal matrix. - * In that case, use {@link #set3x3(Matrix4f)} to set a given Matrix4f to only the upper left 3x3 submatrix - * of this matrix. - * - * @see #set3x3(Matrix4f) - * - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f normal(Matrix4f dest) { - if ((properties & PROPERTY_IDENTITY) != 0) - return dest.identity(); - else if ((properties & PROPERTY_ORTHONORMAL) != 0) - return normalOrthonormal(dest); - return normalGeneric(dest); - } - private Matrix4f normalOrthonormal(Matrix4f dest) { - if (dest != this) - dest.set(this); - return dest._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - } - private Matrix4f normalGeneric(Matrix4f dest) { - float m00m11 = m00() * m11(); - float m01m10 = m01() * m10(); - float m02m10 = m02() * m10(); - float m00m12 = m00() * m12(); - float m01m12 = m01() * m12(); - float m02m11 = m02() * m11(); - float det = (m00m11 - m01m10) * m22() + (m02m10 - m00m12) * m21() + (m01m12 - m02m11) * m20(); - float s = 1.0f / det; - /* Invert and transpose in one go */ - float nm00 = (m11() * m22() - m21() * m12()) * s; - float nm01 = (m20() * m12() - m10() * m22()) * s; - float nm02 = (m10() * m21() - m20() * m11()) * s; - float nm10 = (m21() * m02() - m01() * m22()) * s; - float nm11 = (m00() * m22() - m20() * m02()) * s; - float nm12 = (m20() * m01() - m00() * m21()) * s; - float nm20 = (m01m12 - m02m11) * s; - float nm21 = (m02m10 - m00m12) * s; - float nm22 = (m00m11 - m01m10) * s; - return dest - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(0.0f) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(0.0f) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(0.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(0.0f) - ._m33(1.0f) - ._properties((properties | PROPERTY_AFFINE) & ~(PROPERTY_TRANSLATION | PROPERTY_PERSPECTIVE)); - } - - /** - * Compute a normal matrix from the upper left 3x3 submatrix of this - * and store it into dest. - *

- * The normal matrix of m is the transpose of the inverse of m. - *

- * Please note that, if this is an orthogonal matrix or a matrix whose columns are orthogonal vectors, - * then this method need not be invoked, since in that case this itself is its normal matrix. - * In that case, use {@link Matrix3f#set(Matrix4fc)} to set a given Matrix3f to only the upper left 3x3 submatrix - * of this matrix. - * - * @see Matrix3f#set(Matrix4fc) - * @see #get3x3(Matrix3f) - * - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f normal(Matrix3f dest) { - if ((properties & PROPERTY_ORTHONORMAL) != 0) - return normalOrthonormal(dest); - return normalGeneric(dest); - } - private Matrix3f normalOrthonormal(Matrix3f dest) { - dest.set(this); - return dest; - } - private Matrix3f normalGeneric(Matrix3f dest) { - float det = (m00() * m11() - (m01() * m10())) * m22() - + (m02() * m10() - (m00() * m12())) * m21() - + (m01() * m12() - (m02() * m11())) * m20(); - float s = 1.0f / det; - /* Invert and transpose in one go */ - return dest._m00((m11() * m22() - m21() * m12()) * s) - ._m01((m20() * m12() - m10() * m22()) * s) - ._m02((m10() * m21() - m20() * m11()) * s) - ._m10((m21() * m02() - m01() * m22()) * s) - ._m11((m00() * m22() - m20() * m02()) * s) - ._m12((m20() * m01() - m00() * m21()) * s) - ._m20((m01() * m12() - m02() * m11()) * s) - ._m21((m02() * m10() - m00() * m12()) * s) - ._m22((m00() * m11() - m01() * m10()) * s); - } - - /** - * Compute the cofactor matrix of the upper left 3x3 submatrix of this. - *

- * The cofactor matrix can be used instead of {@link #normal()} to transform normals - * when the orientation of the normals with respect to the surface should be preserved. - * - * @return this - */ - public Matrix4f cofactor3x3() { - return cofactor3x3(this); - } - - /** - * Compute the cofactor matrix of the upper left 3x3 submatrix of this - * and store it into dest. - *

- * The cofactor matrix can be used instead of {@link #normal(Matrix3f)} to transform normals - * when the orientation of the normals with respect to the surface should be preserved. - * - * @param dest - * will hold the result - * @return dest - */ - public Matrix3f cofactor3x3(Matrix3f dest) { - return dest._m00(m11() * m22() - m21() * m12()) - ._m01(m20() * m12() - m10() * m22()) - ._m02(m10() * m21() - m20() * m11()) - ._m10(m21() * m02() - m01() * m22()) - ._m11(m00() * m22() - m20() * m02()) - ._m12(m20() * m01() - m00() * m21()) - ._m20(m01() * m12() - m02() * m11()) - ._m21(m02() * m10() - m00() * m12()) - ._m22(m00() * m11() - m01() * m10()); - } - - /** - * Compute the cofactor matrix of the upper left 3x3 submatrix of this - * and store it into dest. - * All other values of dest will be set to {@link #identity() identity}. - *

- * The cofactor matrix can be used instead of {@link #normal(Matrix4f)} to transform normals - * when the orientation of the normals with respect to the surface should be preserved. - * - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f cofactor3x3(Matrix4f dest) { - float nm10 = m21() * m02() - m01() * m22(); - float nm11 = m00() * m22() - m20() * m02(); - float nm12 = m20() * m01() - m00() * m21(); - float nm20 = m01() * m12() - m11() * m02(); - float nm21 = m02() * m10() - m12() * m00(); - float nm22 = m00() * m11() - m10() * m01(); - return dest - ._m00(m11() * m22() - m21() * m12()) - ._m01(m20() * m12() - m10() * m22()) - ._m02(m10() * m21() - m20() * m11()) - ._m03(0.0f) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(0.0f) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(0.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(0.0f) - ._m33(1.0f) - ._properties((properties | PROPERTY_AFFINE) & ~(PROPERTY_TRANSLATION | PROPERTY_PERSPECTIVE)); - } - - /** - * Normalize the upper left 3x3 submatrix of this matrix. - *

- * The resulting matrix will map unit vectors to unit vectors, though a pair of orthogonal input unit - * vectors need not be mapped to a pair of orthogonal output vectors if the original matrix was not orthogonal itself - * (i.e. had skewing). - * - * @return this - */ - public Matrix4f normalize3x3() { - return normalize3x3(this); - } - - public Matrix4f normalize3x3(Matrix4f dest) { - float invXlen = Math.invsqrt(m00() * m00() + m01() * m01() + m02() * m02()); - float invYlen = Math.invsqrt(m10() * m10() + m11() * m11() + m12() * m12()); - float invZlen = Math.invsqrt(m20() * m20() + m21() * m21() + m22() * m22()); - return dest - ._m00(m00() * invXlen)._m01(m01() * invXlen)._m02(m02() * invXlen) - ._m10(m10() * invYlen)._m11(m11() * invYlen)._m12(m12() * invYlen) - ._m20(m20() * invZlen)._m21(m21() * invZlen)._m22(m22() * invZlen) - ._m30(m30())._m31(m31())._m32(m32())._m33(m33()) - ._properties(properties); - } - - public Matrix3f normalize3x3(Matrix3f dest) { - float invXlen = Math.invsqrt(m00() * m00() + m01() * m01() + m02() * m02()); - float invYlen = Math.invsqrt(m10() * m10() + m11() * m11() + m12() * m12()); - float invZlen = Math.invsqrt(m20() * m20() + m21() * m21() + m22() * m22()); - return dest - ._m00(m00() * invXlen)._m01(m01() * invXlen)._m02(m02() * invXlen) - ._m10(m10() * invYlen)._m11(m11() * invYlen)._m12(m12() * invYlen) - ._m20(m20() * invZlen)._m21(m21() * invZlen)._m22(m22() * invZlen); - } - - public Vector4f frustumPlane(int plane, Vector4f dest) { - switch (plane) { - case PLANE_NX: - dest.set(m03() + m00(), m13() + m10(), m23() + m20(), m33() + m30()).normalize3(); - break; - case PLANE_PX: - dest.set(m03() - m00(), m13() - m10(), m23() - m20(), m33() - m30()).normalize3(); - break; - case PLANE_NY: - dest.set(m03() + m01(), m13() + m11(), m23() + m21(), m33() + m31()).normalize3(); - break; - case PLANE_PY: - dest.set(m03() - m01(), m13() - m11(), m23() - m21(), m33() - m31()).normalize3(); - break; - case PLANE_NZ: - dest.set(m03() + m02(), m13() + m12(), m23() + m22(), m33() + m32()).normalize3(); - break; - case PLANE_PZ: - dest.set(m03() - m02(), m13() - m12(), m23() - m22(), m33() - m32()).normalize3(); - break; - default: - throw new IllegalArgumentException("dest"); //$NON-NLS-1$ - } - return dest; - } - - public Vector3f frustumCorner(int corner, Vector3f point) { - float d1, d2, d3; - float n1x, n1y, n1z, n2x, n2y, n2z, n3x, n3y, n3z; - switch (corner) { - case CORNER_NXNYNZ: // left, bottom, near - n1x = m03() + m00(); n1y = m13() + m10(); n1z = m23() + m20(); d1 = m33() + m30(); // left - n2x = m03() + m01(); n2y = m13() + m11(); n2z = m23() + m21(); d2 = m33() + m31(); // bottom - n3x = m03() + m02(); n3y = m13() + m12(); n3z = m23() + m22(); d3 = m33() + m32(); // near - break; - case CORNER_PXNYNZ: // right, bottom, near - n1x = m03() - m00(); n1y = m13() - m10(); n1z = m23() - m20(); d1 = m33() - m30(); // right - n2x = m03() + m01(); n2y = m13() + m11(); n2z = m23() + m21(); d2 = m33() + m31(); // bottom - n3x = m03() + m02(); n3y = m13() + m12(); n3z = m23() + m22(); d3 = m33() + m32(); // near - break; - case CORNER_PXPYNZ: // right, top, near - n1x = m03() - m00(); n1y = m13() - m10(); n1z = m23() - m20(); d1 = m33() - m30(); // right - n2x = m03() - m01(); n2y = m13() - m11(); n2z = m23() - m21(); d2 = m33() - m31(); // top - n3x = m03() + m02(); n3y = m13() + m12(); n3z = m23() + m22(); d3 = m33() + m32(); // near - break; - case CORNER_NXPYNZ: // left, top, near - n1x = m03() + m00(); n1y = m13() + m10(); n1z = m23() + m20(); d1 = m33() + m30(); // left - n2x = m03() - m01(); n2y = m13() - m11(); n2z = m23() - m21(); d2 = m33() - m31(); // top - n3x = m03() + m02(); n3y = m13() + m12(); n3z = m23() + m22(); d3 = m33() + m32(); // near - break; - case CORNER_PXNYPZ: // right, bottom, far - n1x = m03() - m00(); n1y = m13() - m10(); n1z = m23() - m20(); d1 = m33() - m30(); // right - n2x = m03() + m01(); n2y = m13() + m11(); n2z = m23() + m21(); d2 = m33() + m31(); // bottom - n3x = m03() - m02(); n3y = m13() - m12(); n3z = m23() - m22(); d3 = m33() - m32(); // far - break; - case CORNER_NXNYPZ: // left, bottom, far - n1x = m03() + m00(); n1y = m13() + m10(); n1z = m23() + m20(); d1 = m33() + m30(); // left - n2x = m03() + m01(); n2y = m13() + m11(); n2z = m23() + m21(); d2 = m33() + m31(); // bottom - n3x = m03() - m02(); n3y = m13() - m12(); n3z = m23() - m22(); d3 = m33() - m32(); // far - break; - case CORNER_NXPYPZ: // left, top, far - n1x = m03() + m00(); n1y = m13() + m10(); n1z = m23() + m20(); d1 = m33() + m30(); // left - n2x = m03() - m01(); n2y = m13() - m11(); n2z = m23() - m21(); d2 = m33() - m31(); // top - n3x = m03() - m02(); n3y = m13() - m12(); n3z = m23() - m22(); d3 = m33() - m32(); // far - break; - case CORNER_PXPYPZ: // right, top, far - n1x = m03() - m00(); n1y = m13() - m10(); n1z = m23() - m20(); d1 = m33() - m30(); // right - n2x = m03() - m01(); n2y = m13() - m11(); n2z = m23() - m21(); d2 = m33() - m31(); // top - n3x = m03() - m02(); n3y = m13() - m12(); n3z = m23() - m22(); d3 = m33() - m32(); // far - break; - default: - throw new IllegalArgumentException("corner"); //$NON-NLS-1$ - } - float c23x, c23y, c23z; - c23x = n2y * n3z - n2z * n3y; - c23y = n2z * n3x - n2x * n3z; - c23z = n2x * n3y - n2y * n3x; - float c31x, c31y, c31z; - c31x = n3y * n1z - n3z * n1y; - c31y = n3z * n1x - n3x * n1z; - c31z = n3x * n1y - n3y * n1x; - float c12x, c12y, c12z; - c12x = n1y * n2z - n1z * n2y; - c12y = n1z * n2x - n1x * n2z; - c12z = n1x * n2y - n1y * n2x; - float invDot = 1.0f / (n1x * c23x + n1y * c23y + n1z * c23z); - point.x = (-c23x * d1 - c31x * d2 - c12x * d3) * invDot; - point.y = (-c23y * d1 - c31y * d2 - c12y * d3) * invDot; - point.z = (-c23z * d1 - c31z * d2 - c12z * d3) * invDot; - return point; - } - - /** - * Compute the eye/origin of the perspective frustum transformation defined by this matrix, - * which can be a projection matrix or a combined modelview-projection matrix, and store the result - * in the given origin. - *

- * Note that this method will only work using perspective projections obtained via one of the - * perspective methods, such as {@link #perspective(float, float, float, float) perspective()} - * or {@link #frustum(float, float, float, float, float, float) frustum()}. - *

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

- * This method is equivalent to calling: invert(new Matrix4f()).transformProject(0, 0, -1, 0, origin) - * and in the case of an already available inverse of this matrix, the method {@link #perspectiveInvOrigin(Vector3f)} - * on the inverse of the matrix should be used instead. - *

- * Reference: http://geomalgorithms.com - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @see #perspectiveInvOrigin(Vector3f) - * - * @param origin - * will hold the origin of the coordinate system before applying this - * perspective projection transformation - * @return origin - */ - public Vector3f perspectiveOrigin(Vector3f origin) { - /* - * Simply compute the intersection point of the left, right and top frustum plane. - */ - float d1, d2, d3; - float n1x, n1y, n1z, n2x, n2y, n2z, n3x, n3y, n3z; - n1x = m03() + m00(); n1y = m13() + m10(); n1z = m23() + m20(); d1 = m33() + m30(); // left - n2x = m03() - m00(); n2y = m13() - m10(); n2z = m23() - m20(); d2 = m33() - m30(); // right - n3x = m03() - m01(); n3y = m13() - m11(); n3z = m23() - m21(); d3 = m33() - m31(); // top - float c23x, c23y, c23z; - c23x = n2y * n3z - n2z * n3y; - c23y = n2z * n3x - n2x * n3z; - c23z = n2x * n3y - n2y * n3x; - float c31x, c31y, c31z; - c31x = n3y * n1z - n3z * n1y; - c31y = n3z * n1x - n3x * n1z; - c31z = n3x * n1y - n3y * n1x; - float c12x, c12y, c12z; - c12x = n1y * n2z - n1z * n2y; - c12y = n1z * n2x - n1x * n2z; - c12z = n1x * n2y - n1y * n2x; - float invDot = 1.0f / (n1x * c23x + n1y * c23y + n1z * c23z); - origin.x = (-c23x * d1 - c31x * d2 - c12x * d3) * invDot; - origin.y = (-c23y * d1 - c31y * d2 - c12y * d3) * invDot; - origin.z = (-c23z * d1 - c31z * d2 - c12z * d3) * invDot; - return origin; - } - - /** - * Compute the eye/origin of the inverse of the perspective frustum transformation defined by this matrix, - * which can be the inverse of a projection matrix or the inverse of a combined modelview-projection matrix, and store the result - * in the given dest. - *

- * Note that this method will only work using perspective projections obtained via one of the - * perspective methods, such as {@link #perspective(float, float, float, float) perspective()} - * or {@link #frustum(float, float, float, float, float, float) frustum()}. - *

- * If the inverse of the modelview-projection matrix is not available, then calling {@link #perspectiveOrigin(Vector3f)} - * on the original modelview-projection matrix is preferred. - * - * @see #perspectiveOrigin(Vector3f) - * - * @param dest - * will hold the result - * @return dest - */ - public Vector3f perspectiveInvOrigin(Vector3f dest) { - float invW = 1.0f / m23(); - dest.x = m20() * invW; - dest.y = m21() * invW; - dest.z = m22() * invW; - return dest; - } - - /** - * Return the vertical field-of-view angle in radians of this perspective transformation matrix. - *

- * Note that this method will only work using perspective projections obtained via one of the - * perspective methods, such as {@link #perspective(float, float, float, float) perspective()} - * or {@link #frustum(float, float, float, float, float, float) frustum()}. - *

- * For orthogonal transformations this method will return 0.0. - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @return the vertical field-of-view angle in radians - */ - public float perspectiveFov() { - /* - * Compute the angle between the bottom and top frustum plane normals. - */ - float n1x, n1y, n1z, n2x, n2y, n2z; - n1x = m03() + m01(); n1y = m13() + m11(); n1z = m23() + m21(); // bottom - n2x = m01() - m03(); n2y = m11() - m13(); n2z = m21() - m23(); // top - float n1len = Math.sqrt(n1x * n1x + n1y * n1y + n1z * n1z); - float n2len = Math.sqrt(n2x * n2x + n2y * n2y + n2z * n2z); - return Math.acos((n1x * n2x + n1y * n2y + n1z * n2z) / (n1len * n2len)); - } - - /** - * Extract the near clip plane distance from this perspective projection matrix. - *

- * This method only works if this is a perspective projection matrix, for example obtained via {@link #perspective(float, float, float, float)}. - * - * @return the near clip plane distance - */ - public float perspectiveNear() { - return m32() / (m23() + m22()); - } - - /** - * Extract the far clip plane distance from this perspective projection matrix. - *

- * This method only works if this is a perspective projection matrix, for example obtained via {@link #perspective(float, float, float, float)}. - * - * @return the far clip plane distance - */ - public float perspectiveFar() { - return m32() / (m22() - m23()); - } - - public Vector3f frustumRayDir(float x, float y, Vector3f dir) { - /* - * This method works by first obtaining the frustum plane normals, - * then building the cross product to obtain the corner rays, - * and finally bilinearly interpolating to obtain the desired direction. - * The code below uses a condense form of doing all this making use - * of some mathematical identities to simplify the overall expression. - */ - float a = m10() * m23(), b = m13() * m21(), c = m10() * m21(), d = m11() * m23(), e = m13() * m20(), f = m11() * m20(); - float g = m03() * m20(), h = m01() * m23(), i = m01() * m20(), j = m03() * m21(), k = m00() * m23(), l = m00() * m21(); - float m = m00() * m13(), n = m03() * m11(), o = m00() * m11(), p = m01() * m13(), q = m03() * m10(), r = m01() * m10(); - float m1x, m1y, m1z; - m1x = (d + e + f - a - b - c) * (1.0f - y) + (a - b - c + d - e + f) * y; - m1y = (j + k + l - g - h - i) * (1.0f - y) + (g - h - i + j - k + l) * y; - m1z = (p + q + r - m - n - o) * (1.0f - y) + (m - n - o + p - q + r) * y; - float m2x, m2y, m2z; - m2x = (b - c - d + e + f - a) * (1.0f - y) + (a + b - c - d - e + f) * y; - m2y = (h - i - j + k + l - g) * (1.0f - y) + (g + h - i - j - k + l) * y; - m2z = (n - o - p + q + r - m) * (1.0f - y) + (m + n - o - p - q + r) * y; - dir.x = m1x + (m2x - m1x) * x; - dir.y = m1y + (m2y - m1y) * x; - dir.z = m1z + (m2z - m1z) * x; - return dir.normalize(dir); - } - - public Vector3f positiveZ(Vector3f dir) { - if ((properties & PROPERTY_ORTHONORMAL) != 0) - return normalizedPositiveZ(dir); - return positiveZGeneric(dir); - } - private Vector3f positiveZGeneric(Vector3f dir) { - return dir.set(m10() * m21() - m11() * m20(), m20() * m01() - m21() * m00(), m00() * m11() - m01() * m10()).normalize(); - } - - public Vector3f normalizedPositiveZ(Vector3f dir) { - return dir.set(m02(), m12(), m22()); - } - - public Vector3f positiveX(Vector3f dir) { - if ((properties & PROPERTY_ORTHONORMAL) != 0) - return normalizedPositiveX(dir); - return positiveXGeneric(dir); - } - private Vector3f positiveXGeneric(Vector3f dir) { - return dir.set(m11() * m22() - m12() * m21(), m02() * m21() - m01() * m22(), m01() * m12() - m02() * m11()).normalize(); - } - - public Vector3f normalizedPositiveX(Vector3f dir) { - return dir.set(m00(), m10(), m20()); - } - - public Vector3f positiveY(Vector3f dir) { - if ((properties & PROPERTY_ORTHONORMAL) != 0) - return normalizedPositiveY(dir); - return positiveYGeneric(dir); - } - private Vector3f positiveYGeneric(Vector3f dir) { - return dir.set(m12() * m20() - m10() * m22(), m00() * m22() - m02() * m20(), m02() * m10() - m00() * m12()).normalize(); - } - - public Vector3f normalizedPositiveY(Vector3f dir) { - return dir.set(m01(), m11(), m21()); - } - - public Vector3f originAffine(Vector3f origin) { - float a = m00() * m11() - m01() * m10(); - float b = m00() * m12() - m02() * m10(); - float d = m01() * m12() - m02() * m11(); - float g = m20() * m31() - m21() * m30(); - float h = m20() * m32() - m22() * m30(); - float j = m21() * m32() - m22() * m31(); - return origin.set(-m10() * j + m11() * h - m12() * g, m00() * j - m01() * h + m02() * g, -m30() * d + m31() * b - m32() * a); - } - - public Vector3f origin(Vector3f dest) { - if ((properties & PROPERTY_AFFINE) != 0) - return originAffine(dest); - return originGeneric(dest); - } - private Vector3f originGeneric(Vector3f dest) { - float a = m00() * m11() - m01() * m10(); - float b = m00() * m12() - m02() * m10(); - float c = m00() * m13() - m03() * m10(); - float d = m01() * m12() - m02() * m11(); - float e = m01() * m13() - m03() * m11(); - float f = m02() * m13() - m03() * m12(); - float g = m20() * m31() - m21() * m30(); - float h = m20() * m32() - m22() * m30(); - float i = m20() * m33() - m23() * m30(); - float j = m21() * m32() - m22() * m31(); - float k = m21() * m33() - m23() * m31(); - float l = m22() * m33() - m23() * m32(); - float det = a * l - b * k + c * j + d * i - e * h + f * g; - float invDet = 1.0f / det; - float nm30 = (-m10() * j + m11() * h - m12() * g) * invDet; - float nm31 = ( m00() * j - m01() * h + m02() * g) * invDet; - float nm32 = (-m30() * d + m31() * b - m32() * a) * invDet; - float nm33 = det / ( m20() * d - m21() * b + m22() * a); - return dest.set(nm30 * nm33, nm31 * nm33, nm32 * nm33); - } - - /** - * Apply a projection transformation to this matrix that projects onto the plane specified via the general plane equation - * x*a + y*b + z*c + d = 0 as if casting a shadow from a given light position/direction light. - *

- * If light.w is 0.0 the light is being treated as a directional light; if it is 1.0 it is a point light. - *

- * If M is this matrix and S the shadow matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * shadow projection will be applied first! - *

- * Reference: ftp.sgi.com - * - * @param light - * the light's vector - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return this - */ - public Matrix4f shadow(Vector4f light, float a, float b, float c, float d) { - return shadow(light.x, light.y, light.z, light.w, a, b, c, d, this); - } - - public Matrix4f shadow(Vector4f light, float a, float b, float c, float d, Matrix4f dest) { - return shadow(light.x, light.y, light.z, light.w, a, b, c, d, dest); - } - - /** - * Apply a projection transformation to this matrix that projects onto the plane specified via the general plane equation - * x*a + y*b + z*c + d = 0 as if casting a shadow from a given light position/direction (lightX, lightY, lightZ, lightW). - *

- * If lightW is 0.0 the light is being treated as a directional light; if it is 1.0 it is a point light. - *

- * If M is this matrix and S the shadow matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * shadow projection will be applied first! - *

- * Reference: ftp.sgi.com - * - * @param lightX - * the x-component of the light's vector - * @param lightY - * the y-component of the light's vector - * @param lightZ - * the z-component of the light's vector - * @param lightW - * the w-component of the light's vector - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @return this - */ - public Matrix4f shadow(float lightX, float lightY, float lightZ, float lightW, float a, float b, float c, float d) { - return shadow(lightX, lightY, lightZ, lightW, a, b, c, d, this); - } - - public Matrix4f shadow(float lightX, float lightY, float lightZ, float lightW, float a, float b, float c, float d, Matrix4f dest) { - // normalize plane - float invPlaneLen = Math.invsqrt(a*a + b*b + c*c); - float an = a * invPlaneLen; - float bn = b * invPlaneLen; - float cn = c * invPlaneLen; - float dn = d * invPlaneLen; - - float dot = an * lightX + bn * lightY + cn * lightZ + dn * lightW; - - // compute right matrix elements - float rm00 = dot - an * lightX; - float rm01 = -an * lightY; - float rm02 = -an * lightZ; - float rm03 = -an * lightW; - float rm10 = -bn * lightX; - float rm11 = dot - bn * lightY; - float rm12 = -bn * lightZ; - float rm13 = -bn * lightW; - float rm20 = -cn * lightX; - float rm21 = -cn * lightY; - float rm22 = dot - cn * lightZ; - float rm23 = -cn * lightW; - float rm30 = -dn * lightX; - float rm31 = -dn * lightY; - float rm32 = -dn * lightZ; - float rm33 = dot - dn * lightW; - - // matrix multiplication - float nm00 = m00() * rm00 + m10() * rm01 + m20() * rm02 + m30() * rm03; - float nm01 = m01() * rm00 + m11() * rm01 + m21() * rm02 + m31() * rm03; - float nm02 = m02() * rm00 + m12() * rm01 + m22() * rm02 + m32() * rm03; - float nm03 = m03() * rm00 + m13() * rm01 + m23() * rm02 + m33() * rm03; - float nm10 = m00() * rm10 + m10() * rm11 + m20() * rm12 + m30() * rm13; - float nm11 = m01() * rm10 + m11() * rm11 + m21() * rm12 + m31() * rm13; - float nm12 = m02() * rm10 + m12() * rm11 + m22() * rm12 + m32() * rm13; - float nm13 = m03() * rm10 + m13() * rm11 + m23() * rm12 + m33() * rm13; - float nm20 = m00() * rm20 + m10() * rm21 + m20() * rm22 + m30() * rm23; - float nm21 = m01() * rm20 + m11() * rm21 + m21() * rm22 + m31() * rm23; - float nm22 = m02() * rm20 + m12() * rm21 + m22() * rm22 + m32() * rm23; - float nm23 = m03() * rm20 + m13() * rm21 + m23() * rm22 + m33() * rm23; - dest._m30(m00() * rm30 + m10() * rm31 + m20() * rm32 + m30() * rm33) - ._m31(m01() * rm30 + m11() * rm31 + m21() * rm32 + m31() * rm33) - ._m32(m02() * rm30 + m12() * rm31 + m22() * rm32 + m32() * rm33) - ._m33(m03() * rm30 + m13() * rm31 + m23() * rm32 + m33() * rm33) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - public Matrix4f shadow(Vector4f light, Matrix4fc planeTransform, Matrix4f dest) { - // compute plane equation by transforming (y = 0) - float a = planeTransform.m10(); - float b = planeTransform.m11(); - float c = planeTransform.m12(); - float d = -a * planeTransform.m30() - b * planeTransform.m31() - c * planeTransform.m32(); - return shadow(light.x, light.y, light.z, light.w, a, b, c, d, dest); - } - - /** - * Apply a projection transformation to this matrix that projects onto the plane with the general plane equation - * y = 0 as if casting a shadow from a given light position/direction light. - *

- * Before the shadow projection is applied, the plane is transformed via the specified planeTransformation. - *

- * If light.w is 0.0 the light is being treated as a directional light; if it is 1.0 it is a point light. - *

- * If M is this matrix and S the shadow matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * shadow projection will be applied first! - * - * @param light - * the light's vector - * @param planeTransform - * the transformation to transform the implied plane y = 0 before applying the projection - * @return this - */ - public Matrix4f shadow(Vector4f light, Matrix4f planeTransform) { - return shadow(light, planeTransform, this); - } - - public Matrix4f shadow(float lightX, float lightY, float lightZ, float lightW, Matrix4fc planeTransform, Matrix4f dest) { - // compute plane equation by transforming (y = 0) - float a = planeTransform.m10(); - float b = planeTransform.m11(); - float c = planeTransform.m12(); - float d = -a * planeTransform.m30() - b * planeTransform.m31() - c * planeTransform.m32(); - return shadow(lightX, lightY, lightZ, lightW, a, b, c, d, dest); - } - - /** - * Apply a projection transformation to this matrix that projects onto the plane with the general plane equation - * y = 0 as if casting a shadow from a given light position/direction (lightX, lightY, lightZ, lightW). - *

- * Before the shadow projection is applied, the plane is transformed via the specified planeTransformation. - *

- * If lightW is 0.0 the light is being treated as a directional light; if it is 1.0 it is a point light. - *

- * If M is this matrix and S the shadow matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * shadow projection will be applied first! - * - * @param lightX - * the x-component of the light vector - * @param lightY - * the y-component of the light vector - * @param lightZ - * the z-component of the light vector - * @param lightW - * the w-component of the light vector - * @param planeTransform - * the transformation to transform the implied plane y = 0 before applying the projection - * @return this - */ - public Matrix4f shadow(float lightX, float lightY, float lightZ, float lightW, Matrix4f planeTransform) { - return shadow(lightX, lightY, lightZ, lightW, planeTransform, this); - } - - /** - * Set this matrix to a cylindrical billboard transformation that rotates the local +Z axis of a given object with position objPos towards - * a target position at targetPos while constraining a cylindrical rotation around the given up vector. - *

- * This method can be used to create the complete model transformation for a given object, including the translation of the object to - * its position objPos. - * - * @param objPos - * the position of the object to rotate towards targetPos - * @param targetPos - * the position of the target (for example the camera) towards which to rotate the object - * @param up - * the rotation axis (must be {@link Vector3f#normalize() normalized}) - * @return this - */ - public Matrix4f billboardCylindrical(Vector3fc objPos, Vector3fc targetPos, Vector3fc up) { - float dirX = targetPos.x() - objPos.x(); - float dirY = targetPos.y() - objPos.y(); - float dirZ = targetPos.z() - objPos.z(); - // left = up x dir - float leftX = up.y() * dirZ - up.z() * dirY; - float leftY = up.z() * dirX - up.x() * dirZ; - float leftZ = up.x() * dirY - up.y() * dirX; - // normalize left - float invLeftLen = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLen; - leftY *= invLeftLen; - leftZ *= invLeftLen; - // recompute dir by constraining rotation around 'up' - // dir = left x up - dirX = leftY * up.z() - leftZ * up.y(); - dirY = leftZ * up.x() - leftX * up.z(); - dirZ = leftX * up.y() - leftY * up.x(); - // normalize dir - float invDirLen = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= invDirLen; - dirY *= invDirLen; - dirZ *= invDirLen; - // set matrix elements - this._m00(leftX) - ._m01(leftY) - ._m02(leftZ) - ._m03(0.0f) - ._m10(up.x()) - ._m11(up.y()) - ._m12(up.z()) - ._m13(0.0f) - ._m20(dirX) - ._m21(dirY) - ._m22(dirZ) - ._m23(0.0f) - ._m30(objPos.x()) - ._m31(objPos.y()) - ._m32(objPos.z()) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - /** - * Set this matrix to a spherical billboard transformation that rotates the local +Z axis of a given object with position objPos towards - * a target position at targetPos. - *

- * This method can be used to create the complete model transformation for a given object, including the translation of the object to - * its position objPos. - *

- * If preserving an up vector is not necessary when rotating the +Z axis, then a shortest arc rotation can be obtained - * using {@link #billboardSpherical(Vector3fc, Vector3fc)}. - * - * @see #billboardSpherical(Vector3fc, Vector3fc) - * - * @param objPos - * the position of the object to rotate towards targetPos - * @param targetPos - * the position of the target (for example the camera) towards which to rotate the object - * @param up - * the up axis used to orient the object - * @return this - */ - public Matrix4f billboardSpherical(Vector3fc objPos, Vector3fc targetPos, Vector3fc up) { - float dirX = targetPos.x() - objPos.x(); - float dirY = targetPos.y() - objPos.y(); - float dirZ = targetPos.z() - objPos.z(); - // normalize dir - float invDirLen = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - dirX *= invDirLen; - dirY *= invDirLen; - dirZ *= invDirLen; - // left = up x dir - float leftX = up.y() * dirZ - up.z() * dirY; - float leftY = up.z() * dirX - up.x() * dirZ; - float leftZ = up.x() * dirY - up.y() * dirX; - // normalize left - float invLeftLen = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLen; - leftY *= invLeftLen; - leftZ *= invLeftLen; - // up = dir x left - float upX = dirY * leftZ - dirZ * leftY; - float upY = dirZ * leftX - dirX * leftZ; - float upZ = dirX * leftY - dirY * leftX; - // set matrix elements - this._m00(leftX) - ._m01(leftY) - ._m02(leftZ) - ._m03(0.0f) - ._m10(upX) - ._m11(upY) - ._m12(upZ) - ._m13(0.0f) - ._m20(dirX) - ._m21(dirY) - ._m22(dirZ) - ._m23(0.0f) - ._m30(objPos.x()) - ._m31(objPos.y()) - ._m32(objPos.z()) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - /** - * Set this matrix to a spherical billboard transformation that rotates the local +Z axis of a given object with position objPos towards - * a target position at targetPos using a shortest arc rotation by not preserving any up vector of the object. - *

- * This method can be used to create the complete model transformation for a given object, including the translation of the object to - * its position objPos. - *

- * In order to specify an up vector which needs to be maintained when rotating the +Z axis of the object, - * use {@link #billboardSpherical(Vector3fc, Vector3fc, Vector3fc)}. - * - * @see #billboardSpherical(Vector3fc, Vector3fc, Vector3fc) - * - * @param objPos - * the position of the object to rotate towards targetPos - * @param targetPos - * the position of the target (for example the camera) towards which to rotate the object - * @return this - */ - public Matrix4f billboardSpherical(Vector3fc objPos, Vector3fc targetPos) { - float toDirX = targetPos.x() - objPos.x(); - float toDirY = targetPos.y() - objPos.y(); - float toDirZ = targetPos.z() - objPos.z(); - float x = -toDirY; - float y = toDirX; - float w = Math.sqrt(toDirX * toDirX + toDirY * toDirY + toDirZ * toDirZ) + toDirZ; - float invNorm = Math.invsqrt(x * x + y * y + w * w); - x *= invNorm; - y *= invNorm; - w *= invNorm; - float q00 = (x + x) * x; - float q11 = (y + y) * y; - float q01 = (x + x) * y; - float q03 = (x + x) * w; - float q13 = (y + y) * w; - this._m00(1.0f - q11) - ._m01(q01) - ._m02(-q13) - ._m03(0.0f) - ._m10(q01) - ._m11(1.0f - q00) - ._m12(q03) - ._m13(0.0f) - ._m20(q13) - ._m21(-q03) - ._m22(1.0f - q11 - q00) - ._m23(0.0f) - ._m30(objPos.x()) - ._m31(objPos.y()) - ._m32(objPos.z()) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(m00()); - result = prime * result + Float.floatToIntBits(m01()); - result = prime * result + Float.floatToIntBits(m02()); - result = prime * result + Float.floatToIntBits(m03()); - result = prime * result + Float.floatToIntBits(m10()); - result = prime * result + Float.floatToIntBits(m11()); - result = prime * result + Float.floatToIntBits(m12()); - result = prime * result + Float.floatToIntBits(m13()); - result = prime * result + Float.floatToIntBits(m20()); - result = prime * result + Float.floatToIntBits(m21()); - result = prime * result + Float.floatToIntBits(m22()); - result = prime * result + Float.floatToIntBits(m23()); - result = prime * result + Float.floatToIntBits(m30()); - result = prime * result + Float.floatToIntBits(m31()); - result = prime * result + Float.floatToIntBits(m32()); - result = prime * result + Float.floatToIntBits(m33()); - return result; - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof Matrix4f)) - return false; - Matrix4fc other = (Matrix4fc) obj; - if (Float.floatToIntBits(m00()) != Float.floatToIntBits(other.m00())) - return false; - if (Float.floatToIntBits(m01()) != Float.floatToIntBits(other.m01())) - return false; - if (Float.floatToIntBits(m02()) != Float.floatToIntBits(other.m02())) - return false; - if (Float.floatToIntBits(m03()) != Float.floatToIntBits(other.m03())) - return false; - if (Float.floatToIntBits(m10()) != Float.floatToIntBits(other.m10())) - return false; - if (Float.floatToIntBits(m11()) != Float.floatToIntBits(other.m11())) - return false; - if (Float.floatToIntBits(m12()) != Float.floatToIntBits(other.m12())) - return false; - if (Float.floatToIntBits(m13()) != Float.floatToIntBits(other.m13())) - return false; - if (Float.floatToIntBits(m20()) != Float.floatToIntBits(other.m20())) - return false; - if (Float.floatToIntBits(m21()) != Float.floatToIntBits(other.m21())) - return false; - if (Float.floatToIntBits(m22()) != Float.floatToIntBits(other.m22())) - return false; - if (Float.floatToIntBits(m23()) != Float.floatToIntBits(other.m23())) - return false; - if (Float.floatToIntBits(m30()) != Float.floatToIntBits(other.m30())) - return false; - if (Float.floatToIntBits(m31()) != Float.floatToIntBits(other.m31())) - return false; - if (Float.floatToIntBits(m32()) != Float.floatToIntBits(other.m32())) - return false; - if (Float.floatToIntBits(m33()) != Float.floatToIntBits(other.m33())) - return false; - return true; - } - - public boolean equals(Matrix4fc m, float delta) { - if (this == m) - return true; - if (m == null) - return false; - if (!(m instanceof Matrix4f)) - return false; - if (!Runtime.equals(m00(), m.m00(), delta)) - return false; - if (!Runtime.equals(m01(), m.m01(), delta)) - return false; - if (!Runtime.equals(m02(), m.m02(), delta)) - return false; - if (!Runtime.equals(m03(), m.m03(), delta)) - return false; - if (!Runtime.equals(m10(), m.m10(), delta)) - return false; - if (!Runtime.equals(m11(), m.m11(), delta)) - return false; - if (!Runtime.equals(m12(), m.m12(), delta)) - return false; - if (!Runtime.equals(m13(), m.m13(), delta)) - return false; - if (!Runtime.equals(m20(), m.m20(), delta)) - return false; - if (!Runtime.equals(m21(), m.m21(), delta)) - return false; - if (!Runtime.equals(m22(), m.m22(), delta)) - return false; - if (!Runtime.equals(m23(), m.m23(), delta)) - return false; - if (!Runtime.equals(m30(), m.m30(), delta)) - return false; - if (!Runtime.equals(m31(), m.m31(), delta)) - return false; - if (!Runtime.equals(m32(), m.m32(), delta)) - return false; - if (!Runtime.equals(m33(), m.m33(), delta)) - return false; - return true; - } - - public Matrix4f pick(float x, float y, float width, float height, int[] viewport, Matrix4f dest) { - float sx = viewport[2] / width; - float sy = viewport[3] / height; - float tx = (viewport[2] + 2.0f * (viewport[0] - x)) / width; - float ty = (viewport[3] + 2.0f * (viewport[1] - y)) / height; - dest._m30(m00() * tx + m10() * ty + m30()) - ._m31(m01() * tx + m11() * ty + m31()) - ._m32(m02() * tx + m12() * ty + m32()) - ._m33(m03() * tx + m13() * ty + m33()) - ._m00(m00() * sx) - ._m01(m01() * sx) - ._m02(m02() * sx) - ._m03(m03() * sx) - ._m10(m10() * sy) - ._m11(m11() * sy) - ._m12(m12() * sy) - ._m13(m13() * sy) - ._properties(0); - return dest; - } - - /** - * Apply a picking transformation to this matrix using the given window coordinates (x, y) as the pick center - * and the given (width, height) as the size of the picking region in window coordinates. - * - * @param x - * the x coordinate of the picking region center in window coordinates - * @param y - * the y coordinate of the picking region center in window coordinates - * @param width - * the width of the picking region in window coordinates - * @param height - * the height of the picking region in window coordinates - * @param viewport - * the viewport described by [x, y, width, height] - * @return this - */ - public Matrix4f pick(float x, float y, float width, float height, int[] viewport) { - return pick(x, y, width, height, viewport, this); - } - - public boolean isAffine() { - return m03() == 0.0f && m13() == 0.0f && m23() == 0.0f && m33() == 1.0f; - } - - /** - * Exchange the values of this matrix with the given other matrix. - * - * @param other - * the other matrix to exchange the values with - * @return this - */ - public Matrix4f swap(Matrix4f other) { - MemUtil.INSTANCE.swap(this, other); - int props = properties; - this.properties = other.properties(); - other.properties = props; - return this; - } - - public Matrix4f arcball(float radius, float centerX, float centerY, float centerZ, float angleX, float angleY, Matrix4f dest) { - float m30 = m20() * -radius + this.m30(); - float m31 = m21() * -radius + this.m31(); - float m32 = m22() * -radius + this.m32(); - float m33 = m23() * -radius + this.m33(); - float sin = Math.sin(angleX); - float cos = Math.cosFromSin(sin, angleX); - float nm10 = m10() * cos + m20() * sin; - float nm11 = m11() * cos + m21() * sin; - float nm12 = m12() * cos + m22() * sin; - float nm13 = m13() * cos + m23() * sin; - float m20 = this.m20() * cos - m10() * sin; - float m21 = this.m21() * cos - m11() * sin; - float m22 = this.m22() * cos - m12() * sin; - float m23 = this.m23() * cos - m13() * sin; - sin = Math.sin(angleY); - cos = Math.cosFromSin(sin, angleY); - float nm00 = m00() * cos - m20 * sin; - float nm01 = m01() * cos - m21 * sin; - float nm02 = m02() * cos - m22 * sin; - float nm03 = m03() * cos - m23 * sin; - float nm20 = m00() * sin + m20 * cos; - float nm21 = m01() * sin + m21 * cos; - float nm22 = m02() * sin + m22 * cos; - float nm23 = m03() * sin + m23 * cos; - dest._m30(-nm00 * centerX - nm10 * centerY - nm20 * centerZ + m30) - ._m31(-nm01 * centerX - nm11 * centerY - nm21 * centerZ + m31) - ._m32(-nm02 * centerX - nm12 * centerY - nm22 * centerZ + m32) - ._m33(-nm03 * centerX - nm13 * centerY - nm23 * centerZ + m33) - ._m20(nm20) - ._m21(nm21) - ._m22(nm22) - ._m23(nm23) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - return dest; - } - - public Matrix4f arcball(float radius, Vector3fc center, float angleX, float angleY, Matrix4f dest) { - return arcball(radius, center.x(), center.y(), center.z(), angleX, angleY, dest); - } - - /** - * Apply an arcball view transformation to this matrix with the given radius and center (centerX, centerY, centerZ) - * position of the arcball and the specified X and Y rotation angles. - *

- * This method is equivalent to calling: translate(0, 0, -radius).rotateX(angleX).rotateY(angleY).translate(-centerX, -centerY, -centerZ) - * - * @param radius - * the arcball radius - * @param centerX - * the x coordinate of the center position of the arcball - * @param centerY - * the y coordinate of the center position of the arcball - * @param centerZ - * the z coordinate of the center position of the arcball - * @param angleX - * the rotation angle around the X axis in radians - * @param angleY - * the rotation angle around the Y axis in radians - * @return this - */ - public Matrix4f arcball(float radius, float centerX, float centerY, float centerZ, float angleX, float angleY) { - return arcball(radius, centerX, centerY, centerZ, angleX, angleY, this); - } - - /** - * Apply an arcball view transformation to this matrix with the given radius and center - * position of the arcball and the specified X and Y rotation angles. - *

- * This method is equivalent to calling: translate(0, 0, -radius).rotateX(angleX).rotateY(angleY).translate(-center.x, -center.y, -center.z) - * - * @param radius - * the arcball radius - * @param center - * the center position of the arcball - * @param angleX - * the rotation angle around the X axis in radians - * @param angleY - * the rotation angle around the Y axis in radians - * @return this - */ - public Matrix4f arcball(float radius, Vector3fc center, float angleX, float angleY) { - return arcball(radius, center.x(), center.y(), center.z(), angleX, angleY, this); - } - - /** - * Compute the axis-aligned bounding box of the frustum described by this matrix and store the minimum corner - * coordinates in the given min and the maximum corner coordinates in the given max vector. - *

- * The matrix this is assumed to be the {@link #invert() inverse} of the origial view-projection matrix - * for which to compute the axis-aligned bounding box in world-space. - *

- * The axis-aligned bounding box of the unit frustum is (-1, -1, -1), (1, 1, 1). - * - * @param min - * will hold the minimum corner coordinates of the axis-aligned bounding box - * @param max - * will hold the maximum corner coordinates of the axis-aligned bounding box - * @return this - */ - public Matrix4f frustumAabb(Vector3f min, Vector3f max) { - float minX = Float.POSITIVE_INFINITY; - float minY = Float.POSITIVE_INFINITY; - float minZ = Float.POSITIVE_INFINITY; - float maxX = Float.NEGATIVE_INFINITY; - float maxY = Float.NEGATIVE_INFINITY; - float maxZ = Float.NEGATIVE_INFINITY; - for (int t = 0; t < 8; t++) { - float x = ((t & 1) << 1) - 1.0f; - float y = (((t >>> 1) & 1) << 1) - 1.0f; - float z = (((t >>> 2) & 1) << 1) - 1.0f; - float invW = 1.0f / (m03() * x + m13() * y + m23() * z + m33()); - float nx = (m00() * x + m10() * y + m20() * z + m30()) * invW; - float ny = (m01() * x + m11() * y + m21() * z + m31()) * invW; - float nz = (m02() * x + m12() * y + m22() * z + m32()) * invW; - minX = minX < nx ? minX : nx; - minY = minY < ny ? minY : ny; - minZ = minZ < nz ? minZ : nz; - maxX = maxX > nx ? maxX : nx; - maxY = maxY > ny ? maxY : ny; - maxZ = maxZ > nz ? maxZ : nz; - } - min.x = minX; - min.y = minY; - min.z = minZ; - max.x = maxX; - max.y = maxY; - max.z = maxZ; - return this; - } - - public Matrix4f projectedGridRange(Matrix4fc projector, float sLower, float sUpper, Matrix4f dest) { - // Compute intersection with frustum edges and plane - float minX = Float.POSITIVE_INFINITY, minY = Float.POSITIVE_INFINITY; - float maxX = Float.NEGATIVE_INFINITY, maxY = Float.NEGATIVE_INFINITY; - boolean intersection = false; - for (int t = 0; t < 3 * 4; t++) { - float c0X, c0Y, c0Z; - float c1X, c1Y, c1Z; - if (t < 4) { - // all x edges - c0X = -1; c1X = +1; - c0Y = c1Y = ((t & 1) << 1) - 1.0f; - c0Z = c1Z = (((t >>> 1) & 1) << 1) - 1.0f; - } else if (t < 8) { - // all y edges - c0Y = -1; c1Y = +1; - c0X = c1X = ((t & 1) << 1) - 1.0f; - c0Z = c1Z = (((t >>> 1) & 1) << 1) - 1.0f; - } else { - // all z edges - c0Z = -1; c1Z = +1; - c0X = c1X = ((t & 1) << 1) - 1.0f; - c0Y = c1Y = (((t >>> 1) & 1) << 1) - 1.0f; - } - // unproject corners - float invW = 1.0f / (m03() * c0X + m13() * c0Y + m23() * c0Z + m33()); - float p0x = (m00() * c0X + m10() * c0Y + m20() * c0Z + m30()) * invW; - float p0y = (m01() * c0X + m11() * c0Y + m21() * c0Z + m31()) * invW; - float p0z = (m02() * c0X + m12() * c0Y + m22() * c0Z + m32()) * invW; - invW = 1.0f / (m03() * c1X + m13() * c1Y + m23() * c1Z + m33()); - float p1x = (m00() * c1X + m10() * c1Y + m20() * c1Z + m30()) * invW; - float p1y = (m01() * c1X + m11() * c1Y + m21() * c1Z + m31()) * invW; - float p1z = (m02() * c1X + m12() * c1Y + m22() * c1Z + m32()) * invW; - float dirX = p1x - p0x; - float dirY = p1y - p0y; - float dirZ = p1z - p0z; - float invDenom = 1.0f / dirY; - // test for intersection - for (int s = 0; s < 2; s++) { - float isectT = -(p0y + (s == 0 ? sLower : sUpper)) * invDenom; - if (isectT >= 0.0f && isectT <= 1.0f) { - intersection = true; - // project with projector matrix - float ix = p0x + isectT * dirX; - float iz = p0z + isectT * dirZ; - invW = 1.0f / (projector.m03() * ix + projector.m23() * iz + projector.m33()); - float px = (projector.m00() * ix + projector.m20() * iz + projector.m30()) * invW; - float py = (projector.m01() * ix + projector.m21() * iz + projector.m31()) * invW; - minX = minX < px ? minX : px; - minY = minY < py ? minY : py; - maxX = maxX > px ? maxX : px; - maxY = maxY > py ? maxY : py; - } - } - } - if (!intersection) - return null; // <- projected grid is not visible - dest.set(maxX - minX, 0, 0, 0, 0, maxY - minY, 0, 0, 0, 0, 1, 0, minX, minY, 0, 1); - dest._properties(PROPERTY_AFFINE); - return dest; - } - - /** - * Change the near and far clip plane distances of this perspective frustum transformation matrix - * and store the result in dest. - *

- * This method only works if this is a perspective projection frustum transformation, for example obtained - * via {@link #perspective(float, float, float, float) perspective()} or {@link #frustum(float, float, float, float, float, float) frustum()}. - * - * @see #perspective(float, float, float, float) - * @see #frustum(float, float, float, float, float, float) - * - * @param near - * the new near clip plane distance - * @param far - * the new far clip plane distance - * @param dest - * will hold the resulting matrix - * @return dest - */ - public Matrix4f perspectiveFrustumSlice(float near, float far, Matrix4f dest) { - float invOldNear = (m23() + m22()) / m32(); - float invNearFar = 1.0f / (near - far); - dest._m00(m00() * invOldNear * near) - ._m01(m01()) - ._m02(m02()) - ._m03(m03()) - ._m10(m10()) - ._m11(m11() * invOldNear * near) - ._m12(m12()) - ._m13(m13()) - ._m20(m20()) - ._m21(m21()) - ._m22((far + near) * invNearFar) - ._m23(m23()) - ._m30(m30()) - ._m31(m31()) - ._m32((far + far) * near * invNearFar) - ._m33(m33()) - ._properties(properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL)); - return dest; - } - - /** - * Build an ortographic projection transformation that fits the view-projection transformation represented by this - * into the given affine view transformation. - *

- * The transformation represented by this must be given as the {@link #invert() inverse} of a typical combined camera view-projection - * transformation, whose projection can be either orthographic or perspective. - *

- * The view must be an {@link #isAffine() affine} transformation which in the application of Cascaded Shadow Maps is usually the light view transformation. - * It be obtained via any affine transformation or for example via {@link #lookAt(float, float, float, float, float, float, float, float, float) lookAt()}. - *

- * Reference: OpenGL SDK - Cascaded Shadow Maps - * - * @param view - * the view transformation to build a corresponding orthographic projection to fit the frustum of this - * @param dest - * will hold the crop projection transformation - * @return dest - */ - public Matrix4f orthoCrop(Matrix4fc view, Matrix4f dest) { - // determine min/max world z and min/max orthographically view-projected x/y - float minX = Float.POSITIVE_INFINITY, maxX = Float.NEGATIVE_INFINITY; - float minY = Float.POSITIVE_INFINITY, maxY = Float.NEGATIVE_INFINITY; - float minZ = Float.POSITIVE_INFINITY, maxZ = Float.NEGATIVE_INFINITY; - for (int t = 0; t < 8; t++) { - float x = ((t & 1) << 1) - 1.0f; - float y = (((t >>> 1) & 1) << 1) - 1.0f; - float z = (((t >>> 2) & 1) << 1) - 1.0f; - float invW = 1.0f / (m03() * x + m13() * y + m23() * z + m33()); - float wx = (m00() * x + m10() * y + m20() * z + m30()) * invW; - float wy = (m01() * x + m11() * y + m21() * z + m31()) * invW; - float wz = (m02() * x + m12() * y + m22() * z + m32()) * invW; - invW = 1.0f / (view.m03() * wx + view.m13() * wy + view.m23() * wz + view.m33()); - float vx = view.m00() * wx + view.m10() * wy + view.m20() * wz + view.m30(); - float vy = view.m01() * wx + view.m11() * wy + view.m21() * wz + view.m31(); - float vz = (view.m02() * wx + view.m12() * wy + view.m22() * wz + view.m32()) * invW; - minX = minX < vx ? minX : vx; - maxX = maxX > vx ? maxX : vx; - minY = minY < vy ? minY : vy; - maxY = maxY > vy ? maxY : vy; - minZ = minZ < vz ? minZ : vz; - maxZ = maxZ > vz ? maxZ : vz; - } - // build crop projection matrix to fit 'this' frustum into view - return dest.setOrtho(minX, maxX, minY, maxY, -maxZ, -minZ); - } - - /** - * Set this matrix to a perspective transformation that maps the trapezoid spanned by the four corner coordinates - * (p0x, p0y), (p1x, p1y), (p2x, p2y) and (p3x, p3y) to the unit square [(-1, -1)..(+1, +1)]. - *

- * The corner coordinates are given in counter-clockwise order starting from the left corner on the smaller parallel side of the trapezoid - * seen when looking at the trapezoid oriented with its shorter parallel edge at the bottom and its longer parallel edge at the top. - *

- * Reference: Trapezoidal Shadow Maps (TSM) - Recipe - * - * @param p0x - * the x coordinate of the left corner at the shorter edge of the trapezoid - * @param p0y - * the y coordinate of the left corner at the shorter edge of the trapezoid - * @param p1x - * the x coordinate of the right corner at the shorter edge of the trapezoid - * @param p1y - * the y coordinate of the right corner at the shorter edge of the trapezoid - * @param p2x - * the x coordinate of the right corner at the longer edge of the trapezoid - * @param p2y - * the y coordinate of the right corner at the longer edge of the trapezoid - * @param p3x - * the x coordinate of the left corner at the longer edge of the trapezoid - * @param p3y - * the y coordinate of the left corner at the longer edge of the trapezoid - * @return this - */ - public Matrix4f trapezoidCrop(float p0x, float p0y, float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { - float aX = p1y - p0y, aY = p0x - p1x; - float nm00 = aY; - float nm10 = -aX; - float nm30 = aX * p0y - aY * p0x; - float nm01 = aX; - float nm11 = aY; - float nm31 = -(aX * p0x + aY * p0y); - float c3x = nm00 * p3x + nm10 * p3y + nm30; - float c3y = nm01 * p3x + nm11 * p3y + nm31; - float s = -c3x / c3y; - nm00 += s * nm01; - nm10 += s * nm11; - nm30 += s * nm31; - float d1x = nm00 * p1x + nm10 * p1y + nm30; - float d2x = nm00 * p2x + nm10 * p2y + nm30; - float d = d1x * c3y / (d2x - d1x); - nm31 += d; - float sx = 2.0f / d2x; - float sy = 1.0f / (c3y + d); - float u = (sy + sy) * d / (1.0f - sy * d); - float m03 = nm01 * sy; - float m13 = nm11 * sy; - float m33 = nm31 * sy; - nm01 = (u + 1.0f) * m03; - nm11 = (u + 1.0f) * m13; - nm31 = (u + 1.0f) * m33 - u; - nm00 = sx * nm00 - m03; - nm10 = sx * nm10 - m13; - nm30 = sx * nm30 - m33; - set(nm00, nm01, 0, m03, - nm10, nm11, 0, m13, - 0, 0, 1, 0, - nm30, nm31, 0, m33); - _properties(0); - return this; - } - - public Matrix4f transformAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, Vector3f outMin, Vector3f outMax) { - float xax = m00() * minX, xay = m01() * minX, xaz = m02() * minX; - float xbx = m00() * maxX, xby = m01() * maxX, xbz = m02() * maxX; - float yax = m10() * minY, yay = m11() * minY, yaz = m12() * minY; - float ybx = m10() * maxY, yby = m11() * maxY, ybz = m12() * maxY; - float zax = m20() * minZ, zay = m21() * minZ, zaz = m22() * minZ; - float zbx = m20() * maxZ, zby = m21() * maxZ, zbz = m22() * maxZ; - float xminx, xminy, xminz, yminx, yminy, yminz, zminx, zminy, zminz; - float xmaxx, xmaxy, xmaxz, ymaxx, ymaxy, ymaxz, zmaxx, zmaxy, zmaxz; - if (xax < xbx) { - xminx = xax; - xmaxx = xbx; - } else { - xminx = xbx; - xmaxx = xax; - } - if (xay < xby) { - xminy = xay; - xmaxy = xby; - } else { - xminy = xby; - xmaxy = xay; - } - if (xaz < xbz) { - xminz = xaz; - xmaxz = xbz; - } else { - xminz = xbz; - xmaxz = xaz; - } - if (yax < ybx) { - yminx = yax; - ymaxx = ybx; - } else { - yminx = ybx; - ymaxx = yax; - } - if (yay < yby) { - yminy = yay; - ymaxy = yby; - } else { - yminy = yby; - ymaxy = yay; - } - if (yaz < ybz) { - yminz = yaz; - ymaxz = ybz; - } else { - yminz = ybz; - ymaxz = yaz; - } - if (zax < zbx) { - zminx = zax; - zmaxx = zbx; - } else { - zminx = zbx; - zmaxx = zax; - } - if (zay < zby) { - zminy = zay; - zmaxy = zby; - } else { - zminy = zby; - zmaxy = zay; - } - if (zaz < zbz) { - zminz = zaz; - zmaxz = zbz; - } else { - zminz = zbz; - zmaxz = zaz; - } - outMin.x = xminx + yminx + zminx + m30(); - outMin.y = xminy + yminy + zminy + m31(); - outMin.z = xminz + yminz + zminz + m32(); - outMax.x = xmaxx + ymaxx + zmaxx + m30(); - outMax.y = xmaxy + ymaxy + zmaxy + m31(); - outMax.z = xmaxz + ymaxz + zmaxz + m32(); - return this; - } - - public Matrix4f transformAab(Vector3fc min, Vector3fc max, Vector3f outMin, Vector3f outMax) { - return transformAab(min.x(), min.y(), min.z(), max.x(), max.y(), max.z(), outMin, outMax); - } - - /** - * Linearly interpolate this and other using the given interpolation factor t - * and store the result in this. - *

- * If t is 0.0 then the result is this. If the interpolation factor is 1.0 - * then the result is other. - * - * @param other - * the other matrix - * @param t - * the interpolation factor between 0.0 and 1.0 - * @return this - */ - public Matrix4f lerp(Matrix4fc other, float t) { - return lerp(other, t, this); - } - - public Matrix4f lerp(Matrix4fc other, float t, Matrix4f dest) { - dest._m00(Math.fma(other.m00() - m00(), t, m00())) - ._m01(Math.fma(other.m01() - m01(), t, m01())) - ._m02(Math.fma(other.m02() - m02(), t, m02())) - ._m03(Math.fma(other.m03() - m03(), t, m03())) - ._m10(Math.fma(other.m10() - m10(), t, m10())) - ._m11(Math.fma(other.m11() - m11(), t, m11())) - ._m12(Math.fma(other.m12() - m12(), t, m12())) - ._m13(Math.fma(other.m13() - m13(), t, m13())) - ._m20(Math.fma(other.m20() - m20(), t, m20())) - ._m21(Math.fma(other.m21() - m21(), t, m21())) - ._m22(Math.fma(other.m22() - m22(), t, m22())) - ._m23(Math.fma(other.m23() - m23(), t, m23())) - ._m30(Math.fma(other.m30() - m30(), t, m30())) - ._m31(Math.fma(other.m31() - m31(), t, m31())) - ._m32(Math.fma(other.m32() - m32(), t, m32())) - ._m33(Math.fma(other.m33() - m33(), t, m33())) - ._properties(properties & other.properties()); - return dest; - } - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with dir - * and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying it, - * use {@link #rotationTowards(Vector3fc, Vector3fc) rotationTowards()}. - *

- * This method is equivalent to calling: mulAffine(new Matrix4f().lookAt(new Vector3f(), new Vector3f(dir).negate(), up).invertAffine(), dest) - * - * @see #rotateTowards(float, float, float, float, float, float, Matrix4f) - * @see #rotationTowards(Vector3fc, Vector3fc) - * - * @param dir - * the direction to rotate towards - * @param up - * the up vector - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateTowards(Vector3fc dir, Vector3fc up, Matrix4f dest) { - return rotateTowards(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z(), dest); - } - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with dir. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying it, - * use {@link #rotationTowards(Vector3fc, Vector3fc) rotationTowards()}. - *

- * This method is equivalent to calling: mulAffine(new Matrix4f().lookAt(new Vector3f(), new Vector3f(dir).negate(), up).invertAffine()) - * - * @see #rotateTowards(float, float, float, float, float, float) - * @see #rotationTowards(Vector3fc, Vector3fc) - * - * @param dir - * the direction to orient towards - * @param up - * the up vector - * @return this - */ - public Matrix4f rotateTowards(Vector3fc dir, Vector3fc up) { - return rotateTowards(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z(), this); - } - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with (dirX, dirY, dirZ). - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying it, - * use {@link #rotationTowards(float, float, float, float, float, float) rotationTowards()}. - *

- * This method is equivalent to calling: mulAffine(new Matrix4f().lookAt(0, 0, 0, -dirX, -dirY, -dirZ, upX, upY, upZ).invertAffine()) - * - * @see #rotateTowards(Vector3fc, Vector3fc) - * @see #rotationTowards(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to rotate towards - * @param dirY - * the y-coordinate of the direction to rotate towards - * @param dirZ - * the z-coordinate of the direction to rotate towards - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix4f rotateTowards(float dirX, float dirY, float dirZ, float upX, float upY, float upZ) { - return rotateTowards(dirX, dirY, dirZ, upX, upY, upZ, this); - } - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with (dirX, dirY, dirZ) - * and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * In order to set the matrix to a rotation transformation without post-multiplying it, - * use {@link #rotationTowards(float, float, float, float, float, float) rotationTowards()}. - *

- * This method is equivalent to calling: mulAffine(new Matrix4f().lookAt(0, 0, 0, -dirX, -dirY, -dirZ, upX, upY, upZ).invertAffine(), dest) - * - * @see #rotateTowards(Vector3fc, Vector3fc) - * @see #rotationTowards(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to rotate towards - * @param dirY - * the y-coordinate of the direction to rotate towards - * @param dirZ - * the z-coordinate of the direction to rotate towards - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f rotateTowards(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Matrix4f dest) { - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - float ndirX = dirX * invDirLength; - float ndirY = dirY * invDirLength; - float ndirZ = dirZ * invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * ndirZ - upZ * ndirY; - leftY = upZ * ndirX - upX * ndirZ; - leftZ = upX * ndirY - upY * ndirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = ndirY * leftZ - ndirZ * leftY; - float upnY = ndirZ * leftX - ndirX * leftZ; - float upnZ = ndirX * leftY - ndirY * leftX; - float rm00 = leftX; - float rm01 = leftY; - float rm02 = leftZ; - float rm10 = upnX; - float rm11 = upnY; - float rm12 = upnZ; - float rm20 = ndirX; - float rm21 = ndirY; - float rm22 = ndirZ; - dest._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()); - float nm00 = m00() * rm00 + m10() * rm01 + m20() * rm02; - float nm01 = m01() * rm00 + m11() * rm01 + m21() * rm02; - float nm02 = m02() * rm00 + m12() * rm01 + m22() * rm02; - float nm03 = m03() * rm00 + m13() * rm01 + m23() * rm02; - float nm10 = m00() * rm10 + m10() * rm11 + m20() * rm12; - float nm11 = m01() * rm10 + m11() * rm11 + m21() * rm12; - float nm12 = m02() * rm10 + m12() * rm11 + m22() * rm12; - float nm13 = m03() * rm10 + m13() * rm11 + m23() * rm12; - dest._m20(m00() * rm20 + m10() * rm21 + m20() * rm22) - ._m21(m01() * rm20 + m11() * rm21 + m21() * rm22) - ._m22(m02() * rm20 + m12() * rm21 + m22() * rm22) - ._m23(m03() * rm20 + m13() * rm21 + m23() * rm22) - ._m00(nm00) - ._m01(nm01) - ._m02(nm02) - ._m03(nm03) - ._m10(nm10) - ._m11(nm11) - ._m12(nm12) - ._m13(nm13) - ._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - return dest; - } - - /** - * Set this matrix to a model transformation for a right-handed coordinate system, - * that aligns the local -z axis with dir. - *

- * In order to apply the rotation transformation to a previous existing transformation, - * use {@link #rotateTowards(float, float, float, float, float, float) rotateTowards}. - *

- * This method is equivalent to calling: setLookAt(new Vector3f(), new Vector3f(dir).negate(), up).invertAffine() - * - * @see #rotationTowards(Vector3fc, Vector3fc) - * @see #rotateTowards(float, float, float, float, float, float) - * - * @param dir - * the direction to orient the local -z axis towards - * @param up - * the up vector - * @return this - */ - public Matrix4f rotationTowards(Vector3fc dir, Vector3fc up) { - return rotationTowards(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z()); - } - - /** - * Set this matrix to a model transformation for a right-handed coordinate system, - * that aligns the local -z axis with (dirX, dirY, dirZ). - *

- * In order to apply the rotation transformation to a previous existing transformation, - * use {@link #rotateTowards(float, float, float, float, float, float) rotateTowards}. - *

- * This method is equivalent to calling: setLookAt(0, 0, 0, -dirX, -dirY, -dirZ, upX, upY, upZ).invertAffine() - * - * @see #rotateTowards(Vector3fc, Vector3fc) - * @see #rotationTowards(float, float, float, float, float, float) - * - * @param dirX - * the x-coordinate of the direction to rotate towards - * @param dirY - * the y-coordinate of the direction to rotate towards - * @param dirZ - * the z-coordinate of the direction to rotate towards - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix4f rotationTowards(float dirX, float dirY, float dirZ, float upX, float upY, float upZ) { - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - float ndirX = dirX * invDirLength; - float ndirY = dirY * invDirLength; - float ndirZ = dirZ * invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * ndirZ - upZ * ndirY; - leftY = upZ * ndirX - upX * ndirZ; - leftZ = upX * ndirY - upY * ndirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = ndirY * leftZ - ndirZ * leftY; - float upnY = ndirZ * leftX - ndirX * leftZ; - float upnZ = ndirX * leftY - ndirY * leftX; - if ((properties & PROPERTY_IDENTITY) == 0) - MemUtil.INSTANCE.identity(this); - this._m00(leftX) - ._m01(leftY) - ._m02(leftZ) - ._m10(upnX) - ._m11(upnY) - ._m12(upnZ) - ._m20(ndirX) - ._m21(ndirY) - ._m22(ndirZ) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - /** - * Set this matrix to a model transformation for a right-handed coordinate system, - * that translates to the given pos and aligns the local -z - * axis with dir. - *

- * This method is equivalent to calling: translation(pos).rotateTowards(dir, up) - * - * @see #translation(Vector3fc) - * @see #rotateTowards(Vector3fc, Vector3fc) - * - * @param pos - * the position to translate to - * @param dir - * the direction to rotate towards - * @param up - * the up vector - * @return this - */ - public Matrix4f translationRotateTowards(Vector3fc pos, Vector3fc dir, Vector3fc up) { - return translationRotateTowards(pos.x(), pos.y(), pos.z(), dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z()); - } - - /** - * Set this matrix to a model transformation for a right-handed coordinate system, - * that translates to the given (posX, posY, posZ) and aligns the local -z - * axis with (dirX, dirY, dirZ). - *

- * This method is equivalent to calling: translation(posX, posY, posZ).rotateTowards(dirX, dirY, dirZ, upX, upY, upZ) - * - * @see #translation(float, float, float) - * @see #rotateTowards(float, float, float, float, float, float) - * - * @param posX - * the x-coordinate of the position to translate to - * @param posY - * the y-coordinate of the position to translate to - * @param posZ - * the z-coordinate of the position to translate to - * @param dirX - * the x-coordinate of the direction to rotate towards - * @param dirY - * the y-coordinate of the direction to rotate towards - * @param dirZ - * the z-coordinate of the direction to rotate towards - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Matrix4f translationRotateTowards(float posX, float posY, float posZ, float dirX, float dirY, float dirZ, float upX, float upY, float upZ) { - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - float ndirX = dirX * invDirLength; - float ndirY = dirY * invDirLength; - float ndirZ = dirZ * invDirLength; - // left = up x direction - float leftX, leftY, leftZ; - leftX = upY * ndirZ - upZ * ndirY; - leftY = upZ * ndirX - upX * ndirZ; - leftZ = upX * ndirY - upY * ndirX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = ndirY * leftZ - ndirZ * leftY; - float upnY = ndirZ * leftX - ndirX * leftZ; - float upnZ = ndirX * leftY - ndirY * leftX; - this._m00(leftX) - ._m01(leftY) - ._m02(leftZ) - ._m03(0.0f) - ._m10(upnX) - ._m11(upnY) - ._m12(upnZ) - ._m13(0.0f) - ._m20(ndirX) - ._m21(ndirY) - ._m22(ndirZ) - ._m23(0.0f) - ._m30(posX) - ._m31(posY) - ._m32(posZ) - ._m33(1.0f) - ._properties(PROPERTY_AFFINE | PROPERTY_ORTHONORMAL); - return this; - } - - public Vector3f getEulerAnglesZYX(Vector3f dest) { - dest.x = Math.atan2(m12(), m22()); - dest.y = Math.atan2(-m02(), Math.sqrt(1.0f - m02() * m02())); - dest.z = Math.atan2(m01(), m00()); - return dest; - } - - public Vector3f getEulerAnglesXYZ(Vector3f dest) { - dest.x = Math.atan2(-m21(), m22()); - dest.y = Math.atan2(m20(), Math.sqrt(1.0f - m20() * m20())); - dest.z = Math.atan2(-m10(), m00()); - return dest; - } - - /** - * Compute the extents of the coordinate system before this {@link #isAffine() affine} transformation was applied - * and store the resulting corner coordinates in corner and the span vectors in - * xDir, yDir and zDir. - *

- * That means, given the maximum extents of the coordinate system between [-1..+1] in all dimensions, - * this method returns one corner and the length and direction of the three base axis vectors in the coordinate - * system before this transformation is applied, which transforms into the corner coordinates [-1, +1]. - *

- * This method is equivalent to computing at least three adjacent corners using {@link #frustumCorner(int, Vector3f)} - * and subtracting them to obtain the length and direction of the span vectors. - * - * @param corner - * will hold one corner of the span (usually the corner {@link Matrix4fc#CORNER_NXNYNZ}) - * @param xDir - * will hold the direction and length of the span along the positive X axis - * @param yDir - * will hold the direction and length of the span along the positive Y axis - * @param zDir - * will hold the direction and length of the span along the positive z axis - * @return this - */ - public Matrix4f affineSpan(Vector3f corner, Vector3f xDir, Vector3f yDir, Vector3f zDir) { - float a = m10() * m22(), b = m10() * m21(), c = m10() * m02(), d = m10() * m01(); - float e = m11() * m22(), f = m11() * m20(), g = m11() * m02(), h = m11() * m00(); - float i = m12() * m21(), j = m12() * m20(), k = m12() * m01(), l = m12() * m00(); - float m = m20() * m02(), n = m20() * m01(), o = m21() * m02(), p = m21() * m00(); - float q = m22() * m01(), r = m22() * m00(); - float s = 1.0f / (m00() * m11() - m01() * m10()) * m22() + (m02() * m10() - m00() * m12()) * m21() + (m01() * m12() - m02() * m11()) * m20(); - float nm00 = (e - i) * s, nm01 = (o - q) * s, nm02 = (k - g) * s; - float nm10 = (j - a) * s, nm11 = (r - m) * s, nm12 = (c - l) * s; - float nm20 = (b - f) * s, nm21 = (n - p) * s, nm22 = (h - d) * s; - corner.x = -nm00 - nm10 - nm20 + (a * m31() - b * m32() + f * m32() - e * m30() + i * m30() - j * m31()) * s; - corner.y = -nm01 - nm11 - nm21 + (m * m31() - n * m32() + p * m32() - o * m30() + q * m30() - r * m31()) * s; - corner.z = -nm02 - nm12 - nm22 + (g * m30() - k * m30() + l * m31() - c * m31() + d * m32() - h * m32()) * s; - xDir.x = 2.0f * nm00; xDir.y = 2.0f * nm01; xDir.z = 2.0f * nm02; - yDir.x = 2.0f * nm10; yDir.y = 2.0f * nm11; yDir.z = 2.0f * nm12; - zDir.x = 2.0f * nm20; zDir.y = 2.0f * nm21; zDir.z = 2.0f * nm22; - return this; - } - - public boolean testPoint(float x, float y, float z) { - float nxX = m03() + m00(), nxY = m13() + m10(), nxZ = m23() + m20(), nxW = m33() + m30(); - float pxX = m03() - m00(), pxY = m13() - m10(), pxZ = m23() - m20(), pxW = m33() - m30(); - float nyX = m03() + m01(), nyY = m13() + m11(), nyZ = m23() + m21(), nyW = m33() + m31(); - float pyX = m03() - m01(), pyY = m13() - m11(), pyZ = m23() - m21(), pyW = m33() - m31(); - float nzX = m03() + m02(), nzY = m13() + m12(), nzZ = m23() + m22(), nzW = m33() + m32(); - float pzX = m03() - m02(), pzY = m13() - m12(), pzZ = m23() - m22(), pzW = m33() - m32(); - 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; - } - - public boolean testSphere(float x, float y, float z, float r) { - float invl; - float nxX = m03() + m00(), nxY = m13() + m10(), nxZ = m23() + m20(), nxW = m33() + m30(); - invl = Math.invsqrt(nxX * nxX + nxY * nxY + nxZ * nxZ); - nxX *= invl; nxY *= invl; nxZ *= invl; nxW *= invl; - float pxX = m03() - m00(), pxY = m13() - m10(), pxZ = m23() - m20(), pxW = m33() - m30(); - invl = Math.invsqrt(pxX * pxX + pxY * pxY + pxZ * pxZ); - pxX *= invl; pxY *= invl; pxZ *= invl; pxW *= invl; - float nyX = m03() + m01(), nyY = m13() + m11(), nyZ = m23() + m21(), nyW = m33() + m31(); - invl = Math.invsqrt(nyX * nyX + nyY * nyY + nyZ * nyZ); - nyX *= invl; nyY *= invl; nyZ *= invl; nyW *= invl; - float pyX = m03() - m01(), pyY = m13() - m11(), pyZ = m23() - m21(), pyW = m33() - m31(); - invl = Math.invsqrt(pyX * pyX + pyY * pyY + pyZ * pyZ); - pyX *= invl; pyY *= invl; pyZ *= invl; pyW *= invl; - float nzX = m03() + m02(), nzY = m13() + m12(), nzZ = m23() + m22(), nzW = m33() + m32(); - invl = Math.invsqrt(nzX * nzX + nzY * nzY + nzZ * nzZ); - nzX *= invl; nzY *= invl; nzZ *= invl; nzW *= invl; - float pzX = m03() - m02(), pzY = m13() - m12(), pzZ = m23() - m22(), pzW = m33() - m32(); - invl = Math.invsqrt(pzX * pzX + pzY * pzY + pzZ * pzZ); - pzX *= invl; pzY *= invl; pzZ *= invl; pzW *= invl; - 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; - } - - public boolean testAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - float nxX = m03() + m00(), nxY = m13() + m10(), nxZ = m23() + m20(), nxW = m33() + m30(); - float pxX = m03() - m00(), pxY = m13() - m10(), pxZ = m23() - m20(), pxW = m33() - m30(); - float nyX = m03() + m01(), nyY = m13() + m11(), nyZ = m23() + m21(), nyW = m33() + m31(); - float pyX = m03() - m01(), pyY = m13() - m11(), pyZ = m23() - m21(), pyW = m33() - m31(); - float nzX = m03() + m02(), nzY = m13() + m12(), nzZ = m23() + m22(), nzW = m33() + m32(); - float pzX = m03() - m02(), pzY = m13() - m12(), pzZ = m23() - m22(), pzW = m33() - m32(); - /* - * 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; - } - - /** - * Apply an oblique projection transformation to this matrix with the given values for a and - * b. - *

- * If M is this matrix and O the oblique transformation matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * oblique transformation will be applied first! - *

- * The oblique transformation is defined as: - *

-     * x' = x + a*z
-     * y' = y + a*z
-     * z' = z
-     * 
- * or in matrix form: - *
-     * 1 0 a 0
-     * 0 1 b 0
-     * 0 0 1 0
-     * 0 0 0 1
-     * 
- * - * @param a - * the value for the z factor that applies to x - * @param b - * the value for the z factor that applies to y - * @return this - */ - public Matrix4f obliqueZ(float a, float b) { - return this - ._m20(m00() * a + m10() * b + m20()) - ._m21(m01() * a + m11() * b + m21()) - ._m22(m02() * a + m12() * b + m22()) - ._properties(this.properties & PROPERTY_AFFINE); - } - - /** - * Apply an oblique projection transformation to this matrix with the given values for a and - * b and store the result in dest. - *

- * If M is this matrix and O the oblique transformation matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * oblique transformation will be applied first! - *

- * The oblique transformation is defined as: - *

-     * x' = x + a*z
-     * y' = y + a*z
-     * z' = z
-     * 
- * or in matrix form: - *
-     * 1 0 a 0
-     * 0 1 b 0
-     * 0 0 1 0
-     * 0 0 0 1
-     * 
- * - * @param a - * the value for the z factor that applies to x - * @param b - * the value for the z factor that applies to y - * @param dest - * will hold the result - * @return dest - */ - public Matrix4f obliqueZ(float a, float b, Matrix4f dest) { - dest._m00(m00()) - ._m01(m01()) - ._m02(m02()) - ._m03(m03()) - ._m10(m10()) - ._m11(m11()) - ._m12(m12()) - ._m13(m13()) - ._m20(m00() * a + m10() * b + m20()) - ._m21(m01() * a + m11() * b + m21()) - ._m22(m02() * a + m12() * b + m22()) - ._m23(m23()) - ._m30(m30()) - ._m31(m31()) - ._m32(m32()) - ._m33(m33()) - ._properties(this.properties & PROPERTY_AFFINE); - return dest; - } - - /** - * Create a view and projection matrix from a given eye position, a given bottom left corner position p of the near plane rectangle - * and the extents of the near plane rectangle along its local x and y axes, and store the resulting matrices - * in projDest and viewDest. - *

- * This method creates a view and perspective projection matrix assuming that there is a pinhole camera at position eye - * projecting the scene onto the near plane defined by the rectangle. - *

- * All positions and lengths are in the same (world) unit. - * - * @param eye - * the position of the camera - * @param p - * the bottom left corner of the near plane rectangle (will map to the bottom left corner in window coordinates) - * @param x - * the direction and length of the local "bottom/top" X axis/side of the near plane rectangle - * @param y - * the direction and length of the local "left/right" Y axis/side of the near plane rectangle - * @param nearFarDist - * the distance between the far and near plane (the near plane will be calculated by this method). - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * If the special value {@link Float#NEGATIVE_INFINITY} is used, the near and far planes will be swapped and - * the near clipping plane will be at positive infinity. - * If a negative value is used (except for {@link Float#NEGATIVE_INFINITY}) the near and far planes will be swapped - * @param zeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param projDest - * will hold the resulting projection matrix - * @param viewDest - * will hold the resulting view matrix - */ - public static void projViewFromRectangle( - Vector3f eye, Vector3f p, Vector3f x, Vector3f y, float nearFarDist, boolean zeroToOne, - Matrix4f projDest, Matrix4f viewDest) { - float zx = y.y * x.z - y.z * x.y, zy = y.z * x.x - y.x * x.z, zz = y.x * x.y - y.y * x.x; - float zd = zx * (p.x - eye.x) + zy * (p.y - eye.y) + zz * (p.z - eye.z); - float zs = zd >= 0 ? 1 : -1; zx *= zs; zy *= zs; zz *= zs; zd *= zs; - viewDest.setLookAt(eye.x, eye.y, eye.z, eye.x + zx, eye.y + zy, eye.z + zz, y.x, y.y, y.z); - float px = viewDest.m00() * p.x + viewDest.m10() * p.y + viewDest.m20() * p.z + viewDest.m30(); - float py = viewDest.m01() * p.x + viewDest.m11() * p.y + viewDest.m21() * p.z + viewDest.m31(); - float tx = viewDest.m00() * x.x + viewDest.m10() * x.y + viewDest.m20() * x.z; - float ty = viewDest.m01() * y.x + viewDest.m11() * y.y + viewDest.m21() * y.z; - float len = Math.sqrt(zx * zx + zy * zy + zz * zz); - float near = zd / len, far; - if (Float.isInfinite(nearFarDist) && nearFarDist < 0.0f) { - far = near; - near = Float.POSITIVE_INFINITY; - } else if (Float.isInfinite(nearFarDist) && nearFarDist > 0.0f) { - far = Float.POSITIVE_INFINITY; - } else if (nearFarDist < 0.0f) { - far = near; - near = near + nearFarDist; - } else { - far = near + nearFarDist; - } - projDest.setFrustum(px, px + tx, py, py + ty, near, far, zeroToOne); - } - - /** - * Apply a transformation to this matrix to ensure that the local Y axis (as obtained by {@link #positiveY(Vector3f)}) - * will be coplanar to the plane spanned by the local Z axis (as obtained by {@link #positiveZ(Vector3f)}) and the - * given vector up. - *

- * This effectively ensures that the resulting matrix will be equal to the one obtained from - * {@link #setLookAt(Vector3fc, Vector3fc, Vector3fc)} called with the current - * local origin of this matrix (as obtained by {@link #originAffine(Vector3f)}), the sum of this position and the - * negated local Z axis as well as the given vector up. - *

- * This method must only be called on {@link #isAffine()} matrices. - * - * @param up - * the up vector - * @return this - */ - public Matrix4f withLookAtUp(Vector3fc up) { - return withLookAtUp(up.x(), up.y(), up.z(), this); - } - - public Matrix4f withLookAtUp(Vector3fc up, Matrix4f dest) { - return withLookAtUp(up.x(), up.y(), up.z()); - } - - /** - * Apply a transformation to this matrix to ensure that the local Y axis (as obtained by {@link #positiveY(Vector3f)}) - * will be coplanar to the plane spanned by the local Z axis (as obtained by {@link #positiveZ(Vector3f)}) and the - * given vector (upX, upY, upZ). - *

- * This effectively ensures that the resulting matrix will be equal to the one obtained from - * {@link #setLookAt(float, float, float, float, float, float, float, float, float)} called with the current - * local origin of this matrix (as obtained by {@link #originAffine(Vector3f)}), the sum of this position and the - * negated local Z axis as well as the given vector (upX, upY, upZ). - *

- * This method must only be called on {@link #isAffine()} matrices. - * - * @param upX - * the x coordinate of the up vector - * @param upY - * the y coordinate of the up vector - * @param upZ - * the z coordinate of the up vector - * @return this - */ - public Matrix4f withLookAtUp(float upX, float upY, float upZ) { - return withLookAtUp(upX, upY, upZ, this); - } - - public Matrix4f withLookAtUp(float upX, float upY, float upZ, Matrix4f dest) { - float y = (upY * m21() - upZ * m11()) * m02() + - (upZ * m01() - upX * m21()) * m12() + - (upX * m11() - upY * m01()) * m22(); - float x = upX * m01() + upY * m11() + upZ * m21(); - if ((properties & PROPERTY_ORTHONORMAL) == 0) - x *= Math.sqrt(m01() * m01() + m11() * m11() + m21() * m21()); - float invsqrt = Math.invsqrt(y * y + x * x); - float c = x * invsqrt, s = y * invsqrt; - float nm00 = c * m00() - s * m01(), nm10 = c * m10() - s * m11(), nm20 = c * m20() - s * m21(), nm31 = s * m30() + c * m31(); - float nm01 = s * m00() + c * m01(), nm11 = s * m10() + c * m11(), nm21 = s * m20() + c * m21(), nm30 = c * m30() - s * m31(); - dest._m00(nm00)._m10(nm10)._m20(nm20)._m30(nm30) - ._m01(nm01)._m11(nm11)._m21(nm21)._m31(nm31); - if (dest != this) { - dest._m02(m02())._m12(m12())._m22(m22())._m32(m32()) - ._m03(m03())._m13(m13())._m23(m23())._m33(m33()); - } - dest._properties(properties & ~(PROPERTY_PERSPECTIVE | PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); - return dest; - } - - /** - * Multiply this by the matrix - *

-     * 1 0 0 0
-     * 0 0 1 0
-     * 0 1 0 0
-     * 0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapXZY() { - return mapXZY(this); - } - public Matrix4f mapXZY(Matrix4f dest) { - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(m00())._m01(m01())._m02(m02())._m03(m03())._m10(m20())._m11(m21())._m12(m22())._m13(m13())._m20(m10)._m21(m11)._m22(m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 1 0  0 0
-     * 0 0 -1 0
-     * 0 1  0 0
-     * 0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapXZnY() { - return mapXZnY(this); - } - public Matrix4f mapXZnY(Matrix4f dest) { - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(m00())._m01(m01())._m02(m02())._m03(m03())._m10(m20())._m11(m21())._m12(m22())._m13(m13())._m20(-m10)._m21(-m11)._m22(-m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 1  0  0 0
-     * 0 -1  0 0
-     * 0  0 -1 0
-     * 0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapXnYnZ() { - return mapXnYnZ(this); - } - public Matrix4f mapXnYnZ(Matrix4f dest) { - return dest._m00(m00())._m01(m01())._m02(m02())._m03(m03())._m10(-m10())._m11(-m11())._m12(-m12())._m13(m13())._m20(-m20())._m21(-m21())._m22(-m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 1  0 0 0
-     * 0  0 1 0
-     * 0 -1 0 0
-     * 0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapXnZY() { - return mapXnZY(this); - } - public Matrix4f mapXnZY(Matrix4f dest) { - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(m00())._m01(m01())._m02(m02())._m03(m03())._m10(-m20())._m11(-m21())._m12(-m22())._m13(m13())._m20(m10)._m21(m11)._m22(m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 1  0  0 0
-     * 0  0 -1 0
-     * 0 -1  0 0
-     * 0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapXnZnY() { - return mapXnZnY(this); - } - public Matrix4f mapXnZnY(Matrix4f dest) { - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(m00())._m01(m01())._m02(m02())._m03(m03())._m10(-m20())._m11(-m21())._m12(-m22())._m13(m13())._m20(-m10)._m21(-m11)._m22(-m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 1 0 0
-     * 1 0 0 0
-     * 0 0 1 0
-     * 0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapYXZ() { - return mapYXZ(this); - } - public Matrix4f mapYXZ(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m10())._m01(m11())._m02(m12())._m03(m03())._m10(m00)._m11(m01)._m12(m02)._m13(m13())._m20(m20())._m21(m21())._m22(m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 1  0 0
-     * 1 0  0 0
-     * 0 0 -1 0
-     * 0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapYXnZ() { - return mapYXnZ(this); - } - public Matrix4f mapYXnZ(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m10())._m01(m11())._m02(m12())._m03(m03())._m10(m00)._m11(m01)._m12(m02)._m13(m13())._m20(-m20())._m21(-m21())._m22(-m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 0 1 0
-     * 1 0 0 0
-     * 0 1 0 0
-     * 0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapYZX() { - return mapYZX(this); - } - public Matrix4f mapYZX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m10())._m01(m11())._m02(m12())._m03(m03())._m10(m20())._m11(m21())._m12(m22())._m13(m13())._m20(m00)._m21(m01)._m22(m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 0 -1 0
-     * 1 0  0 0
-     * 0 1  0 0
-     * 0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapYZnX() { - return mapYZnX(this); - } - public Matrix4f mapYZnX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m10())._m01(m11())._m02(m12())._m03(m03())._m10(m20())._m11(m21())._m12(m22())._m13(m13())._m20(-m00)._m21(-m01)._m22(-m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 -1 0 0
-     * 1  0 0 0
-     * 0  0 1 0
-     * 0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapYnXZ() { - return mapYnXZ(this); - } - public Matrix4f mapYnXZ(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m10())._m01(m11())._m02(m12())._m03(m03())._m10(-m00)._m11(-m01)._m12(-m02)._m13(m13())._m20(m20())._m21(m21())._m22(m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 -1  0 0
-     * 1  0  0 0
-     * 0  0 -1 0
-     * 0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapYnXnZ() { - return mapYnXnZ(this); - } - public Matrix4f mapYnXnZ(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m10())._m01(m11())._m02(m12())._m03(m03())._m10(-m00)._m11(-m01)._m12(-m02)._m13(m13())._m20(-m20())._m21(-m21())._m22(-m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0  0 1 0
-     * 1  0 0 0
-     * 0 -1 0 0
-     * 0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapYnZX() { - return mapYnZX(this); - } - public Matrix4f mapYnZX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m10())._m01(m11())._m02(m12())._m03(m03())._m10(-m20())._m11(-m21())._m12(-m22())._m13(m13())._m20(m00)._m21(m01)._m22(m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0  0 -1 0
-     * 1  0  0 0
-     * 0 -1  0 0
-     * 0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapYnZnX() { - return mapYnZnX(this); - } - public Matrix4f mapYnZnX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m10())._m01(m11())._m02(m12())._m03(m03())._m10(-m20())._m11(-m21())._m12(-m22())._m13(m13())._m20(-m00)._m21(-m01)._m22(-m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 1 0 0
-     * 0 0 1 0
-     * 1 0 0 0
-     * 0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapZXY() { - return mapZXY(this); - } - public Matrix4f mapZXY(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(m20())._m01(m21())._m02(m22())._m03(m03())._m10(m00)._m11(m01)._m12(m02)._m13(m13())._m20(m10)._m21(m11)._m22(m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 1  0 0
-     * 0 0 -1 0
-     * 1 0  0 0
-     * 0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapZXnY() { - return mapZXnY(this); - } - public Matrix4f mapZXnY(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(m20())._m01(m21())._m02(m22())._m03(m03())._m10(m00)._m11(m01)._m12(m02)._m13(m13())._m20(-m10)._m21(-m11)._m22(-m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 0 1 0
-     * 0 1 0 0
-     * 1 0 0 0
-     * 0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapZYX() { - return mapZYX(this); - } - public Matrix4f mapZYX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m20())._m01(m21())._m02(m22())._m03(m03())._m10(m10())._m11(m11())._m12(m12())._m13(m13())._m20(m00)._m21(m01)._m22(m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 0 -1 0
-     * 0 1  0 0
-     * 1 0  0 0
-     * 0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapZYnX() { - return mapZYnX(this); - } - public Matrix4f mapZYnX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m20())._m01(m21())._m02(m22())._m03(m03())._m10(m10())._m11(m11())._m12(m12())._m13(m13())._m20(-m00)._m21(-m01)._m22(-m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 -1 0 0
-     * 0  0 1 0
-     * 1  0 0 0
-     * 0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapZnXY() { - return mapZnXY(this); - } - public Matrix4f mapZnXY(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(m20())._m01(m21())._m02(m22())._m03(m03())._m10(-m00)._m11(-m01)._m12(-m02)._m13(m13())._m20(m10)._m21(m11)._m22(m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0 -1  0 0
-     * 0  0 -1 0
-     * 1  0  0 0
-     * 0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapZnXnY() { - return mapZnXnY(this); - } - public Matrix4f mapZnXnY(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(m20())._m01(m21())._m02(m22())._m03(m03())._m10(-m00)._m11(-m01)._m12(-m02)._m13(m13())._m20(-m10)._m21(-m11)._m22(-m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0  0 1 0
-     * 0 -1 0 0
-     * 1  0 0 0
-     * 0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapZnYX() { - return mapZnYX(this); - } - public Matrix4f mapZnYX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m20())._m01(m21())._m02(m22())._m03(m03())._m10(-m10())._m11(-m11())._m12(-m12())._m13(m13())._m20(m00)._m21(m01)._m22(m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * 0  0 -1 0
-     * 0 -1  0 0
-     * 1  0  0 0
-     * 0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapZnYnX() { - return mapZnYnX(this); - } - public Matrix4f mapZnYnX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(m20())._m01(m21())._m02(m22())._m03(m03())._m10(-m10())._m11(-m11())._m12(-m12())._m13(m13())._m20(-m00)._m21(-m01)._m22(-m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * -1 0  0 0
-     *  0 1  0 0
-     *  0 0 -1 0
-     *  0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnXYnZ() { - return mapnXYnZ(this); - } - public Matrix4f mapnXYnZ(Matrix4f dest) { - return dest._m00(-m00())._m01(-m01())._m02(-m02())._m03(m03())._m10(m10())._m11(m11())._m12(m12())._m13(m13())._m20(-m20())._m21(-m21())._m22(-m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * -1 0 0 0
-     *  0 0 1 0
-     *  0 1 0 0
-     *  0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnXZY() { - return mapnXZY(this); - } - public Matrix4f mapnXZY(Matrix4f dest) { - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(-m00())._m01(-m01())._m02(-m02())._m03(m03())._m10(m20())._m11(m21())._m12(m22())._m13(m13())._m20(m10)._m21(m11)._m22(m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * -1 0  0 0
-     *  0 0 -1 0
-     *  0 1  0 0
-     *  0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnXZnY() { - return mapnXZnY(this); - } - public Matrix4f mapnXZnY(Matrix4f dest) { - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(-m00())._m01(-m01())._m02(-m02())._m03(m03())._m10(m20())._m11(m21())._m12(m22())._m13(m13())._m20(-m10)._m21(-m11)._m22(-m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * -1  0 0 0
-     *  0 -1 0 0
-     *  0  0 1 0
-     *  0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnXnYZ() { - return mapnXnYZ(this); - } - public Matrix4f mapnXnYZ(Matrix4f dest) { - return dest._m00(-m00())._m01(-m01())._m02(-m02())._m03(m03())._m10(-m10())._m11(-m11())._m12(-m12())._m13(m13())._m20(m20())._m21(m21())._m22(m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * -1  0  0 0
-     *  0 -1  0 0
-     *  0  0 -1 0
-     *  0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnXnYnZ() { - return mapnXnYnZ(this); - } - public Matrix4f mapnXnYnZ(Matrix4f dest) { - return dest._m00(-m00())._m01(-m01())._m02(-m02())._m03(m03())._m10(-m10())._m11(-m11())._m12(-m12())._m13(m13())._m20(-m20())._m21(-m21())._m22(-m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * -1  0 0 0
-     *  0  0 1 0
-     *  0 -1 0 0
-     *  0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnXnZY() { - return mapnXnZY(this); - } - public Matrix4f mapnXnZY(Matrix4f dest) { - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(-m00())._m01(-m01())._m02(-m02())._m03(m03())._m10(-m20())._m11(-m21())._m12(-m22())._m13(m13())._m20(m10)._m21(m11)._m22(m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     * -1  0  0 0
-     *  0  0 -1 0
-     *  0 -1  0 0
-     *  0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnXnZnY() { - return mapnXnZnY(this); - } - public Matrix4f mapnXnZnY(Matrix4f dest) { - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(-m00())._m01(-m01())._m02(-m02())._m03(m03())._m10(-m20())._m11(-m21())._m12(-m22())._m13(m13())._m20(-m10)._m21(-m11)._m22(-m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 1 0 0
-     * -1 0 0 0
-     *  0 0 1 0
-     *  0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnYXZ() { - return mapnYXZ(this); - } - public Matrix4f mapnYXZ(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m10())._m01(-m11())._m02(-m12())._m03(m03())._m10(m00)._m11(m01)._m12(m02)._m13(m13())._m20(m20())._m21(m21())._m22(m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 1  0 0
-     * -1 0  0 0
-     *  0 0 -1 0
-     *  0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnYXnZ() { - return mapnYXnZ(this); - } - public Matrix4f mapnYXnZ(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m10())._m01(-m11())._m02(-m12())._m03(m03())._m10(m00)._m11(m01)._m12(m02)._m13(m13())._m20(-m20())._m21(-m21())._m22(-m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 0 1 0
-     * -1 0 0 0
-     *  0 1 0 0
-     *  0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnYZX() { - return mapnYZX(this); - } - public Matrix4f mapnYZX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m10())._m01(-m11())._m02(-m12())._m03(m03())._m10(m20())._m11(m21())._m12(m22())._m13(m13())._m20(m00)._m21(m01)._m22(m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 0 -1 0
-     * -1 0  0 0
-     *  0 1  0 0
-     *  0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnYZnX() { - return mapnYZnX(this); - } - public Matrix4f mapnYZnX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m10())._m01(-m11())._m02(-m12())._m03(m03())._m10(m20())._m11(m21())._m12(m22())._m13(m13())._m20(-m00)._m21(-m01)._m22(-m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 -1 0 0
-     * -1  0 0 0
-     *  0  0 1 0
-     *  0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnYnXZ() { - return mapnYnXZ(this); - } - public Matrix4f mapnYnXZ(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m10())._m01(-m11())._m02(-m12())._m03(m03())._m10(-m00)._m11(-m01)._m12(-m02)._m13(m13())._m20(m20())._m21(m21())._m22(m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 -1  0 0
-     * -1  0  0 0
-     *  0  0 -1 0
-     *  0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnYnXnZ() { - return mapnYnXnZ(this); - } - public Matrix4f mapnYnXnZ(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m10())._m01(-m11())._m02(-m12())._m03(m03())._m10(-m00)._m11(-m01)._m12(-m02)._m13(m13())._m20(-m20())._m21(-m21())._m22(-m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0  0 1 0
-     * -1  0 0 0
-     *  0 -1 0 0
-     *  0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnYnZX() { - return mapnYnZX(this); - } - public Matrix4f mapnYnZX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m10())._m01(-m11())._m02(-m12())._m03(m03())._m10(-m20())._m11(-m21())._m12(-m22())._m13(m13())._m20(m00)._m21(m01)._m22(m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0  0 -1 0
-     * -1  0  0 0
-     *  0 -1  0 0
-     *  0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnYnZnX() { - return mapnYnZnX(this); - } - public Matrix4f mapnYnZnX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m10())._m01(-m11())._m02(-m12())._m03(m03())._m10(-m20())._m11(-m21())._m12(-m22())._m13(m13())._m20(-m00)._m21(-m01)._m22(-m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 1 0 0
-     *  0 0 1 0
-     * -1 0 0 0
-     *  0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnZXY() { - return mapnZXY(this); - } - public Matrix4f mapnZXY(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(-m20())._m01(-m21())._m02(-m22())._m03(m03())._m10(m00)._m11(m01)._m12(m02)._m13(m13())._m20(m10)._m21(m11)._m22(m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 1  0 0
-     *  0 0 -1 0
-     * -1 0  0 0
-     *  0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnZXnY() { - return mapnZXnY(this); - } - public Matrix4f mapnZXnY(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(-m20())._m01(-m21())._m02(-m22())._m03(m03())._m10(m00)._m11(m01)._m12(m02)._m13(m13())._m20(-m10)._m21(-m11)._m22(-m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 0 1 0
-     *  0 1 0 0
-     * -1 0 0 0
-     *  0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnZYX() { - return mapnZYX(this); - } - public Matrix4f mapnZYX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m20())._m01(-m21())._m02(-m22())._m03(m03())._m10(m10())._m11(m11())._m12(m12())._m13(m13())._m20(m00)._m21(m01)._m22(m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 0 -1 0
-     *  0 1  0 0
-     * -1 0  0 0
-     *  0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnZYnX() { - return mapnZYnX(this); - } - public Matrix4f mapnZYnX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m20())._m01(-m21())._m02(-m22())._m03(m03())._m10(m10())._m11(m11())._m12(m12())._m13(m13())._m20(-m00)._m21(-m01)._m22(-m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 -1 0 0
-     *  0  0 1 0
-     * -1  0 0 0
-     *  0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnZnXY() { - return mapnZnXY(this); - } - public Matrix4f mapnZnXY(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(-m20())._m01(-m21())._m02(-m22())._m03(m03())._m10(-m00)._m11(-m01)._m12(-m02)._m13(m13())._m20(m10)._m21(m11)._m22(m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0 -1  0 0
-     *  0  0 -1 0
-     * -1  0  0 0
-     *  0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnZnXnY() { - return mapnZnXnY(this); - } - public Matrix4f mapnZnXnY(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - float m10 = this.m10(), m11 = this.m11(), m12 = this.m12(); - return dest._m00(-m20())._m01(-m21())._m02(-m22())._m03(m03())._m10(-m00)._m11(-m01)._m12(-m02)._m13(m13())._m20(-m10)._m21(-m11)._m22(-m12)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0  0 1 0
-     *  0 -1 0 0
-     * -1  0 0 0
-     *  0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnZnYX() { - return mapnZnYX(this); - } - public Matrix4f mapnZnYX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m20())._m01(-m21())._m02(-m22())._m03(m03())._m10(-m10())._m11(-m11())._m12(-m12())._m13(m13())._m20(m00)._m21(m01)._m22(m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - /** - * Multiply this by the matrix - *
-     *  0  0 -1 0
-     *  0 -1  0 0
-     * -1  0  0 0
-     *  0  0  0 1
-     * 
- * - * @return this - */ - public Matrix4f mapnZnYnX() { - return mapnZnYnX(this); - } - public Matrix4f mapnZnYnX(Matrix4f dest) { - float m00 = this.m00(), m01 = this.m01(), m02 = this.m02(); - return dest._m00(-m20())._m01(-m21())._m02(-m22())._m03(m03())._m10(-m10())._m11(-m11())._m12(-m12())._m13(m13())._m20(-m00)._m21(-m01)._m22(-m02)._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - - /** - * Multiply this by the matrix - *
-     * -1 0 0 0
-     *  0 1 0 0
-     *  0 0 1 0
-     *  0 0 0 1
-     * 
- * - * @return this - */ - public Matrix4f negateX() { - return _m00(-m00())._m01(-m01())._m02(-m02())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - public Matrix4f negateX(Matrix4f dest) { - return dest._m00(-m00())._m01(-m01())._m02(-m02())._m03(m03())._m10(m10())._m11(m11())._m12(m12())._m13(m13())._m20(m20())._m21(m21())._m22(m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - - /** - * Multiply this by the matrix - *
-     * 1  0 0 0
-     * 0 -1 0 0
-     * 0  0 1 0
-     * 0  0 0 1
-     * 
- * - * @return this - */ - public Matrix4f negateY() { - return _m10(-m10())._m11(-m11())._m12(-m12())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - public Matrix4f negateY(Matrix4f dest) { - return dest._m00(m00())._m01(m01())._m02(m02())._m03(m03())._m10(-m10())._m11(-m11())._m12(-m12())._m13(m13())._m20(m20())._m21(m21())._m22(m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - - /** - * Multiply this by the matrix - *
-     * 1 0  0 0
-     * 0 1  0 0
-     * 0 0 -1 0
-     * 0 0  0 1
-     * 
- * - * @return this - */ - public Matrix4f negateZ() { - return _m20(-m20())._m21(-m21())._m22(-m22())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - public Matrix4f negateZ(Matrix4f dest) { - return dest._m00(m00())._m01(m01())._m02(m02())._m03(m03())._m10(m10())._m11(m11())._m12(m12())._m13(m13())._m20(-m20())._m21(-m21())._m22(-m22())._m23(m23())._m30(m30())._m31(m31())._m32(m32())._m33(m33())._properties(properties & (PROPERTY_AFFINE | PROPERTY_ORTHONORMAL)); - } - - public boolean isFinite() { - return Math.isFinite(m00()) && Math.isFinite(m01()) && Math.isFinite(m02()) && Math.isFinite(m03()) && - Math.isFinite(m10()) && Math.isFinite(m11()) && Math.isFinite(m12()) && Math.isFinite(m13()) && - Math.isFinite(m20()) && Math.isFinite(m21()) && Math.isFinite(m22()) && Math.isFinite(m23()) && - Math.isFinite(m30()) && Math.isFinite(m31()) && Math.isFinite(m32()) && Math.isFinite(m33()); - } - - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix4fStack.java b/src/main/java/com/jozufozu/flywheel/util/joml/Matrix4fStack.java deleted file mode 100644 index 559a500ac..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix4fStack.java +++ /dev/null @@ -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. - *

- * 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 current 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. - *

- * 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 this - * {@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. - *

- * 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. - *

- * 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; - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix4fc.java b/src/main/java/com/jozufozu/flywheel/util/joml/Matrix4fc.java deleted file mode 100644 index 9652c5ffa..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Matrix4fc.java +++ /dev/null @@ -1,5926 +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 4x4 matrix of single-precision floats. - * - * @author Kai Burjack - */ -public interface Matrix4fc { - - /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} - * identifying the plane with equation x=-1 when using the identity matrix. - */ - int PLANE_NX = 0; - /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} - * identifying the plane with equation x=1 when using the identity matrix. - */ - int PLANE_PX = 1; - /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} - * identifying the plane with equation y=-1 when using the identity matrix. - */ - int PLANE_NY = 2; - /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} - * identifying the plane with equation y=1 when using the identity matrix. - */ - int PLANE_PY = 3; - /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} - * identifying the plane with equation z=-1 when using the identity matrix. - */ - int PLANE_NZ = 4; - /** - * Argument to the first parameter of {@link #frustumPlane(int, Vector4f)} - * identifying the plane with equation z=1 when using the identity matrix. - */ - int PLANE_PZ = 5; - /** - * Argument to the first parameter of {@link #frustumCorner(int, Vector3f)} - * identifying the corner (-1, -1, -1) when using the identity matrix. - */ - int CORNER_NXNYNZ = 0; - /** - * Argument to the first parameter of {@link #frustumCorner(int, Vector3f)} - * identifying the corner (1, -1, -1) when using the identity matrix. - */ - int CORNER_PXNYNZ = 1; - /** - * Argument to the first parameter of {@link #frustumCorner(int, Vector3f)} - * identifying the corner (1, 1, -1) when using the identity matrix. - */ - int CORNER_PXPYNZ = 2; - /** - * Argument to the first parameter of {@link #frustumCorner(int, Vector3f)} - * identifying the corner (-1, 1, -1) when using the identity matrix. - */ - int CORNER_NXPYNZ = 3; - /** - * Argument to the first parameter of {@link #frustumCorner(int, Vector3f)} - * identifying the corner (1, -1, 1) when using the identity matrix. - */ - int CORNER_PXNYPZ = 4; - /** - * Argument to the first parameter of {@link #frustumCorner(int, Vector3f)} - * identifying the corner (-1, -1, 1) when using the identity matrix. - */ - int CORNER_NXNYPZ = 5; - /** - * Argument to the first parameter of {@link #frustumCorner(int, Vector3f)} - * identifying the corner (-1, 1, 1) when using the identity matrix. - */ - int CORNER_NXPYPZ = 6; - /** - * Argument to the first parameter of {@link #frustumCorner(int, Vector3f)} - * identifying the corner (1, 1, 1) when using the identity matrix. - */ - int CORNER_PXPYPZ = 7; - - /** - * Bit returned by {@link #properties()} to indicate that the matrix represents a perspective transformation. - */ - byte PROPERTY_PERSPECTIVE = 1<<0; - /** - * Bit returned by {@link #properties()} to indicate that the matrix represents an affine transformation. - */ - byte PROPERTY_AFFINE = 1<<1; - /** - * Bit returned by {@link #properties()} to indicate that the matrix represents the identity transformation. - */ - byte PROPERTY_IDENTITY = 1<<2; - /** - * Bit returned by {@link #properties()} to indicate that the matrix represents a pure translation transformation. - */ - byte PROPERTY_TRANSLATION = 1<<3; - /** - * Bit returned by {@link #properties()} to indicate that the upper-left 3x3 submatrix represents an orthogonal - * matrix (i.e. orthonormal basis). For practical reasons, this property also always implies - * {@link #PROPERTY_AFFINE} in this implementation. - */ - byte PROPERTY_ORTHONORMAL = 1<<4; - - /** - * Return the assumed properties of this matrix. This is a bit-combination of - * {@link #PROPERTY_IDENTITY}, {@link #PROPERTY_AFFINE}, - * {@link #PROPERTY_TRANSLATION} and {@link #PROPERTY_PERSPECTIVE}. - * - * @return the properties of the matrix - */ - int properties(); - - /** - * Return the value of the matrix element at column 0 and row 0. - * - * @return the value of the matrix element - */ - float m00(); - - /** - * Return the value of the matrix element at column 0 and row 1. - * - * @return the value of the matrix element - */ - float m01(); - - /** - * Return the value of the matrix element at column 0 and row 2. - * - * @return the value of the matrix element - */ - float m02(); - - /** - * Return the value of the matrix element at column 0 and row 3. - * - * @return the value of the matrix element - */ - float m03(); - - /** - * Return the value of the matrix element at column 1 and row 0. - * - * @return the value of the matrix element - */ - float m10(); - - /** - * Return the value of the matrix element at column 1 and row 1. - * - * @return the value of the matrix element - */ - float m11(); - - /** - * Return the value of the matrix element at column 1 and row 2. - * - * @return the value of the matrix element - */ - float m12(); - - /** - * Return the value of the matrix element at column 1 and row 3. - * - * @return the value of the matrix element - */ - float m13(); - - /** - * Return the value of the matrix element at column 2 and row 0. - * - * @return the value of the matrix element - */ - float m20(); - - /** - * Return the value of the matrix element at column 2 and row 1. - * - * @return the value of the matrix element - */ - float m21(); - - /** - * Return the value of the matrix element at column 2 and row 2. - * - * @return the value of the matrix element - */ - float m22(); - - /** - * Return the value of the matrix element at column 2 and row 3. - * - * @return the value of the matrix element - */ - float m23(); - - /** - * Return the value of the matrix element at column 3 and row 0. - * - * @return the value of the matrix element - */ - float m30(); - - /** - * Return the value of the matrix element at column 3 and row 1. - * - * @return the value of the matrix element - */ - float m31(); - - /** - * Return the value of the matrix element at column 3 and row 2. - * - * @return the value of the matrix element - */ - float m32(); - - /** - * Return the value of the matrix element at column 3 and row 3. - * - * @return the value of the matrix element - */ - float m33(); - - /** - * Multiply this matrix by the supplied right matrix and store the result in dest. - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param right - * the right operand of the matrix multiplication - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f mul(Matrix4fc right, Matrix4f dest); - - /** - * Multiply this matrix by the supplied right matrix and store the result in dest. - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - *

- * This method neither assumes nor checks for any matrix properties of this or right - * and will always perform a complete 4x4 matrix multiplication. This method should only be used whenever the - * multiplied matrices do not have any properties for which there are optimized multiplication methods available. - * - * @param right - * the right operand of the matrix multiplication - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f mul0(Matrix4fc right, Matrix4f dest); - - /** - * Multiply this matrix by the matrix with the supplied elements and store the result in dest. - *

- * If M is this matrix and R the right matrix whose - * elements are supplied via the parameters, then the new matrix will be M * R. - * So when transforming a vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param r00 - * the m00 element of the right matrix - * @param r01 - * the m01 element of the right matrix - * @param r02 - * the m02 element of the right matrix - * @param r03 - * the m03 element of the right matrix - * @param r10 - * the m10 element of the right matrix - * @param r11 - * the m11 element of the right matrix - * @param r12 - * the m12 element of the right matrix - * @param r13 - * the m13 element of the right matrix - * @param r20 - * the m20 element of the right matrix - * @param r21 - * the m21 element of the right matrix - * @param r22 - * the m22 element of the right matrix - * @param r23 - * the m23 element of the right matrix - * @param r30 - * the m30 element of the right matrix - * @param r31 - * the m31 element of the right matrix - * @param r32 - * the m32 element of the right matrix - * @param r33 - * the m33 element of the right matrix - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f mul( - float r00, float r01, float r02, float r03, - float r10, float r11, float r12, float r13, - float r20, float r21, float r22, float r23, - float r30, float r31, float r32, float r33, Matrix4f dest); - - /** - * Multiply this matrix by the 3x3 matrix with the supplied elements expanded to a 4x4 matrix with - * all other matrix elements set to identity, and store the result in dest. - *

- * If M is this matrix and R the right matrix whose - * elements are supplied via the parameters, then the new matrix will be M * R. - * So when transforming a vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param r00 - * the m00 element of the right matrix - * @param r01 - * the m01 element of the right matrix - * @param r02 - * the m02 element of the right matrix - * @param r10 - * the m10 element of the right matrix - * @param r11 - * the m11 element of the right matrix - * @param r12 - * the m12 element of the right matrix - * @param r20 - * the m20 element of the right matrix - * @param r21 - * the m21 element of the right matrix - * @param r22 - * the m22 element of the right matrix - * @param dest - * the destination matrix, which will hold the result - * @return this - */ - Matrix4f mul3x3( - float r00, float r01, float r02, - float r10, float r11, float r12, - float r20, float r21, float r22, Matrix4f dest); - - /** - * Pre-multiply this matrix by the supplied left matrix and store the result in dest. - *

- * If M is this matrix and L the left matrix, - * then the new matrix will be L * M. So when transforming a - * vector v with the new matrix by using L * M * v, the - * transformation of this matrix will be applied first! - * - * @param left - * the left operand of the matrix multiplication - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f mulLocal(Matrix4fc left, Matrix4f dest); - - /** - * Pre-multiply this matrix by the supplied left matrix, both of which are assumed to be {@link #isAffine() affine}, and store the result in dest. - *

- * This method assumes that this matrix and the given left matrix both represent an {@link #isAffine() affine} transformation - * (i.e. their last rows are equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrices only represent affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * This method will not modify either the last row of this or the last row of left. - *

- * If M is this matrix and L the left matrix, - * then the new matrix will be L * M. So when transforming a - * vector v with the new matrix by using L * M * v, the - * transformation of this matrix will be applied first! - * - * @param left - * the left operand of the matrix multiplication (the last row is assumed to be (0, 0, 0, 1)) - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f mulLocalAffine(Matrix4fc left, Matrix4f dest); - - /** - * Multiply this symmetric perspective projection matrix by the supplied {@link #isAffine() affine} view matrix and store the result in dest. - *

- * If P is this matrix and V the view matrix, - * then the new matrix will be P * V. So when transforming a - * vector v with the new matrix by using P * V * v, the - * transformation of the view matrix will be applied first! - * - * @param view - * the {@link #isAffine() affine} matrix to multiply this symmetric perspective projection matrix by - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f mulPerspectiveAffine(Matrix4fc view, Matrix4f dest); - - /** - * Multiply this matrix by the supplied right matrix, which is assumed to be {@link #isAffine() affine}, and store the result in dest. - *

- * This method assumes that the given right matrix represents an {@link #isAffine() affine} transformation (i.e. its last row is equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrix only represents affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param right - * the right operand of the matrix multiplication (the last row is assumed to be (0, 0, 0, 1)) - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f mulAffineR(Matrix4fc right, Matrix4f dest); - - /** - * Multiply this matrix by the supplied right matrix, both of which are assumed to be {@link #isAffine() affine}, and store the result in dest. - *

- * This method assumes that this matrix and the given right matrix both represent an {@link #isAffine() affine} transformation - * (i.e. their last rows are equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrices only represent affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * This method will not modify either the last row of this or the last row of right. - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param right - * the right operand of the matrix multiplication (the last row is assumed to be (0, 0, 0, 1)) - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f mulAffine(Matrix4fc right, Matrix4f dest); - - /** - * Multiply this matrix, which is assumed to only contain a translation, by the supplied right matrix, which is assumed to be {@link #isAffine() affine}, and store the result in dest. - *

- * This method assumes that this matrix only contains a translation, and that the given right matrix represents an {@link #isAffine() affine} transformation - * (i.e. its last row is equal to (0, 0, 0, 1)). - *

- * This method will not modify either the last row of this or the last row of right. - *

- * If M is this matrix and R the right matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * transformation of the right matrix will be applied first! - * - * @param right - * the right operand of the matrix multiplication (the last row is assumed to be (0, 0, 0, 1)) - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f mulTranslationAffine(Matrix4fc right, Matrix4f dest); - - /** - * Multiply this orthographic projection matrix by the supplied {@link #isAffine() affine} view matrix - * and store the result in dest. - *

- * If M is this matrix and V the view matrix, - * then the new matrix will be M * V. So when transforming a - * vector v with the new matrix by using M * V * v, the - * transformation of the view matrix will be applied first! - * - * @param view - * the affine matrix which to multiply this with - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f mulOrthoAffine(Matrix4fc view, Matrix4f dest); - - /** - * Component-wise add the upper 4x3 submatrices of this and other - * by first multiplying each component of other's 4x3 submatrix by otherFactor, - * adding that to this and storing the final result in dest. - *

- * The other components of dest will be set to the ones of this. - *

- * The matrices this and other will not be changed. - * - * @param other - * the other matrix - * @param otherFactor - * the factor to multiply each of the other matrix's 4x3 components - * @param dest - * will hold the result - * @return dest - */ - Matrix4f fma4x3(Matrix4fc other, float otherFactor, Matrix4f dest); - - /** - * Component-wise add this and other and store the result in dest. - * - * @param other - * the other addend - * @param dest - * will hold the result - * @return dest - */ - Matrix4f add(Matrix4fc other, Matrix4f dest); - - /** - * Component-wise subtract subtrahend from this and store the result in dest. - * - * @param subtrahend - * the subtrahend - * @param dest - * will hold the result - * @return dest - */ - Matrix4f sub(Matrix4fc subtrahend, Matrix4f dest); - - /** - * Component-wise multiply this by other and store the result in dest. - * - * @param other - * the other matrix - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mulComponentWise(Matrix4fc other, Matrix4f dest); - - /** - * Component-wise add the upper 4x3 submatrices of this and other - * and store the result in dest. - *

- * The other components of dest will be set to the ones of this. - * - * @param other - * the other addend - * @param dest - * will hold the result - * @return dest - */ - Matrix4f add4x3(Matrix4fc other, Matrix4f dest); - - /** - * Component-wise subtract the upper 4x3 submatrices of subtrahend from this - * and store the result in dest. - *

- * The other components of dest will be set to the ones of this. - * - * @param subtrahend - * the subtrahend - * @param dest - * will hold the result - * @return dest - */ - Matrix4f sub4x3(Matrix4fc subtrahend, Matrix4f dest); - - /** - * Component-wise multiply the upper 4x3 submatrices of this by other - * and store the result in dest. - *

- * The other components of dest will be set to the ones of this. - * - * @param other - * the other matrix - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mul4x3ComponentWise(Matrix4fc other, Matrix4f dest); - - /** - * Return the determinant of this matrix. - *

- * If this matrix represents an {@link #isAffine() affine} transformation, such as translation, rotation, scaling and shearing, - * and thus its last row is equal to (0, 0, 0, 1), then {@link #determinantAffine()} can be used instead of this method. - * - * @see #determinantAffine() - * - * @return the determinant - */ - float determinant(); - - /** - * Return the determinant of the upper left 3x3 submatrix of this matrix. - * - * @return the determinant - */ - float determinant3x3(); - - /** - * Return the determinant of this matrix by assuming that it represents an {@link #isAffine() affine} transformation and thus - * its last row is equal to (0, 0, 0, 1). - * - * @return the determinant - */ - float determinantAffine(); - - /** - * Invert this matrix and write the result into dest. - *

- * If this matrix represents an {@link #isAffine() affine} transformation, such as translation, rotation, scaling and shearing, - * and thus its last row is equal to (0, 0, 0, 1), then {@link #invertAffine(Matrix4f)} can be used instead of this method. - * - * @see #invertAffine(Matrix4f) - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f invert(Matrix4f dest); - - /** - * If this is a perspective projection matrix obtained via one of the {@link #perspective(float, float, float, float, Matrix4f) perspective()} methods, - * that is, if this is a symmetrical perspective frustum transformation, - * then this method builds the inverse of this and stores it into the given dest. - *

- * This method can be used to quickly obtain the inverse of a perspective projection matrix when being obtained via {@link #perspective(float, float, float, float, Matrix4f) perspective()}. - * - * @see #perspective(float, float, float, float, Matrix4f) - * - * @param dest - * will hold the inverse of this - * @return dest - */ - Matrix4f invertPerspective(Matrix4f dest); - - /** - * If this is an arbitrary perspective projection matrix obtained via one of the {@link #frustum(float, float, float, float, float, float, Matrix4f) frustum()} methods, - * then this method builds the inverse of this and stores it into the given dest. - *

- * This method can be used to quickly obtain the inverse of a perspective projection matrix. - *

- * If this matrix represents a symmetric perspective frustum transformation, as obtained via {@link #perspective(float, float, float, float, Matrix4f) perspective()}, then - * {@link #invertPerspective(Matrix4f)} should be used instead. - * - * @see #frustum(float, float, float, float, float, float, Matrix4f) - * @see #invertPerspective(Matrix4f) - * - * @param dest - * will hold the inverse of this - * @return dest - */ - Matrix4f invertFrustum(Matrix4f dest); - - /** - * Invert this orthographic projection matrix and store the result into the given dest. - *

- * This method can be used to quickly obtain the inverse of an orthographic projection matrix. - * - * @param dest - * will hold the inverse of this - * @return dest - */ - Matrix4f invertOrtho(Matrix4f dest); - - /** - * If this is a perspective projection matrix obtained via one of the {@link #perspective(float, float, float, float, Matrix4f) perspective()} methods, - * that is, if this is a symmetrical perspective frustum transformation - * and the given view matrix is {@link #isAffine() affine} and has unit scaling (for example by being obtained via {@link #lookAt(float, float, float, float, float, float, float, float, float, Matrix4f) lookAt()}), - * then this method builds the inverse of this * view and stores it into the given dest. - *

- * This method can be used to quickly obtain the inverse of the combination of the view and projection matrices, when both were obtained - * via the common methods {@link #perspective(float, float, float, float, Matrix4f) perspective()} and {@link #lookAt(float, float, float, float, float, float, float, float, float, Matrix4f) lookAt()} or - * other methods, that build affine matrices, such as {@link #translate(float, float, float, Matrix4f) translate} and {@link #rotate(float, float, float, float, Matrix4f)}, except for {@link #scale(float, float, float, Matrix4f) scale()}. - *

- * For the special cases of the matrices this and view mentioned above, this method is equivalent to the following code: - *

-     * dest.set(this).mul(view).invert();
-     * 
- * - * @param view - * the view transformation (must be {@link #isAffine() affine} and have unit scaling) - * @param dest - * will hold the inverse of this * view - * @return dest - */ - Matrix4f invertPerspectiveView(Matrix4fc view, Matrix4f dest); - - /** - * Invert this matrix by assuming that it is an {@link #isAffine() affine} transformation (i.e. its last row is equal to (0, 0, 0, 1)) - * and write the result into dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f invertAffine(Matrix4f dest); - - /** - * Transpose this matrix and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f transpose(Matrix4f dest); - - /** - * Transpose only the upper left 3x3 submatrix of this matrix and store the result in dest. - *

- * All other matrix elements are left unchanged. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f transpose3x3(Matrix4f dest); - - /** - * Transpose only the upper left 3x3 submatrix of this matrix and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f transpose3x3(Matrix3f dest); - - /** - * Get only the translation components (m30, m31, m32) of this matrix and store them in the given vector xyz. - * - * @param dest - * will hold the translation components of this matrix - * @return dest - */ - Vector3f getTranslation(Vector3f dest); - - /** - * Get the scaling factors of this matrix for the three base axes. - * - * @param dest - * will hold the scaling factors for x, y and z - * @return dest - */ - Vector3f getScale(Vector3f dest); - - /** - * Get the current values of this matrix and store them into - * dest. - * - * @param dest - * the destination matrix - * @return the passed in destination - */ - Matrix4f get(Matrix4f dest); - - /** - * Get the current values of the upper left 3x3 submatrix of this matrix and store them into - * dest. - * - * @see Matrix3f#set(Matrix4fc) - * - * @param dest - * the destination matrix - * @return the passed in destination - */ - Matrix3f get3x3(Matrix3f dest); - - /** - * Get the rotational component of this matrix and store the represented rotation - * into the given {@link AxisAngle4f}. - * - * @see AxisAngle4f#set(Matrix4fc) - * - * @param dest - * the destination {@link AxisAngle4f} - * @return the passed in destination - */ - AxisAngle4f getRotation(AxisAngle4f dest); - - /** - * Get the current values of this matrix and store the represented rotation - * into the given {@link Quaternionf}. - *

- * This method assumes that the first three column vectors of the upper left 3x3 submatrix are not normalized and - * thus allows to ignore any additional scaling factor that is applied to the matrix. - * - * @see Quaternionf#setFromUnnormalized(Matrix4fc) - * - * @param dest - * the destination {@link Quaternionf} - * @return the passed in destination - */ - Quaternionf getUnnormalizedRotation(Quaternionf dest); - - /** - * Get the current values of this matrix and store the represented rotation - * into the given {@link Quaternionf}. - *

- * This method assumes that the first three column vectors of the upper left 3x3 submatrix are normalized. - * - * @see Quaternionf#setFromNormalized(Matrix4fc) - * - * @param dest - * the destination {@link Quaternionf} - * @return the passed in destination - */ - Quaternionf getNormalizedRotation(Quaternionf dest); - - /** - * Store this matrix in column-major order into the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the matrix is stored, use {@link #get(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @see #get(int, FloatBuffer) - * - * @param buffer - * will receive the values of this matrix in column-major order at its current position - * @return the passed in buffer - */ - FloatBuffer get(FloatBuffer buffer); - - /** - * Store this matrix in column-major order into the supplied {@link FloatBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given FloatBuffer. - * - * @param index - * the absolute position into the FloatBuffer - * @param buffer - * will receive the values of this matrix in column-major order - * @return the passed in buffer - */ - FloatBuffer get(int index, FloatBuffer buffer); - - /** - * Store this matrix in column-major order into the supplied {@link ByteBuffer} at the current - * buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the matrix is stored, use {@link #get(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @see #get(int, ByteBuffer) - * - * @param buffer - * will receive the values of this matrix in column-major order at its current position - * @return the passed in buffer - */ - ByteBuffer get(ByteBuffer buffer); - - /** - * Store this matrix in column-major order into the supplied {@link ByteBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given ByteBuffer. - * - * @param index - * the absolute position into the ByteBuffer - * @param buffer - * will receive the values of this matrix in column-major order - * @return the passed in buffer - */ - ByteBuffer get(int index, ByteBuffer buffer); - - /** - * Store the upper 4x3 submatrix in column-major order into the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the matrix is stored, use {@link #get(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @see #get(int, FloatBuffer) - * - * @param buffer - * will receive the values of the upper 4x3 submatrix in column-major order at its current position - * @return the passed in buffer - */ - FloatBuffer get4x3(FloatBuffer buffer); - - /** - * Store the upper 4x3 submatrix in column-major order into the supplied {@link FloatBuffer} starting at the specified - * absolute buffer position/index. - *

- * 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 the upper 4x3 submatrix in column-major order - * @return the passed in buffer - */ - FloatBuffer get4x3(int index, FloatBuffer buffer); - - /** - * Store the upper 4x3 submatrix in column-major order into the supplied {@link ByteBuffer} at the current - * buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the matrix is stored, use {@link #get(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @see #get(int, ByteBuffer) - * - * @param buffer - * will receive the values of the upper 4x3 submatrix in column-major order at its current position - * @return the passed in buffer - */ - ByteBuffer get4x3(ByteBuffer buffer); - - /** - * Store the upper 4x3 submatrix in column-major order into the supplied {@link ByteBuffer} starting at the specified - * absolute buffer position/index. - *

- * 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 the upper 4x3 submatrix in column-major order - * @return the passed in buffer - */ - ByteBuffer get4x3(int index, ByteBuffer buffer); - - /** - * Store the left 3x4 submatrix in column-major order into the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the matrix is stored, use {@link #get3x4(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @see #get3x4(int, FloatBuffer) - * - * @param buffer - * will receive the values of the left 3x4 submatrix in column-major order at its current position - * @return the passed in buffer - */ - FloatBuffer get3x4(FloatBuffer buffer); - - /** - * Store the left 3x4 submatrix in column-major order into the supplied {@link FloatBuffer} starting at the specified - * absolute buffer position/index. - *

- * 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 the left 3x4 submatrix in column-major order - * @return the passed in buffer - */ - FloatBuffer get3x4(int index, FloatBuffer buffer); - - /** - * Store the left 3x4 submatrix in column-major order into the supplied {@link ByteBuffer} at the current - * buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the matrix is stored, use {@link #get3x4(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @see #get3x4(int, ByteBuffer) - * - * @param buffer - * will receive the values of the left 3x4 submatrix in column-major order at its current position - * @return the passed in buffer - */ - ByteBuffer get3x4(ByteBuffer buffer); - - /** - * Store the left 3x4 submatrix in column-major order into the supplied {@link ByteBuffer} starting at the specified - * absolute buffer position/index. - *

- * 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 the left 3x4 submatrix in column-major order - * @return the passed in buffer - */ - ByteBuffer get3x4(int index, ByteBuffer buffer); - - /** - * Store the transpose of this matrix in column-major order into the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the matrix is stored, use {@link #getTransposed(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @see #getTransposed(int, FloatBuffer) - * - * @param buffer - * will receive the values of this matrix in column-major order at its current position - * @return the passed in buffer - */ - FloatBuffer getTransposed(FloatBuffer buffer); - - /** - * Store the transpose of this matrix in column-major order into the supplied {@link FloatBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given FloatBuffer. - * - * @param index - * the absolute position into the FloatBuffer - * @param buffer - * will receive the values of this matrix in column-major order - * @return the passed in buffer - */ - FloatBuffer getTransposed(int index, FloatBuffer buffer); - - /** - * Store the transpose of this matrix in column-major order into the supplied {@link ByteBuffer} at the current - * buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the matrix is stored, use {@link #getTransposed(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @see #getTransposed(int, ByteBuffer) - * - * @param buffer - * will receive the values of this matrix in column-major order at its current position - * @return the passed in buffer - */ - ByteBuffer getTransposed(ByteBuffer buffer); - - /** - * Store the transpose of this matrix in column-major order into the supplied {@link ByteBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given ByteBuffer. - * - * @param index - * the absolute position into the ByteBuffer - * @param buffer - * will receive the values of this matrix in column-major order - * @return the passed in buffer - */ - ByteBuffer getTransposed(int index, ByteBuffer buffer); - - /** - * Store the upper 4x3 submatrix of this matrix in row-major order into the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the matrix is stored, use {@link #get4x3Transposed(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @see #get4x3Transposed(int, FloatBuffer) - * - * @param buffer - * will receive the values of the upper 4x3 submatrix in row-major order at its current position - * @return the passed in buffer - */ - FloatBuffer get4x3Transposed(FloatBuffer buffer); - - /** - * Store the upper 4x3 submatrix of this matrix in row-major order into the supplied {@link FloatBuffer} starting at the specified - * absolute buffer position/index. - *

- * 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 the upper 4x3 submatrix in row-major order - * @return the passed in buffer - */ - FloatBuffer get4x3Transposed(int index, FloatBuffer buffer); - - /** - * Store the upper 4x3 submatrix of this matrix in row-major order into the supplied {@link ByteBuffer} at the current - * buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the matrix is stored, use {@link #get4x3Transposed(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @see #get4x3Transposed(int, ByteBuffer) - * - * @param buffer - * will receive the values of the upper 4x3 submatrix in row-major order at its current position - * @return the passed in buffer - */ - ByteBuffer get4x3Transposed(ByteBuffer buffer); - - /** - * Store the upper 4x3 submatrix of this matrix in row-major order into the supplied {@link ByteBuffer} starting at the specified - * absolute buffer position/index. - *

- * 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 the upper 4x3 submatrix in row-major order - * @return the passed in buffer - */ - ByteBuffer get4x3Transposed(int index, ByteBuffer buffer); - - /** - * Store this matrix in column-major order at the given off-heap address. - *

- * This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`. - *

- * 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. - * - * @param address - * the off-heap address where to store this matrix - * @return this - */ - Matrix4fc getToAddress(long address); - - /** - * Store this matrix into the supplied float array in column-major order at the given offset. - * - * @param arr - * the array to write the matrix values into - * @param offset - * the offset into the array - * @return the passed in array - */ - float[] get(float[] arr, int offset); - - /** - * Store this matrix into the supplied float array in column-major order. - *

- * In order to specify an explicit offset into the array, use the method {@link #get(float[], int)}. - * - * @see #get(float[], int) - * - * @param arr - * the array to write the matrix values into - * @return the passed in array - */ - float[] get(float[] arr); - - /** - * Transform/multiply the given vector by this matrix and store the result in that vector. - * - * @see Vector4f#mul(Matrix4fc) - * - * @param v - * the vector to transform and to hold the final result - * @return v - */ - Vector4f transform(Vector4f v); - - /** - * Transform/multiply the given vector by this matrix and store the result in dest. - * - * @see Vector4f#mul(Matrix4fc, Vector4f) - * - * @param v - * the vector to transform - * @param dest - * will contain the result - * @return dest - */ - Vector4f transform(Vector4fc v, Vector4f dest); - - /** - * Transform/multiply the vector (x, y, z, w) by this matrix and store the result in dest. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param w - * the w coordinate of the vector to transform - * @param dest - * will contain the result - * @return dest - */ - Vector4f transform(float x, float y, float z, float w, Vector4f dest); - - /** - * Transform/multiply the given vector by the transpose of this matrix and store the result in that vector. - * - * @see Vector4f#mulTranspose(Matrix4fc) - * - * @param v - * the vector to transform and to hold the final result - * @return v - */ - Vector4f transformTranspose(Vector4f v); - - /** - * Transform/multiply the given vector by the transpose of this matrix and store the result in dest. - * - * @see Vector4f#mulTranspose(Matrix4fc, Vector4f) - * - * @param v - * the vector to transform - * @param dest - * will contain the result - * @return dest - */ - Vector4f transformTranspose(Vector4fc v, Vector4f dest); - - /** - * Transform/multiply the vector (x, y, z, w) by the transpose of this matrix and store the result in dest. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param w - * the w coordinate of the vector to transform - * @param dest - * will contain the result - * @return dest - */ - Vector4f transformTranspose(float x, float y, float z, float w, Vector4f dest); - - /** - * Transform/multiply the given vector by this matrix, perform perspective divide and store the result in that vector. - * - * @see Vector4f#mulProject(Matrix4fc) - * - * @param v - * the vector to transform and to hold the final result - * @return v - */ - Vector4f transformProject(Vector4f v); - - /** - * Transform/multiply the given vector by this matrix, perform perspective divide and store the result in dest. - * - * @see Vector4f#mulProject(Matrix4fc, Vector4f) - * - * @param v - * the vector to transform - * @param dest - * will contain the result - * @return dest - */ - Vector4f transformProject(Vector4fc v, Vector4f dest); - - /** - * Transform/multiply the vector (x, y, z, w) by this matrix, perform perspective divide and store the result in dest. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param w - * the w coordinate of the vector to transform - * @param dest - * will contain the result - * @return dest - */ - Vector4f transformProject(float x, float y, float z, float w, Vector4f dest); - - /** - * Transform/multiply the given vector by this matrix, perform perspective divide and store the result in that vector. - *

- * This method uses w=1.0 as the fourth vector component. - * - * @see Vector3f#mulProject(Matrix4fc) - * - * @param v - * the vector to transform and to hold the final result - * @return v - */ - Vector3f transformProject(Vector3f v); - - /** - * Transform/multiply the given vector by this matrix, perform perspective divide and store the result in dest. - *

- * This method uses w=1.0 as the fourth vector component. - * - * @see Vector3f#mulProject(Matrix4fc, Vector3f) - * - * @param v - * the vector to transform - * @param dest - * will contain the result - * @return dest - */ - Vector3f transformProject(Vector3fc v, Vector3f dest); - - /** - * Transform/multiply the given vector by this matrix, perform perspective divide and store the result in dest. - * - * @see Vector4f#mulProject(Matrix4fc, Vector4f) - * - * @param v - * the vector to transform - * @param dest - * will contain the (x, y, z) components of the result - * @return dest - */ - Vector3f transformProject(Vector4fc v, Vector3f dest); - - /** - * Transform/multiply the vector (x, y, z) by this matrix, perform perspective divide and store the result in dest. - *

- * This method uses w=1.0 as the fourth vector component. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will contain the result - * @return dest - */ - Vector3f transformProject(float x, float y, float z, Vector3f dest); - - /** - * Transform/multiply the vector (x, y, z, w) by this matrix, perform perspective divide and store - * (x, y, z) of the result in dest. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param w - * the w coordinate of the vector to transform - * @param dest - * will contain the (x, y, z) components of the result - * @return dest - */ - Vector3f transformProject(float x, float y, float z, float w, Vector3f dest); - - /** - * Transform/multiply the given 3D-vector, as if it was a 4D-vector with w=1, by - * this matrix and store the result in that vector. - *

- * The given 3D-vector is treated as a 4D-vector with its w-component being 1.0, so it - * will represent a position/location in 3D-space rather than a direction. This method is therefore - * not suited for perspective projection transformations as it will not save the - * w component of the transformed vector. - * For perspective projection use {@link #transform(Vector4f)} or {@link #transformProject(Vector3f)} - * when perspective divide should be applied, too. - *

- * In order to store the result in another vector, use {@link #transformPosition(Vector3fc, Vector3f)}. - * - * @see #transformPosition(Vector3fc, Vector3f) - * @see #transform(Vector4f) - * @see #transformProject(Vector3f) - * - * @param v - * the vector to transform and to hold the final result - * @return v - */ - Vector3f transformPosition(Vector3f v); - - /** - * Transform/multiply the given 3D-vector, as if it was a 4D-vector with w=1, by - * this matrix and store the result in dest. - *

- * The given 3D-vector is treated as a 4D-vector with its w-component being 1.0, so it - * will represent a position/location in 3D-space rather than a direction. This method is therefore - * not suited for perspective projection transformations as it will not save the - * w component of the transformed vector. - * For perspective projection use {@link #transform(Vector4fc, Vector4f)} or - * {@link #transformProject(Vector3fc, Vector3f)} when perspective divide should be applied, too. - *

- * In order to store the result in the same vector, use {@link #transformPosition(Vector3f)}. - * - * @see #transformPosition(Vector3f) - * @see #transform(Vector4fc, Vector4f) - * @see #transformProject(Vector3fc, Vector3f) - * - * @param v - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformPosition(Vector3fc v, Vector3f dest); - - /** - * Transform/multiply the 3D-vector (x, y, z), as if it was a 4D-vector with w=1, by - * this matrix and store the result in dest. - *

- * The given 3D-vector is treated as a 4D-vector with its w-component being 1.0, so it - * will represent a position/location in 3D-space rather than a direction. This method is therefore - * not suited for perspective projection transformations as it will not save the - * w component of the transformed vector. - * For perspective projection use {@link #transform(float, float, float, float, Vector4f)} or - * {@link #transformProject(float, float, float, Vector3f)} when perspective divide should be applied, too. - * - * @see #transform(float, float, float, float, Vector4f) - * @see #transformProject(float, float, float, Vector3f) - * - * @param x - * the x coordinate of the position - * @param y - * the y coordinate of the position - * @param z - * the z coordinate of the position - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformPosition(float x, float y, float z, Vector3f dest); - - /** - * Transform/multiply the given 3D-vector, as if it was a 4D-vector with w=0, by - * this matrix and store the result in that vector. - *

- * The given 3D-vector is treated as a 4D-vector with its w-component being 0.0, so it - * will represent a direction in 3D-space rather than a position. This method will therefore - * not take the translation part of the matrix into account. - *

- * In order to store the result in another vector, use {@link #transformDirection(Vector3fc, Vector3f)}. - * - * @see #transformDirection(Vector3fc, Vector3f) - * - * @param v - * the vector to transform and to hold the final result - * @return v - */ - Vector3f transformDirection(Vector3f v); - - /** - * Transform/multiply the given 3D-vector, as if it was a 4D-vector with w=0, by - * this matrix and store the result in dest. - *

- * The given 3D-vector is treated as a 4D-vector with its w-component being 0.0, so it - * will represent a direction in 3D-space rather than a position. This method will therefore - * not take the translation part of the matrix into account. - *

- * In order to store the result in the same vector, use {@link #transformDirection(Vector3f)}. - * - * @see #transformDirection(Vector3f) - * - * @param v - * the vector to transform and to hold the final result - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformDirection(Vector3fc v, Vector3f dest); - - /** - * Transform/multiply the given 3D-vector (x, y, z), as if it was a 4D-vector with w=0, by - * this matrix and store the result in dest. - *

- * The given 3D-vector is treated as a 4D-vector with its w-component being 0.0, so it - * will represent a direction in 3D-space rather than a position. This method will therefore - * not take the translation part of the matrix into account. - * - * @param x - * the x coordinate of the direction to transform - * @param y - * the y coordinate of the direction to transform - * @param z - * the z coordinate of the direction to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformDirection(float x, float y, float z, Vector3f dest); - - /** - * Transform/multiply the given 4D-vector by assuming that this matrix represents an {@link #isAffine() affine} transformation - * (i.e. its last row is equal to (0, 0, 0, 1)). - *

- * In order to store the result in another vector, use {@link #transformAffine(Vector4fc, Vector4f)}. - * - * @see #transformAffine(Vector4fc, Vector4f) - * - * @param v - * the vector to transform and to hold the final result - * @return v - */ - Vector4f transformAffine(Vector4f v); - - /** - * Transform/multiply the given 4D-vector by assuming that this matrix represents an {@link #isAffine() affine} transformation - * (i.e. its last row is equal to (0, 0, 0, 1)) and store the result in dest. - *

- * In order to store the result in the same vector, use {@link #transformAffine(Vector4f)}. - * - * @see #transformAffine(Vector4f) - * - * @param v - * the vector to transform and to hold the final result - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformAffine(Vector4fc v, Vector4f dest); - - /** - * Transform/multiply the 4D-vector (x, y, z, w) by assuming that this matrix represents an {@link #isAffine() affine} transformation - * (i.e. its last row is equal to (0, 0, 0, 1)) and store the result in dest. - * - * @param x - * the x coordinate of the direction to transform - * @param y - * the y coordinate of the direction to transform - * @param z - * the z coordinate of the direction to transform - * @param w - * the w coordinate of the direction to transform - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformAffine(float x, float y, float z, float w, Vector4f dest); - - /** - * Apply scaling to this matrix by scaling the base axes by the given xyz.x, - * xyz.y and xyz.z factors, respectively and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v - * , the scaling will be applied first! - * - * @param xyz - * the factors of the x, y and z component, respectively - * @param dest - * will hold the result - * @return dest - */ - Matrix4f scale(Vector3fc xyz, Matrix4f dest); - - /** - * Apply scaling to this matrix by uniformly scaling all base axes by the given xyz factor - * and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * scaling will be applied first! - *

- * Individual scaling of all three axes can be applied using {@link #scale(float, float, float, Matrix4f)}. - * - * @see #scale(float, float, float, Matrix4f) - * - * @param xyz - * the factor for all components - * @param dest - * will hold the result - * @return dest - */ - Matrix4f scale(float xyz, Matrix4f dest); - - /** - * Apply scaling to this matrix by by scaling the X axis by x and the Y axis by y - * and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * scaling will be applied first! - * - * @param x - * the factor of the x component - * @param y - * the factor of the y component - * @param dest - * will hold the result - * @return dest - */ - Matrix4f scaleXY(float x, float y, Matrix4f dest); - - /** - * Apply scaling to this matrix by scaling the base axes by the given x, - * y and z factors and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v - * , the scaling will be applied first! - * - * @param x - * the factor of the x component - * @param y - * the factor of the y component - * @param z - * the factor of the z component - * @param dest - * will hold the result - * @return dest - */ - Matrix4f scale(float x, float y, float z, Matrix4f dest); - - /** - * Apply scaling to this matrix by scaling the base axes by the given sx, - * sy and sz factors while using (ox, oy, oz) as the scaling origin, - * and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v - * , the scaling will be applied first! - *

- * This method is equivalent to calling: translate(ox, oy, oz, dest).scale(sx, sy, sz).translate(-ox, -oy, -oz) - * - * @param sx - * the scaling factor of the x component - * @param sy - * the scaling factor of the y component - * @param sz - * the scaling factor of the z component - * @param ox - * the x coordinate of the scaling origin - * @param oy - * the y coordinate of the scaling origin - * @param oz - * the z coordinate of the scaling origin - * @param dest - * will hold the result - * @return dest - */ - Matrix4f scaleAround(float sx, float sy, float sz, float ox, float oy, float oz, Matrix4f dest); - - /** - * Apply scaling to this matrix by scaling all three base axes by the given factor - * while using (ox, oy, oz) as the scaling origin, - * and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * scaling will be applied first! - *

- * This method is equivalent to calling: translate(ox, oy, oz, dest).scale(factor).translate(-ox, -oy, -oz) - * - * @param factor - * the scaling factor for all three axes - * @param ox - * the x coordinate of the scaling origin - * @param oy - * the y coordinate of the scaling origin - * @param oz - * the z coordinate of the scaling origin - * @param dest - * will hold the result - * @return this - */ - Matrix4f scaleAround(float factor, float ox, float oy, float oz, Matrix4f dest); - - /** - * Pre-multiply scaling to this matrix by scaling all base axes by the given xyz factor, - * and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be S * M. So when transforming a - * vector v with the new matrix by using S * M * v - * , the scaling will be applied last! - * - * @param xyz - * the factor to scale all three base axes by - * @param dest - * will hold the result - * @return dest - */ - Matrix4f scaleLocal(float xyz, Matrix4f dest); - - /** - * Pre-multiply scaling to this matrix by scaling the base axes by the given x, - * y and z factors and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be S * M. So when transforming a - * vector v with the new matrix by using S * M * v - * , the scaling will be applied last! - * - * @param x - * the factor of the x component - * @param y - * the factor of the y component - * @param z - * the factor of the z component - * @param dest - * will hold the result - * @return dest - */ - Matrix4f scaleLocal(float x, float y, float z, Matrix4f dest); - - /** - * Pre-multiply scaling to this matrix by scaling the base axes by the given sx, - * sy and sz factors while using the given (ox, oy, oz) as the scaling origin, - * and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be S * M. So when transforming a - * vector v with the new matrix by using S * M * v - * , the scaling will be applied last! - *

- * This method is equivalent to calling: new Matrix4f().translate(ox, oy, oz).scale(sx, sy, sz).translate(-ox, -oy, -oz).mul(this, dest) - * - * @param sx - * the scaling factor of the x component - * @param sy - * the scaling factor of the y component - * @param sz - * the scaling factor of the z component - * @param ox - * the x coordinate of the scaling origin - * @param oy - * the y coordinate of the scaling origin - * @param oz - * the z coordinate of the scaling origin - * @param dest - * will hold the result - * @return dest - */ - Matrix4f scaleAroundLocal(float sx, float sy, float sz, float ox, float oy, float oz, Matrix4f dest); - - /** - * Pre-multiply scaling to this matrix by scaling all three base axes by the given factor - * while using (ox, oy, oz) as the scaling origin, - * and store the result in dest. - *

- * If M is this matrix and S the scaling matrix, - * then the new matrix will be S * M. So when transforming a - * vector v with the new matrix by using S * M * v, the - * scaling will be applied last! - *

- * This method is equivalent to calling: new Matrix4f().translate(ox, oy, oz).scale(factor).translate(-ox, -oy, -oz).mul(this, dest) - * - * @param factor - * the scaling factor for all three axes - * @param ox - * the x coordinate of the scaling origin - * @param oy - * the y coordinate of the scaling origin - * @param oz - * the z coordinate of the scaling origin - * @param dest - * will hold the result - * @return this - */ - Matrix4f scaleAroundLocal(float factor, float ox, float oy, float oz, Matrix4f dest); - - /** - * Apply rotation about the X axis to this matrix by rotating the given amount of radians - * and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateX(float ang, Matrix4f dest); - - /** - * Apply rotation about the Y axis to this matrix by rotating the given amount of radians - * and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateY(float ang, Matrix4f dest); - - /** - * Apply rotation about the Z axis to this matrix by rotating the given amount of radians - * and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateZ(float ang, Matrix4f dest); - - /** - * Apply rotation about the Z axis to align the local +X towards (dirX, dirY) and store the result in dest. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * The vector (dirX, dirY) must be a unit vector. - * - * @param dirX - * the x component of the normalized direction - * @param dirY - * the y component of the normalized direction - * @param dest - * will hold the result - * @return this - */ - Matrix4f rotateTowardsXY(float dirX, float dirY, Matrix4f dest); - - /** - * Apply rotation of angleX radians about the X axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleZ radians about the Z axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateX(angleX, dest).rotateY(angleY).rotateZ(angleZ) - * - * @param angleX - * the angle to rotate about X - * @param angleY - * the angle to rotate about Y - * @param angleZ - * the angle to rotate about Z - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateXYZ(float angleX, float angleY, float angleZ, Matrix4f dest); - - /** - * Apply rotation of angleX radians about the X axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleZ radians about the Z axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method assumes that this matrix represents an {@link #isAffine() affine} transformation (i.e. its last row is equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrix only represents affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - * - * @param angleX - * the angle to rotate about X - * @param angleY - * the angle to rotate about Y - * @param angleZ - * the angle to rotate about Z - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateAffineXYZ(float angleX, float angleY, float angleZ, Matrix4f dest); - - /** - * Apply rotation of angleZ radians about the Z axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleX radians about the X axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateZ(angleZ, dest).rotateY(angleY).rotateX(angleX) - * - * @param angleZ - * the angle to rotate about Z - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateZYX(float angleZ, float angleY, float angleX, Matrix4f dest); - - /** - * Apply rotation of angleZ radians about the Z axis, followed by a rotation of angleY radians about the Y axis and - * followed by a rotation of angleX radians about the X axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method assumes that this matrix represents an {@link #isAffine() affine} transformation (i.e. its last row is equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrix only represents affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - * - * @param angleZ - * the angle to rotate about Z - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateAffineZYX(float angleZ, float angleY, float angleX, Matrix4f dest); - - /** - * Apply rotation of angleY radians about the Y axis, followed by a rotation of angleX radians about the X axis and - * followed by a rotation of angleZ radians about the Z axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * This method is equivalent to calling: rotateY(angleY, dest).rotateX(angleX).rotateZ(angleZ) - * - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param angleZ - * the angle to rotate about Z - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateYXZ(float angleY, float angleX, float angleZ, Matrix4f dest); - - /** - * Apply rotation of angleY radians about the Y axis, followed by a rotation of angleX radians about the X axis and - * followed by a rotation of angleZ radians about the Z axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * This method assumes that this matrix represents an {@link #isAffine() affine} transformation (i.e. its last row is equal to (0, 0, 0, 1)) - * and can be used to speed up matrix multiplication if the matrix only represents affine transformations, such as translation, rotation, scaling and shearing (in any combination). - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - * - * @param angleY - * the angle to rotate about Y - * @param angleX - * the angle to rotate about X - * @param angleZ - * the angle to rotate about Z - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateAffineYXZ(float angleY, float angleX, float angleZ, Matrix4f dest); - - /** - * Apply rotation to this matrix by rotating the given amount of radians - * about the specified (x, y, z) axis and store the result in dest. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotate(float ang, float x, float y, float z, Matrix4f dest); - - /** - * Apply rotation to this matrix, which is assumed to only contain a translation, by rotating the given amount of radians - * about the specified (x, y, z) axis and store the result in dest. - *

- * This method assumes this to only contain a translation. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateTranslation(float ang, float x, float y, float z, Matrix4f dest); - - /** - * Apply rotation to this {@link #isAffine() affine} matrix by rotating the given amount of radians - * about the specified (x, y, z) axis and store the result in dest. - *

- * This method assumes this to be {@link #isAffine() affine}. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateAffine(float ang, float x, float y, float z, Matrix4f dest); - - /** - * Pre-multiply a rotation to this matrix by rotating the given amount of radians - * about the specified (x, y, z) axis and store the result in dest. - *

- * The axis described by the three components needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians - * @param x - * the x component of the axis - * @param y - * the y component of the axis - * @param z - * the z component of the axis - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateLocal(float ang, float x, float y, float z, Matrix4f dest); - - /** - * Pre-multiply a rotation around the X axis to this matrix by rotating the given amount of radians - * about the X axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians to rotate about the X axis - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateLocalX(float ang, Matrix4f dest); - - /** - * Pre-multiply a rotation around the Y axis to this matrix by rotating the given amount of radians - * about the Y axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians to rotate about the Y axis - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateLocalY(float ang, Matrix4f dest); - - /** - * Pre-multiply a rotation around the Z axis to this matrix by rotating the given amount of radians - * about the Z axis and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and R the rotation matrix, - * then the new matrix will be R * M. So when transforming a - * vector v with the new matrix by using R * M * v, the - * rotation will be applied last! - *

- * Reference: http://en.wikipedia.org - * - * @param ang - * the angle in radians to rotate about the Z axis - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateLocalZ(float ang, Matrix4f dest); - - /** - * Apply a translation to this matrix by translating by the given number of - * units in x, y and z and store the result in dest. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be M * T. So when - * transforming a vector v with the new matrix by using - * M * T * v, the translation will be applied first! - * - * @param offset - * the number of units in x, y and z by which to translate - * @param dest - * will hold the result - * @return dest - */ - Matrix4f translate(Vector3fc offset, Matrix4f dest); - - /** - * Apply a translation to this matrix by translating by the given number of - * units in x, y and z and store the result in dest. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be M * T. So when - * transforming a vector v with the new matrix by using - * M * T * v, the translation will be applied first! - * - * @param x - * the offset to translate in x - * @param y - * the offset to translate in y - * @param z - * the offset to translate in z - * @param dest - * will hold the result - * @return dest - */ - Matrix4f translate(float x, float y, float z, Matrix4f dest); - - /** - * Pre-multiply a translation to this matrix by translating by the given number of - * units in x, y and z and store the result in dest. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be T * M. So when - * transforming a vector v with the new matrix by using - * T * M * v, the translation will be applied last! - * - * @param offset - * the number of units in x, y and z by which to translate - * @param dest - * will hold the result - * @return dest - */ - Matrix4f translateLocal(Vector3fc offset, Matrix4f dest); - - /** - * Pre-multiply a translation to this matrix by translating by the given number of - * units in x, y and z and store the result in dest. - *

- * If M is this matrix and T the translation - * matrix, then the new matrix will be T * M. So when - * transforming a vector v with the new matrix by using - * T * M * v, the translation will be applied last! - * - * @param x - * the offset to translate in x - * @param y - * the offset to translate in y - * @param z - * the offset to translate in z - * @param dest - * will hold the result - * @return dest - */ - Matrix4f translateLocal(float x, float y, float z, Matrix4f dest); - - /** - * Apply an orthographic projection transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - * Reference: http://www.songho.ca - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - Matrix4f ortho(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply an orthographic projection transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @return dest - */ - Matrix4f ortho(float left, float right, float bottom, float top, float zNear, float zFar, Matrix4f dest); - - /** - * Apply an orthographic projection transformation for a left-handed coordiante system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - Matrix4f orthoLH(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply an orthographic projection transformation for a left-handed coordiante system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @return dest - */ - Matrix4f orthoLH(float left, float right, float bottom, float top, float zNear, float zFar, Matrix4f dest); - - /** - * Apply a symmetric orthographic projection transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * This method is equivalent to calling {@link #ortho(float, float, float, float, float, float, boolean, Matrix4f) ortho()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return dest - */ - Matrix4f orthoSymmetric(float width, float height, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply a symmetric orthographic projection transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * This method is equivalent to calling {@link #ortho(float, float, float, float, float, float, Matrix4f) ortho()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @return dest - */ - Matrix4f orthoSymmetric(float width, float height, float zNear, float zFar, Matrix4f dest); - - /** - * Apply a symmetric orthographic projection transformation for a left-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * This method is equivalent to calling {@link #orthoLH(float, float, float, float, float, float, boolean, Matrix4f) orthoLH()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return dest - */ - Matrix4f orthoSymmetricLH(float width, float height, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply a symmetric orthographic projection transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * This method is equivalent to calling {@link #orthoLH(float, float, float, float, float, float, Matrix4f) orthoLH()} with - * left=-width/2, right=+width/2, bottom=-height/2 and top=+height/2. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param width - * the distance between the right and left frustum edges - * @param height - * the distance between the top and bottom frustum edges - * @param zNear - * near clipping plane distance - * @param zFar - * far clipping plane distance - * @param dest - * will hold the result - * @return dest - */ - Matrix4f orthoSymmetricLH(float width, float height, float zNear, float zFar, Matrix4f dest); - - /** - * Apply an orthographic projection transformation for a right-handed coordinate system to this matrix - * and store the result in dest. - *

- * This method is equivalent to calling {@link #ortho(float, float, float, float, float, float, Matrix4f) ortho()} with - * zNear=-1 and zFar=+1. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @see #ortho(float, float, float, float, float, float, Matrix4f) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param dest - * will hold the result - * @return dest - */ - Matrix4f ortho2D(float left, float right, float bottom, float top, Matrix4f dest); - - /** - * Apply an orthographic projection transformation for a left-handed coordinate system to this matrix and store the result in dest. - *

- * This method is equivalent to calling {@link #orthoLH(float, float, float, float, float, float, Matrix4f) orthoLH()} with - * zNear=-1 and zFar=+1. - *

- * If M is this matrix and O the orthographic projection matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * orthographic projection transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @see #orthoLH(float, float, float, float, float, float, Matrix4f) - * - * @param left - * the distance from the center to the left frustum edge - * @param right - * the distance from the center to the right frustum edge - * @param bottom - * the distance from the center to the bottom frustum edge - * @param top - * the distance from the center to the top frustum edge - * @param dest - * will hold the result - * @return dest - */ - Matrix4f ortho2DLH(float left, float right, float bottom, float top, Matrix4f dest); - - /** - * Apply a rotation transformation to this matrix to make -z point along dir - * and store the result in dest. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - *

- * This is equivalent to calling - * {@link #lookAt(Vector3fc, Vector3fc, Vector3fc, Matrix4f) lookAt} - * with eye = (0, 0, 0) and center = dir. - * - * @see #lookAlong(float, float, float, float, float, float, Matrix4f) - * @see #lookAt(Vector3fc, Vector3fc, Vector3fc, Matrix4f) - * - * @param dir - * the direction in space to look along - * @param up - * the direction of 'up' - * @param dest - * will hold the result - * @return dest - */ - Matrix4f lookAlong(Vector3fc dir, Vector3fc up, Matrix4f dest); - - /** - * Apply a rotation transformation to this matrix to make -z point along dir - * and store the result in dest. - *

- * If M is this matrix and L the lookalong rotation matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, the - * lookalong rotation transformation will be applied first! - *

- * This is equivalent to calling - * {@link #lookAt(float, float, float, float, float, float, float, float, float, Matrix4f) lookAt()} - * with eye = (0, 0, 0) and center = dir. - * - * @see #lookAt(float, float, float, float, float, float, float, float, float, Matrix4f) - * - * @param dirX - * the x-coordinate of the direction to look along - * @param dirY - * the y-coordinate of the direction to look along - * @param dirZ - * the z-coordinate of the direction to look along - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - Matrix4f lookAlong(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Matrix4f dest); - - /** - * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, - * that aligns -z with center - eye and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - * - * @see #lookAt(float, float, float, float, float, float, float, float, float, Matrix4f) - * - * @param eye - * the position of the camera - * @param center - * the point in space to look at - * @param up - * the direction of 'up' - * @param dest - * will hold the result - * @return dest - */ - Matrix4f lookAt(Vector3fc eye, Vector3fc center, Vector3fc up, Matrix4f dest); - - /** - * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, - * that aligns -z with center - eye and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - * - * @see #lookAt(Vector3fc, Vector3fc, Vector3fc, Matrix4f) - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - Matrix4f lookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ, Matrix4f dest); - - /** - * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, - * that aligns -z with center - eye and store the result in dest. - *

- * This method assumes this to be a perspective transformation, obtained via - * {@link #frustum(float, float, float, float, float, float, Matrix4f) frustum()} or {@link #perspective(float, float, float, float, Matrix4f) perspective()} or - * one of their overloads. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - Matrix4f lookAtPerspective(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ, Matrix4f dest); - - /** - * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, - * that aligns +z with center - eye and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - * - * @see #lookAtLH(float, float, float, float, float, float, float, float, float, Matrix4f) - * - * @param eye - * the position of the camera - * @param center - * the point in space to look at - * @param up - * the direction of 'up' - * @param dest - * will hold the result - * @return dest - */ - Matrix4f lookAtLH(Vector3fc eye, Vector3fc center, Vector3fc up, Matrix4f dest); - - /** - * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, - * that aligns +z with center - eye and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - * - * @see #lookAtLH(Vector3fc, Vector3fc, Vector3fc, Matrix4f) - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - Matrix4f lookAtLH(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ, Matrix4f dest); - - /** - * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, - * that aligns +z with center - eye and store the result in dest. - *

- * This method assumes this to be a perspective transformation, obtained via - * {@link #frustumLH(float, float, float, float, float, float, Matrix4f) frustumLH()} or {@link #perspectiveLH(float, float, float, float, Matrix4f) perspectiveLH()} or - * one of their overloads. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - * - * @param eyeX - * the x-coordinate of the eye/camera location - * @param eyeY - * the y-coordinate of the eye/camera location - * @param eyeZ - * the z-coordinate of the eye/camera location - * @param centerX - * the x-coordinate of the point to look at - * @param centerY - * the y-coordinate of the point to look at - * @param centerZ - * the z-coordinate of the point to look at - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - Matrix4f lookAtPerspectiveLH(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ, Matrix4f dest); - - /** - * This method is equivalent to calling: translate(w-1-2*x, h-1-2*y, 0, dest).scale(w, h, 1) - *

- * If M is this matrix and T the created transformation matrix, - * then the new matrix will be M * T. So when transforming a - * vector v with the new matrix by using M * T * v, the - * created transformation will be applied first! - * - * @param x - * the tile's x coordinate/index (should be in [0..w)) - * @param y - * the tile's y coordinate/index (should be in [0..h)) - * @param w - * the number of tiles along the x axis - * @param h - * the number of tiles along the y axis - * @param dest - * will hold the result - * @return dest - */ - Matrix4f tile(int x, int y, int w, int h, Matrix4f dest); - - /** - * Apply a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return dest - */ - Matrix4f perspective(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - Matrix4f perspective(float fovy, float aspect, float zNear, float zFar, Matrix4f dest); - - /** - * Apply a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param width - * the width of the near frustum plane - * @param height - * the height of the near frustum plane - * @param zNear - * near clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return dest - */ - Matrix4f perspectiveRect(float width, float height, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply a symmetric perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param width - * the width of the near frustum plane - * @param height - * the height of the near frustum plane - * @param zNear - * near clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - Matrix4f perspectiveRect(float width, float height, float zNear, float zFar, Matrix4f dest); - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * The given angles offAngleX and offAngleY are the horizontal and vertical angles between - * the line of sight and the line given by the center of the near and far frustum planes. So, when offAngleY - * is just fovy/2 then the projection frustum is rotated towards +Y and the bottom frustum plane - * is parallel to the XZ-plane. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param offAngleX - * the horizontal angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param offAngleY - * the vertical angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @return dest - */ - Matrix4f perspectiveOffCenter(float fovy, float offAngleX, float offAngleY, float aspect, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * The given angles offAngleX and offAngleY are the horizontal and vertical angles between - * the line of sight and the line given by the center of the near and far frustum planes. So, when offAngleY - * is just fovy/2 then the projection frustum is rotated towards +Y and the bottom frustum plane - * is parallel to the XZ-plane. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param offAngleX - * the horizontal angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param offAngleY - * the vertical angle between the line of sight and the line crossing the center of the near and far frustum planes - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - Matrix4f perspectiveOffCenter(float fovy, float offAngleX, float offAngleY, float aspect, float zNear, float zFar, Matrix4f dest); - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - Matrix4f perspectiveOffCenterFov(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - Matrix4f perspectiveOffCenterFov(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, Matrix4f dest); - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - Matrix4f perspectiveOffCenterFovLH(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply an asymmetric off-center perspective projection frustum transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * The given angles angleLeft and angleRight are the horizontal angles between - * the left and right frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - * The angles angleDown and angleUp are the vertical angles between - * the bottom and top frustum planes, respectively, and a line perpendicular to the near and far frustum planes. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param angleLeft - * the horizontal angle between left frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleRight - * the horizontal angle between right frustum plane and a line perpendicular to the near/far frustum planes - * @param angleDown - * the vertical angle between bottom frustum plane and a line perpendicular to the near/far frustum planes. - * For a symmetric frustum, this value is negative. - * @param angleUp - * the vertical angle between top frustum plane and a line perpendicular to the near/far frustum planes - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - Matrix4f perspectiveOffCenterFovLH(float angleLeft, float angleRight, float angleDown, float angleUp, float zNear, float zFar, Matrix4f dest); - - /** - * Apply a symmetric perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - Matrix4f perspectiveLH(float fovy, float aspect, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply a symmetric perspective projection frustum transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and P the perspective projection matrix, - * then the new matrix will be M * P. So when transforming a - * vector v with the new matrix by using M * P * v, - * the perspective projection will be applied first! - * - * @param fovy - * the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI}) - * @param aspect - * the aspect ratio (i.e. width / height; must be greater than zero) - * @param zNear - * near clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - Matrix4f perspectiveLH(float fovy, float aspect, float zNear, float zFar, Matrix4f dest); - - /** - * Apply an arbitrary perspective projection frustum transformation for a right-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - Matrix4f frustum(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply an arbitrary perspective projection frustum transformation for a right-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - Matrix4f frustum(float left, float right, float bottom, float top, float zNear, float zFar, Matrix4f dest); - - /** - * Apply an arbitrary perspective projection frustum transformation for a left-handed coordinate system - * using the given NDC z range to this matrix and store the result in dest. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param zZeroToOne - * whether to use Vulkan's and Direct3D's NDC z range of [0..+1] when true - * or whether to use OpenGL's NDC z range of [-1..+1] when false - * @param dest - * will hold the result - * @return dest - */ - Matrix4f frustumLH(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne, Matrix4f dest); - - /** - * Apply an arbitrary perspective projection frustum transformation for a left-handed coordinate system - * using OpenGL's NDC z range of [-1..+1] to this matrix and store the result in dest. - *

- * If M is this matrix and F the frustum matrix, - * then the new matrix will be M * F. So when transforming a - * vector v with the new matrix by using M * F * v, - * the frustum transformation will be applied first! - *

- * Reference: http://www.songho.ca - * - * @param left - * the distance along the x-axis to the left frustum edge - * @param right - * the distance along the x-axis to the right frustum edge - * @param bottom - * the distance along the y-axis to the bottom frustum edge - * @param top - * the distance along the y-axis to the top frustum edge - * @param zNear - * near clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity. - * In that case, zFar may not also be {@link Float#POSITIVE_INFINITY}. - * @param zFar - * far clipping plane distance. This value must be greater than zero. - * If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity. - * In that case, zNear may not also be {@link Float#POSITIVE_INFINITY}. - * @param dest - * will hold the result - * @return dest - */ - Matrix4f frustumLH(float left, float right, float bottom, float top, float zNear, float zFar, Matrix4f dest); - - /** - * Apply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix and store - * the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotate(Quaternionfc quat, Matrix4f dest); - - /** - * Apply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this {@link #isAffine() affine} matrix and store - * the result in dest. - *

- * This method assumes this to be {@link #isAffine() affine}. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateAffine(Quaternionfc quat, Matrix4f dest); - - /** - * Apply the rotation - and possibly scaling - ransformation of the given {@link Quaternionfc} to this matrix, which is assumed to only contain a translation, and store - * the result in dest. - *

- * This method assumes this to only contain a translation. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateTranslation(Quaternionfc quat, Matrix4f dest); - - /** - * Apply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this {@link #isAffine() affine} - * matrix while using (ox, oy, oz) as the rotation origin, and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * This method is only applicable if this is an {@link #isAffine() affine} matrix. - *

- * This method is equivalent to calling: translate(ox, oy, oz, dest).rotate(quat).translate(-ox, -oy, -oz) - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param ox - * the x coordinate of the rotation origin - * @param oy - * the y coordinate of the rotation origin - * @param oz - * the z coordinate of the rotation origin - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateAroundAffine(Quaternionfc quat, float ox, float oy, float oz, Matrix4f dest); - - /** - * Apply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix while using (ox, oy, oz) as the rotation origin, - * and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be M * Q. So when transforming a - * vector v with the new matrix by using M * Q * v, - * the quaternion rotation will be applied first! - *

- * This method is equivalent to calling: translate(ox, oy, oz, dest).rotate(quat).translate(-ox, -oy, -oz) - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param ox - * the x coordinate of the rotation origin - * @param oy - * the y coordinate of the rotation origin - * @param oz - * the z coordinate of the rotation origin - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateAround(Quaternionfc quat, float ox, float oy, float oz, Matrix4f dest); - - /** - * Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix and store - * the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be Q * M. So when transforming a - * vector v with the new matrix by using Q * M * v, - * the quaternion rotation will be applied last! - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateLocal(Quaternionfc quat, Matrix4f dest); - - /** - * Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaternionfc} to this matrix while using (ox, oy, oz) - * as the rotation origin, and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and Q the rotation matrix obtained from the given quaternion, - * then the new matrix will be Q * M. So when transforming a - * vector v with the new matrix by using Q * M * v, - * the quaternion rotation will be applied last! - *

- * This method is equivalent to calling: translateLocal(-ox, -oy, -oz, dest).rotateLocal(quat).translateLocal(ox, oy, oz) - *

- * Reference: http://en.wikipedia.org - * - * @param quat - * the {@link Quaternionfc} - * @param ox - * the x coordinate of the rotation origin - * @param oy - * the y coordinate of the rotation origin - * @param oz - * the z coordinate of the rotation origin - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateAroundLocal(Quaternionfc quat, float ox, float oy, float oz, Matrix4f dest); - - /** - * Apply a rotation transformation, rotating about the given {@link AxisAngle4f} and store the result in dest. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given {@link AxisAngle4f}, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the {@link AxisAngle4f} rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float, Matrix4f) - * - * @param axisAngle - * the {@link AxisAngle4f} (needs to be {@link AxisAngle4f#normalize() normalized}) - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotate(AxisAngle4f axisAngle, Matrix4f dest); - - /** - * Apply a rotation transformation, rotating the given radians about the specified axis and store the result in dest. - *

- * The axis described by the axis vector needs to be a unit vector. - *

- * When used with a right-handed coordinate system, the produced rotation will rotate a vector - * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. - * When used with a left-handed coordinate system, the rotation is clockwise. - *

- * If M is this matrix and A the rotation matrix obtained from the given axis-angle, - * then the new matrix will be M * A. So when transforming a - * vector v with the new matrix by using M * A * v, - * the axis-angle rotation will be applied first! - *

- * Reference: http://en.wikipedia.org - * - * @see #rotate(float, float, float, float, Matrix4f) - * - * @param angle - * the angle in radians - * @param axis - * the rotation axis (needs to be {@link Vector3fc#normalize(Vector3f) normalized}) - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotate(float angle, Vector3fc axis, Matrix4f dest); - - /** - * Unproject the given window coordinates (winX, winY, winZ) by this matrix using the specified viewport. - *

- * This method first converts the given window coordinates to normalized device coordinates in the range [-1..1] - * and then transforms those NDC coordinates by the inverse of this matrix. - *

- * The depth range of winZ is assumed to be [0..1], which is also the OpenGL default. - *

- * As a necessary computation step for unprojecting, this method computes the inverse of this matrix. - * In order to avoid computing the matrix inverse with every invocation, the inverse of this matrix can be built - * once outside using {@link #invert(Matrix4f)} and then the method {@link #unprojectInv(float, float, float, int[], Vector4f) unprojectInv()} can be invoked on it. - * - * @see #unprojectInv(float, float, float, int[], Vector4f) - * @see #invert(Matrix4f) - * - * @param winX - * the x-coordinate in window coordinates (pixels) - * @param winY - * the y-coordinate in window coordinates (pixels) - * @param winZ - * the z-coordinate, which is the depth value in [0..1] - * @param viewport - * the viewport described by [x, y, width, height] - * @param dest - * will hold the unprojected position - * @return dest - */ - Vector4f unproject(float winX, float winY, float winZ, int[] viewport, Vector4f dest); - - /** - * Unproject the given window coordinates (winX, winY, winZ) by this matrix using the specified viewport. - *

- * This method first converts the given window coordinates to normalized device coordinates in the range [-1..1] - * and then transforms those NDC coordinates by the inverse of this matrix. - *

- * The depth range of winZ is assumed to be [0..1], which is also the OpenGL default. - *

- * As a necessary computation step for unprojecting, this method computes the inverse of this matrix. - * In order to avoid computing the matrix inverse with every invocation, the inverse of this matrix can be built - * once outside using {@link #invert(Matrix4f)} and then the method {@link #unprojectInv(float, float, float, int[], Vector3f) unprojectInv()} can be invoked on it. - * - * @see #unprojectInv(float, float, float, int[], Vector3f) - * @see #invert(Matrix4f) - * - * @param winX - * the x-coordinate in window coordinates (pixels) - * @param winY - * the y-coordinate in window coordinates (pixels) - * @param winZ - * the z-coordinate, which is the depth value in [0..1] - * @param viewport - * the viewport described by [x, y, width, height] - * @param dest - * will hold the unprojected position - * @return dest - */ - Vector3f unproject(float winX, float winY, float winZ, int[] viewport, Vector3f dest); - - /** - * Unproject the given window coordinates winCoords by this matrix using the specified viewport. - *

- * This method first converts the given window coordinates to normalized device coordinates in the range [-1..1] - * and then transforms those NDC coordinates by the inverse of this matrix. - *

- * The depth range of winCoords.z is assumed to be [0..1], which is also the OpenGL default. - *

- * As a necessary computation step for unprojecting, this method computes the inverse of this matrix. - * In order to avoid computing the matrix inverse with every invocation, the inverse of this matrix can be built - * once outside using {@link #invert(Matrix4f)} and then the method {@link #unprojectInv(float, float, float, int[], Vector4f) unprojectInv()} can be invoked on it. - * - * @see #unprojectInv(float, float, float, int[], Vector4f) - * @see #unproject(float, float, float, int[], Vector4f) - * @see #invert(Matrix4f) - * - * @param winCoords - * the window coordinates to unproject - * @param viewport - * the viewport described by [x, y, width, height] - * @param dest - * will hold the unprojected position - * @return dest - */ - Vector4f unproject(Vector3fc winCoords, int[] viewport, Vector4f dest); - - /** - * Unproject the given window coordinates winCoords by this matrix using the specified viewport. - *

- * This method first converts the given window coordinates to normalized device coordinates in the range [-1..1] - * and then transforms those NDC coordinates by the inverse of this matrix. - *

- * The depth range of winCoords.z is assumed to be [0..1], which is also the OpenGL default. - *

- * As a necessary computation step for unprojecting, this method computes the inverse of this matrix. - * In order to avoid computing the matrix inverse with every invocation, the inverse of this matrix can be built - * once outside using {@link #invert(Matrix4f)} and then the method {@link #unprojectInv(float, float, float, int[], Vector3f) unprojectInv()} can be invoked on it. - * - * @see #unprojectInv(float, float, float, int[], Vector3f) - * @see #unproject(float, float, float, int[], Vector3f) - * @see #invert(Matrix4f) - * - * @param winCoords - * the window coordinates to unproject - * @param viewport - * the viewport described by [x, y, width, height] - * @param dest - * will hold the unprojected position - * @return dest - */ - Vector3f unproject(Vector3fc winCoords, int[] viewport, Vector3f dest); - - /** - * Unproject the given 2D window coordinates (winX, winY) by this matrix using the specified viewport - * and compute the origin and the direction of the resulting ray which starts at NDC z = -1.0 and goes through NDC z = +1.0. - *

- * This method first converts the given window coordinates to normalized device coordinates in the range [-1..1] - * and then transforms those NDC coordinates by the inverse of this matrix. - *

- * As a necessary computation step for unprojecting, this method computes the inverse of this matrix. - * In order to avoid computing the matrix inverse with every invocation, the inverse of this matrix can be built - * once outside using {@link #invert(Matrix4f)} and then the method {@link #unprojectInvRay(float, float, int[], Vector3f, Vector3f) unprojectInvRay()} can be invoked on it. - * - * @see #unprojectInvRay(float, float, int[], Vector3f, Vector3f) - * @see #invert(Matrix4f) - * - * @param winX - * the x-coordinate in window coordinates (pixels) - * @param winY - * the y-coordinate in window coordinates (pixels) - * @param viewport - * the viewport described by [x, y, width, height] - * @param originDest - * will hold the ray origin - * @param dirDest - * will hold the (unnormalized) ray direction - * @return this - */ - Matrix4f unprojectRay(float winX, float winY, int[] viewport, Vector3f originDest, Vector3f dirDest); - - /** - * Unproject the given window coordinates winCoords by this matrix using the specified viewport. - *

- * This method differs from {@link #unproject(Vector3fc, int[], Vector4f) unproject()} - * in that it assumes that this is already the inverse matrix of the original projection matrix. - * It exists to avoid recomputing the matrix inverse with every invocation. - *

- * The depth range of winCoords.z is assumed to be [0..1], which is also the OpenGL default. - *

- * This method reads the four viewport parameters from the given int[]. - * - * @see #unproject(Vector3fc, int[], Vector4f) - * - * @param winCoords - * the window coordinates to unproject - * @param viewport - * the viewport described by [x, y, width, height] - * @param dest - * will hold the unprojected position - * @return dest - */ - Vector4f unprojectInv(Vector3fc winCoords, int[] viewport, Vector4f dest); - - /** - * Unproject the given window coordinates (winX, winY, winZ) by this matrix using the specified viewport. - *

- * This method differs from {@link #unproject(float, float, float, int[], Vector4f) unproject()} - * in that it assumes that this is already the inverse matrix of the original projection matrix. - * It exists to avoid recomputing the matrix inverse with every invocation. - *

- * The depth range of winZ is assumed to be [0..1], which is also the OpenGL default. - * - * @see #unproject(float, float, float, int[], Vector4f) - * - * @param winX - * the x-coordinate in window coordinates (pixels) - * @param winY - * the y-coordinate in window coordinates (pixels) - * @param winZ - * the z-coordinate, which is the depth value in [0..1] - * @param viewport - * the viewport described by [x, y, width, height] - * @param dest - * will hold the unprojected position - * @return dest - */ - Vector4f unprojectInv(float winX, float winY, float winZ, int[] viewport, Vector4f dest); - - /** - * Unproject the given 2D window coordinates (winX, winY) by this matrix using the specified viewport - * and compute the origin and the direction of the resulting ray which starts at NDC z = -1.0 and goes through NDC z = +1.0. - *

- * This method differs from {@link #unprojectRay(float, float, int[], Vector3f, Vector3f) unprojectRay()} - * in that it assumes that this is already the inverse matrix of the original projection matrix. - * It exists to avoid recomputing the matrix inverse with every invocation. - * - * @see #unprojectRay(float, float, int[], Vector3f, Vector3f) - * - * @param winX - * the x-coordinate in window coordinates (pixels) - * @param winY - * the y-coordinate in window coordinates (pixels) - * @param viewport - * the viewport described by [x, y, width, height] - * @param originDest - * will hold the ray origin - * @param dirDest - * will hold the (unnormalized) ray direction - * @return this - */ - Matrix4f unprojectInvRay(float winX, float winY, int[] viewport, Vector3f originDest, Vector3f dirDest); - - /** - * Unproject the given window coordinates winCoords by this matrix using the specified viewport. - *

- * This method differs from {@link #unproject(Vector3fc, int[], Vector3f) unproject()} - * in that it assumes that this is already the inverse matrix of the original projection matrix. - * It exists to avoid recomputing the matrix inverse with every invocation. - *

- * The depth range of winCoords.z is assumed to be [0..1], which is also the OpenGL default. - * - * @see #unproject(Vector3fc, int[], Vector3f) - * - * @param winCoords - * the window coordinates to unproject - * @param viewport - * the viewport described by [x, y, width, height] - * @param dest - * will hold the unprojected position - * @return dest - */ - Vector3f unprojectInv(Vector3fc winCoords, int[] viewport, Vector3f dest); - - /** - * Unproject the given window coordinates (winX, winY, winZ) by this matrix using the specified viewport. - *

- * This method differs from {@link #unproject(float, float, float, int[], Vector3f) unproject()} - * in that it assumes that this is already the inverse matrix of the original projection matrix. - * It exists to avoid recomputing the matrix inverse with every invocation. - *

- * The depth range of winZ is assumed to be [0..1], which is also the OpenGL default. - * - * @see #unproject(float, float, float, int[], Vector3f) - * - * @param winX - * the x-coordinate in window coordinates (pixels) - * @param winY - * the y-coordinate in window coordinates (pixels) - * @param winZ - * the z-coordinate, which is the depth value in [0..1] - * @param viewport - * the viewport described by [x, y, width, height] - * @param dest - * will hold the unprojected position - * @return dest - */ - Vector3f unprojectInv(float winX, float winY, float winZ, int[] viewport, Vector3f dest); - - /** - * Project the given (x, y, z) position via this matrix using the specified viewport - * and store the resulting window coordinates in winCoordsDest. - *

- * This method transforms the given coordinates by this matrix including perspective division to - * obtain normalized device coordinates, and then translates these into window coordinates by using the - * given viewport settings [x, y, width, height]. - *

- * The depth range of the returned winCoordsDest.z will be [0..1], which is also the OpenGL default. - * - * @param x - * the x-coordinate of the position to project - * @param y - * the y-coordinate of the position to project - * @param z - * the z-coordinate of the position to project - * @param viewport - * the viewport described by [x, y, width, height] - * @param winCoordsDest - * will hold the projected window coordinates - * @return winCoordsDest - */ - Vector4f project(float x, float y, float z, int[] viewport, Vector4f winCoordsDest); - - /** - * Project the given (x, y, z) position via this matrix using the specified viewport - * and store the resulting window coordinates in winCoordsDest. - *

- * This method transforms the given coordinates by this matrix including perspective division to - * obtain normalized device coordinates, and then translates these into window coordinates by using the - * given viewport settings [x, y, width, height]. - *

- * The depth range of the returned winCoordsDest.z will be [0..1], which is also the OpenGL default. - * - * @param x - * the x-coordinate of the position to project - * @param y - * the y-coordinate of the position to project - * @param z - * the z-coordinate of the position to project - * @param viewport - * the viewport described by [x, y, width, height] - * @param winCoordsDest - * will hold the projected window coordinates - * @return winCoordsDest - */ - Vector3f project(float x, float y, float z, int[] viewport, Vector3f winCoordsDest); - - /** - * Project the given position via this matrix using the specified viewport - * and store the resulting window coordinates in winCoordsDest. - *

- * This method transforms the given coordinates by this matrix including perspective division to - * obtain normalized device coordinates, and then translates these into window coordinates by using the - * given viewport settings [x, y, width, height]. - *

- * The depth range of the returned winCoordsDest.z will be [0..1], which is also the OpenGL default. - * - * @see #project(float, float, float, int[], Vector4f) - * - * @param position - * the position to project into window coordinates - * @param viewport - * the viewport described by [x, y, width, height] - * @param winCoordsDest - * will hold the projected window coordinates - * @return winCoordsDest - */ - Vector4f project(Vector3fc position, int[] viewport, Vector4f winCoordsDest); - - /** - * Project the given position via this matrix using the specified viewport - * and store the resulting window coordinates in winCoordsDest. - *

- * This method transforms the given coordinates by this matrix including perspective division to - * obtain normalized device coordinates, and then translates these into window coordinates by using the - * given viewport settings [x, y, width, height]. - *

- * The depth range of the returned winCoordsDest.z will be [0..1], which is also the OpenGL default. - * - * @see #project(float, float, float, int[], Vector4f) - * - * @param position - * the position to project into window coordinates - * @param viewport - * the viewport described by [x, y, width, height] - * @param winCoordsDest - * will hold the projected window coordinates - * @return winCoordsDest - */ - Vector3f project(Vector3fc position, int[] viewport, Vector3f winCoordsDest); - - /** - * Apply a mirror/reflection transformation to this matrix that reflects about the given plane - * specified via the equation x*a + y*b + z*c + d = 0 and store the result in dest. - *

- * The vector (a, b, c) must be a unit vector. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - *

- * Reference: msdn.microsoft.com - * - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param dest - * will hold the result - * @return dest - */ - Matrix4f reflect(float a, float b, float c, float d, Matrix4f dest); - - /** - * Apply a mirror/reflection transformation to this matrix that reflects about the given plane - * specified via the plane normal and a point on the plane, and store the result in dest. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param nx - * the x-coordinate of the plane normal - * @param ny - * the y-coordinate of the plane normal - * @param nz - * the z-coordinate of the plane normal - * @param px - * the x-coordinate of a point on the plane - * @param py - * the y-coordinate of a point on the plane - * @param pz - * the z-coordinate of a point on the plane - * @param dest - * will hold the result - * @return dest - */ - Matrix4f reflect(float nx, float ny, float nz, float px, float py, float pz, Matrix4f dest); - - /** - * Apply a mirror/reflection transformation to this matrix that reflects about a plane - * specified via the plane orientation and a point on the plane, and store the result in dest. - *

- * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. - * It is assumed that the default mirror plane's normal is (0, 0, 1). So, if the given {@link Quaternionfc} is - * the identity (does not apply any additional rotation), the reflection plane will be z=0, offset by the given point. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param orientation - * the plane orientation relative to an implied normal vector of (0, 0, 1) - * @param point - * a point on the plane - * @param dest - * will hold the result - * @return dest - */ - Matrix4f reflect(Quaternionfc orientation, Vector3fc point, Matrix4f dest); - - /** - * Apply a mirror/reflection transformation to this matrix that reflects about the given plane - * specified via the plane normal and a point on the plane, and store the result in dest. - *

- * If M is this matrix and R the reflection matrix, - * then the new matrix will be M * R. So when transforming a - * vector v with the new matrix by using M * R * v, the - * reflection will be applied first! - * - * @param normal - * the plane normal - * @param point - * a point on the plane - * @param dest - * will hold the result - * @return dest - */ - Matrix4f reflect(Vector3fc normal, Vector3fc point, Matrix4f dest); - - /** - * Get the row at the given row index, starting with 0. - * - * @param row - * the row index in [0..3] - * @param dest - * will hold the row components - * @return the passed in destination - * @throws IndexOutOfBoundsException if row is not in [0..3] - */ - Vector4f getRow(int row, Vector4f dest) throws IndexOutOfBoundsException; - - /** - * Get the first three components of the row at the given row index, starting with 0. - * - * @param row - * the row index in [0..3] - * @param dest - * will hold the first three row components - * @return the passed in destination - * @throws IndexOutOfBoundsException if row is not in [0..3] - */ - Vector3f getRow(int row, Vector3f dest) throws IndexOutOfBoundsException; - - /** - * Get the column at the given column index, starting with 0. - * - * @param column - * the column index in [0..3] - * @param dest - * will hold the column components - * @return the passed in destination - * @throws IndexOutOfBoundsException if column is not in [0..3] - */ - Vector4f getColumn(int column, Vector4f dest) throws IndexOutOfBoundsException; - - /** - * Get the first three components of the column at the given column index, starting with 0. - * - * @param column - * the column index in [0..3] - * @param dest - * will hold the first three column components - * @return the passed in destination - * @throws IndexOutOfBoundsException if column is not in [0..3] - */ - Vector3f getColumn(int column, Vector3f dest) throws IndexOutOfBoundsException; - - /** - * Get the matrix element value at the given column and row. - * - * @param column - * the colum index in [0..3] - * @param row - * the row index in [0..3] - * @return the element value - */ - float get(int column, int row); - - /** - * Get the matrix element value at the given row and column. - * - * @param row - * the row index in [0..3] - * @param column - * the colum index in [0..3] - * @return the element value - */ - float getRowColumn(int row, int column); - - /** - * Compute a normal matrix from the upper left 3x3 submatrix of this - * and store it into the upper left 3x3 submatrix of dest. - * All other values of dest will be set to identity. - *

- * The normal matrix of m is the transpose of the inverse of m. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f normal(Matrix4f dest); - - /** - * Compute a normal matrix from the upper left 3x3 submatrix of this - * and store it into dest. - *

- * The normal matrix of m is the transpose of the inverse of m. - * - * @see Matrix3f#set(Matrix4fc) - * @see #get3x3(Matrix3f) - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f normal(Matrix3f dest); - - /** - * Compute the cofactor matrix of the upper left 3x3 submatrix of this - * and store it into dest. - *

- * The cofactor matrix can be used instead of {@link #normal(Matrix3f)} to transform normals - * when the orientation of the normals with respect to the surface should be preserved. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f cofactor3x3(Matrix3f dest); - - /** - * Compute the cofactor matrix of the upper left 3x3 submatrix of this - * and store it into dest. - * All other values of dest will be set to identity. - *

- * The cofactor matrix can be used instead of {@link #normal(Matrix4f)} to transform normals - * when the orientation of the normals with respect to the surface should be preserved. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f cofactor3x3(Matrix4f dest); - - /** - * Normalize the upper left 3x3 submatrix of this matrix and store the result in dest. - *

- * The resulting matrix will map unit vectors to unit vectors, though a pair of orthogonal input unit - * vectors need not be mapped to a pair of orthogonal output vectors if the original matrix was not orthogonal itself - * (i.e. had skewing). - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f normalize3x3(Matrix4f dest); - - /** - * Normalize the upper left 3x3 submatrix of this matrix and store the result in dest. - *

- * The resulting matrix will map unit vectors to unit vectors, though a pair of orthogonal input unit - * vectors need not be mapped to a pair of orthogonal output vectors if the original matrix was not orthogonal itself - * (i.e. had skewing). - * - * @param dest - * will hold the result - * @return dest - */ - Matrix3f normalize3x3(Matrix3f dest); - - /** - * Calculate a frustum plane of this matrix, which - * can be a projection matrix or a combined modelview-projection matrix, and store the result - * in the given planeEquation. - *

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

- * The frustum plane will be given in the form of a general plane equation: - * a*x + b*y + c*z + d = 0, where the given {@link Vector4f} components will - * hold the (a, b, c, d) values of the equation. - *

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

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

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @param plane - * one of the six possible planes, given as numeric constants - * {@link #PLANE_NX}, {@link #PLANE_PX}, - * {@link #PLANE_NY}, {@link #PLANE_PY}, - * {@link #PLANE_NZ} and {@link #PLANE_PZ} - * @param planeEquation - * will hold the computed plane equation. - * The plane equation will be normalized, meaning that (a, b, c) will be a unit vector - * @return planeEquation - */ - Vector4f frustumPlane(int plane, Vector4f planeEquation); - - /** - * Compute the corner coordinates of the frustum defined by this matrix, which - * can be a projection matrix or a combined modelview-projection matrix, and store the result - * in the given point. - *

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

- * Reference: http://geomalgorithms.com - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @param corner - * one of the eight possible corners, given as numeric constants - * {@link #CORNER_NXNYNZ}, {@link #CORNER_PXNYNZ}, {@link #CORNER_PXPYNZ}, {@link #CORNER_NXPYNZ}, - * {@link #CORNER_PXNYPZ}, {@link #CORNER_NXNYPZ}, {@link #CORNER_NXPYPZ}, {@link #CORNER_PXPYPZ} - * @param point - * will hold the resulting corner point coordinates - * @return point - */ - Vector3f frustumCorner(int corner, Vector3f point); - - /** - * Compute the eye/origin of the perspective frustum transformation defined by this matrix, - * which can be a projection matrix or a combined modelview-projection matrix, and store the result - * in the given origin. - *

- * Note that this method will only work using perspective projections obtained via one of the - * perspective methods, such as {@link #perspective(float, float, float, float, Matrix4f) perspective()} - * or {@link #frustum(float, float, float, float, float, float, Matrix4f) frustum()}. - *

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

- * This method is equivalent to calling: invert(new Matrix4f()).transformProject(0, 0, -1, 0, origin) - * and in the case of an already available inverse of this matrix, the method {@link #perspectiveInvOrigin(Vector3f)} - * on the inverse of the matrix should be used instead. - *

- * Reference: http://geomalgorithms.com - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @param origin - * will hold the origin of the coordinate system before applying this - * perspective projection transformation - * @return origin - */ - Vector3f perspectiveOrigin(Vector3f origin); - - /** - * Compute the eye/origin of the inverse of the perspective frustum transformation defined by this matrix, - * which can be the inverse of a projection matrix or the inverse of a combined modelview-projection matrix, and store the result - * in the given dest. - *

- * Note that this method will only work using perspective projections obtained via one of the - * perspective methods, such as {@link #perspective(float, float, float, float, Matrix4f) perspective()} - * or {@link #frustum(float, float, float, float, float, float, Matrix4f) frustum()}. - *

- * If the inverse of the modelview-projection matrix is not available, then calling {@link #perspectiveOrigin(Vector3f)} - * on the original modelview-projection matrix is preferred. - * - * @see #perspectiveOrigin(Vector3f) - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f perspectiveInvOrigin(Vector3f dest); - - /** - * Return the vertical field-of-view angle in radians of this perspective transformation matrix. - *

- * Note that this method will only work using perspective projections obtained via one of the - * perspective methods, such as {@link #perspective(float, float, float, float, Matrix4f) perspective()} - * or {@link #frustum(float, float, float, float, float, float, Matrix4f) frustum()}. - *

- * For orthogonal transformations this method will return 0.0. - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @return the vertical field-of-view angle in radians - */ - float perspectiveFov(); - - /** - * Extract the near clip plane distance from this perspective projection matrix. - *

- * This method only works if this is a perspective projection matrix, for example obtained via {@link #perspective(float, float, float, float, Matrix4f)}. - * - * @return the near clip plane distance - */ - float perspectiveNear(); - - /** - * Extract the far clip plane distance from this perspective projection matrix. - *

- * This method only works if this is a perspective projection matrix, for example obtained via {@link #perspective(float, float, float, float, Matrix4f)}. - * - * @return the far clip plane distance - */ - float perspectiveFar(); - - /** - * Obtain the direction of a ray starting at the center of the coordinate system and going - * through the near frustum plane. - *

- * This method computes the dir vector in the local frame of - * any coordinate system that existed before this - * transformation was applied to it in order to yield homogeneous clipping space. - *

- * The parameters x and y are used to interpolate the generated ray direction - * from the bottom-left to the top-right frustum corners. - *

- * For optimal efficiency when building many ray directions over the whole frustum, - * it is recommended to use this method only in order to compute the four corner rays at - * (0, 0), (1, 0), (0, 1) and (1, 1) - * and then bilinearly interpolating between them; or to use the {@link FrustumRayBuilder}. - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @param x - * the interpolation factor along the left-to-right frustum planes, within [0..1] - * @param y - * the interpolation factor along the bottom-to-top frustum planes, within [0..1] - * @param dir - * will hold the normalized ray direction in the local frame of the coordinate system before - * transforming to homogeneous clipping space using this matrix - * @return dir - */ - Vector3f frustumRayDir(float x, float y, Vector3f dir); - - /** - * Obtain the direction of +Z before the transformation represented by this matrix is applied. - *

- * This method uses the rotation component of the upper left 3x3 submatrix to obtain the direction - * that is transformed to +Z by this matrix. - *

- * This method is equivalent to the following code: - *

-     * Matrix4f inv = new Matrix4f(this).invert();
-     * inv.transformDirection(dir.set(0, 0, 1)).normalize();
-     * 
- * If this is already an orthogonal matrix, then consider using {@link #normalizedPositiveZ(Vector3f)} instead. - *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +Z - * @return dir - */ - Vector3f positiveZ(Vector3f dir); - - /** - * Obtain the direction of +Z before the transformation represented by this orthogonal matrix is applied. - * This method only produces correct results if this is an orthogonal matrix. - *

- * This method uses the rotation component of the upper left 3x3 submatrix to obtain the direction - * that is transformed to +Z by this matrix. - *

- * This method is equivalent to the following code: - *

-     * Matrix4f inv = new Matrix4f(this).transpose();
-     * inv.transformDirection(dir.set(0, 0, 1));
-     * 
- *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +Z - * @return dir - */ - Vector3f normalizedPositiveZ(Vector3f dir); - - /** - * Obtain the direction of +X before the transformation represented by this matrix is applied. - *

- * This method uses the rotation component of the upper left 3x3 submatrix to obtain the direction - * that is transformed to +X by this matrix. - *

- * This method is equivalent to the following code: - *

-     * Matrix4f inv = new Matrix4f(this).invert();
-     * inv.transformDirection(dir.set(1, 0, 0)).normalize();
-     * 
- * If this is already an orthogonal matrix, then consider using {@link #normalizedPositiveX(Vector3f)} instead. - *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +X - * @return dir - */ - Vector3f positiveX(Vector3f dir); - - /** - * Obtain the direction of +X before the transformation represented by this orthogonal matrix is applied. - * This method only produces correct results if this is an orthogonal matrix. - *

- * This method uses the rotation component of the upper left 3x3 submatrix to obtain the direction - * that is transformed to +X by this matrix. - *

- * This method is equivalent to the following code: - *

-     * Matrix4f inv = new Matrix4f(this).transpose();
-     * inv.transformDirection(dir.set(1, 0, 0));
-     * 
- *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +X - * @return dir - */ - Vector3f normalizedPositiveX(Vector3f dir); - - /** - * Obtain the direction of +Y before the transformation represented by this matrix is applied. - *

- * This method uses the rotation component of the upper left 3x3 submatrix to obtain the direction - * that is transformed to +Y by this matrix. - *

- * This method is equivalent to the following code: - *

-     * Matrix4f inv = new Matrix4f(this).invert();
-     * inv.transformDirection(dir.set(0, 1, 0)).normalize();
-     * 
- * If this is already an orthogonal matrix, then consider using {@link #normalizedPositiveY(Vector3f)} instead. - *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +Y - * @return dir - */ - Vector3f positiveY(Vector3f dir); - - /** - * Obtain the direction of +Y before the transformation represented by this orthogonal matrix is applied. - * This method only produces correct results if this is an orthogonal matrix. - *

- * This method uses the rotation component of the upper left 3x3 submatrix to obtain the direction - * that is transformed to +Y by this matrix. - *

- * This method is equivalent to the following code: - *

-     * Matrix4f inv = new Matrix4f(this).transpose();
-     * inv.transformDirection(dir.set(0, 1, 0));
-     * 
- *

- * Reference: http://www.euclideanspace.com - * - * @param dir - * will hold the direction of +Y - * @return dir - */ - Vector3f normalizedPositiveY(Vector3f dir); - - /** - * Obtain the position that gets transformed to the origin by this {@link #isAffine() affine} matrix. - * This can be used to get the position of the "camera" from a given view transformation matrix. - *

- * This method only works with {@link #isAffine() affine} matrices. - *

- * This method is equivalent to the following code: - *

-     * Matrix4f inv = new Matrix4f(this).invertAffine();
-     * inv.transformPosition(origin.set(0, 0, 0));
-     * 
- * - * @param origin - * will hold the position transformed to the origin - * @return origin - */ - Vector3f originAffine(Vector3f origin); - - /** - * Obtain the position that gets transformed to the origin by this matrix. - * This can be used to get the position of the "camera" from a given view/projection transformation matrix. - *

- * This method is equivalent to the following code: - *

-     * Matrix4f inv = new Matrix4f(this).invert();
-     * inv.transformPosition(origin.set(0, 0, 0));
-     * 
- * - * @param origin - * will hold the position transformed to the origin - * @return origin - */ - Vector3f origin(Vector3f origin); - - /** - * Apply a projection transformation to this matrix that projects onto the plane specified via the general plane equation - * x*a + y*b + z*c + d = 0 as if casting a shadow from a given light position/direction light - * and store the result in dest. - *

- * If light.w is 0.0 the light is being treated as a directional light; if it is 1.0 it is a point light. - *

- * If M is this matrix and S the shadow matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * shadow projection will be applied first! - *

- * Reference: ftp.sgi.com - * - * @param light - * the light's vector - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param dest - * will hold the result - * @return dest - */ - Matrix4f shadow(Vector4f light, float a, float b, float c, float d, Matrix4f dest); - - /** - * Apply a projection transformation to this matrix that projects onto the plane specified via the general plane equation - * x*a + y*b + z*c + d = 0 as if casting a shadow from a given light position/direction (lightX, lightY, lightZ, lightW) - * and store the result in dest. - *

- * If lightW is 0.0 the light is being treated as a directional light; if it is 1.0 it is a point light. - *

- * If M is this matrix and S the shadow matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * shadow projection will be applied first! - *

- * Reference: ftp.sgi.com - * - * @param lightX - * the x-component of the light's vector - * @param lightY - * the y-component of the light's vector - * @param lightZ - * the z-component of the light's vector - * @param lightW - * the w-component of the light's vector - * @param a - * the x factor in the plane equation - * @param b - * the y factor in the plane equation - * @param c - * the z factor in the plane equation - * @param d - * the constant in the plane equation - * @param dest - * will hold the result - * @return dest - */ - Matrix4f shadow(float lightX, float lightY, float lightZ, float lightW, float a, float b, float c, float d, Matrix4f dest); - - /** - * Apply a projection transformation to this matrix that projects onto the plane with the general plane equation - * y = 0 as if casting a shadow from a given light position/direction light - * and store the result in dest. - *

- * Before the shadow projection is applied, the plane is transformed via the specified planeTransformation. - *

- * If light.w is 0.0 the light is being treated as a directional light; if it is 1.0 it is a point light. - *

- * If M is this matrix and S the shadow matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * shadow projection will be applied first! - * - * @param light - * the light's vector - * @param planeTransform - * the transformation to transform the implied plane y = 0 before applying the projection - * @param dest - * will hold the result - * @return dest - */ - Matrix4f shadow(Vector4f light, Matrix4fc planeTransform, Matrix4f dest); - - /** - * Apply a projection transformation to this matrix that projects onto the plane with the general plane equation - * y = 0 as if casting a shadow from a given light position/direction (lightX, lightY, lightZ, lightW) - * and store the result in dest. - *

- * Before the shadow projection is applied, the plane is transformed via the specified planeTransformation. - *

- * If lightW is 0.0 the light is being treated as a directional light; if it is 1.0 it is a point light. - *

- * If M is this matrix and S the shadow matrix, - * then the new matrix will be M * S. So when transforming a - * vector v with the new matrix by using M * S * v, the - * shadow projection will be applied first! - * - * @param lightX - * the x-component of the light vector - * @param lightY - * the y-component of the light vector - * @param lightZ - * the z-component of the light vector - * @param lightW - * the w-component of the light vector - * @param planeTransform - * the transformation to transform the implied plane y = 0 before applying the projection - * @param dest - * will hold the result - * @return dest - */ - Matrix4f shadow(float lightX, float lightY, float lightZ, float lightW, Matrix4fc planeTransform, Matrix4f dest); - - /** - * Apply a picking transformation to this matrix using the given window coordinates (x, y) as the pick center - * and the given (width, height) as the size of the picking region in window coordinates, and store the result - * in dest. - * - * @param x - * the x coordinate of the picking region center in window coordinates - * @param y - * the y coordinate of the picking region center in window coordinates - * @param width - * the width of the picking region in window coordinates - * @param height - * the height of the picking region in window coordinates - * @param viewport - * the viewport described by [x, y, width, height] - * @param dest - * the destination matrix, which will hold the result - * @return dest - */ - Matrix4f pick(float x, float y, float width, float height, int[] viewport, Matrix4f dest); - - /** - * Determine whether this matrix describes an affine transformation. This is the case iff its last row is equal to (0, 0, 0, 1). - * - * @return true iff this matrix is affine; false otherwise - */ - boolean isAffine(); - - /** - * Apply an arcball view transformation to this matrix with the given radius and center (centerX, centerY, centerZ) - * position of the arcball and the specified X and Y rotation angles, and store the result in dest. - *

- * This method is equivalent to calling: translate(0, 0, -radius, dest).rotateX(angleX).rotateY(angleY).translate(-centerX, -centerY, -centerZ) - * - * @param radius - * the arcball radius - * @param centerX - * the x coordinate of the center position of the arcball - * @param centerY - * the y coordinate of the center position of the arcball - * @param centerZ - * the z coordinate of the center position of the arcball - * @param angleX - * the rotation angle around the X axis in radians - * @param angleY - * the rotation angle around the Y axis in radians - * @param dest - * will hold the result - * @return dest - */ - Matrix4f arcball(float radius, float centerX, float centerY, float centerZ, float angleX, float angleY, Matrix4f dest); - - /** - * Apply an arcball view transformation to this matrix with the given radius and center - * position of the arcball and the specified X and Y rotation angles, and store the result in dest. - *

- * This method is equivalent to calling: translate(0, 0, -radius).rotateX(angleX).rotateY(angleY).translate(-center.x, -center.y, -center.z) - * - * @param radius - * the arcball radius - * @param center - * the center position of the arcball - * @param angleX - * the rotation angle around the X axis in radians - * @param angleY - * the rotation angle around the Y axis in radians - * @param dest - * will hold the result - * @return dest - */ - Matrix4f arcball(float radius, Vector3fc center, float angleX, float angleY, Matrix4f dest); - - /** - * Compute the axis-aligned bounding box of the frustum described by this matrix and store the minimum corner - * coordinates in the given min and the maximum corner coordinates in the given max vector. - *

- * The matrix this is assumed to be the {@link #invert(Matrix4f) inverse} of the origial view-projection matrix - * for which to compute the axis-aligned bounding box in world-space. - *

- * The axis-aligned bounding box of the unit frustum is (-1, -1, -1), (1, 1, 1). - * - * @param min - * will hold the minimum corner coordinates of the axis-aligned bounding box - * @param max - * will hold the maximum corner coordinates of the axis-aligned bounding box - * @return this - */ - Matrix4f frustumAabb(Vector3f min, Vector3f max); - - /** - * Compute the range matrix for the Projected Grid transformation as described in chapter "2.4.2 Creating the range conversion matrix" - * of the paper Real-time water rendering - Introducing the projected grid concept - * based on the inverse of the view-projection matrix which is assumed to be this, and store that range matrix into dest. - *

- * If the projected grid will not be visible then this method returns null. - *

- * This method uses the y = 0 plane for the projection. - * - * @param projector - * the projector view-projection transformation - * @param sLower - * the lower (smallest) Y-coordinate which any transformed vertex might have while still being visible on the projected grid - * @param sUpper - * the upper (highest) Y-coordinate which any transformed vertex might have while still being visible on the projected grid - * @param dest - * will hold the resulting range matrix - * @return the computed range matrix; or null if the projected grid will not be visible - */ - Matrix4f projectedGridRange(Matrix4fc projector, float sLower, float sUpper, Matrix4f dest); - - /** - * Change the near and far clip plane distances of this perspective frustum transformation matrix - * and store the result in dest. - *

- * This method only works if this is a perspective projection frustum transformation, for example obtained - * via {@link #perspective(float, float, float, float, Matrix4f) perspective()} or {@link #frustum(float, float, float, float, float, float, Matrix4f) frustum()}. - * - * @see #perspective(float, float, float, float, Matrix4f) - * @see #frustum(float, float, float, float, float, float, Matrix4f) - * - * @param near - * the new near clip plane distance - * @param far - * the new far clip plane distance - * @param dest - * will hold the resulting matrix - * @return dest - */ - Matrix4f perspectiveFrustumSlice(float near, float far, Matrix4f dest); - - /** - * Build an ortographic projection transformation that fits the view-projection transformation represented by this - * into the given affine view transformation. - *

- * The transformation represented by this must be given as the {@link #invert(Matrix4f) inverse} of a typical combined camera view-projection - * transformation, whose projection can be either orthographic or perspective. - *

- * The view must be an {@link #isAffine() affine} transformation which in the application of Cascaded Shadow Maps is usually the light view transformation. - * It be obtained via any affine transformation or for example via {@link #lookAt(float, float, float, float, float, float, float, float, float, Matrix4f) lookAt()}. - *

- * Reference: OpenGL SDK - Cascaded Shadow Maps - * - * @param view - * the view transformation to build a corresponding orthographic projection to fit the frustum of this - * @param dest - * will hold the crop projection transformation - * @return dest - */ - Matrix4f orthoCrop(Matrix4fc view, Matrix4f dest); - - /** - * Transform the axis-aligned box given as the minimum corner (minX, minY, minZ) and maximum corner (maxX, maxY, maxZ) - * by this {@link #isAffine() affine} matrix and compute the axis-aligned box of the result whose minimum corner is stored in outMin - * and maximum corner stored in outMax. - *

- * Reference: http://dev.theomader.com - * - * @param minX - * the x coordinate of the minimum corner of the axis-aligned box - * @param minY - * the y coordinate of the minimum corner of the axis-aligned box - * @param minZ - * the z coordinate of the minimum corner of the axis-aligned box - * @param maxX - * the x coordinate of the maximum corner of the axis-aligned box - * @param maxY - * the y coordinate of the maximum corner of the axis-aligned box - * @param maxZ - * the y coordinate of the maximum corner of the axis-aligned box - * @param outMin - * will hold the minimum corner of the resulting axis-aligned box - * @param outMax - * will hold the maximum corner of the resulting axis-aligned box - * @return this - */ - Matrix4f transformAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, Vector3f outMin, Vector3f outMax); - - /** - * Transform the axis-aligned box given as the minimum corner min and maximum corner max - * by this {@link #isAffine() affine} matrix and compute the axis-aligned box of the result whose minimum corner is stored in outMin - * and maximum corner stored in outMax. - * - * @param min - * the minimum corner of the axis-aligned box - * @param max - * the maximum corner of the axis-aligned box - * @param outMin - * will hold the minimum corner of the resulting axis-aligned box - * @param outMax - * will hold the maximum corner of the resulting axis-aligned box - * @return this - */ - Matrix4f transformAab(Vector3fc min, Vector3fc max, Vector3f outMin, Vector3f outMax); - - /** - * Linearly interpolate this and other using the given interpolation factor t - * and store the result in dest. - *

- * If t is 0.0 then the result is this. If the interpolation factor is 1.0 - * then the result is other. - * - * @param other - * the other matrix - * @param t - * the interpolation factor between 0.0 and 1.0 - * @param dest - * will hold the result - * @return dest - */ - Matrix4f lerp(Matrix4fc other, float t, Matrix4f dest); - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with dir - * and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * This method is equivalent to calling: mulAffine(new Matrix4f().lookAt(new Vector3f(), new Vector3f(dir).negate(), up).invertAffine(), dest) - * - * @see #rotateTowards(float, float, float, float, float, float, Matrix4f) - * - * @param dir - * the direction to rotate towards - * @param up - * the up vector - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateTowards(Vector3fc dir, Vector3fc up, Matrix4f dest); - - /** - * Apply a model transformation to this matrix for a right-handed coordinate system, - * that aligns the local +Z axis with (dirX, dirY, dirZ) - * and store the result in dest. - *

- * If M is this matrix and L the lookat matrix, - * then the new matrix will be M * L. So when transforming a - * vector v with the new matrix by using M * L * v, - * the lookat transformation will be applied first! - *

- * This method is equivalent to calling: mulAffine(new Matrix4f().lookAt(0, 0, 0, -dirX, -dirY, -dirZ, upX, upY, upZ).invertAffine(), dest) - * - * @see #rotateTowards(Vector3fc, Vector3fc, Matrix4f) - * - * @param dirX - * the x-coordinate of the direction to rotate towards - * @param dirY - * the y-coordinate of the direction to rotate towards - * @param dirZ - * the z-coordinate of the direction to rotate towards - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - Matrix4f rotateTowards(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Matrix4f dest); - - /** - * Extract the Euler angles from the rotation represented by the upper left 3x3 submatrix of this - * and store the extracted Euler angles in dest. - *

- * This method assumes that the upper left of this only represents a rotation without scaling. - *

- * The Euler angles are always returned as the angle around X in the {@link Vector3f#x} field, the angle around Y in the {@link Vector3f#y} - * field and the angle around Z in the {@link Vector3f#z} field of the supplied {@link Vector3f} instance. - *

- * Note that the returned Euler angles must be applied in the order X * Y * Z to obtain the identical matrix. - * This means that calling {@link Matrix4fc#rotateXYZ(float, float, float, Matrix4f)} using the obtained Euler angles will yield - * the same rotation as the original matrix from which the Euler angles were obtained, so in the below code the matrix - * m2 should be identical to m (disregarding possible floating-point inaccuracies). - *

-     * Matrix4f m = ...; // <- matrix only representing rotation
-     * Matrix4f n = new Matrix4f();
-     * n.rotateXYZ(m.getEulerAnglesXYZ(new Vector3f()));
-     * 
- *

- * Reference: http://en.wikipedia.org/ - * - * @param dest - * will hold the extracted Euler angles - * @return dest - */ - Vector3f getEulerAnglesXYZ(Vector3f dest); - - /** - * Extract the Euler angles from the rotation represented by the upper left 3x3 submatrix of this - * and store the extracted Euler angles in dest. - *

- * This method assumes that the upper left of this only represents a rotation without scaling. - *

- * The Euler angles are always returned as the angle around X in the {@link Vector3f#x} field, the angle around Y in the {@link Vector3f#y} - * field and the angle around Z in the {@link Vector3f#z} field of the supplied {@link Vector3f} instance. - *

- * Note that the returned Euler angles must be applied in the order Z * Y * X to obtain the identical matrix. - * This means that calling {@link Matrix4fc#rotateZYX(float, float, float, Matrix4f)} using the obtained Euler angles will yield - * the same rotation as the original matrix from which the Euler angles were obtained, so in the below code the matrix - * m2 should be identical to m (disregarding possible floating-point inaccuracies). - *

-     * Matrix4f m = ...; // <- matrix only representing rotation
-     * Matrix4f n = new Matrix4f();
-     * n.rotateZYX(m.getEulerAnglesZYX(new Vector3f()));
-     * 
- *

- * Reference: http://nghiaho.com/ - * - * @param dest - * will hold the extracted Euler angles - * @return dest - */ - Vector3f getEulerAnglesZYX(Vector3f dest); - - /** - * Test whether the given point (x, y, z) is within the frustum defined by this matrix. - *

- * This method assumes this matrix to be a transformation from any arbitrary coordinate system/space M - * into standard OpenGL clip space and tests whether the given point with the coordinates (x, y, z) given - * in space M is within the clip space. - *

- * When testing multiple points using the same transformation matrix, {@link FrustumIntersection} should be used instead. - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @param x - * the x-coordinate of the point - * @param y - * the y-coordinate of the point - * @param z - * the z-coordinate of the point - * @return true if the given point is inside the frustum; false otherwise - */ - boolean testPoint(float x, float y, float z); - - /** - * Test whether the given sphere is partly or completely within or outside of the frustum defined by this matrix. - *

- * This method assumes this matrix to be a transformation from any arbitrary coordinate system/space M - * into standard OpenGL clip space and tests whether the given sphere with the coordinates (x, y, z) given - * in space M is within the clip space. - *

- * When testing multiple spheres using the same transformation matrix, or more sophisticated/optimized intersection algorithms are required, - * {@link FrustumIntersection} should be used instead. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns true for spheres that are actually not visible. - * See iquilezles.org for an examination of this problem. - *

- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @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 true if the given sphere is partly or completely inside the frustum; false otherwise - */ - boolean testSphere(float x, float y, float z, float r); - - /** - * Test whether the given axis-aligned box is partly or completely within or outside of the frustum defined by this matrix. - * The box is specified via its min and max corner coordinates. - *

- * This method assumes this matrix to be a transformation from any arbitrary coordinate system/space M - * into standard OpenGL clip space and tests whether the given axis-aligned box with its minimum corner coordinates (minX, minY, minZ) - * and maximum corner coordinates (maxX, maxY, maxZ) given in space M is within the clip space. - *

- * When testing multiple axis-aligned boxes using the same transformation matrix, or more sophisticated/optimized intersection algorithms are required, - * {@link FrustumIntersection} should be used instead. - *

- * The algorithm implemented by this method is conservative. This means that in certain circumstances a false positive - * can occur, when the method returns -1 for boxes that are actually not visible/do not intersect the frustum. - * See iquilezles.org for an examination of this problem. - *

- * Reference: Efficient View Frustum Culling - *
- * Reference: - * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * - * @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 true if the axis-aligned box is completely or partly inside of the frustum; false otherwise - */ - boolean testAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ); - - /** - * Apply an oblique projection transformation to this matrix with the given values for a and - * b and store the result in dest. - *

- * If M is this matrix and O the oblique transformation matrix, - * then the new matrix will be M * O. So when transforming a - * vector v with the new matrix by using M * O * v, the - * oblique transformation will be applied first! - *

- * The oblique transformation is defined as: - *

-     * x' = x + a*z
-     * y' = y + a*z
-     * z' = z
-     * 
- * or in matrix form: - *
-     * 1 0 a 0
-     * 0 1 b 0
-     * 0 0 1 0
-     * 0 0 0 1
-     * 
- * - * @param a - * the value for the z factor that applies to x - * @param b - * the value for the z factor that applies to y - * @param dest - * will hold the result - * @return dest - */ - Matrix4f obliqueZ(float a, float b, Matrix4f dest); - - /** - * Apply a transformation to this matrix to ensure that the local Y axis (as obtained by {@link #positiveY(Vector3f)}) - * will be coplanar to the plane spanned by the local Z axis (as obtained by {@link #positiveZ(Vector3f)}) and the - * given vector up, and store the result in dest. - *

- * This effectively ensures that the resulting matrix will be equal to the one obtained from calling - * {@link Matrix4f#setLookAt(Vector3fc, Vector3fc, Vector3fc)} with the current - * local origin of this matrix (as obtained by {@link #originAffine(Vector3f)}), the sum of this position and the - * negated local Z axis as well as the given vector up. - *

- * This method must only be called on {@link #isAffine()} matrices. - * - * @param up - * the up vector - * @param dest - * will hold the result - * @return this - */ - Matrix4f withLookAtUp(Vector3fc up, Matrix4f dest); - - /** - * Apply a transformation to this matrix to ensure that the local Y axis (as obtained by {@link #positiveY(Vector3f)}) - * will be coplanar to the plane spanned by the local Z axis (as obtained by {@link #positiveZ(Vector3f)}) and the - * given vector (upX, upY, upZ), and store the result in dest. - *

- * This effectively ensures that the resulting matrix will be equal to the one obtained from calling - * {@link Matrix4f#setLookAt(float, float, float, float, float, float, float, float, float)} called with the current - * local origin of this matrix (as obtained by {@link #originAffine(Vector3f)}), the sum of this position and the - * negated local Z axis as well as the given vector (upX, upY, upZ). - *

- * This method must only be called on {@link #isAffine()} matrices. - * - * @param upX - * the x coordinate of the up vector - * @param upY - * the y coordinate of the up vector - * @param upZ - * the z coordinate of the up vector - * @param dest - * will hold the result - * @return this - */ - Matrix4f withLookAtUp(float upX, float upY, float upZ, Matrix4f dest); - - /** - * Multiply this by the matrix - *

-     * 1 0 0 0
-     * 0 0 1 0
-     * 0 1 0 0
-     * 0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapXZY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 1 0  0 0
-     * 0 0 -1 0
-     * 0 1  0 0
-     * 0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapXZnY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 1  0  0 0
-     * 0 -1  0 0
-     * 0  0 -1 0
-     * 0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapXnYnZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 1  0 0 0
-     * 0  0 1 0
-     * 0 -1 0 0
-     * 0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapXnZY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 1  0  0 0
-     * 0  0 -1 0
-     * 0 -1  0 0
-     * 0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapXnZnY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 1 0 0
-     * 1 0 0 0
-     * 0 0 1 0
-     * 0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapYXZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 1  0 0
-     * 1 0  0 0
-     * 0 0 -1 0
-     * 0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapYXnZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 0 1 0
-     * 1 0 0 0
-     * 0 1 0 0
-     * 0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapYZX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 0 -1 0
-     * 1 0  0 0
-     * 0 1  0 0
-     * 0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapYZnX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 -1 0 0
-     * 1  0 0 0
-     * 0  0 1 0
-     * 0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapYnXZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 -1  0 0
-     * 1  0  0 0
-     * 0  0 -1 0
-     * 0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapYnXnZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0  0 1 0
-     * 1  0 0 0
-     * 0 -1 0 0
-     * 0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapYnZX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0  0 -1 0
-     * 1  0  0 0
-     * 0 -1  0 0
-     * 0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapYnZnX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 1 0 0
-     * 0 0 1 0
-     * 1 0 0 0
-     * 0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapZXY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 1  0 0
-     * 0 0 -1 0
-     * 1 0  0 0
-     * 0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapZXnY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 0 1 0
-     * 0 1 0 0
-     * 1 0 0 0
-     * 0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapZYX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 0 -1 0
-     * 0 1  0 0
-     * 1 0  0 0
-     * 0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapZYnX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 -1 0 0
-     * 0  0 1 0
-     * 1  0 0 0
-     * 0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapZnXY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0 -1  0 0
-     * 0  0 -1 0
-     * 1  0  0 0
-     * 0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapZnXnY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0  0 1 0
-     * 0 -1 0 0
-     * 1  0 0 0
-     * 0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapZnYX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * 0  0 -1 0
-     * 0 -1  0 0
-     * 1  0  0 0
-     * 0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapZnYnX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * -1 0  0 0
-     *  0 1  0 0
-     *  0 0 -1 0
-     *  0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnXYnZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * -1 0 0 0
-     *  0 0 1 0
-     *  0 1 0 0
-     *  0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnXZY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * -1 0  0 0
-     *  0 0 -1 0
-     *  0 1  0 0
-     *  0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnXZnY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * -1  0 0 0
-     *  0 -1 0 0
-     *  0  0 1 0
-     *  0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnXnYZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * -1  0  0 0
-     *  0 -1  0 0
-     *  0  0 -1 0
-     *  0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnXnYnZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * -1  0 0 0
-     *  0  0 1 0
-     *  0 -1 0 0
-     *  0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnXnZY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     * -1  0  0 0
-     *  0  0 -1 0
-     *  0 -1  0 0
-     *  0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnXnZnY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 1 0 0
-     * -1 0 0 0
-     *  0 0 1 0
-     *  0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnYXZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 1  0 0
-     * -1 0  0 0
-     *  0 0 -1 0
-     *  0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnYXnZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 0 1 0
-     * -1 0 0 0
-     *  0 1 0 0
-     *  0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnYZX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 0 -1 0
-     * -1 0  0 0
-     *  0 1  0 0
-     *  0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnYZnX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 -1 0 0
-     * -1  0 0 0
-     *  0  0 1 0
-     *  0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnYnXZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 -1  0 0
-     * -1  0  0 0
-     *  0  0 -1 0
-     *  0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnYnXnZ(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0  0 1 0
-     * -1  0 0 0
-     *  0 -1 0 0
-     *  0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnYnZX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0  0 -1 0
-     * -1  0  0 0
-     *  0 -1  0 0
-     *  0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnYnZnX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 1 0 0
-     *  0 0 1 0
-     * -1 0 0 0
-     *  0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnZXY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 1  0 0
-     *  0 0 -1 0
-     * -1 0  0 0
-     *  0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnZXnY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 0 1 0
-     *  0 1 0 0
-     * -1 0 0 0
-     *  0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnZYX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 0 -1 0
-     *  0 1  0 0
-     * -1 0  0 0
-     *  0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnZYnX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 -1 0 0
-     *  0  0 1 0
-     * -1  0 0 0
-     *  0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnZnXY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0 -1  0 0
-     *  0  0 -1 0
-     * -1  0  0 0
-     *  0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnZnXnY(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0  0 1 0
-     *  0 -1 0 0
-     * -1  0 0 0
-     *  0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnZnYX(Matrix4f dest); - /** - * Multiply this by the matrix - *
-     *  0  0 -1 0
-     *  0 -1  0 0
-     * -1  0  0 0
-     *  0  0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f mapnZnYnX(Matrix4f dest); - - /** - * Multiply this by the matrix - *
-     * -1 0 0 0
-     *  0 1 0 0
-     *  0 0 1 0
-     *  0 0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f negateX(Matrix4f dest); - - /** - * Multiply this by the matrix - *
-     * 1  0 0 0
-     * 0 -1 0 0
-     * 0  0 1 0
-     * 0  0 0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f negateY(Matrix4f dest); - - /** - * Multiply this by the matrix - *
-     * 1 0  0 0
-     * 0 1  0 0
-     * 0 0 -1 0
-     * 0 0  0 1
-     * 
- * and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Matrix4f negateZ(Matrix4f dest); - - /** - * Compare the matrix elements of this matrix with the given matrix using the given delta - * and return whether all of them are equal within a maximum difference of delta. - *

- * Please note that this method is not used by any data structure such as {@link ArrayList} {@link HashSet} or {@link HashMap} - * and their operations, such as {@link ArrayList#contains(Object)} or {@link HashSet#remove(Object)}, since those - * data structures only use the {@link Object#equals(Object)} and {@link Object#hashCode()} methods. - * - * @param m - * the other matrix - * @param delta - * the allowed maximum difference - * @return true whether all of the matrix elements are equal; false otherwise - */ - boolean equals(Matrix4fc m, float delta); - - /** - * Determine whether all matrix elements are finite floating-point values, that - * is, they are not {@link Float#isNaN() NaN} and not - * {@link Float#isInfinite() infinity}. - * - * @return {@code true} if all components are finite floating-point values; - * {@code false} otherwise - */ - boolean isFinite(); - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/MemUtil.java b/src/main/java/com/jozufozu/flywheel/util/joml/MemUtil.java deleted file mode 100644 index 3f88b030f..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/MemUtil.java +++ /dev/null @@ -1,2034 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2016-2021 Kai Burjack - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.jozufozu.flywheel.util.joml; - -import java.lang.reflect.Field; -import java.nio.*; - -/** - * Helper class to do efficient memory operations on all JOML objects, NIO buffers and primitive arrays. - * This class is used internally throughout JOML, is undocumented and is subject to change. - * Use with extreme caution! - * - * @author The LWJGL authors - * @author Kai Burjack - */ -abstract class MemUtil { - public static final MemUtil INSTANCE = createInstance(); - private static MemUtil createInstance() { - MemUtil accessor; - try { - if (Options.NO_UNSAFE && Options.FORCE_UNSAFE) - throw new ConfigurationException("Cannot enable both -Djoml.nounsafe and -Djoml.forceUnsafe", null); - else if (Options.NO_UNSAFE) - accessor = new MemUtilNIO(); - else - accessor = new MemUtilUnsafe(); - } catch (Throwable e) { - if (Options.FORCE_UNSAFE) - throw new ConfigurationException("Unsafe is not supported but its use was forced via -Djoml.forceUnsafe", e); - accessor = new MemUtilNIO(); - } - return accessor; - } - - public abstract void put(Matrix4f m, int offset, FloatBuffer dest); - public abstract void put(Matrix4f m, int offset, ByteBuffer dest); - public abstract void put4x3(Matrix4f m, int offset, FloatBuffer dest); - public abstract void put4x3(Matrix4f m, int offset, ByteBuffer dest); - public abstract void put3x4(Matrix4f m, int offset, FloatBuffer dest); - public abstract void put3x4(Matrix4f m, int offset, ByteBuffer dest); - public abstract void put3x4(Matrix3f m, int offset, FloatBuffer dest); - public abstract void put3x4(Matrix3f m, int offset, ByteBuffer dest); - public abstract void putTransposed(Matrix4f m, int offset, FloatBuffer dest); - public abstract void putTransposed(Matrix4f m, int offset, ByteBuffer dest); - public abstract void put4x3Transposed(Matrix4f m, int offset, FloatBuffer dest); - public abstract void put4x3Transposed(Matrix4f m, int offset, ByteBuffer dest); - public abstract void putTransposed(Matrix3f m, int offset, FloatBuffer dest); - public abstract void putTransposed(Matrix3f m, int offset, ByteBuffer dest); - public abstract void put(Matrix3f m, int offset, FloatBuffer dest); - public abstract void put(Matrix3f m, int offset, ByteBuffer dest); - public abstract void put(Vector4f src, int offset, FloatBuffer dest); - public abstract void put(Vector4f src, int offset, ByteBuffer dest); - public abstract void put(Vector3f src, int offset, FloatBuffer dest); - public abstract void put(Vector3f src, int offset, ByteBuffer dest); - public abstract void get(Matrix4f m, int offset, FloatBuffer src); - public abstract void get(Matrix4f m, int offset, ByteBuffer src); - public abstract void getTransposed(Matrix4f m, int offset, FloatBuffer src); - public abstract void getTransposed(Matrix4f m, int offset, ByteBuffer src); - public abstract void get(Matrix3f m, int offset, FloatBuffer src); - public abstract void get(Matrix3f m, int offset, ByteBuffer src); - public abstract void get(Vector4f dst, int offset, FloatBuffer src); - public abstract void get(Vector4f dst, int offset, ByteBuffer src); - public abstract void get(Vector3f dst, int offset, FloatBuffer src); - public abstract void get(Vector3f dst, int offset, ByteBuffer src); - public abstract void putMatrix3f(Quaternionf q, int position, ByteBuffer dest); - public abstract void putMatrix3f(Quaternionf q, int position, FloatBuffer dest); - public abstract void putMatrix4f(Quaternionf q, int position, ByteBuffer dest); - public abstract void putMatrix4f(Quaternionf q, int position, FloatBuffer dest); - public abstract void putMatrix4x3f(Quaternionf q, int position, ByteBuffer dest); - public abstract void putMatrix4x3f(Quaternionf q, int position, FloatBuffer dest); - - public abstract float get(Matrix4f m, int column, int row); - public abstract Matrix4f set(Matrix4f m, int column, int row, float v); - public abstract float get(Matrix3f m, int column, int row); - public abstract Matrix3f set(Matrix3f m, int column, int row, float v); - public abstract Vector4f getColumn(Matrix4f m, int column, Vector4f dest); - public abstract Matrix4f setColumn(Vector4f v, int column, Matrix4f dest); - public abstract Matrix4f setColumn(Vector4fc v, int column, Matrix4f dest); - public abstract void copy(Matrix4f src, Matrix4f dest); - public abstract void copy(Matrix3f src, Matrix3f dest); - public abstract void copy(Matrix3f src, Matrix4f dest); - public abstract void copy(Matrix4f src, Matrix3f dest); - public abstract void copy3x3(Matrix4f src, Matrix4f dest); - public abstract void copy3x3(Matrix3f src, Matrix4f dest); - public abstract void copy4x3(Matrix4f src, Matrix4f dest); - public abstract void copy(float[] arr, int off, Matrix4f dest); - public abstract void copyTransposed(float[] arr, int off, Matrix4f dest); - public abstract void copy(float[] arr, int off, Matrix3f dest); - public abstract void copy(Matrix4f src, float[] dest, int off); - public abstract void copy(Matrix3f src, float[] dest, int off); - - public abstract void identity(Matrix4f dest); - - public abstract void identity(Matrix3f dest); - - public abstract void swap(Matrix4f m1, Matrix4f m2); - - public abstract void swap(Matrix3f m1, Matrix3f m2); - - public abstract void zero(Matrix4f dest); - - public abstract void zero(Matrix3f dest); - - public static class MemUtilNIO extends MemUtil { - public void put0(Matrix4f m, FloatBuffer dest) { - dest.put(0, m.m00()) - .put(1, m.m01()) - .put(2, m.m02()) - .put(3, m.m03()) - .put(4, m.m10()) - .put(5, m.m11()) - .put(6, m.m12()) - .put(7, m.m13()) - .put(8, m.m20()) - .put(9, m.m21()) - .put(10, m.m22()) - .put(11, m.m23()) - .put(12, m.m30()) - .put(13, m.m31()) - .put(14, m.m32()) - .put(15, m.m33()); - } - public void putN(Matrix4f m, int offset, FloatBuffer dest) { - dest.put(offset, m.m00()) - .put(offset+1, m.m01()) - .put(offset+2, m.m02()) - .put(offset+3, m.m03()) - .put(offset+4, m.m10()) - .put(offset+5, m.m11()) - .put(offset+6, m.m12()) - .put(offset+7, m.m13()) - .put(offset+8, m.m20()) - .put(offset+9, m.m21()) - .put(offset+10, m.m22()) - .put(offset+11, m.m23()) - .put(offset+12, m.m30()) - .put(offset+13, m.m31()) - .put(offset+14, m.m32()) - .put(offset+15, m.m33()); - } - public void put(Matrix4f m, int offset, FloatBuffer dest) { - if (offset == 0) - put0(m, dest); - else - putN(m, offset, dest); - } - - public void put0(Matrix4f m, ByteBuffer dest) { - dest.putFloat(0, m.m00()) - .putFloat(4, m.m01()) - .putFloat(8, m.m02()) - .putFloat(12, m.m03()) - .putFloat(16, m.m10()) - .putFloat(20, m.m11()) - .putFloat(24, m.m12()) - .putFloat(28, m.m13()) - .putFloat(32, m.m20()) - .putFloat(36, m.m21()) - .putFloat(40, m.m22()) - .putFloat(44, m.m23()) - .putFloat(48, m.m30()) - .putFloat(52, m.m31()) - .putFloat(56, m.m32()) - .putFloat(60, m.m33()); - } - private void putN(Matrix4f m, int offset, ByteBuffer dest) { - dest.putFloat(offset, m.m00()) - .putFloat(offset+4, m.m01()) - .putFloat(offset+8, m.m02()) - .putFloat(offset+12, m.m03()) - .putFloat(offset+16, m.m10()) - .putFloat(offset+20, m.m11()) - .putFloat(offset+24, m.m12()) - .putFloat(offset+28, m.m13()) - .putFloat(offset+32, m.m20()) - .putFloat(offset+36, m.m21()) - .putFloat(offset+40, m.m22()) - .putFloat(offset+44, m.m23()) - .putFloat(offset+48, m.m30()) - .putFloat(offset+52, m.m31()) - .putFloat(offset+56, m.m32()) - .putFloat(offset+60, m.m33()); - } - public void put(Matrix4f m, int offset, ByteBuffer dest) { - if (offset == 0) - put0(m, dest); - else - putN(m, offset, dest); - } - - public void put4x3_0(Matrix4f m, FloatBuffer dest) { - dest.put(0, m.m00()) - .put(1, m.m01()) - .put(2, m.m02()) - .put(3, m.m10()) - .put(4, m.m11()) - .put(5, m.m12()) - .put(6, m.m20()) - .put(7, m.m21()) - .put(8, m.m22()) - .put(9, m.m30()) - .put(10, m.m31()) - .put(11, m.m32()); - } - public void put4x3_N(Matrix4f m, int offset, FloatBuffer dest) { - dest.put(offset, m.m00()) - .put(offset+1, m.m01()) - .put(offset+2, m.m02()) - .put(offset+3, m.m10()) - .put(offset+4, m.m11()) - .put(offset+5, m.m12()) - .put(offset+6, m.m20()) - .put(offset+7, m.m21()) - .put(offset+8, m.m22()) - .put(offset+9, m.m30()) - .put(offset+10, m.m31()) - .put(offset+11, m.m32()); - } - public void put4x3(Matrix4f m, int offset, FloatBuffer dest) { - if (offset == 0) - put4x3_0(m, dest); - else - put4x3_N(m, offset, dest); - } - - public void put4x3_0(Matrix4f m, ByteBuffer dest) { - dest.putFloat(0, m.m00()) - .putFloat(4, m.m01()) - .putFloat(8, m.m02()) - .putFloat(12, m.m10()) - .putFloat(16, m.m11()) - .putFloat(20, m.m12()) - .putFloat(24, m.m20()) - .putFloat(28, m.m21()) - .putFloat(32, m.m22()) - .putFloat(36, m.m30()) - .putFloat(40, m.m31()) - .putFloat(44, m.m32()); - } - private void put4x3_N(Matrix4f m, int offset, ByteBuffer dest) { - dest.putFloat(offset, m.m00()) - .putFloat(offset+4, m.m01()) - .putFloat(offset+8, m.m02()) - .putFloat(offset+12, m.m10()) - .putFloat(offset+16, m.m11()) - .putFloat(offset+20, m.m12()) - .putFloat(offset+24, m.m20()) - .putFloat(offset+28, m.m21()) - .putFloat(offset+32, m.m22()) - .putFloat(offset+36, m.m30()) - .putFloat(offset+40, m.m31()) - .putFloat(offset+44, m.m32()); - } - public void put4x3(Matrix4f m, int offset, ByteBuffer dest) { - if (offset == 0) - put4x3_0(m, dest); - else - put4x3_N(m, offset, dest); - } - - public void put3x4_0(Matrix4f m, ByteBuffer dest) { - dest.putFloat(0, m.m00()) - .putFloat(4, m.m01()) - .putFloat(8, m.m02()) - .putFloat(12, m.m03()) - .putFloat(16, m.m10()) - .putFloat(20, m.m11()) - .putFloat(24, m.m12()) - .putFloat(28, m.m13()) - .putFloat(32, m.m20()) - .putFloat(36, m.m21()) - .putFloat(40, m.m22()) - .putFloat(44, m.m23()); - } - private void put3x4_N(Matrix4f m, int offset, ByteBuffer dest) { - dest.putFloat(offset, m.m00()) - .putFloat(offset+4, m.m01()) - .putFloat(offset+8, m.m02()) - .putFloat(offset+12, m.m03()) - .putFloat(offset+16, m.m10()) - .putFloat(offset+20, m.m11()) - .putFloat(offset+24, m.m12()) - .putFloat(offset+28, m.m13()) - .putFloat(offset+32, m.m20()) - .putFloat(offset+36, m.m21()) - .putFloat(offset+40, m.m22()) - .putFloat(offset+44, m.m23()); - } - public void put3x4(Matrix4f m, int offset, ByteBuffer dest) { - if (offset == 0) - put3x4_0(m, dest); - else - put3x4_N(m, offset, dest); - } - - public void put3x4_0(Matrix4f m, FloatBuffer dest) { - dest.put(0, m.m00()) - .put(1, m.m01()) - .put(2, m.m02()) - .put(3, m.m03()) - .put(4, m.m10()) - .put(5, m.m11()) - .put(6, m.m12()) - .put(7, m.m13()) - .put(8, m.m20()) - .put(9, m.m21()) - .put(10, m.m22()) - .put(11, m.m23()); - } - public void put3x4_N(Matrix4f m, int offset, FloatBuffer dest) { - dest.put(offset, m.m00()) - .put(offset+1, m.m01()) - .put(offset+2, m.m02()) - .put(offset+3, m.m03()) - .put(offset+4, m.m10()) - .put(offset+5, m.m11()) - .put(offset+6, m.m12()) - .put(offset+7, m.m13()) - .put(offset+8, m.m20()) - .put(offset+9, m.m21()) - .put(offset+10, m.m22()) - .put(offset+11, m.m23()); - } - public void put3x4(Matrix4f m, int offset, FloatBuffer dest) { - if (offset == 0) - put3x4_0(m, dest); - else - put3x4_N(m, offset, dest); - } - - private void putTransposedN(Matrix4f m, int offset, FloatBuffer dest) { - dest.put(offset, m.m00()) - .put(offset+1, m.m10()) - .put(offset+2, m.m20()) - .put(offset+3, m.m30()) - .put(offset+4, m.m01()) - .put(offset+5, m.m11()) - .put(offset+6, m.m21()) - .put(offset+7, m.m31()) - .put(offset+8, m.m02()) - .put(offset+9, m.m12()) - .put(offset+10, m.m22()) - .put(offset+11, m.m32()) - .put(offset+12, m.m03()) - .put(offset+13, m.m13()) - .put(offset+14, m.m23()) - .put(offset+15, m.m33()); - } - private void putTransposed0(Matrix4f m, FloatBuffer dest) { - dest.put(0, m.m00()) - .put(1, m.m10()) - .put(2, m.m20()) - .put(3, m.m30()) - .put(4, m.m01()) - .put(5, m.m11()) - .put(6, m.m21()) - .put(7, m.m31()) - .put(8, m.m02()) - .put(9, m.m12()) - .put(10, m.m22()) - .put(11, m.m32()) - .put(12, m.m03()) - .put(13, m.m13()) - .put(14, m.m23()) - .put(15, m.m33()); - } - public void putTransposed(Matrix4f m, int offset, FloatBuffer dest) { - if (offset == 0) - putTransposed0(m, dest); - else - putTransposedN(m, offset, dest); - } - - private void putTransposedN(Matrix4f m, int offset, ByteBuffer dest) { - dest.putFloat(offset, m.m00()) - .putFloat(offset+4, m.m10()) - .putFloat(offset+8, m.m20()) - .putFloat(offset+12, m.m30()) - .putFloat(offset+16, m.m01()) - .putFloat(offset+20, m.m11()) - .putFloat(offset+24, m.m21()) - .putFloat(offset+28, m.m31()) - .putFloat(offset+32, m.m02()) - .putFloat(offset+36, m.m12()) - .putFloat(offset+40, m.m22()) - .putFloat(offset+44, m.m32()) - .putFloat(offset+48, m.m03()) - .putFloat(offset+52, m.m13()) - .putFloat(offset+56, m.m23()) - .putFloat(offset+60, m.m33()); - } - private void putTransposed0(Matrix4f m, ByteBuffer dest) { - dest.putFloat(0, m.m00()) - .putFloat(4, m.m10()) - .putFloat(8, m.m20()) - .putFloat(12, m.m30()) - .putFloat(16, m.m01()) - .putFloat(20, m.m11()) - .putFloat(24, m.m21()) - .putFloat(28, m.m31()) - .putFloat(32, m.m02()) - .putFloat(36, m.m12()) - .putFloat(40, m.m22()) - .putFloat(44, m.m32()) - .putFloat(48, m.m03()) - .putFloat(52, m.m13()) - .putFloat(56, m.m23()) - .putFloat(60, m.m33()); - } - public void putTransposed(Matrix4f m, int offset, ByteBuffer dest) { - if (offset == 0) - putTransposed0(m, dest); - else - putTransposedN(m, offset, dest); - } - - public void put4x3Transposed(Matrix4f m, int offset, FloatBuffer dest) { - dest.put(offset, m.m00()) - .put(offset+1, m.m10()) - .put(offset+2, m.m20()) - .put(offset+3, m.m30()) - .put(offset+4, m.m01()) - .put(offset+5, m.m11()) - .put(offset+6, m.m21()) - .put(offset+7, m.m31()) - .put(offset+8, m.m02()) - .put(offset+9, m.m12()) - .put(offset+10, m.m22()) - .put(offset+11, m.m32()); - } - - public void put4x3Transposed(Matrix4f m, int offset, ByteBuffer dest) { - dest.putFloat(offset, m.m00()) - .putFloat(offset+4, m.m10()) - .putFloat(offset+8, m.m20()) - .putFloat(offset+12, m.m30()) - .putFloat(offset+16, m.m01()) - .putFloat(offset+20, m.m11()) - .putFloat(offset+24, m.m21()) - .putFloat(offset+28, m.m31()) - .putFloat(offset+32, m.m02()) - .putFloat(offset+36, m.m12()) - .putFloat(offset+40, m.m22()) - .putFloat(offset+44, m.m32()); - } - - public void putTransposed(Matrix3f m, int offset, FloatBuffer dest) { - dest.put(offset, m.m00()) - .put(offset+1, m.m10()) - .put(offset+2, m.m20()) - .put(offset+3, m.m01()) - .put(offset+4, m.m11()) - .put(offset+5, m.m21()) - .put(offset+6, m.m02()) - .put(offset+7, m.m12()) - .put(offset+8, m.m22()); - } - - public void putTransposed(Matrix3f m, int offset, ByteBuffer dest) { - dest.putFloat(offset, m.m00()) - .putFloat(offset+4, m.m10()) - .putFloat(offset+8, m.m20()) - .putFloat(offset+12, m.m01()) - .putFloat(offset+16, m.m11()) - .putFloat(offset+20, m.m21()) - .putFloat(offset+24, m.m02()) - .putFloat(offset+28, m.m12()) - .putFloat(offset+32, m.m22()); - } - - public void put0(Matrix3f m, FloatBuffer dest) { - dest.put(0, m.m00()) - .put(1, m.m01()) - .put(2, m.m02()) - .put(3, m.m10()) - .put(4, m.m11()) - .put(5, m.m12()) - .put(6, m.m20()) - .put(7, m.m21()) - .put(8, m.m22()); - } - public void putN(Matrix3f m, int offset, FloatBuffer dest) { - dest.put(offset, m.m00()) - .put(offset+1, m.m01()) - .put(offset+2, m.m02()) - .put(offset+3, m.m10()) - .put(offset+4, m.m11()) - .put(offset+5, m.m12()) - .put(offset+6, m.m20()) - .put(offset+7, m.m21()) - .put(offset+8, m.m22()); - } - public void put(Matrix3f m, int offset, FloatBuffer dest) { - if (offset == 0) - put0(m, dest); - else - putN(m, offset, dest); - } - - public void put0(Matrix3f m, ByteBuffer dest) { - dest.putFloat(0, m.m00()) - .putFloat(4, m.m01()) - .putFloat(8, m.m02()) - .putFloat(12, m.m10()) - .putFloat(16, m.m11()) - .putFloat(20, m.m12()) - .putFloat(24, m.m20()) - .putFloat(28, m.m21()) - .putFloat(32, m.m22()); - } - public void putN(Matrix3f m, int offset, ByteBuffer dest) { - dest.putFloat(offset, m.m00()) - .putFloat(offset+4, m.m01()) - .putFloat(offset+8, m.m02()) - .putFloat(offset+12, m.m10()) - .putFloat(offset+16, m.m11()) - .putFloat(offset+20, m.m12()) - .putFloat(offset+24, m.m20()) - .putFloat(offset+28, m.m21()) - .putFloat(offset+32, m.m22()); - } - public void put(Matrix3f m, int offset, ByteBuffer dest) { - if (offset == 0) - put0(m, dest); - else - putN(m, offset, dest); - } - - public void put3x4_0(Matrix3f m, ByteBuffer dest) { - dest.putFloat(0, m.m00()) - .putFloat(4, m.m01()) - .putFloat(8, m.m02()) - .putFloat(12, 0.0f) - .putFloat(16, m.m10()) - .putFloat(20, m.m11()) - .putFloat(24, m.m12()) - .putFloat(28, 0.0f) - .putFloat(32, m.m20()) - .putFloat(36, m.m21()) - .putFloat(40, m.m22()) - .putFloat(44, 0.0f); - } - private void put3x4_N(Matrix3f m, int offset, ByteBuffer dest) { - dest.putFloat(offset, m.m00()) - .putFloat(offset+4, m.m01()) - .putFloat(offset+8, m.m02()) - .putFloat(offset+12, 0.0f) - .putFloat(offset+16, m.m10()) - .putFloat(offset+20, m.m11()) - .putFloat(offset+24, m.m12()) - .putFloat(offset+28, 0.0f) - .putFloat(offset+32, m.m20()) - .putFloat(offset+36, m.m21()) - .putFloat(offset+40, m.m22()) - .putFloat(offset+44, 0.0f); - } - public void put3x4(Matrix3f m, int offset, ByteBuffer dest) { - if (offset == 0) - put3x4_0(m, dest); - else - put3x4_N(m, offset, dest); - } - - public void put3x4_0(Matrix3f m, FloatBuffer dest) { - dest.put(0, m.m00()) - .put(1, m.m01()) - .put(2, m.m02()) - .put(3, 0.0f) - .put(4, m.m10()) - .put(5, m.m11()) - .put(6, m.m12()) - .put(7, 0.0f) - .put(8, m.m20()) - .put(9, m.m21()) - .put(10, m.m22()) - .put(11, 0.0f); - } - public void put3x4_N(Matrix3f m, int offset, FloatBuffer dest) { - dest.put(offset, m.m00()) - .put(offset+1, m.m01()) - .put(offset+2, m.m02()) - .put(offset+3, 0.0f) - .put(offset+4, m.m10()) - .put(offset+5, m.m11()) - .put(offset+6, m.m12()) - .put(offset+7, 0.0f) - .put(offset+8, m.m20()) - .put(offset+9, m.m21()) - .put(offset+10, m.m22()) - .put(offset+11, 0.0f); - } - public void put3x4(Matrix3f m, int offset, FloatBuffer dest) { - if (offset == 0) - put3x4_0(m, dest); - else - put3x4_N(m, offset, dest); - } - - public void put(Vector4f src, int offset, FloatBuffer dest) { - dest.put(offset, src.x) - .put(offset+1, src.y) - .put(offset+2, src.z) - .put(offset+3, src.w); - } - - public void put(Vector4f src, int offset, ByteBuffer dest) { - dest.putFloat(offset, src.x) - .putFloat(offset+4, src.y) - .putFloat(offset+8, src.z) - .putFloat(offset+12, src.w); - } - - public void put(Vector3f src, int offset, FloatBuffer dest) { - dest.put(offset, src.x) - .put(offset+1, src.y) - .put(offset+2, src.z); - } - - public void put(Vector3f src, int offset, ByteBuffer dest) { - dest.putFloat(offset, src.x) - .putFloat(offset+4, src.y) - .putFloat(offset+8, src.z); - } - - public void get(Matrix4f m, int offset, FloatBuffer src) { - m._m00(src.get(offset)) - ._m01(src.get(offset+1)) - ._m02(src.get(offset+2)) - ._m03(src.get(offset+3)) - ._m10(src.get(offset+4)) - ._m11(src.get(offset+5)) - ._m12(src.get(offset+6)) - ._m13(src.get(offset+7)) - ._m20(src.get(offset+8)) - ._m21(src.get(offset+9)) - ._m22(src.get(offset+10)) - ._m23(src.get(offset+11)) - ._m30(src.get(offset+12)) - ._m31(src.get(offset+13)) - ._m32(src.get(offset+14)) - ._m33(src.get(offset+15)); - } - - public void get(Matrix4f m, int offset, ByteBuffer src) { - m._m00(src.getFloat(offset)) - ._m01(src.getFloat(offset+4)) - ._m02(src.getFloat(offset+8)) - ._m03(src.getFloat(offset+12)) - ._m10(src.getFloat(offset+16)) - ._m11(src.getFloat(offset+20)) - ._m12(src.getFloat(offset+24)) - ._m13(src.getFloat(offset+28)) - ._m20(src.getFloat(offset+32)) - ._m21(src.getFloat(offset+36)) - ._m22(src.getFloat(offset+40)) - ._m23(src.getFloat(offset+44)) - ._m30(src.getFloat(offset+48)) - ._m31(src.getFloat(offset+52)) - ._m32(src.getFloat(offset+56)) - ._m33(src.getFloat(offset+60)); - } - - public void getTransposed(Matrix4f m, int offset, FloatBuffer src) { - m._m00(src.get(offset)) - ._m10(src.get(offset+1)) - ._m20(src.get(offset+2)) - ._m30(src.get(offset+3)) - ._m01(src.get(offset+4)) - ._m11(src.get(offset+5)) - ._m21(src.get(offset+6)) - ._m31(src.get(offset+7)) - ._m02(src.get(offset+8)) - ._m12(src.get(offset+9)) - ._m22(src.get(offset+10)) - ._m32(src.get(offset+11)) - ._m03(src.get(offset+12)) - ._m13(src.get(offset+13)) - ._m23(src.get(offset+14)) - ._m33(src.get(offset+15)); - } - - public void getTransposed(Matrix4f m, int offset, ByteBuffer src) { - m._m00(src.getFloat(offset)) - ._m10(src.getFloat(offset+4)) - ._m20(src.getFloat(offset+8)) - ._m30(src.getFloat(offset+12)) - ._m01(src.getFloat(offset+16)) - ._m11(src.getFloat(offset+20)) - ._m21(src.getFloat(offset+24)) - ._m31(src.getFloat(offset+28)) - ._m02(src.getFloat(offset+32)) - ._m12(src.getFloat(offset+36)) - ._m22(src.getFloat(offset+40)) - ._m32(src.getFloat(offset+44)) - ._m03(src.getFloat(offset+48)) - ._m13(src.getFloat(offset+52)) - ._m23(src.getFloat(offset+56)) - ._m33(src.getFloat(offset+60)); - } - - public void get(Matrix3f m, int offset, FloatBuffer src) { - m._m00(src.get(offset)) - ._m01(src.get(offset+1)) - ._m02(src.get(offset+2)) - ._m10(src.get(offset+3)) - ._m11(src.get(offset+4)) - ._m12(src.get(offset+5)) - ._m20(src.get(offset+6)) - ._m21(src.get(offset+7)) - ._m22(src.get(offset+8)); - } - - public void get(Matrix3f m, int offset, ByteBuffer src) { - m._m00(src.getFloat(offset)) - ._m01(src.getFloat(offset+4)) - ._m02(src.getFloat(offset+8)) - ._m10(src.getFloat(offset+12)) - ._m11(src.getFloat(offset+16)) - ._m12(src.getFloat(offset+20)) - ._m20(src.getFloat(offset+24)) - ._m21(src.getFloat(offset+28)) - ._m22(src.getFloat(offset+32)); - } - - - public void get(Vector4f dst, int offset, FloatBuffer src) { - dst.x = src.get(offset); - dst.y = src.get(offset+1); - dst.z = src.get(offset+2); - dst.w = src.get(offset+3); - } - - public void get(Vector4f dst, int offset, ByteBuffer src) { - dst.x = src.getFloat(offset); - dst.y = src.getFloat(offset+4); - dst.z = src.getFloat(offset+8); - dst.w = src.getFloat(offset+12); - } - - public void get(Vector3f dst, int offset, FloatBuffer src) { - dst.x = src.get(offset); - dst.y = src.get(offset+1); - dst.z = src.get(offset+2); - } - - public void get(Vector3f dst, int offset, ByteBuffer src) { - dst.x = src.getFloat(offset); - dst.y = src.getFloat(offset+4); - dst.z = src.getFloat(offset+8); - } - - public float get(Matrix4f m, int column, int row) { - switch (column) { - case 0: - switch (row) { - case 0: - return m.m00(); - case 1: - return m.m01(); - case 2: - return m.m02(); - case 3: - return m.m03(); - default: - break; - } - break; - case 1: - switch (row) { - case 0: - return m.m10(); - case 1: - return m.m11(); - case 2: - return m.m12(); - case 3: - return m.m13(); - default: - break; - } - break; - case 2: - switch (row) { - case 0: - return m.m20(); - case 1: - return m.m21(); - case 2: - return m.m22(); - case 3: - return m.m23(); - default: - break; - } - break; - case 3: - switch (row) { - case 0: - return m.m30(); - case 1: - return m.m31(); - case 2: - return m.m32(); - case 3: - return m.m33(); - default: - break; - } - break; - default: - break; - } - throw new IllegalArgumentException(); - } - - public Matrix4f set(Matrix4f m, int column, int row, float value) { - switch (column) { - case 0: - switch (row) { - case 0: - return m.m00(value); - case 1: - return m.m01(value); - case 2: - return m.m02(value); - case 3: - return m.m03(value); - default: - break; - } - break; - case 1: - switch (row) { - case 0: - return m.m10(value); - case 1: - return m.m11(value); - case 2: - return m.m12(value); - case 3: - return m.m13(value); - default: - break; - } - break; - case 2: - switch (row) { - case 0: - return m.m20(value); - case 1: - return m.m21(value); - case 2: - return m.m22(value); - case 3: - return m.m23(value); - default: - break; - } - break; - case 3: - switch (row) { - case 0: - return m.m30(value); - case 1: - return m.m31(value); - case 2: - return m.m32(value); - case 3: - return m.m33(value); - default: - break; - } - break; - default: - break; - } - throw new IllegalArgumentException(); - } - - public float get(Matrix3f m, int column, int row) { - switch (column) { - case 0: - switch (row) { - case 0: - return m.m00; - case 1: - return m.m01; - case 2: - return m.m02; - default: - break; - } - break; - case 1: - switch (row) { - case 0: - return m.m10; - case 1: - return m.m11; - case 2: - return m.m12; - default: - break; - } - break; - case 2: - switch (row) { - case 0: - return m.m20; - case 1: - return m.m21; - case 2: - return m.m22; - default: - break; - } - break; - default: - break; - } - throw new IllegalArgumentException(); - } - - public Matrix3f set(Matrix3f m, int column, int row, float value) { - switch (column) { - case 0: - switch (row) { - case 0: - return m.m00(value); - case 1: - return m.m01(value); - case 2: - return m.m02(value); - default: - break; - } - break; - case 1: - switch (row) { - case 0: - return m.m10(value); - case 1: - return m.m11(value); - case 2: - return m.m12(value); - default: - break; - } - break; - case 2: - switch (row) { - case 0: - return m.m20(value); - case 1: - return m.m21(value); - case 2: - return m.m22(value); - default: - break; - } - break; - default: - break; - } - throw new IllegalArgumentException(); - } - - public Vector4f getColumn(Matrix4f m, int column, Vector4f dest) { - switch (column) { - case 0: - return dest.set(m.m00(), m.m01(), m.m02(), m.m03()); - case 1: - return dest.set(m.m10(), m.m11(), m.m12(), m.m13()); - case 2: - return dest.set(m.m20(), m.m21(), m.m22(), m.m23()); - case 3: - return dest.set(m.m30(), m.m31(), m.m32(), m.m33()); - default: - throw new IndexOutOfBoundsException(); - } - } - - public Matrix4f setColumn(Vector4f v, int column, Matrix4f dest) { - switch (column) { - case 0: - return dest._m00(v.x)._m01(v.y)._m02(v.z)._m03(v.w); - case 1: - return dest._m10(v.x)._m11(v.y)._m12(v.z)._m13(v.w); - case 2: - return dest._m20(v.x)._m21(v.y)._m22(v.z)._m23(v.w); - case 3: - return dest._m30(v.x)._m31(v.y)._m32(v.z)._m33(v.w); - default: - throw new IndexOutOfBoundsException(); - } - } - - public Matrix4f setColumn(Vector4fc v, int column, Matrix4f dest) { - switch (column) { - case 0: - return dest._m00(v.x())._m01(v.y())._m02(v.z())._m03(v.w()); - case 1: - return dest._m10(v.x())._m11(v.y())._m12(v.z())._m13(v.w()); - case 2: - return dest._m20(v.x())._m21(v.y())._m22(v.z())._m23(v.w()); - case 3: - return dest._m30(v.x())._m31(v.y())._m32(v.z())._m33(v.w()); - default: - throw new IndexOutOfBoundsException(); - } - } - - public void copy(Matrix4f src, Matrix4f dest) { - dest._m00(src.m00()). - _m01(src.m01()). - _m02(src.m02()). - _m03(src.m03()). - _m10(src.m10()). - _m11(src.m11()). - _m12(src.m12()). - _m13(src.m13()). - _m20(src.m20()). - _m21(src.m21()). - _m22(src.m22()). - _m23(src.m23()). - _m30(src.m30()). - _m31(src.m31()). - _m32(src.m32()). - _m33(src.m33()); - } - - public void copy(Matrix3f src, Matrix4f dest) { - dest._m00(src.m00()) - ._m01(src.m01()) - ._m02(src.m02()) - ._m03(0.0f) - ._m10(src.m10()) - ._m11(src.m11()) - ._m12(src.m12()) - ._m13(0.0f) - ._m20(src.m20()) - ._m21(src.m21()) - ._m22(src.m22()) - ._m23(0.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(0.0f) - ._m33(1.0f); - } - - public void copy(Matrix4f src, Matrix3f dest) { - dest._m00(src.m00()) - ._m01(src.m01()) - ._m02(src.m02()) - ._m10(src.m10()) - ._m11(src.m11()) - ._m12(src.m12()) - ._m20(src.m20()) - ._m21(src.m21()) - ._m22(src.m22()); - } - - public void copy3x3(Matrix4f src, Matrix4f dest) { - dest._m00(src.m00()) - ._m01(src.m01()) - ._m02(src.m02()) - ._m10(src.m10()) - ._m11(src.m11()) - ._m12(src.m12()) - ._m20(src.m20()) - ._m21(src.m21()) - ._m22(src.m22()); - } - - public void copy3x3(Matrix3f src, Matrix4f dest) { - dest._m00(src.m00()) - ._m01(src.m01()) - ._m02(src.m02()) - ._m10(src.m10()) - ._m11(src.m11()) - ._m12(src.m12()) - ._m20(src.m20()) - ._m21(src.m21()) - ._m22(src.m22()); - } - - public void copy4x3(Matrix4f src, Matrix4f dest) { - dest._m00(src.m00()) - ._m01(src.m01()) - ._m02(src.m02()) - ._m10(src.m10()) - ._m11(src.m11()) - ._m12(src.m12()) - ._m20(src.m20()) - ._m21(src.m21()) - ._m22(src.m22()) - ._m30(src.m30()) - ._m31(src.m31()) - ._m32(src.m32()); - } - - public void copy(Matrix3f src, Matrix3f dest) { - dest._m00(src.m00()) - ._m01(src.m01()) - ._m02(src.m02()) - ._m10(src.m10()) - ._m11(src.m11()) - ._m12(src.m12()) - ._m20(src.m20()) - ._m21(src.m21()) - ._m22(src.m22()); - } - - public void copy(float[] arr, int off, Matrix4f dest) { - dest._m00(arr[off+0]) - ._m01(arr[off+1]) - ._m02(arr[off+2]) - ._m03(arr[off+3]) - ._m10(arr[off+4]) - ._m11(arr[off+5]) - ._m12(arr[off+6]) - ._m13(arr[off+7]) - ._m20(arr[off+8]) - ._m21(arr[off+9]) - ._m22(arr[off+10]) - ._m23(arr[off+11]) - ._m30(arr[off+12]) - ._m31(arr[off+13]) - ._m32(arr[off+14]) - ._m33(arr[off+15]); - } - - public void copyTransposed(float[] arr, int off, Matrix4f dest) { - dest._m00(arr[off+0]) - ._m10(arr[off+1]) - ._m20(arr[off+2]) - ._m30(arr[off+3]) - ._m01(arr[off+4]) - ._m11(arr[off+5]) - ._m21(arr[off+6]) - ._m31(arr[off+7]) - ._m02(arr[off+8]) - ._m12(arr[off+9]) - ._m22(arr[off+10]) - ._m32(arr[off+11]) - ._m03(arr[off+12]) - ._m13(arr[off+13]) - ._m23(arr[off+14]) - ._m33(arr[off+15]); - } - - public void copy(float[] arr, int off, Matrix3f dest) { - dest._m00(arr[off+0]) - ._m01(arr[off+1]) - ._m02(arr[off+2]) - ._m10(arr[off+3]) - ._m11(arr[off+4]) - ._m12(arr[off+5]) - ._m20(arr[off+6]) - ._m21(arr[off+7]) - ._m22(arr[off+8]); - } - - public void copy(Matrix4f src, float[] dest, int off) { - dest[off+0] = src.m00(); - dest[off+1] = src.m01(); - dest[off+2] = src.m02(); - dest[off+3] = src.m03(); - dest[off+4] = src.m10(); - dest[off+5] = src.m11(); - dest[off+6] = src.m12(); - dest[off+7] = src.m13(); - dest[off+8] = src.m20(); - dest[off+9] = src.m21(); - dest[off+10] = src.m22(); - dest[off+11] = src.m23(); - dest[off+12] = src.m30(); - dest[off+13] = src.m31(); - dest[off+14] = src.m32(); - dest[off+15] = src.m33(); - } - - public void copy(Matrix3f src, float[] dest, int off) { - dest[off+0] = src.m00(); - dest[off+1] = src.m01(); - dest[off+2] = src.m02(); - dest[off+3] = src.m10(); - dest[off+4] = src.m11(); - dest[off+5] = src.m12(); - dest[off+6] = src.m20(); - dest[off+7] = src.m21(); - dest[off+8] = src.m22(); - } - - public void identity(Matrix4f dest) { - dest._m00(1.0f) - ._m01(0.0f) - ._m02(0.0f) - ._m03(0.0f) - ._m10(0.0f) - ._m11(1.0f) - ._m12(0.0f) - ._m13(0.0f) - ._m20(0.0f) - ._m21(0.0f) - ._m22(1.0f) - ._m23(0.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(0.0f) - ._m33(1.0f); - } - - public void identity(Matrix3f dest) { - dest._m00(1.0f) - ._m01(0.0f) - ._m02(0.0f) - ._m10(0.0f) - ._m11(1.0f) - ._m12(0.0f) - ._m20(0.0f) - ._m21(0.0f) - ._m22(1.0f); - } - - public void swap(Matrix4f m1, Matrix4f m2) { - float tmp; - tmp = m1.m00(); m1._m00(m2.m00()); m2._m00(tmp); - tmp = m1.m01(); m1._m01(m2.m01()); m2._m01(tmp); - tmp = m1.m02(); m1._m02(m2.m02()); m2._m02(tmp); - tmp = m1.m03(); m1._m03(m2.m03()); m2._m03(tmp); - tmp = m1.m10(); m1._m10(m2.m10()); m2._m10(tmp); - tmp = m1.m11(); m1._m11(m2.m11()); m2._m11(tmp); - tmp = m1.m12(); m1._m12(m2.m12()); m2._m12(tmp); - tmp = m1.m13(); m1._m13(m2.m13()); m2._m13(tmp); - tmp = m1.m20(); m1._m20(m2.m20()); m2._m20(tmp); - tmp = m1.m21(); m1._m21(m2.m21()); m2._m21(tmp); - tmp = m1.m22(); m1._m22(m2.m22()); m2._m22(tmp); - tmp = m1.m23(); m1._m23(m2.m23()); m2._m23(tmp); - tmp = m1.m30(); m1._m30(m2.m30()); m2._m30(tmp); - tmp = m1.m31(); m1._m31(m2.m31()); m2._m31(tmp); - tmp = m1.m32(); m1._m32(m2.m32()); m2._m32(tmp); - tmp = m1.m33(); m1._m33(m2.m33()); m2._m33(tmp); - } - - public void swap(Matrix3f m1, Matrix3f m2) { - float tmp; - tmp = m1.m00(); m1._m00(m2.m00()); m2._m00(tmp); - tmp = m1.m01(); m1._m01(m2.m01()); m2._m01(tmp); - tmp = m1.m02(); m1._m02(m2.m02()); m2._m02(tmp); - tmp = m1.m10(); m1._m10(m2.m10()); m2._m10(tmp); - tmp = m1.m11(); m1._m11(m2.m11()); m2._m11(tmp); - tmp = m1.m12(); m1._m12(m2.m12()); m2._m12(tmp); - tmp = m1.m20(); m1._m20(m2.m20()); m2._m20(tmp); - tmp = m1.m21(); m1._m21(m2.m21()); m2._m21(tmp); - tmp = m1.m22(); m1._m22(m2.m22()); m2._m22(tmp); - } - - public void zero(Matrix4f dest) { - dest._m00(0.0f) - ._m01(0.0f) - ._m02(0.0f) - ._m03(0.0f) - ._m10(0.0f) - ._m11(0.0f) - ._m12(0.0f) - ._m13(0.0f) - ._m20(0.0f) - ._m21(0.0f) - ._m22(0.0f) - ._m23(0.0f) - ._m30(0.0f) - ._m31(0.0f) - ._m32(0.0f) - ._m33(0.0f); - } - - public void zero(Matrix3f dest) { - dest._m00(0.0f) - ._m01(0.0f) - ._m02(0.0f) - ._m10(0.0f) - ._m11(0.0f) - ._m12(0.0f) - ._m20(0.0f) - ._m21(0.0f) - ._m22(0.0f); - } - - public void putMatrix3f(Quaternionf q, int position, ByteBuffer dest) { - float w2 = q.w * q.w; - float x2 = q.x * q.x; - float y2 = q.y * q.y; - float z2 = q.z * q.z; - float zw = q.z * q.w; - float xy = q.x * q.y; - float xz = q.x * q.z; - float yw = q.y * q.w; - float yz = q.y * q.z; - float xw = q.x * q.w; - dest.putFloat(position, w2 + x2 - z2 - y2) - .putFloat(position + 4, xy + zw + zw + xy) - .putFloat(position + 8, xz - yw + xz - yw) - .putFloat(position + 12, -zw + xy - zw + xy) - .putFloat(position + 16, y2 - z2 + w2 - x2) - .putFloat(position + 20, yz + yz + xw + xw) - .putFloat(position + 24, yw + xz + xz + yw) - .putFloat(position + 28, yz + yz - xw - xw) - .putFloat(position + 32, z2 - y2 - x2 + w2); - } - - public void putMatrix3f(Quaternionf q, int position, FloatBuffer dest) { - float w2 = q.w * q.w; - float x2 = q.x * q.x; - float y2 = q.y * q.y; - float z2 = q.z * q.z; - float zw = q.z * q.w; - float xy = q.x * q.y; - float xz = q.x * q.z; - float yw = q.y * q.w; - float yz = q.y * q.z; - float xw = q.x * q.w; - dest.put(position, w2 + x2 - z2 - y2) - .put(position + 1, xy + zw + zw + xy) - .put(position + 2, xz - yw + xz - yw) - .put(position + 3, -zw + xy - zw + xy) - .put(position + 4, y2 - z2 + w2 - x2) - .put(position + 5, yz + yz + xw + xw) - .put(position + 6, yw + xz + xz + yw) - .put(position + 7, yz + yz - xw - xw) - .put(position + 8, z2 - y2 - x2 + w2); - } - - public void putMatrix4f(Quaternionf q, int position, ByteBuffer dest) { - float w2 = q.w * q.w; - float x2 = q.x * q.x; - float y2 = q.y * q.y; - float z2 = q.z * q.z; - float zw = q.z * q.w; - float xy = q.x * q.y; - float xz = q.x * q.z; - float yw = q.y * q.w; - float yz = q.y * q.z; - float xw = q.x * q.w; - dest.putFloat(position, w2 + x2 - z2 - y2) - .putFloat(position + 4, xy + zw + zw + xy) - .putFloat(position + 8, xz - yw + xz - yw) - .putFloat(position + 12, 0.0f) - .putFloat(position + 16, -zw + xy - zw + xy) - .putFloat(position + 20, y2 - z2 + w2 - x2) - .putFloat(position + 24, yz + yz + xw + xw) - .putFloat(position + 28, 0.0f) - .putFloat(position + 32, yw + xz + xz + yw) - .putFloat(position + 36, yz + yz - xw - xw) - .putFloat(position + 40, z2 - y2 - x2 + w2) - .putFloat(position + 44, 0.0f) - .putLong(position + 48, 0L) - .putLong(position + 56, 0x3F80000000000000L); - } - - public void putMatrix4f(Quaternionf q, int position, FloatBuffer dest) { - float w2 = q.w * q.w; - float x2 = q.x * q.x; - float y2 = q.y * q.y; - float z2 = q.z * q.z; - float zw = q.z * q.w; - float xy = q.x * q.y; - float xz = q.x * q.z; - float yw = q.y * q.w; - float yz = q.y * q.z; - float xw = q.x * q.w; - dest.put(position, w2 + x2 - z2 - y2) - .put(position + 1, xy + zw + zw + xy) - .put(position + 2, xz - yw + xz - yw) - .put(position + 3, 0.0f) - .put(position + 4, -zw + xy - zw + xy) - .put(position + 5, y2 - z2 + w2 - x2) - .put(position + 6, yz + yz + xw + xw) - .put(position + 7, 0.0f) - .put(position + 8, yw + xz + xz + yw) - .put(position + 9, yz + yz - xw - xw) - .put(position + 10, z2 - y2 - x2 + w2) - .put(position + 11, 0.0f) - .put(position + 12, 0.0f) - .put(position + 13, 0.0f) - .put(position + 14, 0.0f) - .put(position + 15, 1.0f); - } - - public void putMatrix4x3f(Quaternionf q, int position, ByteBuffer dest) { - float w2 = q.w * q.w; - float x2 = q.x * q.x; - float y2 = q.y * q.y; - float z2 = q.z * q.z; - float zw = q.z * q.w; - float xy = q.x * q.y; - float xz = q.x * q.z; - float yw = q.y * q.w; - float yz = q.y * q.z; - float xw = q.x * q.w; - dest.putFloat(position, w2 + x2 - z2 - y2) - .putFloat(position + 4, xy + zw + zw + xy) - .putFloat(position + 8, xz - yw + xz - yw) - .putFloat(position + 12, -zw + xy - zw + xy) - .putFloat(position + 16, y2 - z2 + w2 - x2) - .putFloat(position + 20, yz + yz + xw + xw) - .putFloat(position + 24, yw + xz + xz + yw) - .putFloat(position + 28, yz + yz - xw - xw) - .putFloat(position + 32, z2 - y2 - x2 + w2) - .putLong(position + 36, 0L) - .putFloat(position + 44, 0.0f); - } - - public void putMatrix4x3f(Quaternionf q, int position, FloatBuffer dest) { - float w2 = q.w * q.w; - float x2 = q.x * q.x; - float y2 = q.y * q.y; - float z2 = q.z * q.z; - float zw = q.z * q.w; - float xy = q.x * q.y; - float xz = q.x * q.z; - float yw = q.y * q.w; - float yz = q.y * q.z; - float xw = q.x * q.w; - dest.put(position, w2 + x2 - z2 - y2) - .put(position + 1, xy + zw + zw + xy) - .put(position + 2, xz - yw + xz - yw) - .put(position + 3, -zw + xy - zw + xy) - .put(position + 4, y2 - z2 + w2 - x2) - .put(position + 5, yz + yz + xw + xw) - .put(position + 6, yw + xz + xz + yw) - .put(position + 7, yz + yz - xw - xw) - .put(position + 8, z2 - y2 - x2 + w2) - .put(position + 9, 0.0f) - .put(position + 10, 0.0f) - .put(position + 11, 0.0f); - } - } - - public static class MemUtilUnsafe extends MemUtilNIO { - public static final sun.misc.Unsafe UNSAFE; - - public static final long ADDRESS; - public static final long Matrix3f_m00; - public static final long Matrix4f_m00; - public static final long Vector4f_x; - public static final long Vector3f_x; - public static final long Quaternionf_x; - public static final long floatArrayOffset; - - static { - UNSAFE = getUnsafeInstance(); - try { - ADDRESS = findBufferAddress(); - Matrix4f_m00 = checkMatrix4f(); - Matrix3f_m00 = checkMatrix3f(); - Vector4f_x = checkVector4f(); - Vector3f_x = checkVector3f(); - Quaternionf_x = checkQuaternionf(); - floatArrayOffset = UNSAFE.arrayBaseOffset(float[].class); - // Check if we can use object field offset/address put/get methods - sun.misc.Unsafe.class.getDeclaredMethod("getLong", new Class[] {Object.class, long.class}); - sun.misc.Unsafe.class.getDeclaredMethod("putLong", new Class[] {Object.class, long.class, long.class}); - } catch (NoSuchFieldException e) { - throw new UnsupportedOperationException(e); - } catch (NoSuchMethodException e) { - throw new UnsupportedOperationException(e); - } - } - - private static long findBufferAddress() { - try { - return UNSAFE.objectFieldOffset(getDeclaredField(Buffer.class, "address")); //$NON-NLS-1$ - } catch (Exception e) { - throw new UnsupportedOperationException(e); - } - } - - private static long checkMatrix4f() throws NoSuchFieldException, SecurityException { - Field f = Matrix4f.class.getDeclaredField("m00"); - long Matrix4f_m00 = UNSAFE.objectFieldOffset(f); - // Validate expected field offsets - for (int i = 1; i < 16; i++) { - int c = i >>> 2; - int r = i & 3; - f = Matrix4f.class.getDeclaredField("m" + c + r); - long offset = UNSAFE.objectFieldOffset(f); - if (offset != Matrix4f_m00 + (i << 2)) - throw new UnsupportedOperationException("Unexpected Matrix4f element offset"); - } - return Matrix4f_m00; - } - - private static long checkMatrix3f() throws NoSuchFieldException, SecurityException { - Field f = Matrix3f.class.getDeclaredField("m00"); - long Matrix3f_m00 = UNSAFE.objectFieldOffset(f); - // Validate expected field offsets - for (int i = 1; i < 9; i++) { - int c = i / 3; - int r = i % 3; - f = Matrix3f.class.getDeclaredField("m" + c + r); - long offset = UNSAFE.objectFieldOffset(f); - if (offset != Matrix3f_m00 + (i << 2)) - throw new UnsupportedOperationException("Unexpected Matrix3f element offset"); - } - return Matrix3f_m00; - } - - private static long checkVector4f() throws NoSuchFieldException, SecurityException { - Field f = Vector4f.class.getDeclaredField("x"); - long Vector4f_x = UNSAFE.objectFieldOffset(f); - // Validate expected field offsets - String[] names = {"y", "z", "w"}; - for (int i = 1; i < 4; i++) { - f = Vector4f.class.getDeclaredField(names[i-1]); - long offset = UNSAFE.objectFieldOffset(f); - if (offset != Vector4f_x + (i << 2)) - throw new UnsupportedOperationException("Unexpected Vector4f element offset"); - } - return Vector4f_x; - } - - private static long checkVector3f() throws NoSuchFieldException, SecurityException { - Field f = Vector3f.class.getDeclaredField("x"); - long Vector3f_x = UNSAFE.objectFieldOffset(f); - // Validate expected field offsets - String[] names = {"y", "z"}; - for (int i = 1; i < 3; i++) { - f = Vector3f.class.getDeclaredField(names[i-1]); - long offset = UNSAFE.objectFieldOffset(f); - if (offset != Vector3f_x + (i << 2)) - throw new UnsupportedOperationException("Unexpected Vector3f element offset"); - } - return Vector3f_x; - } - - private static long checkQuaternionf() throws NoSuchFieldException, SecurityException { - Field f = Quaternionf.class.getDeclaredField("x"); - long Quaternionf_x = UNSAFE.objectFieldOffset(f); - // Validate expected field offsets - String[] names = {"y", "z", "w"}; - for (int i = 1; i < 4; i++) { - f = Quaternionf.class.getDeclaredField(names[i-1]); - long offset = UNSAFE.objectFieldOffset(f); - if (offset != Quaternionf_x + (i << 2)) - throw new UnsupportedOperationException("Unexpected Quaternionf element offset"); - } - return Quaternionf_x; - } - - private static java.lang.reflect.Field getDeclaredField(Class root, String fieldName) throws NoSuchFieldException { - Class type = root; - do { - try { - java.lang.reflect.Field field = type.getDeclaredField(fieldName); - return field; - } catch (NoSuchFieldException e) { - type = type.getSuperclass(); - } catch (SecurityException e) { - type = type.getSuperclass(); - } - } while (type != null); - throw new NoSuchFieldException(fieldName + " does not exist in " + root.getName() + " or any of its superclasses."); //$NON-NLS-1$ //$NON-NLS-2$ - } - - public static sun.misc.Unsafe getUnsafeInstance() throws SecurityException { - java.lang.reflect.Field[] fields = sun.misc.Unsafe.class.getDeclaredFields(); - for (int i = 0; i < fields.length; i++) { - java.lang.reflect.Field field = fields[i]; - if (!field.getType().equals(sun.misc.Unsafe.class)) - continue; - int modifiers = field.getModifiers(); - if (!(java.lang.reflect.Modifier.isStatic(modifiers) && java.lang.reflect.Modifier.isFinal(modifiers))) - continue; - field.setAccessible(true); - try { - return (sun.misc.Unsafe) field.get(null); - } catch (IllegalAccessException e) { - /* Ignore */ - } - break; - } - throw new UnsupportedOperationException(); - } - - public static void put(Matrix4f m, long destAddr) { - for (int i = 0; i < 8; i++) { - UNSAFE.putLong(null, destAddr + (i << 3), UNSAFE.getLong(m, Matrix4f_m00 + (i << 3))); - } - } - - public static void put4x3(Matrix4f m, long destAddr) { - sun.misc.Unsafe u = UNSAFE; - for (int i = 0; i < 4; i++) { - u.putLong(null, destAddr + 12 * i, u.getLong(m, Matrix4f_m00 + (i << 4))); - } - u.putFloat(null, destAddr + 8, m.m02()); - u.putFloat(null, destAddr + 20, m.m12()); - u.putFloat(null, destAddr + 32, m.m22()); - u.putFloat(null, destAddr + 44, m.m32()); - } - - public static void put3x4(Matrix4f m, long destAddr) { - for (int i = 0; i < 6; i++) { - UNSAFE.putLong(null, destAddr + (i << 3), UNSAFE.getLong(m, Matrix4f_m00 + (i << 3))); - } - } - - public static void putTransposed(Matrix4f m, long destAddr) { - sun.misc.Unsafe u = UNSAFE; - u.putFloat(null, destAddr, m.m00()); - u.putFloat(null, destAddr + 4, m.m10()); - u.putFloat(null, destAddr + 8, m.m20()); - u.putFloat(null, destAddr + 12, m.m30()); - u.putFloat(null, destAddr + 16, m.m01()); - u.putFloat(null, destAddr + 20, m.m11()); - u.putFloat(null, destAddr + 24, m.m21()); - u.putFloat(null, destAddr + 28, m.m31()); - u.putFloat(null, destAddr + 32, m.m02()); - u.putFloat(null, destAddr + 36, m.m12()); - u.putFloat(null, destAddr + 40, m.m22()); - u.putFloat(null, destAddr + 44, m.m32()); - u.putFloat(null, destAddr + 48, m.m03()); - u.putFloat(null, destAddr + 52, m.m13()); - u.putFloat(null, destAddr + 56, m.m23()); - u.putFloat(null, destAddr + 60, m.m33()); - } - - public static void put4x3Transposed(Matrix4f m, long destAddr) { - sun.misc.Unsafe u = UNSAFE; - u.putFloat(null, destAddr, m.m00()); - u.putFloat(null, destAddr + 4, m.m10()); - u.putFloat(null, destAddr + 8, m.m20()); - u.putFloat(null, destAddr + 12, m.m30()); - u.putFloat(null, destAddr + 16, m.m01()); - u.putFloat(null, destAddr + 20, m.m11()); - u.putFloat(null, destAddr + 24, m.m21()); - u.putFloat(null, destAddr + 28, m.m31()); - u.putFloat(null, destAddr + 32, m.m02()); - u.putFloat(null, destAddr + 36, m.m12()); - u.putFloat(null, destAddr + 40, m.m22()); - u.putFloat(null, destAddr + 44, m.m32()); - } - - public static void putTransposed(Matrix3f m, long destAddr) { - sun.misc.Unsafe u = UNSAFE; - u.putFloat(null, destAddr, m.m00()); - u.putFloat(null, destAddr + 4, m.m10()); - u.putFloat(null, destAddr + 8, m.m20()); - u.putFloat(null, destAddr + 12, m.m01()); - u.putFloat(null, destAddr + 16, m.m11()); - u.putFloat(null, destAddr + 20, m.m21()); - u.putFloat(null, destAddr + 24, m.m02()); - u.putFloat(null, destAddr + 28, m.m12()); - u.putFloat(null, destAddr + 32, m.m22()); - } - - public static void put(Matrix3f m, long destAddr) { - for (int i = 0; i < 4; i++) { - UNSAFE.putLong(null, destAddr + (i << 3), UNSAFE.getLong(m, Matrix3f_m00 + (i << 3))); - } - UNSAFE.putFloat(null, destAddr + 32, m.m22()); - } - - public static void put3x4(Matrix3f m, long destAddr) { - for (int i = 0; i < 3; i++) { - UNSAFE.putLong(null, destAddr + (i << 4), UNSAFE.getLong(m, Matrix3f_m00 + 12 * i)); - UNSAFE.putFloat(null, destAddr + (i << 4) + 8, UNSAFE.getFloat(m, Matrix3f_m00 + 8 + 12 * i)); - UNSAFE.putFloat(null, destAddr + 12 * i, 0.0f); - } - } - - public static void put(Vector4f src, long destAddr) { - UNSAFE.putLong(null, destAddr, UNSAFE.getLong(src, Vector4f_x)); - UNSAFE.putLong(null, destAddr+8, UNSAFE.getLong(src, Vector4f_x+8)); - } - - public static void put(Vector3f src, long destAddr) { - UNSAFE.putLong(null, destAddr, UNSAFE.getLong(src, Vector3f_x)); - UNSAFE.putFloat(null, destAddr+8, src.z); - } - - public static void get(Matrix4f m, long srcAddr) { - for (int i = 0; i < 8; i++) { - UNSAFE.putLong(m, Matrix4f_m00 + (i << 3), UNSAFE.getLong(srcAddr + (i << 3))); - } - } - - public static void getTransposed(Matrix4f m, long srcAddr) { - m._m00(UNSAFE.getFloat(srcAddr)) - ._m10(UNSAFE.getFloat(srcAddr + 4)) - ._m20(UNSAFE.getFloat(srcAddr + 8)) - ._m30(UNSAFE.getFloat(srcAddr + 12)) - ._m01(UNSAFE.getFloat(srcAddr + 16)) - ._m11(UNSAFE.getFloat(srcAddr + 20)) - ._m21(UNSAFE.getFloat(srcAddr + 24)) - ._m31(UNSAFE.getFloat(srcAddr + 28)) - ._m02(UNSAFE.getFloat(srcAddr + 32)) - ._m12(UNSAFE.getFloat(srcAddr + 36)) - ._m22(UNSAFE.getFloat(srcAddr + 40)) - ._m32(UNSAFE.getFloat(srcAddr + 44)) - ._m03(UNSAFE.getFloat(srcAddr + 48)) - ._m13(UNSAFE.getFloat(srcAddr + 52)) - ._m23(UNSAFE.getFloat(srcAddr + 56)) - ._m33(UNSAFE.getFloat(srcAddr + 60)); - } - - public static void get(Matrix3f m, long srcAddr) { - for (int i = 0; i < 4; i++) { - UNSAFE.putLong(m, Matrix3f_m00 + (i << 3), UNSAFE.getLong(null, srcAddr + (i << 3))); - } - m._m22(UNSAFE.getFloat(null, srcAddr+32)); - } - - public static void get(Vector4f dst, long srcAddr) { - dst.x = UNSAFE.getFloat(null, srcAddr); - dst.y = UNSAFE.getFloat(null, srcAddr+4); - dst.z = UNSAFE.getFloat(null, srcAddr+8); - dst.w = UNSAFE.getFloat(null, srcAddr+12); - } - - public static void get(Vector3f dst, long srcAddr) { - dst.x = UNSAFE.getFloat(null, srcAddr); - dst.y = UNSAFE.getFloat(null, srcAddr+4); - dst.z = UNSAFE.getFloat(null, srcAddr+8); - } - - public static void putMatrix3f(Quaternionf q, long addr) { - 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; - sun.misc.Unsafe u = UNSAFE; - u.putFloat(null, addr, 1.0f - q11 - q22); - u.putFloat(null, addr + 4, q01 + q23); - u.putFloat(null, addr + 8, q02 - q13); - u.putFloat(null, addr + 12, q01 - q23); - u.putFloat(null, addr + 16, 1.0f - q22 - q00); - u.putFloat(null, addr + 20, q12 + q03); - u.putFloat(null, addr + 24, q02 + q13); - u.putFloat(null, addr + 28, q12 - q03); - u.putFloat(null, addr + 32, 1.0f - q11 - q00); - } - - public static void putMatrix4f(Quaternionf q, long addr) { - 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; - sun.misc.Unsafe u = UNSAFE; - u.putFloat(null, addr, 1.0f - q11 - q22); - u.putFloat(null, addr + 4, q01 + q23); - u.putLong(null, addr + 8, Float.floatToRawIntBits(q02 - q13) & 0xFFFFFFFFL); - u.putFloat(null, addr + 16, q01 - q23); - u.putFloat(null, addr + 20, 1.0f - q22 - q00); - u.putLong(null, addr + 24, Float.floatToRawIntBits(q12 + q03) & 0xFFFFFFFFL); - u.putFloat(null, addr + 32, q02 + q13); - u.putFloat(null, addr + 36, q12 - q03); - u.putLong(null, addr + 40, Float.floatToRawIntBits(1.0f - q11 - q00) & 0xFFFFFFFFL); - u.putLong(null, addr + 48, 0L); - u.putLong(null, addr + 56, 0x3F80000000000000L); - } - - public static void putMatrix4x3f(Quaternionf q, long addr) { - 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; - sun.misc.Unsafe u = UNSAFE; - u.putFloat(null, addr, 1.0f - q11 - q22); - u.putFloat(null, addr + 4, q01 + q23); - u.putFloat(null, addr + 8, q02 - q13); - u.putFloat(null, addr + 12, q01 - q23); - u.putFloat(null, addr + 16, 1.0f - q22 - q00); - u.putFloat(null, addr + 20, q12 + q03); - u.putFloat(null, addr + 24, q02 + q13); - u.putFloat(null, addr + 28, q12 - q03); - u.putFloat(null, addr + 32, 1.0f - q11 - q00); - u.putLong(null, addr + 36, 0L); - u.putFloat(null, addr + 44, 0.0f); - } - - private static void throwNoDirectBufferException() { - throw new IllegalArgumentException("Must use a direct buffer"); - } - - public void putMatrix3f(Quaternionf q, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 9 << 2); - putMatrix3f(q, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void putMatrix3f(Quaternionf q, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 9); - putMatrix3f(q, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - private static void checkPut(int offset, boolean direct, int capacity, int i) { - if (!direct) - throwNoDirectBufferException(); - if (capacity - offset < i) - throw new BufferOverflowException(); - } - - public void putMatrix4f(Quaternionf q, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 16 << 2); - putMatrix4f(q, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void putMatrix4f(Quaternionf q, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 16); - putMatrix4f(q, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void putMatrix4x3f(Quaternionf q, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 12 << 2); - putMatrix4x3f(q, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void putMatrix4x3f(Quaternionf q, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 12); - putMatrix4x3f(q, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void put(Matrix4f m, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 16); - put(m, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void put(Matrix4f m, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 16 << 2); - put(m, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void put4x3(Matrix4f m, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 12); - put4x3(m, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void put4x3(Matrix4f m, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 12 << 2); - put4x3(m, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void put3x4(Matrix4f m, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 12); - put3x4(m, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void put3x4(Matrix4f m, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 12 << 2); - put3x4(m, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void putTransposed(Matrix4f m, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 16); - putTransposed(m, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void putTransposed(Matrix4f m, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 16 << 2); - putTransposed(m, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void put4x3Transposed(Matrix4f m, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 12); - put4x3Transposed(m, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void put4x3Transposed(Matrix4f m, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 12 << 2); - put4x3Transposed(m, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void putTransposed(Matrix3f m, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 9); - putTransposed(m, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void putTransposed(Matrix3f m, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 9 << 2); - putTransposed(m, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void put(Matrix3f m, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 9); - put(m, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void put(Matrix3f m, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 9 << 2); - put(m, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void put3x4(Matrix3f m, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 12); - put3x4(m, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void put3x4(Matrix3f m, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 12 << 2); - put3x4(m, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void put(Vector4f src, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 4); - put(src, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void put(Vector4f src, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 4 << 2); - put(src, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void put(Vector3f src, int offset, FloatBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 3); - put(src, UNSAFE.getLong(dest, ADDRESS) + (offset << 2)); - } - - public void put(Vector3f src, int offset, ByteBuffer dest) { - if (Options.DEBUG) checkPut(offset, dest.isDirect(), dest.capacity(), 3 << 2); - put(src, UNSAFE.getLong(dest, ADDRESS) + offset); - } - - public void get(Matrix4f m, int offset, FloatBuffer src) { - if (Options.DEBUG) checkGet(offset, src.isDirect(), src.capacity(), 16); - get(m, UNSAFE.getLong(src, ADDRESS) + (offset << 2)); - } - - public void get(Matrix4f m, int offset, ByteBuffer src) { - if (Options.DEBUG) checkGet(offset, src.isDirect(), src.capacity(), 16 << 2); - get(m, UNSAFE.getLong(src, ADDRESS) + offset); - } - - public float get(Matrix4f m, int column, int row) { - return UNSAFE.getFloat(m, Matrix4f_m00 + (column << 4) + (row << 2)); - } - - public Matrix4f set(Matrix4f m, int column, int row, float value) { - UNSAFE.putFloat(m, Matrix4f_m00 + (column << 4) + (row << 2), value); - return m; - } - - public float get(Matrix3f m, int column, int row) { - return UNSAFE.getFloat(m, Matrix3f_m00 + (column * (3<<2)) + (row << 2)); - } - - public Matrix3f set(Matrix3f m, int column, int row, float value) { - UNSAFE.putFloat(m, Matrix3f_m00 + (column * (3<<2)) + (row << 2), value); - return m; - } - - private static void checkGet(int offset, boolean direct, int capacity, int i) { - if (!direct) - throwNoDirectBufferException(); - if (capacity - offset < i) - throw new BufferUnderflowException(); - } - - public void get(Matrix3f m, int offset, FloatBuffer src) { - if (Options.DEBUG) checkGet(offset, src.isDirect(), src.capacity(), 9); - get(m, UNSAFE.getLong(src, ADDRESS) + (offset << 2)); - } - - public void get(Matrix3f m, int offset, ByteBuffer src) { - if (Options.DEBUG) checkGet(offset, src.isDirect(), src.capacity(), 9 << 2); - get(m, UNSAFE.getLong(src, ADDRESS) + offset); - } - - public void get(Vector4f dst, int offset, FloatBuffer src) { - if (Options.DEBUG) checkGet(offset, src.isDirect(), src.capacity(), 4); - get(dst, UNSAFE.getLong(src, ADDRESS) + (offset << 2)); - } - - public void get(Vector4f dst, int offset, ByteBuffer src) { - if (Options.DEBUG) checkGet(offset, src.isDirect(), src.capacity(), 4 << 2); - get(dst, UNSAFE.getLong(src, ADDRESS) + offset); - } - - public void get(Vector3f dst, int offset, FloatBuffer src) { - if (Options.DEBUG) checkGet(offset, src.isDirect(), src.capacity(), 3); - get(dst, UNSAFE.getLong(src, ADDRESS) + (offset << 2)); - } - - public void get(Vector3f dst, int offset, ByteBuffer src) { - if (Options.DEBUG) checkGet(offset, src.isDirect(), src.capacity(), 3 << 2); - get(dst, UNSAFE.getLong(src, ADDRESS) + offset); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Options.java b/src/main/java/com/jozufozu/flywheel/util/joml/Options.java deleted file mode 100644 index e0aa98c86..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Options.java +++ /dev/null @@ -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 not to use sun.misc.Unsafe when copying memory with MemUtil. - */ - public static final boolean NO_UNSAFE = hasOption(System.getProperty("joml.nounsafe", "false")); - /** - * Whether to force 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 true, 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 true, 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 not 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 true 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(); - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Quaternionf.java b/src/main/java/com/jozufozu/flywheel/util/joml/Quaternionf.java deleted file mode 100644 index ad2ef13cd..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Quaternionf.java +++ /dev/null @@ -1,2565 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2015-2021 Richard Greenlees - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.jozufozu.flywheel.util.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -import com.mojang.math.Quaternion; - -/** - * Quaternion of 4 single-precision floats which can represent rotation and uniform scaling. - * - * @author Richard Greenlees - * @author Kai Burjack - */ -public class Quaternionf implements Externalizable, Cloneable, Quaternionfc { - - private static final long serialVersionUID = 1L; - - /** - * The first component of the vector part. - */ - public float x; - /** - * The second component of the vector part. - */ - public float y; - /** - * The third component of the vector part. - */ - public float z; - /** - * The real/scalar part of the quaternion. - */ - public float w; - - /** - * Create a new {@link Quaternionf} and initialize it with (x=0, y=0, z=0, w=1), - * where (x, y, z) is the vector part of the quaternion and w is the real/scalar part. - */ - public Quaternionf() { - this.w = 1.0f; - } - - /** - * Create a new {@link Quaternionf} and initialize its components to the given values. - * - * @param x - * the first component of the imaginary part - * @param y - * the second component of the imaginary part - * @param z - * the third component of the imaginary part - * @param w - * the real part - */ - public Quaternionf(double x, double y, double z, double w) { - this.x = (float) x; - this.y = (float) y; - this.z = (float) z; - this.w = (float) w; - } - - /** - * Create a new {@link Quaternionf} and initialize its components to the given values. - * - * @param x - * the first component of the imaginary part - * @param y - * the second component of the imaginary part - * @param z - * the third component of the imaginary part - * @param w - * the real part - */ - public Quaternionf(float x, float y, float z, float w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - } - - /** - * Create a new {@link Quaternionf} and initialize its components to the same values as the given {@link Quaternionfc}. - * - * @param source - * the {@link Quaternionfc} to take the component values from - */ - public Quaternionf(Quaternionfc source) { - set(source); - } - - /** - * Create a new {@link Quaternionf} which represents the rotation of the given {@link AxisAngle4f}. - * - * @param axisAngle - * the {@link AxisAngle4f} - */ - public Quaternionf(AxisAngle4f axisAngle) { - float sin = Math.sin(axisAngle.angle * 0.5f); - float cos = Math.cosFromSin(sin, axisAngle.angle * 0.5f); - x = axisAngle.x * sin; - y = axisAngle.y * sin; - z = axisAngle.z * sin; - w = cos; - } - - public Quaternionf(Quaternion moj) { - x = moj.i(); - y = moj.j(); - z = moj.k(); - w = moj.r(); - } - - /** - * @return the first component of the vector part - */ - public float x() { - return this.x; - } - - /** - * @return the second component of the vector part - */ - public float y() { - return this.y; - } - - /** - * @return the third component of the vector part - */ - public float z() { - return this.z; - } - - /** - * @return the real/scalar part of the quaternion - */ - public float w() { - return this.w; - } - - /** - * Normalize this quaternion. - * - * @return this - */ - public Quaternionf normalize() { - return normalize(this); - } - - public Quaternionf normalize(Quaternionf dest) { - float invNorm = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w)))); - dest.x = x * invNorm; - dest.y = y * invNorm; - dest.z = z * invNorm; - dest.w = w * invNorm; - return dest; - } - - /** - * Add the quaternion (x, y, z, w) to this quaternion. - * - * @param x - * the x component of the vector part - * @param y - * the y component of the vector part - * @param z - * the z component of the vector part - * @param w - * the real/scalar component - * @return this - */ - public Quaternionf add(float x, float y, float z, float w) { - return add(x, y, z, w, this); - } - - public Quaternionf add(float x, float y, float z, float w, Quaternionf dest) { - dest.x = this.x + x; - dest.y = this.y + y; - dest.z = this.z + z; - dest.w = this.w + w; - return dest; - } - - /** - * Add q2 to this quaternion. - * - * @param q2 - * the quaternion to add to this - * @return this - */ - public Quaternionf add(Quaternionfc q2) { - return add(q2, this); - } - - public Quaternionf add(Quaternionfc q2, Quaternionf dest) { - dest.x = x + q2.x(); - dest.y = y + q2.y(); - dest.z = z + q2.z(); - dest.w = w + q2.w(); - return dest; - } - - /** - * Return the dot of this quaternion and otherQuat. - * - * @param otherQuat - * the other quaternion - * @return the dot product - */ - public float dot(Quaternionf otherQuat) { - return this.x * otherQuat.x + this.y * otherQuat.y + this.z * otherQuat.z + this.w * otherQuat.w; - } - - public float angle() { - return (float) (2.0 * Math.safeAcos(w)); - } - - public Matrix3f get(Matrix3f dest) { - return dest.set(this); - } - - public Matrix4f get(Matrix4f dest) { - return dest.set(this); - } - - public AxisAngle4f get(AxisAngle4f dest) { - float x = this.x; - float y = this.y; - float z = this.z; - float w = this.w; - if (w > 1.0f) { - float invNorm = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w)))); - x *= invNorm; - y *= invNorm; - z *= invNorm; - w *= invNorm; - } - dest.angle = (float) (2.0f * Math.acos(w)); - float s = Math.sqrt(1.0f - w * w); - if (s < 0.001f) { - dest.x = x; - dest.y = y; - dest.z = z; - } else { - s = 1.0f / s; - dest.x = x * s; - dest.y = y * s; - dest.z = z * s; - } - return dest; - } - - /** - * Set the given {@link Quaternionf} to the values of this. - * - * @see #set(Quaternionfc) - * - * @param dest - * the {@link Quaternionf} to set - * @return the passed in destination - */ - public Quaternionf get(Quaternionf dest) { - return dest.set(this); - } - - public ByteBuffer getAsMatrix3f(ByteBuffer dest) { - MemUtil.INSTANCE.putMatrix3f(this, dest.position(), dest); - return dest; - } - - public FloatBuffer getAsMatrix3f(FloatBuffer dest) { - MemUtil.INSTANCE.putMatrix3f(this, dest.position(), dest); - return dest; - } - - public ByteBuffer getAsMatrix4f(ByteBuffer dest) { - MemUtil.INSTANCE.putMatrix4f(this, dest.position(), dest); - return dest; - } - - public FloatBuffer getAsMatrix4f(FloatBuffer dest) { - MemUtil.INSTANCE.putMatrix4f(this, dest.position(), dest); - return dest; - } - - public ByteBuffer getAsMatrix4x3f(ByteBuffer dest) { - MemUtil.INSTANCE.putMatrix4x3f(this, dest.position(), dest); - return dest; - } - - public FloatBuffer getAsMatrix4x3f(FloatBuffer dest) { - MemUtil.INSTANCE.putMatrix4x3f(this, dest.position(), dest); - return dest; - } - - /** - * Set this quaternion to the given values. - * - * @param x - * the new value of x - * @param y - * the new value of y - * @param z - * the new value of z - * @param w - * the new value of w - * @return this - */ - public Quaternionf set(float x, float y, float z, float w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - return this; - } - - /** - * Set this quaternion to be a copy of q. - * - * @param q - * the {@link Quaternionfc} to copy - * @return this - */ - public Quaternionf set(Quaternionfc q) { - this.x = q.x(); - this.y = q.y(); - this.z = q.z(); - this.w = q.w(); - return this; - } - - /** - * Set this quaternion to a rotation equivalent to the given {@link AxisAngle4f}. - * - * @param axisAngle - * the {@link AxisAngle4f} - * @return this - */ - public Quaternionf set(AxisAngle4f axisAngle) { - return setAngleAxis(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z); - } - - /** - * Set this quaternion to a rotation equivalent to the supplied axis and - * angle (in radians). - *

- * This method assumes that the given rotation axis (x, y, z) is already normalized - * - * @param angle - * the angle in radians - * @param x - * the x-component of the normalized rotation axis - * @param y - * the y-component of the normalized rotation axis - * @param z - * the z-component of the normalized rotation axis - * @return this - */ - public Quaternionf setAngleAxis(float angle, float x, float y, float z) { - float s = Math.sin(angle * 0.5f); - this.x = x * s; - this.y = y * s; - this.z = z * s; - this.w = Math.cosFromSin(s, angle * 0.5f); - return this; - } - - /** - * Set this quaternion to a rotation equivalent to the supplied axis and - * angle (in radians). - *

- * This method assumes that the given rotation axis (x, y, z) is already normalized - * - * @param angle - * the angle in radians - * @param x - * the x-component of the normalized rotation axis - * @param y - * the y-component of the normalized rotation axis - * @param z - * the z-component of the normalized rotation axis - * @return this - */ - public Quaternionf setAngleAxis(double angle, double x, double y, double z) { - double s = Math.sin(angle * 0.5f); - this.x = (float) (x * s); - this.y = (float) (y * s); - this.z = (float) (z * s); - this.w = (float) Math.cosFromSin(s, angle * 0.5f); - return this; - } - - /** - * Set this {@link Quaternionf} to a rotation of the given angle in radians about the supplied - * axis, all of which are specified via the {@link AxisAngle4f}. - * - * @see #rotationAxis(float, float, float, float) - * - * @param axisAngle - * the {@link AxisAngle4f} giving the rotation angle in radians and the axis to rotate about - * @return this - */ - public Quaternionf rotationAxis(AxisAngle4f axisAngle) { - return rotationAxis(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z); - } - - /** - * Set this quaternion to a rotation of the given angle in radians about the supplied axis. - * - * @param angle - * the rotation angle in radians - * @param axisX - * the x-coordinate of the rotation axis - * @param axisY - * the y-coordinate of the rotation axis - * @param axisZ - * the z-coordinate of the rotation axis - * @return this - */ - public Quaternionf rotationAxis(float angle, float axisX, float axisY, float axisZ) { - float hangle = angle / 2.0f; - float sinAngle = Math.sin(hangle); - float invVLength = Math.invsqrt(axisX * axisX + axisY * axisY + axisZ * axisZ); - return set(axisX * invVLength * sinAngle, - axisY * invVLength * sinAngle, - axisZ * invVLength * sinAngle, - Math.cosFromSin(sinAngle, hangle)); - } - - /** - * Set this quaternion to a rotation of the given angle in radians about the supplied axis. - * - * @see #rotationAxis(float, float, float, float) - * - * @param angle - * the rotation angle in radians - * @param axis - * the axis to rotate about - * @return this - */ - public Quaternionf rotationAxis(float angle, Vector3fc axis) { - return rotationAxis(angle, axis.x(), axis.y(), axis.z()); - } - - /** - * Set this quaternion to represent a rotation of the given radians about the x axis. - * - * @param angle - * the angle in radians to rotate about the x axis - * @return this - */ - public Quaternionf rotationX(float angle) { - float sin = Math.sin(angle * 0.5f); - float cos = Math.cosFromSin(sin, angle * 0.5f); - return set(sin, 0, 0, cos); - } - - /** - * Set this quaternion to represent a rotation of the given radians about the y axis. - * - * @param angle - * the angle in radians to rotate about the y axis - * @return this - */ - public Quaternionf rotationY(float angle) { - float sin = Math.sin(angle * 0.5f); - float cos = Math.cosFromSin(sin, angle * 0.5f); - return set(0, sin, 0, cos); - } - - /** - * Set this quaternion to represent a rotation of the given radians about the z axis. - * - * @param angle - * the angle in radians to rotate about the z axis - * @return this - */ - public Quaternionf rotationZ(float angle) { - float sin = Math.sin(angle * 0.5f); - float cos = Math.cosFromSin(sin, angle * 0.5f); - return set(0, 0, sin, cos); - } - - private void setFromUnnormalized(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) { - float nm00 = m00, nm01 = m01, nm02 = m02; - float nm10 = m10, nm11 = m11, nm12 = m12; - float nm20 = m20, nm21 = m21, nm22 = m22; - float lenX = Math.invsqrt(m00 * m00 + m01 * m01 + m02 * m02); - float lenY = Math.invsqrt(m10 * m10 + m11 * m11 + m12 * m12); - float lenZ = Math.invsqrt(m20 * m20 + m21 * m21 + m22 * m22); - nm00 *= lenX; nm01 *= lenX; nm02 *= lenX; - nm10 *= lenY; nm11 *= lenY; nm12 *= lenY; - nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ; - setFromNormalized(nm00, nm01, nm02, nm10, nm11, nm12, nm20, nm21, nm22); - } - - private void setFromNormalized(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) { - float t; - float tr = m00 + m11 + m22; - if (tr >= 0.0f) { - t = Math.sqrt(tr + 1.0f); - w = t * 0.5f; - t = 0.5f / t; - x = (m12 - m21) * t; - y = (m20 - m02) * t; - z = (m01 - m10) * t; - } else { - if (m00 >= m11 && m00 >= m22) { - t = Math.sqrt(m00 - (m11 + m22) + 1.0f); - x = t * 0.5f; - t = 0.5f / t; - y = (m10 + m01) * t; - z = (m02 + m20) * t; - w = (m12 - m21) * t; - } else if (m11 > m22) { - t = Math.sqrt(m11 - (m22 + m00) + 1.0f); - y = t * 0.5f; - t = 0.5f / t; - z = (m21 + m12) * t; - x = (m10 + m01) * t; - w = (m20 - m02) * t; - } else { - t = Math.sqrt(m22 - (m00 + m11) + 1.0f); - z = t * 0.5f; - t = 0.5f / t; - x = (m02 + m20) * t; - y = (m21 + m12) * t; - w = (m01 - m10) * t; - } - } - } - - private void setFromUnnormalized(double m00, double m01, double m02, double m10, double m11, double m12, double m20, double m21, double m22) { - double nm00 = m00, nm01 = m01, nm02 = m02; - double nm10 = m10, nm11 = m11, nm12 = m12; - double nm20 = m20, nm21 = m21, nm22 = m22; - double lenX = Math.invsqrt(m00 * m00 + m01 * m01 + m02 * m02); - double lenY = Math.invsqrt(m10 * m10 + m11 * m11 + m12 * m12); - double lenZ = Math.invsqrt(m20 * m20 + m21 * m21 + m22 * m22); - nm00 *= lenX; nm01 *= lenX; nm02 *= lenX; - nm10 *= lenY; nm11 *= lenY; nm12 *= lenY; - nm20 *= lenZ; nm21 *= lenZ; nm22 *= lenZ; - setFromNormalized(nm00, nm01, nm02, nm10, nm11, nm12, nm20, nm21, nm22); - } - - private void setFromNormalized(double m00, double m01, double m02, double m10, double m11, double m12, double m20, double m21, double m22) { - double t; - double tr = m00 + m11 + m22; - if (tr >= 0.0) { - t = Math.sqrt(tr + 1.0); - w = (float) (t * 0.5); - t = 0.5 / t; - x = (float) ((m12 - m21) * t); - y = (float) ((m20 - m02) * t); - z = (float) ((m01 - m10) * t); - } else { - if (m00 >= m11 && m00 >= m22) { - t = Math.sqrt(m00 - (m11 + m22) + 1.0); - x = (float) (t * 0.5); - t = 0.5 / t; - y = (float) ((m10 + m01) * t); - z = (float) ((m02 + m20) * t); - w = (float) ((m12 - m21) * t); - } else if (m11 > m22) { - t = Math.sqrt(m11 - (m22 + m00) + 1.0); - y = (float) (t * 0.5); - t = 0.5 / t; - z = (float) ((m21 + m12) * t); - x = (float) ((m10 + m01) * t); - w = (float) ((m20 - m02) * t); - } else { - t = Math.sqrt(m22 - (m00 + m11) + 1.0); - z = (float) (t * 0.5); - t = 0.5 / t; - x = (float) ((m02 + m20) * t); - y = (float) ((m21 + m12) * t); - w = (float) ((m01 - m10) * t); - } - } - } - - /** - * Set this quaternion to be a representation of the rotational component of the given matrix. - *

- * This method assumes that the first three columns of the upper left 3x3 submatrix are no unit vectors. - * - * @param mat - * the matrix whose rotational component is used to set this quaternion - * @return this - */ - public Quaternionf setFromUnnormalized(Matrix4fc mat) { - setFromUnnormalized(mat.m00(), mat.m01(), mat.m02(), mat.m10(), mat.m11(), mat.m12(), mat.m20(), mat.m21(), mat.m22()); - return this; - } - - /** - * Set this quaternion to be a representation of the rotational component of the given matrix. - *

- * This method assumes that the first three columns of the upper left 3x3 submatrix are unit vectors. - * - * @param mat - * the matrix whose rotational component is used to set this quaternion - * @return this - */ - public Quaternionf setFromNormalized(Matrix4fc mat) { - setFromNormalized(mat.m00(), mat.m01(), mat.m02(), mat.m10(), mat.m11(), mat.m12(), mat.m20(), mat.m21(), mat.m22()); - return this; - } - - /** - * Set this quaternion to be a representation of the rotational component of the given matrix. - *

- * This method assumes that the first three columns of the upper left 3x3 submatrix are no unit vectors. - * - * @param mat - * the matrix whose rotational component is used to set this quaternion - * @return this - */ - public Quaternionf setFromUnnormalized(Matrix3fc mat) { - setFromUnnormalized(mat.m00(), mat.m01(), mat.m02(), mat.m10(), mat.m11(), mat.m12(), mat.m20(), mat.m21(), mat.m22()); - return this; - } - - /** - * Set this quaternion to be a representation of the rotational component of the given matrix. - *

- * This method assumes that the first three columns of the upper left 3x3 submatrix are unit vectors. - * - * @param mat - * the matrix whose rotational component is used to set this quaternion - * @return this - */ - public Quaternionf setFromNormalized(Matrix3fc mat) { - setFromNormalized(mat.m00(), mat.m01(), mat.m02(), mat.m10(), mat.m11(), mat.m12(), mat.m20(), mat.m21(), mat.m22()); - return this; - } - - /** - * Set this quaternion to be a representation of the supplied axis and - * angle (in radians). - * - * @param axis - * the rotation axis - * @param angle - * the angle in radians - * @return this - */ - public Quaternionf fromAxisAngleRad(Vector3fc axis, float angle) { - return fromAxisAngleRad(axis.x(), axis.y(), axis.z(), angle); - } - - /** - * Set this quaternion to be a representation of the supplied axis and - * angle (in radians). - * - * @param axisX - * the x component of the rotation axis - * @param axisY - * the y component of the rotation axis - * @param axisZ - * the z component of the rotation axis - * @param angle - * the angle in radians - * @return this - */ - public Quaternionf fromAxisAngleRad(float axisX, float axisY, float axisZ, float angle) { - float hangle = angle / 2.0f; - float sinAngle = Math.sin(hangle); - float vLength = Math.sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ); - x = axisX / vLength * sinAngle; - y = axisY / vLength * sinAngle; - z = axisZ / vLength * sinAngle; - w = Math.cosFromSin(sinAngle, hangle); - return this; - } - - /** - * Set this quaternion to be a representation of the supplied axis and - * angle (in degrees). - * - * @param axis - * the rotation axis - * @param angle - * the angle in degrees - * @return this - */ - public Quaternionf fromAxisAngleDeg(Vector3fc axis, float angle) { - return fromAxisAngleRad(axis.x(), axis.y(), axis.z(), Math.toRadians(angle)); - } - - /** - * Set this quaternion to be a representation of the supplied axis and - * angle (in degrees). - * - * @param axisX - * the x component of the rotation axis - * @param axisY - * the y component of the rotation axis - * @param axisZ - * the z component of the rotation axis - * @param angle - * the angle in radians - * @return this - */ - public Quaternionf fromAxisAngleDeg(float axisX, float axisY, float axisZ, float angle) { - return fromAxisAngleRad(axisX, axisY, axisZ, Math.toRadians(angle)); - } - - /** - * Multiply this quaternion by q. - *

- * If T is this and Q is the given - * quaternion, then the resulting quaternion R is: - *

- * R = T * Q - *

- * So, this method uses post-multiplication like the matrix classes, resulting in a - * vector to be transformed by Q first, and then by T. - * - * @param q - * the quaternion to multiply this by - * @return this - */ - public Quaternionf mul(Quaternionfc q) { - return mul(q, this); - } - - public Quaternionf mul(Quaternionfc q, Quaternionf dest) { - return dest.set(Math.fma(w, q.x(), Math.fma(x, q.w(), Math.fma(y, q.z(), -z * q.y()))), - Math.fma(w, q.y(), Math.fma(-x, q.z(), Math.fma(y, q.w(), z * q.x()))), - Math.fma(w, q.z(), Math.fma(x, q.y(), Math.fma(-y, q.x(), z * q.w()))), - Math.fma(w, q.w(), Math.fma(-x, q.x(), Math.fma(-y, q.y(), -z * q.z())))); - } - - /** - * Multiply this quaternion by the quaternion represented via (qx, qy, qz, qw). - *

- * If T is this and Q is the given - * quaternion, then the resulting quaternion R is: - *

- * R = T * Q - *

- * So, this method uses post-multiplication like the matrix classes, resulting in a - * vector to be transformed by Q first, and then by T. - * - * @param qx - * the x component of the quaternion to multiply this by - * @param qy - * the y component of the quaternion to multiply this by - * @param qz - * the z component of the quaternion to multiply this by - * @param qw - * the w component of the quaternion to multiply this by - * @return this - */ - public Quaternionf mul(float qx, float qy, float qz, float qw) { - return mul(qx, qy, qz, qw, this); - } - - public Quaternionf mul(float qx, float qy, float qz, float qw, Quaternionf dest) { - return dest.set(Math.fma(w, qx, Math.fma(x, qw, Math.fma(y, qz, -z * qy))), - Math.fma(w, qy, Math.fma(-x, qz, Math.fma(y, qw, z * qx))), - Math.fma(w, qz, Math.fma(x, qy, Math.fma(-y, qx, z * qw))), - Math.fma(w, qw, Math.fma(-x, qx, Math.fma(-y, qy, -z * qz)))); - } - - /** - * Pre-multiply this quaternion by q. - *

- * If T is this and Q is the given quaternion, then the resulting quaternion R is: - *

- * R = Q * T - *

- * So, this method uses pre-multiplication, resulting in a vector to be transformed by T first, and then by Q. - * - * @param q - * the quaternion to pre-multiply this by - * @return this - */ - public Quaternionf premul(Quaternionfc q) { - return premul(q, this); - } - - public Quaternionf premul(Quaternionfc q, Quaternionf dest) { - return dest.set(Math.fma(q.w(), x, Math.fma(q.x(), w, Math.fma(q.y(), z, -q.z() * y))), - Math.fma(q.w(), y, Math.fma(-q.x(), z, Math.fma(q.y(), w, q.z() * x))), - Math.fma(q.w(), z, Math.fma(q.x(), y, Math.fma(-q.y(), x, q.z() * w))), - Math.fma(q.w(), w, Math.fma(-q.x(), x, Math.fma(-q.y(), y, -q.z() * z)))); - } - - /** - * Pre-multiply this quaternion by the quaternion represented via (qx, qy, qz, qw). - *

- * If T is this and Q is the given quaternion, then the resulting quaternion R is: - *

- * R = Q * T - *

- * So, this method uses pre-multiplication, resulting in a vector to be transformed by T first, and then by Q. - * - * @param qx - * the x component of the quaternion to multiply this by - * @param qy - * the y component of the quaternion to multiply this by - * @param qz - * the z component of the quaternion to multiply this by - * @param qw - * the w component of the quaternion to multiply this by - * @return this - */ - public Quaternionf premul(float qx, float qy, float qz, float qw) { - return premul(qx, qy, qz, qw, this); - } - - public Quaternionf premul(float qx, float qy, float qz, float qw, Quaternionf dest) { - return dest.set(Math.fma(qw, x, Math.fma(qx, w, Math.fma(qy, z, -qz * y))), - Math.fma(qw, y, Math.fma(-qx, z, Math.fma(qy, w, qz * x))), - Math.fma(qw, z, Math.fma(qx, y, Math.fma(-qy, x, qz * w))), - Math.fma(qw, w, Math.fma(-qx, x, Math.fma(-qy, y, -qz * z)))); - } - - public Vector3f transform(Vector3f vec){ - return transform(vec.x, vec.y, vec.z, vec); - } - - public Vector3f transformInverse(Vector3f vec){ - return transformInverse(vec.x, vec.y, vec.z, vec); - } - - public Vector3f transformPositiveX(Vector3f dest) { - float ww = w * w; - float xx = x * x; - float yy = y * y; - float zz = z * z; - float zw = z * w; - float xy = x * y; - float xz = x * z; - float yw = y * w; - dest.x = ww + xx - zz - yy; - dest.y = xy + zw + zw + xy; - dest.z = xz - yw + xz - yw; - return dest; - } - - public Vector4f transformPositiveX(Vector4f dest) { - float ww = w * w; - float xx = x * x; - float yy = y * y; - float zz = z * z; - float zw = z * w; - float xy = x * y; - float xz = x * z; - float yw = y * w; - dest.x = ww + xx - zz - yy; - dest.y = xy + zw + zw + xy; - dest.z = xz - yw + xz - yw; - return dest; - } - - public Vector3f transformUnitPositiveX(Vector3f dest) { - float xy = x * y, xz = x * z, yy = y * y; - float yw = y * w, zz = z * z, zw = z * w; - dest.x = 1 - yy - zz - yy - zz; - dest.y = xy + zw + xy + zw; - dest.z = xz - yw + xz - yw; - return dest; - } - - public Vector4f transformUnitPositiveX(Vector4f dest) { - float yy = y * y, zz = z * z, xy = x * y; - float xz = x * z, yw = y * w, zw = z * w; - dest.x = 1 - yy - yy - zz - zz; - dest.y = xy + zw + xy + zw; - dest.z = xz - yw + xz - yw; - return dest; - } - - public Vector3f transformPositiveY(Vector3f dest) { - float ww = w * w; - float xx = x * x; - float yy = y * y; - float zz = z * z; - float zw = z * w; - float xy = x * y; - float yz = y * z; - float xw = x * w; - dest.x = -zw + xy - zw + xy; - dest.y = yy - zz + ww - xx; - dest.z = yz + yz + xw + xw; - return dest; - } - - public Vector4f transformPositiveY(Vector4f dest) { - float ww = w * w, xx = x * x, yy = y * y; - float zz = z * z, zw = z * w, xy = x * y; - float yz = y * z, xw = x * w; - dest.x = -zw + xy - zw + xy; - dest.y = yy - zz + ww - xx; - dest.z = yz + yz + xw + xw; - return dest; - } - - public Vector4f transformUnitPositiveY(Vector4f dest) { - float xx = x * x, zz = z * z, xy = x * y; - float yz = y * z, xw = x * w, zw = z * w; - dest.x = xy - zw + xy - zw; - dest.y = 1 - xx - xx - zz - zz; - dest.z = yz + yz + xw + xw; - return dest; - } - - public Vector3f transformUnitPositiveY(Vector3f dest) { - float xx = x * x, zz = z * z, xy = x * y; - float yz = y * z, xw = x * w, zw = z * w; - dest.x = xy - zw + xy - zw; - dest.y = 1 - xx - xx - zz - zz; - dest.z = yz + yz + xw + xw; - return dest; - } - - public Vector3f transformPositiveZ(Vector3f dest) { - float ww = w * w, xx = x * x, yy = y * y; - float zz = z * z, xz = x * z, yw = y * w; - float yz = y * z, xw = x * w; - dest.x = yw + xz + xz + yw; - dest.y = yz + yz - xw - xw; - dest.z = zz - yy - xx + ww; - return dest; - } - - public Vector4f transformPositiveZ(Vector4f dest) { - float ww = w * w, xx = x * x, yy = y * y; - float zz = z * z, xz = x * z, yw = y * w; - float yz = y * z, xw = x * w; - dest.x = yw + xz + xz + yw; - dest.y = yz + yz - xw - xw; - dest.z = zz - yy - xx + ww; - return dest; - } - - public Vector4f transformUnitPositiveZ(Vector4f dest) { - float xx = x * x, yy = y * y, xz = x * z; - float yz = y * z, xw = x * w, yw = y * w; - dest.x = xz + yw + xz + yw; - dest.y = yz + yz - xw - xw; - dest.z = 1 - xx - xx - yy - yy; - return dest; - } - - public Vector3f transformUnitPositiveZ(Vector3f dest) { - float xx = x * x, yy = y * y, xz = x * z; - float yz = y * z, xw = x * w, yw = y * w; - dest.x = xz + yw + xz + yw; - dest.y = yz + yz - xw - xw; - dest.z = 1.0f - xx - xx - yy - yy; - return dest; - } - - public Vector4f transform(Vector4f vec){ - return transform(vec, vec); - } - - public Vector4f transformInverse(Vector4f vec){ - return transformInverse(vec, vec); - } - - public Vector3f transform(Vector3fc vec, Vector3f dest) { - return transform(vec.x(), vec.y(), vec.z(), dest); - } - - public Vector3f transformInverse(Vector3fc vec, Vector3f dest) { - return transformInverse(vec.x(), vec.y(), vec.z(), dest); - } - - public Vector3f transform(float x, float y, float z, Vector3f dest) { - float xx = this.x * this.x, yy = this.y * this.y, zz = this.z * this.z, ww = this.w * this.w; - float xy = this.x * this.y, xz = this.x * this.z, yz = this.y * this.z, xw = this.x * this.w; - float zw = this.z * this.w, yw = this.y * this.w, k = 1 / (xx + yy + zz + ww); - return dest.set(Math.fma((xx - yy - zz + ww) * k, x, Math.fma(2 * (xy - zw) * k, y, (2 * (xz + yw) * k) * z)), - Math.fma(2 * (xy + zw) * k, x, Math.fma((yy - xx - zz + ww) * k, y, (2 * (yz - xw) * k) * z)), - Math.fma(2 * (xz - yw) * k, x, Math.fma(2 * (yz + xw) * k, y, ((zz - xx - yy + ww) * k) * z))); - } - - public Vector3f transformInverse(float x, float y, float z, Vector3f dest) { - float n = 1.0f / Math.fma(this.x, this.x, Math.fma(this.y, this.y, Math.fma(this.z, this.z, this.w * this.w))); - float qx = this.x * n, qy = this.y * n, qz = this.z * n, qw = this.w * n; - float xx = qx * qx, yy = qy * qy, zz = qz * qz, ww = qw * qw; - float xy = qx * qy, xz = qx * qz, yz = qy * qz, xw = qx * qw; - float zw = qz * qw, yw = qy * qw, k = 1 / (xx + yy + zz + ww); - return dest.set(Math.fma((xx - yy - zz + ww) * k, x, Math.fma(2 * (xy + zw) * k, y, (2 * (xz - yw) * k) * z)), - Math.fma(2 * (xy - zw) * k, x, Math.fma((yy - xx - zz + ww) * k, y, (2 * (yz + xw) * k) * z)), - Math.fma(2 * (xz + yw) * k, x, Math.fma(2 * (yz - xw) * k, y, ((zz - xx - yy + ww) * k) * z))); - } - - public Vector3f transformUnit(Vector3f vec) { - return transformUnit(vec.x, vec.y, vec.z, vec); - } - - public Vector3f transformInverseUnit(Vector3f vec) { - return transformInverseUnit(vec.x, vec.y, vec.z, vec); - } - - public Vector3f transformUnit(Vector3fc vec, Vector3f dest) { - return transformUnit(vec.x(), vec.y(), vec.z(), dest); - } - - public Vector3f transformInverseUnit(Vector3fc vec, Vector3f dest) { - return transformInverseUnit(vec.x(), vec.y(), vec.z(), dest); - } - - public Vector3f transformUnit(float x, float y, float z, Vector3f dest) { - float xx = this.x * this.x, xy = this.x * this.y, xz = this.x * this.z; - float xw = this.x * this.w, yy = this.y * this.y, yz = this.y * this.z; - float yw = this.y * this.w, zz = this.z * this.z, zw = this.z * this.w; - return dest.set(Math.fma(Math.fma(-2, yy + zz, 1), x, Math.fma(2 * (xy - zw), y, (2 * (xz + yw)) * z)), - Math.fma(2 * (xy + zw), x, Math.fma(Math.fma(-2, xx + zz, 1), y, (2 * (yz - xw)) * z)), - Math.fma(2 * (xz - yw), x, Math.fma(2 * (yz + xw), y, Math.fma(-2, xx + yy, 1) * z))); - } - - public Vector3f transformInverseUnit(float x, float y, float z, Vector3f dest) { - float xx = this.x * this.x, xy = this.x * this.y, xz = this.x * this.z; - float xw = this.x * this.w, yy = this.y * this.y, yz = this.y * this.z; - float yw = this.y * this.w, zz = this.z * this.z, zw = this.z * this.w; - return dest.set(Math.fma(Math.fma(-2, yy + zz, 1), x, Math.fma(2 * (xy + zw), y, (2 * (xz - yw)) * z)), - Math.fma(2 * (xy - zw), x, Math.fma(Math.fma(-2, xx + zz, 1), y, (2 * (yz + xw)) * z)), - Math.fma(2 * (xz + yw), x, Math.fma(2 * (yz - xw), y, Math.fma(-2, xx + yy, 1) * z))); - } - - public Vector4f transform(Vector4fc vec, Vector4f dest) { - return transform(vec.x(), vec.y(), vec.z(), dest); - } - - public Vector4f transformInverse(Vector4fc vec, Vector4f dest) { - return transformInverse(vec.x(), vec.y(), vec.z(), dest); - } - - public Vector4f transform(float x, float y, float z, Vector4f dest) { - float xx = this.x * this.x, yy = this.y * this.y, zz = this.z * this.z, ww = this.w * this.w; - float xy = this.x * this.y, xz = this.x * this.z, yz = this.y * this.z, xw = this.x * this.w; - float zw = this.z * this.w, yw = this.y * this.w, k = 1 / (xx + yy + zz + ww); - return dest.set(Math.fma((xx - yy - zz + ww) * k, x, Math.fma(2 * (xy - zw) * k, y, (2 * (xz + yw) * k) * z)), - Math.fma(2 * (xy + zw) * k, x, Math.fma((yy - xx - zz + ww) * k, y, (2 * (yz - xw) * k) * z)), - Math.fma(2 * (xz - yw) * k, x, Math.fma(2 * (yz + xw) * k, y, ((zz - xx - yy + ww) * k) * z))); - } - - public Vector4f transformInverse(float x, float y, float z, Vector4f dest) { - float n = 1.0f / Math.fma(this.x, this.x, Math.fma(this.y, this.y, Math.fma(this.z, this.z, this.w * this.w))); - float qx = this.x * n, qy = this.y * n, qz = this.z * n, qw = this.w * n; - float xx = qx * qx, yy = qy * qy, zz = qz * qz, ww = qw * qw; - float xy = qx * qy, xz = qx * qz, yz = qy * qz, xw = qx * qw; - float zw = qz * qw, yw = qy * qw, k = 1 / (xx + yy + zz + ww); - return dest.set(Math.fma((xx - yy - zz + ww) * k, x, Math.fma(2 * (xy + zw) * k, y, (2 * (xz - yw) * k) * z)), - Math.fma(2 * (xy - zw) * k, x, Math.fma((yy - xx - zz + ww) * k, y, (2 * (yz + xw) * k) * z)), - Math.fma(2 * (xz + yw) * k, x, Math.fma(2 * (yz - xw) * k, y, ((zz - xx - yy + ww) * k) * z))); - } - - public Vector4f transformUnit(Vector4f vec) { - return transformUnit(vec.x, vec.y, vec.z, vec); - } - - public Vector4f transformInverseUnit(Vector4f vec) { - return transformInverseUnit(vec.x, vec.y, vec.z, vec); - } - - public Vector4f transformUnit(Vector4fc vec, Vector4f dest) { - return transformUnit(vec.x(), vec.y(), vec.z(), dest); - } - - public Vector4f transformInverseUnit(Vector4fc vec, Vector4f dest) { - return transformInverseUnit(vec.x(), vec.y(), vec.z(), dest); - } - - public Vector4f transformUnit(float x, float y, float z, Vector4f dest) { - float xx = this.x * this.x, xy = this.x * this.y, xz = this.x * this.z; - float xw = this.x * this.w, yy = this.y * this.y, yz = this.y * this.z; - float yw = this.y * this.w, zz = this.z * this.z, zw = this.z * this.w; - return dest.set(Math.fma(Math.fma(-2, yy + zz, 1), x, Math.fma(2 * (xy - zw), y, (2 * (xz + yw)) * z)), - Math.fma(2 * (xy + zw), x, Math.fma(Math.fma(-2, xx + zz, 1), y, (2 * (yz - xw)) * z)), - Math.fma(2 * (xz - yw), x, Math.fma(2 * (yz + xw), y, Math.fma(-2, xx + yy, 1) * z))); - } - - public Vector4f transformInverseUnit(float x, float y, float z, Vector4f dest) { - float xx = this.x * this.x, xy = this.x * this.y, xz = this.x * this.z; - float xw = this.x * this.w, yy = this.y * this.y, yz = this.y * this.z; - float yw = this.y * this.w, zz = this.z * this.z, zw = this.z * this.w; - return dest.set(Math.fma(Math.fma(-2, yy + zz, 1), x, Math.fma(2 * (xy + zw), y, (2 * (xz - yw)) * z)), - Math.fma(2 * (xy - zw), x, Math.fma(Math.fma(-2, xx + zz, 1), y, (2 * (yz + xw)) * z)), - Math.fma(2 * (xz + yw), x, Math.fma(2 * (yz - xw), y, Math.fma(-2, xx + yy, 1) * z))); - } - - public Quaternionf invert(Quaternionf dest) { - float invNorm = 1.0f / Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w))); - dest.x = -x * invNorm; - dest.y = -y * invNorm; - dest.z = -z * invNorm; - dest.w = w * invNorm; - return dest; - } - - /** - * Invert this quaternion and {@link #normalize() normalize} it. - *

- * If this quaternion is already normalized, then {@link #conjugate()} should be used instead. - * - * @see #conjugate() - * - * @return this - */ - public Quaternionf invert() { - return invert(this); - } - - public Quaternionf div(Quaternionfc b, Quaternionf dest) { - float invNorm = 1.0f / Math.fma(b.x(), b.x(), Math.fma(b.y(), b.y(), Math.fma(b.z(), b.z(), b.w() * b.w()))); - float x = -b.x() * invNorm; - float y = -b.y() * invNorm; - float z = -b.z() * invNorm; - float w = b.w() * invNorm; - return dest.set(Math.fma(this.w, x, Math.fma(this.x, w, Math.fma(this.y, z, -this.z * y))), - Math.fma(this.w, y, Math.fma(-this.x, z, Math.fma(this.y, w, this.z * x))), - Math.fma(this.w, z, Math.fma(this.x, y, Math.fma(-this.y, x, this.z * w))), - Math.fma(this.w, w, Math.fma(-this.x, x, Math.fma(-this.y, y, -this.z * z)))); - } - - /** - * Divide this quaternion by b. - *

- * The division expressed using the inverse is performed in the following way: - *

- * this = this * b^-1, where b^-1 is the inverse of b. - * - * @param b - * the {@link Quaternionf} to divide this by - * @return this - */ - public Quaternionf div(Quaternionfc b) { - return div(b, this); - } - - /** - * Conjugate this quaternion. - * - * @return this - */ - public Quaternionf conjugate() { - return conjugate(this); - } - - public Quaternionf conjugate(Quaternionf dest) { - dest.x = -x; - dest.y = -y; - dest.z = -z; - dest.w = w; - return dest; - } - - /** - * Set this quaternion to the identity. - * - * @return this - */ - public Quaternionf identity() { - x = 0; - y = 0; - z = 0; - w = 1; - return this; - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the cartesian base unit axes, - * called the euler angles using rotation sequence XYZ. - *

- * This method is equivalent to calling: rotateX(angleX).rotateY(angleY).rotateZ(angleZ) - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angleX - * the angle in radians to rotate about the x axis - * @param angleY - * the angle in radians to rotate about the y axis - * @param angleZ - * the angle in radians to rotate about the z axis - * @return this - */ - public Quaternionf rotateXYZ(float angleX, float angleY, float angleZ) { - return rotateXYZ(angleX, angleY, angleZ, this); - } - - public Quaternionf rotateXYZ(float angleX, float angleY, float angleZ, Quaternionf dest) { - float sx = Math.sin(angleX * 0.5f); - float cx = Math.cosFromSin(sx, angleX * 0.5f); - float sy = Math.sin(angleY * 0.5f); - float cy = Math.cosFromSin(sy, angleY * 0.5f); - float sz = Math.sin(angleZ * 0.5f); - float cz = Math.cosFromSin(sz, angleZ * 0.5f); - - float cycz = cy * cz; - float sysz = sy * sz; - float sycz = sy * cz; - float cysz = cy * sz; - float w = cx*cycz - sx*sysz; - float x = sx*cycz + cx*sysz; - float y = cx*sycz - sx*cysz; - float z = cx*cysz + sx*sycz; - // right-multiply - return dest.set(Math.fma(this.w, x, Math.fma(this.x, w, Math.fma(this.y, z, -this.z * y))), - Math.fma(this.w, y, Math.fma(-this.x, z, Math.fma(this.y, w, this.z * x))), - Math.fma(this.w, z, Math.fma(this.x, y, Math.fma(-this.y, x, this.z * w))), - Math.fma(this.w, w, Math.fma(-this.x, x, Math.fma(-this.y, y, -this.z * z)))); - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the cartesian base unit axes, - * called the euler angles, using the rotation sequence ZYX. - *

- * This method is equivalent to calling: rotateZ(angleZ).rotateY(angleY).rotateX(angleX) - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angleZ - * the angle in radians to rotate about the z axis - * @param angleY - * the angle in radians to rotate about the y axis - * @param angleX - * the angle in radians to rotate about the x axis - * @return this - */ - public Quaternionf rotateZYX(float angleZ, float angleY, float angleX) { - return rotateZYX(angleZ, angleY, angleX, this); - } - - public Quaternionf rotateZYX(float angleZ, float angleY, float angleX, Quaternionf dest) { - float sx = Math.sin(angleX * 0.5f); - float cx = Math.cosFromSin(sx, angleX * 0.5f); - float sy = Math.sin(angleY * 0.5f); - float cy = Math.cosFromSin(sy, angleY * 0.5f); - float sz = Math.sin(angleZ * 0.5f); - float cz = Math.cosFromSin(sz, angleZ * 0.5f); - - float cycz = cy * cz; - float sysz = sy * sz; - float sycz = sy * cz; - float cysz = cy * sz; - float w = cx*cycz + sx*sysz; - float x = sx*cycz - cx*sysz; - float y = cx*sycz + sx*cysz; - float z = cx*cysz - sx*sycz; - // right-multiply - return dest.set(Math.fma(this.w, x, Math.fma(this.x, w, Math.fma(this.y, z, -this.z * y))), - Math.fma(this.w, y, Math.fma(-this.x, z, Math.fma(this.y, w, this.z * x))), - Math.fma(this.w, z, Math.fma(this.x, y, Math.fma(-this.y, x, this.z * w))), - Math.fma(this.w, w, Math.fma(-this.x, x, Math.fma(-this.y, y, -this.z * z)))); - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the cartesian base unit axes, - * called the euler angles, using the rotation sequence YXZ. - *

- * This method is equivalent to calling: rotateY(angleY).rotateX(angleX).rotateZ(angleZ) - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angleY - * the angle in radians to rotate about the y axis - * @param angleX - * the angle in radians to rotate about the x axis - * @param angleZ - * the angle in radians to rotate about the z axis - * @return this - */ - public Quaternionf rotateYXZ(float angleY, float angleX, float angleZ) { - return rotateYXZ(angleY, angleX, angleZ, this); - } - - public Quaternionf rotateYXZ(float angleY, float angleX, float angleZ, Quaternionf dest) { - float sx = Math.sin(angleX * 0.5f); - float cx = Math.cosFromSin(sx, angleX * 0.5f); - float sy = Math.sin(angleY * 0.5f); - float cy = Math.cosFromSin(sy, angleY * 0.5f); - float sz = Math.sin(angleZ * 0.5f); - float cz = Math.cosFromSin(sz, angleZ * 0.5f); - - float yx = cy * sx; - float yy = sy * cx; - float yz = sy * sx; - float yw = cy * cx; - float x = yx * cz + yy * sz; - float y = yy * cz - yx * sz; - float z = yw * sz - yz * cz; - float w = yw * cz + yz * sz; - // right-multiply - return dest.set(Math.fma(this.w, x, Math.fma(this.x, w, Math.fma(this.y, z, -this.z * y))), - Math.fma(this.w, y, Math.fma(-this.x, z, Math.fma(this.y, w, this.z * x))), - Math.fma(this.w, z, Math.fma(this.x, y, Math.fma(-this.y, x, this.z * w))), - Math.fma(this.w, w, Math.fma(-this.x, x, Math.fma(-this.y, y, -this.z * z)))); - } - - public Vector3f getEulerAnglesXYZ(Vector3f eulerAngles) { - eulerAngles.x = Math.atan2(x * w - y * z, 0.5f - x * x - y * y); - eulerAngles.y = Math.safeAsin(2.0f * (x * z + y * w)); - eulerAngles.z = Math.atan2(z * w - x * y, 0.5f - y * y - z * z); - return eulerAngles; - } - - public Vector3f getEulerAnglesZYX(Vector3f eulerAngles) { - eulerAngles.x = Math.atan2(y * z + w * x, 0.5f - x * x + y * y); - eulerAngles.y = Math.safeAsin(-2.0f * (x * z - w * y)); - eulerAngles.z = Math.atan2(x * y + w * z, 0.5f - y * y - z * z); - return eulerAngles; - } - - public Vector3f getEulerAnglesZXY(Vector3f eulerAngles) { - eulerAngles.x = Math.safeAsin(2.0f * (w * x + y * z)); - eulerAngles.y = Math.atan2(w * y - x * z, 0.5f - y * y - x * x); - eulerAngles.z = Math.atan2(w * z - x * y, 0.5f - z * z - x * x); - return eulerAngles; - } - - public Vector3f getEulerAnglesYXZ(Vector3f eulerAngles) { - eulerAngles.x = Math.safeAsin(-2.0f * (y * z - w * x)); - eulerAngles.y = Math.atan2(x * z + y * w, 0.5f - y * y - x * x); - eulerAngles.z = Math.atan2(y * x + w * z, 0.5f - x * x - z * z); - return eulerAngles; - } - - public float lengthSquared() { - return Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w))); - } - - /** - * Set this quaternion from the supplied euler angles (in radians) with rotation order XYZ. - *

- * This method is equivalent to calling: rotationX(angleX).rotateY(angleY).rotateZ(angleZ) - *

- * Reference: this stackexchange answer - * - * @param angleX - * the angle in radians to rotate about x - * @param angleY - * the angle in radians to rotate about y - * @param angleZ - * the angle in radians to rotate about z - * @return this - */ - public Quaternionf rotationXYZ(float angleX, float angleY, float angleZ) { - float sx = Math.sin(angleX * 0.5f); - float cx = Math.cosFromSin(sx, angleX * 0.5f); - float sy = Math.sin(angleY * 0.5f); - float cy = Math.cosFromSin(sy, angleY * 0.5f); - float sz = Math.sin(angleZ * 0.5f); - float cz = Math.cosFromSin(sz, angleZ * 0.5f); - - float cycz = cy * cz; - float sysz = sy * sz; - float sycz = sy * cz; - float cysz = cy * sz; - w = cx*cycz - sx*sysz; - x = sx*cycz + cx*sysz; - y = cx*sycz - sx*cysz; - z = cx*cysz + sx*sycz; - - return this; - } - - /** - * Set this quaternion from the supplied euler angles (in radians) with rotation order ZYX. - *

- * This method is equivalent to calling: rotationZ(angleZ).rotateY(angleY).rotateX(angleX) - *

- * Reference: this stackexchange answer - * - * @param angleX - * the angle in radians to rotate about x - * @param angleY - * the angle in radians to rotate about y - * @param angleZ - * the angle in radians to rotate about z - * @return this - */ - public Quaternionf rotationZYX(float angleZ, float angleY, float angleX) { - float sx = Math.sin(angleX * 0.5f); - float cx = Math.cosFromSin(sx, angleX * 0.5f); - float sy = Math.sin(angleY * 0.5f); - float cy = Math.cosFromSin(sy, angleY * 0.5f); - float sz = Math.sin(angleZ * 0.5f); - float cz = Math.cosFromSin(sz, angleZ * 0.5f); - - float cycz = cy * cz; - float sysz = sy * sz; - float sycz = sy * cz; - float cysz = cy * sz; - w = cx*cycz + sx*sysz; - x = sx*cycz - cx*sysz; - y = cx*sycz + sx*cysz; - z = cx*cysz - sx*sycz; - - return this; - } - - /** - * Set this quaternion from the supplied euler angles (in radians) with rotation order YXZ. - *

- * This method is equivalent to calling: rotationY(angleY).rotateX(angleX).rotateZ(angleZ) - *

- * Reference: https://en.wikipedia.org - * - * @param angleY - * the angle in radians to rotate about y - * @param angleX - * the angle in radians to rotate about x - * @param angleZ - * the angle in radians to rotate about z - * @return this - */ - public Quaternionf rotationYXZ(float angleY, float angleX, float angleZ) { - float sx = Math.sin(angleX * 0.5f); - float cx = Math.cosFromSin(sx, angleX * 0.5f); - float sy = Math.sin(angleY * 0.5f); - float cy = Math.cosFromSin(sy, angleY * 0.5f); - float sz = Math.sin(angleZ * 0.5f); - float cz = Math.cosFromSin(sz, angleZ * 0.5f); - - float x = cy * sx; - float y = sy * cx; - float z = sy * sx; - float w = cy * cx; - this.x = x * cz + y * sz; - this.y = y * cz - x * sz; - this.z = w * sz - z * cz; - this.w = w * cz + z * sz; - - return this; - } - - /** - * Interpolate between this {@link #normalize() unit} quaternion and the specified - * target {@link #normalize() unit} quaternion using spherical linear interpolation using the specified interpolation factor alpha. - *

- * This method resorts to non-spherical linear interpolation when the absolute dot product of this and target is - * below 1E-6f. - * - * @param target - * the target of the interpolation, which should be reached with alpha = 1.0 - * @param alpha - * the interpolation factor, within [0..1] - * @return this - */ - public Quaternionf slerp(Quaternionfc target, float alpha) { - return slerp(target, alpha, this); - } - - public Quaternionf slerp(Quaternionfc target, float alpha, Quaternionf dest) { - float cosom = Math.fma(x, target.x(), Math.fma(y, target.y(), Math.fma(z, target.z(), w * target.w()))); - float absCosom = Math.abs(cosom); - float scale0, scale1; - if (1.0f - absCosom > 1E-6f) { - float sinSqr = 1.0f - absCosom * absCosom; - float sinom = Math.invsqrt(sinSqr); - float omega = Math.atan2(sinSqr * sinom, absCosom); - scale0 = (float) (Math.sin((1.0 - alpha) * omega) * sinom); - scale1 = (float) (Math.sin(alpha * omega) * sinom); - } else { - scale0 = 1.0f - alpha; - scale1 = alpha; - } - scale1 = cosom >= 0.0f ? scale1 : -scale1; - dest.x = Math.fma(scale0, x, scale1 * target.x()); - dest.y = Math.fma(scale0, y, scale1 * target.y()); - dest.z = Math.fma(scale0, z, scale1 * target.z()); - dest.w = Math.fma(scale0, w, scale1 * target.w()); - return dest; - } - - /** - * Interpolate between all of the quaternions given in qs via spherical linear interpolation using the specified interpolation factors weights, - * and store the result in dest. - *

- * This method will interpolate between each two successive quaternions via {@link #slerp(Quaternionfc, float)} using their relative interpolation weights. - *

- * This method resorts to non-spherical linear interpolation when the absolute dot product of any two interpolated quaternions is below 1E-6f. - *

- * Reference: http://gamedev.stackexchange.com/ - * - * @param qs - * the quaternions to interpolate over - * @param weights - * the weights of each individual quaternion in qs - * @param dest - * will hold the result - * @return dest - */ - public static Quaternionfc slerp(Quaternionf[] qs, float[] weights, Quaternionf dest) { - dest.set(qs[0]); - float w = weights[0]; - for (int i = 1; i < qs.length; i++) { - float w0 = w; - float w1 = weights[i]; - float rw1 = w1 / (w0 + w1); - w += w1; - dest.slerp(qs[i], rw1); - } - return dest; - } - - /** - * Apply scaling to this quaternion, which results in any vector transformed by this quaternion to change - * its length by the given factor. - * - * @param factor - * the scaling factor - * @return this - */ - public Quaternionf scale(float factor) { - return scale(factor, this); - } - - public Quaternionf scale(float factor, Quaternionf dest) { - float sqrt = Math.sqrt(factor); - dest.x = sqrt * x; - dest.y = sqrt * y; - dest.z = sqrt * z; - dest.w = sqrt * w; - return dest; - } - - /** - * Set this quaternion to represent scaling, which results in a transformed vector to change - * its length by the given factor. - * - * @param factor - * the scaling factor - * @return this - */ - public Quaternionf scaling(float factor) { - float sqrt = Math.sqrt(factor); - this.x = 0.0f; - this.y = 0.0f; - this.z = 0.0f; - this.w = sqrt; - return this; - } - - /** - * Integrate the rotation given by the angular velocity (vx, vy, vz) around the x, y and z axis, respectively, - * with respect to the given elapsed time delta dt and add the differentiate rotation to the rotation represented by this quaternion. - *

- * This method pre-multiplies the rotation given by dt and (vx, vy, vz) by this, so - * the angular velocities are always relative to the local coordinate system of the rotation represented by this quaternion. - *

- * This method is equivalent to calling: rotateLocal(dt * vx, dt * vy, dt * vz) - *

- * Reference: http://physicsforgames.blogspot.de/ - * - * @param dt - * the delta time - * @param vx - * the angular velocity around the x axis - * @param vy - * the angular velocity around the y axis - * @param vz - * the angular velocity around the z axis - * @return this - */ - public Quaternionf integrate(float dt, float vx, float vy, float vz) { - return integrate(dt, vx, vy, vz, this); - } - - public Quaternionf integrate(float dt, float vx, float vy, float vz, Quaternionf dest) { - float thetaX = dt * vx * 0.5f; - float thetaY = dt * vy * 0.5f; - float thetaZ = dt * vz * 0.5f; - float thetaMagSq = thetaX * thetaX + thetaY * thetaY + thetaZ * thetaZ; - float s; - float dqX, dqY, dqZ, dqW; - if (thetaMagSq * thetaMagSq / 24.0f < 1E-8f) { - dqW = 1.0f - thetaMagSq * 0.5f; - s = 1.0f - thetaMagSq / 6.0f; - } else { - float thetaMag = Math.sqrt(thetaMagSq); - float sin = Math.sin(thetaMag); - s = sin / thetaMag; - dqW = Math.cosFromSin(sin, thetaMag); - } - dqX = thetaX * s; - dqY = thetaY * s; - dqZ = thetaZ * s; - /* Pre-multiplication */ - return dest.set(Math.fma(dqW, x, Math.fma(dqX, w, Math.fma(dqY, z, -dqZ * y))), - Math.fma(dqW, y, Math.fma(-dqX, z, Math.fma(dqY, w, dqZ * x))), - Math.fma(dqW, z, Math.fma(dqX, y, Math.fma(-dqY, x, dqZ * w))), - Math.fma(dqW, w, Math.fma(-dqX, x, Math.fma(-dqY, y, -dqZ * z)))); - } - - /** - * Compute a linear (non-spherical) interpolation of this and the given quaternion q - * and store the result in this. - * - * @param q - * the other quaternion - * @param factor - * the interpolation factor. It is between 0.0 and 1.0 - * @return this - */ - public Quaternionf nlerp(Quaternionfc q, float factor) { - return nlerp(q, factor, this); - } - - public Quaternionf nlerp(Quaternionfc q, float factor, Quaternionf dest) { - float cosom = Math.fma(x, q.x(), Math.fma(y, q.y(), Math.fma(z, q.z(), w * q.w()))); - float scale0 = 1.0f - factor; - float scale1 = (cosom >= 0.0f) ? factor : -factor; - dest.x = Math.fma(scale0, x, scale1 * q.x()); - dest.y = Math.fma(scale0, y, scale1 * q.y()); - dest.z = Math.fma(scale0, z, scale1 * q.z()); - dest.w = Math.fma(scale0, w, scale1 * q.w()); - float s = Math.invsqrt(Math.fma(dest.x, dest.x, Math.fma(dest.y, dest.y, Math.fma(dest.z, dest.z, dest.w * dest.w)))); - dest.x *= s; - dest.y *= s; - dest.z *= s; - dest.w *= s; - return dest; - } - - /** - * Interpolate between all of the quaternions given in qs via non-spherical linear interpolation using the - * specified interpolation factors weights, and store the result in dest. - *

- * This method will interpolate between each two successive quaternions via {@link #nlerp(Quaternionfc, float)} - * using their relative interpolation weights. - *

- * Reference: http://gamedev.stackexchange.com/ - * - * @param qs - * the quaternions to interpolate over - * @param weights - * the weights of each individual quaternion in qs - * @param dest - * will hold the result - * @return dest - */ - public static Quaternionfc nlerp(Quaternionfc[] qs, float[] weights, Quaternionf dest) { - dest.set(qs[0]); - float w = weights[0]; - for (int i = 1; i < qs.length; i++) { - float w0 = w; - float w1 = weights[i]; - float rw1 = w1 / (w0 + w1); - w += w1; - dest.nlerp(qs[i], rw1); - } - return dest; - } - - public Quaternionf nlerpIterative(Quaternionfc q, float alpha, float dotThreshold, Quaternionf dest) { - float q1x = x, q1y = y, q1z = z, q1w = w; - float q2x = q.x(), q2y = q.y(), q2z = q.z(), q2w = q.w(); - float dot = Math.fma(q1x, q2x, Math.fma(q1y, q2y, Math.fma(q1z, q2z, q1w * q2w))); - float absDot = Math.abs(dot); - if (1.0f - 1E-6f < absDot) { - return dest.set(this); - } - float alphaN = alpha; - while (absDot < dotThreshold) { - float scale0 = 0.5f; - float scale1 = dot >= 0.0f ? 0.5f : -0.5f; - if (alphaN < 0.5f) { - q2x = Math.fma(scale0, q2x, scale1 * q1x); - q2y = Math.fma(scale0, q2y, scale1 * q1y); - q2z = Math.fma(scale0, q2z, scale1 * q1z); - q2w = Math.fma(scale0, q2w, scale1 * q1w); - float s = Math.invsqrt(Math.fma(q2x, q2x, Math.fma(q2y, q2y, Math.fma(q2z, q2z, q2w * q2w)))); - q2x *= s; - q2y *= s; - q2z *= s; - q2w *= s; - alphaN = alphaN + alphaN; - } else { - q1x = Math.fma(scale0, q1x, scale1 * q2x); - q1y = Math.fma(scale0, q1y, scale1 * q2y); - q1z = Math.fma(scale0, q1z, scale1 * q2z); - q1w = Math.fma(scale0, q1w, scale1 * q2w); - float s = Math.invsqrt(Math.fma(q1x, q1x, Math.fma(q1y, q1y, Math.fma(q1z, q1z, q1w * q1w)))); - q1x *= s; - q1y *= s; - q1z *= s; - q1w *= s; - alphaN = alphaN + alphaN - 1.0f; - } - dot = Math.fma(q1x, q2x, Math.fma(q1y, q2y, Math.fma(q1z, q2z, q1w * q2w))); - absDot = Math.abs(dot); - } - float scale0 = 1.0f - alphaN; - float scale1 = dot >= 0.0f ? alphaN : -alphaN; - float resX = Math.fma(scale0, q1x, scale1 * q2x); - float resY = Math.fma(scale0, q1y, scale1 * q2y); - float resZ = Math.fma(scale0, q1z, scale1 * q2z); - float resW = Math.fma(scale0, q1w, scale1 * q2w); - float s = Math.invsqrt(Math.fma(resX, resX, Math.fma(resY, resY, Math.fma(resZ, resZ, resW * resW)))); - dest.x = resX * s; - dest.y = resY * s; - dest.z = resZ * s; - dest.w = resW * s; - return dest; - } - - /** - * Compute linear (non-spherical) interpolations of this and the given quaternion q - * iteratively and store the result in this. - *

- * This method performs a series of small-step nlerp interpolations to avoid doing a costly spherical linear interpolation, like - * {@link #slerp(Quaternionfc, float, Quaternionf) slerp}, - * by subdividing the rotation arc between this and q via non-spherical linear interpolations as long as - * the absolute dot product of this and q is greater than the given dotThreshold parameter. - *

- * Thanks to @theagentd at http://www.java-gaming.org/ for providing the code. - * - * @param q - * the other quaternion - * @param alpha - * the interpolation factor, between 0.0 and 1.0 - * @param dotThreshold - * the threshold for the dot product of this and q above which this method performs another iteration - * of a small-step linear interpolation - * @return this - */ - public Quaternionf nlerpIterative(Quaternionfc q, float alpha, float dotThreshold) { - return nlerpIterative(q, alpha, dotThreshold, this); - } - - /** - * Interpolate between all of the quaternions given in qs via iterative non-spherical linear interpolation using the - * specified interpolation factors weights, and store the result in dest. - *

- * This method will interpolate between each two successive quaternions via {@link #nlerpIterative(Quaternionfc, float, float)} - * using their relative interpolation weights. - *

- * Reference: http://gamedev.stackexchange.com/ - * - * @param qs - * the quaternions to interpolate over - * @param weights - * the weights of each individual quaternion in qs - * @param dotThreshold - * the threshold for the dot product of each two interpolated quaternions above which {@link #nlerpIterative(Quaternionfc, float, float)} performs another iteration - * of a small-step linear interpolation - * @param dest - * will hold the result - * @return dest - */ - public static Quaternionfc nlerpIterative(Quaternionf[] qs, float[] weights, float dotThreshold, Quaternionf dest) { - dest.set(qs[0]); - float w = weights[0]; - for (int i = 1; i < qs.length; i++) { - float w0 = w; - float w1 = weights[i]; - float rw1 = w1 / (w0 + w1); - w += w1; - dest.nlerpIterative(qs[i], rw1, dotThreshold); - } - return dest; - } - - /** - * Apply a rotation to this quaternion that maps the given direction to the positive Z axis. - *

- * Because there are multiple possibilities for such a rotation, this method will choose the one that ensures the given up direction to remain - * parallel to the plane spanned by the up and dir vectors. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - *

- * Reference: http://answers.unity3d.com - * - * @see #lookAlong(float, float, float, float, float, float, Quaternionf) - * - * @param dir - * the direction to map to the positive Z axis - * @param up - * the vector which will be mapped to a vector parallel to the plane - * spanned by the given dir and up - * @return this - */ - public Quaternionf lookAlong(Vector3fc dir, Vector3fc up) { - return lookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z(), this); - } - - public Quaternionf lookAlong(Vector3fc dir, Vector3fc up, Quaternionf dest) { - return lookAlong(dir.x(), dir.y(), dir.z(), up.x(), up.y(), up.z(), dest); - } - - /** - * Apply a rotation to this quaternion that maps the given direction to the positive Z axis. - *

- * Because there are multiple possibilities for such a rotation, this method will choose the one that ensures the given up direction to remain - * parallel to the plane spanned by the up and dir vectors. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - *

- * Reference: http://answers.unity3d.com - * - * @see #lookAlong(float, float, float, float, float, float, Quaternionf) - * - * @param dirX - * the x-coordinate of the direction to look along - * @param dirY - * the y-coordinate of the direction to look along - * @param dirZ - * the z-coordinate of the direction to look along - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @return this - */ - public Quaternionf lookAlong(float dirX, float dirY, float dirZ, float upX, float upY, float upZ) { - return lookAlong(dirX, dirY, dirZ, upX, upY, upZ, this); - } - - public Quaternionf lookAlong(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Quaternionf dest) { - // Normalize direction - float invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); - float dirnX = -dirX * invDirLength; - float dirnY = -dirY * invDirLength; - float dirnZ = -dirZ * invDirLength; - // left = up x dir - float leftX, leftY, leftZ; - leftX = upY * dirnZ - upZ * dirnY; - leftY = upZ * dirnX - upX * dirnZ; - leftZ = upX * dirnY - upY * dirnX; - // normalize left - float invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); - leftX *= invLeftLength; - leftY *= invLeftLength; - leftZ *= invLeftLength; - // up = direction x left - float upnX = dirnY * leftZ - dirnZ * leftY; - float upnY = dirnZ * leftX - dirnX * leftZ; - float upnZ = dirnX * leftY - dirnY * leftX; - - /* Convert orthonormal basis vectors to quaternion */ - float x, y, z, w; - double t; - double tr = leftX + upnY + dirnZ; - if (tr >= 0.0) { - t = Math.sqrt(tr + 1.0); - w = (float) (t * 0.5); - t = 0.5 / t; - x = (float) ((dirnY - upnZ) * t); - y = (float) ((leftZ - dirnX) * t); - z = (float) ((upnX - leftY) * t); - } else { - if (leftX > upnY && leftX > dirnZ) { - t = Math.sqrt(1.0 + leftX - upnY - dirnZ); - x = (float) (t * 0.5); - t = 0.5 / t; - y = (float) ((leftY + upnX) * t); - z = (float) ((dirnX + leftZ) * t); - w = (float) ((dirnY - upnZ) * t); - } else if (upnY > dirnZ) { - t = Math.sqrt(1.0 + upnY - leftX - dirnZ); - y = (float) (t * 0.5); - t = 0.5 / t; - x = (float) ((leftY + upnX) * t); - z = (float) ((upnZ + dirnY) * t); - w = (float) ((leftZ - dirnX) * t); - } else { - t = Math.sqrt(1.0 + dirnZ - leftX - upnY); - z = (float) (t * 0.5); - t = 0.5 / t; - x = (float) ((dirnX + leftZ) * t); - y = (float) ((upnZ + dirnY) * t); - w = (float) ((upnX - leftY) * t); - } - } - /* Multiply */ - return dest.set(Math.fma(this.w, x, Math.fma(this.x, w, Math.fma(this.y, z, -this.z * y))), - Math.fma(this.w, y, Math.fma(-this.x, z, Math.fma(this.y, w, this.z * x))), - Math.fma(this.w, z, Math.fma(this.x, y, Math.fma(-this.y, x, this.z * w))), - Math.fma(this.w, w, Math.fma(-this.x, x, Math.fma(-this.y, y, -this.z * z)))); - } - - /** - * Set this quaternion to a rotation that rotates the fromDir vector to point along toDir. - *

- * Since there can be multiple possible rotations, this method chooses the one with the shortest arc. - *

- * Reference: stackoverflow.com - * - * @param fromDirX - * the x-coordinate of the direction to rotate into the destination direction - * @param fromDirY - * the y-coordinate of the direction to rotate into the destination direction - * @param fromDirZ - * the z-coordinate of the direction to rotate into the destination direction - * @param toDirX - * the x-coordinate of the direction to rotate to - * @param toDirY - * the y-coordinate of the direction to rotate to - * @param toDirZ - * the z-coordinate of the direction to rotate to - * @return this - */ - public Quaternionf rotationTo(float fromDirX, float fromDirY, float fromDirZ, float toDirX, float toDirY, float toDirZ) { - float fn = Math.invsqrt(Math.fma(fromDirX, fromDirX, Math.fma(fromDirY, fromDirY, fromDirZ * fromDirZ))); - float tn = Math.invsqrt(Math.fma(toDirX, toDirX, Math.fma(toDirY, toDirY, toDirZ * toDirZ))); - float fx = fromDirX * fn, fy = fromDirY * fn, fz = fromDirZ * fn; - float tx = toDirX * tn, ty = toDirY * tn, tz = toDirZ * tn; - float dot = fx * tx + fy * ty + fz * tz; - float x, y, z, w; - if (dot < -1.0f + 1E-6f) { - x = fy; - y = -fx; - z = 0.0f; - w = 0.0f; - if (x * x + y * y == 0.0f) { - x = 0.0f; - y = fz; - z = -fy; - w = 0.0f; - } - this.x = x; - this.y = y; - this.z = z; - this.w = 0; - } else { - float sd2 = Math.sqrt((1.0f + dot) * 2.0f); - float isd2 = 1.0f / sd2; - float cx = fy * tz - fz * ty; - float cy = fz * tx - fx * tz; - float cz = fx * ty - fy * tx; - x = cx * isd2; - y = cy * isd2; - z = cz * isd2; - w = sd2 * 0.5f; - float n2 = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w)))); - this.x = x * n2; - this.y = y * n2; - this.z = z * n2; - this.w = w * n2; - } - return this; - } - - /** - * Set this quaternion to a rotation that rotates the fromDir vector to point along toDir. - *

- * Because there can be multiple possible rotations, this method chooses the one with the shortest arc. - * - * @see #rotationTo(float, float, float, float, float, float) - * - * @param fromDir - * the starting direction - * @param toDir - * the destination direction - * @return this - */ - public Quaternionf rotationTo(Vector3fc fromDir, Vector3fc toDir) { - return rotationTo(fromDir.x(), fromDir.y(), fromDir.z(), toDir.x(), toDir.y(), toDir.z()); - } - - public Quaternionf rotateTo(float fromDirX, float fromDirY, float fromDirZ, float toDirX, float toDirY, float toDirZ, Quaternionf dest) { - float fn = Math.invsqrt(Math.fma(fromDirX, fromDirX, Math.fma(fromDirY, fromDirY, fromDirZ * fromDirZ))); - float tn = Math.invsqrt(Math.fma(toDirX, toDirX, Math.fma(toDirY, toDirY, toDirZ * toDirZ))); - float fx = fromDirX * fn, fy = fromDirY * fn, fz = fromDirZ * fn; - float tx = toDirX * tn, ty = toDirY * tn, tz = toDirZ * tn; - float dot = fx * tx + fy * ty + fz * tz; - float x, y, z, w; - if (dot < -1.0f + 1E-6f) { - x = fy; - y = -fx; - z = 0.0f; - w = 0.0f; - if (x * x + y * y == 0.0f) { - x = 0.0f; - y = fz; - z = -fy; - w = 0.0f; - } - } else { - float sd2 = Math.sqrt((1.0f + dot) * 2.0f); - float isd2 = 1.0f / sd2; - float cx = fy * tz - fz * ty; - float cy = fz * tx - fx * tz; - float cz = fx * ty - fy * tx; - x = cx * isd2; - y = cy * isd2; - z = cz * isd2; - w = sd2 * 0.5f; - float n2 = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w)))); - x *= n2; - y *= n2; - z *= n2; - w *= n2; - } - /* Multiply */ - return dest.set(Math.fma(this.w, x, Math.fma(this.x, w, Math.fma(this.y, z, -this.z * y))), - Math.fma(this.w, y, Math.fma(-this.x, z, Math.fma(this.y, w, this.z * x))), - Math.fma(this.w, z, Math.fma(this.x, y, Math.fma(-this.y, x, this.z * w))), - Math.fma(this.w, w, Math.fma(-this.x, x, Math.fma(-this.y, y, -this.z * z)))); - } - - /** - * Apply a rotation to this that rotates the fromDir vector to point along toDir. - *

- * Since there can be multiple possible rotations, this method chooses the one with the shortest arc. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @see #rotateTo(float, float, float, float, float, float, Quaternionf) - * - * @param fromDirX - * the x-coordinate of the direction to rotate into the destination direction - * @param fromDirY - * the y-coordinate of the direction to rotate into the destination direction - * @param fromDirZ - * the z-coordinate of the direction to rotate into the destination direction - * @param toDirX - * the x-coordinate of the direction to rotate to - * @param toDirY - * the y-coordinate of the direction to rotate to - * @param toDirZ - * the z-coordinate of the direction to rotate to - * @return this - */ - public Quaternionf rotateTo(float fromDirX, float fromDirY, float fromDirZ, float toDirX, float toDirY, float toDirZ) { - return rotateTo(fromDirX, fromDirY, fromDirZ, toDirX, toDirY, toDirZ, this); - } - - public Quaternionf rotateTo(Vector3fc fromDir, Vector3fc toDir, Quaternionf dest) { - return rotateTo(fromDir.x(), fromDir.y(), fromDir.z(), toDir.x(), toDir.y(), toDir.z(), dest); - } - - /** - * Apply a rotation to this that rotates the fromDir vector to point along toDir. - *

- * Because there can be multiple possible rotations, this method chooses the one with the shortest arc. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @see #rotateTo(float, float, float, float, float, float, Quaternionf) - * - * @param fromDir - * the starting direction - * @param toDir - * the destination direction - * @return this - */ - public Quaternionf rotateTo(Vector3fc fromDir, Vector3fc toDir) { - return rotateTo(fromDir.x(), fromDir.y(), fromDir.z(), toDir.x(), toDir.y(), toDir.z(), this); - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the x axis. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angle - * the angle in radians to rotate about the x axis - * @return this - */ - public Quaternionf rotateX(float angle) { - return rotateX(angle, this); - } - - public Quaternionf rotateX(float angle, Quaternionf dest) { - float sin = Math.sin(angle * 0.5f); - float cos = Math.cosFromSin(sin, angle * 0.5f); - return dest.set(w * sin + x * cos, - y * cos + z * sin, - z * cos - y * sin, - w * cos - x * sin); - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the y axis. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angle - * the angle in radians to rotate about the y axis - * @return this - */ - public Quaternionf rotateY(float angle) { - return rotateY(angle, this); - } - - public Quaternionf rotateY(float angle, Quaternionf dest) { - float sin = Math.sin(angle * 0.5f); - float cos = Math.cosFromSin(sin, angle * 0.5f); - return dest.set(x * cos - z * sin, - w * sin + y * cos, - x * sin + z * cos, - w * cos - y * sin); - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the z axis. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angle - * the angle in radians to rotate about the z axis - * @return this - */ - public Quaternionf rotateZ(float angle) { - return rotateZ(angle, this); - } - - public Quaternionf rotateZ(float angle, Quaternionf dest) { - float sin = Math.sin(angle * 0.5f); - float cos = Math.cosFromSin(sin, angle * 0.5f); - return dest.set(x * cos + y * sin, - y * cos - x * sin, - w * sin + z * cos, - w * cos - z * sin); - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the local x axis. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be R * Q. So when transforming a - * vector v with the new quaternion by using R * Q * v, the - * rotation represented by this will be applied first! - * - * @param angle - * the angle in radians to rotate about the local x axis - * @return this - */ - public Quaternionf rotateLocalX(float angle) { - return rotateLocalX(angle, this); - } - - public Quaternionf rotateLocalX(float angle, Quaternionf dest) { - float hangle = angle * 0.5f; - float s = Math.sin(hangle); - float c = Math.cosFromSin(s, hangle); - dest.set(c * x + s * w, - c * y - s * z, - c * z + s * y, - c * w - s * x); - return dest; - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the local y axis. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be R * Q. So when transforming a - * vector v with the new quaternion by using R * Q * v, the - * rotation represented by this will be applied first! - * - * @param angle - * the angle in radians to rotate about the local y axis - * @return this - */ - public Quaternionf rotateLocalY(float angle) { - return rotateLocalY(angle, this); - } - - public Quaternionf rotateLocalY(float angle, Quaternionf dest) { - float hangle = angle * 0.5f; - float s = Math.sin(hangle); - float c = Math.cosFromSin(s, hangle); - dest.set(c * x + s * z, - c * y + s * w, - c * z - s * x, - c * w - s * y); - return dest; - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the local z axis. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be R * Q. So when transforming a - * vector v with the new quaternion by using R * Q * v, the - * rotation represented by this will be applied first! - * - * @param angle - * the angle in radians to rotate about the local z axis - * @return this - */ - public Quaternionf rotateLocalZ(float angle) { - return rotateLocalZ(angle, this); - } - - public Quaternionf rotateLocalZ(float angle, Quaternionf dest) { - float hangle = angle * 0.5f; - float s = Math.sin(hangle); - float c = Math.cosFromSin(s, hangle); - dest.set(c * x - s * y, - c * y + s * x, - c * z + s * w, - c * w - s * z); - return dest; - } - - public Quaternionf rotateAxis(float angle, float axisX, float axisY, float axisZ, Quaternionf dest) { - float hangle = angle / 2.0f; - float sinAngle = Math.sin(hangle); - float invVLength = Math.invsqrt(Math.fma(axisX, axisX, Math.fma(axisY, axisY, axisZ * axisZ))); - float rx = axisX * invVLength * sinAngle; - float ry = axisY * invVLength * sinAngle; - float rz = axisZ * invVLength * sinAngle; - float rw = Math.cosFromSin(sinAngle, hangle); - return dest.set(Math.fma(this.w, rx, Math.fma(this.x, rw, Math.fma(this.y, rz, -this.z * ry))), - Math.fma(this.w, ry, Math.fma(-this.x, rz, Math.fma(this.y, rw, this.z * rx))), - Math.fma(this.w, rz, Math.fma(this.x, ry, Math.fma(-this.y, rx, this.z * rw))), - Math.fma(this.w, rw, Math.fma(-this.x, rx, Math.fma(-this.y, ry, -this.z * rz)))); - } - - public Quaternionf rotateAxis(float angle, Vector3fc axis, Quaternionf dest) { - return rotateAxis(angle, axis.x(), axis.y(), axis.z(), dest); - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the specified axis. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @see #rotateAxis(float, float, float, float, Quaternionf) - * - * @param angle - * the angle in radians to rotate about the specified axis - * @param axis - * the rotation axis - * @return this - */ - public Quaternionf rotateAxis(float angle, Vector3fc axis) { - return rotateAxis(angle, axis.x(), axis.y(), axis.z(), this); - } - - /** - * Apply a rotation to this quaternion rotating the given radians about the specified axis. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @see #rotateAxis(float, float, float, float, Quaternionf) - * - * @param angle - * the angle in radians to rotate about the specified axis - * @param axisX - * the x coordinate of the rotation axis - * @param axisY - * the y coordinate of the rotation axis - * @param axisZ - * the z coordinate of the rotation axis - * @return this - */ - public Quaternionf rotateAxis(float angle, float axisX, float axisY, float axisZ) { - return rotateAxis(angle, axisX, axisY, axisZ, this); - } - - /** - * Return a string representation of this quaternion. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this quaternion by formatting the components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the quaternion 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(w, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(x); - out.writeFloat(y); - out.writeFloat(z); - out.writeFloat(w); - } - - public void readExternal(ObjectInput in) throws IOException, - ClassNotFoundException { - x = in.readFloat(); - y = in.readFloat(); - z = in.readFloat(); - w = in.readFloat(); - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(w); - 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; - Quaternionf other = (Quaternionf) obj; - if (Float.floatToIntBits(w) != Float.floatToIntBits(other.w)) - 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; - } - - /** - * Compute the difference between this and the other quaternion - * and store the result in this. - *

- * The difference is the rotation that has to be applied to get from - * this rotation to other. If T is this, Q - * is other and D is the computed difference, then the following equation holds: - *

- * T * D = Q - *

- * It is defined as: D = T^-1 * Q, where T^-1 denotes the {@link #invert() inverse} of T. - * - * @param other - * the other quaternion - * @return this - */ - public Quaternionf difference(Quaternionf other) { - return difference(other, this); - } - - public Quaternionf difference(Quaternionfc other, Quaternionf dest) { - float invNorm = 1.0f / lengthSquared(); - float x = -this.x * invNorm; - float y = -this.y * invNorm; - float z = -this.z * invNorm; - float w = this.w * invNorm; - dest.set(Math.fma(w, other.x(), Math.fma(x, other.w(), Math.fma(y, other.z(), -z * other.y()))), - Math.fma(w, other.y(), Math.fma(-x, other.z(), Math.fma(y, other.w(), z * other.x()))), - Math.fma(w, other.z(), Math.fma(x, other.y(), Math.fma(-y, other.x(), z * other.w()))), - Math.fma(w, other.w(), Math.fma(-x, other.x(), Math.fma(-y, other.y(), -z * other.z())))); - return dest; - } - - public Vector3f positiveX(Vector3f dir) { - float invNorm = 1.0f / lengthSquared(); - float nx = -x * invNorm; - float ny = -y * invNorm; - float nz = -z * invNorm; - float nw = w * invNorm; - float dy = ny + ny; - float dz = nz + nz; - dir.x = -ny * dy - nz * dz + 1.0f; - dir.y = nx * dy + nw * dz; - dir.z = nx * dz - nw * dy; - return dir; - } - - public Vector3f normalizedPositiveX(Vector3f dir) { - float dy = y + y; - float dz = z + z; - dir.x = -y * dy - z * dz + 1.0f; - dir.y = x * dy - w * dz; - dir.z = x * dz + w * dy; - return dir; - } - - public Vector3f positiveY(Vector3f dir) { - float invNorm = 1.0f / lengthSquared(); - float nx = -x * invNorm; - float ny = -y * invNorm; - float nz = -z * invNorm; - float nw = w * invNorm; - float dx = nx + nx; - float dy = ny + ny; - float dz = nz + nz; - dir.x = nx * dy - nw * dz; - dir.y = -nx * dx - nz * dz + 1.0f; - dir.z = ny * dz + nw * dx; - return dir; - } - - public Vector3f normalizedPositiveY(Vector3f dir) { - float dx = x + x; - float dy = y + y; - float dz = z + z; - dir.x = x * dy + w * dz; - dir.y = -x * dx - z * dz + 1.0f; - dir.z = y * dz - w * dx; - return dir; - } - - public Vector3f positiveZ(Vector3f dir) { - float invNorm = 1.0f / lengthSquared(); - float nx = -x * invNorm; - float ny = -y * invNorm; - float nz = -z * invNorm; - float nw = w * invNorm; - float dx = nx + nx; - float dy = ny + ny; - float dz = nz + nz; - dir.x = nx * dz + nw * dy; - dir.y = ny * dz - nw * dx; - dir.z = -nx * dx - ny * dy + 1.0f; - return dir; - } - - public Vector3f normalizedPositiveZ(Vector3f dir) { - float dx = x + x; - float dy = y + y; - float dz = z + z; - dir.x = x * dz - w * dy; - dir.y = y * dz + w * dx; - dir.z = -x * dx - y * dy + 1.0f; - return dir; - } - - /** - * Conjugate this by the given quaternion q by computing q * this * q^-1. - * - * @param q - * the {@link Quaternionfc} to conjugate this by - * @return this - */ - public Quaternionf conjugateBy(Quaternionfc q) { - return conjugateBy(q, this); - } - - /** - * Conjugate this by the given quaternion q by computing q * this * q^-1 - * and store the result into dest. - * - * @param q - * the {@link Quaternionfc} to conjugate this by - * @param dest - * will hold the result - * @return dest - */ - public Quaternionf conjugateBy(Quaternionfc q, Quaternionf dest) { - float invNorm = 1.0f / q.lengthSquared(); - float qix = -q.x() * invNorm, qiy = -q.y() * invNorm, qiz = -q.z() * invNorm, qiw = q.w() * invNorm; - float qpx = Math.fma(q.w(), x, Math.fma(q.x(), w, Math.fma(q.y(), z, -q.z() * y))); - float qpy = Math.fma(q.w(), y, Math.fma(-q.x(), z, Math.fma(q.y(), w, q.z() * x))); - float qpz = Math.fma(q.w(), z, Math.fma(q.x(), y, Math.fma(-q.y(), x, q.z() * w))); - float qpw = Math.fma(q.w(), w, Math.fma(-q.x(), x, Math.fma(-q.y(), y, -q.z() * z))); - return dest.set(Math.fma(qpw, qix, Math.fma(qpx, qiw, Math.fma(qpy, qiz, -qpz * qiy))), - Math.fma(qpw, qiy, Math.fma(-qpx, qiz, Math.fma(qpy, qiw, qpz * qix))), - Math.fma(qpw, qiz, Math.fma(qpx, qiy, Math.fma(-qpy, qix, qpz * qiw))), - Math.fma(qpw, qiw, Math.fma(-qpx, qix, Math.fma(-qpy, qiy, -qpz * qiz)))); - } - - public boolean isFinite() { - return Math.isFinite(x) && Math.isFinite(y) && Math.isFinite(z) && Math.isFinite(w); - } - - public boolean equals(Quaternionfc q, float delta) { - if (this == q) - return true; - if (q == null) - return false; - if (!(q instanceof Quaternionfc)) - return false; - if (!Runtime.equals(x, q.x(), delta)) - return false; - if (!Runtime.equals(y, q.y(), delta)) - return false; - if (!Runtime.equals(z, q.z(), delta)) - return false; - if (!Runtime.equals(w, q.w(), delta)) - return false; - return true; - } - - public boolean equals(float x, float y, float z, float w) { - if (Float.floatToIntBits(this.x) != Float.floatToIntBits(x)) - return false; - if (Float.floatToIntBits(this.y) != Float.floatToIntBits(y)) - return false; - if (Float.floatToIntBits(this.z) != Float.floatToIntBits(z)) - return false; - if (Float.floatToIntBits(this.w) != Float.floatToIntBits(w)) - return false; - return true; - } - - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/QuaternionfInterpolator.java b/src/main/java/com/jozufozu/flywheel/util/joml/QuaternionfInterpolator.java deleted file mode 100644 index 2fcf2c988..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/QuaternionfInterpolator.java +++ /dev/null @@ -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. - *

- * Instances of this class are not thread-safe. - * - * @author Kai Burjack - */ -public class QuaternionfInterpolator { - - /** - * Performs singular value decomposition on {@link Matrix3f}. - *

- * This code was adapted from http://www.public.iastate.edu/. - * - * @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 qs using the specified interpolation factors weights, and store the result in dest. - * - * @param qs - * the quaternions to interpolate over - * @param weights - * the weights of each individual quaternion in qs - * @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(); - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Quaternionfc.java b/src/main/java/com/jozufozu/flywheel/util/joml/Quaternionfc.java deleted file mode 100644 index 616dc7767..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Quaternionfc.java +++ /dev/null @@ -1,1500 +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; - -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.util.*; - -/** - * Interface to a read-only view of a quaternion of single-precision floats. - * - * @author Kai Burjack - */ -public interface Quaternionfc { - - /** - * @return the first component of the vector part - */ - float x(); - - /** - * @return the second component of the vector part - */ - float y(); - - /** - * @return the third component of the vector part - */ - float z(); - - /** - * @return the real/scalar part of the quaternion - */ - float w(); - - /** - * Normalize this quaternion and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Quaternionf normalize(Quaternionf dest); - - /** - * Add the quaternion (x, y, z, w) to this quaternion and store the result in dest. - * - * @param x - * the x component of the vector part - * @param y - * the y component of the vector part - * @param z - * the z component of the vector part - * @param w - * the real/scalar component - * @param dest - * will hold the result - * @return dest - */ - Quaternionf add(float x, float y, float z, float w, Quaternionf dest); - - /** - * Add q2 to this quaternion and store the result in dest. - * - * @param q2 - * the quaternion to add to this - * @param dest - * will hold the result - * @return dest - */ - Quaternionf add(Quaternionfc q2, Quaternionf dest); - - /** - * Return the angle in radians represented by this normalized quaternion rotation. - *

- * This quaternion must be {@link #normalize(Quaternionf) normalized}. - * - * @return the angle in radians - */ - float angle(); - - /** - * Set the given destination matrix to the rotation represented by this. - * - * @see Matrix3f#set(Quaternionfc) - * - * @param dest - * the matrix to write the rotation into - * @return the passed in destination - */ - Matrix3f get(Matrix3f dest); - - /** - * Set the given destination matrix to the rotation represented by this. - * - * @see Matrix4f#set(Quaternionfc) - * - * @param dest - * the matrix to write the rotation into - * @return the passed in destination - */ - Matrix4f get(Matrix4f dest); - - /** - * Set the given {@link AxisAngle4f} to represent the rotation of - * this quaternion. - * - * @param dest - * the {@link AxisAngle4f} to set - * @return the passed in destination - */ - AxisAngle4f get(AxisAngle4f dest); - - /** - * Set the given {@link Quaternionf} to the values of this. - * - * @param dest - * the {@link Quaternionf} to set - * @return the passed in destination - */ - Quaternionf get(Quaternionf dest); - - /** - * Store the 3x3 float matrix representation of this quaternion in column-major order into the given {@link ByteBuffer}. - *

- * This is equivalent to calling: this.get(new Matrix3f()).get(dest) - * - * @param dest - * the destination buffer - * @return dest - */ - ByteBuffer getAsMatrix3f(ByteBuffer dest); - - /** - * Store the 3x3 float matrix representation of this quaternion in column-major order into the given {@link FloatBuffer}. - *

- * This is equivalent to calling: this.get(new Matrix3f()).get(dest) - * - * @param dest - * the destination buffer - * @return dest - */ - FloatBuffer getAsMatrix3f(FloatBuffer dest); - - /** - * Store the 4x4 float matrix representation of this quaternion in column-major order into the given {@link ByteBuffer}. - *

- * This is equivalent to calling: this.get(new Matrix4f()).get(dest) - * - * @param dest - * the destination buffer - * @return dest - */ - ByteBuffer getAsMatrix4f(ByteBuffer dest); - - /** - * Store the 4x4 float matrix representation of this quaternion in column-major order into the given {@link FloatBuffer}. - *

- * This is equivalent to calling: this.get(new Matrix4f()).get(dest) - * - * @param dest - * the destination buffer - * @return dest - */ - FloatBuffer getAsMatrix4f(FloatBuffer dest); - - /** - * Store the 4x3 float matrix representation of this quaternion in column-major order into the given {@link ByteBuffer}. - *

- * This is equivalent to calling: this.get(new Matrix4x3f()).get(dest) - * - * @param dest - * the destination buffer - * @return dest - */ - ByteBuffer getAsMatrix4x3f(ByteBuffer dest); - - /** - * Store the 4x3 float matrix representation of this quaternion in column-major order into the given {@link FloatBuffer}. - *

- * This is equivalent to calling: this.get(new Matrix4x3f()).get(dest) - * - * @param dest - * the destination buffer - * @return dest - */ - FloatBuffer getAsMatrix4x3f(FloatBuffer dest); - - /** - * Multiply this quaternion by q and store the result in dest. - *

- * If T is this and Q is the given - * quaternion, then the resulting quaternion R is: - *

- * R = T * Q - *

- * So, this method uses post-multiplication like the matrix classes, resulting in a - * vector to be transformed by Q first, and then by T. - * - * @param q - * the quaternion to multiply this by - * @param dest - * will hold the result - * @return dest - */ - Quaternionf mul(Quaternionfc q, Quaternionf dest); - - /** - * Multiply this quaternion by the quaternion represented via (qx, qy, qz, qw) and store the result in dest. - *

- * If T is this and Q is the given - * quaternion, then the resulting quaternion R is: - *

- * R = T * Q - *

- * So, this method uses post-multiplication like the matrix classes, resulting in a - * vector to be transformed by Q first, and then by T. - * - * @param qx - * the x component of the quaternion to multiply this by - * @param qy - * the y component of the quaternion to multiply this by - * @param qz - * the z component of the quaternion to multiply this by - * @param qw - * the w component of the quaternion to multiply this by - * @param dest - * will hold the result - * @return dest - */ - Quaternionf mul(float qx, float qy, float qz, float qw, Quaternionf dest); - - /** - * Pre-multiply this quaternion by q and store the result in dest. - *

- * If T is this and Q is the given quaternion, then the resulting quaternion R is: - *

- * R = Q * T - *

- * So, this method uses pre-multiplication, resulting in a vector to be transformed by T first, and then by Q. - * - * @param q - * the quaternion to pre-multiply this by - * @param dest - * will hold the result - * @return dest - */ - Quaternionf premul(Quaternionfc q, Quaternionf dest); - - /** - * Pre-multiply this quaternion by the quaternion represented via (qx, qy, qz, qw) and store the result in dest. - *

- * If T is this and Q is the given quaternion, then the resulting quaternion R is: - *

- * R = Q * T - *

- * So, this method uses pre-multiplication, resulting in a vector to be transformed by T first, and then by Q. - * - * @param qx - * the x component of the quaternion to multiply this by - * @param qy - * the y component of the quaternion to multiply this by - * @param qz - * the z component of the quaternion to multiply this by - * @param qw - * the w component of the quaternion to multiply this by - * @param dest - * will hold the result - * @return dest - */ - Quaternionf premul(float qx, float qy, float qz, float qw, Quaternionf dest); - - /** - * Transform the given vector by this quaternion. - *

- * This will apply the rotation described by this quaternion to the given vector. - * - * @param vec - * the vector to transform - * @return vec - */ - Vector3f transform(Vector3f vec); - - /** - * Transform the given vector by the inverse of this quaternion. - *

- * This will apply the rotation described by this quaternion to the given vector. - * - * @param vec - * the vector to transform - * @return vec - */ - Vector3f transformInverse(Vector3f vec); - - /** - * Transform the given vector by this unit quaternion. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param vec - * the vector to transform - * @return vec - */ - Vector3f transformUnit(Vector3f vec); - - /** - * Transform the vector (1, 0, 0) by this quaternion. - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformPositiveX(Vector3f dest); - - /** - * Transform the vector (1, 0, 0) by this quaternion. - *

- * Only the first three components of the given 4D vector are modified. - * - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformPositiveX(Vector4f dest); - - /** - * Transform the vector (1, 0, 0) by this unit quaternion. - *

- * This method is only applicable when this is a unit quaternion. - *

- * Reference: https://de.mathworks.com/ - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformUnitPositiveX(Vector3f dest); - - /** - * Transform the vector (1, 0, 0) by this unit quaternion. - *

- * Only the first three components of the given 4D vector are modified. - *

- * This method is only applicable when this is a unit quaternion. - *

- * Reference: https://de.mathworks.com/ - * - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformUnitPositiveX(Vector4f dest); - - /** - * Transform the vector (0, 1, 0) by this quaternion. - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformPositiveY(Vector3f dest); - - /** - * Transform the vector (0, 1, 0) by this quaternion. - *

- * Only the first three components of the given 4D vector are modified. - * - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformPositiveY(Vector4f dest); - - /** - * Transform the vector (0, 1, 0) by this unit quaternion. - *

- * This method is only applicable when this is a unit quaternion. - *

- * Reference: https://de.mathworks.com/ - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformUnitPositiveY(Vector3f dest); - - /** - * Transform the vector (0, 1, 0) by this unit quaternion. - *

- * Only the first three components of the given 4D vector are modified. - *

- * This method is only applicable when this is a unit quaternion. - *

- * Reference: https://de.mathworks.com/ - * - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformUnitPositiveY(Vector4f dest); - - /** - * Transform the vector (0, 0, 1) by this quaternion. - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformPositiveZ(Vector3f dest); - - /** - * Transform the vector (0, 0, 1) by this quaternion. - *

- * Only the first three components of the given 4D vector are modified. - * - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformPositiveZ(Vector4f dest); - - /** - * Transform the vector (0, 0, 1) by this unit quaternion. - *

- * This method is only applicable when this is a unit quaternion. - *

- * Reference: https://de.mathworks.com/ - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformUnitPositiveZ(Vector3f dest); - - /** - * Transform the vector (0, 0, 1) by this unit quaternion. - *

- * Only the first three components of the given 4D vector are modified. - *

- * This method is only applicable when this is a unit quaternion. - *

- * Reference: https://de.mathworks.com/ - * - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformUnitPositiveZ(Vector4f dest); - - /** - * Transform the given vector by this quaternion. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * Only the first three components of the given 4D vector are being used and modified. - * - * @param vec - * the vector to transform - * @return vec - */ - Vector4f transform(Vector4f vec); - - /** - * Transform the given vector by the inverse of this quaternion. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * Only the first three components of the given 4D vector are being used and modified. - * - * @param vec - * the vector to transform - * @return vec - */ - Vector4f transformInverse(Vector4f vec); - - /** - * Transform the given vector by this quaternion - * and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - * - * @param vec - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transform(Vector3fc vec, Vector3f dest); - - /** - * Transform the given vector by the inverse of quaternion - * and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - * - * @param vec - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformInverse(Vector3fc vec, Vector3f dest); - - /** - * Transform the given vector (x, y, z) by this quaternion - * and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transform(float x, float y, float z, Vector3f dest); - - /** - * Transform the given vector (x, y, z) by the inverse of this quaternion - * and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformInverse(float x, float y, float z, Vector3f dest); - - /** - * Transform the given vector by the inverse of this unit quaternion. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param vec - * the vector to transform - * @return vec - */ - Vector3f transformInverseUnit(Vector3f vec); - - /** - * Transform the given vector by this unit quaternion - * and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param vec - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformUnit(Vector3fc vec, Vector3f dest); - - /** - * Transform the given vector by the inverse of this unit quaternion - * and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param vec - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformInverseUnit(Vector3fc vec, Vector3f dest); - - /** - * Transform the given vector (x, y, z) by this unit quaternion - * and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformUnit(float x, float y, float z, Vector3f dest); - - /** - * Transform the given vector (x, y, z) by the inverse of this unit quaternion - * and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector3f transformInverseUnit(float x, float y, float z, Vector3f dest); - - /** - * Transform the given vector by this quaternion and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * Only the first three components of the given 4D vector are being used and set on the destination. - * - * @param vec - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector4f transform(Vector4fc vec, Vector4f dest); - - /** - * Transform the given vector by the inverse of this quaternion and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * Only the first three components of the given 4D vector are being used and set on the destination. - * - * @param vec - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformInverse(Vector4fc vec, Vector4f dest); - - /** - * Transform the given vector (x, y, z) by this quaternion and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector4f transform(float x, float y, float z, Vector4f dest); - - /** - * Transform the given vector (x, y, z) by the inverse of - * this quaternion and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformInverse(float x, float y, float z, Vector4f dest); - - /** - * Transform the given vector by this unit quaternion and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * Only the first three components of the given 4D vector are being used and set on the destination. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param vec - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformUnit(Vector4fc vec, Vector4f dest); - - /** - * Transform the given vector by this unit quaternion. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * Only the first three components of the given 4D vector are being used and set on the destination. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param vec - * the vector to transform - * @return vec - */ - Vector4f transformUnit(Vector4f vec); - - /** - * Transform the given vector by the inverse of this unit quaternion. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * Only the first three components of the given 4D vector are being used and set on the destination. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param vec - * the vector to transform - * @return vec - */ - Vector4f transformInverseUnit(Vector4f vec); - - /** - * Transform the given vector by the inverse of this unit quaternion and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * Only the first three components of the given 4D vector are being used and set on the destination. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param vec - * the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformInverseUnit(Vector4fc vec, Vector4f dest); - - /** - * Transform the given vector (x, y, z) by this unit quaternion and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformUnit(float x, float y, float z, Vector4f dest); - - /** - * Transform the given vector (x, y, z) by the inverse of - * this unit quaternion and store the result in dest. - *

- * This will apply the rotation described by this quaternion to the given vector. - *

- * This method is only applicable when this is a unit quaternion. - * - * @param x - * the x coordinate of the vector to transform - * @param y - * the y coordinate of the vector to transform - * @param z - * the z coordinate of the vector to transform - * @param dest - * will hold the result - * @return dest - */ - Vector4f transformInverseUnit(float x, float y, float z, Vector4f dest); - - /** - * Invert this quaternion and store the {@link #normalize(Quaternionf) normalized} result in dest. - *

- * If this quaternion is already normalized, then {@link #conjugate(Quaternionf)} should be used instead. - * - * @see #conjugate(Quaternionf) - * - * @param dest - * will hold the result - * @return dest - */ - Quaternionf invert(Quaternionf dest); - - /** - * Divide this quaternion by b and store the result in dest. - *

- * The division expressed using the inverse is performed in the following way: - *

- * dest = this * b^-1, where b^-1 is the inverse of b. - * - * @param b - * the {@link Quaternionfc} to divide this by - * @param dest - * will hold the result - * @return dest - */ - Quaternionf div(Quaternionfc b, Quaternionf dest); - - /** - * Conjugate this quaternion and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Quaternionf conjugate(Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the cartesian base unit axes, - * called the euler angles using rotation sequence XYZ and store the result in dest. - *

- * This method is equivalent to calling: rotateX(angleX, dest).rotateY(angleY).rotateZ(angleZ) - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angleX - * the angle in radians to rotate about the x axis - * @param angleY - * the angle in radians to rotate about the y axis - * @param angleZ - * the angle in radians to rotate about the z axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateXYZ(float angleX, float angleY, float angleZ, Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the cartesian base unit axes, - * called the euler angles, using the rotation sequence ZYX and store the result in dest. - *

- * This method is equivalent to calling: rotateZ(angleZ, dest).rotateY(angleY).rotateX(angleX) - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angleZ - * the angle in radians to rotate about the z axis - * @param angleY - * the angle in radians to rotate about the y axis - * @param angleX - * the angle in radians to rotate about the x axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateZYX(float angleZ, float angleY, float angleX, Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the cartesian base unit axes, - * called the euler angles, using the rotation sequence YXZ and store the result in dest. - *

- * This method is equivalent to calling: rotateY(angleY, dest).rotateX(angleX).rotateZ(angleZ) - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angleY - * the angle in radians to rotate about the y axis - * @param angleX - * the angle in radians to rotate about the x axis - * @param angleZ - * the angle in radians to rotate about the z axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateYXZ(float angleY, float angleX, float angleZ, Quaternionf dest); - - /** - * Get the euler angles in radians in rotation sequence XYZ of this quaternion and store them in the - * provided parameter eulerAngles. - *

- * The Euler angles are always returned as the angle around X in the {@link Vector3f#x} field, the angle around Y in the {@link Vector3f#y} - * field and the angle around Z in the {@link Vector3f#z} field of the supplied {@link Vector3f} instance. - * - * @param eulerAngles - * will hold the euler angles in radians - * @return the passed in vector - */ - Vector3f getEulerAnglesXYZ(Vector3f eulerAngles); - - /** - * Get the euler angles in radians in rotation sequence ZYX of this quaternion and store them in the - * provided parameter eulerAngles. - *

- * The Euler angles are always returned as the angle around X in the {@link Vector3f#x} field, the angle around Y in the {@link Vector3f#y} - * field and the angle around Z in the {@link Vector3f#z} field of the supplied {@link Vector3f} instance. - * - * @param eulerAngles - * will hold the euler angles in radians - * @return the passed in vector - */ - Vector3f getEulerAnglesZYX(Vector3f eulerAngles); - - /** - * Get the euler angles in radians in rotation sequence ZXY of this quaternion and store them in the - * provided parameter eulerAngles. - *

- * The Euler angles are always returned as the angle around X in the {@link Vector3f#x} field, the angle around Y in the {@link Vector3f#y} - * field and the angle around Z in the {@link Vector3f#z} field of the supplied {@link Vector3f} instance. - * - * @param eulerAngles - * will hold the euler angles in radians - * @return the passed in vector - */ - Vector3f getEulerAnglesZXY(Vector3f eulerAngles); - - /** - * Get the euler angles in radians in rotation sequence YXZ of this quaternion and store them in the - * provided parameter eulerAngles. - *

- * The Euler angles are always returned as the angle around X in the {@link Vector3f#x} field, the angle around Y in the {@link Vector3f#y} - * field and the angle around Z in the {@link Vector3f#z} field of the supplied {@link Vector3f} instance. - * - * @param eulerAngles - * will hold the euler angles in radians - * @return the passed in vector - */ - Vector3f getEulerAnglesYXZ(Vector3f eulerAngles); - - /** - * Return the square of the length of this quaternion. - * - * @return the length - */ - float lengthSquared(); - - /** - * Interpolate between this {@link #normalize(Quaternionf) unit} quaternion and the specified - * target {@link #normalize(Quaternionf) unit} quaternion using spherical linear interpolation using the specified interpolation factor alpha, - * and store the result in dest. - *

- * This method resorts to non-spherical linear interpolation when the absolute dot product of this and target is - * below 1E-6f. - *

- * Reference: http://fabiensanglard.net - * - * @param target - * the target of the interpolation, which should be reached with alpha = 1.0 - * @param alpha - * the interpolation factor, within [0..1] - * @param dest - * will hold the result - * @return dest - */ - Quaternionf slerp(Quaternionfc target, float alpha, Quaternionf dest); - - /** - * Apply scaling to this quaternion, which results in any vector transformed by the quaternion to change - * its length by the given factor, and store the result in dest. - * - * @param factor - * the scaling factor - * @param dest - * will hold the result - * @return dest - */ - Quaternionf scale(float factor, Quaternionf dest); - - /** - * Integrate the rotation given by the angular velocity (vx, vy, vz) around the x, y and z axis, respectively, - * with respect to the given elapsed time delta dt and add the differentiate rotation to the rotation represented by this quaternion - * and store the result into dest. - *

- * This method pre-multiplies the rotation given by dt and (vx, vy, vz) by this, so - * the angular velocities are always relative to the local coordinate system of the rotation represented by this quaternion. - *

- * This method is equivalent to calling: rotateLocal(dt * vx, dt * vy, dt * vz, dest) - *

- * Reference: http://physicsforgames.blogspot.de/ - * - * @param dt - * the delta time - * @param vx - * the angular velocity around the x axis - * @param vy - * the angular velocity around the y axis - * @param vz - * the angular velocity around the z axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf integrate(float dt, float vx, float vy, float vz, Quaternionf dest); - - /** - * Compute a linear (non-spherical) interpolation of this and the given quaternion q - * and store the result in dest. - *

- * Reference: http://fabiensanglard.net - * - * @param q - * the other quaternion - * @param factor - * the interpolation factor. It is between 0.0 and 1.0 - * @param dest - * will hold the result - * @return dest - */ - Quaternionf nlerp(Quaternionfc q, float factor, Quaternionf dest); - - /** - * Compute linear (non-spherical) interpolations of this and the given quaternion q - * iteratively and store the result in dest. - *

- * This method performs a series of small-step nlerp interpolations to avoid doing a costly spherical linear interpolation, like - * {@link #slerp(Quaternionfc, float, Quaternionf) slerp}, - * by subdividing the rotation arc between this and q via non-spherical linear interpolations as long as - * the absolute dot product of this and q is greater than the given dotThreshold parameter. - *

- * Thanks to @theagentd at http://www.java-gaming.org/ for providing the code. - * - * @param q - * the other quaternion - * @param alpha - * the interpolation factor, between 0.0 and 1.0 - * @param dotThreshold - * the threshold for the dot product of this and q above which this method performs another iteration - * of a small-step linear interpolation - * @param dest - * will hold the result - * @return dest - */ - Quaternionf nlerpIterative(Quaternionfc q, float alpha, float dotThreshold, Quaternionf dest); - - /** - * Apply a rotation to this quaternion that maps the given direction to the positive Z axis, and store the result in dest. - *

- * Because there are multiple possibilities for such a rotation, this method will choose the one that ensures the given up direction to remain - * parallel to the plane spanned by the up and dir vectors. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - *

- * Reference: http://answers.unity3d.com - * - * @see #lookAlong(float, float, float, float, float, float, Quaternionf) - * - * @param dir - * the direction to map to the positive Z axis - * @param up - * the vector which will be mapped to a vector parallel to the plane - * spanned by the given dir and up - * @param dest - * will hold the result - * @return dest - */ - Quaternionf lookAlong(Vector3fc dir, Vector3fc up, Quaternionf dest); - - /** - * Apply a rotation to this quaternion that maps the given direction to the positive Z axis, and store the result in dest. - *

- * Because there are multiple possibilities for such a rotation, this method will choose the one that ensures the given up direction to remain - * parallel to the plane spanned by the up and dir vectors. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - *

- * Reference: http://answers.unity3d.com - * - * @param dirX - * the x-coordinate of the direction to look along - * @param dirY - * the y-coordinate of the direction to look along - * @param dirZ - * the z-coordinate of the direction to look along - * @param upX - * the x-coordinate of the up vector - * @param upY - * the y-coordinate of the up vector - * @param upZ - * the z-coordinate of the up vector - * @param dest - * will hold the result - * @return dest - */ - Quaternionf lookAlong(float dirX, float dirY, float dirZ, float upX, float upY, float upZ, Quaternionf dest); - - /** - * Apply a rotation to this that rotates the fromDir vector to point along toDir and - * store the result in dest. - *

- * Since there can be multiple possible rotations, this method chooses the one with the shortest arc. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - *

- * Reference: stackoverflow.com - * - * @param fromDirX - * the x-coordinate of the direction to rotate into the destination direction - * @param fromDirY - * the y-coordinate of the direction to rotate into the destination direction - * @param fromDirZ - * the z-coordinate of the direction to rotate into the destination direction - * @param toDirX - * the x-coordinate of the direction to rotate to - * @param toDirY - * the y-coordinate of the direction to rotate to - * @param toDirZ - * the z-coordinate of the direction to rotate to - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateTo(float fromDirX, float fromDirY, float fromDirZ, float toDirX, float toDirY, float toDirZ, Quaternionf dest); - - /** - * Apply a rotation to this that rotates the fromDir vector to point along toDir and - * store the result in dest. - *

- * Because there can be multiple possible rotations, this method chooses the one with the shortest arc. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @see #rotateTo(float, float, float, float, float, float, Quaternionf) - * - * @param fromDir - * the starting direction - * @param toDir - * the destination direction - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateTo(Vector3fc fromDir, Vector3fc toDir, Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the x axis - * and store the result in dest. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angle - * the angle in radians to rotate about the x axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateX(float angle, Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the y axis - * and store the result in dest. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angle - * the angle in radians to rotate about the y axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateY(float angle, Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the z axis - * and store the result in dest. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angle - * the angle in radians to rotate about the z axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateZ(float angle, Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the local x axis - * and store the result in dest. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be R * Q. So when transforming a - * vector v with the new quaternion by using R * Q * v, the - * rotation represented by this will be applied first! - * - * @param angle - * the angle in radians to rotate about the local x axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateLocalX(float angle, Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the local y axis - * and store the result in dest. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be R * Q. So when transforming a - * vector v with the new quaternion by using R * Q * v, the - * rotation represented by this will be applied first! - * - * @param angle - * the angle in radians to rotate about the local y axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateLocalY(float angle, Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the local z axis - * and store the result in dest. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be R * Q. So when transforming a - * vector v with the new quaternion by using R * Q * v, the - * rotation represented by this will be applied first! - * - * @param angle - * the angle in radians to rotate about the local z axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateLocalZ(float angle, Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the specified axis - * and store the result in dest. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @param angle - * the angle in radians to rotate about the specified axis - * @param axisX - * the x coordinate of the rotation axis - * @param axisY - * the y coordinate of the rotation axis - * @param axisZ - * the z coordinate of the rotation axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateAxis(float angle, float axisX, float axisY, float axisZ, Quaternionf dest); - - /** - * Apply a rotation to this quaternion rotating the given radians about the specified axis - * and store the result in dest. - *

- * If Q is this quaternion and R the quaternion representing the - * specified rotation, then the new quaternion will be Q * R. So when transforming a - * vector v with the new quaternion by using Q * R * v, the - * rotation added by this method will be applied first! - * - * @see #rotateAxis(float, float, float, float, Quaternionf) - * - * @param angle - * the angle in radians to rotate about the specified axis - * @param axis - * the rotation axis - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotateAxis(float angle, Vector3fc axis, Quaternionf dest); - - /** - * Compute the difference between this and the other quaternion - * and store the result in dest. - *

- * The difference is the rotation that has to be applied to get from - * this rotation to other. If T is this, Q - * is other and D is the computed difference, then the following equation holds: - *

- * T * D = Q - *

- * It is defined as: D = T^-1 * Q, where T^-1 denotes the {@link #invert(Quaternionf) inverse} of T. - * - * @param other - * the other quaternion - * @param dest - * will hold the result - * @return dest - */ - Quaternionf difference(Quaternionfc other, Quaternionf dest); - - /** - * Obtain the direction of +X before the rotation transformation represented by this quaternion is applied. - *

- * This method is equivalent to the following code: - *

-     * Quaternionf inv = new Quaternionf(this).invert();
-     * inv.transform(dir.set(1, 0, 0));
-     * 
- * - * @param dir - * will hold the direction of +X - * @return dir - */ - Vector3f positiveX(Vector3f dir); - - /** - * Obtain the direction of +X before the rotation transformation represented by this normalized quaternion is applied. - * The quaternion must be {@link #normalize(Quaternionf) normalized} for this method to work. - *

- * This method is equivalent to the following code: - *

-     * Quaternionf inv = new Quaternionf(this).conjugate();
-     * inv.transform(dir.set(1, 0, 0));
-     * 
- * - * @param dir - * will hold the direction of +X - * @return dir - */ - Vector3f normalizedPositiveX(Vector3f dir); - - /** - * Obtain the direction of +Y before the rotation transformation represented by this quaternion is applied. - *

- * This method is equivalent to the following code: - *

-     * Quaternionf inv = new Quaternionf(this).invert();
-     * inv.transform(dir.set(0, 1, 0));
-     * 
- * - * @param dir - * will hold the direction of +Y - * @return dir - */ - Vector3f positiveY(Vector3f dir); - - /** - * Obtain the direction of +Y before the rotation transformation represented by this normalized quaternion is applied. - * The quaternion must be {@link #normalize(Quaternionf) normalized} for this method to work. - *

- * This method is equivalent to the following code: - *

-     * Quaternionf inv = new Quaternionf(this).conjugate();
-     * inv.transform(dir.set(0, 1, 0));
-     * 
- * - * @param dir - * will hold the direction of +Y - * @return dir - */ - Vector3f normalizedPositiveY(Vector3f dir); - - /** - * Obtain the direction of +Z before the rotation transformation represented by this quaternion is applied. - *

- * This method is equivalent to the following code: - *

-     * Quaternionf inv = new Quaternionf(this).invert();
-     * inv.transform(dir.set(0, 0, 1));
-     * 
- * - * @param dir - * will hold the direction of +Z - * @return dir - */ - Vector3f positiveZ(Vector3f dir); - - /** - * Obtain the direction of +Z before the rotation transformation represented by this normalized quaternion is applied. - * The quaternion must be {@link #normalize(Quaternionf) normalized} for this method to work. - *

- * This method is equivalent to the following code: - *

-     * Quaternionf inv = new Quaternionf(this).conjugate();
-     * inv.transform(dir.set(0, 0, 1));
-     * 
- * - * @param dir - * will hold the direction of +Z - * @return dir - */ - Vector3f normalizedPositiveZ(Vector3f dir); - - /** - * Conjugate this by the given quaternion q by computing q * this * q^-1 - * and store the result into dest. - * - * @param q - * the {@link Quaternionfc} to conjugate this by - * @param dest - * will hold the result - * @return dest - */ - Quaternionf conjugateBy(Quaternionfc q, Quaternionf 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(); - - /** - Compare the quaternion components of this quaternion with the given quaternion using the given delta - * and return whether all of them are equal within a maximum difference of delta. - *

- * 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 q - * the other quaternion - * @param delta - * the allowed maximum difference - * @return true whether all of the quaternion components are equal; false otherwise - */ - boolean equals(Quaternionfc q, float delta); - - /** - * - * @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 true if all the quaternion components are equal - */ - boolean equals(float x, float y, float z, float w); -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/RayAabIntersection.java b/src/main/java/com/jozufozu/flywheel/util/joml/RayAabIntersection.java deleted file mode 100644 index fcda32a3d..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/RayAabIntersection.java +++ /dev/null @@ -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 Fast Ray/Axis-Aligned Bounding Box - * Overlap Tests using Ray Slopes paper. - *

- * It is an efficient implementation when testing many axis-aligned boxes against the same ray. - *

- * 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. - *

- * 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 (originX, originY, originZ) - * and direction (dirX, dirY, dirZ). - *

- * 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 (originX, originY, originZ) - * and direction (dirX, dirY, dirZ). - * - * @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 (minX, minY, minZ) and its maximum corner (maxX, maxY, maxZ). - *

- * This implementation uses a tableswitch to dispatch to the correct intersection method. - *

- * 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 true iff the ray intersects the given axis-aligned box; false 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; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/RoundingMode.java b/src/main/java/com/jozufozu/flywheel/util/joml/RoundingMode.java deleted file mode 100644 index 4f3ef6cf2..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/RoundingMode.java +++ /dev/null @@ -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; -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Runtime.java b/src/main/java/com/jozufozu/flywheel/util/joml/Runtime.java deleted file mode 100644 index f46f4d18d..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Runtime.java +++ /dev/null @@ -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; - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Vector3f.java b/src/main/java/com/jozufozu/flywheel/util/joml/Vector3f.java deleted file mode 100644 index 93627940b..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Vector3f.java +++ /dev/null @@ -1,1827 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2015-2021 Richard Greenlees - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.jozufozu.flywheel.util.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Contains the definition of a Vector comprising 3 floats and associated - * transformations. - * - * @author Richard Greenlees - * @author Kai Burjack - * @author F. Neurath - */ -public class Vector3f implements Externalizable, Cloneable, Vector3fc { - - private static final long serialVersionUID = 1L; - - /** - * The x component of the vector. - */ - public float x; - /** - * The y component of the vector. - */ - public float y; - /** - * The z component of the vector. - */ - public float z; - - /** - * Create a new {@link Vector3f} of (0, 0, 0). - */ - public Vector3f() { - } - - /** - * Create a new {@link Vector3f} and initialize all three components with the given value. - * - * @param d - * the value of all three components - */ - public Vector3f(float d) { - this.x = d; - this.y = d; - this.z = d; - } - - /** - * Create a new {@link Vector3f} with the given component values. - * - * @param x - * the value of x - * @param y - * the value of y - * @param z - * the value of z - */ - public Vector3f(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - } - - /** - * Create a new {@link Vector3f} with the same values as v. - * - * @param v - * the {@link Vector3fc} to copy the values from - */ - public Vector3f(Vector3fc v) { - this.x = v.x(); - this.y = v.y(); - this.z = v.z(); - } - - /** - * Create a new {@link Vector3f} and initialize its three components from the first - * three elements of the given array. - * - * @param xyz - * the array containing at least three elements - */ - public Vector3f(float[] xyz) { - this.x = xyz[0]; - this.y = xyz[1]; - this.z = xyz[2]; - } - - /** - * Create a new {@link Vector3f} and read this vector from the supplied {@link ByteBuffer} - * at the current buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the vector is read, use {@link #Vector3f(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @param buffer values will be read in x, y, z order - * @see #Vector3f(int, ByteBuffer) - */ - public Vector3f(ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - } - - /** - * Create a new {@link Vector3f} and read this vector from the supplied {@link ByteBuffer} - * starting at the specified absolute buffer position/index. - *

- * This method will not increment the position of the given ByteBuffer. - * - * @param index the absolute position into the ByteBuffer - * @param buffer values will be read in x, y, z order - */ - public Vector3f(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - } - - /** - * Create a new {@link Vector3f} and read this vector from the supplied {@link FloatBuffer} - * at the current buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the vector is read, use {@link #Vector3f(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @param buffer values will be read in x, y, z order - * @see #Vector3f(int, FloatBuffer) - */ - public Vector3f(FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - } - - /** - * Create a new {@link Vector3f} and read this vector from the supplied {@link FloatBuffer} - * starting at the specified absolute buffer position/index. - *

- * This method will not increment the position of the given FloatBuffer. - * - * @param index the absolute position into the FloatBuffer - * @param buffer values will be read in x, y, z order - */ - public Vector3f(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - } - - public float x() { - return this.x; - } - - public float y() { - return this.y; - } - - public float z() { - return this.z; - } - - /** - * Set the x, y and z components to match the supplied vector. - * - * @param v - * contains the values of x, y and z to set - * @return this - */ - public Vector3f set(Vector3fc v) { - this.x = v.x(); - this.y = v.y(); - this.z = v.z(); - return this; - } - - /** - * Set the x, y, and z components to the supplied value. - * - * @param d - * the value of all three components - * @return this - */ - public Vector3f set(float d) { - this.x = d; - this.y = d; - this.z = d; - return this; - } - - /** - * Set the x, y and z components to the supplied values. - * - * @param x - * the x component - * @param y - * the y component - * @param z - * the z component - * @return this - */ - public Vector3f set(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - return this; - } - - /** - * Set the x, y, and z components to the supplied value. - * - * @param d - * the value of all three components - * @return this - */ - public Vector3f set(double d) { - this.x = (float) d; - this.y = (float) d; - this.z = (float) d; - return this; - } - - /** - * Set the x, y and z components to the supplied values. - * - * @param x - * the x component - * @param y - * the y component - * @param z - * the z component - * @return this - */ - public Vector3f set(double x, double y, double z) { - this.x = (float) x; - this.y = (float) y; - this.z = (float) z; - return this; - } - - /** - * Set the three components of this vector to the first three elements of the given array. - * - * @param xyz - * the array containing at least three elements - * @return this - */ - public Vector3f set(float[] xyz) { - this.x = xyz[0]; - this.y = xyz[1]; - this.z = xyz[2]; - return this; - } - - /** - * Read this vector from the supplied {@link ByteBuffer} at the current - * buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the vector is read, use {@link #set(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @param buffer - * values will be read in x, y, z order - * @return this - * @see #set(int, ByteBuffer) - */ - public Vector3f set(ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - return this; - } - - /** - * Read this vector from the supplied {@link ByteBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given ByteBuffer. - * - * @param index - * the absolute position into the ByteBuffer - * @param buffer - * values will be read in x, y, z order - * @return this - */ - public Vector3f set(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - return this; - } - - /** - * Read this vector from the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the vector is read, use {@link #set(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @param buffer - * values will be read in x, y, z order - * @return this - * @see #set(int, FloatBuffer) - */ - public Vector3f set(FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - return this; - } - - /** - * Read this vector from the supplied {@link FloatBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given FloatBuffer. - * - * @param index - * the absolute position into the FloatBuffer - * @param buffer - * values will be read in x, y, z order - * @return this - */ - public Vector3f set(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - return this; - } - - /** - * Set the values of this vector by reading 3 float values from off-heap memory, - * starting at the given address. - *

- * This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`. - *

- * 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. - * - * @param address - * the off-heap memory address to read the vector values from - * @return this - */ - public Vector3f setFromAddress(long address) { - if (Options.NO_UNSAFE) - throw new UnsupportedOperationException("Not supported when using joml.nounsafe"); - MemUtil.MemUtilUnsafe.get(this, address); - return this; - } - - /** - * Set the value of the specified component of this vector. - * - * @param component - * the component whose value to set, within [0..2] - * @param value - * the value to set - * @return this - * @throws IllegalArgumentException if component is not within [0..2] - */ - public Vector3f setComponent(int component, float value) throws IllegalArgumentException { - switch (component) { - case 0: - x = value; - break; - case 1: - y = value; - break; - case 2: - z = value; - break; - default: - throw new IllegalArgumentException(); - } - return this; - } - - public FloatBuffer get(FloatBuffer buffer) { - MemUtil.INSTANCE.put(this, buffer.position(), buffer); - return buffer; - } - - public FloatBuffer get(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.put(this, index, buffer); - return buffer; - } - - public ByteBuffer get(ByteBuffer buffer) { - MemUtil.INSTANCE.put(this, buffer.position(), buffer); - return buffer; - } - - public ByteBuffer get(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.put(this, index, buffer); - return buffer; - } - - public Vector3fc getToAddress(long address) { - if (Options.NO_UNSAFE) - throw new UnsupportedOperationException("Not supported when using joml.nounsafe"); - MemUtil.MemUtilUnsafe.put(this, address); - return this; - } - - /** - * Subtract the supplied vector from this one and store the result in this. - * - * @param v - * the vector to subtract - * @return this - */ - public Vector3f sub(Vector3fc v) { - this.x = x - v.x(); - this.y = y - v.y(); - this.z = z - v.z(); - return this; - } - - public Vector3f sub(Vector3fc v, Vector3f dest) { - dest.x = x - v.x(); - dest.y = y - v.y(); - dest.z = z - v.z(); - return dest; - } - - /** - * Decrement the components of this vector by the given values. - * - * @param x - * the x component to subtract - * @param y - * the y component to subtract - * @param z - * the z component to subtract - * @return this - */ - public Vector3f sub(float x, float y, float z) { - this.x = this.x - x; - this.y = this.y - y; - this.z = this.z - z; - return this; - } - - public Vector3f sub(float x, float y, float z, Vector3f dest) { - dest.x = this.x - x; - dest.y = this.y - y; - dest.z = this.z - z; - return dest; - } - - /** - * Add the supplied vector to this one. - * - * @param v - * the vector to add - * @return this - */ - public Vector3f add(Vector3fc v) { - this.x = this.x + v.x(); - this.y = this.y + v.y(); - this.z = this.z + v.z(); - return this; - } - - public Vector3f add(Vector3fc v, Vector3f dest) { - dest.x = this.x + v.x(); - dest.y = this.y + v.y(); - dest.z = this.z + v.z(); - return dest; - } - - /** - * Increment the components of this vector by the given values. - * - * @param x - * the x component to add - * @param y - * the y component to add - * @param z - * the z component to add - * @return this - */ - public Vector3f add(float x, float y, float z) { - this.x = this.x + x; - this.y = this.y + y; - this.z = this.z + z; - return this; - } - - public Vector3f add(float x, float y, float z, Vector3f dest) { - dest.x = this.x + x; - dest.y = this.y + y; - dest.z = this.z + z; - return dest; - } - - /** - * Add the component-wise multiplication of a * b to this vector. - * - * @param a - * the first multiplicand - * @param b - * the second multiplicand - * @return this - */ - public Vector3f fma(Vector3fc a, Vector3fc b) { - this.x = Math.fma(a.x(), b.x(), x); - this.y = Math.fma(a.y(), b.y(), y); - this.z = Math.fma(a.z(), b.z(), z); - return this; - } - - /** - * Add the component-wise multiplication of a * b to this vector. - * - * @param a - * the first multiplicand - * @param b - * the second multiplicand - * @return this - */ - public Vector3f fma(float a, Vector3fc b) { - this.x = Math.fma(a, b.x(), x); - this.y = Math.fma(a, b.y(), y); - this.z = Math.fma(a, b.z(), z); - return this; - } - - public Vector3f fma(Vector3fc a, Vector3fc b, Vector3f dest) { - dest.x = Math.fma(a.x(), b.x(), x); - dest.y = Math.fma(a.y(), b.y(), y); - dest.z = Math.fma(a.z(), b.z(), z); - return dest; - } - - public Vector3f fma(float a, Vector3fc b, Vector3f dest) { - dest.x = Math.fma(a, b.x(), x); - dest.y = Math.fma(a, b.y(), y); - dest.z = Math.fma(a, b.z(), z); - return dest; - } - - /** - * Add the component-wise multiplication of this * a to b - * and store the result in this. - * - * @param a - * the multiplicand - * @param b - * the addend - * @return this - */ - public Vector3f mulAdd(Vector3fc a, Vector3fc b) { - this.x = Math.fma(x, a.x(), b.x()); - this.y = Math.fma(y, a.y(), b.y()); - this.z = Math.fma(z, a.z(), b.z()); - return this; - } - - /** - * Add the component-wise multiplication of this * a to b - * and store the result in this. - * - * @param a - * the multiplicand - * @param b - * the addend - * @return this - */ - public Vector3f mulAdd(float a, Vector3fc b) { - this.x = Math.fma(x, a, b.x()); - this.y = Math.fma(y, a, b.y()); - this.z = Math.fma(z, a, b.z()); - return this; - } - - public Vector3f mulAdd(Vector3fc a, Vector3fc b, Vector3f dest) { - dest.x = Math.fma(x, a.x(), b.x()); - dest.y = Math.fma(y, a.y(), b.y()); - dest.z = Math.fma(z, a.z(), b.z()); - return dest; - } - - public Vector3f mulAdd(float a, Vector3fc b, Vector3f dest) { - dest.x = Math.fma(x, a, b.x()); - dest.y = Math.fma(y, a, b.y()); - dest.z = Math.fma(z, a, b.z()); - return dest; - } - - /** - * Multiply this Vector3f component-wise by another Vector3fc. - * - * @param v - * the vector to multiply by - * @return this - */ - public Vector3f mul(Vector3fc v) { - this.x = x * v.x(); - this.y = y * v.y(); - this.z = z * v.z(); - return this; - } - - public Vector3f mul(Vector3fc v, Vector3f dest) { - dest.x = x * v.x(); - dest.y = y * v.y(); - dest.z = z * v.z(); - return dest; - } - - /** - * Divide this Vector3f component-wise by another Vector3fc. - * - * @param v - * the vector to divide by - * @return this - */ - public Vector3f div(Vector3fc v) { - this.x = this.x / v.x(); - this.y = this.y / v.y(); - this.z = this.z / v.z(); - return this; - } - - public Vector3f div(Vector3fc v, Vector3f dest) { - dest.x = x / v.x(); - dest.y = y / v.y(); - dest.z = z / v.z(); - return dest; - } - - public Vector3f mulProject(Matrix4fc mat, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - float invW = 1.0f / Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33()))); - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30()))) * invW; - dest.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31()))) * invW; - dest.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32()))) * invW; - return dest; - } - - public Vector3f mulProject(Matrix4fc mat, float w, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - float invW = 1.0f / Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33() * w))); - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w))) * invW; - dest.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w))) * invW; - dest.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w))) * invW; - return dest; - } - - /** - * Multiply the given matrix mat with this Vector3f, perform perspective division. - *

- * This method uses w=1.0 as the fourth vector component. - * - * @param mat - * the matrix to multiply this vector by - * @return this - */ - public Vector3f mulProject(Matrix4fc mat) { - float x = this.x, y = this.y, z = this.z; - float invW = 1.0f / Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33()))); - this.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30()))) * invW; - this.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31()))) * invW; - this.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32()))) * invW; - return this; - } - - /** - * Multiply the given matrix with this Vector3f and store the result in this. - * - * @param mat - * the matrix - * @return this - */ - public Vector3f mul(Matrix3fc mat) { - float lx = x, ly = y, lz = z; - this.x = Math.fma(mat.m00(), lx, Math.fma(mat.m10(), ly, mat.m20() * lz)); - this.y = Math.fma(mat.m01(), lx, Math.fma(mat.m11(), ly, mat.m21() * lz)); - this.z = Math.fma(mat.m02(), lx, Math.fma(mat.m12(), ly, mat.m22() * lz)); - return this; - } - - public Vector3f mul(Matrix3fc mat, Vector3f dest) { - float lx = x, ly = y, lz = z; - dest.x = Math.fma(mat.m00(), lx, Math.fma(mat.m10(), ly, mat.m20() * lz)); - dest.y = Math.fma(mat.m01(), lx, Math.fma(mat.m11(), ly, mat.m21() * lz)); - dest.z = Math.fma(mat.m02(), lx, Math.fma(mat.m12(), ly, mat.m22() * lz)); - return dest; - } - - /** - * Multiply the transpose of the given matrix with this Vector3f store the result in this. - * - * @param mat - * the matrix - * @return this - */ - public Vector3f mulTranspose(Matrix3fc mat) { - float x = this.x, y = this.y, z = this.z; - this.x = Math.fma(mat.m00(), x, Math.fma(mat.m01(), y, mat.m02() * z)); - this.y = Math.fma(mat.m10(), x, Math.fma(mat.m11(), y, mat.m12() * z)); - this.z = Math.fma(mat.m20(), x, Math.fma(mat.m21(), y, mat.m22() * z)); - return this; - } - - public Vector3f mulTranspose(Matrix3fc mat, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m01(), y, mat.m02() * z)); - dest.y = Math.fma(mat.m10(), x, Math.fma(mat.m11(), y, mat.m12() * z)); - dest.z = Math.fma(mat.m20(), x, Math.fma(mat.m21(), y, mat.m22() * z)); - return dest; - } - - /** - * Multiply the given 4x4 matrix mat with this. - *

- * This method assumes the w component of this to be 1.0. - * - * @param mat - * the matrix to multiply this vector by - * @return this - */ - public Vector3f mulPosition(Matrix4fc mat) { - float x = this.x, y = this.y, z = this.z; - this.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30()))); - this.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31()))); - this.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32()))); - return this; - } - - public Vector3f mulPosition(Matrix4fc mat, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30()))); - dest.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31()))); - dest.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32()))); - return dest; - } - - /** - * Multiply the transpose of the given 4x4 matrix mat with this. - *

- * This method assumes the w component of this to be 1.0. - * - * @param mat - * the matrix whose transpose to multiply this vector by - * @return this - */ - public Vector3f mulTransposePosition(Matrix4fc mat) { - float x = this.x, y = this.y, z = this.z; - this.x = Math.fma(mat.m00(), x, Math.fma(mat.m01(), y, Math.fma(mat.m02(), z, mat.m03()))); - this.y = Math.fma(mat.m10(), x, Math.fma(mat.m11(), y, Math.fma(mat.m12(), z, mat.m13()))); - this.z = Math.fma(mat.m20(), x, Math.fma(mat.m21(), y, Math.fma(mat.m22(), z, mat.m23()))); - return this; - } - - public Vector3f mulTransposePosition(Matrix4fc mat, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m01(), y, Math.fma(mat.m02(), z, mat.m03()))); - dest.y = Math.fma(mat.m10(), x, Math.fma(mat.m11(), y, Math.fma(mat.m12(), z, mat.m13()))); - dest.z = Math.fma(mat.m20(), x, Math.fma(mat.m21(), y, Math.fma(mat.m22(), z, mat.m23()))); - return dest; - } - - /** - * Multiply the given 4x4 matrix mat with this and return the w component - * of the resulting 4D vector. - *

- * This method assumes the w component of this to be 1.0. - * - * @param mat - * the matrix to multiply this vector by - * @return the w component of the resulting 4D vector after multiplication - */ - public float mulPositionW(Matrix4fc mat) { - float x = this.x, y = this.y, z = this.z; - float w = Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33()))); - this.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30()))); - this.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31()))); - this.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32()))); - return w; - } - - public float mulPositionW(Matrix4fc mat, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - float w = Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33()))); - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30()))); - dest.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31()))); - dest.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32()))); - return w; - } - - /** - * Multiply the given 4x4 matrix mat with this. - *

- * This method assumes the w component of this to be 0.0. - * - * @param mat - * the matrix to multiply this vector by - * @return this - */ - public Vector3f mulDirection(Matrix4fc mat) { - float x = this.x, y = this.y, z = this.z; - this.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, mat.m20() * z)); - this.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, mat.m21() * z)); - this.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, mat.m22() * z)); - return this; - } - - public Vector3f mulDirection(Matrix4fc mat, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, mat.m20() * z)); - dest.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, mat.m21() * z)); - dest.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, mat.m22() * z)); - return dest; - } - - /** - * Multiply the transpose of the given 4x4 matrix mat with this. - *

- * This method assumes the w component of this to be 0.0. - * - * @param mat - * the matrix whose transpose to multiply this vector by - * @return this - */ - public Vector3f mulTransposeDirection(Matrix4fc mat) { - float x = this.x, y = this.y, z = this.z; - this.x = Math.fma(mat.m00(), x, Math.fma(mat.m01(), y, mat.m02() * z)); - this.y = Math.fma(mat.m10(), x, Math.fma(mat.m11(), y, mat.m12() * z)); - this.z = Math.fma(mat.m20(), x, Math.fma(mat.m21(), y, mat.m22() * z)); - return this; - } - - public Vector3f mulTransposeDirection(Matrix4fc mat, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m01(), y, mat.m02() * z)); - dest.y = Math.fma(mat.m10(), x, Math.fma(mat.m11(), y, mat.m12() * z)); - dest.z = Math.fma(mat.m20(), x, Math.fma(mat.m21(), y, mat.m22() * z)); - return dest; - } - - /** - * Multiply all components of this {@link Vector3f} by the given scalar - * value. - * - * @param scalar - * the scalar to multiply this vector by - * @return this - */ - public Vector3f mul(float scalar) { - this.x = this.x * scalar; - this.y = this.y * scalar; - this.z = this.z * scalar; - return this; - } - - public Vector3f mul(float scalar, Vector3f dest) { - dest.x = this.x * scalar; - dest.y = this.y * scalar; - dest.z = this.z * scalar; - return dest; - } - - /** - * Multiply the components of this Vector3f by the given scalar values and store the result in this. - * - * @param x - * the x component to multiply this vector by - * @param y - * the y component to multiply this vector by - * @param z - * the z component to multiply this vector by - * @return this - */ - public Vector3f mul(float x, float y, float z) { - this.x = this.x * x; - this.y = this.y * y; - this.z = this.z * z; - return this; - } - - public Vector3f mul(float x, float y, float z, Vector3f dest) { - dest.x = this.x * x; - dest.y = this.y * y; - dest.z = this.z * z; - return dest; - } - - /** - * Divide all components of this {@link Vector3f} by the given scalar - * value. - * - * @param scalar - * the scalar to divide by - * @return this - */ - public Vector3f div(float scalar) { - float inv = 1.0f / scalar; - this.x = this.x * inv; - this.y = this.y * inv; - this.z = this.z * inv; - return this; - } - - public Vector3f div(float scalar, Vector3f dest) { - float inv = 1.0f / scalar; - dest.x = this.x * inv; - dest.y = this.y * inv; - dest.z = this.z * inv; - return dest; - } - - /** - * Divide the components of this Vector3f by the given scalar values and store the result in this. - * - * @param x - * the x component to divide this vector by - * @param y - * the y component to divide this vector by - * @param z - * the z component to divide this vector by - * @return this - */ - public Vector3f div(float x, float y, float z) { - this.x = this.x / x; - this.y = this.y / y; - this.z = this.z / z; - return this; - } - - public Vector3f div(float x, float y, float z, Vector3f dest) { - dest.x = this.x / x; - dest.y = this.y / y; - dest.z = this.z / z; - return dest; - } - - /** - * Rotate this vector by the given quaternion quat and store the result in this. - * - * @see Quaternionfc#transform(Vector3f) - * - * @param quat - * the quaternion to rotate this vector - * @return this - */ - public Vector3f rotate(Quaternionfc quat) { - return quat.transform(this, this); - } - - public Vector3f rotate(Quaternionfc quat, Vector3f dest) { - return quat.transform(this, dest); - } - - public Quaternionf rotationTo(Vector3fc toDir, Quaternionf dest) { - return dest.rotationTo(this, toDir); - } - - public Quaternionf rotationTo(float toDirX, float toDirY, float toDirZ, Quaternionf dest) { - return dest.rotationTo(x, y, z, toDirX, toDirY, toDirZ); - } - - /** - * Rotate this vector the specified radians around the given rotation axis. - * - * @param angle - * the angle in radians - * @param x - * the x component of the rotation axis - * @param y - * the y component of the rotation axis - * @param z - * the z component of the rotation axis - * @return this - */ - public Vector3f rotateAxis(float angle, float x, float y, float z) { - if (y == 0.0f && z == 0.0f && Math.absEqualsOne(x)) - return rotateX(x * angle, this); - else if (x == 0.0f && z == 0.0f && Math.absEqualsOne(y)) - return rotateY(y * angle, this); - else if (x == 0.0f && y == 0.0f && Math.absEqualsOne(z)) - return rotateZ(z * angle, this); - return rotateAxisInternal(angle, x, y, z, this); - } - - public Vector3f rotateAxis(float angle, float aX, float aY, float aZ, Vector3f dest) { - if (aY == 0.0f && aZ == 0.0f && Math.absEqualsOne(aX)) - return rotateX(aX * angle, dest); - else if (aX == 0.0f && aZ == 0.0f && Math.absEqualsOne(aY)) - return rotateY(aY * angle, dest); - else if (aX == 0.0f && aY == 0.0f && Math.absEqualsOne(aZ)) - return rotateZ(aZ * angle, dest); - return rotateAxisInternal(angle, aX, aY, aZ, dest); - } - private Vector3f rotateAxisInternal(float angle, float aX, float aY, float aZ, Vector3f dest) { - float hangle = angle * 0.5f; - float sinAngle = Math.sin(hangle); - float qx = aX * sinAngle, qy = aY * sinAngle, qz = aZ * sinAngle; - float qw = Math.cosFromSin(sinAngle, hangle); - float w2 = qw * qw, x2 = qx * qx, y2 = qy * qy, z2 = qz * qz, zw = qz * qw; - float xy = qx * qy, xz = qx * qz, yw = qy * qw, yz = qy * qz, xw = qx * qw; - float x = this.x, y = this.y, z = this.z; - dest.x = (w2 + x2 - z2 - y2) * x + (-zw + xy - zw + xy) * y + (yw + xz + xz + yw) * z; - dest.y = (xy + zw + zw + xy) * x + ( y2 - z2 + w2 - x2) * y + (yz + yz - xw - xw) * z; - dest.z = (xz - yw + xz - yw) * x + ( yz + yz + xw + xw) * y + (z2 - y2 - x2 + w2) * z; - return dest; - } - - /** - * Rotate this vector the specified radians around the X axis. - * - * @param angle - * the angle in radians - * @return this - */ - public Vector3f rotateX(float angle) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float y = this.y * cos - this.z * sin; - float z = this.y * sin + this.z * cos; - this.y = y; - this.z = z; - return this; - } - - public Vector3f rotateX(float angle, Vector3f dest) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float y = this.y * cos - this.z * sin; - float z = this.y * sin + this.z * cos; - dest.x = this.x; - dest.y = y; - dest.z = z; - return dest; - } - - /** - * Rotate this vector the specified radians around the Y axis. - * - * @param angle - * the angle in radians - * @return this - */ - public Vector3f rotateY(float angle) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float x = this.x * cos + this.z * sin; - float z = -this.x * sin + this.z * cos; - this.x = x; - this.z = z; - return this; - } - - public Vector3f rotateY(float angle, Vector3f dest) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float x = this.x * cos + this.z * sin; - float z = -this.x * sin + this.z * cos; - dest.x = x; - dest.y = this.y; - dest.z = z; - return dest; - } - - /** - * Rotate this vector the specified radians around the Z axis. - * - * @param angle - * the angle in radians - * @return this - */ - public Vector3f rotateZ(float angle) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float x = this.x * cos - this.y * sin; - float y = this.x * sin + this.y * cos; - this.x = x; - this.y = y; - return this; - } - - public Vector3f rotateZ(float angle, Vector3f dest) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float x = this.x * cos - this.y * sin; - float y = this.x * sin + this.y * cos; - dest.x = x; - dest.y = y; - dest.z = this.z; - return dest; - } - - public float lengthSquared() { - return Math.fma(x, x, Math.fma(y, y, z * z)); - } - - /** - * Get the length squared of a 3-dimensional single-precision vector. - * - * @param x The vector's x component - * @param y The vector's y component - * @param z The vector's z component - * - * @return the length squared of the given vector - * - * @author F. Neurath - */ - public static float lengthSquared(float x, float y, float z) { - return Math.fma(x, x, Math.fma(y, y, z * z)); - } - - public float length() { - return Math.sqrt(Math.fma(x, x, Math.fma(y, y, z * z))); - } - - /** - * Get the length of a 3-dimensional single-precision vector. - * - * @param x The vector's x component - * @param y The vector's y component - * @param z The vector's z component - * - * @return the length of the given vector - * - * @author F. Neurath - */ - public static float length(float x, float y, float z) { - return Math.sqrt(Math.fma(x, x, Math.fma(y, y, z * z))); - } - - /** - * Normalize this vector. - * - * @return this - */ - public Vector3f normalize() { - float scalar = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))); - this.x = this.x * scalar; - this.y = this.y * scalar; - this.z = this.z * scalar; - return this; - } - - public Vector3f normalize(Vector3f dest) { - float scalar = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))); - dest.x = this.x * scalar; - dest.y = this.y * scalar; - dest.z = this.z * scalar; - return dest; - } - - /** - * Scale this vector to have the given length. - * - * @param length - * the desired length - * @return this - */ - public Vector3f normalize(float length) { - float scalar = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))) * length; - this.x = this.x * scalar; - this.y = this.y * scalar; - this.z = this.z * scalar; - return this; - } - - public Vector3f normalize(float length, Vector3f dest) { - float scalar = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))) * length; - dest.x = this.x * scalar; - dest.y = this.y * scalar; - dest.z = this.z * scalar; - return dest; - } - - /** - * Set this vector to be the cross product of itself and v. - * - * @param v - * the other vector - * @return this - */ - public Vector3f cross(Vector3fc v) { - float rx = Math.fma(y, v.z(), -z * v.y()); - float ry = Math.fma(z, v.x(), -x * v.z()); - float rz = Math.fma(x, v.y(), -y * v.x()); - this.x = rx; - this.y = ry; - this.z = rz; - return this; - } - - /** - * Set this vector to be the cross product of itself and (x, y, z). - * - * @param x - * the x component of the other vector - * @param y - * the y component of the other vector - * @param z - * the z component of the other vector - * @return this - */ - public Vector3f cross(float x, float y, float z) { - float rx = Math.fma(this.y, z, -this.z * y); - float ry = Math.fma(this.z, x, -this.x * z); - float rz = Math.fma(this.x, y, -this.y * x); - this.x = rx; - this.y = ry; - this.z = rz; - return this; - } - - public Vector3f cross(Vector3fc v, Vector3f dest) { - float rx = Math.fma(y, v.z(), -z * v.y()); - float ry = Math.fma(z, v.x(), -x * v.z()); - float rz = Math.fma(x, v.y(), -y * v.x()); - dest.x = rx; - dest.y = ry; - dest.z = rz; - return dest; - } - - public Vector3f cross(float x, float y, float z, Vector3f dest) { - float rx = Math.fma(this.y, z, -this.z * y); - float ry = Math.fma(this.z, x, -this.x * z); - float rz = Math.fma(this.x, y, -this.y * x); - dest.x = rx; - dest.y = ry; - dest.z = rz; - return dest; - } - - public float distance(Vector3fc v) { - float dx = this.x - v.x(); - float dy = this.y - v.y(); - float dz = this.z - v.z(); - return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, dz * dz))); - } - - public float distance(float x, float y, float z) { - float dx = this.x - x; - float dy = this.y - y; - float dz = this.z - z; - return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, dz * dz))); - } - - public float distanceSquared(Vector3fc v) { - float dx = this.x - v.x(); - float dy = this.y - v.y(); - float dz = this.z - v.z(); - return Math.fma(dx, dx, Math.fma(dy, dy, dz * dz)); - } - - public float distanceSquared(float x, float y, float z) { - float dx = this.x - x; - float dy = this.y - y; - float dz = this.z - z; - return Math.fma(dx, dx, Math.fma(dy, dy, dz * dz)); - } - - /** - * Return the distance between (x1, y1, z1) and (x2, y2, z2). - * - * @param x1 - * the x component of the first vector - * @param y1 - * the y component of the first vector - * @param z1 - * the z component of the first vector - * @param x2 - * the x component of the second vector - * @param y2 - * the y component of the second vector - * @param z2 - * the z component of the second vector - * @return the euclidean distance - */ - public static float distance(float x1, float y1, float z1, float x2, float y2, float z2) { - return Math.sqrt(distanceSquared(x1, y1, z1, x2, y2, z2)); - } - - /** - * Return the squared distance between (x1, y1, z1) and (x2, y2, z2). - * - * @param x1 - * the x component of the first vector - * @param y1 - * the y component of the first vector - * @param z1 - * the z component of the first vector - * @param x2 - * the x component of the second vector - * @param y2 - * the y component of the second vector - * @param z2 - * the z component of the second vector - * @return the euclidean distance squared - */ - public static float distanceSquared(float x1, float y1, float z1, float x2, float y2, float z2) { - float dx = x1 - x2; - float dy = y1 - y2; - float dz = z1 - z2; - return Math.fma(dx, dx, Math.fma(dy, dy, dz * dz)); - } - - public float dot(Vector3fc v) { - return Math.fma(this.x, v.x(), Math.fma(this.y, v.y(), this.z * v.z())); - } - - public float dot(float x, float y, float z) { - return Math.fma(this.x, x, Math.fma(this.y, y, this.z * z)); - } - - public float angleCos(Vector3fc v) { - float x = this.x, y = this.y, z = this.z; - float length1Squared = Math.fma(x, x, Math.fma(y, y, z * z)); - float length2Squared = Math.fma(v.x(), v.x(), Math.fma(v.y(), v.y(), v.z() * v.z())); - float dot = Math.fma(x, v.x(), Math.fma(y, v.y(), z * v.z())); - return dot / (float)Math.sqrt(length1Squared * length2Squared); - } - - public float angle(Vector3fc v) { - float cos = angleCos(v); - // This is because sometimes cos goes above 1 or below -1 because of lost precision - cos = cos < 1 ? cos : 1; - cos = cos > -1 ? cos : -1; - return Math.acos(cos); - } - - public float angleSigned(Vector3fc v, Vector3fc n) { - return angleSigned(v.x(), v.y(), v.z(), n.x(), n.y(), n.z()); - } - - public float angleSigned(float x, float y, float z, float nx, float ny, float nz) { - float tx = this.x, ty = this.y, tz = this.z; - return Math.atan2( - (ty * z - tz * y) * nx + (tz * x - tx * z) * ny + (tx * y - ty * x) * nz, - tx * x + ty * y + tz * z); - } - - /** - * Set the components of this vector to be the component-wise minimum of this and the other vector. - * - * @param v - * the other vector - * @return this - */ - public Vector3f min(Vector3fc v) { - float x = this.x, y = this.y, z = this.z; - this.x = x < v.x() ? x : v.x(); - this.y = y < v.y() ? y : v.y(); - this.z = z < v.z() ? z : v.z(); - return this; - } - - public Vector3f min(Vector3fc v, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - dest.x = x < v.x() ? x : v.x(); - dest.y = y < v.y() ? y : v.y(); - dest.z = z < v.z() ? z : v.z(); - return dest; - } - - /** - * Set the components of this vector to be the component-wise maximum of this and the other vector. - * - * @param v - * the other vector - * @return this - */ - public Vector3f max(Vector3fc v) { - float x = this.x, y = this.y, z = this.z; - this.x = x > v.x() ? x : v.x(); - this.y = y > v.y() ? y : v.y(); - this.z = z > v.z() ? z : v.z(); - return this; - } - - public Vector3f max(Vector3fc v, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - dest.x = x > v.x() ? x : v.x(); - dest.y = y > v.y() ? y : v.y(); - dest.z = z > v.z() ? z : v.z(); - return dest; - } - - /** - * Set all components to zero. - * - * @return this - */ - public Vector3f zero() { - this.x = 0; - this.y = 0; - this.z = 0; - return this; - } - - /** - * Return a string representation of this vector. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this vector by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(x, formatter) + " " + Runtime.format(y, formatter) + " " + Runtime.format(z, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(x); - out.writeFloat(y); - out.writeFloat(z); - } - - public void readExternal(ObjectInput in) throws IOException, - ClassNotFoundException { - set(in.readFloat(), in.readFloat(), in.readFloat()); - } - - /** - * Negate this vector. - * - * @return this - */ - public Vector3f negate() { - this.x = -x; - this.y = -y; - this.z = -z; - return this; - } - - public Vector3f negate(Vector3f dest) { - dest.x = -x; - dest.y = -y; - dest.z = -z; - return dest; - } - - /** - * Set this vector's components to their respective absolute values. - * - * @return this - */ - public Vector3f absolute() { - this.x = Math.abs(this.x); - this.y = Math.abs(this.y); - this.z = Math.abs(this.z); - return this; - } - - public Vector3f absolute(Vector3f dest) { - dest.x = Math.abs(this.x); - dest.y = Math.abs(this.y); - dest.z = Math.abs(this.z); - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - 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; - Vector3f other = (Vector3f) obj; - 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 boolean equals(Vector3fc v, float delta) { - if (this == v) - return true; - if (v == null) - return false; - if (!(v instanceof Vector3fc)) - return false; - if (!Runtime.equals(x, v.x(), delta)) - return false; - if (!Runtime.equals(y, v.y(), delta)) - return false; - if (!Runtime.equals(z, v.z(), delta)) - return false; - return true; - } - - public boolean equals(float x, float y, float z) { - if (Float.floatToIntBits(this.x) != Float.floatToIntBits(x)) - return false; - if (Float.floatToIntBits(this.y) != Float.floatToIntBits(y)) - return false; - if (Float.floatToIntBits(this.z) != Float.floatToIntBits(z)) - return false; - return true; - } - - /** - * Reflect this vector about the given normal vector. - * - * @param normal - * the vector to reflect about - * @return this - */ - public Vector3f reflect(Vector3fc normal) { - float x = normal.x(); - float y = normal.y(); - float z = normal.z(); - float dot = Math.fma(this.x, x, Math.fma(this.y, y, this.z * z)); - this.x = this.x - (dot + dot) * x; - this.y = this.y - (dot + dot) * y; - this.z = this.z - (dot + dot) * z; - return this; - } - - /** - * Reflect this vector about the given normal vector. - * - * @param x - * the x component of the normal - * @param y - * the y component of the normal - * @param z - * the z component of the normal - * @return this - */ - public Vector3f reflect(float x, float y, float z) { - float dot = Math.fma(this.x, x, Math.fma(this.y, y, this.z * z)); - this.x = this.x - (dot + dot) * x; - this.y = this.y - (dot + dot) * y; - this.z = this.z - (dot + dot) * z; - return this; - } - - public Vector3f reflect(Vector3fc normal, Vector3f dest) { - return reflect(normal.x(), normal.y(), normal.z(), dest); - } - - public Vector3f reflect(float x, float y, float z, Vector3f dest) { - float dot = this.dot(x, y, z); - dest.x = this.x - (dot + dot) * x; - dest.y = this.y - (dot + dot) * y; - dest.z = this.z - (dot + dot) * z; - return dest; - } - - /** - * Compute the half vector between this and the other vector. - * - * @param other - * the other vector - * @return this - */ - public Vector3f half(Vector3fc other) { - return this.set(this).add(other.x(), other.y(), other.z()).normalize(); - } - - /** - * Compute the half vector between this and the vector (x, y, z). - * - * @param x - * the x component of the other vector - * @param y - * the y component of the other vector - * @param z - * the z component of the other vector - * @return this - */ - public Vector3f half(float x, float y, float z) { - return half(x, y, z, this); - } - - public Vector3f half(Vector3fc other, Vector3f dest) { - return half(other.x(), other.y(), other.z(), dest); - } - - public Vector3f half(float x, float y, float z, Vector3f dest) { - return dest.set(this).add(x, y, z).normalize(); - } - - public Vector3f smoothStep(Vector3fc v, float t, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - float t2 = t * t; - float t3 = t2 * t; - dest.x = (x + x - v.x() - v.x()) * t3 + (3.0f * v.x() - 3.0f * x) * t2 + x * t + x; - dest.y = (y + y - v.y() - v.y()) * t3 + (3.0f * v.y() - 3.0f * y) * t2 + y * t + y; - dest.z = (z + z - v.z() - v.z()) * t3 + (3.0f * v.z() - 3.0f * z) * t2 + z * t + z; - return dest; - } - - public Vector3f hermite(Vector3fc t0, Vector3fc v1, Vector3fc t1, float t, Vector3f dest) { - float x = this.x, y = this.y, z = this.z; - float t2 = t * t; - float t3 = t2 * t; - dest.x = (x + x - v1.x() - v1.x() + t1.x() + t0.x()) * t3 + (3.0f * v1.x() - 3.0f * x - t0.x() - t0.x() - t1.x()) * t2 + x * t + x; - dest.y = (y + y - v1.y() - v1.y() + t1.y() + t0.y()) * t3 + (3.0f * v1.y() - 3.0f * y - t0.y() - t0.y() - t1.y()) * t2 + y * t + y; - dest.z = (z + z - v1.z() - v1.z() + t1.z() + t0.z()) * t3 + (3.0f * v1.z() - 3.0f * z - t0.z() - t0.z() - t1.z()) * t2 + z * t + z; - return dest; - } - - /** - * Linearly interpolate this and other using the given interpolation factor t - * and store the result in this. - *

- * If t is 0.0 then the result is this. If the interpolation factor is 1.0 - * then the result is other. - * - * @param other - * the other vector - * @param t - * the interpolation factor between 0.0 and 1.0 - * @return this - */ - public Vector3f lerp(Vector3fc other, float t) { - return lerp(other, t, this); - } - - public Vector3f lerp(Vector3fc other, float t, Vector3f dest) { - dest.x = Math.fma(other.x() - x, t, x); - dest.y = Math.fma(other.y() - y, t, y); - dest.z = Math.fma(other.z() - z, t, z); - return dest; - } - - public float get(int component) throws IllegalArgumentException { - switch (component) { - case 0: - return x; - case 1: - return y; - case 2: - return z; - default: - throw new IllegalArgumentException(); - } - } - - public Vector3f get(Vector3f dest) { - dest.x = this.x(); - dest.y = this.y(); - dest.z = this.z(); - return dest; - } - - public int maxComponent() { - float absX = Math.abs(x); - float absY = Math.abs(y); - float absZ = Math.abs(z); - if (absX >= absY && absX >= absZ) { - return 0; - } else if (absY >= absZ) { - return 1; - } - return 2; - } - - public int minComponent() { - float absX = Math.abs(x); - float absY = Math.abs(y); - float absZ = Math.abs(z); - if (absX < absY && absX < absZ) { - return 0; - } else if (absY < absZ) { - return 1; - } - return 2; - } - - public Vector3f orthogonalize(Vector3fc v, Vector3f dest) { - /* - * http://lolengine.net/blog/2013/09/21/picking-orthogonal-vector-combing-coconuts - */ - float rx, ry, rz; - if (Math.abs(v.x()) > Math.abs(v.z())) { - rx = -v.y(); - ry = v.x(); - rz = 0.0f; - } else { - rx = 0.0f; - ry = -v.z(); - rz = v.y(); - } - float invLen = Math.invsqrt(rx * rx + ry * ry + rz * rz); - dest.x = rx * invLen; - dest.y = ry * invLen; - dest.z = rz * invLen; - return dest; - } - - /** - * Transform this vector so that it is orthogonal to the given vector v and normalize the result. - *

- * Reference: Gram–Schmidt process - * - * @param v - * the reference vector which the result should be orthogonal to - * @return this - */ - public Vector3f orthogonalize(Vector3fc v) { - return orthogonalize(v, this); - } - - public Vector3f orthogonalizeUnit(Vector3fc v, Vector3f dest) { - return orthogonalize(v, dest); - } - - /** - * Transform this vector so that it is orthogonal to the given unit vector v and normalize the result. - *

- * The vector v is assumed to be a {@link #normalize() unit} vector. - *

- * Reference: Gram–Schmidt process - * - * @param v - * the reference unit vector which the result should be orthogonal to - * @return this - */ - public Vector3f orthogonalizeUnit(Vector3fc v) { - return orthogonalizeUnit(v, this); - } - - /** - * Set each component of this vector to 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. - * - * @return this - */ - public Vector3f floor() { - return floor(this); - } - - public Vector3f floor(Vector3f dest) { - dest.x = Math.floor(x); - dest.y = Math.floor(y); - dest.z = Math.floor(z); - return dest; - } - - /** - * Set each component of this vector to 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. - * - * @return this - */ - public Vector3f ceil() { - return ceil(this); - } - - public Vector3f ceil(Vector3f dest) { - dest.x = Math.ceil(x); - dest.y = Math.ceil(y); - dest.z = Math.ceil(z); - return dest; - } - - /** - * Set each component of this vector to the closest float that is equal to - * a mathematical integer, with ties rounding to positive infinity. - * - * @return this - */ - public Vector3f round() { - return round(this); - } - - public Vector3f round(Vector3f dest) { - dest.x = Math.round(x); - dest.y = Math.round(y); - dest.z = Math.round(z); - return dest; - } - - public boolean isFinite() { - return Math.isFinite(x) && Math.isFinite(y) && Math.isFinite(z); - } - - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Vector3fc.java b/src/main/java/com/jozufozu/flywheel/util/joml/Vector3fc.java deleted file mode 100644 index 690aee2dc..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Vector3fc.java +++ /dev/null @@ -1,1003 +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 3-dimensional vector of single-precision floats. - * - * @author Kai Burjack - */ -public interface Vector3fc { - - /** - * @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(); - - /** - * Store this vector into the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * 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. - * - * @see #get(int, FloatBuffer) - * - * @param buffer - * will receive the values of this vector in x, y, z 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. - *

- * 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 x, y, z 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}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the vector is stored, use {@link #get(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @see #get(int, ByteBuffer) - * - * @param buffer - * will receive the values of this vector in x, y, z 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. - *

- * 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 x, y, z order - * @return the passed in buffer - */ - ByteBuffer get(int index, ByteBuffer buffer); - - /** - * Store this vector at the given off-heap memory address. - *

- * This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`. - *

- * 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. - * - * @param address - * the off-heap address where to store this vector - * @return this - */ - Vector3fc getToAddress(long address); - - /** - * Subtract the supplied vector from this one and store the result in dest. - * - * @param v - * the vector to subtract - * @param dest - * will hold the result - * @return dest - */ - Vector3f sub(Vector3fc v, Vector3f dest); - - /** - * Decrement the components of this vector by the given values and store the result in dest. - * - * @param x - * the x component to subtract - * @param y - * the y component to subtract - * @param z - * the z component to subtract - * @param dest - * will hold the result - * @return dest - */ - Vector3f sub(float x, float y, float z, Vector3f dest); - - /** - * Add the supplied vector to this one and store the result in dest. - * - * @param v - * the vector to add - * @param dest - * will hold the result - * @return dest - */ - Vector3f add(Vector3fc v, Vector3f dest); - - /** - * Increment the components of this vector by the given values and store the result in dest. - * - * @param x - * the x component to add - * @param y - * the y component to add - * @param z - * the z component to add - * @param dest - * will hold the result - * @return dest - */ - Vector3f add(float x, float y, float z, Vector3f dest); - - /** - * Add the component-wise multiplication of a * b to this vector - * and store the result in dest. - * - * @param a - * the first multiplicand - * @param b - * the second multiplicand - * @param dest - * will hold the result - * @return dest - */ - Vector3f fma(Vector3fc a, Vector3fc b, Vector3f dest); - - /** - * Add the component-wise multiplication of a * b to this vector - * and store the result in dest. - * - * @param a - * the first multiplicand - * @param b - * the second multiplicand - * @param dest - * will hold the result - * @return dest - */ - Vector3f fma(float a, Vector3fc b, Vector3f dest); - - /** - * Add the component-wise multiplication of this * a to b - * and store the result in dest. - * - * @param a - * the multiplicand - * @param b - * the addend - * @param dest - * will hold the result - * @return dest - */ - Vector3f mulAdd(Vector3fc a, Vector3fc b, Vector3f dest); - - /** - * Add the component-wise multiplication of this * a to b - * and store the result in dest. - * - * @param a - * the multiplicand - * @param b - * the addend - * @param dest - * will hold the result - * @return dest - */ - Vector3f mulAdd(float a, Vector3fc b, Vector3f dest); - - /** - * Multiply this Vector3f component-wise by another Vector3f and store the result in dest. - * - * @param v - * the vector to multiply by - * @param dest - * will hold the result - * @return dest - */ - Vector3f mul(Vector3fc v, Vector3f dest); - - /** - * Divide this Vector3f component-wise by another Vector3f and store the result in dest. - * - * @param v - * the vector to divide by - * @param dest - * will hold the result - * @return dest - */ - Vector3f div(Vector3fc v, Vector3f dest); - - /** - * Multiply the given matrix mat with this Vector3f, perform perspective division - * and store the result in dest. - *

- * This method uses w=1.0 as the fourth vector component. - * - * @param mat - * the matrix to multiply this vector by - * @param dest - * will hold the result - * @return dest - */ - Vector3f mulProject(Matrix4fc mat, Vector3f dest); - - /** - * Multiply the given matrix mat with this Vector3f, perform perspective division - * and store the result in dest. - *

- * This method uses the given w as the fourth vector component. - * - * @param mat - * the matrix to multiply this vector by - * @param w - * the w component to use - * @param dest - * will hold the result - * @return dest - */ - Vector3f mulProject(Matrix4fc mat, float w, Vector3f dest); - - /** - * Multiply the given matrix with this Vector3f and store the result in dest. - * - * @param mat - * the matrix - * @param dest - * will hold the result - * @return dest - */ - Vector3f mul(Matrix3fc mat, Vector3f dest); - - /** - * Multiply the transpose of the given matrix with this Vector3f and store the result in dest. - * - * @param mat - * the matrix - * @param dest - * will hold the result - * @return dest - */ - Vector3f mulTranspose(Matrix3fc mat, Vector3f dest); - - /** - * Multiply the given 4x4 matrix mat with this and store the - * result in dest. - *

- * This method assumes the w component of this to be 1.0. - * - * @param mat - * the matrix to multiply this vector by - * @param dest - * will hold the result - * @return dest - */ - Vector3f mulPosition(Matrix4fc mat, Vector3f dest); - - /** - * Multiply the transpose of the given 4x4 matrix mat with this and store the - * result in dest. - *

- * This method assumes the w component of this to be 1.0. - * - * @param mat - * the matrix whose transpose to multiply this vector by - * @param dest - * will hold the result - * @return dest - */ - Vector3f mulTransposePosition(Matrix4fc mat, Vector3f dest); - - /** - * Multiply the given 4x4 matrix mat with this, store the - * result in dest and return the w component of the resulting 4D vector. - *

- * This method assumes the w component of this to be 1.0. - * - * @param mat - * the matrix to multiply this vector by - * @param dest - * will hold the (x, y, z) components of the resulting vector - * @return the w component of the resulting 4D vector after multiplication - */ - float mulPositionW(Matrix4fc mat, Vector3f dest); - - /** - * Multiply the given 4x4 matrix mat with this and store the - * result in dest. - *

- * This method assumes the w component of this to be 0.0. - * - * @param mat - * the matrix to multiply this vector by - * @param dest - * will hold the result - * @return dest - */ - Vector3f mulDirection(Matrix4fc mat, Vector3f dest); - - /** - * Multiply the transpose of the given 4x4 matrix mat with this and store the - * result in dest. - *

- * This method assumes the w component of this to be 0.0. - * - * @param mat - * the matrix whose transpose to multiply this vector by - * @param dest - * will hold the result - * @return dest - */ - Vector3f mulTransposeDirection(Matrix4fc mat, Vector3f dest); - - /** - * Multiply all components of this {@link Vector3f} by the given scalar - * value and store the result in dest. - * - * @param scalar - * the scalar to multiply this vector by - * @param dest - * will hold the result - * @return dest - */ - Vector3f mul(float scalar, Vector3f dest); - - /** - * Multiply the components of this Vector3f by the given scalar values and store the result in dest. - * - * @param x - * the x component to multiply this vector by - * @param y - * the y component to multiply this vector by - * @param z - * the z component to multiply this vector by - * @param dest - * will hold the result - * @return dest - */ - Vector3f mul(float x, float y, float z, Vector3f dest); - - /** - * Divide all components of this {@link Vector3f} by the given scalar - * value and store the result in dest. - * - * @param scalar - * the scalar to divide by - * @param dest - * will hold the result - * @return dest - */ - Vector3f div(float scalar, Vector3f dest); - - /** - * Divide the components of this Vector3f by the given scalar values and store the result in dest. - * - * @param x - * the x component to divide this vector by - * @param y - * the y component to divide this vector by - * @param z - * the z component to divide this vector by - * @param dest - * will hold the result - * @return dest - */ - Vector3f div(float x, float y, float z, Vector3f dest); - - /** - * Rotate this vector by the given quaternion quat and store the result in dest. - * - * @see Quaternionfc#transform(Vector3f) - * - * @param quat - * the quaternion to rotate this vector - * @param dest - * will hold the result - * @return dest - */ - Vector3f rotate(Quaternionfc quat, Vector3f dest); - - /** - * Compute the quaternion representing a rotation of this vector to point along toDir - * and store the result in dest. - *

- * Because there can be multiple possible rotations, this method chooses the one with the shortest arc. - * - * @see Quaternionf#rotationTo(Vector3fc, Vector3fc) - * - * @param toDir - * the destination direction - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotationTo(Vector3fc toDir, Quaternionf dest); - - /** - * Compute the quaternion representing a rotation of this vector to point along (toDirX, toDirY, toDirZ) - * and store the result in dest. - *

- * Because there can be multiple possible rotations, this method chooses the one with the shortest arc. - * - * @see Quaternionf#rotationTo(float, float, float, float, float, float) - * - * @param toDirX - * the x coordinate of the destination direction - * @param toDirY - * the y coordinate of the destination direction - * @param toDirZ - * the z coordinate of the destination direction - * @param dest - * will hold the result - * @return dest - */ - Quaternionf rotationTo(float toDirX, float toDirY, float toDirZ, Quaternionf dest); - - /** - * Rotate this vector the specified radians around the given rotation axis and store the result - * into dest. - * - * @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 - */ - Vector3f rotateAxis(float angle, float aX, float aY, float aZ, Vector3f dest); - - /** - * Rotate this vector the specified radians around the X axis and store the result - * into dest. - * - * @param angle - * the angle in radians - * @param dest - * will hold the result - * @return dest - */ - Vector3f rotateX(float angle, Vector3f dest); - - /** - * Rotate this vector the specified radians around the Y axis and store the result - * into dest. - * - * @param angle - * the angle in radians - * @param dest - * will hold the result - * @return dest - */ - Vector3f rotateY(float angle, Vector3f dest); - - /** - * Rotate this vector the specified radians around the Z axis and store the result - * into dest. - * - * @param angle - * the angle in radians - * @param dest - * will hold the result - * @return dest - */ - Vector3f rotateZ(float angle, Vector3f 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(); - - /** - * Normalize this vector and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f normalize(Vector3f dest); - - /** - * Scale this vector to have the given length and store the result in dest. - * - * @param length - * the desired length - * @param dest - * will hold the result - * @return dest - */ - Vector3f normalize(float length, Vector3f dest); - - /** - * Compute the cross product of this vector and v and store the result in dest. - * - * @param v - * the other vector - * @param dest - * will hold the result - * @return dest - */ - Vector3f cross(Vector3fc v, Vector3f dest); - - /** - * Compute the cross product of this vector and (x, y, z) and store the result in dest. - * - * @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 dest - * will hold the result - * @return dest - */ - Vector3f cross(float x, float y, float z, Vector3f dest); - - /** - * Return the distance between this Vector and v. - * - * @param v - * the other vector - * @return the distance - */ - float distance(Vector3fc v); - - /** - * Return the distance between this vector and (x, y, z). - * - * @param x - * the x component of the other vector - * @param y - * the y component of the other vector - * @param z - * the z component of the other vector - * @return the euclidean distance - */ - float distance(float x, float y, float z); - - /** - * Return the square of the distance between this vector and v. - * - * @param v - * the other vector - * @return the squared of the distance - */ - float distanceSquared(Vector3fc v); - - /** - * Return the square of the distance between this vector and (x, y, z). - * - * @param x - * the x component of the other vector - * @param y - * the y component of the other vector - * @param z - * the z component of the other vector - * @return the square of the distance - */ - float distanceSquared(float x, float y, float z); - - /** - * Return the dot product of this vector and the supplied vector. - * - * @param v - * the other vector - * @return the dot product - */ - float dot(Vector3fc v); - - /** - * Return the dot product of this vector and the vector (x, y, z). - * - * @param x - * the x component of the other vector - * @param y - * the y component of the other vector - * @param z - * the z component of the other vector - * @return the dot product - */ - float dot(float x, float y, float z); - - /** - * Return the cosine of the angle between this vector and the supplied vector. Use this instead of Math.cos(this.angle(v)). - * - * @see #angle(Vector3fc) - * - * @param v - * the other vector - * @return the cosine of the angle - */ - float angleCos(Vector3fc v); - - /** - * Return the angle between this vector and the supplied vector. - * - * @see #angleCos(Vector3fc) - * - * @param v - * the other vector - * @return the angle, in radians - */ - float angle(Vector3fc v); - - /** - * Return the signed angle between this vector and the supplied vector with - * respect to the plane with the given normal vector n. - * - * @see #angleCos(Vector3fc) - * - * @param v - * the other vector - * @param n - * the plane's normal vector - * @return the angle, in radians - */ - float angleSigned(Vector3fc v, Vector3fc n); - - /** - * Return the signed angle between this vector and the supplied vector with - * respect to the plane with the given normal vector (nx, ny, nz). - * - * @param x - * the x coordinate of the other vector - * @param y - * the y coordinate of the other vector - * @param z - * the z coordinate of the other vector - * @param nx - * the x coordinate of the plane's normal vector - * @param ny - * the y coordinate of the plane's normal vector - * @param nz - * the z coordinate of the plane's normal vector - * @return the angle, in radians - */ - float angleSigned(float x, float y, float z, float nx, float ny, float nz); - - /** - * Set the components of dest 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 - */ - Vector3f min(Vector3fc v, Vector3f dest); - - /** - * Set the components of dest 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 - */ - Vector3f max(Vector3fc v, Vector3f dest); - - /** - * Negate this vector and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f negate(Vector3f dest); - - /** - * Compute the absolute values of the individual components of this and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f absolute(Vector3f dest); - - /** - * Reflect this vector about the given normal vector and store the result in dest. - * - * @param normal - * the vector to reflect about - * @param dest - * will hold the result - * @return dest - */ - Vector3f reflect(Vector3fc normal, Vector3f dest); - - /** - * Reflect this vector about the given normal vector and store the result in dest. - * - * @param x - * the x component of the normal - * @param y - * the y component of the normal - * @param z - * the z component of the normal - * @param dest - * will hold the result - * @return dest - */ - Vector3f reflect(float x, float y, float z, Vector3f dest); - - /** - * Compute the half vector between this and the other vector and store the result in dest. - * - * @param other - * the other vector - * @param dest - * will hold the result - * @return dest - */ - Vector3f half(Vector3fc other, Vector3f dest); - - /** - * Compute the half vector between this and the vector (x, y, z) - * and store the result in dest. - * - * @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 dest - * will hold the result - * @return dest - */ - Vector3f half(float x, float y, float z, Vector3f dest); - - /** - * Compute a smooth-step (i.e. hermite with zero tangents) interpolation - * between this vector and the given vector v and - * store the result in dest. - * - * @param v - * the other vector - * @param t - * the interpolation factor, within [0..1] - * @param dest - * will hold the result - * @return dest - */ - Vector3f smoothStep(Vector3fc v, float t, Vector3f dest); - - /** - * Compute a hermite interpolation between this vector with its - * associated tangent t0 and the given vector v - * with its tangent t1 and store the result in - * dest. - * - * @param t0 - * the tangent of this vector - * @param v1 - * the other vector - * @param t1 - * the tangent of the other vector - * @param t - * the interpolation factor, within [0..1] - * @param dest - * will hold the result - * @return dest - */ - Vector3f hermite(Vector3fc t0, Vector3fc v1, Vector3fc t1, float t, Vector3f dest); - - /** - * Linearly interpolate this and other using the given interpolation factor t - * and store the result in dest. - *

- * If t is 0.0 then the result is this. If the interpolation factor is 1.0 - * then the result is other. - * - * @param other - * the other vector - * @param t - * the interpolation factor between 0.0 and 1.0 - * @param dest - * will hold the result - * @return dest - */ - Vector3f lerp(Vector3fc other, float t, Vector3f dest); - - /** - * Get the value of the specified component of this vector. - * - * @param component - * the component, within [0..2] - * @return the value - * @throws IllegalArgumentException if component is not within [0..2] - */ - float get(int component) throws IllegalArgumentException; - - /** - * Set the components of the given vector dest to those of this vector. - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f get(Vector3f dest); - - /** - * Determine the component with the biggest absolute value. - * - * @return the component index, within [0..2] - */ - int maxComponent(); - - /** - * Determine the component with the smallest (towards zero) absolute value. - * - * @return the component index, within [0..2] - */ - int minComponent(); - - /** - * Transform this vector so that it is orthogonal to the given vector v, normalize the result and store it into dest. - *

- * Reference: Gram–Schmidt process - * - * @param v - * the reference vector which the result should be orthogonal to - * @param dest - * will hold the result - * @return dest - */ - Vector3f orthogonalize(Vector3fc v, Vector3f dest); - - /** - * Transform this vector so that it is orthogonal to the given unit vector v, normalize the result and store it into dest. - *

- * The vector v is assumed to be a {@link #normalize(Vector3f) unit} vector. - *

- * Reference: Gram–Schmidt process - * - * @param v - * the reference unit vector which the result should be orthogonal to - * @param dest - * will hold the result - * @return dest - */ - Vector3f orthogonalizeUnit(Vector3fc v, Vector3f dest); - - /** - * Compute for each component of this vector the largest (closest to positive - * infinity) {@code float} value that is less than or equal to that - * component and is equal to a mathematical integer and store the result in - * dest. - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f floor(Vector3f 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 - * dest. - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f ceil(Vector3f 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 dest. - * - * @param dest - * will hold the result - * @return dest - */ - Vector3f round(Vector3f 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(); - - /** - * Compare the vector components of this vector with the given vector using the given delta - * and return whether all of them are equal within a maximum difference of delta. - *

- * 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 true whether all of the vector components are equal; false otherwise - */ - boolean equals(Vector3fc v, float delta); - - /** - * Compare the vector components of this vector with the given (x, y, z) - * and return whether all of them are equal. - * - * @param x - * the x component to compare to - * @param y - * the y component to compare to - * @param z - * the z component to compare to - * @return true if all the vector components are equal - */ - boolean equals(float x, float y, float z); - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Vector4f.java b/src/main/java/com/jozufozu/flywheel/util/joml/Vector4f.java deleted file mode 100644 index 3c7650e9a..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Vector4f.java +++ /dev/null @@ -1,1741 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2015-2021 Richard Greenlees - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.jozufozu.flywheel.util.joml; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -/** - * Contains the definition of a Vector comprising 4 floats and associated - * transformations. - * - * @author Richard Greenlees - * @author Kai Burjack - * @author F. Neurath - */ -public class Vector4f implements Externalizable, Cloneable, Vector4fc { - - private static final long serialVersionUID = 1L; - - /** - * The x component of the vector. - */ - public float x; - /** - * The y component of the vector. - */ - public float y; - /** - * The z component of the vector. - */ - public float z; - /** - * The w component of the vector. - */ - public float w; - - /** - * Create a new {@link Vector4f} of (0, 0, 0, 1). - */ - public Vector4f() { - this.w = 1.0f; - } - - /** - * Create a new {@link Vector4f} with the same values as v. - * - * @param v - * the {@link Vector4fc} to copy the values from - */ - public Vector4f(Vector4fc v) { - this.x = v.x(); - this.y = v.y(); - this.z = v.z(); - this.w = v.w(); - } - - /** - * Create a new {@link Vector4f} with the first three components from the - * given v and the given w. - * - * @param v - * the {@link Vector3fc} - * @param w - * the w component - */ - public Vector4f(Vector3fc v, float w) { - this.x = v.x(); - this.y = v.y(); - this.z = v.z(); - this.w = w; - } - - /** - * Create a new {@link Vector4f} and initialize all four components with the given value. - * - * @param d - * the value of all four components - */ - public Vector4f(float d) { - this.x = d; - this.y = d; - this.z = d; - this.w = d; - } - - /** - * Create a new {@link Vector4f} with the given component values. - * - * @param x - * the x component - * @param y - * the y component - * @param z - * the z component - * @param w - * the w component - */ - public Vector4f(float x, float y, float z, float w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - } - - /** - * Create a new {@link Vector4f} and initialize its four components from the first - * four elements of the given array. - * - * @param xyzw - * the array containing at least four elements - */ - public Vector4f(float[] xyzw) { - this.x = xyzw[0]; - this.y = xyzw[1]; - this.z = xyzw[2]; - this.w = xyzw[3]; - } - - /** - * Create a new {@link Vector4f} and read this vector from the supplied {@link ByteBuffer} - * at the current buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the vector is read, use {@link #Vector4f(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @param buffer - * values will be read in x, y, z, w order - * @see #Vector4f(int, ByteBuffer) - */ - public Vector4f(ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - } - - /** - * Create a new {@link Vector4f} and read this vector from the supplied {@link ByteBuffer} - * starting at the specified absolute buffer position/index. - *

- * This method will not increment the position of the given ByteBuffer. - * - * @param index - * the absolute position into the ByteBuffer - * @param buffer - * values will be read in x, y, z, w order - */ - public Vector4f(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - } - - /** - * Create a new {@link Vector4f} and read this vector from the supplied {@link FloatBuffer} - * at the current buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the vector is read, use {@link #Vector4f(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @param buffer - * values will be read in x, y, z, w order - * @see #Vector4f(int, FloatBuffer) - */ - public Vector4f(FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - } - - /** - * Create a new {@link Vector4f} and read this vector from the supplied {@link FloatBuffer} - * starting at the specified absolute buffer position/index. - *

- * This method will not increment the position of the given FloatBuffer. - * - * @param index - * the absolute position into the FloatBuffer - * @param buffer - * values will be read in x, y, z, w order - */ - public Vector4f(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - } - - public float x() { - return this.x; - } - - public float y() { - return this.y; - } - - public float z() { - return this.z; - } - - public float w() { - return this.w; - } - - /** - * Set this {@link Vector4f} to the values of the given v. - * - * @param v - * the vector whose values will be copied into this - * @return this - */ - public Vector4f set(Vector4fc v) { - this.x = v.x(); - this.y = v.y(); - this.z = v.z(); - this.w = v.w(); - return this; - } - - /** - * Set the first three components of this to the components of - * v and the last component to w. - * - * @param v - * the {@link Vector3fc} to copy - * @param w - * the w component - * @return this - */ - public Vector4f set(Vector3fc v, float w) { - this.x = v.x(); - this.y = v.y(); - this.z = v.z(); - this.w = w; - return this; - } - - /** - * Set the x, y, z, and w components to the supplied value. - * - * @param d - * the value of all four components - * @return this - */ - public Vector4f set(float d) { - this.x = d; - this.y = d; - this.z = d; - this.w = d; - return this; - } - - /** - * Set the x, y, z, and w components to the supplied values. - * - * @param x - * the x component - * @param y - * the y component - * @param z - * the z component - * @param w - * the w component - * @return this - */ - public Vector4f set(float x, float y, float z, float w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - return this; - } - - /** - * Set the x, y, z components to the supplied values. - * - * @param x - * the x component - * @param y - * the y component - * @param z - * the z component - * @return this - */ - public Vector4f set(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - return this; - } - - /** - * Set the x, y, z, and w components to the supplied value. - * - * @param d - * the value of all four components - * @return this - */ - public Vector4f set(double d) { - this.x = (float) d; - this.y = (float) d; - this.z = (float) d; - this.w = (float) d; - return this; - } - - /** - * Set the x, y, z, and w components to the supplied values. - * - * @param x - * the x component - * @param y - * the y component - * @param z - * the z component - * @param w - * the w component - * @return this - */ - public Vector4f set(double x, double y, double z, double w) { - this.x = (float) x; - this.y = (float) y; - this.z = (float) z; - this.w = (float) w; - return this; - } - - /** - * Set the four components of this vector to the first four elements of the given array. - * - * @param xyzw - * the array containing at least four elements - * @return this - */ - public Vector4f set(float[] xyzw) { - this.x = xyzw[0]; - this.y = xyzw[1]; - this.z = xyzw[2]; - this.w = xyzw[3]; - return this; - } - - /** - * Read this vector from the supplied {@link ByteBuffer} at the current - * buffer {@link ByteBuffer#position() position}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * In order to specify the offset into the ByteBuffer at which - * the vector is read, use {@link #set(int, ByteBuffer)}, taking - * the absolute position as parameter. - * - * @param buffer - * values will be read in x, y, z, w order - * @return this - * @see #set(int, ByteBuffer) - */ - public Vector4f set(ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - return this; - } - - /** - * Read this vector from the supplied {@link ByteBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given ByteBuffer. - * - * @param index - * the absolute position into the ByteBuffer - * @param buffer - * values will be read in x, y, z, w order - * @return this - */ - public Vector4f set(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - return this; - } - - /** - * Read this vector from the supplied {@link FloatBuffer} at the current - * buffer {@link FloatBuffer#position() position}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * In order to specify the offset into the FloatBuffer at which - * the vector is read, use {@link #set(int, FloatBuffer)}, taking - * the absolute position as parameter. - * - * @param buffer - * values will be read in x, y, z, w order - * @return this - * @see #set(int, FloatBuffer) - */ - public Vector4f set(FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, buffer.position(), buffer); - return this; - } - - /** - * Read this vector from the supplied {@link FloatBuffer} starting at the specified - * absolute buffer position/index. - *

- * This method will not increment the position of the given FloatBuffer. - * - * @param index - * the absolute position into the FloatBuffer - * @param buffer - * values will be read in x, y, z, w order - * @return this - */ - public Vector4f set(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.get(this, index, buffer); - return this; - } - - /** - * Set the values of this vector by reading 4 float values from off-heap memory, - * starting at the given address. - *

- * This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`. - *

- * 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. - * - * @param address - * the off-heap memory address to read the vector values from - * @return this - */ - public Vector4f setFromAddress(long address) { - if (Options.NO_UNSAFE) - throw new UnsupportedOperationException("Not supported when using joml.nounsafe"); - MemUtil.MemUtilUnsafe.get(this, address); - return this; - } - - /** - * Set the value of the specified component of this vector. - * - * @param component - * the component whose value to set, within [0..3] - * @param value - * the value to set - * @return this - * @throws IllegalArgumentException if component is not within [0..3] - */ - public Vector4f setComponent(int component, float value) throws IllegalArgumentException { - switch (component) { - case 0: - x = value; - break; - case 1: - y = value; - break; - case 2: - z = value; - break; - case 3: - w = value; - break; - default: - throw new IllegalArgumentException(); - } - return this; - } - - public FloatBuffer get(FloatBuffer buffer) { - MemUtil.INSTANCE.put(this, buffer.position(), buffer); - return buffer; - } - - public FloatBuffer get(int index, FloatBuffer buffer) { - MemUtil.INSTANCE.put(this, index, buffer); - return buffer; - } - - public ByteBuffer get(ByteBuffer buffer) { - MemUtil.INSTANCE.put(this, buffer.position(), buffer); - return buffer; - } - - public ByteBuffer get(int index, ByteBuffer buffer) { - MemUtil.INSTANCE.put(this, index, buffer); - return buffer; - } - - public Vector4fc getToAddress(long address) { - if (Options.NO_UNSAFE) - throw new UnsupportedOperationException("Not supported when using joml.nounsafe"); - MemUtil.MemUtilUnsafe.put(this, address); - return this; - } - - /** - * Subtract the supplied vector from this one. - * - * @param v - * the vector to subtract - * @return this - */ - public Vector4f sub(Vector4fc v) { - this.x = this.x - v.x(); - this.y = this.y - v.y(); - this.z = this.z - v.z(); - this.w = this.w - v.w(); - return this; - } - - /** - * Subtract (x, y, z, w) from this. - * - * @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 - * @return this - */ - public Vector4f sub(float x, float y, float z, float w) { - this.x = this.x - x; - this.y = this.y - y; - this.z = this.z - z; - this.w = this.w - w; - return this; - } - - public Vector4f sub(Vector4fc v, Vector4f dest) { - dest.x = this.x - v.x(); - dest.y = this.y - v.y(); - dest.z = this.z - v.z(); - dest.w = this.w - v.w(); - return dest; - } - - public Vector4f sub(float x, float y, float z, float w, Vector4f dest) { - dest.x = this.x - x; - dest.y = this.y - y; - dest.z = this.z - z; - dest.w = this.w - w; - return dest; - } - - /** - * Add the supplied vector to this one. - * - * @param v - * the vector to add - * @return this - */ - public Vector4f add(Vector4fc v) { - this.x = x + v.x(); - this.y = y + v.y(); - this.z = z + v.z(); - this.w = w + v.w(); - return this; - } - - public Vector4f add(Vector4fc v, Vector4f dest) { - dest.x = x + v.x(); - dest.y = y + v.y(); - dest.z = z + v.z(); - dest.w = w + v.w(); - return dest; - } - - /** - * Increment the components of this vector by the given values. - * - * @param x - * the x component to add - * @param y - * the y component to add - * @param z - * the z component to add - * @param w - * the w component to add - * @return this - */ - public Vector4f add(float x, float y, float z, float w) { - this.x = this.x + x; - this.y = this.y + y; - this.z = this.z + z; - this.w = this.w + w; - return this; - } - - public Vector4f add(float x, float y, float z, float w, Vector4f dest) { - dest.x = this.x + x; - dest.y = this.y + y; - dest.z = this.z + z; - dest.w = this.w + w; - return dest; - } - - /** - * Add the component-wise multiplication of a * b to this vector. - * - * @param a - * the first multiplicand - * @param b - * the second multiplicand - * @return this - */ - public Vector4f fma(Vector4fc a, Vector4fc b) { - this.x = Math.fma(a.x(), b.x(), x); - this.y = Math.fma(a.y(), b.y(), y); - this.z = Math.fma(a.z(), b.z(), z); - this.w = Math.fma(a.w(), b.w(), w); - return this; - } - - /** - * Add the component-wise multiplication of a * b to this vector. - * - * @param a - * the first multiplicand - * @param b - * the second multiplicand - * @return this - */ - public Vector4f fma(float a, Vector4fc b) { - this.x = Math.fma(a, b.x(), x); - this.y = Math.fma(a, b.y(), y); - this.z = Math.fma(a, b.z(), z); - this.w = Math.fma(a, b.w(), w); - return this; - } - - public Vector4f fma(Vector4fc a, Vector4fc b, Vector4f dest) { - dest.x = Math.fma(a.x(), b.x(), x); - dest.y = Math.fma(a.y(), b.y(), y); - dest.z = Math.fma(a.z(), b.z(), z); - dest.w = Math.fma(a.w(), b.w(), w); - return dest; - } - - public Vector4f fma(float a, Vector4fc b, Vector4f dest) { - dest.x = Math.fma(a, b.x(), x); - dest.y = Math.fma(a, b.y(), y); - dest.z = Math.fma(a, b.z(), z); - dest.w = Math.fma(a, b.w(), w); - return dest; - } - - /** - * Add the component-wise multiplication of this * a to b - * and store the result in this. - * - * @param a - * the multiplicand - * @param b - * the addend - * @return this - */ - public Vector4f mulAdd(Vector4fc a, Vector4fc b) { - this.x = Math.fma(x, a.x(), b.x()); - this.y = Math.fma(y, a.y(), b.y()); - this.z = Math.fma(z, a.z(), b.z()); - return this; - } - - /** - * Add the component-wise multiplication of this * a to b - * and store the result in this. - * - * @param a - * the multiplicand - * @param b - * the addend - * @return this - */ - public Vector4f mulAdd(float a, Vector4fc b) { - this.x = Math.fma(x, a, b.x()); - this.y = Math.fma(y, a, b.y()); - this.z = Math.fma(z, a, b.z()); - return this; - } - - public Vector4f mulAdd(Vector4fc a, Vector4fc b, Vector4f dest) { - dest.x = Math.fma(x, a.x(), b.x()); - dest.y = Math.fma(y, a.y(), b.y()); - dest.z = Math.fma(z, a.z(), b.z()); - return dest; - } - - public Vector4f mulAdd(float a, Vector4fc b, Vector4f dest) { - dest.x = Math.fma(x, a, b.x()); - dest.y = Math.fma(y, a, b.y()); - dest.z = Math.fma(z, a, b.z()); - return dest; - } - - /** - * Multiply this Vector4f component-wise by another Vector4f. - * - * @param v - * the other vector - * @return this - */ - public Vector4f mul(Vector4fc v) { - this.x = x * v.x(); - this.y = y * v.y(); - this.z = z * v.z(); - this.w = w * v.w(); - return this; - } - - public Vector4f mul(Vector4fc v, Vector4f dest) { - dest.x = x * v.x(); - dest.y = y * v.y(); - dest.z = z * v.z(); - dest.w = w * v.w(); - return dest; - } - - /** - * Divide this Vector4f component-wise by another Vector4f. - * - * @param v - * the vector to divide by - * @return this - */ - public Vector4f div(Vector4fc v) { - this.x = x / v.x(); - this.y = y / v.y(); - this.z = z / v.z(); - this.w = w / v.w(); - return this; - } - - public Vector4f div(Vector4fc v, Vector4f dest) { - dest.x = x / v.x(); - dest.y = y / v.y(); - dest.z = z / v.z(); - dest.w = w / v.w(); - return dest; - } - - /** - * Multiply the given matrix mat with this Vector4f and store the result in - * this. - * - * @param mat - * the matrix to multiply the vector with - * @return this - */ - public Vector4f mul(Matrix4fc mat) { - if ((mat.properties() & Matrix4fc.PROPERTY_AFFINE) != 0) - return mulAffine(mat, this); - return mulGeneric(mat, this); - } - public Vector4f mul(Matrix4fc mat, Vector4f dest) { - if ((mat.properties() & Matrix4fc.PROPERTY_AFFINE) != 0) - return mulAffine(mat, dest); - return mulGeneric(mat, dest); - } - - /** - * Multiply the transpose of the given matrix mat with this Vector4f and store the result in - * this. - * - * @param mat - * the matrix whose transpose to multiply the vector with - * @return this - */ - public Vector4f mulTranspose(Matrix4fc mat) { - if ((mat.properties() & Matrix4fc.PROPERTY_AFFINE) != 0) - return mulAffineTranspose(mat, this); - return mulGenericTranspose(mat, this); - } - public Vector4f mulTranspose(Matrix4fc mat, Vector4f dest) { - if ((mat.properties() & Matrix4fc.PROPERTY_AFFINE) != 0) - return mulAffineTranspose(mat, dest); - return mulGenericTranspose(mat, dest); - } - - public Vector4f mulAffine(Matrix4fc mat, Vector4f dest) { - float x = this.x, y = this.y, z = this.z, w = this.w; - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w))); - dest.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w))); - dest.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w))); - dest.w = w; - return dest; - } - - private Vector4f mulGeneric(Matrix4fc mat, Vector4f dest) { - float x = this.x, y = this.y, z = this.z, w = this.w; - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w))); - dest.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w))); - dest.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w))); - dest.w = Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33() * w))); - return dest; - } - - public Vector4f mulAffineTranspose(Matrix4fc mat, Vector4f dest) { - float x = this.x, y = this.y, z = this.z, w = this.w; - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m01(), y, mat.m02() * z)); - dest.y = Math.fma(mat.m10(), x, Math.fma(mat.m11(), y, mat.m12() * z)); - dest.z = Math.fma(mat.m20(), x, Math.fma(mat.m21(), y, mat.m22() * z)); - dest.w = Math.fma(mat.m30(), x, Math.fma(mat.m31(), y, mat.m32() * z + w)); - return dest; - } - private Vector4f mulGenericTranspose(Matrix4fc mat, Vector4f dest) { - float x = this.x, y = this.y, z = this.z, w = this.w; - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m01(), y, Math.fma(mat.m02(), z, mat.m03() * w))); - dest.y = Math.fma(mat.m10(), x, Math.fma(mat.m11(), y, Math.fma(mat.m12(), z, mat.m13() * w))); - dest.z = Math.fma(mat.m20(), x, Math.fma(mat.m21(), y, Math.fma(mat.m22(), z, mat.m23() * w))); - dest.w = Math.fma(mat.m30(), x, Math.fma(mat.m31(), y, Math.fma(mat.m32(), z, mat.m33() * w))); - return dest; - } - - public Vector4f mulProject(Matrix4fc mat, Vector4f dest) { - float x = this.x, y = this.y, z = this.z, w = this.w; - float invW = 1.0f / Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33() * w))); - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w))) * invW; - dest.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w))) * invW; - dest.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w))) * invW; - dest.w = 1.0f; - return dest; - } - - /** - * Multiply the given matrix mat with this Vector4f, perform perspective division. - * - * @param mat - * the matrix to multiply this vector by - * @return this - */ - public Vector4f mulProject(Matrix4fc mat) { - float x = this.x, y = this.y, z = this.z, w = this.w; - float invW = 1.0f / Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33() * w))); - this.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w))) * invW; - this.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w))) * invW; - this.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w))) * invW; - this.w = 1.0f; - return this; - } - - public Vector3f mulProject(Matrix4fc mat, Vector3f dest) { - float x = this.x, y = this.y, z = this.z, w = this.w; - float invW = 1.0f / Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33() * w))); - dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w))) * invW; - dest.y = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w))) * invW; - dest.z = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w))) * invW; - return dest; - } - - /** - * Multiply all components of this {@link Vector4f} by the given scalar - * value. - * - * @param scalar - * the scalar to multiply by - * @return this - */ - public Vector4f mul(float scalar) { - this.x = x * scalar; - this.y = y * scalar; - this.z = z * scalar; - this.w = w * scalar; - return this; - } - - public Vector4f mul(float scalar, Vector4f dest) { - dest.x = x * scalar; - dest.y = y * scalar; - dest.z = z * scalar; - dest.w = w * scalar; - return dest; - } - - /** - * Multiply the components of this Vector4f by the given scalar values and store the result in this. - * - * @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 - * @return this - */ - public Vector4f mul(float x, float y, float z, float w) { - this.x = this.x * x; - this.y = this.y * y; - this.z = this.z * z; - this.w = this.w * w; - return this; - } - - public Vector4f mul(float x, float y, float z, float w, Vector4f dest) { - dest.x = this.x * x; - dest.y = this.y * y; - dest.z = this.z * z; - dest.w = this.w * w; - return dest; - } - - /** - * Divide all components of this {@link Vector4f} by the given scalar - * value. - * - * @param scalar - * the scalar to divide by - * @return this - */ - public Vector4f div(float scalar) { - float inv = 1.0f / scalar; - this.x = x * inv; - this.y = y * inv; - this.z = z * inv; - this.w = w * inv; - return this; - } - - public Vector4f div(float scalar, Vector4f dest) { - float inv = 1.0f / scalar; - dest.x = x * inv; - dest.y = y * inv; - dest.z = z * inv; - dest.w = w * inv; - return dest; - } - - /** - * Divide the components of this Vector4f by the given scalar values and store the result in this. - * - * @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 - * @return this - */ - public Vector4f div(float x, float y, float z, float w) { - this.x = this.x / x; - this.y = this.y / y; - this.z = this.z / z; - this.w = this.w / w; - return this; - } - - public Vector4f div(float x, float y, float z, float w, Vector4f dest) { - dest.x = this.x / x; - dest.y = this.y / y; - dest.z = this.z / z; - dest.w = this.w / w; - return dest; - } - - /** - * Rotate this vector by the given quaternion quat and store the result in this. - * - * @see Quaternionf#transform(Vector4f) - * - * @param quat - * the quaternion to rotate this vector - * @return this - */ - public Vector4f rotate(Quaternionfc quat) { - return quat.transform(this, this); - } - - public Vector4f rotate(Quaternionfc quat, Vector4f dest) { - return quat.transform(this, dest); - } - - /** - * Rotate this vector the specified radians around the given rotation axis. - * - * @param angle - * the angle in radians - * @param x - * the x component of the rotation axis - * @param y - * the y component of the rotation axis - * @param z - * the z component of the rotation axis - * @return this - */ - public Vector4f rotateAbout(float angle, float x, float y, float z) { - if (y == 0.0f && z == 0.0f && Math.absEqualsOne(x)) - return rotateX(x * angle, this); - else if (x == 0.0f && z == 0.0f && Math.absEqualsOne(y)) - return rotateY(y * angle, this); - else if (x == 0.0f && y == 0.0f && Math.absEqualsOne(z)) - return rotateZ(z * angle, this); - return rotateAxisInternal(angle, x, y, z, this); - } - - public Vector4f rotateAxis(float angle, float aX, float aY, float aZ, Vector4f dest) { - if (aY == 0.0f && aZ == 0.0f && Math.absEqualsOne(aX)) - return rotateX(aX * angle, dest); - else if (aX == 0.0f && aZ == 0.0f && Math.absEqualsOne(aY)) - return rotateY(aY * angle, dest); - else if (aX == 0.0f && aY == 0.0f && Math.absEqualsOne(aZ)) - return rotateZ(aZ * angle, dest); - return rotateAxisInternal(angle, aX, aY, aZ, dest); - } - private Vector4f rotateAxisInternal(float angle, float aX, float aY, float aZ, Vector4f dest) { - float hangle = angle * 0.5f; - float sinAngle = Math.sin(hangle); - float qx = aX * sinAngle, qy = aY * sinAngle, qz = aZ * sinAngle; - float qw = Math.cosFromSin(sinAngle, hangle); - float w2 = qw * qw, x2 = qx * qx, y2 = qy * qy, z2 = qz * qz, zw = qz * qw; - float xy = qx * qy, xz = qx * qz, yw = qy * qw, yz = qy * qz, xw = qx * qw; - float x = this.x, y = this.y, z = this.z; - dest.x = (w2 + x2 - z2 - y2) * x + (-zw + xy - zw + xy) * y + (yw + xz + xz + yw) * z; - dest.y = (xy + zw + zw + xy) * x + ( y2 - z2 + w2 - x2) * y + (yz + yz - xw - xw) * z; - dest.z = (xz - yw + xz - yw) * x + ( yz + yz + xw + xw) * y + (z2 - y2 - x2 + w2) * z; - return dest; - } - - /** - * Rotate this vector the specified radians around the X axis. - * - * @param angle - * the angle in radians - * @return this - */ - public Vector4f rotateX(float angle) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float y = this.y * cos - this.z * sin; - float z = this.y * sin + this.z * cos; - this.y = y; - this.z = z; - return this; - } - - public Vector4f rotateX(float angle, Vector4f dest) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float y = this.y * cos - this.z * sin; - float z = this.y * sin + this.z * cos; - dest.x = this.x; - dest.y = y; - dest.z = z; - dest.w = this.w; - return dest; - } - - /** - * Rotate this vector the specified radians around the Y axis. - * - * @param angle - * the angle in radians - * @return this - */ - public Vector4f rotateY(float angle) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float x = this.x * cos + this.z * sin; - float z = -this.x * sin + this.z * cos; - this.x = x; - this.z = z; - return this; - } - - public Vector4f rotateY(float angle, Vector4f dest) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float x = this.x * cos + this.z * sin; - float z = -this.x * sin + this.z * cos; - dest.x = x; - dest.y = this.y; - dest.z = z; - dest.w = this.w; - return dest; - } - - /** - * Rotate this vector the specified radians around the Z axis. - * - * @param angle - * the angle in radians - * @return this - */ - public Vector4f rotateZ(float angle) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float x = this.x * cos - this.y * sin; - float y = this.x * sin + this.y * cos; - this.x = x; - this.y = y; - return this; - } - - public Vector4f rotateZ(float angle, Vector4f dest) { - float sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); - float x = this.x * cos - this.y * sin; - float y = this.x * sin + this.y * cos; - dest.x = x; - dest.y = y; - dest.z = this.z; - dest.w = this.w; - return dest; - } - - public float lengthSquared() { - return Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w))); - } - - /** - * Get the length squared of a 4-dimensional single-precision vector. - * - * @param x the vector's x component - * @param y the vector's y component - * @param z the vector's z component - * @param w the vector's w component - * - * @return the length squared of the given vector - * - * @author F. Neurath - */ - public static float lengthSquared(float x, float y, float z, float w) { - return Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w))); - } - - /** - * Get the length squared of a 4-dimensional int vector. - * - * @param x the vector's x component - * @param y the vector's y component - * @param z the vector's z component - * @param w the vector's w component - * - * @return the length squared of the given vector - */ - public static float lengthSquared(int x, int y, int z, int w) { - return Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w))); - } - - public float length() { - return Math.sqrt(Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w)))); - } - - /** - * Get the length of a 4-dimensional single-precision vector. - * - * @param x The vector's x component - * @param y The vector's y component - * @param z The vector's z component - * @param w The vector's w component - * - * @return the length of the given vector - * - * @author F. Neurath - */ - public static float length(float x, float y, float z, float w) { - return Math.sqrt(Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w)))); - } - - /** - * Normalizes this vector. - * - * @return this - */ - public Vector4f normalize() { - float invLength = 1.0f / length(); - this.x = x * invLength; - this.y = y * invLength; - this.z = z * invLength; - this.w = w * invLength; - return this; - } - - public Vector4f normalize(Vector4f dest) { - float invLength = 1.0f / length(); - dest.x = x * invLength; - dest.y = y * invLength; - dest.z = z * invLength; - dest.w = w * invLength; - return dest; - } - - /** - * Scale this vector to have the given length. - * - * @param length - * the desired length - * @return this - */ - public Vector4f normalize(float length) { - float invLength = 1.0f / length() * length; - this.x = x * invLength; - this.y = y * invLength; - this.z = z * invLength; - this.w = w * invLength; - return this; - } - - public Vector4f normalize(float length, Vector4f dest) { - float invLength = 1.0f / length() * length; - dest.x = x * invLength; - dest.y = y * invLength; - dest.z = z * invLength; - dest.w = w * invLength; - return dest; - } - - /** - * Normalize this vector by computing only the norm of (x, y, z). - * - * @return this - */ - public Vector4f normalize3() { - float invLength = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))); - this.x = x * invLength; - this.y = y * invLength; - this.z = z * invLength; - this.w = w * invLength; - return this; - } - - public Vector4f normalize3(Vector4f dest) { - float invLength = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))); - dest.x = x * invLength; - dest.y = y * invLength; - dest.z = z * invLength; - dest.w = w * invLength; - return dest; - } - - public float distance(Vector4fc v) { - float dx = this.x - v.x(); - float dy = this.y - v.y(); - float dz = this.z - v.z(); - float dw = this.w - v.w(); - return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, Math.fma(dz, dz, dw * dw)))); - } - - public float distance(float x, float y, float z, float w) { - float dx = this.x - x; - float dy = this.y - y; - float dz = this.z - z; - float dw = this.w - w; - return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, Math.fma(dz, dz, dw * dw)))); - } - - public float distanceSquared(Vector4fc v) { - float dx = this.x - v.x(); - float dy = this.y - v.y(); - float dz = this.z - v.z(); - float dw = this.w - v.w(); - return Math.fma(dx, dx, Math.fma(dy, dy, Math.fma(dz, dz, dw * dw))); - } - - public float distanceSquared(float x, float y, float z, float w) { - float dx = this.x - x; - float dy = this.y - y; - float dz = this.z - z; - float dw = this.w - w; - return Math.fma(dx, dx, Math.fma(dy, dy, Math.fma(dz, dz, dw * dw))); - } - - /** - * Return the distance between (x1, y1, z1, w1) and (x2, y2, z2, w2). - * - * @param x1 - * the x component of the first vector - * @param y1 - * the y component of the first vector - * @param z1 - * the z component of the first vector - * @param w1 - * the w component of the first vector - * @param x2 - * the x component of the second vector - * @param y2 - * the y component of the second vector - * @param z2 - * the z component of the second vector - * @param w2 - * the 2 component of the second vector - * @return the euclidean distance - */ - public static float distance(float x1, float y1, float z1, float w1, float x2, float y2, float z2, float w2) { - float dx = x1 - x2; - float dy = y1 - y2; - float dz = z1 - z2; - float dw = w1 - w2; - return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, Math.fma(dz, dz, dw * dw)))); - } - - /** - * Return the squared distance between (x1, y1, z1, w1) and (x2, y2, z2, w2). - * - * @param x1 - * the x component of the first vector - * @param y1 - * the y component of the first vector - * @param z1 - * the z component of the first vector - * @param w1 - * the w component of the first vector - * @param x2 - * the x component of the second vector - * @param y2 - * the y component of the second vector - * @param z2 - * the z component of the second vector - * @param w2 - * the w component of the second vector - * @return the euclidean distance squared - */ - public static float distanceSquared(float x1, float y1, float z1, float w1, float x2, float y2, float z2, float w2) { - float dx = x1 - x2; - float dy = y1 - y2; - float dz = z1 - z2; - float dw = w1 - w2; - return Math.fma(dx, dx, Math.fma(dy, dy, Math.fma(dz, dz, dw * dw))); - } - - public float dot(Vector4fc v) { - return Math.fma(this.x, v.x(), Math.fma(this.y, v.y(), Math.fma(this.z, v.z(), this.w * v.w()))); - } - - public float dot(float x, float y, float z, float w) { - return Math.fma(this.x, x, Math.fma(this.y, y, Math.fma(this.z, z, this.w * w))); - } - - public float angleCos(Vector4fc v) { - float x = this.x, y = this.y, z = this.z, w = this.w; - float length1Squared = Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w))); - float length2Squared = Math.fma(v.x(), v.x(), Math.fma(v.y(), v.y(), Math.fma(v.z(), v.z(), v.w() * v.w()))); - float dot = Math.fma(x, v.x(), Math.fma(y, v.y(), Math.fma(z, v.z(), w * v.w()))); - return dot / Math.sqrt(length1Squared * length2Squared); - } - - public float angle(Vector4fc v) { - float cos = angleCos(v); - // This is because sometimes cos goes above 1 or below -1 because of lost precision - cos = cos < 1 ? cos : 1; - cos = cos > -1 ? cos : -1; - return Math.acos(cos); - } - - /** - * Set all components to zero. - * - * @return this - */ - public Vector4f zero() { - this.x = 0; - this.y = 0; - this.z = 0; - this.w = 0; - return this; - } - - /** - * Negate this vector. - * - * @return this - */ - public Vector4f negate() { - this.x = -x; - this.y = -y; - this.z = -z; - this.w = -w; - return this; - } - - public Vector4f negate(Vector4f dest) { - dest.x = -x; - dest.y = -y; - dest.z = -z; - dest.w = -w; - return dest; - } - - /** - * Return a string representation of this vector. - *

- * This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-". - * - * @return the string representation - */ - public String toString() { - return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT)); - } - - /** - * Return a string representation of this vector by formatting the vector components with the given {@link NumberFormat}. - * - * @param formatter - * the {@link NumberFormat} used to format the vector components with - * @return the string representation - */ - public String toString(NumberFormat formatter) { - return "(" + Runtime.format(x, formatter) + " " + Runtime.format(y, formatter) + " " + Runtime.format(z, formatter) + " " + Runtime.format(w, formatter) + ")"; - } - - public void writeExternal(ObjectOutput out) throws IOException { - out.writeFloat(x); - out.writeFloat(y); - out.writeFloat(z); - out.writeFloat(w); - } - - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - this.set(in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); - } - - /** - * Set the components of this vector to be the component-wise minimum of this and the other vector. - * - * @param v - * the other vector - * @return this - */ - public Vector4f min(Vector4fc v) { - float x = this.x, y = this.y, z = this.z, w = this.w; - this.x = x < v.x() ? x : v.x(); - this.y = y < v.y() ? y : v.y(); - this.z = z < v.z() ? z : v.z(); - this.w = w < v.w() ? w : v.w(); - return this; - } - - public Vector4f min(Vector4fc v, Vector4f dest) { - float x = this.x, y = this.y, z = this.z, w = this.w; - dest.x = x < v.x() ? x : v.x(); - dest.y = y < v.y() ? y : v.y(); - dest.z = z < v.z() ? z : v.z(); - dest.w = w < v.w() ? w : v.w(); - return dest; - } - - /** - * Set the components of this vector to be the component-wise maximum of this and the other vector. - * - * @param v - * the other vector - * @return this - */ - public Vector4f max(Vector4fc v) { - float x = this.x, y = this.y, z = this.z, w = this.w; - this.x = x > v.x() ? x : v.x(); - this.y = y > v.y() ? y : v.y(); - this.z = z > v.z() ? z : v.z(); - this.w = w > v.w() ? w : v.w(); - return this; - } - - public Vector4f max(Vector4fc v, Vector4f dest) { - float x = this.x, y = this.y, z = this.z, w = this.w; - dest.x = x > v.x() ? x : v.x(); - dest.y = y > v.y() ? y : v.y(); - dest.z = z > v.z() ? z : v.z(); - dest.w = w > v.w() ? w : v.w(); - return dest; - } - - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(w); - 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; - Vector4f other = (Vector4f) obj; - if (Float.floatToIntBits(w) != Float.floatToIntBits(other.w)) - 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 boolean equals(Vector4fc v, float delta) { - if (this == v) - return true; - if (v == null) - return false; - if (!(v instanceof Vector4fc)) - return false; - if (!Runtime.equals(x, v.x(), delta)) - return false; - if (!Runtime.equals(y, v.y(), delta)) - return false; - if (!Runtime.equals(z, v.z(), delta)) - return false; - if (!Runtime.equals(w, v.w(), delta)) - return false; - return true; - } - - public boolean equals(float x, float y, float z, float w) { - if (Float.floatToIntBits(this.x) != Float.floatToIntBits(x)) - return false; - if (Float.floatToIntBits(this.y) != Float.floatToIntBits(y)) - return false; - if (Float.floatToIntBits(this.z) != Float.floatToIntBits(z)) - return false; - if (Float.floatToIntBits(this.w) != Float.floatToIntBits(w)) - return false; - return true; - } - - public Vector4f smoothStep(Vector4fc v, float t, Vector4f dest) { - float t2 = t * t; - float t3 = t2 * t; - float x = this.x, y = this.y, z = this.z, w = this.w; - dest.x = (x + x - v.x() - v.x()) * t3 + (3.0f * v.x() - 3.0f * x) * t2 + x * t + x; - dest.y = (y + y - v.y() - v.y()) * t3 + (3.0f * v.y() - 3.0f * y) * t2 + y * t + y; - dest.z = (z + z - v.z() - v.z()) * t3 + (3.0f * v.z() - 3.0f * z) * t2 + z * t + z; - dest.w = (w + w - v.w() - v.w()) * t3 + (3.0f * v.w() - 3.0f * w) * t2 + w * t + w; - return dest; - } - - public Vector4f hermite(Vector4fc t0, Vector4fc v1, Vector4fc t1, float t, Vector4f dest) { - float t2 = t * t; - float t3 = t2 * t; - float x = this.x, y = this.y, z = this.z, w = this.w; - dest.x = (x + x - v1.x() - v1.x() + t1.x() + t0.x()) * t3 + (3.0f * v1.x() - 3.0f * x - t0.x() - t0.x() - t1.x()) * t2 + x * t + x; - dest.y = (y + y - v1.y() - v1.y() + t1.y() + t0.y()) * t3 + (3.0f * v1.y() - 3.0f * y - t0.y() - t0.y() - t1.y()) * t2 + y * t + y; - dest.z = (z + z - v1.z() - v1.z() + t1.z() + t0.z()) * t3 + (3.0f * v1.z() - 3.0f * z - t0.z() - t0.z() - t1.z()) * t2 + z * t + z; - dest.w = (w + w - v1.w() - v1.w() + t1.w() + t0.w()) * t3 + (3.0f * v1.w() - 3.0f * w - t0.w() - t0.w() - t1.w()) * t2 + w * t + w; - return dest; - } - - /** - * Linearly interpolate this and other using the given interpolation factor t - * and store the result in this. - *

- * If t is 0.0 then the result is this. If the interpolation factor is 1.0 - * then the result is other. - * - * @param other - * the other vector - * @param t - * the interpolation factor between 0.0 and 1.0 - * @return this - */ - public Vector4f lerp(Vector4fc other, float t) { - this.x = Math.fma(other.x() - x, t, x); - this.y = Math.fma(other.y() - y, t, y); - this.z = Math.fma(other.z() - z, t, z); - this.w = Math.fma(other.w() - w, t, w); - return this; - } - - public Vector4f lerp(Vector4fc other, float t, Vector4f dest) { - dest.x = Math.fma(other.x() - x, t, x); - dest.y = Math.fma(other.y() - y, t, y); - dest.z = Math.fma(other.z() - z, t, z); - dest.w = Math.fma(other.w() - w, t, w); - return dest; - } - - public float get(int component) throws IllegalArgumentException { - switch (component) { - case 0: - return x; - case 1: - return y; - case 2: - return z; - case 3: - return w; - default: - throw new IllegalArgumentException(); - } - } - - public Vector4f get(Vector4f dest) { - dest.x = this.x(); - dest.y = this.y(); - dest.z = this.z(); - dest.w = this.w(); - return dest; - } - - public int maxComponent() { - float absX = Math.abs(x); - float absY = Math.abs(y); - float absZ = Math.abs(z); - float absW = Math.abs(w); - if (absX >= absY && absX >= absZ && absX >= absW) { - return 0; - } else if (absY >= absZ && absY >= absW) { - return 1; - } else if (absZ >= absW) { - return 2; - } - return 3; - } - - public int minComponent() { - float absX = Math.abs(x); - float absY = Math.abs(y); - float absZ = Math.abs(z); - float absW = Math.abs(w); - if (absX < absY && absX < absZ && absX < absW) { - return 0; - } else if (absY < absZ && absY < absW) { - return 1; - } else if (absZ < absW) { - return 2; - } - return 3; - } - - /** - * Set each component of this vector to 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. - * - * @return this - */ - public Vector4f floor() { - this.x = Math.floor(x); - this.y = Math.floor(y); - this.z = Math.floor(z); - this.w = Math.floor(w); - return this; - } - - public Vector4f floor(Vector4f dest) { - dest.x = Math.floor(x); - dest.y = Math.floor(y); - dest.z = Math.floor(z); - dest.w = Math.floor(w); - return dest; - } - - /** - * Set each component of this vector to 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. - * - * @return this - */ - public Vector4f ceil() { - this.x = Math.ceil(x); - this.y = Math.ceil(y); - this.z = Math.ceil(z); - this.w = Math.ceil(w); - return this; - } - - public Vector4f ceil(Vector4f dest) { - dest.x = Math.ceil(x); - dest.y = Math.ceil(y); - dest.z = Math.ceil(z); - dest.w = Math.ceil(w); - return dest; - } - - /** - * Set each component of this vector to the closest float that is equal to - * a mathematical integer, with ties rounding to positive infinity. - * - * @return this - */ - public Vector4f round() { - this.x = Math.round(x); - this.y = Math.round(y); - this.z = Math.round(z); - this.w = Math.round(w); - return this; - } - - public Vector4f round(Vector4f dest) { - dest.x = Math.round(x); - dest.y = Math.round(y); - dest.z = Math.round(z); - dest.w = Math.round(w); - return dest; - } - - public boolean isFinite() { - return Math.isFinite(x) && Math.isFinite(y) && Math.isFinite(z) && Math.isFinite(w); - } - - /** - * Compute the absolute of each of this vector's components. - * - * @return this - */ - public Vector4f absolute() { - this.x = Math.abs(x); - this.y = Math.abs(y); - this.z = Math.abs(z); - this.w = Math.abs(w); - return this; - } - - public Vector4f absolute(Vector4f dest) { - dest.x = Math.abs(x); - dest.y = Math.abs(y); - dest.z = Math.abs(z); - dest.w = Math.abs(w); - return dest; - } - - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/util/joml/Vector4fc.java b/src/main/java/com/jozufozu/flywheel/util/joml/Vector4fc.java deleted file mode 100644 index 6242c01a1..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/joml/Vector4fc.java +++ /dev/null @@ -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}. - *

- * This method will not increment the position of the given FloatBuffer. - *

- * 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 x, y, z, w 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. - *

- * 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 x, y, z, w 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}. - *

- * This method will not increment the position of the given ByteBuffer. - *

- * 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 x, y, z, w 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. - *

- * 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 x, y, z, w order - * @return the passed in buffer - */ - ByteBuffer get(int index, ByteBuffer buffer); - - /** - * Store this vector at the given off-heap memory address. - *

- * This method will throw an {@link UnsupportedOperationException} when JOML is used with `-Djoml.nounsafe`. - *

- * 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. - * - * @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 dest. - * - * @param v - * the vector to subtract from this - * @param dest - * will hold the result - * @return dest - */ - Vector4f sub(Vector4fc v, Vector4f dest); - - /** - * Subtract (x, y, z, w) from this and store the result in dest. - * - * @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 dest. - * - * @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 dest. - * - * @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 a * b to this vector - * and store the result in dest. - * - * @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 a * b to this vector - * and store the result in dest. - * - * @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 this * a to b - * and store the result in dest. - * - * @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 this * a to b - * and store the result in dest. - * - * @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 dest. - * - * @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 dest. - * - * @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 - * dest. - * - * @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 mat with this Vector4f and store the result in - * dest. - * - * @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 - * dest. - * - * @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 mat with this Vector4f and store the result in - * dest. - * - * @param mat - * the affine matrix whose transpose to multiply the vector with - * @param dest - * the destination vector to hold the result - * @return dest - */ - Vector4f mulAffineTranspose(Matrix4fc mat, Vector4f dest); - - /** - * Multiply the given matrix mat with this Vector4f, perform perspective division - * and store the result in dest. - * - * @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 mat with this Vector4f, perform perspective division - * and store the (x, y, z) result in dest. - * - * @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 dest. - * - * @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 dest. - * - * @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 dest. - * - * @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 dest. - * - * @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 quat and store the result in dest. - * - * @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 dest. - * - * @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 dest. - * - * @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 dest. - * - * @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 dest. - * - * @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 dest. - * - * @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 dest. - * - * @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 (x, y, z) and store the result in dest. - * - * @param dest - * will hold the result - * @return dest - */ - Vector4f normalize3(Vector4f dest); - - /** - * Return the distance between this Vector and v. - * - * @param v - * the other vector - * @return the distance - */ - float distance(Vector4fc v); - - /** - * Return the distance between this vector and (x, y, z, w). - * - * @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 v. - * - * @param v - * the other vector - * @return the squared of the distance - */ - float distanceSquared(Vector4fc v); - - /** - * Return the square of the distance between this vector and - * (x, y, z, w). - * - * @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 v - * . - * - * @param v - * the other vector - * @return the dot product - */ - float dot(Vector4fc v); - - /** - * Compute the dot product (inner product) of this vector and (x, y, z, w). - * - * @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 Math.cos(angle(v)). - * - * @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 dest. - * - * @param dest - * will hold the result - * @return dest - */ - Vector4f negate(Vector4f dest); - - /** - * Set the components of dest 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 dest 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 this and other using the given interpolation factor t - * and store the result in dest. - *

- * If t is 0.0 then the result is this. If the interpolation factor is 1.0 - * then the result is other. - * - * @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 this vector and the given vector v and - * store the result in dest. - * - * @param v - * the other vector - * @param t - * the interpolation factor, within [0..1] - * @param dest - * will hold the result - * @return dest - */ - Vector4f smoothStep(Vector4fc v, float t, Vector4f dest); - - /** - * Compute a hermite interpolation between this vector and its - * associated tangent t0 and the given vector v - * with its tangent t1 and store the result in - * dest. - * - * @param t0 - * the tangent of this vector - * @param v1 - * the other vector - * @param t1 - * the tangent of the other vector - * @param t - * the interpolation factor, within [0..1] - * @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 [0..3] - * @return the value - * @throws IllegalArgumentException if component is not within [0..3] - */ - float get(int component) throws IllegalArgumentException; - - /** - * Set the components of the given vector dest to those of this 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 [0..3] - */ - int maxComponent(); - - /** - * Determine the component with the smallest (towards zero) absolute value. - * - * @return the component index, within [0..3] - */ - 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 - * dest. - * - * @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 - * dest. - * - * @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 dest. - * - * @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 dest. - * - * @param dest - * will hold the result - * @return dest - */ - Vector4f absolute(Vector4f dest); - - /** - * Compare the vector components of this vector with the given vector using the given delta - * and return whether all of them are equal within a maximum difference of delta. - *

- * 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 true whether all of the vector components are equal; false otherwise - */ - boolean equals(Vector4fc v, float delta); - - /** - * Compare the vector components of this vector with the given (x, y, z, w) - * 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 true if all the vector components are equal - */ - boolean equals(float x, float y, float z, float w); - -} diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java b/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java index abd583d14..d90edc46d 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java @@ -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;