From e0b8df4e3085ad2480b64d71680e68b60199337b Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Mon, 25 Mar 2024 04:09:52 +0300 Subject: [PATCH] Refactor DMF exporter to use JOML (#66) --- .../data/viewer/model/BaseModelExporter.java | 63 +++-- .../ui/data/viewer/model/dmf/DMFExporter.java | 83 +++---- .../data/viewer/model/dmf/DMFTransform.java | 32 +-- .../ui/data/viewer/model/utils/Matrix3x3.java | 177 -------------- .../ui/data/viewer/model/utils/Matrix4x4.java | 226 ------------------ .../data/viewer/model/utils/Quaternion.java | 29 --- .../ui/data/viewer/model/utils/Transform.java | 6 - .../ui/data/viewer/model/utils/Vector3.java | 14 -- 8 files changed, 85 insertions(+), 545 deletions(-) delete mode 100644 modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Matrix3x3.java delete mode 100644 modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Matrix4x4.java delete mode 100644 modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Quaternion.java delete mode 100644 modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Transform.java delete mode 100644 modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Vector3.java diff --git a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/BaseModelExporter.java b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/BaseModelExporter.java index 4ad436181..057e694e0 100644 --- a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/BaseModelExporter.java +++ b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/BaseModelExporter.java @@ -5,67 +5,62 @@ import com.shade.decima.model.rtti.objects.RTTIReference; import com.shade.decima.model.rtti.registry.RTTITypeRegistry; import com.shade.decima.model.rtti.types.RTTITypeEnum; -import com.shade.decima.ui.data.viewer.model.utils.Matrix3x3; -import com.shade.decima.ui.data.viewer.model.utils.Matrix4x4; -import com.shade.decima.ui.data.viewer.model.utils.Transform; -import com.shade.decima.ui.data.viewer.model.utils.Vector3; import com.shade.platform.model.util.MathUtils; import com.shade.util.NotNull; +import org.joml.Matrix4d; import java.util.UUID; public class BaseModelExporter { @NotNull - protected static Transform worldTransformToTransform(@NotNull RTTIObject transform) { + protected static Matrix4d worldTransformToMatrix(@NotNull RTTIObject transform) { + if (!transform.type().isInstanceOf("WorldTransform")) { + throw new IllegalArgumentException("Expected WorldTransform instance, but got " + transform.type()); + } final var pos = transform.obj("Position"); final var ori = transform.obj("Orientation"); final var col0 = ori.obj("Col0"); final var col1 = ori.obj("Col1"); final var col2 = ori.obj("Col2"); - - final Vector3 translation = new Vector3(new double[]{ - pos.f64("X"), - pos.f64("Y"), - pos.f64("Z") - }); - - final Matrix3x3 rotationAndScale = new Matrix3x3(new double[][]{ - new double[]{col0.f32("X"), col0.f32("Y"), col0.f32("Z")}, - new double[]{col1.f32("X"), col1.f32("Y"), col1.f32("Z")}, - new double[]{col2.f32("X"), col2.f32("Y"), col2.f32("Z")} - }); - - return new Transform(translation, rotationAndScale.toQuaternion(), rotationAndScale.toScale()); + return new Matrix4d( + col0.f32("X"), col0.f32("Y"), col0.f32("Z"), 0, + col1.f32("X"), col1.f32("Y"), col1.f32("Z"), 0, + col2.f32("X"), col2.f32("Y"), col2.f32("Z"), 0, + pos.f64("X"), pos.f64("Y"), pos.f64("Z"), 1 + ); } @NotNull - protected static Transform mat34ToTransform(@NotNull RTTIObject object) { + protected static Matrix4d mat34ToMatrix(@NotNull RTTIObject object) { final RTTIObject row0 = object.obj("Row0"); final RTTIObject row1 = object.obj("Row1"); final RTTIObject row2 = object.obj("Row2"); - final Matrix4x4 mat = new Matrix4x4(new double[][]{ - {row0.f32("X"), row0.f32("Y"), row0.f32("Z"), row0.f32("W")}, - {row1.f32("X"), row1.f32("Y"), row1.f32("Z"), row1.f32("W")}, - {row2.f32("X"), row2.f32("Y"), row2.f32("Z"), row2.f32("W")}, - {0.0, 0.0, 0.0, 1.0} - }); - return new Transform(mat.toTranslation(), mat.toQuaternion(), mat.toScale()); + return new Matrix4d( + row0.f32("X"), row1.f32("X"), row2.f32("X"), 0.0f, + row0.f32("Y"), row1.f32("Y"), row2.f32("Y"), 0.0f, + row0.f32("Z"), row1.f32("Z"), row2.f32("Z"), 0.0f, + row0.f32("W"), row1.f32("W"), row2.f32("W"), 1.0f + ); } + @NotNull - protected static Matrix4x4 mat44TransformToMatrix4x4(@NotNull RTTIObject transform) { + protected static Matrix4d mat44TransformToMatrix(@NotNull RTTIObject transform) { + if (!transform.type().isInstanceOf("Mat44")) { + throw new IllegalArgumentException("Expected Mat44 instance, but got " + transform.type()); + } final var col0 = transform.obj("Col0"); final var col1 = transform.obj("Col1"); final var col2 = transform.obj("Col2"); final var col3 = transform.obj("Col3"); - return new Matrix4x4(new double[][]{ - new double[]{col0.f32("X"), col1.f32("X"), col2.f32("X"), col3.f32("X")}, - new double[]{col0.f32("Y"), col1.f32("Y"), col2.f32("Y"), col3.f32("Y")}, - new double[]{col0.f32("Z"), col1.f32("Z"), col2.f32("Z"), col3.f32("Z")}, - new double[]{col0.f32("W"), col1.f32("W"), col2.f32("W"), col3.f32("W")} - }); + return new Matrix4d( + col0.f32("X"), col0.f32("Y"), col0.f32("Z"), col0.f32("W"), + col1.f32("X"), col1.f32("Y"), col1.f32("Z"), col1.f32("W"), + col2.f32("X"), col2.f32("Y"), col2.f32("Z"), col2.f32("W"), + col3.f32("X"), col3.f32("Y"), col3.f32("Z"), col3.f32("W") + ); } @NotNull diff --git a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/dmf/DMFExporter.java b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/dmf/DMFExporter.java index 3751f61e1..7451ed286 100644 --- a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/dmf/DMFExporter.java +++ b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/dmf/DMFExporter.java @@ -20,10 +20,6 @@ import com.shade.decima.ui.data.viewer.model.BaseModelExporter; import com.shade.decima.ui.data.viewer.model.ModelExporter; import com.shade.decima.ui.data.viewer.model.ModelExporterProvider; -import com.shade.decima.ui.data.viewer.model.utils.Matrix4x4; -import com.shade.decima.ui.data.viewer.model.utils.Quaternion; -import com.shade.decima.ui.data.viewer.model.utils.Transform; -import com.shade.decima.ui.data.viewer.model.utils.Vector3; import com.shade.decima.ui.data.viewer.texture.TextureViewer; import com.shade.decima.ui.data.viewer.texture.controls.ImageProvider; import com.shade.decima.ui.data.viewer.texture.exporter.TextureExporterPNG; @@ -33,6 +29,9 @@ import com.shade.platform.model.util.MathUtils; import com.shade.util.NotNull; import com.shade.util.Nullable; +import org.joml.Matrix4dc; +import org.joml.Quaterniond; +import org.joml.Vector3d; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -171,7 +170,7 @@ private void exportControlledEntityResource( task.worked(1); } - final RTTIReference[] convertedParts = destructibilityResourceRef.object().get("ConvertedParts"); + final var convertedParts = destructibilityResourceRef.object().refs("ConvertedParts"); try (ProgressMonitor.Task cpTask = task.split(1).begin("Exporting ControlledEntity ConvertedParts", convertedParts.length)) { for (RTTIReference part : convertedParts) { final RTTIReference.FollowResult partRef = part.follow(project, destructibilityResourceRef.file()); @@ -301,7 +300,7 @@ private void exportTerrain( primitive.setMaterial(material, scene); - final Transform transform = worldTransformToTransform(object.get("Orientation")); + final Matrix4dc transform = worldTransformToMatrix(object.get("Orientation")); model.transform = new DMFTransform(transform); terrainTask.worked(1); scene.models.add(model); @@ -337,18 +336,7 @@ private void exportArtPartsDataResource( final RTTIObject[] joints = repSkeleton.objs("Joints"); for (short i = 0; i < joints.length; i++) { final RTTIObject joint = joints[i]; - final Quaternion rotations; - if (defaultRot.length > 0) { - rotations = new Quaternion(defaultRot[i].f32("X"), defaultRot[i].f32("Y"), defaultRot[i].f32("Z"), defaultRot[i].f32("W")); - } else { - rotations = new Quaternion(0d, 0d, 0d, 1d); - } - - DMFTransform matrix = new DMFTransform( - new Vector3(defaultPos[i].f32("X"), defaultPos[i].f32("Y"), defaultPos[i].f32("Z")), - new Vector3(1, 1, 1), - rotations - ); + final DMFTransform matrix = poseToMatrix(i, defaultRot, defaultPos); final DMFBone bone = masterSkeleton.findBone(joint.str("Name")); if (bone != null) { bone.transform = matrix; @@ -579,18 +567,7 @@ private DMFNode artPartsSubModelResourceToModel( final RTTIObject[] joints = skeleton.objs("Joints"); for (short i = 0; i < joints.length; i++) { final RTTIObject joint = joints[i]; - final Quaternion rotations; - if (defaultRot.length > 0) { - rotations = new Quaternion(defaultRot[i].f32("X"), defaultRot[i].f32("Y"), defaultRot[i].f32("Z"), defaultRot[i].f32("W")); - } else { - rotations = new Quaternion(0d, 0d, 0d, 1d); - } - - DMFTransform matrix = new DMFTransform( - new Vector3(defaultPos[i].f32("X"), defaultPos[i].f32("Y"), defaultPos[i].f32("Z")), - new Vector3(1, 1, 1), - rotations - ); + DMFTransform matrix = poseToMatrix(i, defaultRot, defaultPos); final DMFBone bone = masterSkeleton.findBone(joint.str("Name")); if (bone != null) { bone.transform = matrix; @@ -627,6 +604,27 @@ private DMFNode artPartsSubModelResourceToModel( return model; } + private static DMFTransform poseToMatrix(short jointId, RTTIObject[] defaultRot, RTTIObject[] defaultPos) { + final Quaterniond rotations; + final Vector3d position; + if (jointId < defaultRot.length) { + rotations = new Quaterniond(defaultRot[jointId].f32("X"), defaultRot[jointId].f32("Y"), defaultRot[jointId].f32("Z"), defaultRot[jointId].f32("W")); + } else { + rotations = new Quaterniond(0, 0, 0, 1); + } + if (jointId < defaultPos.length) { + position = new Vector3d(defaultPos[jointId].f32("X"), defaultPos[jointId].f32("Y"), defaultPos[jointId].f32("Z")); + } else { + position = new Vector3d(0, 0, 0); + } + + return new DMFTransform( + position, + new Vector3d(1, 1, 1), + rotations + ); + } + @Nullable private DMFNode artPartsSubModelWithChildrenResourceToModel( @NotNull ProgressMonitor monitor, @@ -729,7 +727,7 @@ private DMFNode prefabInstanceToModel( final DMFInstance instance = new DMFInstance(resourceName, instanceId); - final Transform transform = worldTransformToTransform(object.get("Orientation")); + final Matrix4dc transform = worldTransformToMatrix(object.get("Orientation")); instance.transform = new DMFTransform(transform); return instance; } @@ -761,7 +759,7 @@ private DMFNode staticMeshInstanceToModel( } final DMFInstance instance = new DMFInstance(resourceName, instanceId); - final Transform transform = worldTransformToTransform(object.get("Orientation")); + final Matrix4dc transform = worldTransformToMatrix(object.get("Orientation")); instance.transform = new DMFTransform(transform); return instance; @@ -806,7 +804,7 @@ private DMFAttachmentNode destructibilityPartToModel( if (state == null) { return null; } - DMFAttachmentNode node = new DMFAttachmentNode(object.str("Name"), object.str("BoneName"), new DMFTransform(mat44TransformToMatrix4x4(object.obj("LocalMatrix")))); + DMFAttachmentNode node = new DMFAttachmentNode(object.str("Name"), object.str("BoneName"), new DMFTransform(mat44TransformToMatrix(object.obj("LocalMatrix")))); node.children.add(state); return node; } @@ -826,7 +824,7 @@ private DMFNode destructibilityPartStateResourceToModel( if (state == null) { return null; } - final Matrix4x4 offsetMatrix = mat44TransformToMatrix4x4(object.obj("OffsetMatrix")); + final Matrix4dc offsetMatrix = mat44TransformToMatrix(object.obj("OffsetMatrix")); DMFNode node = new DMFModelGroup(resourceName); node.transform = new DMFTransform(offsetMatrix); node.children.add(state); @@ -929,7 +927,7 @@ private DMFNode multiMeshResourceToModel( if (model.transform != null) { throw new IllegalStateException("Model already had transforms, please handle me!"); } - model.transform = new DMFTransform(mat34ToTransform(transforms[partId])); + model.transform = new DMFTransform(mat34ToMatrix(transforms[partId])); } group.children.add(model); } @@ -942,7 +940,6 @@ private DMFNode multiMeshResourceToModel( final RTTIObject part = parts[partId]; final RTTIReference meshRef = part.ref("Mesh"); final RTTIReference.FollowResult mesh = Objects.requireNonNull(meshRef.follow(project, file)); - final Transform transform = worldTransformToTransform(part.obj("Transform")); final DMFNode model = toModel(task.split(1), mesh.file(), mesh.object(), "%s_Part%d".formatted(nameFromReference(meshRef, resourceName), partId)); if (model == null) { continue; @@ -950,7 +947,7 @@ private DMFNode multiMeshResourceToModel( if (model.transform != null) { throw new IllegalStateException("Model already had transforms, please handle me!"); } - model.transform = new DMFTransform(transform); + model.transform = new DMFTransform(worldTransformToMatrix(part.get("Transform"))); group.children.add(model); } } @@ -996,13 +993,11 @@ private DMFNode regularSkinnedMeshResourceToModel( if (localBoneId == -1) { continue; } - DMFTransform matrix; DMFBone bone = currentSkeleton.findBone(joints[i].str("Name")); if (bone == null) { throw new IllegalStateException("All new bones should've been created in validateSkeleton call"); } - matrix = new DMFTransform(mat44TransformToMatrix4x4(inverseBindMatrices[localBoneId]).inverted()); - bone.transform = matrix; + bone.transform = new DMFTransform(mat44TransformToMatrix(inverseBindMatrices[localBoneId]).invert()); bone.localSpace = false; } @@ -1413,7 +1408,7 @@ private DMFSkeleton exportSkeleton(@NotNull RTTIObject skeleton) { final DMFSkeleton dmfSkeleton = new DMFSkeleton(); RTTIObject[] bones = skeleton.objs("Joints"); for (final RTTIObject bone : bones) { - dmfSkeleton.newBone(bone.str("Name"), new DMFTransform(Matrix4x4.identity()), bone.i16("ParentIndex")); + dmfSkeleton.newBone(bone.str("Name"), DMFTransform.IDENTITY, bone.i16("ParentIndex")); } return dmfSkeleton; } @@ -1423,7 +1418,7 @@ private void validateSkeleton(@NotNull DMFSkeleton currentSkeleton, @NotNull RTT for (final RTTIObject bone : bones) { final String boneName = bone.str("Name"); if (currentSkeleton.findBone(boneName) == null) { - currentSkeleton.newBone(boneName, new DMFTransform(Matrix4x4.identity()), bone.i16("ParentIndex")); + currentSkeleton.newBone(boneName, DMFTransform.IDENTITY, bone.i16("ParentIndex")); } } } @@ -1435,14 +1430,14 @@ private void exportHelpers(@NotNull RTTIObject helper, @NotNull DMFSkeleton mast if (boneId == -1) { masterSkeleton.newBone( helperNode.str("Name"), - new DMFTransform(mat44TransformToMatrix4x4(helperNode.obj("Matrix"))), + new DMFTransform(mat44TransformToMatrix(helperNode.obj("Matrix"))), -1 ).localSpace = false; } else { String boneName = bones[boneId].str("Name"); masterSkeleton.newBone( helperNode.str("Name"), - new DMFTransform(mat44TransformToMatrix4x4(helperNode.obj("Matrix"))), + new DMFTransform(mat44TransformToMatrix(helperNode.obj("Matrix"))), masterSkeleton.findBoneId(boneName) ).localSpace = true; } diff --git a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/dmf/DMFTransform.java b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/dmf/DMFTransform.java index bc33c3406..d1ca09bbf 100644 --- a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/dmf/DMFTransform.java +++ b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/dmf/DMFTransform.java @@ -1,34 +1,36 @@ package com.shade.decima.ui.data.viewer.model.dmf; -import com.shade.decima.ui.data.viewer.model.utils.Matrix4x4; -import com.shade.decima.ui.data.viewer.model.utils.Quaternion; -import com.shade.decima.ui.data.viewer.model.utils.Transform; -import com.shade.decima.ui.data.viewer.model.utils.Vector3; import com.shade.util.NotNull; +import org.joml.*; import java.util.Arrays; public class DMFTransform { - public static final DMFTransform IDENTITY = new DMFTransform(new Vector3(0, 0, 0), new Vector3(1, 1, 1), new Quaternion(0, 0, 0, 1)); + public static final DMFTransform IDENTITY = new DMFTransform(new double[]{0, 0, 0}, new double[]{1, 1, 1}, new double[]{0, 0, 0, 1}); public final double[] position; public final double[] scale; public final double[] rotation; - public DMFTransform(@NotNull Vector3 position, @NotNull Vector3 scale, @NotNull Quaternion rotation) { - this.position = position.toArray(); - this.scale = scale.toArray(); - this.rotation = rotation.toArray(); + public DMFTransform(@NotNull double[] position, @NotNull double[] scale, @NotNull double[] rotation) { + this.position = position; + this.scale = scale; + this.rotation = rotation; } - public DMFTransform(@NotNull Transform transform) { - this.position = transform.translation().toArray(); - this.scale = transform.scale().toArray(); - this.rotation = transform.rotation().toArray(); + public DMFTransform(@NotNull Matrix4dc matrix) { + final Vector3d translation = matrix.getTranslation(new Vector3d()); + final Vector3d scale = matrix.getScale(new Vector3d()); + final Quaterniond rotation = matrix.getUnnormalizedRotation(new Quaterniond()); + this.position = new double[]{translation.x(), translation.y(), translation.z()}; + this.scale = new double[]{scale.x(), scale.y(), scale.z()}; + this.rotation = new double[]{rotation.x(), rotation.y(), rotation.z(), rotation.w()}; } - public DMFTransform(@NotNull Matrix4x4 matrix) { - this(matrix.toTranslation(), matrix.toScale(), matrix.toQuaternion()); + public DMFTransform(@NotNull Vector3dc translation, @NotNull Vector3dc scale, @NotNull Quaterniondc rotation) { + this.position = new double[]{translation.x(), translation.y(), translation.z()}; + this.scale = new double[]{scale.x(), scale.y(), scale.z()}; + this.rotation = new double[]{rotation.x(), rotation.y(), rotation.z(), rotation.w()}; } @Override diff --git a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Matrix3x3.java b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Matrix3x3.java deleted file mode 100644 index 9bc1457e5..000000000 --- a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Matrix3x3.java +++ /dev/null @@ -1,177 +0,0 @@ -package com.shade.decima.ui.data.viewer.model.utils; - -import com.shade.util.NotNull; - -import java.util.Arrays; - -public record Matrix3x3(@NotNull double[][] matrix) { - public Matrix3x3(@NotNull double[][] matrix) { - this.matrix = new double[3][3]; - System.arraycopy(matrix[0], 0, this.matrix[0], 0, 3); - System.arraycopy(matrix[1], 0, this.matrix[1], 0, 3); - System.arraycopy(matrix[2], 0, this.matrix[2], 0, 3); - } - - @NotNull - public static Matrix3x3 identity() { - return new Matrix3x3(new double[][]{ - {1, 0, 0}, - {0, 1, 0}, - {0, 0, 1}, - }); - } - - - @NotNull - public Matrix3x3 negative() { - final Matrix3x3 output = Matrix3x3.identity(); - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - output.matrix[i][j] = -matrix[i][j]; - } - } - return output; - } - - public Matrix3x3 normalized() { - Matrix3x3 output = Matrix3x3.identity(); - for (int i = 0; i < matrix.length; i++) { - double[] col = matrix[i]; - double mag = 0; - for (double v : col) { - mag += v * v; - } - mag = Math.sqrt(mag); - for (int j = 0; j < col.length; j++) { - output.matrix[i][j] = col[j] / mag; - } - } - return output; - } - - public double determinant() { - return determinant(matrix); - } - - public static double determinant(double[][] matrix) { - return (matrix[0][0] * (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1]) - - matrix[1][0] * (matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1]) + - matrix[2][0] * (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])); - } - - public boolean isNegative() { - return determinant() < 0; - } - - @NotNull - public Matrix3x3 transposed() { - double[][] transposed = new double[3][3]; - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - transposed[j][i] = matrix[i][j]; - } - } - return new Matrix3x3(transposed); - } - - public Quaternion toQuaternion() { - Matrix3x3 normalized = normalized(); - double[][] mat = normalized.matrix; - double det = determinant(); - if (Double.isInfinite(det)) { - mat = Matrix3x3.identity().matrix; - } else if (isNegative()) { - mat = negative().matrix; - } - double[] q = new double[4]; - - if (mat[2][2] < 0.0f) { - if (mat[0][0] > mat[1][1]) { - double trace = 1.0f + mat[0][0] - mat[1][1] - mat[2][2]; - double s = 2.0f * Math.sqrt(trace); - if (mat[1][2] < mat[2][1]) { - /* Ensure W is non-negative for a canonical result. */ - s = -s; - } - q[1] = 0.25f * s; - s = 1.0f / s; - q[0] = (mat[1][2] - mat[2][1]) * s; - q[2] = (mat[0][1] + mat[1][0]) * s; - q[3] = (mat[2][0] + mat[0][2]) * s; - if ((trace == 1.0f) && (q[0] == 0.0f && q[2] == 0.0f && q[3] == 0.0f)) { - /* Avoids the need to normalize the degenerate case. */ - q[1] = 1.0f; - } - } else { - double trace = 1.0f - mat[0][0] + mat[1][1] - mat[2][2]; - double s = 2.0f * Math.sqrt(trace); - if (mat[2][0] < mat[0][2]) { - /* Ensure W is non-negative for a canonical result. */ - s = -s; - } - q[2] = 0.25f * s; - s = 1.0f / s; - q[0] = (mat[2][0] - mat[0][2]) * s; - q[1] = (mat[0][1] + mat[1][0]) * s; - q[3] = (mat[1][2] + mat[2][1]) * s; - if ((trace == 1.0f) && (q[0] == 0.0f && q[1] == 0.0f && q[3] == 0.0f)) { - /* Avoids the need to normalize the degenerate case. */ - q[2] = 1.0f; - } - } - } else { - if (mat[0][0] < -mat[1][1]) { - double trace = 1.0f - mat[0][0] - mat[1][1] + mat[2][2]; - double s = 2.0f * Math.sqrt(trace); - if (mat[0][1] < mat[1][0]) { - /* Ensure W is non-negative for a canonical result. */ - s = -s; - } - q[3] = 0.25f * s; - s = 1.0f / s; - q[0] = (mat[0][1] - mat[1][0]) * s; - q[1] = (mat[2][0] + mat[0][2]) * s; - q[2] = (mat[1][2] + mat[2][1]) * s; - if ((trace == 1.0f) && (q[0] == 0.0f && q[1] == 0.0f && q[2] == 0.0f)) { - /* Avoids the need to normalize the degenerate case. */ - q[3] = 1.0f; - } - } else { - /* NOTE(@campbellbarton): A zero matrix will fall through to this block, - * needed so a zero scaled matrices to return a quaternion without rotation, see: T101848. */ - double trace = 1.0f + mat[0][0] + mat[1][1] + mat[2][2]; - double s = 2.0f * Math.sqrt(trace); - q[0] = 0.25f * s; - s = 1.0f / s; - q[1] = (mat[1][2] - mat[2][1]) * s; - q[2] = (mat[2][0] - mat[0][2]) * s; - q[3] = (mat[0][1] - mat[1][0]) * s; - if ((trace == 1.0f) && (q[1] == 0.0f && q[2] == 0.0f && q[3] == 0.0f)) { - /* Avoids the need to normalize the degenerate case. */ - q[0] = 1.0f; - } - } - } - return new Quaternion(new double[]{q[1], q[2], q[3], q[0]}).normalized(); - } - - public Vector3 toScale() { - double[] size = new double[3]; - for (int i = 0; i < 3; i++) { - double[] row = matrix[i]; - double mag = Math.sqrt(row[0] * row[0] + row[1] * row[1] + row[2] * row[2]); - size[i] = mag; - } - if (isNegative()) { - for (int i = 0; i < size.length; i++) { - size[i] = -size[i]; - } - } - return new Vector3(size); - } - - @Override - public String toString() { - return "Matrix3x3[\n\t%s,\n\t%s,\n\t%s\n]".formatted(Arrays.toString(matrix[0]), Arrays.toString(matrix[1]), Arrays.toString(matrix[2])); - } -} diff --git a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Matrix4x4.java b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Matrix4x4.java deleted file mode 100644 index 8d53b0dd1..000000000 --- a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Matrix4x4.java +++ /dev/null @@ -1,226 +0,0 @@ -package com.shade.decima.ui.data.viewer.model.utils; - - -import com.shade.util.NotNull; - -public record Matrix4x4(@NotNull double[][] matrix) { - public Matrix4x4(@NotNull double[][] matrix) { - this.matrix = new double[4][4]; - System.arraycopy(matrix[0], 0, this.matrix[0], 0, 4); - System.arraycopy(matrix[1], 0, this.matrix[1], 0, 4); - System.arraycopy(matrix[2], 0, this.matrix[2], 0, 4); - System.arraycopy(matrix[3], 0, this.matrix[3], 0, 4); - } - - public Matrix4x4() { - this(new double[4][4]); - } - - @NotNull - public static Matrix4x4 identity() { - return new Matrix4x4(new double[][]{ - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1} - }); - } - - @NotNull - public static Matrix4x4 translation(Vector3 translation) { - Matrix4x4 matrix = Matrix4x4.identity(); - matrix.matrix[0][3] = translation.x(); - matrix.matrix[1][3] = translation.y(); - matrix.matrix[2][3] = translation.z(); - return matrix; - } - - public Matrix4x4 matMul(Matrix4x4 other) { - Matrix4x4 otherT = other.transposed(); - Matrix4x4 mat = new Matrix4x4(); - for (int col = 0; col < matrix.length; col++) { - for (int row = 0; row < matrix.length; row++) { - double dot = 0; - dot += matrix[row][0] * otherT.matrix[col][0]; - dot += matrix[row][1] * otherT.matrix[col][1]; - dot += matrix[row][2] * otherT.matrix[col][2]; - dot += matrix[row][3] * otherT.matrix[col][3]; - mat.matrix[col][row] = dot; - } - } - return mat.transposed(); - } - - public Matrix4x4 transposed() { - double[][] transposed = new double[4][4]; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - transposed[j][i] = matrix[i][j]; - } - } - return new Matrix4x4(transposed); - } - - public Matrix4x4 adjoint() { - double[][] srcMat = matrix; - Matrix4x4 res = Matrix4x4.identity(); - double[][] dstMat = res.matrix; - - double a1 = srcMat[0][0]; - double b1 = srcMat[0][1]; - double c1 = srcMat[0][2]; - double d1 = srcMat[0][3]; - - double a2 = srcMat[1][0]; - double b2 = srcMat[1][1]; - double c2 = srcMat[1][2]; - double d2 = srcMat[1][3]; - - double a3 = srcMat[2][0]; - double b3 = srcMat[2][1]; - double c3 = srcMat[2][2]; - double d3 = srcMat[2][3]; - - double a4 = srcMat[3][0]; - double b4 = srcMat[3][1]; - double c4 = srcMat[3][2]; - double d4 = srcMat[3][3]; - - dstMat[0][0] = Matrix3x3.determinant(new double[][]{{b2, b3, b4}, {c2, c3, c4}, {d2, d3, d4}}); - dstMat[1][0] = -Matrix3x3.determinant(new double[][]{{a2, a3, a4}, {c2, c3, c4}, {d2, d3, d4}}); - dstMat[2][0] = Matrix3x3.determinant(new double[][]{{a2, a3, a4}, {b2, b3, b4}, {d2, d3, d4}}); - dstMat[3][0] = -Matrix3x3.determinant(new double[][]{{a2, a3, a4}, {b2, b3, b4}, {c2, c3, c4}}); - - dstMat[0][1] = -Matrix3x3.determinant(new double[][]{{b1, b3, b4}, {c1, c3, c4}, {d1, d3, d4}}); - dstMat[1][1] = Matrix3x3.determinant(new double[][]{{a1, a3, a4}, {c1, c3, c4}, {d1, d3, d4}}); - dstMat[2][1] = -Matrix3x3.determinant(new double[][]{{a1, a3, a4}, {b1, b3, b4}, {d1, d3, d4}}); - dstMat[3][1] = Matrix3x3.determinant(new double[][]{{a1, a3, a4}, {b1, b3, b4}, {c1, c3, c4}}); - - dstMat[0][2] = Matrix3x3.determinant(new double[][]{{b1, b2, b4}, {c1, c2, c4}, {d1, d2, d4}}); - dstMat[1][2] = -Matrix3x3.determinant(new double[][]{{a1, a2, a4}, {c1, c2, c4}, {d1, d2, d4}}); - dstMat[2][2] = Matrix3x3.determinant(new double[][]{{a1, a2, a4}, {b1, b2, b4}, {d1, d2, d4}}); - dstMat[3][2] = -Matrix3x3.determinant(new double[][]{{a1, a2, a4}, {b1, b2, b4}, {c1, c2, c4}}); - - dstMat[0][3] = -Matrix3x3.determinant(new double[][]{{b1, b2, b3}, {c1, c2, c3}, {d1, d2, d3}}); - dstMat[1][3] = Matrix3x3.determinant(new double[][]{{a1, a2, a3}, {c1, c2, c3}, {d1, d2, d3}}); - dstMat[2][3] = -Matrix3x3.determinant(new double[][]{{a1, a2, a3}, {b1, b2, b3}, {d1, d2, d3}}); - dstMat[3][3] = Matrix3x3.determinant(new double[][]{{a1, a2, a3}, {b1, b2, b3}, {c1, c2, c3}}); - return res; - } - - public Matrix4x4 normalized() { - Matrix4x4 output = Matrix4x4.identity(); - for (int i = 0; i < matrix.length; i++) { - double[] col = matrix[i]; - double mag = 0; - for (double v : col) { - mag += v * v; - } - mag = Math.sqrt(mag); - for (int j = 0; j < col.length; j++) { - output.matrix[i][j] = col[j] / mag; - } - } - return output; - } - - public double determinant() { - double determinant1 = Matrix3x3.determinant(new double[][]{ - {matrix[1][1], matrix[1][2], matrix[1][3]}, - {matrix[2][1], matrix[2][2], matrix[2][3]}, - {matrix[3][1], matrix[3][2], matrix[3][3]}, - } - ); - double determinant2 = Matrix3x3.determinant(new double[][]{ - {matrix[1][0], matrix[1][2], matrix[1][3]}, - {matrix[2][0], matrix[2][2], matrix[2][3]}, - {matrix[3][0], matrix[3][2], matrix[3][3]}, - } - ); - double determinant3 = Matrix3x3.determinant(new double[][]{ - {matrix[1][0], matrix[1][1], matrix[1][3]}, - {matrix[2][0], matrix[2][1], matrix[2][3]}, - {matrix[3][0], matrix[3][1], matrix[3][3]}, - } - ); - double determinant4 = Matrix3x3.determinant(new double[][]{ - {matrix[1][0], matrix[1][1], matrix[1][2]}, - {matrix[2][0], matrix[2][1], matrix[2][2]}, - {matrix[3][0], matrix[3][1], matrix[3][2]}, - } - ); - - return ( - matrix[0][0] * determinant1 - - matrix[0][1] * determinant2 - + matrix[0][2] * determinant3 - - matrix[0][3] * determinant4 - ); - } - - @NotNull - public Quaternion toQuaternion() { - return new Matrix3x3(matrix).toQuaternion(); - } - - public Vector3 toScale() { - double[] size = new double[3]; - for (int i = 0; i < 3; i++) { - double[] row = matrix[i]; - double mag = Math.sqrt(row[0] * row[0] + row[1] * row[1] + row[2] * row[2]); - size[i] = mag; - } - if (isNegative()) { - for (int i = 0; i < size.length; i++) { - size[i] = -size[i]; - } - } - return new Vector3(size); - } - - @NotNull - public Vector3 toTranslation() { - return new Vector3(matrix[0][3], matrix[1][3], matrix[2][3]); - } - - public boolean isNegative() { - return determinant() < 0; - } - - public Matrix4x4 inverted() { - Matrix4x4 invertedMatrix = new Matrix4x4(matrix); - double[][] matSrc = invertedMatrix.matrix; - final double pseudoinverseEpsilon = 1e-8f; - double det = determinant(); - if (det == 0) { - - matSrc[0][0] += pseudoinverseEpsilon; - matSrc[1][1] += pseudoinverseEpsilon; - matSrc[2][2] += pseudoinverseEpsilon; - matSrc[3][3] += pseudoinverseEpsilon; - det = invertedMatrix.determinant(); - if (det == 0) { - invertedMatrix = Matrix4x4.identity(); - det = 1; - } - } - - Matrix4x4 adjointMatrix = invertedMatrix.adjoint(); - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - matSrc[j][i] = adjointMatrix.matrix[j][i] / det; - } - } - return invertedMatrix; - } - - public double[] toArray() { - double[] output = new double[16]; - System.arraycopy(matrix[0], 0, output, 0, 4); - System.arraycopy(matrix[1], 0, output, 4, 4); - System.arraycopy(matrix[2], 0, output, 8, 4); - System.arraycopy(matrix[3], 0, output, 12, 4); - return output; - } -} diff --git a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Quaternion.java b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Quaternion.java deleted file mode 100644 index 07de508ee..000000000 --- a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Quaternion.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.shade.decima.ui.data.viewer.model.utils; - -import com.shade.util.NotNull; - -public record Quaternion(double x, double y, double z, double w) { - public Quaternion(@NotNull double[] xyzw) { - this(xyzw[0], xyzw[1], xyzw[2], xyzw[3]); - } - - @NotNull - public Quaternion add(@NotNull Quaternion other) { - return new Quaternion(x() + other.x(), y() + other.y(), z() + other.y(), w() + other.w()); - } - - public double magnitude() { - return Math.sqrt(x() * x() + y() * y() + z() * z() + w() * w()); - } - - @NotNull - public Quaternion normalized() { - final double norm = magnitude(); - return new Quaternion(x() / norm, y() / norm, z() / norm, w() / norm); - } - - @NotNull - public double[] toArray() { - return new double[]{x, y, z, w}; - } -} diff --git a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Transform.java b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Transform.java deleted file mode 100644 index adfe9bd97..000000000 --- a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Transform.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.shade.decima.ui.data.viewer.model.utils; - -import com.shade.util.NotNull; - -public record Transform(@NotNull Vector3 translation, @NotNull Quaternion rotation, @NotNull Vector3 scale) { -} diff --git a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Vector3.java b/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Vector3.java deleted file mode 100644 index aca95136f..000000000 --- a/modules/decima-ext-model-exporter/src/main/java/com/shade/decima/ui/data/viewer/model/utils/Vector3.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.shade.decima.ui.data.viewer.model.utils; - -import com.shade.util.NotNull; - -public record Vector3(double x, double y, double z) { - public Vector3(@NotNull double[] xyz) { - this(xyz[0], xyz[1], xyz[2]); - } - - @NotNull - public double[] toArray() { - return new double[]{x(), y(), z()}; - } -}