From 897f256413c13d932a3c6f34eebe156c96defab8 Mon Sep 17 00:00:00 2001 From: ziadb Date: Fri, 20 Jul 2018 13:10:11 -0400 Subject: SkAR Java: smooth finger painting, planes draw with outlines Bug: skia: Change-Id: I0e6f3c00f030f7a03c3829cd4ff22ac7459dc132 Reviewed-on: https://skia-review.googlesource.com/142685 Reviewed-by: Mike Reed --- .../core/examples/java/helloskar/DrawManager.java | 28 ++++++--- .../examples/java/helloskar/HelloSkARActivity.java | 22 +++++-- .../java/com/google/skar/SkARFingerPainting.java | 67 ++++++++++++++++++---- .../apps/skar_java/src/main/res/menu/main_menu.xml | 11 ++++ 4 files changed, 104 insertions(+), 24 deletions(-) diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/ar/core/examples/java/helloskar/DrawManager.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/ar/core/examples/java/helloskar/DrawManager.java index 9732cb1647..98f36fbe1f 100644 --- a/platform_tools/android/apps/skar_java/src/main/java/com/google/ar/core/examples/java/helloskar/DrawManager.java +++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/ar/core/examples/java/helloskar/DrawManager.java @@ -46,7 +46,7 @@ public class DrawManager { private ColorFilter lightFilter; private BitmapShader planeShader; public ArrayList modelMatrices = new ArrayList<>(); - public SkARFingerPainting fingerPainting = new SkARFingerPainting(); + public SkARFingerPainting fingerPainting = new SkARFingerPainting(false); public void updateViewport(float width, float height) { viewportWidth = width; @@ -65,10 +65,6 @@ public class DrawManager { lightFilter = SkARUtil.createLightCorrectionColorFilter(colorCorr); } - public void updateFingerPainting(PointF p) { - fingerPainting.addPoint(p); - } - // Sample function for drawing a circle public void drawCircle(Canvas canvas) { if (modelMatrices.isEmpty()) { @@ -143,6 +139,10 @@ public class DrawManager { } public void drawFingerPainting(Canvas canvas) { + // Build the path before rendering + fingerPainting.buildPath(); + + // If path empty, return if (fingerPainting.path.isEmpty()) { return; } @@ -166,7 +166,12 @@ public class DrawManager { // Set up paint Paint p = new Paint(); - p.setColor(Color.GREEN); + if (fingerPainting.getSmoothness()) { + p.setColor(Color.CYAN); + } else { + p.setColor(Color.GREEN); + } + p.setStyle(Paint.Style.STROKE); p.setStrokeWidth(30f); p.setAlpha(120); @@ -269,19 +274,24 @@ public class DrawManager { // Set up paint Paint p = new Paint(); - p.setShader(planeShader); - p.setColorFilter(new PorterDuffColorFilter(Color.argb(0.4f, 1, 0, 0), + + if (false) { + //p.setShader(planeShader); + p.setColorFilter(new PorterDuffColorFilter(Color.argb(0.4f, 1, 0, 0), PorterDuff.Mode.SRC_ATOP)); + } p.setColor(Color.RED); p.setAlpha(100); + p.setStrokeWidth(0.01f); + p.setStyle(Paint.Style.STROKE); + if (true) { // Shader local matrix android.graphics.Matrix lm = new android.graphics.Matrix(); lm.setScale(0.00005f, 0.00005f); planeShader.setLocalMatrix(lm); - // Draw dest path canvas.save(); canvas.setMatrix(mvpv); diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/ar/core/examples/java/helloskar/HelloSkARActivity.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/ar/core/examples/java/helloskar/HelloSkARActivity.java index d8161c7979..56b46017e7 100644 --- a/platform_tools/android/apps/skar_java/src/main/java/com/google/ar/core/examples/java/helloskar/HelloSkARActivity.java +++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/ar/core/examples/java/helloskar/HelloSkARActivity.java @@ -104,6 +104,7 @@ public class HelloSkARActivity extends AppCompatActivity implements GLSurfaceVie // 2D Renderer private DrawManager drawManager = new DrawManager(); private DrawingType currentDrawabletype = DrawingType.circle; + private boolean drawSmoothPainting = false; // Temporary matrix allocated here to reduce number of allocations for each frame. private final float[] anchorMatrix = new float[16]; @@ -384,6 +385,10 @@ public class HelloSkARActivity extends AppCompatActivity implements GLSurfaceVie PointF distance = new PointF(point[0] - previousEvent.x, point[2] - previousEvent.y); + if (distance.length() < 0.05f) { + continue; + } + // New point is distance + old point PointF p = new PointF(distance.x * localDistanceScale + drawManager.fingerPainting.previousPoint.x, @@ -466,24 +471,25 @@ public class HelloSkARActivity extends AppCompatActivity implements GLSurfaceVie switch (currentDrawabletype) { case circle: drawManager.drawCircle(canvas); - return; + break; case rect: drawManager.drawRect(canvas); - return; + break; case animation: drawManager.drawAnimatedRoundRect(canvas, radius); - return; + break; case text: drawManager.drawText(canvas, "Android"); - return; + break; default: drawManager.drawCircle(canvas); - return; + break; } } } private void drawFingerPainting(Canvas canvas) { + drawManager.fingerPainting.setSmoothness(drawSmoothPainting); drawManager.drawFingerPainting(canvas); } @@ -499,6 +505,12 @@ public class HelloSkARActivity extends AppCompatActivity implements GLSurfaceVie case R.id.reset_paint: drawManager.fingerPainting.reset(); return true; + case R.id.smooth_paint: + drawSmoothPainting = true; + return true; + case R.id.rough_paint: + drawSmoothPainting = false; + return true; case R.id.draw_circle: currentDrawabletype = DrawingType.circle; return true; diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARFingerPainting.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARFingerPainting.java index 5fc31e7ff8..c93a900f58 100644 --- a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARFingerPainting.java +++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/SkARFingerPainting.java @@ -3,33 +3,80 @@ package com.google.skar; import android.graphics.Path; import android.graphics.PointF; +import java.util.ArrayList; + public class SkARFingerPainting { + // Points obtained by touching the screen. The first point is always brough to (0,0). + // All subsequent points are translated by the same amount. + public ArrayList points = new ArrayList<>(); + public Path path = new Path(); // Previous point added to the path. This points belongs to the path in local space. public PointF previousPoint; - private int numberOfPoints = 0; - // Holds the model matrix of the first point added to such that the path can be drawn at the // model location (i.e on the Plane) private float[] modelMatrix; - public SkARFingerPainting() {} + private boolean isSmooth; + + public SkARFingerPainting(boolean smooth) { + this.isSmooth = smooth; + } + + public boolean getSmoothness() { + return isSmooth; + } + + public void setSmoothness(boolean smooth) { + isSmooth = smooth; + } // Adds another point to the path in Local space public void addPoint(PointF p) { - if (numberOfPoints == 0) { - path.moveTo(p.x, p.y); + points.add(p); + previousPoint = p; + } + + // Used to build a path before rendering it + public void buildPath() { + if (points.size() < 1) { + return; + } + + path = new Path(); + if (isSmooth) { + // If less than 3 points, than draw a line between the two points + if (points.size() <= 2 && points.size() > 0) { + path.moveTo(points.get(0).x, points.get(0).y); + path.lineTo(points.get(1).x, points.get(1).y); + } else if (points.size() >= 3){ + // Else, essentially run deCasteljau + path.moveTo(points.get(0).x, points.get(0).y); + PointF mid = new PointF((points.get(0).x + points.get(1).x) / 2, + (points.get(0).y + points.get(1).y) / 2); + path.lineTo(mid.x, mid.y); + + for (int i = 1; i < points.size() - 1; i++) { + PointF p1 = points.get(i); + PointF p2 = points.get(i + 1); + PointF midP = new PointF((p1.x + p2.x) / 2,(p1.y + p2.y) / 2); + path.quadTo(p1.x, p1.y, midP.x, midP.y); + } + + path.lineTo(points.get(points.size() - 1).x, points.get(points.size() - 1).y); + } } else { - path.lineTo(p.x, p.y); + path.moveTo(points.get(0).x, points.get(0).y); + for (int i = 1; i < points.size(); i++) { + path.lineTo(points.get(i).x, points.get(i).y); + } } - previousPoint = p; - numberOfPoints++; } public boolean isEmpty() { - return numberOfPoints == 0; + return path.isEmpty(); } public float[] getModelMatrix() { @@ -41,7 +88,7 @@ public class SkARFingerPainting { } public void reset() { + points = new ArrayList<>(); path = new Path(); - numberOfPoints = 0; } } diff --git a/platform_tools/android/apps/skar_java/src/main/res/menu/main_menu.xml b/platform_tools/android/apps/skar_java/src/main/res/menu/main_menu.xml index f70e272aa5..d4383f99f1 100644 --- a/platform_tools/android/apps/skar_java/src/main/res/menu/main_menu.xml +++ b/platform_tools/android/apps/skar_java/src/main/res/menu/main_menu.xml @@ -6,6 +6,17 @@ android:id="@+id/reset_paint" android:title="Reset Finger Painting"/> + + + + +