WIP: initial epic fight core extraction (Phase 0)
83 files forkés d'Epic Fight (~18k LOC). Base non-compilable en l'état.
Contenu extrait :
- math/ — OpenMatrix4f, Vec3f/4f/2f, QuaternionUtils, MathUtils, ...
- armature/ — Armature, Joint, JointTransform, HumanoidArmature
- anim/ — Animator, ServerAnimator, ClientAnimator, LivingMotion, ...
- anim/types/ — StaticAnimation, DynamicAnimation, MovementAnimation, LinkAnimation,
ConcurrentLinkAnimation, LayerOffAnimation, EntityState
- anim/client/ — Layer, ClientAnimator, JointMask
- mesh/ — SkinnedMesh, SingleGroupVertexBuilder, Mesh, HumanoidMesh, ...
- cloth/ — AbstractSimulator, ClothSimulator (dépendance transitive de StaticMesh)
- asset/ — JsonAssetLoader, AssetAccessor
- patch/ — EntityPatch, LivingEntityPatch, PlayerPatch, ClientPlayerPatch
- util/ — ParseUtil, TypeFlexibleHashMap
- exception/ — AssetLoadingException
- event/ — PatchedRenderersEvent, PrepareModelEvent, RegisterResourceLayersEvent
- render/ — TiedUpRenderTypes
Headers GPLv3 + attribution injectés sur tous les .java.
Package declarations fixées sur Armature.java et TiedUpRenderTypes.java.
115 imports résiduels à résoudre manuellement :
- yesman.epicfight.main (EpicFightMod, EpicFightSharedConstants) — 30
- yesman.epicfight.gameasset (Animations, Armatures, EpicFightSounds) — 12
- yesman.epicfight.api.physics + physics.ik (combat physics) — 16
- yesman.epicfight.network.* (combat packets) — 13
- yesman.epicfight.world.* (combat entity logic) — 10
- yesman.epicfight.config.ClientConfig — 3
- yesman.epicfight.skill, .client.gui, .particle, .collider — divers combat/UI
Stratégie fix (2-3 sem manuel) : strip usage combat, stubs pour refs
core (EpicFightMod → TiedUpMod, SharedConstants → TiedUpRigConstants,
ClientConfig → TiedUpAnimationConfig).
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.math;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import com.tiedup.remake.rig.armature.JointTransform;
|
||||
|
||||
public class AnimationTransformEntry {
|
||||
private static final String[] BINDING_PRIORITY = {JointTransform.PARENT, JointTransform.JOINT_LOCAL_TRANSFORM, JointTransform.ANIMATION_TRANSFORM, JointTransform.RESULT1, JointTransform.RESULT2};
|
||||
private final Map<String, Pair<OpenMatrix4f, MatrixOperation>> matrices = Maps.newHashMap();
|
||||
|
||||
public void put(String entryPosition, OpenMatrix4f matrix) {
|
||||
this.put(entryPosition, matrix, OpenMatrix4f::mul);
|
||||
}
|
||||
|
||||
public void put(String entryPosition, OpenMatrix4f matrix, MatrixOperation operation) {
|
||||
if (this.matrices.containsKey(entryPosition)) {
|
||||
Pair<OpenMatrix4f, MatrixOperation> appliedTransform = this.matrices.get(entryPosition);
|
||||
OpenMatrix4f result = appliedTransform.getSecond().mul(appliedTransform.getFirst(), matrix, null);
|
||||
this.matrices.put(entryPosition, Pair.of(result, operation));
|
||||
} else {
|
||||
this.matrices.put(entryPosition, Pair.of(new OpenMatrix4f(matrix), operation));
|
||||
}
|
||||
}
|
||||
|
||||
public OpenMatrix4f getResult() {
|
||||
OpenMatrix4f result = new OpenMatrix4f();
|
||||
|
||||
for (String entryName : BINDING_PRIORITY) {
|
||||
if (this.matrices.containsKey(entryName)) {
|
||||
Pair<OpenMatrix4f, MatrixOperation> pair = this.matrices.get(entryName);
|
||||
pair.getSecond().mul(result, pair.getFirst(), result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
599
src/main/java/com/tiedup/remake/rig/math/MathUtils.java
Normal file
599
src/main/java/com/tiedup/remake/rig/math/MathUtils.java
Normal file
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.math;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.joml.Math;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector4i;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class MathUtils {
|
||||
public static final Vec3 XP = new Vec3(1.0D, 0.0D, 0.0D);
|
||||
public static final Vec3 XN = new Vec3(-1.0D, 0.0D, 0.0D);
|
||||
public static final Vec3 YP = new Vec3(0.0D, 1.0D, 0.0D);
|
||||
public static final Vec3 YN = new Vec3(0.0D, -1.0D, 0.0D);
|
||||
public static final Vec3 ZP = new Vec3(0.0D, 0.0D, 1.0D);
|
||||
public static final Vec3 ZN = new Vec3(0.0D, 0.0D, -1.0D);
|
||||
|
||||
public static OpenMatrix4f getModelMatrixIntegral(float xPosO, float xPos, float yPosO, float yPos, float zPosO, float zPos, float xRotO, float xRot, float yRotO, float yRot, float partialTick, float scaleX, float scaleY, float scaleZ) {
|
||||
OpenMatrix4f modelMatrix = new OpenMatrix4f();
|
||||
Vec3f translation = new Vec3f(-(xPosO + (xPos - xPosO) * partialTick), ((yPosO + (yPos - yPosO) * partialTick)), -(zPosO + (zPos - zPosO) * partialTick));
|
||||
float partialXRot = Mth.rotLerp(partialTick, xRotO, xRot);
|
||||
float partialYRot = Mth.rotLerp(partialTick, yRotO, yRot);
|
||||
modelMatrix.translate(translation).rotateDeg(-partialYRot, Vec3f.Y_AXIS).rotateDeg(-partialXRot, Vec3f.X_AXIS).scale(scaleX, scaleY, scaleZ);
|
||||
|
||||
return modelMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blender 2.79 bezier curve
|
||||
* @param t: 0 ~ 1
|
||||
* @retur
|
||||
*/
|
||||
public static double bezierCurve(double t) {
|
||||
double p1 = 0.0D;
|
||||
double p2 = 0.0D;
|
||||
double p3 = 1.0D;
|
||||
double p4 = 1.0D;
|
||||
double v1, v2, v3, v4;
|
||||
|
||||
v1 = p1;
|
||||
v2 = 3.0D * (p2 - p1);
|
||||
v3 = 3.0D * (p1 - 2.0D * p2 + p3);
|
||||
v4 = p4 - p1 + 3.0D * (p2 - p3);
|
||||
|
||||
return v1 + t * v2 + t * t * v3 + t * t * t * v4;
|
||||
}
|
||||
|
||||
public static float bezierCurve(float t) {
|
||||
return (float)bezierCurve((double)t);
|
||||
}
|
||||
|
||||
public static int getSign(double value) {
|
||||
return value > 0.0D ? 1 : -1;
|
||||
}
|
||||
|
||||
public static Vec3 getVectorForRotation(float pitch, float yaw) {
|
||||
float f = pitch * (float) Math.PI / 180F;
|
||||
float f1 = -yaw * (float) Math.PI / 180F;
|
||||
float f2 = Mth.cos(f1);
|
||||
float f3 = Mth.sin(f1);
|
||||
float f4 = Mth.cos(f);
|
||||
float f5 = Mth.sin(f);
|
||||
|
||||
return new Vec3(f3 * f4, -f5, f2 * f4);
|
||||
}
|
||||
|
||||
public static float lerpBetween(float f1, float f2, float zero2one) {
|
||||
float f = 0;
|
||||
|
||||
for (f = f2 - f1; f < -180.0F; f += 360.0F) {
|
||||
}
|
||||
|
||||
while (f >= 180.0F) {
|
||||
f -= 360.0F;
|
||||
}
|
||||
|
||||
return f1 + zero2one * f;
|
||||
}
|
||||
|
||||
public static float rotlerp(float from, float to, float limit) {
|
||||
float f = Mth.wrapDegrees(to - from);
|
||||
|
||||
if (f > limit) {
|
||||
f = limit;
|
||||
}
|
||||
|
||||
if (f < -limit) {
|
||||
f = -limit;
|
||||
}
|
||||
|
||||
float f1 = from + f;
|
||||
|
||||
while (f1 >= 180.0F) {
|
||||
f1 -= 360.0F;
|
||||
}
|
||||
|
||||
while (f1 <= -180.0F) {
|
||||
f1 += 360.0F;
|
||||
}
|
||||
|
||||
return f1;
|
||||
}
|
||||
|
||||
public static float rotWrap(double d) {
|
||||
while (d >= 180.0) {
|
||||
d -= 360.0;
|
||||
}
|
||||
while (d < -180.0) {
|
||||
d += 360.0;
|
||||
}
|
||||
return (float)d;
|
||||
}
|
||||
|
||||
public static float wrapRadian(float pValue) {
|
||||
float maxRot = (float)Math.PI * 2.0F;
|
||||
float f = pValue % maxRot;
|
||||
|
||||
if (f >= Math.PI) {
|
||||
f -= maxRot;
|
||||
}
|
||||
|
||||
if (f < -Math.PI) {
|
||||
f += maxRot;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public static float lerpDegree(float from, float to, float progression) {
|
||||
from = Mth.wrapDegrees(from);
|
||||
to = Mth.wrapDegrees(to);
|
||||
|
||||
if (Math.abs(from - to) > 180.0F) {
|
||||
if (to < 0.0F) {
|
||||
from -= 360.0F;
|
||||
} else if (to > 0.0F) {
|
||||
from += 360.0F;
|
||||
}
|
||||
}
|
||||
|
||||
return Mth.lerp(progression, from, to);
|
||||
}
|
||||
|
||||
public static float findNearestRotation(float src, float rotation) {
|
||||
float diff = Math.abs(src - rotation);
|
||||
float idealRotation = rotation;
|
||||
int sign = Mth.sign(src - rotation);
|
||||
|
||||
if (sign == 0) {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
float next = idealRotation + sign * 360.0F;
|
||||
|
||||
if (Math.abs(src - next) > diff) {
|
||||
return idealRotation;
|
||||
}
|
||||
|
||||
idealRotation = next;
|
||||
diff = Math.abs(src - next);
|
||||
}
|
||||
}
|
||||
|
||||
public static Vec3 getNearestVector(Vec3 from, Vec3... vectors) {
|
||||
double minLength = 1000000.0D;
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < vectors.length; i++) {
|
||||
if (vectors[i] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double distSqr = from.distanceToSqr(vectors[i]);
|
||||
|
||||
if (distSqr < minLength) {
|
||||
minLength = distSqr;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return vectors[index];
|
||||
}
|
||||
|
||||
public static Vec3 getNearestVector(Vec3 from, List<Vec3> vectors) {
|
||||
return getNearestVector(from, vectors.toArray(new Vec3[0]));
|
||||
}
|
||||
|
||||
public static int greatest(int... iList) {
|
||||
int max = Integer.MIN_VALUE;
|
||||
|
||||
for (int i : iList) {
|
||||
if (max < i) {
|
||||
max = i;
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
public static int least(int... iList) {
|
||||
int min = Integer.MAX_VALUE;
|
||||
|
||||
for (int i : iList) {
|
||||
if (min > i) {
|
||||
min = i;
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
public static float greatest(float... fList) {
|
||||
float max = -1000000.0F;
|
||||
|
||||
for (float f : fList) {
|
||||
if (max < f) {
|
||||
max = f;
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
public static float least(float... fList) {
|
||||
float min = 1000000.0F;
|
||||
|
||||
for (float f : fList) {
|
||||
if (min > f) {
|
||||
min = f;
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
public static double greatest(double... dList) {
|
||||
double max = -1000000.0D;
|
||||
|
||||
for (double d : dList) {
|
||||
if (max < d) {
|
||||
max = d;
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
public static double least(double... dList) {
|
||||
double min = 1000000.0D;
|
||||
|
||||
for (double d : dList) {
|
||||
if (min > d) {
|
||||
min = d;
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true, since = "1.21.1")
|
||||
public static void translateStack(PoseStack poseStack, OpenMatrix4f mat) {
|
||||
poseStack.translate(mat.m30, mat.m31, mat.m32);
|
||||
}
|
||||
|
||||
private static final OpenMatrix4f OPEN_MATRIX_BUFFER = new OpenMatrix4f();
|
||||
|
||||
@Deprecated(forRemoval = true, since = "1.21.1")
|
||||
public static void rotateStack(PoseStack poseStack, OpenMatrix4f mat) {
|
||||
OpenMatrix4f.transpose(mat, OPEN_MATRIX_BUFFER);
|
||||
poseStack.mulPose(getQuaternionFromMatrix(OPEN_MATRIX_BUFFER));
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true, since = "1.21.1")
|
||||
public static void scaleStack(PoseStack poseStack, OpenMatrix4f mat) {
|
||||
OpenMatrix4f.transpose(mat, OPEN_MATRIX_BUFFER);
|
||||
Vector3f vector = getScaleVectorFromMatrix(OPEN_MATRIX_BUFFER);
|
||||
poseStack.scale(vector.x(), vector.y(), vector.z());
|
||||
}
|
||||
|
||||
private static final Matrix4f MATRIX4F = new Matrix4f();
|
||||
private static final Matrix3f MATRIX3F = new Matrix3f();
|
||||
|
||||
public static void mulStack(PoseStack poseStack, OpenMatrix4f mat) {
|
||||
OpenMatrix4f.exportToMojangMatrix(mat, MATRIX4F);
|
||||
MATRIX3F.set(MATRIX4F);
|
||||
poseStack.mulPoseMatrix(MATRIX4F);
|
||||
poseStack.last().normal().mul(MATRIX3F);
|
||||
}
|
||||
|
||||
public static double getAngleBetween(Vec3f a, Vec3f b) {
|
||||
Vec3f normA = Vec3f.normalize(a, null);
|
||||
Vec3f normB = Vec3f.normalize(b, null);
|
||||
|
||||
double cos = (normA.x * normB.x + normA.y * normB.y + normA.z * normB.z);
|
||||
return Math.toDegrees(Math.acos(cos));
|
||||
}
|
||||
|
||||
public static double getAngleBetween(Vec3 a, Vec3 b) {
|
||||
Vec3 normA = a.normalize();
|
||||
Vec3 normB = b.normalize();
|
||||
|
||||
double cos = (normA.x * normB.x + normA.y * normB.y + normA.z * normB.z);
|
||||
return Math.toDegrees(Math.safeAcos(cos));
|
||||
}
|
||||
|
||||
public static float getAngleBetween(Quaternionf a, Quaternionf b) {
|
||||
float dot = a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
return 2.0F * (Math.safeAcos(MathUtils.getSign(dot) * b.w) - Math.safeAcos(a.w));
|
||||
}
|
||||
|
||||
public static double getXRotOfVector(Vec3 vec) {
|
||||
Vec3 normalized = vec.normalize();
|
||||
return -(Math.atan2(normalized.y, (float)Math.sqrt(normalized.x * normalized.x + normalized.z * normalized.z)) * (180D / Math.PI));
|
||||
}
|
||||
|
||||
public static double getYRotOfVector(Vec3 vec) {
|
||||
Vec3 normalized = vec.normalize();
|
||||
return Math.atan2(normalized.z, normalized.x) * (180D / Math.PI) - 90.0F;
|
||||
}
|
||||
|
||||
private static Quaternionf getQuaternionFromMatrix(OpenMatrix4f mat) {
|
||||
Quaternionf quat = new Quaternionf(0, 0, 0, 1);
|
||||
quat.setFromUnnormalized(OpenMatrix4f.exportToMojangMatrix(mat.transpose(null)));
|
||||
return quat;
|
||||
}
|
||||
|
||||
public static Vec3f lerpVector(Vec3f start, Vec3f end, float delta) {
|
||||
return lerpVector(start, end, delta, new Vec3f());
|
||||
}
|
||||
|
||||
public static Vec3f lerpVector(Vec3f start, Vec3f end, float delta, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
dest.x = start.x + (end.x - start.x) * delta;
|
||||
dest.y = start.y + (end.y - start.y) * delta;
|
||||
dest.z = start.z + (end.z - start.z) * delta;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static Vec3 lerpVector(Vec3 start, Vec3 end, float delta) {
|
||||
return new Vec3(start.x + (end.x - start.x) * delta, start.y + (end.y - start.y) * delta, start.z + (end.z - start.z) * delta);
|
||||
}
|
||||
|
||||
public static Vector3f lerpMojangVector(Vector3f start, Vector3f end, float delta) {
|
||||
float x = start.x() + (end.x() - start.x()) * delta;
|
||||
float y = start.y() + (end.y() - start.y()) * delta;
|
||||
float z = start.z() + (end.z() - start.z()) * delta;
|
||||
return new Vector3f(x, y, z);
|
||||
}
|
||||
|
||||
public static Vec3 projectVector(Vec3 from, Vec3 to) {
|
||||
double dot = to.dot(from);
|
||||
double normalScale = 1.0D / ((to.x * to.x) + (to.y * to.y) + (to.z * to.z));
|
||||
|
||||
return new Vec3(dot * to.x * normalScale, dot * to.y * normalScale, dot * to.z * normalScale);
|
||||
}
|
||||
|
||||
public static Vec3f projectVector(Vec3f from, Vec3f to, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
float dot = Vec3f.dot(to, from);
|
||||
float normalScale = 1.0F / ((to.x * to.x) + (to.y * to.y) + (to.z * to.z));
|
||||
|
||||
dest.x = dot * to.x * normalScale;
|
||||
dest.y = dot * to.y * normalScale;
|
||||
dest.z = dot * to.z * normalScale;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static void setQuaternion(Quaternionf quat, float x, float y, float z, float w) {
|
||||
quat.set(x, y, z, w);
|
||||
}
|
||||
|
||||
public static Quaternionf mulQuaternion(Quaternionf left, Quaternionf right, Quaternionf dest) {
|
||||
if (dest == null) {
|
||||
dest = new Quaternionf(0.0F, 0.0F, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
float f = left.x();
|
||||
float f1 = left.y();
|
||||
float f2 = left.z();
|
||||
float f3 = left.w();
|
||||
float f4 = right.x();
|
||||
float f5 = right.y();
|
||||
float f6 = right.z();
|
||||
float f7 = right.w();
|
||||
float i = f3 * f4 + f * f7 + f1 * f6 - f2 * f5;
|
||||
float j = f3 * f5 - f * f6 + f1 * f7 + f2 * f4;
|
||||
float k = f3 * f6 + f * f5 - f1 * f4 + f2 * f7;
|
||||
float r = f3 * f7 - f * f4 - f1 * f5 - f2 * f6;
|
||||
|
||||
dest.set(i, j, k, r);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static Quaternionf lerpQuaternion(Quaternionf from, Quaternionf to, float delta) {
|
||||
return lerpQuaternion(from, to, delta, null);
|
||||
}
|
||||
|
||||
public static Quaternionf lerpQuaternion(Quaternionf from, Quaternionf to, float delta, Quaternionf dest) {
|
||||
if (dest == null) {
|
||||
dest = new Quaternionf();
|
||||
}
|
||||
|
||||
float fromX = from.x();
|
||||
float fromY = from.y();
|
||||
float fromZ = from.z();
|
||||
float fromW = from.w();
|
||||
float toX = to.x();
|
||||
float toY = to.y();
|
||||
float toZ = to.z();
|
||||
float toW = to.w();
|
||||
float resultX;
|
||||
float resultY;
|
||||
float resultZ;
|
||||
float resultW;
|
||||
float dot = fromW * toW + fromX * toX + fromY * toY + fromZ * toZ;
|
||||
float blendI = 1.0F - delta;
|
||||
|
||||
if (dot < 0.0F) {
|
||||
resultW = blendI * fromW + delta * -toW;
|
||||
resultX = blendI * fromX + delta * -toX;
|
||||
resultY = blendI * fromY + delta * -toY;
|
||||
resultZ = blendI * fromZ + delta * -toZ;
|
||||
} else {
|
||||
resultW = blendI * fromW + delta * toW;
|
||||
resultX = blendI * fromX + delta * toX;
|
||||
resultY = blendI * fromY + delta * toY;
|
||||
resultZ = blendI * fromZ + delta * toZ;
|
||||
}
|
||||
|
||||
dest.set(resultX, resultY, resultZ, resultW);
|
||||
dest.normalize();
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
private static Vector3f getScaleVectorFromMatrix(OpenMatrix4f mat) {
|
||||
Vec3f a = new Vec3f(mat.m00, mat.m10, mat.m20);
|
||||
Vec3f b = new Vec3f(mat.m01, mat.m11, mat.m21);
|
||||
Vec3f c = new Vec3f(mat.m02, mat.m12, mat.m22);
|
||||
return new Vector3f(a.length(), b.length(), c.length());
|
||||
}
|
||||
|
||||
public static <T> Set<Set<T>> getSubset(Collection<T> collection) {
|
||||
Set<Set<T>> subsets = new HashSet<> ();
|
||||
List<T> asList = new ArrayList<> (collection);
|
||||
createSubset(0, asList, new HashSet<> (), subsets);
|
||||
|
||||
return subsets;
|
||||
}
|
||||
|
||||
private static <T> void createSubset(int idx, List<T> elements, Set<T> parent, Set<Set<T>> subsets) {
|
||||
for (int i = idx; i < elements.size(); i++) {
|
||||
Set<T> subset = new HashSet<> (parent);
|
||||
subset.add(elements.get(i));
|
||||
subsets.add(subset);
|
||||
|
||||
createSubset(i + 1, elements, subset, subsets);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getLeastAngleVectorIdx(Vec3f src, Vec3f... candidates) {
|
||||
int leastVectorIdx = -1;
|
||||
int current = 0;
|
||||
float maxDot = -10000.0F;
|
||||
|
||||
for (Vec3f normzlizedVec : Stream.of(candidates).map((vec) -> vec.normalize()).collect(Collectors.toList())) {
|
||||
float dot = Vec3f.dot(src, normzlizedVec);
|
||||
|
||||
if (maxDot < dot) {
|
||||
maxDot = dot;
|
||||
leastVectorIdx = current;
|
||||
}
|
||||
|
||||
current++;
|
||||
}
|
||||
|
||||
return leastVectorIdx;
|
||||
}
|
||||
|
||||
public static Vec3f getLeastAngleVector(Vec3f src, Vec3f... candidates) {
|
||||
return candidates[getLeastAngleVectorIdx(src, candidates)];
|
||||
}
|
||||
|
||||
public static boolean canBeSeen(Entity target, Entity watcher, double maxDistance) {
|
||||
if (target.level() != watcher.level()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double sqr = maxDistance * maxDistance;
|
||||
Level level = target.level();
|
||||
Vec3 vec1 = watcher.getEyePosition();
|
||||
|
||||
double height = target.getBoundingBox().maxY - target.getBoundingBox().minY;
|
||||
Vec3 vec2 = target.position().add(0.0D, height * 0.15D, 0.0D);
|
||||
Vec3 vec3 = target.position().add(0.0D, height * 0.5D, 0.0D);
|
||||
Vec3 vec4 = target.position().add(0.0D, height * 0.95D, 0.0D);
|
||||
|
||||
return vec1.distanceToSqr(vec2) < sqr && level.clip(new ClipContext(vec1, vec2, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, watcher)).getType() == HitResult.Type.MISS ||
|
||||
vec1.distanceToSqr(vec3) < sqr && level.clip(new ClipContext(vec1, vec3, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, watcher)).getType() == HitResult.Type.MISS ||
|
||||
vec1.distanceToSqr(vec4) < sqr && level.clip(new ClipContext(vec1, vec4, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, watcher)).getType() == HitResult.Type.MISS;
|
||||
}
|
||||
|
||||
public static int packColor(int r, int g, int b, int a) {
|
||||
int ir = r << 16;
|
||||
int ig = g << 8;
|
||||
int ib = b;
|
||||
int ia = a << 24;
|
||||
|
||||
return ir | ig | ib | ia;
|
||||
}
|
||||
|
||||
public static void unpackColor(int packedColor, Vector4i result) {
|
||||
int b = (packedColor & 0x000000FF);
|
||||
int g = (packedColor & 0x0000FF00) >>> 8;
|
||||
int r = (packedColor & 0x00FF0000) >>> 16;
|
||||
int a = (packedColor & 0xFF000000) >>> 24;
|
||||
|
||||
result.x = r;
|
||||
result.y = g;
|
||||
result.z = b;
|
||||
result.w = a;
|
||||
}
|
||||
|
||||
public static byte normalIntValue(float pNum) {
|
||||
return (byte)((int)(Mth.clamp(pNum, -1.0F, 1.0F) * 127.0F) & 255);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a value within bounds
|
||||
*/
|
||||
public static int wrapClamp(int value, int min, int max) {
|
||||
int stride = max - min + 1;
|
||||
while (value < min) value += stride;
|
||||
while (value > max) value -= stride;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the world coordinate system to -1~1 screen coord system
|
||||
* @param projection current projection matrix
|
||||
* @param modelView current model-view matrix
|
||||
* @param position a source vector to transform
|
||||
*/
|
||||
public static Vec2 worldToScreenCoord(Matrix4f projectionMatrix, Camera camera, Vec3 position) {
|
||||
Vector4f relativeCamera = new Vector4f((float)camera.getPosition().x() - (float)position.x(), (float)camera.getPosition().y() - (float)position.y(), (float)camera.getPosition().z() - (float)position.z(), 1.0F);
|
||||
relativeCamera.rotate(Axis.YP.rotationDegrees(camera.getYRot() + 180.0F));
|
||||
relativeCamera.rotate(Axis.XP.rotationDegrees(camera.getXRot()));
|
||||
relativeCamera.mul(projectionMatrix);
|
||||
|
||||
float depth = relativeCamera.w;
|
||||
relativeCamera.mul(1.0F / relativeCamera.w());
|
||||
|
||||
if (depth < 0.0F) {
|
||||
relativeCamera.x = -relativeCamera.x;
|
||||
relativeCamera.y = -relativeCamera.y;
|
||||
}
|
||||
|
||||
return new Vec2(relativeCamera.x(), relativeCamera.y());
|
||||
}
|
||||
|
||||
private MathUtils() {}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.math;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface MatrixOperation {
|
||||
OpenMatrix4f mul(OpenMatrix4f left, OpenMatrix4f right, OpenMatrix4f dest);
|
||||
}
|
||||
953
src/main/java/com/tiedup/remake/rig/math/OpenMatrix4f.java
Normal file
953
src/main/java/com/tiedup/remake/rig/math/OpenMatrix4f.java
Normal file
@@ -0,0 +1,953 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.math;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.joml.Math;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Quaternionf;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import com.tiedup.remake.rig.armature.JointTransform;
|
||||
|
||||
public class OpenMatrix4f {
|
||||
private static final FloatBuffer MATRIX_TRANSFORMER = ByteBuffer.allocateDirect(16 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||
private static final Vec3f VECTOR_STORAGE = new Vec3f();
|
||||
private static final Vec4f VEC4_STORAGE = new Vec4f();
|
||||
|
||||
public static final OpenMatrix4f IDENTITY = new OpenMatrix4f();
|
||||
|
||||
/*
|
||||
* m00 m01 m02 m03
|
||||
* m10 m11 m12 m13
|
||||
* m20 m21 m22 m23
|
||||
* m30 m31 m32 m33
|
||||
*/
|
||||
public float m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33;
|
||||
|
||||
private final boolean immutable;
|
||||
|
||||
public OpenMatrix4f() {
|
||||
this.setIdentity();
|
||||
this.immutable = false;
|
||||
}
|
||||
|
||||
public OpenMatrix4f(final OpenMatrix4f src) {
|
||||
this(src, false);
|
||||
}
|
||||
|
||||
public OpenMatrix4f(final OpenMatrix4f src, boolean immutable) {
|
||||
load(src);
|
||||
this.immutable = immutable;
|
||||
}
|
||||
|
||||
public OpenMatrix4f(final JointTransform jointTransform) {
|
||||
load(OpenMatrix4f.fromQuaternion(jointTransform.rotation()).translate(jointTransform.translation()).scale(jointTransform.scale()));
|
||||
this.immutable = false;
|
||||
}
|
||||
|
||||
public OpenMatrix4f(
|
||||
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;
|
||||
this.m01 = m01;
|
||||
this.m02 = m02;
|
||||
this.m03 = m03;
|
||||
this.m10 = m10;
|
||||
this.m11 = m11;
|
||||
this.m12 = m12;
|
||||
this.m13 = m13;
|
||||
this.m20 = m20;
|
||||
this.m21 = m21;
|
||||
this.m22 = m22;
|
||||
this.m23 = m23;
|
||||
this.m30 = m30;
|
||||
this.m31 = m31;
|
||||
this.m32 = m32;
|
||||
this.m33 = m33;
|
||||
this.immutable = false;
|
||||
}
|
||||
|
||||
public OpenMatrix4f setIdentity() {
|
||||
return setIdentity(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given matrix to be the identity matrix.
|
||||
* @param m The matrix to set to the identity
|
||||
* @return m
|
||||
*/
|
||||
public static OpenMatrix4f setIdentity(OpenMatrix4f m) {
|
||||
if (m.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
m.m00 = 1.0f;
|
||||
m.m01 = 0.0f;
|
||||
m.m02 = 0.0f;
|
||||
m.m03 = 0.0f;
|
||||
m.m10 = 0.0f;
|
||||
m.m11 = 1.0f;
|
||||
m.m12 = 0.0f;
|
||||
m.m13 = 0.0f;
|
||||
m.m20 = 0.0f;
|
||||
m.m21 = 0.0f;
|
||||
m.m22 = 1.0f;
|
||||
m.m23 = 0.0f;
|
||||
m.m30 = 0.0f;
|
||||
m.m31 = 0.0f;
|
||||
m.m32 = 0.0f;
|
||||
m.m33 = 1.0f;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public OpenMatrix4f load(OpenMatrix4f src) {
|
||||
return load(src, this);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f load(OpenMatrix4f src, @Nullable OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
dest.m00 = src.m00;
|
||||
dest.m01 = src.m01;
|
||||
dest.m02 = src.m02;
|
||||
dest.m03 = src.m03;
|
||||
dest.m10 = src.m10;
|
||||
dest.m11 = src.m11;
|
||||
dest.m12 = src.m12;
|
||||
dest.m13 = src.m13;
|
||||
dest.m20 = src.m20;
|
||||
dest.m21 = src.m21;
|
||||
dest.m22 = src.m22;
|
||||
dest.m23 = src.m23;
|
||||
dest.m30 = src.m30;
|
||||
dest.m31 = src.m31;
|
||||
dest.m32 = src.m32;
|
||||
dest.m33 = src.m33;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static OpenMatrix4f load(@Nullable OpenMatrix4f dest, float[] elements) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
dest.m00 = elements[0];
|
||||
dest.m01 = elements[1];
|
||||
dest.m02 = elements[2];
|
||||
dest.m03 = elements[3];
|
||||
dest.m10 = elements[4];
|
||||
dest.m11 = elements[5];
|
||||
dest.m12 = elements[6];
|
||||
dest.m13 = elements[7];
|
||||
dest.m20 = elements[8];
|
||||
dest.m21 = elements[9];
|
||||
dest.m22 = elements[10];
|
||||
dest.m23 = elements[11];
|
||||
dest.m30 = elements[12];
|
||||
dest.m31 = elements[13];
|
||||
dest.m32 = elements[14];
|
||||
dest.m33 = elements[15];
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static OpenMatrix4f load(@Nullable OpenMatrix4f dest, FloatBuffer buf) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
buf.position(0);
|
||||
|
||||
dest.m00 = buf.get();
|
||||
dest.m01 = buf.get();
|
||||
dest.m02 = buf.get();
|
||||
dest.m03 = buf.get();
|
||||
dest.m10 = buf.get();
|
||||
dest.m11 = buf.get();
|
||||
dest.m12 = buf.get();
|
||||
dest.m13 = buf.get();
|
||||
dest.m20 = buf.get();
|
||||
dest.m21 = buf.get();
|
||||
dest.m22 = buf.get();
|
||||
dest.m23 = buf.get();
|
||||
dest.m30 = buf.get();
|
||||
dest.m31 = buf.get();
|
||||
dest.m32 = buf.get();
|
||||
dest.m33 = buf.get();
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public OpenMatrix4f load(FloatBuffer buf) {
|
||||
return OpenMatrix4f.load(this, buf);
|
||||
}
|
||||
|
||||
public OpenMatrix4f store(FloatBuffer buf) {
|
||||
buf.put(m00);
|
||||
buf.put(m01);
|
||||
buf.put(m02);
|
||||
buf.put(m03);
|
||||
buf.put(m10);
|
||||
buf.put(m11);
|
||||
buf.put(m12);
|
||||
buf.put(m13);
|
||||
buf.put(m20);
|
||||
buf.put(m21);
|
||||
buf.put(m22);
|
||||
buf.put(m23);
|
||||
buf.put(m30);
|
||||
buf.put(m31);
|
||||
buf.put(m32);
|
||||
buf.put(m33);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<Float> toList() {
|
||||
List<Float> elements = Lists.newArrayList();
|
||||
|
||||
elements.add(0, m00);
|
||||
elements.add(1, m01);
|
||||
elements.add(2, m02);
|
||||
elements.add(3, m03);
|
||||
elements.add(4, m10);
|
||||
elements.add(5, m11);
|
||||
elements.add(6, m12);
|
||||
elements.add(7, m13);
|
||||
elements.add(8, m20);
|
||||
elements.add(9, m21);
|
||||
elements.add(10, m22);
|
||||
elements.add(11, m23);
|
||||
elements.add(12, m30);
|
||||
elements.add(13, m31);
|
||||
elements.add(14, m32);
|
||||
elements.add(15, m33);
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
public OpenMatrix4f unmodifiable() {
|
||||
return new OpenMatrix4f(this, true);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f add(OpenMatrix4f left, OpenMatrix4f right, @Nullable OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
dest.m00 = left.m00 + right.m00;
|
||||
dest.m01 = left.m01 + right.m01;
|
||||
dest.m02 = left.m02 + right.m02;
|
||||
dest.m03 = left.m03 + right.m03;
|
||||
dest.m10 = left.m10 + right.m10;
|
||||
dest.m11 = left.m11 + right.m11;
|
||||
dest.m12 = left.m12 + right.m12;
|
||||
dest.m13 = left.m13 + right.m13;
|
||||
dest.m20 = left.m20 + right.m20;
|
||||
dest.m21 = left.m21 + right.m21;
|
||||
dest.m22 = left.m22 + right.m22;
|
||||
dest.m23 = left.m23 + right.m23;
|
||||
dest.m30 = left.m30 + right.m30;
|
||||
dest.m31 = left.m31 + right.m31;
|
||||
dest.m32 = left.m32 + right.m32;
|
||||
dest.m33 = left.m33 + right.m33;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public OpenMatrix4f mulFront(OpenMatrix4f mulTransform) {
|
||||
return OpenMatrix4f.mul(mulTransform, this, this);
|
||||
}
|
||||
|
||||
public OpenMatrix4f mulBack(OpenMatrix4f mulTransform) {
|
||||
return OpenMatrix4f.mul(this, mulTransform, this);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f mul(OpenMatrix4f left, OpenMatrix4f right, @Nullable OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
float m00 = left.m00 * right.m00 + left.m10 * right.m01 + left.m20 * right.m02 + left.m30 * right.m03;
|
||||
float m01 = left.m01 * right.m00 + left.m11 * right.m01 + left.m21 * right.m02 + left.m31 * right.m03;
|
||||
float m02 = left.m02 * right.m00 + left.m12 * right.m01 + left.m22 * right.m02 + left.m32 * right.m03;
|
||||
float m03 = left.m03 * right.m00 + left.m13 * right.m01 + left.m23 * right.m02 + left.m33 * right.m03;
|
||||
float m10 = left.m00 * right.m10 + left.m10 * right.m11 + left.m20 * right.m12 + left.m30 * right.m13;
|
||||
float m11 = left.m01 * right.m10 + left.m11 * right.m11 + left.m21 * right.m12 + left.m31 * right.m13;
|
||||
float m12 = left.m02 * right.m10 + left.m12 * right.m11 + left.m22 * right.m12 + left.m32 * right.m13;
|
||||
float m13 = left.m03 * right.m10 + left.m13 * right.m11 + left.m23 * right.m12 + left.m33 * right.m13;
|
||||
float m20 = left.m00 * right.m20 + left.m10 * right.m21 + left.m20 * right.m22 + left.m30 * right.m23;
|
||||
float m21 = left.m01 * right.m20 + left.m11 * right.m21 + left.m21 * right.m22 + left.m31 * right.m23;
|
||||
float m22 = left.m02 * right.m20 + left.m12 * right.m21 + left.m22 * right.m22 + left.m32 * right.m23;
|
||||
float m23 = left.m03 * right.m20 + left.m13 * right.m21 + left.m23 * right.m22 + left.m33 * right.m23;
|
||||
float m30 = left.m00 * right.m30 + left.m10 * right.m31 + left.m20 * right.m32 + left.m30 * right.m33;
|
||||
float m31 = left.m01 * right.m30 + left.m11 * right.m31 + left.m21 * right.m32 + left.m31 * right.m33;
|
||||
float m32 = left.m02 * right.m30 + left.m12 * right.m31 + left.m22 * right.m32 + left.m32 * right.m33;
|
||||
float m33 = left.m03 * right.m30 + left.m13 * right.m31 + left.m23 * right.m32 + left.m33 * right.m33;
|
||||
|
||||
dest.m00 = m00;
|
||||
dest.m01 = m01;
|
||||
dest.m02 = m02;
|
||||
dest.m03 = m03;
|
||||
dest.m10 = m10;
|
||||
dest.m11 = m11;
|
||||
dest.m12 = m12;
|
||||
dest.m13 = m13;
|
||||
dest.m20 = m20;
|
||||
dest.m21 = m21;
|
||||
dest.m22 = m22;
|
||||
dest.m23 = m23;
|
||||
dest.m30 = m30;
|
||||
dest.m31 = m31;
|
||||
dest.m32 = m32;
|
||||
dest.m33 = m33;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static OpenMatrix4f mulMatrices(OpenMatrix4f... srcs) {
|
||||
OpenMatrix4f result = new OpenMatrix4f();
|
||||
|
||||
for (OpenMatrix4f src : srcs) {
|
||||
result.mulBack(src);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static OpenMatrix4f mulAsOrigin(OpenMatrix4f left, OpenMatrix4f right, OpenMatrix4f dest) {
|
||||
float x = right.m30;
|
||||
float y = right.m31;
|
||||
float z = right.m32;
|
||||
|
||||
OpenMatrix4f result = mul(left, right, dest);
|
||||
result.m30 = x;
|
||||
result.m31 = y;
|
||||
result.m32 = z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static OpenMatrix4f mulAsOriginInverse(OpenMatrix4f left, OpenMatrix4f right, OpenMatrix4f dest) {
|
||||
return mulAsOrigin(right, left, dest);
|
||||
}
|
||||
|
||||
public static Vec4f transform(OpenMatrix4f matrix, Vec4f src, @Nullable Vec4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec4f();
|
||||
}
|
||||
|
||||
float x = matrix.m00 * src.x + matrix.m10 * src.y + matrix.m20 * src.z + matrix.m30 * src.w;
|
||||
float y = matrix.m01 * src.x + matrix.m11 * src.y + matrix.m21 * src.z + matrix.m31 * src.w;
|
||||
float z = matrix.m02 * src.x + matrix.m12 * src.y + matrix.m22 * src.z + matrix.m32 * src.w;
|
||||
float w = matrix.m03 * src.x + matrix.m13 * src.y + matrix.m23 * src.z + matrix.m33 * src.w;
|
||||
|
||||
dest.x = x;
|
||||
dest.y = y;
|
||||
dest.z = z;
|
||||
dest.w = w;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static Vec3 transform(OpenMatrix4f matrix, Vec3 src) {
|
||||
double x = matrix.m00 * src.x + matrix.m10 * src.y + matrix.m20 * src.z + matrix.m30;
|
||||
double y = matrix.m01 * src.x + matrix.m11 * src.y + matrix.m21 * src.z + matrix.m31;
|
||||
double z = matrix.m02 * src.x + matrix.m12 * src.y + matrix.m22 * src.z + matrix.m32;
|
||||
|
||||
return new Vec3(x, y ,z);
|
||||
}
|
||||
|
||||
public static Vec3f transform3v(OpenMatrix4f matrix, Vec3f src, @Nullable Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
VEC4_STORAGE.set(src.x, src.y, src.z, 1.0F);
|
||||
|
||||
Vec4f result = transform(matrix, VEC4_STORAGE, null);
|
||||
dest.x = result.x;
|
||||
dest.y = result.y;
|
||||
dest.z = result.z;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public OpenMatrix4f transpose() {
|
||||
return transpose(this);
|
||||
}
|
||||
|
||||
public OpenMatrix4f transpose(OpenMatrix4f dest) {
|
||||
return transpose(this, dest);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f transpose(OpenMatrix4f src, @Nullable OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
float m00 = src.m00;
|
||||
float m01 = src.m10;
|
||||
float m02 = src.m20;
|
||||
float m03 = src.m30;
|
||||
float m10 = src.m01;
|
||||
float m11 = src.m11;
|
||||
float m12 = src.m21;
|
||||
float m13 = src.m31;
|
||||
float m20 = src.m02;
|
||||
float m21 = src.m12;
|
||||
float m22 = src.m22;
|
||||
float m23 = src.m32;
|
||||
float m30 = src.m03;
|
||||
float m31 = src.m13;
|
||||
float m32 = src.m23;
|
||||
float m33 = src.m33;
|
||||
|
||||
dest.m00 = m00;
|
||||
dest.m01 = m01;
|
||||
dest.m02 = m02;
|
||||
dest.m03 = m03;
|
||||
dest.m10 = m10;
|
||||
dest.m11 = m11;
|
||||
dest.m12 = m12;
|
||||
dest.m13 = m13;
|
||||
dest.m20 = m20;
|
||||
dest.m21 = m21;
|
||||
dest.m22 = m22;
|
||||
dest.m23 = m23;
|
||||
dest.m30 = m30;
|
||||
dest.m31 = m31;
|
||||
dest.m32 = m32;
|
||||
dest.m33 = m33;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public float determinant() {
|
||||
float f = m00 * ((m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32) - m13 * m22 * m31 - m11 * m23 * m32 - m12 * m21 * m33);
|
||||
f -= m01 * ((m10 * m22 * m33 + m12 * m23 * m30 + m13 * m20 * m32) - m13 * m22 * m30 - m10 * m23 * m32 - m12 * m20 * m33);
|
||||
f += m02 * ((m10 * m21 * m33 + m11 * m23 * m30 + m13 * m20 * m31) - m13 * m21 * m30 - m10 * m23 * m31 - m11 * m20 * m33);
|
||||
f -= m03 * ((m10 * m21 * m32 + m11 * m22 * m30 + m12 * m20 * m31) - m12 * m21 * m30 - m10 * m22 * m31 - m11 * m20 * m32);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
private static float determinant3x3(float t00, float t01, float t02, float t10, float t11, float t12, float t20, float t21, float t22) {
|
||||
return t00 * (t11 * t22 - t12 * t21) + t01 * (t12 * t20 - t10 * t22) + t02 * (t10 * t21 - t11 * t20);
|
||||
}
|
||||
|
||||
public OpenMatrix4f invert() {
|
||||
return OpenMatrix4f.invert(this, this);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f invert(OpenMatrix4f src, @Nullable OpenMatrix4f dest) {
|
||||
float determinant = src.determinant();
|
||||
|
||||
if (determinant != 0.0F) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
float determinant_inv = 1.0F / determinant;
|
||||
|
||||
float t00 = determinant3x3(src.m11, src.m12, src.m13, src.m21, src.m22, src.m23, src.m31, src.m32, src.m33);
|
||||
float t01 = -determinant3x3(src.m10, src.m12, src.m13, src.m20, src.m22, src.m23, src.m30, src.m32, src.m33);
|
||||
float t02 = determinant3x3(src.m10, src.m11, src.m13, src.m20, src.m21, src.m23, src.m30, src.m31, src.m33);
|
||||
float t03 = -determinant3x3(src.m10, src.m11, src.m12, src.m20, src.m21, src.m22, src.m30, src.m31, src.m32);
|
||||
float t10 = -determinant3x3(src.m01, src.m02, src.m03, src.m21, src.m22, src.m23, src.m31, src.m32, src.m33);
|
||||
float t11 = determinant3x3(src.m00, src.m02, src.m03, src.m20, src.m22, src.m23, src.m30, src.m32, src.m33);
|
||||
float t12 = -determinant3x3(src.m00, src.m01, src.m03, src.m20, src.m21, src.m23, src.m30, src.m31, src.m33);
|
||||
float t13 = determinant3x3(src.m00, src.m01, src.m02, src.m20, src.m21, src.m22, src.m30, src.m31, src.m32);
|
||||
float t20 = determinant3x3(src.m01, src.m02, src.m03, src.m11, src.m12, src.m13, src.m31, src.m32, src.m33);
|
||||
float t21 = -determinant3x3(src.m00, src.m02, src.m03, src.m10, src.m12, src.m13, src.m30, src.m32, src.m33);
|
||||
float t22 = determinant3x3(src.m00, src.m01, src.m03, src.m10, src.m11, src.m13, src.m30, src.m31, src.m33);
|
||||
float t23 = -determinant3x3(src.m00, src.m01, src.m02, src.m10, src.m11, src.m12, src.m30, src.m31, src.m32);
|
||||
float t30 = -determinant3x3(src.m01, src.m02, src.m03, src.m11, src.m12, src.m13, src.m21, src.m22, src.m23);
|
||||
float t31 = determinant3x3(src.m00, src.m02, src.m03, src.m10, src.m12, src.m13, src.m20, src.m22, src.m23);
|
||||
float t32 = -determinant3x3(src.m00, src.m01, src.m03, src.m10, src.m11, src.m13, src.m20, src.m21, src.m23);
|
||||
float t33 = determinant3x3(src.m00, src.m01, src.m02, src.m10, src.m11, src.m12, src.m20, src.m21, src.m22);
|
||||
|
||||
dest.m00 = t00 * determinant_inv;
|
||||
dest.m11 = t11 * determinant_inv;
|
||||
dest.m22 = t22 * determinant_inv;
|
||||
dest.m33 = t33 * determinant_inv;
|
||||
dest.m01 = t10 * determinant_inv;
|
||||
dest.m10 = t01 * determinant_inv;
|
||||
dest.m20 = t02 * determinant_inv;
|
||||
dest.m02 = t20 * determinant_inv;
|
||||
dest.m12 = t21 * determinant_inv;
|
||||
dest.m21 = t12 * determinant_inv;
|
||||
dest.m03 = t30 * determinant_inv;
|
||||
dest.m30 = t03 * determinant_inv;
|
||||
dest.m13 = t31 * determinant_inv;
|
||||
dest.m31 = t13 * determinant_inv;
|
||||
dest.m32 = t23 * determinant_inv;
|
||||
dest.m23 = t32 * determinant_inv;
|
||||
|
||||
return dest;
|
||||
} else {
|
||||
dest.setIdentity();
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
|
||||
public OpenMatrix4f translate(float x, float y, float z) {
|
||||
VECTOR_STORAGE.set(x, y, z);
|
||||
return translate(VECTOR_STORAGE, this);
|
||||
}
|
||||
|
||||
public OpenMatrix4f translate(Vec3f vec) {
|
||||
return translate(vec, this);
|
||||
}
|
||||
|
||||
public OpenMatrix4f translate(Vec3f vec, OpenMatrix4f dest) {
|
||||
return translate(vec, this, dest);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f translate(Vec3f vec, OpenMatrix4f src, @Nullable OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
dest.m30 += src.m00 * vec.x + src.m10 * vec.y + src.m20 * vec.z;
|
||||
dest.m31 += src.m01 * vec.x + src.m11 * vec.y + src.m21 * vec.z;
|
||||
dest.m32 += src.m02 * vec.x + src.m12 * vec.y + src.m22 * vec.z;
|
||||
dest.m33 += src.m03 * vec.x + src.m13 * vec.y + src.m23 * vec.z;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static OpenMatrix4f createTranslation(float x, float y, float z) {
|
||||
return ofTranslation(x, y, z, null);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f ofTranslation(float x, float y, float z, OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
dest.setIdentity();
|
||||
dest.m30 = x;
|
||||
dest.m31 = y;
|
||||
dest.m32 = z;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static OpenMatrix4f createScale(float x, float y, float z) {
|
||||
return ofScale(x, y, z, null);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f ofScale(float x, float y, float z, OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
dest.setIdentity();
|
||||
dest.m00 = x;
|
||||
dest.m11 = y;
|
||||
dest.m22 = z;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public OpenMatrix4f rotateDeg(float angle, Vec3f axis) {
|
||||
return rotate((float)Math.toRadians(angle), axis);
|
||||
}
|
||||
|
||||
public OpenMatrix4f rotate(float angle, Vec3f axis) {
|
||||
return rotate(angle, axis, this);
|
||||
}
|
||||
|
||||
public OpenMatrix4f rotate(float angle, Vec3f axis, OpenMatrix4f dest) {
|
||||
return rotate(angle, axis, this, dest);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f createRotatorDeg(float degree, Vec3f axis) {
|
||||
return rotate((float)Math.toRadians(degree), axis, new OpenMatrix4f(), null);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f ofRotationDegree(float degree, Vec3f axis, @Nullable OpenMatrix4f dest) {
|
||||
dest.setIdentity();
|
||||
return rotate((float)Math.toRadians(degree), axis, dest, dest);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f rotate(float angle, Vec3f axis, OpenMatrix4f src, @Nullable OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
float c = (float) Math.cos(angle);
|
||||
float s = (float) Math.sin(angle);
|
||||
float oneminusc = 1.0f - c;
|
||||
float xy = axis.x * axis.y;
|
||||
float yz = axis.y * axis.z;
|
||||
float xz = axis.x * axis.z;
|
||||
float xs = axis.x * s;
|
||||
float ys = axis.y * s;
|
||||
float zs = axis.z * s;
|
||||
|
||||
float f00 = axis.x * axis.x * oneminusc+c;
|
||||
float f01 = xy * oneminusc + zs;
|
||||
float f02 = xz * oneminusc - ys;
|
||||
// n[3] not used
|
||||
float f10 = xy * oneminusc - zs;
|
||||
float f11 = axis.y * axis.y * oneminusc+c;
|
||||
float f12 = yz * oneminusc + xs;
|
||||
// n[7] not used
|
||||
float f20 = xz * oneminusc + ys;
|
||||
float f21 = yz * oneminusc - xs;
|
||||
float f22 = axis.z * axis.z * oneminusc+c;
|
||||
|
||||
float t00 = src.m00 * f00 + src.m10 * f01 + src.m20 * f02;
|
||||
float t01 = src.m01 * f00 + src.m11 * f01 + src.m21 * f02;
|
||||
float t02 = src.m02 * f00 + src.m12 * f01 + src.m22 * f02;
|
||||
float t03 = src.m03 * f00 + src.m13 * f01 + src.m23 * f02;
|
||||
float t10 = src.m00 * f10 + src.m10 * f11 + src.m20 * f12;
|
||||
float t11 = src.m01 * f10 + src.m11 * f11 + src.m21 * f12;
|
||||
float t12 = src.m02 * f10 + src.m12 * f11 + src.m22 * f12;
|
||||
float t13 = src.m03 * f10 + src.m13 * f11 + src.m23 * f12;
|
||||
|
||||
dest.m20 = src.m00 * f20 + src.m10 * f21 + src.m20 * f22;
|
||||
dest.m21 = src.m01 * f20 + src.m11 * f21 + src.m21 * f22;
|
||||
dest.m22 = src.m02 * f20 + src.m12 * f21 + src.m22 * f22;
|
||||
dest.m23 = src.m03 * f20 + src.m13 * f21 + src.m23 * f22;
|
||||
dest.m00 = t00;
|
||||
dest.m01 = t01;
|
||||
dest.m02 = t02;
|
||||
dest.m03 = t03;
|
||||
dest.m10 = t10;
|
||||
dest.m11 = t11;
|
||||
dest.m12 = t12;
|
||||
dest.m13 = t13;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public Vec3f toTranslationVector() {
|
||||
return toTranslationVector(this);
|
||||
}
|
||||
|
||||
public Vec3f toTranslationVector(Vec3f dest) {
|
||||
return toTranslationVector(this, dest);
|
||||
}
|
||||
|
||||
public static Vec3f toTranslationVector(OpenMatrix4f matrix) {
|
||||
return toTranslationVector(matrix, null);
|
||||
}
|
||||
|
||||
public static Vec3f toTranslationVector(OpenMatrix4f matrix, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
dest.x = matrix.m30;
|
||||
dest.y = matrix.m31;
|
||||
dest.z = matrix.m32;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public Quaternionf toQuaternion() {
|
||||
return OpenMatrix4f.toQuaternion(this);
|
||||
}
|
||||
|
||||
public Quaternionf toQuaternion(Quaternionf dest) {
|
||||
return OpenMatrix4f.toQuaternion(this, dest);
|
||||
}
|
||||
|
||||
public static Quaternionf toQuaternion(OpenMatrix4f matrix) {
|
||||
return toQuaternion(matrix, new Quaternionf());
|
||||
}
|
||||
|
||||
private static final OpenMatrix4f MATRIX_STORAGE = new OpenMatrix4f();
|
||||
|
||||
public static Quaternionf toQuaternion(OpenMatrix4f matrix, Quaternionf dest) {
|
||||
if (dest == null) {
|
||||
dest = new Quaternionf();
|
||||
}
|
||||
|
||||
OpenMatrix4f.load(matrix, MATRIX_STORAGE);
|
||||
|
||||
float w, x, y, z;
|
||||
MATRIX_STORAGE.transpose();
|
||||
|
||||
float lenX = MATRIX_STORAGE.m00 * MATRIX_STORAGE.m00 + MATRIX_STORAGE.m01 * MATRIX_STORAGE.m01 + MATRIX_STORAGE.m02 * MATRIX_STORAGE.m02;
|
||||
float lenY = MATRIX_STORAGE.m10 * MATRIX_STORAGE.m10 + MATRIX_STORAGE.m11 * MATRIX_STORAGE.m11 + MATRIX_STORAGE.m12 * MATRIX_STORAGE.m12;
|
||||
float lenZ = MATRIX_STORAGE.m20 * MATRIX_STORAGE.m20 + MATRIX_STORAGE.m21 * MATRIX_STORAGE.m21 + MATRIX_STORAGE.m22 * MATRIX_STORAGE.m22;
|
||||
|
||||
if (lenX == 0.0F || lenY == 0.0F || lenZ == 0.0F) {
|
||||
return new Quaternionf(0.0F, 0.0F, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
lenX = Math.invsqrt(lenX);
|
||||
lenY = Math.invsqrt(lenY);
|
||||
lenZ = Math.invsqrt(lenZ);
|
||||
|
||||
MATRIX_STORAGE.m00 *= lenX; MATRIX_STORAGE.m01 *= lenX; MATRIX_STORAGE.m02 *= lenX;
|
||||
MATRIX_STORAGE.m10 *= lenY; MATRIX_STORAGE.m11 *= lenY; MATRIX_STORAGE.m12 *= lenY;
|
||||
MATRIX_STORAGE.m20 *= lenZ; MATRIX_STORAGE.m21 *= lenZ; MATRIX_STORAGE.m22 *= lenZ;
|
||||
|
||||
float t;
|
||||
float tr = MATRIX_STORAGE.m00 + MATRIX_STORAGE.m11 + MATRIX_STORAGE.m22;
|
||||
|
||||
if (tr >= 0.0F) {
|
||||
t = (float)Math.sqrt(tr + 1.0F);
|
||||
w = t * 0.5F;
|
||||
t = 0.5F / t;
|
||||
x = (MATRIX_STORAGE.m12 - MATRIX_STORAGE.m21) * t;
|
||||
y = (MATRIX_STORAGE.m20 - MATRIX_STORAGE.m02) * t;
|
||||
z = (MATRIX_STORAGE.m01 - MATRIX_STORAGE.m10) * t;
|
||||
} else {
|
||||
if (MATRIX_STORAGE.m00 >= MATRIX_STORAGE.m11 && MATRIX_STORAGE.m00 >= MATRIX_STORAGE.m22) {
|
||||
t = (float)Math.sqrt(MATRIX_STORAGE.m00 - (MATRIX_STORAGE.m11 + MATRIX_STORAGE.m22) + 1.0);
|
||||
x = t * 0.5F;
|
||||
t = 0.5F / t;
|
||||
y = (MATRIX_STORAGE.m10 + MATRIX_STORAGE.m01) * t;
|
||||
z = (MATRIX_STORAGE.m02 + MATRIX_STORAGE.m20) * t;
|
||||
w = (MATRIX_STORAGE.m12 - MATRIX_STORAGE.m21) * t;
|
||||
} else if (MATRIX_STORAGE.m11 > MATRIX_STORAGE.m22) {
|
||||
t = (float)Math.sqrt(MATRIX_STORAGE.m11 - (MATRIX_STORAGE.m22 + MATRIX_STORAGE.m00) + 1.0F);
|
||||
y = t * 0.5F;
|
||||
t = 0.5F / t;
|
||||
z = (MATRIX_STORAGE.m21 + MATRIX_STORAGE.m12) * t;
|
||||
x = (MATRIX_STORAGE.m10 + MATRIX_STORAGE.m01) * t;
|
||||
w = (MATRIX_STORAGE.m20 - MATRIX_STORAGE.m02) * t;
|
||||
} else {
|
||||
t = (float)Math.sqrt(MATRIX_STORAGE.m22 - (MATRIX_STORAGE.m00 + MATRIX_STORAGE.m11) + 1.0F);
|
||||
z = t * 0.5F;
|
||||
t = 0.5F / t;
|
||||
x = (MATRIX_STORAGE.m02 + MATRIX_STORAGE.m20) * t;
|
||||
y = (MATRIX_STORAGE.m21 + MATRIX_STORAGE.m12) * t;
|
||||
w = (MATRIX_STORAGE.m01 - MATRIX_STORAGE.m10) * t;
|
||||
}
|
||||
}
|
||||
|
||||
dest.x = x;
|
||||
dest.y = y;
|
||||
dest.z = z;
|
||||
dest.w = w;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static OpenMatrix4f fromQuaternion(Quaternionf quaternion) {
|
||||
return fromQuaternion(quaternion, null);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f fromQuaternion(Quaternionf quaternion, OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
float x = quaternion.x();
|
||||
float y = quaternion.y();
|
||||
float z = quaternion.z();
|
||||
float w = quaternion.w();
|
||||
float xy = x * y;
|
||||
float xz = x * z;
|
||||
float xw = x * w;
|
||||
float yz = y * z;
|
||||
float yw = y * w;
|
||||
float zw = z * w;
|
||||
float xSquared = 2F * x * x;
|
||||
float ySquared = 2F * y * y;
|
||||
float zSquared = 2F * z * z;
|
||||
dest.m00 = 1.0F - ySquared - zSquared;
|
||||
dest.m01 = 2.0F * (xy - zw);
|
||||
dest.m02 = 2.0F * (xz + yw);
|
||||
dest.m10 = 2.0F * (xy + zw);
|
||||
dest.m11 = 1.0F - xSquared - zSquared;
|
||||
dest.m12 = 2.0F * (yz - xw);
|
||||
dest.m20 = 2.0F * (xz - yw);
|
||||
dest.m21 = 2.0F * (yz + xw);
|
||||
dest.m22 = 1.0F - xSquared - ySquared;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public OpenMatrix4f scale(float x, float y, float z) {
|
||||
VECTOR_STORAGE.set(x, y, z);
|
||||
return this.scale(VECTOR_STORAGE);
|
||||
}
|
||||
|
||||
public OpenMatrix4f scale(Vec3f vec) {
|
||||
return scale(vec, this, this);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f scale(Vec3f vec, OpenMatrix4f src, @Nullable OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
dest.m00 = src.m00 * vec.x;
|
||||
dest.m01 = src.m01 * vec.x;
|
||||
dest.m02 = src.m02 * vec.x;
|
||||
dest.m03 = src.m03 * vec.x;
|
||||
dest.m10 = src.m10 * vec.y;
|
||||
dest.m11 = src.m11 * vec.y;
|
||||
dest.m12 = src.m12 * vec.y;
|
||||
dest.m13 = src.m13 * vec.y;
|
||||
dest.m20 = src.m20 * vec.z;
|
||||
dest.m21 = src.m21 * vec.z;
|
||||
dest.m22 = src.m22 * vec.z;
|
||||
dest.m23 = src.m23 * vec.z;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public Vec3f toScaleVector() {
|
||||
return toScaleVector(null);
|
||||
}
|
||||
|
||||
public Vec3f toScaleVector(Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
VECTOR_STORAGE.set(this.m00, this.m01, this.m02);
|
||||
dest.x = VECTOR_STORAGE.length();
|
||||
|
||||
VECTOR_STORAGE.set(this.m10, this.m11, this.m12);
|
||||
dest.y = VECTOR_STORAGE.length();
|
||||
|
||||
VECTOR_STORAGE.set(this.m20, this.m21, this.m22);
|
||||
dest.z = VECTOR_STORAGE.length();
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public OpenMatrix4f removeTranslation() {
|
||||
return removeTranslation(this, null);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f removeTranslation(OpenMatrix4f src, @Nullable OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
dest.load(src);
|
||||
dest.m30 = 0.0F;
|
||||
dest.m31 = 0.0F;
|
||||
dest.m32 = 0.0F;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public OpenMatrix4f removeScale() {
|
||||
return removeScale(this, null);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f removeScale(OpenMatrix4f src, @Nullable OpenMatrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new OpenMatrix4f();
|
||||
} else if (dest.immutable) {
|
||||
throw new UnsupportedOperationException("Can't modify immutable matrix");
|
||||
}
|
||||
|
||||
VECTOR_STORAGE.set(src.m00, src.m01, src.m02);
|
||||
float xScale = VECTOR_STORAGE.length();
|
||||
|
||||
VECTOR_STORAGE.set(src.m10, src.m11, src.m12);
|
||||
float yScale = VECTOR_STORAGE.length();
|
||||
|
||||
VECTOR_STORAGE.set(src.m20, src.m21, src.m22);
|
||||
float zScale = VECTOR_STORAGE.length();
|
||||
|
||||
dest.load(src);
|
||||
dest.scale(1.0F / xScale, 1.0F / yScale, 1.0F / zScale);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "\n" +
|
||||
String.format("%.4f", m00) + " " + String.format("%.4f", m01) + " " + String.format("%.4f", m02) + " " + String.format("%.4f", m03) + "\n" +
|
||||
String.format("%.4f", m10) + " " + String.format("%.4f", m11) + " " + String.format("%.4f", m12) + " " + String.format("%.4f", m13) + "\n" +
|
||||
String.format("%.4f", m20) + " " + String.format("%.4f", m21) + " " + String.format("%.4f", m22) + " " + String.format("%.4f", m23) + "\n" +
|
||||
String.format("%.4f", m30) + " " + String.format("%.4f", m31) + " " + String.format("%.4f", m32) + " " + String.format("%.4f", m33) + "\n"
|
||||
;
|
||||
}
|
||||
|
||||
public static Matrix4f exportToMojangMatrix(OpenMatrix4f src) {
|
||||
return exportToMojangMatrix(src, null);
|
||||
}
|
||||
|
||||
public static Matrix4f exportToMojangMatrix(OpenMatrix4f src, Matrix4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Matrix4f();
|
||||
}
|
||||
|
||||
MATRIX_TRANSFORMER.position(0);
|
||||
src.store(MATRIX_TRANSFORMER);
|
||||
MATRIX_TRANSFORMER.position(0);
|
||||
|
||||
return dest.set(MATRIX_TRANSFORMER);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f importFromMojangMatrix(Matrix4f src) {
|
||||
MATRIX_TRANSFORMER.position(0);
|
||||
src.get(MATRIX_TRANSFORMER);
|
||||
|
||||
return OpenMatrix4f.load(null, MATRIX_TRANSFORMER);
|
||||
}
|
||||
|
||||
public static OpenMatrix4f[] allocateMatrixArray(int size) {
|
||||
OpenMatrix4f[] matrixArray = new OpenMatrix4f[size];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
matrixArray[i] = new OpenMatrix4f();
|
||||
}
|
||||
|
||||
return matrixArray;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.math;
|
||||
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class QuaternionUtils {
|
||||
public static Axis XN = new Axis(-1.0F, 0.0F, 0.0F);
|
||||
public static Axis XP = new Axis(1.0F, 0.0F, 0.0F);
|
||||
public static Axis YN = new Axis(0.0F, -1.0F, 0.0F);
|
||||
public static Axis YP = new Axis(0.0F, 1.0F, 0.0F);
|
||||
public static Axis ZN = new Axis(0.0F, 0.0F, -1.0F);
|
||||
public static Axis ZP = new Axis(0.0F, 0.0F, 1.0F);
|
||||
|
||||
public static Quaternionf rotationDegrees(Vector3f axis, float degress) {
|
||||
float angle = degress * (float) Math.PI / 180;
|
||||
return rotation(axis, angle);
|
||||
}
|
||||
|
||||
public static Quaternionf rotation(Vector3f axis, float angle) {
|
||||
Quaternionf quat = new Quaternionf();
|
||||
quat.setAngleAxis(angle, axis.x, axis.y, axis.z);
|
||||
return quat;
|
||||
}
|
||||
|
||||
public static class Axis {
|
||||
private final Vector3f axis;
|
||||
|
||||
public Axis(float x, float y, float z) {
|
||||
this.axis = new Vector3f(x, y, z);
|
||||
}
|
||||
|
||||
public Quaternionf rotation(float angle) {
|
||||
return QuaternionUtils.rotation(axis, angle);
|
||||
}
|
||||
|
||||
public Quaternionf rotationDegrees(float degrees) {
|
||||
return QuaternionUtils.rotationDegrees(axis, degrees);
|
||||
}
|
||||
}
|
||||
}
|
||||
139
src/main/java/com/tiedup/remake/rig/math/ValueModifier.java
Normal file
139
src/main/java/com/tiedup/remake/rig/math/ValueModifier.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.math;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
public interface ValueModifier {
|
||||
public static final Codec<Unified> CODEC =
|
||||
RecordCodecBuilder.create(instance -> instance.group(
|
||||
Codec.FLOAT.fieldOf("adder").forGetter(Unified::adder),
|
||||
Codec.FLOAT.fieldOf("multiplier").forGetter(Unified::multiplier),
|
||||
Codec.FLOAT.fieldOf("setter").forGetter(Unified::setter)
|
||||
).apply(instance, Unified::new)
|
||||
);
|
||||
|
||||
public void attach(ResultCalculator calculator);
|
||||
|
||||
public static ValueModifier adder(float value) {
|
||||
return new Adder(value);
|
||||
}
|
||||
|
||||
public static ValueModifier multiplier(float value) {
|
||||
return new Multiplier(value);
|
||||
}
|
||||
|
||||
public static ValueModifier setter(float arg) {
|
||||
return new Setter(arg);
|
||||
}
|
||||
|
||||
public static record Adder(float adder) implements ValueModifier {
|
||||
@Override
|
||||
public void attach(ResultCalculator calculator) {
|
||||
calculator.add += this.adder;
|
||||
}
|
||||
}
|
||||
|
||||
public static record Multiplier(float multiplier) implements ValueModifier {
|
||||
@Override
|
||||
public void attach(ResultCalculator calculator) {
|
||||
calculator.multiply *= this.multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
public static record Setter(float setter) implements ValueModifier {
|
||||
@Override
|
||||
public void attach(ResultCalculator calculator) {
|
||||
if (Float.isNaN(calculator.set)) {
|
||||
calculator.set = this.setter;
|
||||
} else if (!Float.isNaN(this.setter)) {
|
||||
calculator.set = Math.min(calculator.set, this.setter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static record Unified(float adder, float multiplier, float setter) implements ValueModifier {
|
||||
@Override
|
||||
public void attach(ResultCalculator calculator) {
|
||||
if (Float.isNaN(calculator.set)) {
|
||||
calculator.set = this.setter;
|
||||
} else if (!Float.isNaN(this.setter)) {
|
||||
calculator.set = Math.min(calculator.set, this.setter);
|
||||
}
|
||||
|
||||
calculator.add += this.adder;
|
||||
calculator.multiply *= this.multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
public static ResultCalculator calculator() {
|
||||
return new ResultCalculator();
|
||||
}
|
||||
|
||||
public static class ResultCalculator implements ValueModifier {
|
||||
private float set = Float.NaN;
|
||||
private float add = 0.0F;
|
||||
private float multiply = 1.0F;
|
||||
|
||||
public ResultCalculator attach(ValueModifier valueModifier) {
|
||||
valueModifier.attach(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attach(ResultCalculator calculator) {
|
||||
if (Float.isNaN(calculator.set)) {
|
||||
calculator.set = this.set;
|
||||
} else if (!Float.isNaN(this.set)) {
|
||||
calculator.set = Math.min(calculator.set, this.set);
|
||||
}
|
||||
|
||||
calculator.add += this.add;
|
||||
calculator.multiply *= this.multiply;
|
||||
}
|
||||
|
||||
public ValueModifier toValueModifier() {
|
||||
if (Float.isNaN(this.set)) {
|
||||
if (Float.compare(this.add, 0.0F) == 0 && Float.compare(this.multiply, 1.0F) != 0) {
|
||||
return new Multiplier(this.multiply);
|
||||
} else if (Float.compare(this.add, 0.0F) != 0 && Float.compare(this.multiply, 1.0F) == 0) {
|
||||
return new Adder(this.add);
|
||||
}
|
||||
} else if (Float.compare(this.add, 0.0F) == 0 && Float.compare(this.multiply, 1.0F) == 0) {
|
||||
return new Setter(this.set);
|
||||
}
|
||||
|
||||
return new Unified(this.set, this.add, this.multiply);
|
||||
}
|
||||
|
||||
public void set(float f) {
|
||||
this.set = f;
|
||||
}
|
||||
|
||||
public void add(float f) {
|
||||
this.add += add;
|
||||
}
|
||||
|
||||
public void multiply(float f) {
|
||||
this.multiply *= f;
|
||||
}
|
||||
|
||||
public float getResult(float baseValue) {
|
||||
float result = baseValue;
|
||||
|
||||
if (!Float.isNaN(this.set)) {
|
||||
result = this.set;
|
||||
}
|
||||
|
||||
result += this.add;
|
||||
result *= this.multiply;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/main/java/com/tiedup/remake/rig/math/Vec2f.java
Normal file
33
src/main/java/com/tiedup/remake/rig/math/Vec2f.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.math;
|
||||
|
||||
public class Vec2f {
|
||||
public float x;
|
||||
public float y;
|
||||
|
||||
public Vec2f() {
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
}
|
||||
|
||||
public Vec2f(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public Vec2f scale(float f) {
|
||||
this.x *= f;
|
||||
this.y *= f;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Vec2f[" + this.x + ", " + this.y + ", " + "]";
|
||||
}
|
||||
}
|
||||
22
src/main/java/com/tiedup/remake/rig/math/Vec2i.java
Normal file
22
src/main/java/com/tiedup/remake/rig/math/Vec2i.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.math;
|
||||
|
||||
public class Vec2i {
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
public Vec2i(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%d, %d]", this.x, this.y);
|
||||
}
|
||||
}
|
||||
473
src/main/java/com/tiedup/remake/rig/math/Vec3f.java
Normal file
473
src/main/java/com/tiedup/remake/rig/math/Vec3f.java
Normal file
@@ -0,0 +1,473 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.math;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import yesman.epicfight.main.EpicFightMod;
|
||||
|
||||
public class Vec3f extends Vec2f {
|
||||
public static final Vec3f X_AXIS = new Vec3f(1.0F, 0.0F, 0.0F);
|
||||
public static final Vec3f Y_AXIS = new Vec3f(0.0F, 1.0F, 0.0F);
|
||||
public static final Vec3f Z_AXIS = new Vec3f(0.0F, 0.0F, 1.0F);
|
||||
public static final Vec3f M_X_AXIS = new Vec3f(-1.0F, 0.0F, 0.0F);
|
||||
public static final Vec3f M_Y_AXIS = new Vec3f(0.0F, -1.0F, 0.0F);
|
||||
public static final Vec3f M_Z_AXIS = new Vec3f(0.0F, 0.0F, -1.0F);
|
||||
public static final Vec3f ZERO = new Vec3f(0.0F, 0.0F, 0.0F);
|
||||
|
||||
public float z;
|
||||
|
||||
public Vec3f() {
|
||||
super();
|
||||
this.z = 0;
|
||||
}
|
||||
|
||||
public Vec3f(float x, float y, float z) {
|
||||
super(x, y);
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public Vec3f(double x, double y, double z) {
|
||||
this((float)x, (float)y, (float)z);
|
||||
}
|
||||
|
||||
public Vec3f(Vec3 mojangVec) {
|
||||
this((float)mojangVec.x, (float)mojangVec.y, (float)mojangVec.z);
|
||||
}
|
||||
|
||||
public Vec3f set(float x, float y, float z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vec3f set(Vec3 vec3f) {
|
||||
this.x = (float)vec3f.x;
|
||||
this.y = (float)vec3f.y;
|
||||
this.z = (float)vec3f.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vec3f set(Vec3f vec3f) {
|
||||
this.x = vec3f.x;
|
||||
this.y = vec3f.y;
|
||||
this.z = vec3f.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vec3f add(float x, float y, float z) {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
this.z += z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vec3f add(Vec3f vec) {
|
||||
return this.add(vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
public Vec3f add(Vec3 vec) {
|
||||
return this.add((float)vec.x, (float)vec.y, (float)vec.z);
|
||||
}
|
||||
|
||||
public Vec3f sub(float x, float y, float z) {
|
||||
this.x -= x;
|
||||
this.y -= y;
|
||||
this.z -= z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vec3f sub(Vec3f vec) {
|
||||
return this.sub(vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
public static Vec3f add(Vec3f left, Vec3f right, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
return new Vec3f(left.x + right.x, left.y + right.y, left.z + right.z);
|
||||
} else {
|
||||
dest.set(left.x + right.x, left.y + right.y, left.z + right.z);
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vec3f sub(Vec3f left, Vec3f right, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
return new Vec3f(left.x - right.x, left.y - right.y, left.z - right.z);
|
||||
} else {
|
||||
dest.set(left.x - right.x, left.y - right.y, left.z - right.z);
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
|
||||
public Vec3f multiply(Vec3f vec) {
|
||||
return multiply(this, this, vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
public Vec3f multiply(float x, float y, float z) {
|
||||
return multiply(this, this, x, y, z);
|
||||
}
|
||||
|
||||
public static Vec3f multiply(Vec3f src, Vec3f dest, float x, float y, float z) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
dest.x = src.x * x;
|
||||
dest.y = src.y * y;
|
||||
dest.z = src.z * z;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3f scale(float f) {
|
||||
return scale(this, this, f);
|
||||
}
|
||||
|
||||
public static Vec3f scale(Vec3f src, Vec3f dest, float f) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
dest.x = src.x * f;
|
||||
dest.y = src.y * f;
|
||||
dest.z = src.z * f;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public Vec3f copy() {
|
||||
return new Vec3f(this.x, this.y, this.z);
|
||||
}
|
||||
|
||||
public float length() {
|
||||
return (float) Math.sqrt(this.lengthSqr());
|
||||
}
|
||||
|
||||
public float lengthSqr() {
|
||||
return this.x * this.x + this.y * this.y + this.z * this.z;
|
||||
}
|
||||
|
||||
public float distance(Vec3f opponent) {
|
||||
return (float)Math.sqrt(this.distanceSqr(opponent));
|
||||
}
|
||||
|
||||
public float distanceSqr(Vec3f opponent) {
|
||||
return (float)(Math.pow(this.x - opponent.x, 2) + Math.pow(this.y - opponent.y, 2) + Math.pow(this.z - opponent.z, 2));
|
||||
}
|
||||
|
||||
public float horizontalDistance() {
|
||||
return (float)Math.sqrt(this.x * this.x + this.z * this.z);
|
||||
}
|
||||
|
||||
public float horizontalDistanceSqr() {
|
||||
return this.x * this.x + this.z * this.z;
|
||||
}
|
||||
|
||||
public void rotate(float degree, Vec3f axis) {
|
||||
rotate(degree, axis, this, this);
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
this.x = Float.NaN;
|
||||
this.y = Float.NaN;
|
||||
this.z = Float.NaN;
|
||||
}
|
||||
|
||||
public boolean validateValues() {
|
||||
return Float.isFinite(this.x) && Float.isFinite(this.y) && Float.isFinite(this.z);
|
||||
}
|
||||
|
||||
public static Vec3f rotate(float degree, Vec3f axis, Vec3f src, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
return OpenMatrix4f.transform3v(OpenMatrix4f.createRotatorDeg(degree, axis), src, dest);
|
||||
}
|
||||
|
||||
private static final Vector3f SRC = new Vector3f();
|
||||
private static final Vector3f TRANSFORM_RESULT = new Vector3f();
|
||||
|
||||
public static Vec3f rotate(Quaternionf rot, Vec3f src, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
SRC.set(src.x, src.y, src.z);
|
||||
rot.transform(SRC, TRANSFORM_RESULT);
|
||||
dest.set(TRANSFORM_RESULT.x, TRANSFORM_RESULT.y, TRANSFORM_RESULT.z);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static float dot(Vec3f left, Vec3f right) {
|
||||
return left.x * right.x + left.y * right.y + left.z * right.z;
|
||||
}
|
||||
|
||||
public static Vec3f cross(Vec3f left, Vec3f right, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
dest.set(left.y * right.z - left.z * right.y, right.x * left.z - right.z * left.x, left.x * right.y - left.y * right.x);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static float getAngleBetween(Vec3f a, Vec3f b) {
|
||||
return (float) Math.acos(Math.min(1.0F, Vec3f.dot(a, b) / (a.length() * b.length())));
|
||||
}
|
||||
|
||||
public static Quaternionf getRotatorBetween(Vec3f a, Vec3f b, Quaternionf dest) {
|
||||
if (dest == null) {
|
||||
dest = new Quaternionf();
|
||||
}
|
||||
|
||||
Vec3f axis = Vec3f.cross(a, b, null).normalize();
|
||||
float dotDivLength = Vec3f.dot(a, b) / (a.length() * b.length());
|
||||
|
||||
if (!Float.isFinite(dotDivLength)) {
|
||||
EpicFightMod.LOGGER.info("Warning : given vector's length is zero");
|
||||
(new IllegalArgumentException()).printStackTrace();
|
||||
dotDivLength = 1.0F;
|
||||
}
|
||||
|
||||
float radian = (float)Math.acos(Math.min(1.0F, dotDivLength));
|
||||
dest.setAngleAxis(radian, axis.x, axis.y, axis.z);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static Vec3f interpolate(Vec3f from, Vec3f to, float interpolation, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
dest.x = from.x + (to.x - from.x) * interpolation;
|
||||
dest.y = from.y + (to.y - from.y) * interpolation;
|
||||
dest.z = from.z + (to.z - from.z) * interpolation;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public Vec3f normalize() {
|
||||
return normalize(this, this);
|
||||
}
|
||||
|
||||
public static Vec3f normalize(Vec3f src, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
float norm = (float) Math.sqrt(src.x * src.x + src.y * src.y + src.z * src.z);
|
||||
|
||||
if (norm > 1E-5F) {
|
||||
dest.x = src.x / norm;
|
||||
dest.y = src.y / norm;
|
||||
dest.z = src.z / norm;
|
||||
} else {
|
||||
dest.x = 0;
|
||||
dest.y = 0;
|
||||
dest.z = 0;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + this.x + ", " + this.y + ", " + this.z + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
} else if (o instanceof Vec3f vec3f) {
|
||||
return Float.compare(this.x, vec3f.x) == 0 && Float.compare(this.y, vec3f.y) == 0 && Float.compare(this.z, vec3f.z) == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int j = Float.floatToIntBits(this.x);
|
||||
int i = (int) (j ^ j >>> 32);
|
||||
j = Float.floatToIntBits(this.y);
|
||||
i = 31 * i + (int) (j ^ j >>> 32);
|
||||
j = Float.floatToIntBits(this.z);
|
||||
|
||||
return 31 * i + (int) (j ^ j >>> 32);
|
||||
}
|
||||
|
||||
public static Vec3f average(Collection<Vec3f> vectors, Vec3f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
dest.set(0.0F, 0.0F, 0.0F);
|
||||
|
||||
for (Vec3f v : vectors) {
|
||||
dest.add(v);
|
||||
}
|
||||
|
||||
dest.scale(1.0F / vectors.size());
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static Vec3f average(Vec3f dest, Vec3f... vectors) {
|
||||
if (dest == null) {
|
||||
dest = new Vec3f();
|
||||
}
|
||||
|
||||
dest.set(0.0F, 0.0F, 0.0F);
|
||||
|
||||
for (Vec3f v : vectors) {
|
||||
dest.add(v);
|
||||
}
|
||||
|
||||
dest.scale(vectors.length);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static int getNearest(Vec3f from, List<Vec3f> vectors) {
|
||||
float minLength = Float.MAX_VALUE;
|
||||
int index = -1;
|
||||
|
||||
for (int i = 0; i < vectors.size(); i++) {
|
||||
if (vectors.get(i) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!vectors.get(i).validateValues()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float distSqr = from.distanceSqr(vectors.get(i));
|
||||
|
||||
if (distSqr < minLength) {
|
||||
minLength = distSqr;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
public static int getNearest(Vec3f from, Vec3f... vectors) {
|
||||
float minLength = Float.MAX_VALUE;
|
||||
int index = -1;
|
||||
|
||||
for (int i = 0; i < vectors.length; i++) {
|
||||
if (vectors[i] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!vectors[i].validateValues()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float distSqr = from.distanceSqr(vectors[i]);
|
||||
|
||||
if (distSqr < minLength) {
|
||||
minLength = distSqr;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
public static int getMostSimilar(Vec3f start, Vec3f end, Vec3f... vectors) {
|
||||
Vec3f.sub(end, start, BASIS_DIRECTION);
|
||||
float maxDot = Float.MIN_VALUE;
|
||||
int index = -1;
|
||||
|
||||
for (int i = 0; i < vectors.length; i++) {
|
||||
if (vectors[i] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!vectors[i].validateValues()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Vec3f.sub(vectors[i], start, COMPARISION);
|
||||
float dot = Vec3f.dot(BASIS_DIRECTION, COMPARISION) / BASIS_DIRECTION.length() * COMPARISION.length();
|
||||
|
||||
if (dot > maxDot) {
|
||||
maxDot = dot;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
private static final Vec3f BASIS_DIRECTION = new Vec3f();
|
||||
private static final Vec3f COMPARISION = new Vec3f();
|
||||
|
||||
public static int getMostSimilar(Vec3f start, Vec3f end, List<Vec3f> vectors) {
|
||||
Vec3f.sub(end, start, BASIS_DIRECTION);
|
||||
float maxDot = Float.MIN_VALUE;
|
||||
int index = -1;
|
||||
|
||||
for (int i = 0; i < vectors.size(); i++) {
|
||||
if (vectors.get(i) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!vectors.get(i).validateValues()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Vec3f.sub(vectors.get(i), start, COMPARISION);
|
||||
float dot = Vec3f.dot(BASIS_DIRECTION, COMPARISION) / BASIS_DIRECTION.length() * COMPARISION.length();
|
||||
|
||||
if (dot > maxDot) {
|
||||
maxDot = dot;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
public Vector3f toMojangVector() {
|
||||
return new Vector3f(this.x, this.y, this.z);
|
||||
}
|
||||
|
||||
public Vec3 toDoubleVector() {
|
||||
return new Vec3(this.x, this.y, this.z);
|
||||
}
|
||||
|
||||
public static Vec3f fromMojangVector(Vector3f vec3) {
|
||||
return new Vec3f(vec3.x(), vec3.y(), vec3.z());
|
||||
}
|
||||
|
||||
public static Vec3f fromDoubleVector(Vec3 vec3) {
|
||||
return new Vec3f((float)vec3.x(), (float)vec3.y(), (float)vec3.z());
|
||||
}
|
||||
|
||||
private static final OpenMatrix4f DEST = new OpenMatrix4f();
|
||||
|
||||
public Vec3f rotateDegree(Vec3f axis, float degree) {
|
||||
OpenMatrix4f.ofRotationDegree(degree, axis, DEST);
|
||||
OpenMatrix4f.transform3v(DEST, this, this);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
75
src/main/java/com/tiedup/remake/rig/math/Vec4f.java
Normal file
75
src/main/java/com/tiedup/remake/rig/math/Vec4f.java
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Derived from Epic Fight (https://github.com/Epic-Fight/epicfight)
|
||||
* by the Epic Fight Team, licensed under GPLv3.
|
||||
* Modifications © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
|
||||
*/
|
||||
|
||||
package com.tiedup.remake.rig.math;
|
||||
|
||||
public class Vec4f extends Vec3f {
|
||||
public float w;
|
||||
|
||||
public Vec4f() {
|
||||
super();
|
||||
this.w = 0;
|
||||
}
|
||||
|
||||
public Vec4f(float x, float y, float z, float w) {
|
||||
super(x, y, z);
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
public Vec4f(Vec3f vec3f) {
|
||||
super(vec3f.x, vec3f.y, vec3f.z);
|
||||
this.w = 1.0F;
|
||||
}
|
||||
|
||||
public void set(float x, float y, float z, float w) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
public void set(Vec4f vec4f) {
|
||||
super.set(vec4f);
|
||||
this.w = vec4f.w;
|
||||
}
|
||||
|
||||
public Vec4f add(float x, float y, float z, float w) {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
this.z += z;
|
||||
this.w += w;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Vec4f add(Vec4f left, Vec4f right, Vec4f dest) {
|
||||
if (dest == null) {
|
||||
dest = new Vec4f();
|
||||
}
|
||||
|
||||
dest.x = left.x + right.x;
|
||||
dest.y = left.y + right.y;
|
||||
dest.z = left.z + right.z;
|
||||
dest.w = left.w + right.w;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec4f scale(float f) {
|
||||
super.scale(f);
|
||||
this.w *= f;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vec4f transform(OpenMatrix4f matrix) {
|
||||
return OpenMatrix4f.transform(matrix, this, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Vec4f[" + this.x + ", " + this.y + ", " + this.z + ", " + this.w + "]";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user