package NET.worlds.scape; import NET.worlds.console.Console; import NET.worlds.console.Main; import java.io.IOException; import java.util.Vector; public class Transform extends SuperRoot { private static Vector recycled = new Vector(); private int transformID; private float xScale; private float yScale; private float zScale; private static Object classCookie = new Object(); private float[] matrix = new float[16]; static { 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; } } public void recycle() { if (recycled.size() < 100) { this.makeIdentity(); recycled.addElement(this); } } protected Transform() { 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 float getX() { return matrix[12]; } public float getY() { return matrix[13]; } public float getZ() { return matrix[14]; } public Point3Temp getPosition() { return Point3Temp.make(this.getX(), this.getY(), this.getZ()); } public void setZ(float z) { this.moveTo(this.getX(), this.getY(), z); } public float getScaleX() { return this.xScale; } public float getScaleY() { return this.yScale; } public float getScaleZ() { return this.zScale; } public Point3Temp getScale() { return Point3Temp.make(this.getScaleX(), this.getScaleY(), this.getScaleZ()); } public float getTotalScale() { return (this.getScaleX() + this.getScaleY() + this.getScaleZ()) / 3.0F; } 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; float angleRadians = (float)Math.acos(cosAngle); float angleDegrees = (float)(angleRadians * 180.0 / Math.PI); float axisX, axisY, axisZ; if (angleRadians > 0.0001f) { float sinAngle = (float)Math.sin(angleRadians); 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); } public Transform lower(float z) { return this.moveBy(0.0F, 0.0F, -z); } public Transform yaw(float a) { return this.spin(0.0F, 0.0F, 1.0F, a); } public Transform roll(float a) { return this.spin(0.0F, 1.0F, 0.0F, a); } public Transform pitch(float a) { return this.spin(1.0F, 0.0F, 0.0F, a); } public Transform scale(float s) { return this.scale(s, s, s); } @Override protected void finalize() { this.nativeFinalize(); super.finalize(); } 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); } } 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 Transform postHelper(Transform t) { if (t == null) return this; postTransformMatrix(t.matrix); this.noteTransformChange(); return this; } 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 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 Transform moveTo(float x, float y, float z) { matrix[12] = x; matrix[13] = y; matrix[14] = z; this.noteTransformChange(); return this; } 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 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); } public void setScale(float x, float y, float z) { this.scale(x / this.xScale, y / this.yScale, z / this.zScale); } public void setScale(Point3Temp s) { this.setScale(s.x, s.y, s.z); } public Transform postscale(float x, float y, float z) { return this.postscale(Point3Temp.make(x, y, z)); } public Transform postscale(Point3Temp s) { if (!this.checkPostScale(s)) { return this; } else { 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 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)); } public Transform worldScale(Point3Temp s) { return !this.checkPostScale(s) ? this : this.scale(s); } 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); } public Transform postspin(Point3Temp axis, float a) { return this.postspin(axis.x, axis.y, axis.z, a); } 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 void nativeFinalize() {} public Transform getTransform() { Transform t = make(); t.setTransform(this); return t; } 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 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(); } 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) { ret = TransformPropertyEditor.make(new Property(this, index, "Transform")); } else if (mode == 1) { ret = this.getTransform(); } else if (mode == 2) { this.setTransform((Transform)value); } break; default: ret = super.properties(index, offset + 1, mode, value); } return ret; } @Override public void saveState(Saver s) throws IOException { s.saveVersion(2, classCookie); super.saveState(s); s.saveFloat(this.xScale); s.saveFloat(this.yScale); s.saveFloat(this.zScale); float[] guts = this.getGuts(); for (int i = 0; i < 16; i++) { s.saveFloat(guts[i]); } } @Override public void restoreState(Restorer r) throws IOException, TooNewException { switch (r.restoreVersion(classCookie)) { case 1: 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++) { guts[i] = r.restoreFloat(); } this.setGuts(guts); break; case 2: super.restoreState(r); this.xScale = r.restoreFloat(); this.yScale = r.restoreFloat(); this.zScale = r.restoreFloat(); guts = new float[16]; for (int i = 0; i < 16; i++) { guts[i] = r.restoreFloat(); } this.setGuts(guts); break; default: throw new TooNewException(); } } 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 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 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 (" + pos + "), scale (" + (this.xScale == this.yScale && this.yScale == this.zScale ? "" + this.xScale : this.xScale + "," + this.yScale + "," + this.zScale) + "), rot (" + axis + "@" + angle + ")]"; } @Override public String toString() { return this.getName() + this.toTransformSubstring(); } public Transform printGuts() { float[] arr = this.getGuts(); assert arr.length == 16; String[] strs = new String[16]; int maxStr = 0; for (int i = 0; i < 16; i++) { strs[i] = Float.toString(arr[i]); maxStr = Math.max(maxStr, strs[i].length()); } for (int j = 0; j < 4; j++) { 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) { System.out.print(" "); } } System.out.println(""); } return this; } }