139 lines
4.2 KiB
Java
139 lines
4.2 KiB
Java
package com.mojang.math;
|
|
|
|
import net.minecraft.Util;
|
|
import java.util.Objects;
|
|
import org.apache.commons.lang3.tuple.Triple;
|
|
import com.mojang.datafixers.util.Pair;
|
|
import javax.annotation.Nullable;
|
|
|
|
public final class Transformation {
|
|
private final Matrix4f matrix;
|
|
private boolean decomposed;
|
|
@Nullable
|
|
private Vector3f translation;
|
|
@Nullable
|
|
private Quaternion leftRotation;
|
|
@Nullable
|
|
private Vector3f scale;
|
|
@Nullable
|
|
private Quaternion rightRotation;
|
|
private static final Transformation IDENTITY;
|
|
|
|
public Transformation(@Nullable final Matrix4f b) {
|
|
if (b == null) {
|
|
this.matrix = Transformation.IDENTITY.matrix;
|
|
}
|
|
else {
|
|
this.matrix = b;
|
|
}
|
|
}
|
|
|
|
public Transformation(@Nullable final Vector3f e1, @Nullable final Quaternion c2, @Nullable final Vector3f e3, @Nullable final Quaternion c4) {
|
|
this.matrix = compose(e1, c2, e3, c4);
|
|
this.translation = ((e1 != null) ? e1 : new Vector3f());
|
|
this.leftRotation = ((c2 != null) ? c2 : Quaternion.ONE.copy());
|
|
this.scale = ((e3 != null) ? e3 : new Vector3f(1.0f, 1.0f, 1.0f));
|
|
this.rightRotation = ((c4 != null) ? c4 : Quaternion.ONE.copy());
|
|
this.decomposed = true;
|
|
}
|
|
|
|
public static Transformation identity() {
|
|
return Transformation.IDENTITY;
|
|
}
|
|
|
|
public Transformation compose(final Transformation d) {
|
|
final Matrix4f b3 = this.getMatrix();
|
|
b3.multiply(d.getMatrix());
|
|
return new Transformation(b3);
|
|
}
|
|
|
|
@Nullable
|
|
public Transformation inverse() {
|
|
if (this == Transformation.IDENTITY) {
|
|
return this;
|
|
}
|
|
final Matrix4f b2 = this.getMatrix();
|
|
if (b2.invert()) {
|
|
return new Transformation(b2);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void ensureDecomposed() {
|
|
if (!this.decomposed) {
|
|
final Pair<Matrix3f, Vector3f> pair2 = toAffine(this.matrix);
|
|
final Triple<Quaternion, Vector3f, Quaternion> triple3 = ((Matrix3f)pair2.getFirst()).svdDecompose();
|
|
this.translation = (Vector3f)pair2.getSecond();
|
|
this.leftRotation = (Quaternion)triple3.getLeft();
|
|
this.scale = (Vector3f)triple3.getMiddle();
|
|
this.rightRotation = (Quaternion)triple3.getRight();
|
|
this.decomposed = true;
|
|
}
|
|
}
|
|
|
|
private static Matrix4f compose(@Nullable final Vector3f e1, @Nullable final Quaternion c2, @Nullable final Vector3f e3, @Nullable final Quaternion c4) {
|
|
final Matrix4f b5 = new Matrix4f();
|
|
b5.setIdentity();
|
|
if (c2 != null) {
|
|
b5.multiply(new Matrix4f(c2));
|
|
}
|
|
if (e3 != null) {
|
|
b5.multiply(Matrix4f.createScaleMatrix(e3.x(), e3.y(), e3.z()));
|
|
}
|
|
if (c4 != null) {
|
|
b5.multiply(new Matrix4f(c4));
|
|
}
|
|
if (e1 != null) {
|
|
b5.m03 = e1.x();
|
|
b5.m13 = e1.y();
|
|
b5.m23 = e1.z();
|
|
}
|
|
return b5;
|
|
}
|
|
|
|
public static Pair<Matrix3f, Vector3f> toAffine(final Matrix4f b) {
|
|
b.multiply(1.0f / b.m33);
|
|
final Vector3f e2 = new Vector3f(b.m03, b.m13, b.m23);
|
|
final Matrix3f a3 = new Matrix3f(b);
|
|
return (Pair<Matrix3f, Vector3f>)Pair.of(a3, e2);
|
|
}
|
|
|
|
public Matrix4f getMatrix() {
|
|
return this.matrix.copy();
|
|
}
|
|
|
|
public Quaternion getLeftRotation() {
|
|
this.ensureDecomposed();
|
|
return this.leftRotation.copy();
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(final Object object) {
|
|
if (this == object) {
|
|
return true;
|
|
}
|
|
if (object == null || this.getClass() != object.getClass()) {
|
|
return false;
|
|
}
|
|
final Transformation d3 = (Transformation)object;
|
|
return Objects.equals(this.matrix, d3.matrix);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(this.matrix);
|
|
}
|
|
|
|
static {
|
|
final Matrix4f b1;
|
|
final Transformation d2;
|
|
IDENTITY = Util.<Transformation>make(() -> {
|
|
b1 = new Matrix4f();
|
|
b1.setIdentity();
|
|
d2 = new Transformation(b1);
|
|
d2.getLeftRotation();
|
|
return d2;
|
|
});
|
|
}
|
|
}
|