From aafaf924d597b4143a513a517e952f60afa49e5e Mon Sep 17 00:00:00 2001 From: ziadb Date: Thu, 26 Jul 2018 12:19:38 -0400 Subject: SkAR Java: refactored SkARMatrix.java (now CanvasMatrixUtil.java) Bug: skia: Change-Id: I57ff2f723b2445270246c96ee35e9669e2b21954 Reviewed-on: https://skia-review.googlesource.com/143503 Reviewed-by: Mike Reed --- .../java/com/google/skar/CanvasMatrixUtil.java | 176 +++++++++++++++++++++ .../src/main/java/com/google/skar/SkARMatrix.java | 171 -------------------- 2 files changed, 176 insertions(+), 171 deletions(-) create mode 100644 platform_tools/android/apps/skar_java/src/main/java/com/google/skar/CanvasMatrixUtil.java delete mode 100644 platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARMatrix.java diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/CanvasMatrixUtil.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/CanvasMatrixUtil.java new file mode 100644 index 0000000000..bfab93e375 --- /dev/null +++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/CanvasMatrixUtil.java @@ -0,0 +1,176 @@ +package com.google.skar; + +import android.graphics.Matrix; + +/** + * Provides static methods for matrix manipulation needed to draw in ARCore with Canvas. + * Input matrices are assumed to be 4x4 android.opengl.Matrix types (16-float arrays in column-major + * order). + * Output matrices are 3x3 android.graphics.Matrix types. + */ + +public class CanvasMatrixUtil { + + /******************* PUBLIC FUNCTIONS ***********************/ + + /** + * Returns an android.graphics.Matrix that can be used on a Canvas to draw a 2D object in + * perspective. Object will be rotated towards the XZ plane and will appear to stick on Planes. + * Undefined behavior when any of the matrices are not of size 16, or are null. + * + * @param model 4x4 model matrix of the object to be drawn (global/world) + * @param view 4x4 camera view matrix (brings objects to camera origin and + * orientation) + * @param projection 4x4 projection matrix + * @param viewPortWidth width of viewport of GLSurfaceView + * @param viewPortHeight height of viewport of GLSurfaceView + * @return 3x3 matrix that puts a 2D objects in perspective on a Canvas + */ + + public static Matrix createPerspectiveMatrix(float[] model, float[] view, float[] projection, + float viewPortWidth, float viewPortHeight) { + float[] viewPort = createViewportMatrix(viewPortWidth, viewPortHeight); + float[] planeStickRotation = createXYtoXZRotationMatrix(); + float[][] matrices = {planeStickRotation, model, view, projection, viewPort}; + return createMatrixFrom4x4Array(matrices); + } + + /** + * Returns a 16-float matrix in column-major order that represents a viewport matrix given + * the width and height of the viewport. + * + * @param width width of viewport + * @param height height of viewport + */ + + public static float[] createViewportMatrix(float width, float height) { + float[] viewPort = new float[16]; + android.opengl.Matrix.setIdentityM(viewPort, 0); + android.opengl.Matrix.translateM(viewPort, 0, width / 2, height / 2, 0); + android.opengl.Matrix.scaleM(viewPort, 0, width / 2, -height / 2, 0); + return viewPort; + } + + /** + * Returns a 16-float matrix in column-major order that is used to rotate objects from the + * XY plane to the XZ plane. This is useful given that objects drawn on the Canvas are on the + * XY plane. + * In order to get objects to appear as if they are sticking on planes/ceilings/walls, we need + * to rotate them from the XY plane to the XZ plane. + */ + + public static float[] createXYtoXZRotationMatrix() { + float[] rotation = new float[16]; + android.opengl.Matrix.setIdentityM(rotation, 0); + android.opengl.Matrix.rotateM(rotation, 0, 90, 1, 0, 0); + return rotation; + } + + + /** + * Returns an android.graphics.Matrix resulting from a 16-float matrix array in column-major + * order. + * Undefined behavior when the array is not of size 16 or is null. + * + * @param m4 16-float matrix in column-major order + */ + + public static Matrix createMatrixFrom4x4(float[] m4) { + float[] m3 = matrix4x4ToMatrix3x3(m4); + return createMatrixFrom3x3(m3); + } + + /** + * Returns an android.graphics.Matrix resulting from the concatenation of 16-float matrices + * in column-major order from left to right. + * e.g: m4Array = {m1, m2, m3} --> returns m = m3 * m2 * m1 + * Undefined behavior when the array is empty, null, or contains arrays not of size 9 (or null) + * + * @param m4Array array of 16-float matrices in column-major order + */ + + public static Matrix createMatrixFrom4x4Array(float[][] m4Array) { + float[] result = multiplyMatrices4x4(m4Array); + return createMatrixFrom4x4(result); + } + + /** + * Returns 4-float array resulting from the multiplication of a Vector of 4 floats + * with a 4x4 float Matrix. The return is essentially m4 * v4, with perspective-divide applied + * if perspectiveDivide is true + * @param m4 16-float matrix in column-major order + * @param v4 4-float vector + * @param perspectiveDivide if true, divide return value by the w-coordinate + * @return 4-float array resulting from the multiplication + */ + + public static float[] multiplyMatrixVector(float[] m4, float[] v4, boolean perspectiveDivide) { + float[] result = new float[4]; + android.opengl.Matrix.multiplyMV(result, 0, m4, 0, v4, 0); + if (perspectiveDivide) { + return new float[] {result[0] / result[3], result[1] / result[3], + result[2] / result[3], 1}; + } + + return new float[] {result[0], result[1], result[2], result[3]}; + } + + /** + * Returns a 16-float matrix in column-major order resulting from the multiplication of matrices + * e.g: m4Array = {m1, m2, m3} --> returns m = m3 * m2 * m1 + * Undefined behavior when the array is empty, null, or contains arrays not of size 9 (or null) + * + * @param m4Array array of 16-float matrices in column-major order + */ + + public static float[] multiplyMatrices4x4(float[][] m4Array) { + float[] result = new float[16]; + android.opengl.Matrix.setIdentityM(result, 0); + float[] rhs = result; + for (int i = 0; i < m4Array.length; i++) { + float[] lhs = m4Array[i]; + android.opengl.Matrix.multiplyMM(result, 0, lhs, 0, rhs, 0); + rhs = result; + } + return result; + } + + /******************* PRIVATE FUNCTIONS ***********************/ + + /** + * Returns an android.graphics.Matrix resulting from a 9-float matrix array in row-major order. + * Undefined behavior when the array is not of size 9 or is null. + * + * @param m3 9-float matrix array in row-major order + */ + + private static Matrix createMatrixFrom3x3(float[] m3) { + Matrix m = new Matrix(); + m.setValues(m3); + return m; + } + + /** + * Returns a 9-float matrix in row-major order given a 16-float matrix in column-major order. + * This will drop the Z column and row. + * Undefined behavior when the array is not of size 9 or is null. + * + * @param m4 16-float matrix in column-major order + */ + + private static float[] matrix4x4ToMatrix3x3(float[] m4) { + float[] m3 = new float[9]; + + int j = 0; + for (int i = 0; i < 7; i = i + 3) { + if (j == 2) { + j++; //skip row #3 + } + m3[i] = m4[j]; + m3[i + 1] = m4[j + 4]; + m3[i + 2] = m4[j + 12]; + j++; + } + return m3; + } +} diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARMatrix.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARMatrix.java deleted file mode 100644 index 13c249ce36..0000000000 --- a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARMatrix.java +++ /dev/null @@ -1,171 +0,0 @@ -package com.google.skar; - -import android.graphics.Matrix; -import android.graphics.PointF; - -/** - * Provides static methods for matrix manipulation. Input matrices are assumed to be 4x4 - * android.opengl.Matrix types. Output matrices are 3x3 android.graphics.Matrix types. - * The main use of this class is to be able to get a Matrix for a Canvas that applies perspective - * to 2D objects - */ - -public class SkARMatrix { - - /******************* PUBLIC FUNCTIONS ***********************/ - - /** - * Returns an android.graphics.Matrix that can be used on a Canvas to draw a 2D object in - * perspective. Object will be rotated towards the XZ plane. Undefined behavior when any of - * the matrices are not of size 16, or are null. - * - * @param model 4x4 model matrix of the object to be drawn (global/world) - * @param view 4x4 camera view matrix (brings objects to camera origin and orientation) - * @param projection 4x4 projection matrix - * @param viewPortWidth width of viewport of GLSurfaceView - * @param viewPortHeight height of viewport of GLSurfaceView - * @return 3x3 matrix that puts a 2D objects in perspective on a Canvas - */ - - public static Matrix createPerspectiveMatrix(float[] model, float[] view, float[] projection, - float viewPortWidth, float viewPortHeight) { - float[] viewPort = createViewportMatrix(viewPortWidth, viewPortHeight); - float[] skiaRotation = createXYtoXZRotationMatrix(); - float[][] matrices = {skiaRotation, model, view, projection, viewPort}; - return createMatrixFrom4x4Array(matrices); - } - - /** - * Returns a 16-float matrix in column-major order that represents a viewport matrix given - * the width and height of the viewport. - * - * @param width width of viewport - * @param height height of viewport - */ - - public static float[] createViewportMatrix(float width, float height) { - float[] viewPort = new float[16]; - android.opengl.Matrix.setIdentityM(viewPort, 0); - android.opengl.Matrix.translateM(viewPort, 0, width / 2, height / 2, 0); - android.opengl.Matrix.scaleM(viewPort, 0, width / 2, -height / 2, 0); - return viewPort; - } - - /** - * Returns a 16-float matrix in column-major order that is used to rotate objects from the XY plane - * to the XZ plane. This is useful given that objects drawn on the Canvas are on the XY plane. - * In order to get objects to appear as if they are sticking on planes/ceilings/walls, we need - * to rotate them from the XY plane to the XZ plane. - */ - - public static float[] createXYtoXZRotationMatrix() { - float[] rotation = new float[16]; - android.opengl.Matrix.setIdentityM(rotation, 0); - android.opengl.Matrix.rotateM(rotation, 0, 90, 1, 0, 0); - return rotation; - } - - - /** - * Returns an android.graphics.Matrix resulting from a 16-float matrix array in column-major order - * Undefined behavior when the array is not of size 16 or is null. - * - * @param m4 16-float matrix in column-major order - */ - - public static Matrix createMatrixFrom4x4(float[] m4) { - float[] m3 = matrix4x4ToMatrix3x3(m4); - return createMatrixFrom3x3(m3); - } - - /** - * Returns an android.graphics.PointF resulting from the multiplication of a Vector of 4 floats - * with a 4x4 float Matrix. The return PointF is the (x, y) values of m4 * v4 - * @param m4 16-float matrix in column-major order - * @param v4 4-float vector - * @param perspectiveDivide if true, divide return value by the w-coordinate - * @return PointF resulting from taking the (x, y) values of m4 * v4 - */ - public static PointF multiplyMatrixVector(float[] m4, float[] v4, boolean perspectiveDivide) { - float[] result = new float[4]; - android.opengl.Matrix.multiplyMV(result, 0, m4, 0, v4, 0); - if (perspectiveDivide) { - return new PointF(result[0] / result[3], result[1] / result[3]); - } - - return new PointF(result[0], result[1]); - } - - /** - * Returns a 16-float matrix in column-major order resulting from the multiplication of matrices. - * e.g: m4Array = {m1, m2, m3} --> returns m = m3 * m2 * m1 - * Undefined behavior when the array is empty, null, or contains arrays not of size 9 (or null) - * - * @param m4Array array of 16-float matrices in column-major order - */ - - public static float[] multiplyMatrices4x4(float[][] m4Array) { - float[] result = new float[16]; - android.opengl.Matrix.setIdentityM(result, 0); - float[] rhs = result; - for (int i = 0; i < m4Array.length; i++) { - float[] lhs = m4Array[i]; - android.opengl.Matrix.multiplyMM(result, 0, lhs, 0, rhs, 0); - rhs = result; - } - return result; - } - - /******************* PRIVATE FUNCTIONS ***********************/ - - /** - * Returns an android.graphics.Matrix resulting from the concatenation of 16-float matrices - * in column-major order from left to right. - * e.g: m4Array = {m1, m2, m3} --> returns m = m3 * m2 * m1 - * Undefined behavior when the array is empty, null, or contains arrays not of size 9 (or null) - * - * @param m4Array array of 16-float matrices in column-major order - */ - - private static Matrix createMatrixFrom4x4Array(float[][] m4Array) { - float[] result = multiplyMatrices4x4(m4Array); - return createMatrixFrom4x4(result); - } - - /** - * Returns an android.graphics.Matrix resulting from a 9-float matrix array in row-major order. - * Undefined behavior when the array is not of size 9 or is null. - * - * @param m3 9-float matrix array in row-major order - */ - - private static Matrix createMatrixFrom3x3(float[] m3) { - Matrix m = new Matrix(); - m.setValues(m3); - return m; - } - - /** - * Returns a 9-float matrix in row-major order given a 16-float matrix in column-major order. - * This will drop the Z column and row. - * Undefined behavior when the array is not of size 9 or is null. - * - * @param m4 16-float matrix in column-major order - */ - - private static float[] matrix4x4ToMatrix3x3(float[] m4) { - float[] m3 = new float[9]; - - int j = 0; - for (int i = 0; i < 7; i = i + 3) { - if (j == 2) { - j++; //skip row #3 - } - m3[i] = m4[j]; - m3[i + 1] = m4[j + 4]; - m3[i + 2] = m4[j + 12]; - j++; - } - return m3; - } -} -- cgit v1.2.3