8package org.skia.jetskidemo;
11import android.content.res.Resources;
13import android.view.GestureDetector;
15import android.view.ScaleGestureDetector;
18import org.
skia.jetski.Canvas;
19import org.skia.jetski.Matrix;
20import org.skia.jetski.Surface;
21import org.skia.jetski.util.SurfaceRenderer;
23import org.skia.jetskidemo.samples.ImageShaderSample;
24import org.skia.jetskidemo.samples.RuntimeSample;
25import org.skia.jetskidemo.samples.Sample;
26import org.skia.jetskidemo.samples.SkottieSample;
28import static java.lang.Math.tan;
42 return new Matrix().rotateY(rotY).rotateX(rotX).translate(0, 0,
scale);
50 public Vec3(
float x,
float y,
float z) { this.x =
x; this.y =
y; this.z =
z; }
52 public float length() {
return (
float)Math.sqrt(
x*
x +
y*
y +
z*
z); }
60 x += v;
y += v;
z += v;
65 x *= v;
y *= v;
z *= v;
70 return x*v.x +
y*v.y +
z*v.
z;
74 float xx =
y*v.z -
z*v.
y,
77 x = xx;
y = yy;
z = zz;
83 private Matrix mRotMatrix =
new Matrix();
84 private Vec3 mRotAxis =
new Vec3(0, 1, 0),
86 private float mRotSpeed = (float)Math.PI,
98 final float kDecay = 0.99f;
100 rotate(mRotAxis, mRotSpeed * dt);
109 public void fling(
float dx,
float dy) {
110 Vec3 u = normalVec(mCenterX, mCenterY),
111 v = normalVec(mCenterX + dx, mCenterY + dy);
114 double flingSpeed = Math.sqrt(dx*dx + dy*dy)/mRadius;
115 mRotSpeed = (float)(flingSpeed*Math.PI);
119 mCurrentDrag = normalVec(e.getX(), e.getY());
123 public void drag(MotionEvent e) {
124 Vec3 u = mCurrentDrag,
125 v = normalVec(e.getX(), e.getY());
127 float angle = (float)Math.acos(Math.max(-1, Math.min(1, u.
dot(v)/u.
length()/v.length())));
135 private Vec3 normalVec(
float x,
float y) {
136 x = (
x - mCenterX)/mRadius;
137 y = -(
y - mCenterY)/mRadius;
138 float len2 =
x*
x +
y*
y;
142 float len = (float)Math.sqrt(len2);
148 return new Vec3(
x,
y, (
float)Math.sqrt(1 - len2));
151 private void rotate(Vec3 axis,
float angle) {
152 mRotMatrix =
new Matrix().rotate(axis.x, axis.y, axis.z, angle)
153 .preConcat(mRotMatrix);
157class CubeRenderer extends SurfaceRenderer implements GestureDetector.OnGestureListener,
158 ScaleGestureDetector.OnScaleGestureListener {
160 private Matrix mViewMatrix;
161 private float mCubeSideLength;
162 private long mPrevMS;
163 private Face[] mFaces;
164 private float mZoom = 1;
167 final float rot = (float) Math.PI;
168 mFaces =
new Face[] {
169 new Face(0, -rot/2,
new ImageShaderSample(res,
R.raw.brickwork_texture)),
170 new Face(0, 0 ,
new SkottieSample(res,
R.raw.im_thirsty)),
171 new Face(0, rot ,
new RuntimeSample(res,
R.raw.runtime_shader1)),
172 new Face(rot/2, 0 ,
new SkottieSample(res,
R.raw.permission)),
173 new Face(0, rot/2 ,
new RuntimeSample(res,
R.raw.runtime_shader2)),
179 float cx =
surface.getWidth() / 2,
181 r = Math.min(cx, cy);
188 mCubeSideLength = vsz * 0.5f;
190 float viewAngle = (float)Math.PI / 4f,
191 viewDistance = (
float)(r / tan(viewAngle/2));
193 mViewMatrix =
new Matrix()
197 .scale(vsz/2, vsz/2, 1)
198 .preConcat(Matrix.makePerspective(0.05f, viewDistance, viewAngle))
200 .preConcat(Matrix.makeLookAt(0, 0, -viewDistance, 0, 0, 0, 0, 1, 0));
209 mVSphere.
animate((ms - mPrevMS) / 1000.f);
214 canvas.drawColor(0xffffffff);
217 canvas.concat(mViewMatrix);
218 canvas.scale(mZoom, mZoom);
221 drawFaces(canvas, ms,
false);
222 drawFaces(canvas, ms,
true);
227 private void drawFaces(Canvas canvas,
long ms,
boolean renderFront) {
228 for (
Face f : mFaces) {
230 canvas.concat(f.asMatrix(mCubeSideLength/2));
232 if (front(canvas.getLocalToDevice()) == renderFront) {
233 f.sample.render(canvas, ms,
243 private void zoom(
float z) {
244 final float kMinZoom = 0.5f,
246 mZoom = Math.max(kMinZoom, Math.min(kMaxZoom, mZoom * z));
250 public boolean onFling(MotionEvent
e1, MotionEvent e2,
float dx,
float dy) {
251 mVSphere.
fling(dx, dy);
262 public boolean onScroll(MotionEvent
e1, MotionEvent e2,
float dx,
float dy) {
277 private boolean front(Matrix m) {
280 m2 = Matrix.makeInverse(m);
281 }
catch (RuntimeException e) {
284 return m2.getAtRowCol(2, 2) > 0;
289 public boolean onScale(ScaleGestureDetector detector) {
290 zoom(detector.getScaleFactor());
296 zoom(detector.getScaleFactor());
302 zoom(detector.getScaleFactor());
308 System.loadLibrary(
"jetski");
311 private GestureDetector mGestureDetector;
312 private ScaleGestureDetector mScaleDetector;
315 protected void onCreate(Bundle savedInstanceState) {
316 super.onCreate(savedInstanceState);
317 setContentView(
R.layout.activity_cube);
319 SurfaceView sv = findViewById(
R.id.surfaceView);
322 sv.getHolder().addCallback(renderer);
324 mGestureDetector =
new GestureDetector(
this, renderer);
325 mScaleDetector =
new ScaleGestureDetector(
this, renderer);
331 mGestureDetector.onTouchEvent(e);
332 mScaleDetector.onTouchEvent(e);
boolean onTouchEvent(MotionEvent e)
void onCreate(Bundle savedInstanceState)
boolean onFling(MotionEvent e1, MotionEvent e2, float dx, float dy)
void onLongPress(MotionEvent e)
boolean onSingleTapUp(MotionEvent e)
boolean onScaleBegin(ScaleGestureDetector detector)
boolean onScroll(MotionEvent e1, MotionEvent e2, float dx, float dy)
boolean onScale(ScaleGestureDetector detector)
CubeRenderer(Resources res)
boolean onDown(MotionEvent e)
void onSurfaceInitialized(Surface surface)
void onShowPress(MotionEvent e)
void onRenderFrame(Canvas canvas, long ms)
void onScaleEnd(ScaleGestureDetector detector)
Face(float rotX, float rotY, Sample sample)
Matrix asMatrix(float scale)
void fling(float dx, float dy)
VSphereAnimator(float x, float y, float r)
void startDrag(MotionEvent e)
Vec3(float x, float y, float z)