aboutsummaryrefslogtreecommitdiffhomepage
path: root/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARMatrix.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARMatrix.java')
-rw-r--r--platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARMatrix.java211
1 files changed, 211 insertions, 0 deletions
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
new file mode 100644
index 0000000000..fc9333c6df
--- /dev/null
+++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARMatrix.java
@@ -0,0 +1,211 @@
+package com.google.skar;
+
+import android.graphics.Matrix;
+
+/**
+ * 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 {
+ /**
+ * Returns an android.graphics.Matrix that can be used on a Canvas to draw a 2D object in
+ * perspective. Objects 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 viewport 4x4 viewport matrix
+ * @return 3x3 matrix that puts a 2D objects in perspective on a Canvas
+ */
+
+ public static Matrix createPerspectiveMatrix(float[] model, float[] view, float[] projection,
+ float[] viewport) {
+ float[] skiaRotation = createXYtoXZRotationMatrix();
+ float[][] matrices = {skiaRotation, model, view, projection, viewport};
+ return createMatrixFrom4x4Array(matrices);
+ }
+
+ /**
+ * Returns an android.graphics.Matrix that can be used on a Canvas to draw a 2D object in
+ * perspective. 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 viewport 4x4 viewport matrix
+ * @param rotatePlane specifies if object should be from the XY plane to the XZ plane
+ * @return 3x3 matrix that puts a 2D objects in perspective on a Canvas
+ */
+
+ public static Matrix createPerspectiveMatrix(float[] model, float[] view, float[] projection,
+ float[] viewport, boolean rotatePlane) {
+ if (rotatePlane) {
+ return createPerspectiveMatrix(model, view, projection, viewport);
+ } else {
+ float[][] matrices = {model, view, projection, viewport};
+ return createMatrixFrom4x4Array(matrices);
+ }
+ }
+
+ /**
+ * Returns an android.graphics.Matrix that can be used on a Canvas to draw a 2D object in
+ * perspective. 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
+ * @param rotatePlane specifies if object should be from the XY plane to the XZ plane
+ * @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, boolean rotatePlane) {
+ if (rotatePlane) {
+ return createPerspectiveMatrix(model, view, projection, viewPortWidth, viewPortHeight);
+ } else {
+ float[] viewPort = createViewportMatrix(viewPortWidth, viewPortHeight);
+ float[][] matrices = {model, view, projection, viewPort};
+ return createMatrixFrom4x4Array(matrices);
+ }
+ }
+
+ /**
+ * 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.
+ */
+
+ private 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 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
+ */
+
+ public static Matrix createMatrixFrom3x3(float[] m3) {
+ Matrix m = new Matrix();
+ m.setValues(m3);
+ return m;
+ }
+
+ /**
+ * 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
+ */
+
+ 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 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;
+ }
+
+ /**
+ * 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
+ */
+
+ private 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;
+ }
+}