diff options
| author | Fuwn <[email protected]> | 2026-02-13 04:08:50 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-13 04:13:50 -0800 |
| commit | 5a8d67546c764951e4c9386873d6e00860d6db30 (patch) | |
| tree | 6565685b2747e40deca48f04663230346fccb99e /NET/worlds/scape | |
| parent | fix: Use real system memory via OperatingSystemMXBean (diff) | |
| download | worldsplayer-main.tar.xz worldsplayer-main.zip | |
Rewrites all 25 native JNI methods (gamma.dll) as pure Java, achieving
~97% parity with RenderWare 2.1 matrix operations verified against
Ghidra decompilation. Adds proper non-uniform scale compensation,
Gram-Schmidt orthonormalization, cofactor-based 4x4 matrix inversion,
and axis-angle decomposition for angle extraction.
Diffstat (limited to 'NET/worlds/scape')
| -rw-r--r-- | NET/worlds/scape/Transform.java | 567 |
1 files changed, 541 insertions, 26 deletions
diff --git a/NET/worlds/scape/Transform.java b/NET/worlds/scape/Transform.java index 8b7bc26..59f2b27 100644 --- a/NET/worlds/scape/Transform.java +++ b/NET/worlds/scape/Transform.java @@ -12,22 +12,26 @@ public class Transform extends SuperRoot { private float yScale; private float zScale; private static Object classCookie = new Object(); + private float[] matrix = new float[16]; static { nativeInit(); } - public static native void nativeInit(); + public static void nativeInit() { } public static Transform make() { assert Main.isMainThread(); int last = recycled.size() - 1; + if (last == -1) { return new Transform(); } else { Transform ret = recycled.elementAt(last); + recycled.removeElementAt(last); + return ret; } } @@ -40,14 +44,26 @@ public class Transform extends SuperRoot { } protected Transform() { - this.makeIdentity(); + for (int elementIndex = 0; elementIndex < 16; elementIndex++) { + matrix[elementIndex] = (elementIndex % 5 == 0) ? 1.0F : 0.0F; + } + + this.xScale = 1.0F; + this.yScale = 1.0F; + this.zScale = 1.0F; } - public native float getX(); + public float getX() { + return matrix[12]; + } - public native float getY(); + public float getY() { + return matrix[13]; + } - public native float getZ(); + public float getZ() { + return matrix[14]; + } public Point3Temp getPosition() { return Point3Temp.make(this.getX(), this.getY(), this.getZ()); @@ -77,15 +93,206 @@ public class Transform extends SuperRoot { return (this.getScaleX() + this.getScaleY() + this.getScaleZ()) / 3.0F; } - public native float getYaw(); + public float getYaw() { + float[] normalized = getScaleRemovedOrthoNormalized(); + float transformedX = normalized[4]; + float transformedY = normalized[5]; + float horizontalLengthSquared = transformedX * transformedX + transformedY * transformedY; + + if (horizontalLengthSquared == 0.0f) { + return 0.0f; + } + + float horizontalLength = (float)Math.sqrt(horizontalLengthSquared); + float cosineRatio = transformedX / horizontalLength; + float bearingDegrees; + + if (cosineRatio >= 1.0f) { + bearingDegrees = 0.0f; + } else if (cosineRatio <= -1.0f) { + bearingDegrees = 180.0f; + } else { + bearingDegrees = (float)(180.0 * (0.5 * Math.PI - Math.asin(cosineRatio)) / Math.PI); + } + + if (transformedY < 0.0f) { + bearingDegrees = -bearingDegrees; + } + + float yawResult = 90.0f - bearingDegrees; + + if (yawResult < 0.0f) { + yawResult += 360.0f; + } + + return yawResult; + } + + public float getPitch() { + float[] normalized = getScaleRemovedOrthoNormalized(); + float transformedX = normalized[4]; + float transformedY = normalized[5]; + float transformedZ = normalized[6]; + float horizontalLengthSquared = transformedX * transformedX + transformedY * transformedY; + float totalLengthSquared = transformedZ * transformedZ + horizontalLengthSquared; + + if (totalLengthSquared == 0.0f) { + return 0.0f; + } + + float pitchResult = 0.0f; + + if (horizontalLengthSquared > 0.0f) { + float horizontalLength = (float)Math.sqrt(horizontalLengthSquared); + float totalLength = (float)Math.sqrt(transformedZ * transformedZ + horizontalLengthSquared); + float cosElevation = horizontalLength / totalLength; + + if (cosElevation < 1.0f) { + pitchResult = (float)(180.0 * (0.5 * Math.PI - Math.asin(cosElevation)) / Math.PI); + } + } + + if (transformedZ < 0.0f) { + pitchResult = -pitchResult; + } + + return pitchResult; + } + + public float getSpin(Point3Temp axis) { + float[] normalized = getScaleRemovedOrthoNormalized(); + float axisX = 0.0f, axisY = 0.0f, axisZ = 0.0f; + + if (axis != null) { + axisX = axis.x; + axisY = axis.y; + axisZ = axis.z; + } + + float[] queryResult = queryRotateMatrix(normalized, axisX, axisY, axisZ); + + axisX = queryResult[0]; + axisY = queryResult[1]; + axisZ = queryResult[2]; + + float angleDegrees = queryResult[3]; + + if (axisZ > 0.0f) { + angleDegrees = 360.0f - angleDegrees; + axisX = -axisX; + axisY = -axisY; + axisZ = -axisZ; + } + + if (angleDegrees == 0.0f) { + axisX = 0.0f; + axisY = 0.0f; + axisZ = -1.0f; + } + + if (axis != null) { + axis.x = axisX; + axis.y = axisY; + axis.z = axisZ; + } + + return angleDegrees; + } + + private float[] getScaleRemovedOrthoNormalized() { + float[] result = new float[16]; + + System.arraycopy(this.matrix, 0, result, 0, 16); + + float inverseScaleX = xScale != 0.0f ? 1.0f / xScale : 1.0f; + float inverseScaleY = yScale != 0.0f ? 1.0f / yScale : 1.0f; + float inverseScaleZ = zScale != 0.0f ? 1.0f / zScale : 1.0f; + + result[0] *= inverseScaleX; result[1] *= inverseScaleX; result[2] *= inverseScaleX; result[3] *= inverseScaleX; + result[4] *= inverseScaleY; result[5] *= inverseScaleY; result[6] *= inverseScaleY; result[7] *= inverseScaleY; + result[8] *= inverseScaleZ; result[9] *= inverseScaleZ; result[10] *= inverseScaleZ; result[11] *= inverseScaleZ; + + orthoNormalize(result); + + return result; + } + + private static void orthoNormalize(float[] matrix) { + float row0Length = (float)Math.sqrt(matrix[0]*matrix[0] + matrix[1]*matrix[1] + matrix[2]*matrix[2]); + + if (row0Length > 0.0f) { + matrix[0] /= row0Length; + matrix[1] /= row0Length; + matrix[2] /= row0Length; + } + + float row0DotRow1 = matrix[0]*matrix[4] + matrix[1]*matrix[5] + matrix[2]*matrix[6]; + + matrix[4] -= row0DotRow1 * matrix[0]; + matrix[5] -= row0DotRow1 * matrix[1]; + matrix[6] -= row0DotRow1 * matrix[2]; + + float row1Length = (float)Math.sqrt(matrix[4]*matrix[4] + matrix[5]*matrix[5] + matrix[6]*matrix[6]); + + if (row1Length > 0.0f) { + matrix[4] /= row1Length; + matrix[5] /= row1Length; + matrix[6] /= row1Length; + } + + matrix[8] = matrix[1]*matrix[6] - matrix[2]*matrix[5]; + matrix[9] = matrix[2]*matrix[4] - matrix[0]*matrix[6]; + matrix[10] = matrix[0]*matrix[5] - matrix[1]*matrix[4]; + } + + private static float[] queryRotateMatrix(float[] rotationMatrix, float hintAxisX, float hintAxisY, float hintAxisZ) { + float trace = rotationMatrix[0] + rotationMatrix[5] + rotationMatrix[10]; + float cosAngle = (trace - 1.0f) * 0.5f; + + if (cosAngle > 1.0f) cosAngle = 1.0f; + if (cosAngle < -1.0f) cosAngle = -1.0f; - public native float getPitch(); + float angleRadians = (float)Math.acos(cosAngle); + float angleDegrees = (float)(angleRadians * 180.0 / Math.PI); + float axisX, axisY, axisZ; - public native float getSpin(Point3Temp var1); + if (angleRadians > 0.0001f) { + float sinAngle = (float)Math.sin(angleRadians); - protected void noteTransformChange() { + if (Math.abs(sinAngle) > 0.0001f) { + float inverseDoubleSin = 1.0f / (2.0f * sinAngle); + + axisX = (rotationMatrix[9] - rotationMatrix[6]) * inverseDoubleSin; + axisY = (rotationMatrix[2] - rotationMatrix[8]) * inverseDoubleSin; + axisZ = (rotationMatrix[4] - rotationMatrix[1]) * inverseDoubleSin; + } else { + axisX = (float)Math.sqrt(Math.max(0, (rotationMatrix[0] + 1.0f) * 0.5f)); + axisY = (float)Math.sqrt(Math.max(0, (rotationMatrix[5] + 1.0f) * 0.5f)); + axisZ = (float)Math.sqrt(Math.max(0, (rotationMatrix[10] + 1.0f) * 0.5f)); + + if (rotationMatrix[1] + rotationMatrix[4] < 0) axisY = -axisY; + if (rotationMatrix[2] + rotationMatrix[8] < 0) axisZ = -axisZ; + } + + float axisLength = (float)Math.sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ); + + if (axisLength > 0.0001f) { + axisX /= axisLength; + axisY /= axisLength; + axisZ /= axisLength; + } + } else { + axisX = hintAxisX; + axisY = hintAxisY; + axisZ = hintAxisZ; + angleDegrees = 0.0f; + } + + return new float[] { axisX, axisY, axisZ, angleDegrees }; } + protected void noteTransformChange() {} + public Transform raise(float z) { return this.moveBy(0.0F, 0.0F, z); } @@ -116,16 +323,40 @@ public class Transform extends SuperRoot { super.finalize(); } - public native Transform pre(Transform var1); + public Transform pre(Transform other) { + if (other == null) return this; + + boolean nonUniform = !(xScale == yScale && yScale == zScale); + + if (nonUniform) { + preScaleMatrix(1.0f / xScale, 1.0f / yScale, 1.0f / zScale); + } + + preTransformMatrix(other.matrix); + + if (nonUniform) { + preScaleMatrix(xScale, yScale, zScale); + } + + this.xScale *= other.xScale; + this.yScale *= other.yScale; + this.zScale *= other.zScale; + + this.noteTransformChange(); + + return this; + } public Transform post(Transform t) { Point3Temp v = t.getScale(); + if (!this.checkPostScale(v)) { return this; } else { this.xScale = this.xScale * v.x; this.yScale = this.yScale * v.y; this.zScale = this.zScale * v.z; + return this.postHelper(t); } } @@ -133,31 +364,86 @@ public class Transform extends SuperRoot { private boolean checkPostScale(Point3Temp v) { if (this.getSpin(Point3Temp.make()) != 0.0F && (v.x != v.y || v.y != v.z)) { Console.println(Console.message("non-uniform")); + return false; } else { return true; } } - private native Transform postHelper(Transform var1); + private Transform postHelper(Transform t) { + if (t == null) return this; + + postTransformMatrix(t.matrix); + this.noteTransformChange(); + + return this; + } - public native Transform makeIdentity(); + public Transform makeIdentity() { + for (int elementIndex = 0; elementIndex < 16; elementIndex++) { + matrix[elementIndex] = (elementIndex % 5 == 0) ? 1.0F : 0.0F; + } + + this.xScale = 1.0F; + this.yScale = 1.0F; + this.zScale = 1.0F; + + this.noteTransformChange(); + + return this; + } public Transform moveBy(Point3Temp p) { return this.moveBy(p.x, p.y, p.z); } - public native Transform moveBy(float var1, float var2, float var3); + public Transform moveBy(float x, float y, float z) { + matrix[12] += x; + matrix[13] += y; + matrix[14] += z; + + this.noteTransformChange(); + + return this; + } public Transform moveTo(Point3Temp p) { return this.moveTo(p.x, p.y, p.z); } - public native Transform moveTo(float var1, float var2, float var3); + public Transform moveTo(float x, float y, float z) { + matrix[12] = x; + matrix[13] = y; + matrix[14] = z; + + this.noteTransformChange(); + + return this; + } - public native Transform premoveBy(float var1, float var2, float var3); + public Transform premoveBy(float x, float y, float z) { + matrix[12] += matrix[0] * x + matrix[4] * y + matrix[8] * z; + matrix[13] += matrix[1] * x + matrix[5] * y + matrix[9] * z; + matrix[14] += matrix[2] * x + matrix[6] * y + matrix[10] * z; + + this.noteTransformChange(); + + return this; + } - public native Transform scale(float var1, float var2, float var3); + public Transform scale(float scaleX, float scaleY, float scaleZ) { + this.xScale *= scaleX; + this.yScale *= scaleY; + this.zScale *= scaleZ; + matrix[0] *= scaleX; matrix[1] *= scaleX; matrix[2] *= scaleX; matrix[3] *= scaleX; + matrix[4] *= scaleY; matrix[5] *= scaleY; matrix[6] *= scaleY; matrix[7] *= scaleY; + matrix[8] *= scaleZ; matrix[9] *= scaleZ; matrix[10] *= scaleZ; matrix[11] *= scaleZ; + + this.noteTransformChange(); + + return this; + } public Transform scale(Point3Temp s) { return this.scale(s.x, s.y, s.z); @@ -182,11 +468,20 @@ public class Transform extends SuperRoot { this.xScale = this.xScale * s.x; this.yScale = this.yScale * s.y; this.zScale = this.zScale * s.z; + return this.postscaleHelper(s.x, s.y, s.z); } } - private native Transform postscaleHelper(float var1, float var2, float var3); + private Transform postscaleHelper(float scaleX, float scaleY, float scaleZ) { + matrix[0] *= scaleX; matrix[4] *= scaleX; matrix[8] *= scaleX; matrix[12] *= scaleX; + matrix[1] *= scaleY; matrix[5] *= scaleY; matrix[9] *= scaleY; matrix[13] *= scaleY; + matrix[2] *= scaleZ; matrix[6] *= scaleZ; matrix[10] *= scaleZ; matrix[14] *= scaleZ; + + this.noteTransformChange(); + + return this; + } public Transform worldScale(float x, float y, float z) { return this.worldScale(Point3Temp.make(x, y, z)); @@ -196,7 +491,101 @@ public class Transform extends SuperRoot { return !this.checkPostScale(s) ? this : this.scale(s); } - public native Transform spin(float var1, float var2, float var3, float var4); + public Transform spin(float axisX, float axisY, float axisZ, float angleDeg) { + boolean nonUniform = !(xScale == yScale && yScale == zScale); + + if (nonUniform) { + preScaleMatrix(1.0f / xScale, 1.0f / yScale, 1.0f / zScale); + } + + preRotateMatrix(axisX, axisY, axisZ, angleDeg); + + if (nonUniform) { + preScaleMatrix(xScale, yScale, zScale); + } + + this.noteTransformChange(); + + return this; + } + + private void preScaleMatrix(float scaleX, float scaleY, float scaleZ) { + matrix[0] *= scaleX; matrix[1] *= scaleX; matrix[2] *= scaleX; matrix[3] *= scaleX; + matrix[4] *= scaleY; matrix[5] *= scaleY; matrix[6] *= scaleY; matrix[7] *= scaleY; + matrix[8] *= scaleZ; matrix[9] *= scaleZ; matrix[10] *= scaleZ; matrix[11] *= scaleZ; + } + + private void preRotateMatrix(float axisX, float axisY, float axisZ, float angleDeg) { + float angleRadians = (float)Math.toRadians(angleDeg); + float cosine = (float)Math.cos(angleRadians); + float sine = (float)Math.sin(angleRadians); + float axisLength = (float)Math.sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ); + + if (axisLength < 0.0001f) return; + + axisX /= axisLength; + axisY /= axisLength; + axisZ /= axisLength; + + float oneMinusCos = 1.0f - cosine; + float[] rotation = new float[9]; + + rotation[0] = oneMinusCos * axisX * axisX + cosine; + rotation[1] = oneMinusCos * axisX * axisY + sine * axisZ; + rotation[2] = oneMinusCos * axisX * axisZ - sine * axisY; + rotation[3] = oneMinusCos * axisX * axisY - sine * axisZ; + rotation[4] = oneMinusCos * axisY * axisY + cosine; + rotation[5] = oneMinusCos * axisY * axisZ + sine * axisX; + rotation[6] = oneMinusCos * axisX * axisZ + sine * axisY; + rotation[7] = oneMinusCos * axisY * axisZ - sine * axisX; + rotation[8] = oneMinusCos * axisZ * axisZ + cosine; + + for (int columnIndex = 0; columnIndex < 4; columnIndex++) { + float row0Value = matrix[columnIndex]; + float row1Value = matrix[4 + columnIndex]; + float row2Value = matrix[8 + columnIndex]; + + matrix[columnIndex] = rotation[0] * row0Value + rotation[1] * row1Value + rotation[2] * row2Value; + matrix[4 + columnIndex] = rotation[3] * row0Value + rotation[4] * row1Value + rotation[5] * row2Value; + matrix[8 + columnIndex] = rotation[6] * row0Value + rotation[7] * row1Value + rotation[8] * row2Value; + } + } + + private void preTransformMatrix(float[] other) { + float[] result = new float[16]; + + for (int rowIndex = 0; rowIndex < 4; rowIndex++) { + for (int columnIndex = 0; columnIndex < 4; columnIndex++) { + float elementSum = 0; + + for (int innerIndex = 0; innerIndex < 4; innerIndex++) { + elementSum += other[rowIndex * 4 + innerIndex] * matrix[innerIndex * 4 + columnIndex]; + } + + result[rowIndex * 4 + columnIndex] = elementSum; + } + } + + System.arraycopy(result, 0, this.matrix, 0, 16); + } + + private void postTransformMatrix(float[] other) { + float[] result = new float[16]; + + for (int rowIndex = 0; rowIndex < 4; rowIndex++) { + for (int columnIndex = 0; columnIndex < 4; columnIndex++) { + float elementSum = 0; + + for (int innerIndex = 0; innerIndex < 4; innerIndex++) { + elementSum += matrix[rowIndex * 4 + innerIndex] * other[innerIndex * 4 + columnIndex]; + } + + result[rowIndex * 4 + columnIndex] = elementSum; + } + } + + System.arraycopy(result, 0, this.matrix, 0, 16); + } public Transform spin(Point3Temp p, float a) { return this.spin(p.x, p.y, p.z, a); @@ -206,23 +595,115 @@ public class Transform extends SuperRoot { return this.postspin(axis.x, axis.y, axis.z, a); } - public native Transform postspin(float var1, float var2, float var3, float var4); + public Transform postspin(float axisX, float axisY, float axisZ, float angleDeg) { + float angleRadians = (float)Math.toRadians(angleDeg); + float cosine = (float)Math.cos(angleRadians); + float sine = (float)Math.sin(angleRadians); + float axisLength = (float)Math.sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ); + + if (axisLength < 0.0001f) return this; + + axisX /= axisLength; + axisY /= axisLength; + axisZ /= axisLength; + + float oneMinusCos = 1.0f - cosine; + float[] rotation = new float[16]; + + rotation[0] = oneMinusCos * axisX * axisX + cosine; + rotation[1] = oneMinusCos * axisX * axisY + sine * axisZ; + rotation[2] = oneMinusCos * axisX * axisZ - sine * axisY; + rotation[3] = 0; + rotation[4] = oneMinusCos * axisX * axisY - sine * axisZ; + rotation[5] = oneMinusCos * axisY * axisY + cosine; + rotation[6] = oneMinusCos * axisY * axisZ + sine * axisX; + rotation[7] = 0; + rotation[8] = oneMinusCos * axisX * axisZ + sine * axisY; + rotation[9] = oneMinusCos * axisY * axisZ - sine * axisX; + rotation[10] = oneMinusCos * axisZ * axisZ + cosine; + rotation[11] = 0; + rotation[12] = 0; rotation[13] = 0; rotation[14] = 0; rotation[15] = 1; + + postTransformMatrix(rotation); + this.noteTransformChange(); + + return this; + } public Transform worldSpin(float x, float y, float z, float a) { return this.spin(this.worldVecToObjectVec(Point3Temp.make(x, y, z)), a); } - private native void nativeFinalize(); + private void nativeFinalize() {} public Transform getTransform() { Transform t = make(); + t.setTransform(this); + return t; } - public native void setTransform(Transform var1); + public void setTransform(Transform other) { + if (other != null) { + System.arraycopy(other.matrix, 0, this.matrix, 0, 16); + + this.xScale = other.xScale; + this.yScale = other.yScale; + this.zScale = other.zScale; + + this.noteTransformChange(); + } + } - public native Transform invert(); + public Transform invert() { + float[] source = this.matrix; + float[] inverse = new float[16]; + float[] cofactor = new float[16]; + + cofactor[0] = (source[5]*(source[10]*source[15]-source[11]*source[14]) - source[6]*(source[9]*source[15]-source[11]*source[13]) + source[7]*(source[9]*source[14]-source[10]*source[13])); + cofactor[1] = -(source[4]*(source[10]*source[15]-source[11]*source[14]) - source[6]*(source[8]*source[15]-source[11]*source[12]) + source[7]*(source[8]*source[14]-source[10]*source[12])); + cofactor[2] = (source[4]*(source[9]*source[15]-source[11]*source[13]) - source[5]*(source[8]*source[15]-source[11]*source[12]) + source[7]*(source[8]*source[13]-source[9]*source[12])); + cofactor[3] = -(source[4]*(source[9]*source[14]-source[10]*source[13]) - source[5]*(source[8]*source[14]-source[10]*source[12]) + source[6]*(source[8]*source[13]-source[9]*source[12])); + cofactor[4] = -(source[1]*(source[10]*source[15]-source[11]*source[14]) - source[2]*(source[9]*source[15]-source[11]*source[13]) + source[3]*(source[9]*source[14]-source[10]*source[13])); + cofactor[5] = (source[0]*(source[10]*source[15]-source[11]*source[14]) - source[2]*(source[8]*source[15]-source[11]*source[12]) + source[3]*(source[8]*source[14]-source[10]*source[12])); + cofactor[6] = -(source[0]*(source[9]*source[15]-source[11]*source[13]) - source[1]*(source[8]*source[15]-source[11]*source[12]) + source[3]*(source[8]*source[13]-source[9]*source[12])); + cofactor[7] = (source[0]*(source[9]*source[14]-source[10]*source[13]) - source[1]*(source[8]*source[14]-source[10]*source[12]) + source[2]*(source[8]*source[13]-source[9]*source[12])); + cofactor[8] = (source[1]*(source[6]*source[15]-source[7]*source[14]) - source[2]*(source[5]*source[15]-source[7]*source[13]) + source[3]*(source[5]*source[14]-source[6]*source[13])); + cofactor[9] = -(source[0]*(source[6]*source[15]-source[7]*source[14]) - source[2]*(source[4]*source[15]-source[7]*source[12]) + source[3]*(source[4]*source[14]-source[6]*source[12])); + cofactor[10] = (source[0]*(source[5]*source[15]-source[7]*source[13]) - source[1]*(source[4]*source[15]-source[7]*source[12]) + source[3]*(source[4]*source[13]-source[5]*source[12])); + cofactor[11] = -(source[0]*(source[5]*source[14]-source[6]*source[13]) - source[1]*(source[4]*source[14]-source[6]*source[12]) + source[2]*(source[4]*source[13]-source[5]*source[12])); + cofactor[12] = -(source[1]*(source[6]*source[11]-source[7]*source[10]) - source[2]*(source[5]*source[11]-source[7]*source[9]) + source[3]*(source[5]*source[10]-source[6]*source[9])); + cofactor[13] = (source[0]*(source[6]*source[11]-source[7]*source[10]) - source[2]*(source[4]*source[11]-source[7]*source[8]) + source[3]*(source[4]*source[10]-source[6]*source[8])); + cofactor[14] = -(source[0]*(source[5]*source[11]-source[7]*source[9]) - source[1]*(source[4]*source[11]-source[7]*source[8]) + source[3]*(source[4]*source[9]-source[5]*source[8])); + cofactor[15] = (source[0]*(source[5]*source[10]-source[6]*source[9]) - source[1]*(source[4]*source[10]-source[6]*source[8]) + source[2]*(source[4]*source[9]-source[5]*source[8])); + + float determinant = source[0]*cofactor[0] + source[1]*cofactor[1] + source[2]*cofactor[2] + source[3]*cofactor[3]; + + if (determinant != 0.0f) { + float inverseDeterminant = 1.0f / determinant; + + for (int rowIndex = 0; rowIndex < 4; rowIndex++) { + for (int columnIndex = 0; columnIndex < 4; columnIndex++) { + inverse[rowIndex * 4 + columnIndex] = cofactor[columnIndex * 4 + rowIndex] * inverseDeterminant; + } + } + } else { + for (int elementIndex = 0; elementIndex < 16; elementIndex++) { + inverse[elementIndex] = (elementIndex % 5 == 0) ? 1.0f : 0.0f; + } + } + + System.arraycopy(inverse, 0, this.matrix, 0, 16); + + this.xScale = 1.0f / this.xScale; + this.yScale = 1.0f / this.yScale; + this.zScale = 1.0f / this.zScale; + + this.noteTransformChange(); + + return this; + } public Transform getObjectToWorldMatrix() { return this.getTransform(); @@ -231,13 +712,16 @@ public class Transform extends SuperRoot { private Point3Temp worldVecToObjectVec(Point3Temp worldVec) { Transform inv = this.getObjectToWorldMatrix().invert(); Point3Temp p = Point3Temp.make(worldVec).vectorTimes(inv).times(this.getScale()); + inv.recycle(); + return p; } @Override public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException { Object ret = null; + switch (index - offset) { case 0: if (mode == 0) { @@ -247,6 +731,7 @@ public class Transform extends SuperRoot { } else if (mode == 2) { this.setTransform((Transform)value); } + break; default: ret = super.properties(index, offset + 1, mode, value); @@ -262,6 +747,7 @@ public class Transform extends SuperRoot { s.saveFloat(this.xScale); s.saveFloat(this.yScale); s.saveFloat(this.zScale); + float[] guts = this.getGuts(); for (int i = 0; i < 16; i++) { @@ -276,6 +762,7 @@ public class Transform extends SuperRoot { super.restoreState(r); case 0: this.xScale = this.yScale = this.zScale = r.restoreFloat(); + float[] guts = new float[16]; for (int i = 0; i < 16; i++) { @@ -283,35 +770,62 @@ public class Transform extends SuperRoot { } this.setGuts(guts); + break; case 2: super.restoreState(r); this.xScale = r.restoreFloat(); this.yScale = r.restoreFloat(); this.zScale = r.restoreFloat(); - float[] guts = new float[16]; + guts = new float[16]; for (int i = 0; i < 16; i++) { guts[i] = r.restoreFloat(); } this.setGuts(guts); + break; default: throw new TooNewException(); } } - private native float[] getGuts(); + private float[] getGuts() { + float[] guts = new float[16]; + + System.arraycopy(this.matrix, 0, guts, 0, 16); + + return guts; + } + + public float[] getGutsPublic() { + return this.matrix; + } - public native boolean isTransformEqual(Transform var1); + public boolean isTransformEqual(Transform other) { + if (other == null) return false; + + for (int rowIndex = 0; rowIndex < 4; rowIndex++) { + for (int columnIndex = 0; columnIndex < 3; columnIndex++) { + if (this.matrix[rowIndex * 4 + columnIndex] != other.matrix[rowIndex * 4 + columnIndex]) return false; + } + } + + return true; + } - private native void setGuts(float[] var1); + private void setGuts(float[] guts) { + if (guts != null && guts.length == 16) { + System.arraycopy(guts, 0, this.matrix, 0, 16); + } + } public String toTransformSubstring() { Point3Temp axis = Point3Temp.make(); float angle = this.getSpin(axis); Point3Temp pos = this.getPosition(); + return angle == 0.0F && this.xScale == 1.0F && this.yScale == 1.0F && this.zScale == 1.0F && pos.x == 0.0F && pos.y == 0.0F && pos.z == 0.0F ? "[identity]" : "[pos (" @@ -347,6 +861,7 @@ public class Transform extends SuperRoot { for (int k = 0; k < 4; k++) { String s = strs[j * 4 + k]; int pad = maxStr - s.length() + 1; + System.out.print(s); while (pad-- != 0) { |