summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore10
-rw-r--r--AndroidManifest.xml28
-rw-r--r--ant.properties17
-rw-r--r--build.xml92
-rw-r--r--jni/Android.mk80
-rw-r--r--jni/Application.mk21
-rw-r--r--jni/jni.c386
-rw-r--r--libdimension/error.c28
-rw-r--r--libdimension/future.c11
-rw-r--r--libdimension/platform.c4
-rw-r--r--libdimension/threads.c8
-rw-r--r--proguard-project.txt20
-rw-r--r--project.properties14
-rw-r--r--res/drawable-hdpi/ic_launcher.pngbin0 -> 9397 bytes
-rw-r--r--res/drawable-ldpi/ic_launcher.pngbin0 -> 2729 bytes
-rw-r--r--res/drawable-mdpi/ic_launcher.pngbin0 -> 5237 bytes
-rw-r--r--res/drawable-xhdpi/ic_launcher.pngbin0 -> 14383 bytes
-rw-r--r--res/layout/main.xml11
-rw-r--r--res/values/strings.xml4
-rw-r--r--src/com/tavianator/dimension/android/DimensionActivity.java36
-rw-r--r--src/com/tavianator/dimension/android/RaytracedView.java178
21 files changed, 921 insertions, 27 deletions
diff --git a/.gitignore b/.gitignore
index ebb7df2..8cb96c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,3 +46,13 @@ __pycache__
# Core dumps
core
vgcore.*
+
+# Android code
+/bin/
+/gen/
+/libs/
+/obj/
+/local.properties
+.classpath
+.project
+.settings
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..fd9aa04
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.tavianator.dimension.android"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name="DimensionActivity"
+ android:label="@string/app_name"
+ android:configChanges="orientation|screenSize"
+ android:screenOrientation="sensor"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/ant.properties b/ant.properties
new file mode 100644
index 0000000..b0971e8
--- /dev/null
+++ b/ant.properties
@@ -0,0 +1,17 @@
+# This file is used to override default values used by the Ant build system.
+#
+# This file must be checked into Version Control Systems, as it is
+# integral to the build system of your project.
+
+# This file is only used by the Ant script.
+
+# You can use this to override default values such as
+# 'source.dir' for the location of your java source folder and
+# 'out.dir' for the location of your output folder.
+
+# You can also use it define how the release builds are signed by declaring
+# the following properties:
+# 'key.store' for the location of your keystore and
+# 'key.alias' for the name of the key to use.
+# The password will be asked during the build when you use the 'release' target.
+
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..816253e
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="dimension" default="help">
+
+ <!-- The local.properties file is created and updated by the 'android' tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The ant.properties file can be created by you. It is only edited by the
+ 'android' tool to add properties to it.
+ This is the place to change some Ant specific build properties.
+ Here are some properties you may want to change/update:
+
+ source.dir
+ The name of the source directory. Default is 'src'.
+ out.dir
+ The name of the output directory. Default is 'bin'.
+
+ For other overridable properties, look at the beginning of the rules
+ files in the SDK, at tools/ant/build.xml
+
+ Properties related to the SDK location or the project target should
+ be updated using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems.
+
+ -->
+ <property file="ant.properties" />
+
+ <!-- if sdk.dir was not set from one of the property file, then
+ get it from the ANDROID_HOME env var.
+ This must be done before we load project.properties since
+ the proguard config can use sdk.dir -->
+ <property environment="env" />
+ <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+ <isset property="env.ANDROID_HOME" />
+ </condition>
+
+ <!-- The project.properties file is created and updated by the 'android'
+ tool, as well as ADT.
+
+ This contains project specific properties such as project target, and library
+ dependencies. Lower level build properties are stored in ant.properties
+ (or in .classpath for Eclipse projects).
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems. -->
+ <loadproperties srcFile="project.properties" />
+
+ <!-- quick check on sdk.dir -->
+ <fail
+ message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+ unless="sdk.dir"
+ />
+
+ <!--
+ Import per project custom build rules if present at the root of the project.
+ This is the place to put custom intermediary targets such as:
+ -pre-build
+ -pre-compile
+ -post-compile (This is typically used for code obfuscation.
+ Compiled code location: ${out.classes.absolute.dir}
+ If this is not done in place, override ${out.dex.input.absolute.dir})
+ -post-package
+ -post-build
+ -pre-clean
+ -->
+ <import file="custom_rules.xml" optional="true" />
+
+ <!-- Import the actual build file.
+
+ To customize existing targets, there are two options:
+ - Customize only one target:
+ - copy/paste the target into this file, *before* the
+ <import> task.
+ - customize it to your needs.
+ - Customize the whole content of build.xml
+ - copy/paste the content of the rules files (minus the top node)
+ into this file, replacing the <import> task.
+ - customize to your needs.
+
+ ***********************
+ ****** IMPORTANT ******
+ ***********************
+ In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+ in order to avoid having your file be overridden by tools such as "android update project"
+ -->
+ <!-- version-tag: 1 -->
+ <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/jni/Android.mk b/jni/Android.mk
new file mode 100644
index 0000000..1adf510
--- /dev/null
+++ b/jni/Android.mk
@@ -0,0 +1,80 @@
+###########################################################################
+## Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> ##
+## ##
+## This file is part of The Dimension Build Suite. ##
+## ##
+## The Dimension Build Suite 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 Build Suite 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/>. ##
+###########################################################################
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := dimension
+LOCAL_SRC_FILES := \
+ jni.c \
+ ../libdimension/camera.c \
+ ../libdimension/canvas.c \
+ ../libdimension/canvas_pigment.c \
+ ../libdimension/checker.c \
+ ../libdimension/cone.c \
+ ../libdimension/cube.c \
+ ../libdimension/csg.c \
+ ../libdimension/dictionary.c \
+ ../libdimension/error.c \
+ ../libdimension/finish.c \
+ ../libdimension/future.c \
+ ../libdimension/geometry.c \
+ ../libdimension/gradient.c \
+ ../libdimension/inline.c \
+ ../libdimension/interior.c \
+ ../libdimension/lambertian.c \
+ ../libdimension/leopard.c \
+ ../libdimension/light.c \
+ ../libdimension/malloc.c \
+ ../libdimension/map.c \
+ ../libdimension/object.c \
+ ../libdimension/pattern.c \
+ ../libdimension/perspective.c \
+ ../libdimension/phong.c \
+ ../libdimension/pigment.c \
+ ../libdimension/pigment_map.c \
+ ../libdimension/plane.c \
+ ../libdimension/platform.c \
+ ../libdimension/point_light.c \
+ ../libdimension/polynomial.c \
+ ../libdimension/prtree.c \
+ ../libdimension/ray_trace.c \
+ ../libdimension/reflection.c \
+ ../libdimension/rgba16.c \
+ ../libdimension/scene.c \
+ ../libdimension/solid_pigment.c \
+ ../libdimension/sphere.c \
+ ../libdimension/texture.c \
+ ../libdimension/threads.c \
+ ../libdimension/timer.c \
+ ../libdimension/torus.c \
+ ../libdimension/triangle.c \
+ ../libdimension/png-stubs.c \
+ ../libdimension/gl-stubs.c
+LOCAL_CFLAGS := \
+ -Ilibdimension/ \
+ -std=gnu99 \
+ -DHAVE_UNISTD_H=1 \
+ -DDMNSN_GETTID_DIRECT=1 \
+ -DDMNSN_SC_NPROCESSORS_ONLN=1 \
+ -DDMNSN_GETRUSAGE=1
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/jni/Application.mk b/jni/Application.mk
new file mode 100644
index 0000000..74fec4c
--- /dev/null
+++ b/jni/Application.mk
@@ -0,0 +1,21 @@
+###########################################################################
+## Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> ##
+## ##
+## This file is part of The Dimension Build Suite. ##
+## ##
+## The Dimension Build Suite 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 Build Suite 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/>. ##
+###########################################################################
+
+APP_ABI := armeabi armeabi-v7a
+APP_PLATFORM := android-16
diff --git a/jni/jni.c b/jni/jni.c
new file mode 100644
index 0000000..d12dd01
--- /dev/null
+++ b/jni/jni.c
@@ -0,0 +1,386 @@
+/*************************************************************************
+ * 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/>. *
+ *************************************************************************/
+
+/**
+ * @file
+ * Java interface to libdimension used by Android.
+ */
+
+#include "dimension-internal.h"
+#include <jni.h>
+#include <android/log.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define TAG "libdimension_jni"
+
+static void
+dmnsn_test_scene_set_defaults(dmnsn_scene *scene)
+{
+ /* Default texture */
+ scene->default_texture->pigment =
+ dmnsn_new_solid_pigment(DMNSN_TCOLOR(dmnsn_black));
+ dmnsn_finish *default_finish = &scene->default_texture->finish;
+ default_finish->ambient = dmnsn_new_ambient(
+ dmnsn_color_from_sRGB(dmnsn_color_mul(0.1, dmnsn_white))
+ );
+ default_finish->diffuse = dmnsn_new_lambertian(dmnsn_sRGB_inverse_gamma(0.7));
+}
+
+static void
+dmnsn_test_scene_add_canvas(dmnsn_scene *scene, size_t width, size_t height)
+{
+ scene->canvas = dmnsn_new_canvas(width, height);
+}
+
+static void
+dmnsn_test_scene_add_camera(dmnsn_scene *scene)
+{
+ /* Set up the transformation matrix for the perspective camera */
+ dmnsn_matrix trans = dmnsn_scale_matrix(
+ dmnsn_new_vector(
+ ((double)scene->canvas->width)/scene->canvas->height, 1.0, 1.0
+ )
+ );
+ trans = dmnsn_matrix_mul(
+ dmnsn_rotation_matrix(dmnsn_new_vector(0.0624188099959577, 0.0, 0.0)),
+ trans
+ );
+ trans = dmnsn_matrix_mul(
+ dmnsn_translation_matrix(dmnsn_new_vector(0.0, 0.25, -4.0)),
+ trans
+ );
+ trans = dmnsn_matrix_mul(
+ dmnsn_rotation_matrix(dmnsn_new_vector(0.0, dmnsn_radians(53.0), 0.0)),
+ trans
+ );
+
+ /* Create a perspective camera */
+ scene->camera = dmnsn_new_perspective_camera();
+ scene->camera->trans = trans;
+}
+
+static void
+dmnsn_test_scene_add_background(dmnsn_scene *scene)
+{
+ scene->background = dmnsn_new_solid_pigment(dmnsn_clear);
+}
+
+static void
+dmnsn_test_scene_add_lights(dmnsn_scene *scene)
+{
+ dmnsn_light *light = dmnsn_new_point_light(
+ dmnsn_new_vector(-15.0, 20.0, 10.0),
+ dmnsn_white
+ );
+ dmnsn_array_push(scene->lights, &light);
+}
+
+static void
+dmnsn_test_scene_add_hollow_cube(dmnsn_scene *scene)
+{
+ dmnsn_object *cube = dmnsn_new_cube();
+ cube->trans = dmnsn_rotation_matrix(
+ dmnsn_new_vector(dmnsn_radians(45.0), 0.0, 0.0)
+ );
+
+ cube->texture = dmnsn_new_texture();
+ dmnsn_tcolor cube_color = dmnsn_new_tcolor(dmnsn_blue, 0.75, 1.0/3.0);
+ cube->texture->pigment = dmnsn_new_solid_pigment(cube_color);
+
+ dmnsn_color reflect =
+ dmnsn_color_from_sRGB(dmnsn_color_mul(0.5, dmnsn_white));
+ cube->texture->finish.reflection =
+ dmnsn_new_basic_reflection(dmnsn_black, reflect, 1.0);
+
+ cube->interior = dmnsn_new_interior();
+ cube->interior->ior = 1.1;
+
+ dmnsn_object *sphere = dmnsn_new_sphere();
+ sphere->texture = dmnsn_new_texture();
+ sphere->texture->pigment = dmnsn_new_solid_pigment(DMNSN_TCOLOR(dmnsn_green));
+ sphere->texture->finish.specular =
+ dmnsn_new_phong(dmnsn_sRGB_inverse_gamma(0.2), 40.0);
+ sphere->trans = dmnsn_scale_matrix(dmnsn_new_vector(1.25, 1.25, 1.25));
+
+ dmnsn_object *hollow_cube = dmnsn_new_csg_difference(cube, sphere);
+ dmnsn_array_push(scene->objects, &hollow_cube);
+}
+
+#define dmnsn_pigment_map_add_color(map, n, color) \
+ do { \
+ dmnsn_tcolor tcolor = DMNSN_TCOLOR(color); \
+ dmnsn_pigment *pigment = dmnsn_new_solid_pigment(tcolor); \
+ dmnsn_map_add_entry(map, n, &pigment); \
+ } while (0)
+
+static void
+dmnsn_test_scene_add_spike(dmnsn_scene *scene)
+{
+ dmnsn_array *arrow_array = dmnsn_new_array(sizeof(dmnsn_object *));
+
+ dmnsn_object *cylinder = dmnsn_new_cone(0.1, 0.1, false);
+ cylinder->trans = dmnsn_scale_matrix(dmnsn_new_vector(1.0, 1.25, 1.0));
+ dmnsn_array_push(arrow_array, &cylinder);
+
+ dmnsn_object *cone = dmnsn_new_cone(0.1, 0.0, true);
+ cone->trans = dmnsn_matrix_mul(
+ dmnsn_translation_matrix(dmnsn_new_vector(0.0, 1.375, 0.0)),
+ dmnsn_scale_matrix(dmnsn_new_vector(1.0, 0.125, 1.0))
+ );
+ dmnsn_array_push(arrow_array, &cone);
+
+ dmnsn_object *arrow = dmnsn_new_csg_union(arrow_array);
+ dmnsn_delete_array(arrow_array);
+ dmnsn_pattern *gradient = dmnsn_new_gradient_pattern(dmnsn_y);
+ dmnsn_map *gradient_pigment_map = dmnsn_new_pigment_map();
+ dmnsn_pigment_map_add_color(gradient_pigment_map, 0.0, dmnsn_red);
+ dmnsn_pigment_map_add_color(gradient_pigment_map, 1.0/6.0, dmnsn_orange);
+ dmnsn_pigment_map_add_color(gradient_pigment_map, 2.0/6.0, dmnsn_yellow);
+ dmnsn_pigment_map_add_color(gradient_pigment_map, 3.0/6.0, dmnsn_green);
+ dmnsn_pigment_map_add_color(gradient_pigment_map, 4.0/6.0, dmnsn_blue);
+ dmnsn_pigment_map_add_color(gradient_pigment_map, 5.0/6.0, dmnsn_magenta);
+ dmnsn_pigment_map_add_color(gradient_pigment_map, 1.0, dmnsn_red);
+ arrow->texture = dmnsn_new_texture();
+ arrow->texture->pigment =
+ dmnsn_new_pigment_map_pigment(gradient, gradient_pigment_map,
+ DMNSN_PIGMENT_MAP_SRGB);
+
+ arrow->texture->trans =
+ dmnsn_matrix_mul(
+ dmnsn_translation_matrix(dmnsn_new_vector(0.0, -1.25, 0.0)),
+ dmnsn_scale_matrix(dmnsn_new_vector(1.0, 2.75, 1.0))
+ );
+
+ dmnsn_array *torus_array = dmnsn_new_array(sizeof(dmnsn_object *));
+
+ dmnsn_object *torus1 = dmnsn_new_torus(0.15, 0.05);
+ torus1->trans = dmnsn_translation_matrix(dmnsn_new_vector(0.0, -1.0, 0.0));
+ dmnsn_array_push(torus_array, &torus1);
+
+ dmnsn_object *torus2 = dmnsn_new_torus(0.15, 0.05);
+ dmnsn_array_push(torus_array, &torus2);
+
+ dmnsn_object *torus3 = dmnsn_new_torus(0.15, 0.05);
+ torus3->trans = dmnsn_translation_matrix(dmnsn_new_vector(0.0, 1.0, 0.0));
+ dmnsn_array_push(torus_array, &torus3);
+
+ dmnsn_object *torii = dmnsn_new_csg_union(torus_array);
+ dmnsn_delete_array(torus_array);
+ torii->texture = dmnsn_new_texture();
+ torii->texture->pigment = dmnsn_new_solid_pigment(DMNSN_TCOLOR(dmnsn_blue));
+ torii->texture->finish.ambient = dmnsn_new_ambient(dmnsn_white);
+
+ dmnsn_array *spike_array = dmnsn_new_array(sizeof(dmnsn_object *));
+ dmnsn_array_push(spike_array, &arrow);
+ dmnsn_array_push(spike_array, &torii);
+ dmnsn_object *spike = dmnsn_new_csg_union(spike_array);
+ dmnsn_delete_array(spike_array);
+ spike->trans = dmnsn_rotation_matrix(
+ dmnsn_new_vector(dmnsn_radians(-45.0), 0.0, 0.0)
+ );
+ dmnsn_array_push(scene->objects, &spike);
+}
+
+static void
+dmnsn_test_scene_add_triangle_strip(dmnsn_scene *scene)
+{
+ dmnsn_array *strip_array = dmnsn_new_array(sizeof(dmnsn_object *));
+ dmnsn_vector a = dmnsn_zero;
+ dmnsn_vector b = dmnsn_new_vector(0.0, sqrt(3.0)/2.0, 0.5);
+ dmnsn_vector c = dmnsn_z;
+ dmnsn_texture *strip_textures[3] = {
+ dmnsn_new_texture(),
+ dmnsn_new_texture(),
+ dmnsn_new_texture(),
+ };
+ strip_textures[0]->pigment =
+ dmnsn_new_solid_pigment(DMNSN_TCOLOR(dmnsn_red));
+ strip_textures[1]->pigment =
+ dmnsn_new_solid_pigment(DMNSN_TCOLOR(dmnsn_orange));
+ strip_textures[2]->pigment =
+ dmnsn_new_solid_pigment(DMNSN_TCOLOR(dmnsn_yellow));
+ for (unsigned int i = 0; i < 128; ++i) {
+ dmnsn_object *triangle = dmnsn_new_flat_triangle(a, b, c);
+ triangle->texture = strip_textures[i%3];
+ DMNSN_INCREF(triangle->texture);
+ dmnsn_array_push(strip_array, &triangle);
+
+ a = b;
+ b = c;
+ c = dmnsn_vector_add(a, dmnsn_z);
+ }
+ for (unsigned int i = 0; i < 3; ++i) {
+ dmnsn_delete_texture(strip_textures[i]);
+ }
+
+ dmnsn_object *strip = dmnsn_new_csg_union(strip_array);
+ dmnsn_delete_array(strip_array);
+ strip->trans = dmnsn_translation_matrix(dmnsn_new_vector(5.0, -2.0, -4.0));
+ dmnsn_array_push(scene->objects, &strip);
+}
+
+static void
+dmnsn_test_scene_add_ground(dmnsn_scene *scene)
+{
+ dmnsn_object *plane = dmnsn_new_plane(dmnsn_new_vector(0.0, 1.0, 0.0));
+ plane->trans = dmnsn_translation_matrix(dmnsn_new_vector(0.0, -2.0, 0.0));
+ dmnsn_pattern *checker1 = dmnsn_new_checker_pattern();
+ dmnsn_pattern *checker2 = dmnsn_new_checker_pattern();
+ dmnsn_map *small_map = dmnsn_new_pigment_map();
+ dmnsn_pigment_map_add_color(small_map, 0.0, dmnsn_black);
+ dmnsn_pigment_map_add_color(small_map, 1.0, dmnsn_white);
+ dmnsn_pigment *small_pigment =
+ dmnsn_new_pigment_map_pigment(checker1, small_map,
+ DMNSN_PIGMENT_MAP_REGULAR);
+ small_pigment->trans =
+ dmnsn_scale_matrix(dmnsn_new_vector(1.0/3.0, 1.0/3.0, 1.0/3.0));
+ dmnsn_map *big_map = dmnsn_new_pigment_map();
+ dmnsn_pigment_map_add_color(big_map, 0.0, dmnsn_white);
+ dmnsn_map_add_entry(big_map, 1.0, &small_pigment);
+ plane->texture = dmnsn_new_texture();
+ plane->texture->pigment =
+ dmnsn_new_pigment_map_pigment(checker2, big_map, DMNSN_PIGMENT_MAP_REGULAR);
+ plane->texture->pigment->quick_color = DMNSN_TCOLOR(
+ dmnsn_color_from_sRGB(
+ dmnsn_new_color(1.0, 0.5, 0.75)
+ )
+ );
+ dmnsn_array_push(scene->objects, &plane);
+}
+
+static void
+dmnsn_test_scene_add_objects(dmnsn_scene *scene)
+{
+ dmnsn_test_scene_add_hollow_cube(scene);
+ dmnsn_test_scene_add_spike(scene);
+ dmnsn_test_scene_add_triangle_strip(scene);
+ dmnsn_test_scene_add_ground(scene);
+}
+
+/*
+ * Test scene
+ */
+static dmnsn_scene *
+dmnsn_new_test_scene(size_t width, size_t height)
+{
+ dmnsn_scene *scene = dmnsn_new_scene();
+ dmnsn_test_scene_set_defaults(scene);
+ dmnsn_test_scene_add_canvas(scene, width, height);
+ dmnsn_test_scene_add_camera(scene);
+ dmnsn_test_scene_add_background(scene);
+ dmnsn_test_scene_add_lights(scene);
+ dmnsn_test_scene_add_objects(scene);
+ return scene;
+}
+
+static JavaVM *jvm;
+static jobject shared_obj;
+static jclass shared_cls;
+static jmethodID method;
+
+static dmnsn_scene *scene;
+static dmnsn_future *future;
+
+static pthread_key_t dmnsn_detach;
+static pthread_once_t dmnsn_detach_once = PTHREAD_ONCE_INIT;
+
+static void dmnsn_jni_optimizer_fn(const dmnsn_canvas *canvas,
+ dmnsn_canvas_optimizer optimizer,
+ size_t x, size_t y);
+
+JNIEXPORT void JNICALL Java_com_tavianator_dimension_android_RaytracedView_renderNative(JNIEnv *env, jobject obj, jint width, jint height)
+{
+ scene = dmnsn_new_test_scene(width, height);
+
+ (*env)->GetJavaVM(env, &jvm);
+ shared_obj = (*env)->NewGlobalRef(env, obj);
+ jclass cls = (*env)->GetObjectClass(env, shared_obj);
+ shared_cls = (*env)->NewGlobalRef(env, cls);
+ method = (*env)->GetMethodID(env, shared_cls, "setPixel", "(III)V");
+
+ /* Use a canvas optimizer to pass pixels back to the JVM */
+ dmnsn_canvas_optimizer optimizer;
+ optimizer.optimizer_fn = dmnsn_jni_optimizer_fn;
+ optimizer.free_fn = NULL;
+ dmnsn_canvas_optimize(scene->canvas, optimizer);
+
+ __android_log_print(ANDROID_LOG_INFO, TAG, "Rendering with %u threads ...", scene->nthreads);
+ future = dmnsn_ray_trace_async(scene);
+}
+
+JNIEXPORT void JNICALL Java_com_tavianator_dimension_android_RaytracedView_waitNative(JNIEnv *env, jobject obj, jdouble progress)
+{
+ dmnsn_future_wait(future, progress);
+}
+
+JNIEXPORT void JNICALL Java_com_tavianator_dimension_android_RaytracedView_joinNative(JNIEnv *env, jobject obj)
+{
+ dmnsn_future_join(future);
+ __android_log_print(ANDROID_LOG_INFO, TAG, "Rendered!");
+
+ dmnsn_delete_scene(scene);
+
+ (*env)->DeleteGlobalRef(env, shared_cls);
+ (*env)->DeleteGlobalRef(env, shared_obj);
+}
+
+static void
+dmnsn_do_detach(void *ptr)
+{
+ (*jvm)->DetachCurrentThread(jvm);
+}
+
+static void
+dmnsn_initialize_detach(void)
+{
+ dmnsn_key_create(&dmnsn_detach, dmnsn_do_detach);
+}
+
+static void
+dmnsn_jni_optimizer_fn(const dmnsn_canvas *canvas,
+ dmnsn_canvas_optimizer optimizer, size_t x, size_t y)
+{
+ dmnsn_tcolor tcolor = dmnsn_canvas_get_pixel(canvas, x, y);
+ tcolor = dmnsn_tcolor_remove_filter(tcolor);
+ tcolor.c = dmnsn_color_to_sRGB(tcolor.c);
+ tcolor = dmnsn_tcolor_saturate(tcolor);
+
+ uint32_t argb = 0;
+
+ unsigned char component = (unsigned char) ((1.0 - tcolor.T)*UCHAR_MAX);
+ argb |= component << UINT32_C(24);
+
+ component = (unsigned char) (tcolor.c.R*UCHAR_MAX);
+ argb |= component << UINT32_C(16);
+
+ component = (unsigned char) (tcolor.c.G*UCHAR_MAX);
+ argb |= component << UINT32_C(8);
+
+ component = (unsigned char) (tcolor.c.B*UCHAR_MAX);
+ argb |= component;
+
+ dmnsn_once(&dmnsn_detach_once, dmnsn_initialize_detach);
+ JNIEnv *env = pthread_getspecific(dmnsn_detach);
+ if (env == NULL) {
+ (*jvm)->AttachCurrentThread(jvm, &env, NULL);
+ pthread_setspecific(dmnsn_detach, env);
+ }
+ (*env)->CallVoidMethod(env, shared_obj, method, (jint) x, (jint) y, (jint) argb);
+}
diff --git a/libdimension/error.c b/libdimension/error.c
index 371c7cd..9fb116a 100644
--- a/libdimension/error.c
+++ b/libdimension/error.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * Copyright (C) 2009-2012 Tavian Barnes <tavianator@tavianator.com> *
* *
* This file is part of The Dimension Library. *
* *
@@ -28,13 +28,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <android/log.h>
+
+/** Android log tag. */
+#define TAG "libdimension"
/** Report internal errors in this file. */
-#define DMNSN_LOCAL_ERROR(str) \
- do { \
- fprintf(stderr, "Dimension ERROR: %s, %s:%u: %s\n", \
- DMNSN_FUNC, __FILE__, __LINE__, (str)); \
- abort(); \
+#define DMNSN_LOCAL_ERROR(str) \
+ do { \
+ __android_log_print(ANDROID_LOG_ERROR, TAG, \
+ "Dimension ERROR: %s, %s:%u: %s\n", \
+ DMNSN_FUNC, __FILE__, __LINE__, (str)); \
+ abort(); \
} while (0)
/** dmnsn_local_lock_mutex implementation. */
@@ -89,18 +94,19 @@ dmnsn_report_error(bool die, const char *func, const char *file,
dmnsn_local_unlock_mutex(&dmnsn_always_die_mutex);
/* Print the diagnostic string */
- fprintf(stderr, "Dimension %s: %s, %s:%u: %s\n",
- die ? "ERROR" : "WARNING", func, file, line, str);
+ __android_log_print(ANDROID_LOG_ERROR, TAG,
+ "Dimension %s: %s, %s:%u: %s\n",
+ die ? "ERROR" : "WARNING", func, file, line, str);
/* Print the value of errno */
if (err != 0) {
- fprintf(stderr, "Last error: %d", err);
+ __android_log_print(ANDROID_LOG_ERROR, TAG, "Last error: %d", err);
#if DMNSN_SYS_ERRLIST
if (err >= 0 && err < sys_nerr) {
- fprintf(stderr, " (%s)", sys_errlist[err]);
+ __android_log_print(ANDROID_LOG_ERROR, TAG, " (%s)", sys_errlist[err]);
}
#endif
- fprintf(stderr, "\n");
+ __android_log_print(ANDROID_LOG_ERROR, TAG, "\n");
}
/* Print a stack trace to standard error */
diff --git a/libdimension/future.c b/libdimension/future.c
index c328815..437b490 100644
--- a/libdimension/future.c
+++ b/libdimension/future.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * Copyright (C) 2009-2012 Tavian Barnes <tavianator@tavianator.com> *
* *
* This file is part of The Dimension Library. *
* *
@@ -61,7 +61,7 @@ dmnsn_future_join(dmnsn_future *future)
if (future) {
/* Get the thread's return value */
dmnsn_join_thread(future->thread, &ptr);
- if (ptr && ptr != PTHREAD_CANCELED) {
+ if (ptr) {
retval = *(int *)ptr;
dmnsn_free(ptr);
}
@@ -89,7 +89,7 @@ dmnsn_future_join(dmnsn_future *future)
void
dmnsn_future_cancel(dmnsn_future *future)
{
- pthread_cancel(future->thread);
+ dmnsn_error("Thread cancellation not supported on Android.");
}
/* Get the current progress of the worker thread, in [0.0, 1.0] */
@@ -133,11 +133,6 @@ dmnsn_future_set_total(dmnsn_future *future, size_t total)
void
dmnsn_future_increment(dmnsn_future *future)
{
- /* Allow a thread to be canceled whenever it increments a future object --
- this is close to PTHREAD_CANCEL_ASYNCHRONOUS but allows consistent state
- on cancellation */
- pthread_testcancel();
-
dmnsn_write_lock(future->rwlock);
++future->progress;
dmnsn_unlock_rwlock(future->rwlock);
diff --git a/libdimension/platform.c b/libdimension/platform.c
index a27343d..b4efa09 100644
--- a/libdimension/platform.c
+++ b/libdimension/platform.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * Copyright (C) 2010-2012 Tavian Barnes <tavianator@tavianator.com> *
* *
* This file is part of The Dimension Library. *
* *
@@ -67,6 +67,8 @@ dmnsn_is_main_thread(void)
{
#if DMNSN_GETTID
return getpid() == syscall(SYS_gettid);
+#elif DMNSN_GETTID_DIRECT
+ return getpid() == gettid();
#else
return true;
#endif
diff --git a/libdimension/threads.c b/libdimension/threads.c
index 0aed16d..5dce26c 100644
--- a/libdimension/threads.c
+++ b/libdimension/threads.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * Copyright (C) 2010-2012 Tavian Barnes <tavianator@tavianator.com> *
* *
* This file is part of The Dimension Library. *
* *
@@ -102,12 +102,6 @@ dmnsn_ccthread_cleanup(void *ptr)
for (unsigned int i = 0; i < payload->nthreads; ++i) {
if (payload->payloads[i].started) {
- pthread_cancel(payload->threads[i]);
- }
- }
-
- for (unsigned int i = 0; i < payload->nthreads; ++i) {
- if (payload->payloads[i].started) {
dmnsn_join_thread(payload->threads[i], NULL);
}
}
diff --git a/proguard-project.txt b/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/project.properties b/project.properties
new file mode 100644
index 0000000..9b84a6b
--- /dev/null
+++ b/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-ldpi/ic_launcher.png b/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/res/layout/main.xml b/res/layout/main.xml
new file mode 100644
index 0000000..00a3579
--- /dev/null
+++ b/res/layout/main.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <com.tavianator.dimension.android.RaytracedView
+ android:id="@+id/main_raytraced"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</FrameLayout> \ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644
index 0000000..0b689d1
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">Dimension</string>
+</resources>
diff --git a/src/com/tavianator/dimension/android/DimensionActivity.java b/src/com/tavianator/dimension/android/DimensionActivity.java
new file mode 100644
index 0000000..60a6f21
--- /dev/null
+++ b/src/com/tavianator/dimension/android/DimensionActivity.java
@@ -0,0 +1,36 @@
+/*************************************************************************
+ * 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.app.Activity;
+import android.os.Bundle;
+
+/**
+ * @author Tavian Barnes <tavianator@tavianator.com>
+ * @version 1.0
+ * @since 1.0
+ */
+public class DimensionActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+}
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;
+ }
+}