diff --git a/Changelog.txt b/Changelog.txt index cd6d2b2..2c6c4ad 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,7 @@ +1.3.8 (2020/07/17) +- Fixed the Mat3f.createRotationMatrix() method to correctly handle the singularity on the positive Y-axis (thanks, meaten!) +- Also added a (commented out) Pixar version which works, but generates slightly different orthogonal 3x3 matrices (see method for details) + 1.3.7 (2020/04/02) - Updated documentation to discuss potential Mac demo crash & potential mitigation steps - Updated documentation display of project file structure diff --git a/README.md b/README.md index 6c347ec..edb7b49 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,11 @@ To use the library in your own Maven project, declare the following dependencies au.edu.federation.caliko caliko +<<<<<<< HEAD + 1.3.8 +======= 1.3.6 +>>>>>>> 863cb069101035f61613b7983f504991d9a0d876 ``` @@ -51,7 +55,11 @@ To use the library in your own Maven project, declare the following dependencies au.edu.federation.caliko.visualisation caliko-visualisation +<<<<<<< HEAD + 1.3.8 +======= 1.3.6 +>>>>>>> 863cb069101035f61613b7983f504991d9a0d876 ``` diff --git a/caliko-demo/pom.xml b/caliko-demo/pom.xml index 4399dc7..ce85f0c 100644 --- a/caliko-demo/pom.xml +++ b/caliko-demo/pom.xml @@ -13,7 +13,7 @@ au.edu.federation.caliko caliko-aggregate - 1.3.7 + 1.3.8 diff --git a/caliko-distribution/pom.xml b/caliko-distribution/pom.xml index 8953980..9674bfa 100644 --- a/caliko-distribution/pom.xml +++ b/caliko-distribution/pom.xml @@ -3,7 +3,7 @@ au.edu.federation.caliko caliko-aggregate - 1.3.7 + 1.3.8 caliko-distribution diff --git a/caliko-distribution/src/site/docs/caliko-user-guide.docx b/caliko-distribution/src/site/docs/caliko-user-guide.docx index 38632cc..da7ed20 100755 Binary files a/caliko-distribution/src/site/docs/caliko-user-guide.docx and b/caliko-distribution/src/site/docs/caliko-user-guide.docx differ diff --git a/caliko-distribution/src/site/docs/caliko-user-guide.pdf b/caliko-distribution/src/site/docs/caliko-user-guide.pdf index b87c107..c4aa738 100755 Binary files a/caliko-distribution/src/site/docs/caliko-user-guide.pdf and b/caliko-distribution/src/site/docs/caliko-user-guide.pdf differ diff --git a/caliko-visualisation/pom.xml b/caliko-visualisation/pom.xml index 0f8d9cd..a5deff5 100644 --- a/caliko-visualisation/pom.xml +++ b/caliko-visualisation/pom.xml @@ -13,7 +13,7 @@ au.edu.federation.caliko caliko-aggregate - 1.3.7 + 1.3.8 diff --git a/caliko/pom.xml b/caliko/pom.xml index b2949a9..fb64cb8 100644 --- a/caliko/pom.xml +++ b/caliko/pom.xml @@ -10,7 +10,7 @@ au.edu.federation.caliko caliko-aggregate - 1.3.7 + 1.3.8 diff --git a/caliko/src/main/java/au/edu/federation/utils/Mat3f.java b/caliko/src/main/java/au/edu/federation/utils/Mat3f.java index f2e8ee7..04b5208 100644 --- a/caliko/src/main/java/au/edu/federation/utils/Mat3f.java +++ b/caliko/src/main/java/au/edu/federation/utils/Mat3f.java @@ -119,7 +119,7 @@ public void setIdentity() * Create a rotation matrix from a given direction. *

* The reference direction is aligned to the Z-Axis, and the X-Axis is generated via the - * genPerpendicularVectorQuuck() method. The Y-Axis is then the cross-product of those two axes. + * genPerpendicularVectorQuick() method. The Y-Axis is then the cross-product of those two axes. *

* This method uses the Frisvad technique for generating perpendicular axes. * @@ -136,8 +136,71 @@ public void setIdentity() return new Mat3f(xAxis, yAxis, zAxis); }*/ + /** + * Create a rotation matrix from a given direction. + *

+ * The reference direction is aligned to the Z-Axis. Note: The singularity is on the positive Y-Axis. + *

+ * This method uses the Frisvad technique for generating perpendicular axes. + * + * @param referenceDirection The vector to use as the Z-Axis + * @return The created rotation matrix. + * + * @see Vec3f#genPerpendicularVectorQuick(Vec3f) + */ public static Mat3f createRotationMatrix(Vec3f referenceDirection) { + /*** You may want to try this - but the generated rotation matrix will be a little different (see below): + Note: There is no difference in solve distance between these, performance varies slightly - see test details on build (i.e. "mvn package") + + --- Rotation matrix creation (Meaten fix) --- --- Rotation matrix creation (Pixar) --- + + Rotation matrix generated from plusX: + X Axis: 0.000, 0.000, 1.000 X Axis: 0.000, -0.000, -1.000 + Y Axis: 0.000, 1.000, 0.000 Y Axis: -0.000, 1.000, -0.000 + Z Axis: 1.000, 0.000, 0.000 Z Axis: 1.000, 0.000, 0.000 + + Rotation matrix generated from plusY: + X Axis: 1.000, 0.000, 0.000 X Axis: 1.000, -0.000, -0.000 + Y Axis: 0.000, 0.000, 1.000 Y Axis: -0.000, 0.000, -1.000 + Z Axis: 0.000, 1.000, 0.000 Z Axis: 0.000, 1.000, 0.000 + + Rotation matrix generated from plusZ: + X Axis: -1.000, 0.000, 0.000 X Axis: 1.000, -0.000, -0.000 + Y Axis: 0.000, 1.000, -0.000 Y Axis: -0.000, 1.000, -0.000 + Z Axis: 0.000, 0.000, 1.000 Z Axis: 0.000, 0.000, 1.000 + + Rotation matrix generated from minusX: + X Axis: 0.000, 0.000, -1.000 X Axis: 0.000, 0.000, 1.000 + Y Axis: 0.000, 1.000, 0.000 Y Axis: 0.000, 1.000, -0.000 + Z Axis: -1.000, 0.000, 0.000 Z Axis: -1.000, 0.000, 0.000 + + Rotation matrix generated from minusY: + X Axis: 1.000, 0.000, 0.000 1.000, 0.000, -0.000 + Y Axis: 0.000, 0.000, -1.000 Y Axis: 0.000, 0.000, 1.000 + Z Axis: 0.000, -1.000, 0.000 Z Axis: 0.000, -1.000, 0.000 + + Rotation matrix generated from minusZ: + X Axis: 1.000, -0.000, 0.000 X Axis: 1.000, -0.000, 0.000 + Y Axis: 0.000, 1.000, 0.000 Y Axis: 0.000, -1.000, -0.000 + Z Axis: 0.000, 0.000, -1.000 Z Axis: 0.000, 0.000, -1.000 + + // Create an orthonormal basis using Pixar's method. + // Source: https://graphics.pixar.com/library/OrthonormalB/paper.pdf + + float sign = Math.copySign(1.0f, referenceDirection.z); + float a = -1.0f / (sign + referenceDirection.z); + float b = referenceDirection.x * referenceDirection.y * a; + Vec3f xAxis = new Vec3f(1.0f + sign * referenceDirection.x * referenceDirection.x * a, sign * b, -sign * referenceDirection.x); + Vec3f yAxis = new Vec3f(b, sign + referenceDirection.y * referenceDirection.y * a, -referenceDirection.y); + + Mat3f rotMat = new Mat3f(); + rotMat.setZBasis( referenceDirection ); + rotMat.setXBasis( xAxis.normalised() ); + rotMat.setYBasis( yAxis.normalised() ); + return rotMat; + ***/ + /*** OLD VERSION 1.3.4 and earlier Vec3f xAxis; Vec3f yAxis; @@ -160,27 +223,28 @@ public static Mat3f createRotationMatrix(Vec3f referenceDirection) return new Mat3f(xAxis, yAxis, zAxis); ***/ - /*** NEW VERSION - 1.3.5 onwards ***/ + /*** NEW VERSION - 1.3.8 onwards ***/ + Mat3f rotMat = new Mat3f(); - - // Bone direction is bang on the Y-axis singularity? Give it a tiny nudge because you can't cross product two identical vectors. - if (referenceDirection.y == 1.0f) { - referenceDirection.y -= 0.0001f; - referenceDirection.normalise(); + + // Singularity fix provided by meaten - see: https://github.com/FedUni/caliko/issues/19 + if (Math.abs(referenceDirection.y) > 0.9999f) + { + rotMat.setZBasis(referenceDirection); + rotMat.setXBasis( new Vec3f(1.0f, 0.0f, 0.0f)); + rotMat.setYBasis( Vec3f.crossProduct( rotMat.getXBasis(), rotMat.getZBasis()).normalised()); + } + else + { + rotMat.setZBasis( referenceDirection ); + rotMat.setXBasis( Vec3f.crossProduct( referenceDirection, new Vec3f(0.0f, 1.0f, 0.0f) ).normalised() ); + rotMat.setYBasis( Vec3f.crossProduct( rotMat.getXBasis(), rotMat.getZBasis() ).normalised() ); } - - rotMat.setZBasis( referenceDirection ); - rotMat.setXBasis( Vec3f.crossProduct( referenceDirection, new Vec3f(0.0f, 1.0f, 0.0f) ).normalised() ); - rotMat.setYBasis( Vec3f.crossProduct( rotMat.getXBasis(), rotMat.getZBasis() ).normalised() ); return rotMat; + } - -// THIS IS WAAAAAY BETTER THAN THE COMMENTED OUT ABOVE - BUT I THINK REFERENCE ANGLES **MUST** BE HONOURED IN THE -// FORWARD PASS OR WE END UP WITH JUMPY BULLSHIT RESULTS (SEE LOCAL HINGE WITH REFERENCE CONSTRAINTS) -// -// PERHAPS genPerpendicularVectorQuick SHOULD USE THE SAME TECHNIQUE TO KEEP EVERYTHING IN ORDER?? - + /** * Return whether this matrix consists of three orthogonal axes or not to within a cross-product of 0.01f. * diff --git a/caliko/src/test/java/au/edu/federation/caliko/ApplicationPerfTest.java b/caliko/src/test/java/au/edu/federation/caliko/ApplicationPerfTest.java index e6bbd47..19b7ac3 100644 --- a/caliko/src/test/java/au/edu/federation/caliko/ApplicationPerfTest.java +++ b/caliko/src/test/java/au/edu/federation/caliko/ApplicationPerfTest.java @@ -14,6 +14,7 @@ import au.edu.federation.utils.SerializationUtil; import au.edu.federation.utils.Utils; import au.edu.federation.utils.Vec3f; +import au.edu.federation.utils.Mat3f; public class ApplicationPerfTest { @@ -35,10 +36,46 @@ public class ApplicationPerfTest @Test public void runTests() throws IOException, Exception { - System.out.println("---------- Caliko CPU Performance Analysis ----------"); + System.out.println("---------- Caliko Performance Analysis ----------"); writer = new PrintWriter(folder.newFile("caliko-performance-test.txt"), "UTF-8"); + System.out.println("\n--- Rotation matrix creation ---\n"); + writer.println("\n--- Rotation matrix creation ---\n"); + + Mat3f m; + + Vec3f plusX = new Vec3f(1.0f, 0.0f, 0.0f); + Vec3f plusY = new Vec3f(0.0f, 1.0f, 0.0f); + Vec3f plusZ = new Vec3f(0.0f, 0.0f, 1.0f); + + Vec3f minusX = new Vec3f(-1.0f, 0.0f, 0.0f); + Vec3f minusY = new Vec3f( 0.0f, -1.0f, 0.0f); + Vec3f minusZ = new Vec3f( 0.0f, 0.0f, -1.0f); + + m = Mat3f.createRotationMatrix(plusX); + System.out.println("Rotation matrix generated from plusX:\n" + m.toString() ); + writer.println("Rotation matrix generated from plusX:\n" + m.toString() ); + m = Mat3f.createRotationMatrix(plusY); + System.out.println("Rotation matrix generated from plusY:\n" + m.toString() ); + writer.println("Rotation matrix generated from plusY:\n" + m.toString() ); + m = Mat3f.createRotationMatrix(plusZ); + System.out.println("Rotation matrix generated from plusZ:\n" + m.toString() ); + writer.println("Rotation matrix generated from plusZ:\n" + m.toString() ); + + m = Mat3f.createRotationMatrix(minusX); + System.out.println("Rotation matrix generated from minusX:\n" + m.toString() ); + writer.println("Rotation matrix generated from minusX:\n" + m.toString() ); + m = Mat3f.createRotationMatrix(minusY); + System.out.println("Rotation matrix generated from minusY:\n" + m.toString() ); + writer.println("Rotation matrix generated from minusY:\n" + m.toString() ); + m = Mat3f.createRotationMatrix(minusZ); + System.out.println("Rotation matrix generated from minusZ:\n" + m.toString() ); + writer.println("Rotation matrix generated from minusZ:\n" + m.toString() ); + + System.out.println("\n -----------------\n"); + writer.println("\n -----------------\n"); + // Perform tests int numTests = 3; for (int loop = 1; loop <= numTests; ++loop) @@ -159,6 +196,8 @@ private void assertChain(FabrikChain3D chain, int testNumber) throws IOException private double solveChain(FabrikChain3D chain, int numIterations) { + float avgSolveDistance = 0.0f; + // Get half the length of the chain (to ensure target can be reached) float len = chain.getChainLength() / 2.0f; @@ -175,8 +214,8 @@ private double solveChain(FabrikChain3D chain, int numIterations) // Get start time startNanos = System.nanoTime(); - // Solve for target - chain.solveForTarget(target); + // Solve for target + avgSolveDistance += chain.solveForTarget(target); writer.println(chain.toString()); writer.flush(); @@ -192,6 +231,10 @@ private double solveChain(FabrikChain3D chain, int numIterations) long averageMicrosecondsPerIteration = combinedMicrosecondsForIteration / (long)numIterations; averageMilliseconds = (double)averageMicrosecondsPerIteration / 1000.0; + // Calculate average solve distance & display it + avgSolveDistance /= numIterations; + System.out.println("Average solve distance: " + avgSolveDistance); + return averageMilliseconds; } diff --git a/pom.xml b/pom.xml index b61463d..1524dd3 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ caliko-aggregate pom - 1.3.7 + 1.3.8 Caliko library Aggregate POM POM to build the Caliko library including the visualisation component, demo application, source and documentation archives. https://github.com/FedUni/caliko