3d cube initial demo
Change-Id: Idc3d05eeac13715d2cb57d5930e9642181fc670d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/406436
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Jorge Betancourt <jmbetancourt@google.com>
diff --git a/platform_tools/android/apps/androidkitdemo/src/main/AndroidManifest.xml b/platform_tools/android/apps/androidkitdemo/src/main/AndroidManifest.xml
index 5051801..6aca27a 100644
--- a/platform_tools/android/apps/androidkitdemo/src/main/AndroidManifest.xml
+++ b/platform_tools/android/apps/androidkitdemo/src/main/AndroidManifest.xml
@@ -26,5 +26,11 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:name=".CubeActivity" android:label="AK Cube">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
\ No newline at end of file
diff --git a/platform_tools/android/apps/androidkitdemo/src/main/java/org/skia/androidkitdemo1/CubeActivity.java b/platform_tools/android/apps/androidkitdemo/src/main/java/org/skia/androidkitdemo1/CubeActivity.java
new file mode 100644
index 0000000..72cefa3
--- /dev/null
+++ b/platform_tools/android/apps/androidkitdemo/src/main/java/org/skia/androidkitdemo1/CubeActivity.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+package org.skia.androidkitdemo1;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import org.skia.androidkit.Canvas;
+import org.skia.androidkit.Color;
+import org.skia.androidkit.Matrix;
+import org.skia.androidkit.Paint;
+import org.skia.androidkit.Surface;
+
+import static java.lang.Math.tan;
+
+class Face {
+ private float rotX;
+ private float rotY;
+
+ Face(float rotX, float rotY) {
+ this.rotX = rotX;
+ this.rotY = rotY;
+ }
+
+ Matrix asMatrix(float scale) {
+ return new Matrix().rotateY(rotY).rotateX(rotX).translate(0, 0, scale);
+ }
+}
+
+class CubeRenderThread extends Thread {
+ private android.view.Surface mASurface;
+ private boolean mRunning;
+ // TODO: make these relative to surface size
+ private float mCubeSideLength = 500;
+ private int DX = 200;
+ private int DY = 300;
+
+ private float fAngle = (float)Math.PI / 12;
+ private float eyeZ = (float)(1.0f/tan(fAngle/2) - 1);
+
+ private Matrix cam = Matrix.makeLookAt(0, 0, eyeZ, 0, 0, 0, 0, 1, 0);
+ private Matrix perspective = Matrix.makePerspective(0.05f, 4, fAngle);
+ private Matrix viewport;
+
+ private Paint mPaint;
+
+ private final float rot = (float) Math.PI;
+ private Face[] faces = {new Face(0, 0),
+ new Face(0, rot),
+ new Face(rot/2, 0),
+ new Face(-rot/2, 0),
+ new Face(0, rot/2),
+ new Face(0, -rot/2),};
+
+ private static final String TAG = "*** AK CubeRenderThread";
+
+ public CubeRenderThread(android.view.Surface surface) {
+ mASurface = surface;
+ mPaint = new Paint();
+ mPaint.setColor(new Color(0, 1, 1, 1));
+ mPaint.setStroke(true);
+ mPaint.setStrokeWidth(10);
+
+ }
+
+ public void finish(){
+ mRunning = false;
+ }
+
+ @Override
+ public void run() {
+ mRunning = true;
+ long time_base = java.lang.System.currentTimeMillis();
+
+ Surface surface = Surface.CreateGL(mASurface);
+ viewport = new Matrix().translate(mCubeSideLength/2, mCubeSideLength/2, 0)
+ .scale(mCubeSideLength/2, mCubeSideLength/2, surface.getWidth());
+ while (mRunning) {
+ float t = (float)(java.lang.System.currentTimeMillis() - time_base) / 1000;
+ float speed = 0.5f;
+ float rads = t * speed % (float)(2 * Math.PI);
+ renderFrame(surface, rads);
+ surface.flushAndSubmit();
+ }
+
+ surface.release();
+ }
+
+ private void renderFrame(Surface surface, float rads) {
+ Canvas canvas = surface.getCanvas();
+ // clear canvas
+ canvas.drawColor(0xffffffff);
+
+ canvas.save();
+ canvas.concat(new Matrix().translate(DX, DY, 0));
+ canvas.concat(viewport.preConcat(perspective).preConcat(cam).preConcat(Matrix.makeInverse(viewport)));
+
+ for (Face f : faces) {
+ //TODO: auto restore
+ canvas.save();
+ Matrix trans = new Matrix().translate(mCubeSideLength/2, mCubeSideLength/2, 0);
+ Matrix m = new Matrix().rotateY(rads).rotateZ(rads).preConcat(f.asMatrix(mCubeSideLength/2));
+
+ canvas.concat(trans);
+ Matrix localToWorld = m.preConcat(Matrix.makeInverse(trans));
+ canvas.concat(localToWorld);
+
+ canvas.drawRect(0, 0, mCubeSideLength, mCubeSideLength, mPaint);
+ canvas.restore();
+ }
+ canvas.restore();
+
+
+ }
+}
+public class CubeActivity extends Activity implements SurfaceHolder.Callback {
+ private CubeRenderThread mRenderThread;
+ static {
+ System.loadLibrary("androidkit");
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_cube);
+
+ SurfaceView sv = findViewById(R.id.surfaceView);
+ sv.getHolder().addCallback(this);
+ }
+
+ @Override
+ public void surfaceCreated(@NonNull SurfaceHolder holder) {
+
+ }
+
+ @Override
+ public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
+ if (mRenderThread != null) {
+ mRenderThread.finish();
+ try {
+ mRenderThread.join();
+ } catch (InterruptedException e) {}
+ }
+
+ mRenderThread = new CubeRenderThread(holder.getSurface());;
+ mRenderThread.start();
+ }
+
+ @Override
+ public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
+ if (mRenderThread != null) {
+ mRenderThread.finish();
+ try {
+ mRenderThread.join();
+ } catch (InterruptedException e) {}
+ }
+ }
+}
diff --git a/platform_tools/android/apps/androidkitdemo/src/main/res/layout/activity_cube.xml b/platform_tools/android/apps/androidkitdemo/src/main/res/layout/activity_cube.xml
new file mode 100644
index 0000000..1eb516a
--- /dev/null
+++ b/platform_tools/android/apps/androidkitdemo/src/main/res/layout/activity_cube.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".CubeActivity">
+
+ <SurfaceView
+ android:id="@+id/surfaceView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"/>
+
+ <org.skia.androidkitdemo1.NavigationSpinner
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:layout_constraintBottom_toBottomOf="parent">
+ </org.skia.androidkitdemo1.NavigationSpinner>
+</android.support.constraint.ConstraintLayout>
\ No newline at end of file