summaryrefslogtreecommitdiffstats
path: root/src/com/tavianator/dimension/android/RaytracedView.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/tavianator/dimension/android/RaytracedView.java')
-rw-r--r--src/com/tavianator/dimension/android/RaytracedView.java178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/com/tavianator/dimension/android/RaytracedView.java b/src/com/tavianator/dimension/android/RaytracedView.java
new file mode 100644
index 0000000..4a88793
--- /dev/null
+++ b/src/com/tavianator/dimension/android/RaytracedView.java
@@ -0,0 +1,178 @@
+/*************************************************************************
+ * Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Android Binding. *
+ * *
+ * The Dimension Android Binding is free software; you can redistribute *
+ * it and/or modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 3 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * The Dimension Android Binding is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+package com.tavianator.dimension.android;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * @author Tavian Barnes <tavianator@tavianator.com>
+ * @version 1.0
+ * @since 1.0
+ */
+@SuppressLint("HandlerLeak")
+public class RaytracedView extends SurfaceView implements
+ SurfaceHolder.Callback {
+ private static final String TAG = RaytracedView.class.getSimpleName();
+
+ private static final int NFRAMES = 64;
+
+ static {
+ System.loadLibrary("dimension");
+ Log.d(TAG, "libdimension loaded sucessfully!");
+ }
+
+ private static final int MSG_RENDER = 0;
+ private static final int MSG_QUIT = 1;
+
+ private static class RenderPayload {
+ public int width;
+ public int height;
+
+ public RenderPayload(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+ }
+
+ private class RenderHandler extends Handler {
+ public RenderHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_RENDER:
+ handleRender((RenderPayload) msg.obj);
+ break;
+ case MSG_QUIT:
+ handleQuit();
+ break;
+ }
+ }
+
+ private void handleRender(RenderPayload payload) {
+ render(payload.width, payload.height);
+ }
+
+ private void handleQuit() {
+ getLooper().quit();
+ }
+ }
+
+ private RenderHandler m_Handler;
+ private int mWidth, mHeight;
+ private int[] mBitmap;
+
+ public RaytracedView(Context context) {
+ super(context);
+ init();
+ }
+
+ public RaytracedView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public RaytracedView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ SurfaceHolder holder = getHolder();
+ holder.addCallback(this);
+ holder.setFormat(PixelFormat.TRANSLUCENT);
+ }
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ HandlerThread thread = new HandlerThread("RenderThread");
+ thread.start();
+
+ m_Handler = new RenderHandler(thread.getLooper());
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int width,
+ int height) {
+ m_Handler.obtainMessage(MSG_RENDER, new RenderPayload(width, height))
+ .sendToTarget();
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ m_Handler.sendEmptyMessage(MSG_QUIT);
+ }
+
+ private void render(int width, int height) {
+ mBitmap = new int[width * height];
+ mWidth = width;
+ mHeight = height;
+
+ renderNative(width, height);
+
+ for (int i = 0; i < NFRAMES; ++i) {
+ waitNative(((double) i) / NFRAMES);
+ draw();
+ }
+
+ joinNative();
+ draw();
+ }
+
+ private void draw() {
+ SurfaceHolder holder = getHolder();
+ Canvas canvas = holder.lockCanvas();
+ if (canvas == null) {
+ return;
+ }
+
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ canvas.drawBitmap(mBitmap, 0, mWidth, 0.0F, 0.0F, mWidth, mHeight,
+ true, null);
+
+ holder.unlockCanvasAndPost(canvas);
+ }
+
+ /** Start the render. */
+ private native void renderNative(int width, int height);
+
+ /** Wait for the render to reach a certain amount of progress. */
+ private native void waitNative(double progress);
+
+ /** Wait for the render to complete. */
+ private native void joinNative();
+
+ /** Called by JNI code to set the pixel colors. */
+ private void setPixel(int x, int y, int color) {
+ y = mHeight - y - 1;
+ mBitmap[y * mWidth + x] = color;
+ }
+}