diff options
author | Alex Sakhartchouk <alexst@google.com> | 2011-12-08 11:39:14 -0800 |
---|---|---|
committer | Alex Sakhartchouk <alexst@google.com> | 2011-12-08 11:39:14 -0800 |
commit | a7a211b8a68a7d3f5ff4409aa286db07f96c0550 (patch) | |
tree | 411b4721ebb7e42aca30b415b11ec1b9f6893509 /tests/RenderScriptTests/SceneGraph/src | |
parent | 8030bfd9c8956bd94ccda5ee4643a4c375338303 (diff) | |
download | frameworks_base-a7a211b8a68a7d3f5ff4409aa286db07f96c0550.zip frameworks_base-a7a211b8a68a7d3f5ff4409aa286db07f96c0550.tar.gz frameworks_base-a7a211b8a68a7d3f5ff4409aa286db07f96c0550.tar.bz2 |
Sample scene graph
Change-Id: I65b210b770121ac02c5857b48d2ec0d053133dd6
Diffstat (limited to 'tests/RenderScriptTests/SceneGraph/src')
32 files changed, 4243 insertions, 0 deletions
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Camera.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Camera.java new file mode 100644 index 0000000..d220df9 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Camera.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.Matrix4f; +import android.renderscript.RenderScriptGL; +import android.renderscript.*; +import android.util.Log; + +/** + * @hide + */ +public class Camera extends SceneGraphBase { + + Transform mTransform; + float mFOV; + float mNear; + float mFar; + + ScriptField_Camera_s mField; + + public Camera() { + mFOV = 60.0f; + mNear = 0.1f; + mFar = 100.0f; + } + + public void setTransform(Transform t) { + mTransform = t; + } + public void setFOV(float fov) { + mFOV = fov; + } + + public void setNear(float n) { + mNear = n; + } + + public void setFar(float f) { + mFar = f; + } + + ScriptField_Camera_s getRSData(RenderScriptGL rs) { + if (mField != null) { + return mField; + } + + mField = new ScriptField_Camera_s(rs, 1); + ScriptField_Camera_s.Item cam = new ScriptField_Camera_s.Item(); + cam.horizontalFOV = mFOV; + cam.near = mNear; + cam.far = mFar; + cam.transformMatrix = mTransform.getRSData(rs).getAllocation(); + cam.name = getStringAsAllocation(rs, getName()); + mField.set(cam, 0, true); + + return mField; + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaParser.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaParser.java new file mode 100644 index 0000000..c7caf8d --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaParser.java @@ -0,0 +1,528 @@ +/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.scenegraph;
+import com.android.scenegraph.CompoundTransform.TranslateComponent;
+import com.android.scenegraph.CompoundTransform.RotateComponent;
+import com.android.scenegraph.CompoundTransform.ScaleComponent;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.HashMap;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import android.renderscript.*;
+import android.util.Log;
+
+public class ColladaParser {
+ static final String TAG = "ColladaParser";
+ Document mDom;
+
+ HashMap<String, LightBase> mLights;
+ HashMap<String, Camera> mCameras;
+ HashMap<String, ArrayList<ShaderParam> > mEffectsParams;
+ HashMap<String, Texture2D> mImages;
+ HashMap<String, Texture2D> mSamplerImageMap;
+ Scene mScene;
+
+ String toString(Float3 v) {
+ String valueStr = v.x + " " + v.y + " " + v.z;
+ return valueStr;
+ }
+
+ String toString(Float4 v) {
+ String valueStr = v.x + " " + v.y + " " + v.z + " " + v.w;
+ return valueStr;
+ }
+
+ public ColladaParser(){
+ mLights = new HashMap<String, LightBase>();
+ mCameras = new HashMap<String, Camera>();
+ mEffectsParams = new HashMap<String, ArrayList<ShaderParam> >();
+ mImages = new HashMap<String, Texture2D>();
+ }
+
+ public void init(InputStream is) {
+ mLights.clear();
+ mCameras.clear();
+ mEffectsParams.clear();
+
+ long start = System.currentTimeMillis();
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ try {
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ mDom = db.parse(is);
+ } catch(ParserConfigurationException e) {
+ e.printStackTrace();
+ } catch(SAXException e) {
+ e.printStackTrace();
+ } catch(IOException e) {
+ e.printStackTrace();
+ }
+ long end = System.currentTimeMillis();
+ Log.v("TIMER", " Parse time: " + (end - start));
+ exportSceneData();
+ }
+
+ Scene getScene() {
+ return mScene;
+ }
+
+ private void exportSceneData(){
+ mScene = new Scene();
+
+ Element docEle = mDom.getDocumentElement();
+ NodeList nl = docEle.getElementsByTagName("light");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element l = (Element)nl.item(i);
+ convertLight(l);
+ }
+ }
+
+ nl = docEle.getElementsByTagName("camera");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element c = (Element)nl.item(i);
+ convertCamera(c);
+ }
+ }
+
+ nl = docEle.getElementsByTagName("image");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element img = (Element)nl.item(i);
+ convertImage(img);
+ }
+ }
+
+ nl = docEle.getElementsByTagName("effect");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element e = (Element)nl.item(i);
+ convertEffects(e);
+ }
+ }
+
+ // Material is just a link to the effect
+ nl = docEle.getElementsByTagName("material");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element m = (Element)nl.item(i);
+ convertMaterials(m);
+ }
+ }
+
+ nl = docEle.getElementsByTagName("visual_scene");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element s = (Element)nl.item(i);
+ getScene(s);
+ }
+ }
+ }
+
+ private void getDrawable(Element shape, Transform t) {
+ String geoURL = shape.getAttribute("url");
+ //DrawableGroup group = new DrawableGroup();
+ //group.setName(geoURL.substring(1));
+ //mScene.appendDrawable(group);
+ NodeList nl = shape.getElementsByTagName("instance_material");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element materialRef = (Element)nl.item(i);
+ String meshIndexName = materialRef.getAttribute("symbol");
+ String materialName = materialRef.getAttribute("target");
+
+ Drawable d = new Drawable();
+ d.setMesh(geoURL.substring(1), meshIndexName);
+ d.setMaterialName(materialName);
+ d.setName(geoURL.substring(1));
+
+ //Log.v(TAG, "Created drawable geo " + geoURL + " index " + meshIndexName + " material " + materialName);
+
+ // Append transform and material data here
+ TransformParam modelP = new TransformParam("model");
+ modelP.setTransform(t);
+ d.appendSourceParams(modelP);
+ d.setTransform(t);
+ //Log.v(TAG, "Set source param " + t.getName());
+
+ // Now find all the parameters that exist on the material
+ ArrayList<ShaderParam> materialParams;
+ materialParams = mEffectsParams.get(materialName.substring(1));
+ for (int pI = 0; pI < materialParams.size(); pI ++) {
+ d.appendSourceParams(materialParams.get(pI));
+ //Log.v(TAG, "Set source param i: " + pI + " name " + materialParams.get(pI).getParamName());
+ }
+ mScene.appendDrawable(d);
+ //group.appendChildren(d);
+ }
+ }
+ }
+
+ private void updateLight(Element shape, Transform t) {
+ String lightURL = shape.getAttribute("url");
+ // collada uses a uri structure to link things,
+ // but we ignore it for now and do a simple search
+ LightBase light = mLights.get(lightURL.substring(1));
+ if (light != null) {
+ light.setTransform(t);
+ //Log.v(TAG, "Set Light " + light.getName() + " " + t.getName());
+ }
+ }
+
+ private void updateCamera(Element shape, Transform t) {
+ String camURL = shape.getAttribute("url");
+ // collada uses a uri structure to link things,
+ // but we ignore it for now and do a simple search
+ Camera cam = mCameras.get(camURL.substring(1));
+ if (cam != null) {
+ cam.setTransform(t);
+ //Log.v(TAG, "Set Camera " + cam.getName() + " " + t.getName());
+ }
+ }
+
+ private void getNode(Element node, Transform parent, String indent) {
+ String name = node.getAttribute("name");
+ String id = node.getAttribute("id");
+ CompoundTransform current = new CompoundTransform();
+ current.setName(name);
+ if (parent != null) {
+ parent.appendChild(current);
+ } else {
+ mScene.appendTransform(current);
+ }
+
+ mScene.addToTransformMap(current);
+
+ //Log.v(TAG, indent + "|");
+ //Log.v(TAG, indent + "[" + name + "]");
+
+ Node childNode = node.getFirstChild();
+ while (childNode != null) {
+ if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element field = (Element)childNode;
+ String fieldName = field.getTagName();
+ String description = field.getAttribute("sid");
+ if (fieldName.equals("translate")) {
+ Float3 value = getFloat3(field);
+ current.addComponent(new TranslateComponent(description, value));
+ //Log.v(TAG, indent + " translate " + description + toString(value));
+ } else if (fieldName.equals("rotate")) {
+ Float4 value = getFloat4(field);
+ //Log.v(TAG, indent + " rotate " + description + toString(value));
+ Float3 axis = new Float3(value.x, value.y, value.z);
+ current.addComponent(new RotateComponent(description, axis, value.w));
+ } else if (fieldName.equals("scale")) {
+ Float3 value = getFloat3(field);
+ //Log.v(TAG, indent + " scale " + description + toString(value));
+ current.addComponent(new ScaleComponent(description, value));
+ } else if (fieldName.equals("instance_geometry")) {
+ getDrawable(field, current);
+ } else if (fieldName.equals("instance_light")) {
+ updateLight(field, current);
+ } else if (fieldName.equals("instance_camera")) {
+ updateCamera(field, current);
+ } else if (fieldName.equals("node")) {
+ getNode(field, current, indent + " ");
+ }
+ }
+ childNode = childNode.getNextSibling();
+ }
+ }
+
+ Texture2D getTexture(String samplerName) {
+ Element sampler = mDom.getElementById(samplerName);
+ if (sampler == null) {
+ return null;
+ }
+
+ NodeList nl = sampler.getElementsByTagName("source");
+ if (nl != null && nl.getLength() == 1) {
+ Element ref = (Element)nl.item(0);
+ String surfaceName = getString(ref);
+ if (surfaceName == null) {
+ return null;
+ }
+
+ Element surface = mDom.getElementById(surfaceName);
+ if (surface == null) {
+ return null;
+ }
+ nl = surface.getElementsByTagName("init_from");
+ if (nl != null && nl.getLength() == 1) {
+ ref = (Element)nl.item(0);
+ String texName = getString(ref);
+ //Log.v(TAG, "Extracted texture name " + texName);
+ return mImages.get(texName);
+ }
+ }
+ return null;
+ }
+
+ void extractParams(Element fx, ArrayList<ShaderParam> params) {
+ Node paramNode = fx.getFirstChild();
+ while (paramNode != null) {
+ if (paramNode.getNodeType() == Node.ELEMENT_NODE) {
+ String name = paramNode.getNodeName();
+ // Now find what type it is
+ Node typeNode = paramNode.getFirstChild();
+ while (typeNode != null && typeNode.getNodeType() != Node.ELEMENT_NODE) {
+ typeNode = typeNode.getNextSibling();
+ }
+ String paramType = typeNode.getNodeName();
+ Element typeElem = (Element)typeNode;
+ ShaderParam sceneParam = null;
+ if (paramType.equals("color")) {
+ Float4Param f4p = new Float4Param(name);
+ Float4 value = getFloat4(typeElem);
+ f4p.setValue(value);
+ sceneParam = f4p;
+ //Log.v(TAG, "Extracted " + sceneParam.getParamName() + " value " + toString(value));
+ } else if (paramType.equals("float")) {
+ Float4Param f4p = new Float4Param(name);
+ float value = getFloat(typeElem);
+ f4p.setValue(new Float4(value, value, value, value));
+ sceneParam = f4p;
+ //Log.v(TAG, "Extracted " + sceneParam.getParamName() + " value " + value);
+ } else if (paramType.equals("texture")) {
+ String samplerName = typeElem.getAttribute("texture");
+ Texture2D tex = getTexture(samplerName);
+ TextureParam texP = new TextureParam(name);
+ texP.setTexture(tex);
+ sceneParam = texP;
+ //Log.v(TAG, "Extracted texture " + tex);
+ }
+ if (sceneParam != null) {
+ params.add(sceneParam);
+ }
+ }
+ paramNode = paramNode.getNextSibling();
+ }
+ }
+
+ private void convertMaterials(Element mat) {
+ String id = mat.getAttribute("id");
+ NodeList nl = mat.getElementsByTagName("instance_effect");
+ if (nl != null && nl.getLength() == 1) {
+ Element ref = (Element)nl.item(0);
+ String url = ref.getAttribute("url");
+ ArrayList<ShaderParam> params = mEffectsParams.get(url.substring(1));
+ mEffectsParams.put(id, params);
+ }
+ }
+
+ private void convertEffects(Element fx) {
+ String id = fx.getAttribute("id");
+ ArrayList<ShaderParam> params = new ArrayList<ShaderParam>();
+
+ NodeList nl = fx.getElementsByTagName("newparam");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element field = (Element)nl.item(i);
+ field.setIdAttribute("sid", true);
+ }
+ }
+
+ nl = fx.getElementsByTagName("blinn");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element field = (Element)nl.item(i);
+ //Log.v(TAG, "blinn");
+ extractParams(field, params);
+ }
+ }
+ nl = fx.getElementsByTagName("lambert");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element field = (Element)nl.item(i);
+ //Log.v(TAG, "lambert");
+ extractParams(field, params);
+ }
+ }
+ nl = fx.getElementsByTagName("phong");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element field = (Element)nl.item(i);
+ //Log.v(TAG, "phong");
+ extractParams(field, params);
+ }
+ }
+ mEffectsParams.put(id, params);
+ }
+
+ private void convertLight(Element light) {
+ String name = light.getAttribute("name");
+ String id = light.getAttribute("id");
+
+ // Determine type
+ String[] knownTypes = { "point", "spot", "directional" };
+ final int POINT_LIGHT = 0;
+ final int SPOT_LIGHT = 1;
+ final int DIR_LIGHT = 2;
+ int type = -1;
+ for (int i = 0; i < knownTypes.length; i ++) {
+ NodeList nl = light.getElementsByTagName(knownTypes[i]);
+ if (nl != null && nl.getLength() != 0) {
+ type = i;
+ break;
+ }
+ }
+
+ //Log.v(TAG, "Found Light Type " + type);
+
+ LightBase sceneLight = null;
+ switch (type) {
+ case POINT_LIGHT:
+ sceneLight = new PointLight();
+ break;
+ case SPOT_LIGHT: // TODO: finish light types
+ break;
+ case DIR_LIGHT: // TODO: finish light types
+ break;
+ }
+
+ if (sceneLight == null) {
+ return;
+ }
+
+ Float3 color = getFloat3(light, "color");
+ sceneLight.setColor(color);
+ sceneLight.setName(name);
+ mScene.appendLight(sceneLight);
+ mLights.put(id, sceneLight);
+
+ //Log.v(TAG, "Light " + name + " color " + toString(color));
+ }
+
+ private void convertCamera(Element camera) {
+ String name = camera.getAttribute("name");
+ String id = camera.getAttribute("id");
+ float fov = getFloat(camera, "yfov");
+ float near = getFloat(camera, "znear");
+ float far = getFloat(camera, "zfar");
+
+ Camera sceneCamera = new Camera();
+ sceneCamera.setFOV(fov);
+ sceneCamera.setNear(near);
+ sceneCamera.setFar(far);
+ sceneCamera.setName(name);
+ mScene.appendCamera(sceneCamera);
+ mCameras.put(id, sceneCamera);
+ }
+
+ private void convertImage(Element img) {
+ String name = img.getAttribute("name");
+ String id = img.getAttribute("id");
+ String file = getString(img, "init_from");
+
+ Texture2D tex = new Texture2D();
+ tex.setFileName(file);
+ mScene.appendTextures(tex);
+ mImages.put(id, tex);
+ }
+
+ private void getScene(Element scene) {
+ String name = scene.getAttribute("name");
+ String id = scene.getAttribute("id");
+
+ Node childNode = scene.getFirstChild();
+ while (childNode != null) {
+ if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+ String indent = "";
+ getNode((Element)childNode, null, indent);
+ }
+ childNode = childNode.getNextSibling();
+ }
+ }
+
+ private String getString(Element elem, String name) {
+ String text = null;
+ NodeList nl = elem.getElementsByTagName(name);
+ if (nl != null) {
+ text = ((Element)nl.item(0)).getFirstChild().getNodeValue();
+ }
+ return text;
+ }
+
+ private String getString(Element elem) {
+ String text = null;
+ text = elem.getFirstChild().getNodeValue();
+ return text;
+ }
+
+ private int getInt(Element elem, String name) {
+ return Integer.parseInt(getString(elem, name));
+ }
+
+ private float getFloat(Element elem, String name) {
+ return Float.parseFloat(getString(elem, name));
+ }
+
+ private float getFloat(Element elem) {
+ return Float.parseFloat(getString(elem));
+ }
+
+ private Float3 parseFloat3(String valueString) {
+ StringTokenizer st = new StringTokenizer(valueString);
+ float x = Float.parseFloat(st.nextToken());
+ float y = Float.parseFloat(st.nextToken());
+ float z = Float.parseFloat(st.nextToken());
+ return new Float3(x, y, z);
+ }
+
+ private Float4 parseFloat4(String valueString) {
+ StringTokenizer st = new StringTokenizer(valueString);
+ float x = Float.parseFloat(st.nextToken());
+ float y = Float.parseFloat(st.nextToken());
+ float z = Float.parseFloat(st.nextToken());
+ float w = Float.parseFloat(st.nextToken());
+ return new Float4(x, y, z, w);
+ }
+
+ private Float3 getFloat3(Element elem, String name) {
+ String valueString = getString(elem, name);
+ return parseFloat3(valueString);
+ }
+
+ private Float4 getFloat4(Element elem, String name) {
+ String valueString = getString(elem, name);
+ return parseFloat4(valueString);
+ }
+
+ private Float3 getFloat3(Element elem) {
+ String valueString = getString(elem);
+ return parseFloat3(valueString);
+ }
+
+ private Float4 getFloat4(Element elem) {
+ String valueString = getString(elem);
+ return parseFloat4(valueString);
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaScene.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaScene.java new file mode 100644 index 0000000..9394b66 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaScene.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.AsyncTask; +import android.renderscript.*; +import android.renderscript.Allocation.MipmapControl; +import android.renderscript.Element.Builder; +import android.renderscript.Font.Style; +import android.renderscript.Program.TextureType; +import android.renderscript.ProgramStore.DepthFunc; +import android.util.Log; +import com.android.scenegraph.SceneManager.SceneLoadedCallback; + + +public class ColladaScene { + + private String modelName; + private static String TAG = "ColladaScene"; + private final int STATE_LAST_FOCUS = 1; + private final boolean mLoadFromSD = true; + private static String mSDCardPath = "sdcard/scenegraph/"; + + SceneGraphRS mRenderer; + SceneLoadedCallback mCallback; + + public ColladaScene(String name, SceneGraphRS renderer) { + modelName = name; + mRenderer = renderer; + } + + public ColladaScene(String name, SceneLoadedCallback cb) { + modelName = name; + mCallback = cb; + } + + public void init(RenderScriptGL rs, Resources res) { + mRS = rs; + mRes = res; + + new ColladaLoaderTask().execute(modelName + ".dae"); + } + + private Resources mRes; + private RenderScriptGL mRS; + Scene mActiveScene; + + private class ColladaLoaderTask extends AsyncTask<String, Void, Boolean> { + ColladaParser sceneSource; + protected Boolean doInBackground(String... names) { + long start = System.currentTimeMillis(); + sceneSource = new ColladaParser(); + InputStream is = null; + try { + if (!mLoadFromSD) { + is = mRes.getAssets().open(names[0]); + } else { + File f = new File(mSDCardPath + names[0]); + is = new BufferedInputStream(new FileInputStream(f)); + } + } catch (IOException e) { + Log.e(TAG, "Could not open collada file"); + return new Boolean(false); + } + long end = System.currentTimeMillis(); + Log.v("TIMER", "Stream load time: " + (end - start)); + + start = System.currentTimeMillis(); + sceneSource.init(is); + end = System.currentTimeMillis(); + Log.v("TIMER", "Collada parse time: " + (end - start)); + return new Boolean(true); + } + + protected void onPostExecute(Boolean result) { + mActiveScene = sceneSource.getScene(); + if (mRenderer != null) { + mRenderer.prepareToRender(mActiveScene); + } + if (mCallback != null) { + mCallback.mLoadedScene = mActiveScene; + mCallback.run(); + } + + new A3DLoaderTask().execute(modelName + ".a3d"); + } + } + + private class A3DLoaderTask extends AsyncTask<String, Void, Boolean> { + protected Boolean doInBackground(String... names) { + long start = System.currentTimeMillis(); + FileA3D model; + if (!mLoadFromSD) { + model = FileA3D.createFromAsset(mRS, mRes.getAssets(), names[0]); + } else { + model = FileA3D.createFromFile(mRS, mSDCardPath + names[0]); + } + int numModels = model.getIndexEntryCount(); + for (int i = 0; i < numModels; i ++) { + FileA3D.IndexEntry entry = model.getIndexEntry(i); + if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) { + mActiveScene.meshLoaded(entry.getMesh()); + } + } + long end = System.currentTimeMillis(); + Log.v("TIMER", "A3D load time: " + (end - start)); + return new Boolean(true); + } + + protected void onPostExecute(Boolean result) { + } + } + +} + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/CompoundTransform.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/CompoundTransform.java new file mode 100644 index 0000000..0de6ba2 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/CompoundTransform.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.*; +import android.renderscript.Float3; +import android.renderscript.Matrix4f; +import android.util.Log; + +/** + * @hide + */ +public class CompoundTransform extends Transform { + + public static class Component { + String mName; + int mRsId; + public Float4 mValue; + + public String getName() { + return mName; + } + } + + public static class TranslateComponent extends Component { + public TranslateComponent(String name, Float3 translate) { + mRsId = RS_ID_TRANSLATE; + mName = name; + mValue = new Float4(translate.x, translate.y, translate.z, 0); + } + } + + public static class RotateComponent extends Component { + public RotateComponent(String name, Float3 axis, float angle) { + mRsId = RS_ID_ROTATE; + mName = name; + mValue = new Float4(axis.x, axis.y, axis.z, angle); + } + } + + public static class ScaleComponent extends Component { + public ScaleComponent(String name, Float3 scale) { + mRsId = RS_ID_SCALE; + mName = name; + mValue = new Float4(scale.x, scale.y, scale.z, 0); + } + } + + public ArrayList<Component> mTransformComponents; + + Matrix4f mLocalMatrix; + Matrix4f mGlobalMatrix; + + public CompoundTransform() { + mTransformComponents = new ArrayList<Component>(); + } + + public void addComponent(Component c) { + mTransformComponents.add(c); + } + + public void setComponent(int index, Component c) { + mTransformComponents.set(index, c); + } + + void initLocalData() { + mTransformData = new ScriptField_SgTransform.Item(); + int numElements = mTransformComponents.size(); + for (int i = 0; i < numElements; i ++) { + Component ith = mTransformComponents.get(i); + mTransformData.transforms[i] = ith.mValue; + mTransformData.transformTypes[i] = ith.mRsId; + mTransformData.transformNames[i] = getStringAsAllocation(mRS, ith.mName); + } + // "null" terminate the array + mTransformData.transformTypes[numElements] = RS_ID_NONE; + + mTransformData.isDirty = 1; + mTransformData.children = null; + mTransformData.name = getStringAsAllocation(mRS, getName()); + } + + public void updateRSData() { + int numElements = mTransformComponents.size(); + for (int i = 0; i < numElements; i ++) { + Component ith = mTransformComponents.get(i); + mTransformData.transforms[i] = ith.mValue; + mTransformData.transformTypes[i] = ith.mRsId; + mTransformData.transformNames[i] = getStringAsAllocation(mRS, ith.mName); + } + // "null" terminate the array + mTransformData.transformTypes[numElements] = RS_ID_NONE; + mTransformData.isDirty = 1; + mField.set(mTransformData, 0, true); + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Drawable.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Drawable.java new file mode 100644 index 0000000..2eaca13 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Drawable.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; +import java.util.HashMap; + +import android.renderscript.Allocation; +import android.renderscript.Matrix4f; +import android.renderscript.Mesh; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.renderscript.RenderScriptGL; +import android.util.Log; +import android.content.res.Resources; + +/** + * @hide + */ +public class Drawable extends DrawableBase { + Allocation mVertexParams; + Allocation mFragmentParams; + ArrayList<Allocation> mFragmentTextures; + ArrayList<ShaderParam> mVertexParam; + ArrayList<ShaderParam> mFragmentParam; + ArrayList<ShaderParam> mSourceParams; + Mesh mMesh; + int mMeshIndex; + + int mCullType; + + RenderState mRenderState; + + Transform mTransform; + + String mMeshName; + String mMeshIndexName; + + public String mMaterialName; + + // quick hack to prototype + int sceneIndex; + + ScriptField_Drawable_s mRsField; + ScriptField_Drawable_s.Item mRsFieldItem; + + public Drawable() { + mSourceParams = new ArrayList<ShaderParam>(); + } + + public void setCullType(int cull) { + mCullType = cull; + } + + public void setRenderState(RenderState renderState) { + mRenderState = renderState; + } + + public void setMesh(Mesh mesh) { + mMesh = mesh; + } + + public void setMesh(String mesh, String indexName) { + mMeshName = mesh; + mMeshIndexName = indexName; + } + + public void setMaterialName(String name) { + mMaterialName = name; + } + + public void setTransform(Transform t) { + mTransform = t; + } + + public void appendSourceParams(ShaderParam p) { + mSourceParams.add(p); + } + + public void resolveMeshData(Mesh mMesh) { + mMesh = mMesh; + if (mMesh == null) { + Log.v("DRAWABLE: ", "*** NO MESH *** " + mMeshName); + return; + } + int subIndexCount = mMesh.getPrimitiveCount(); + if (subIndexCount == 1 || mMeshIndexName == null) { + mMeshIndex = 0; + } else { + for (int i = 0; i < subIndexCount; i ++) { + if (mMesh.getIndexSetAllocation(i).getName().equals(mMeshIndexName)) { + mMeshIndex = i; + break; + } + } + } + + mRsFieldItem.mesh = mMesh; + mRsFieldItem.meshIndex = mMeshIndex; + + mRsField.set(mRsFieldItem, 0, true); + } + + void updateTextures(RenderScriptGL rs, Resources res) { + for (int i = 0; i < mSourceParams.size(); i ++) { + ShaderParam sp = mSourceParams.get(i); + if (sp instanceof TextureParam) { + TextureParam p = (TextureParam)sp; + mRsFieldItem.pf_textures[0] = p.getTexture().getRsData(rs, res); + break; + } + } + mRsField.set(mRsFieldItem, 0, true); + } + + void updateTextures(RenderScriptGL rs, Allocation a, int slot) { + getRsFieldItem(rs, null); + mRsFieldItem.pf_textures[slot] = a; + } + + void setVisible(RenderScriptGL rs, boolean vis) { + getRsField(rs, null); + mRsFieldItem.cullType = vis ? 0 : 2; + mRsField.set(mRsFieldItem, 0, true); + } + + ScriptField_Drawable_s getRsField(RenderScriptGL rs, Resources res) { + if (mRsField != null) { + return mRsField; + } + getRsFieldItem(rs, res); + + mRsField = new ScriptField_Drawable_s(rs, 1); + mRsField.set(mRsFieldItem, 0, true); + + return mRsField; + } + + void getRsFieldItem(RenderScriptGL rs, Resources res) { + if (mRsFieldItem != null) { + return; + } + + mRsFieldItem = new ScriptField_Drawable_s.Item(); + mRsFieldItem.mesh = mMesh; + mRsFieldItem.meshIndex = mMeshIndex; + mRsFieldItem.pv_const = mVertexParams; + mRsFieldItem.pf_const = mFragmentParams; + if (mTransform != null) { + mRsFieldItem.transformMatrix = mTransform.getRSData(rs).getAllocation(); + } + mRsFieldItem.name = getStringAsAllocation(rs, getName()); + mRsFieldItem.render_state = mRenderState.getRSData(rs).getAllocation(); + mRsFieldItem.bVolInitialized = 0; + mRsFieldItem.cullType = mCullType; + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/DrawableBase.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/DrawableBase.java new file mode 100644 index 0000000..113ccd4 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/DrawableBase.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.Matrix4f; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.util.Log; + +/** + * @hide + */ +public class DrawableBase extends SceneGraphBase { + public DrawableBase() { + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/DrawableGroup.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/DrawableGroup.java new file mode 100644 index 0000000..ac44f0b --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/DrawableGroup.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.Matrix4f; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.util.Log; + +/** + * @hide + */ +public class DrawableGroup extends DrawableBase { + + ArrayList<DrawableBase> mChildren; + + public DrawableGroup() { + mChildren = new ArrayList<DrawableBase>(); + } + + public void appendChildren(DrawableBase d) { + mChildren.add(d); + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FileSelector.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FileSelector.java new file mode 100644 index 0000000..691b433 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FileSelector.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.io.File; +import java.io.FileFilter; +import java.util.ArrayList; +import java.util.List; + +import android.app.ListActivity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.ListView; + +/** + * A list view where the last item the user clicked is placed in + * the "activated" state, causing its background to highlight. + */ +public class FileSelector extends ListActivity { + + File[] mCurrentSubList; + File mCurrentFile; + + class DAEFilter implements FileFilter { + public boolean accept(File file) { + if (file.isDirectory()) { + return true; + } + return file.getName().endsWith(".dae"); + } + } + + private void populateList(File file) { + + mCurrentFile = file; + setTitle(mCurrentFile.getAbsolutePath() + "/*.dae"); + List<String> names = new ArrayList<String>(); + names.add(".."); + + mCurrentSubList = mCurrentFile.listFiles(new DAEFilter()); + + if (mCurrentSubList != null) { + for (int i = 0; i < mCurrentSubList.length; i ++) { + String fileName = mCurrentSubList[i].getName(); + if (mCurrentSubList[i].isDirectory()) { + fileName = "/" + fileName; + } + names.add(fileName); + } + } + + // Use the built-in layout for showing a list item with a single + // line of text whose background is changes when activated. + setListAdapter(new ArrayAdapter<String>(this, + android.R.layout.simple_list_item_activated_1, names)); + getListView().setTextFilterEnabled(true); + + // Tell the list view to show one checked/activated item at a time. + getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + populateList(new File("/sdcard/")); + } + + @Override + protected void onListItemClick(ListView l, View v, int position, long id) { + if (position == 0) { + File parent = mCurrentFile.getParentFile(); + if (parent == null) { + return; + } + populateList(parent); + return; + } + + // the first thing in list is parent directory + File selectedFile = mCurrentSubList[position - 1]; + if (selectedFile.isDirectory()) { + populateList(selectedFile); + return; + } + + Intent resultIntent = new Intent(); + resultIntent.setData(Uri.fromFile(selectedFile)); + setResult(RESULT_OK, resultIntent); + finish(); + } + +} diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Float4Param.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Float4Param.java new file mode 100644 index 0000000..b40db64 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Float4Param.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.graphics.Camera; +import android.renderscript.Float4; +import android.renderscript.Matrix4f; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.renderscript.Element; +import android.util.Log; + +/** + * @hide + */ +public class Float4Param extends ShaderParam { + + public static final int VALUE = 0; + public static final int CAMERA_POSITION = 1; + public static final int CAMERA_DIRECTION = 2; + public static final int LIGHT_POSITION = 3; + public static final int LIGHT_COLOR = 4; + public static final int LIGHT_DIRECTION = 5; + Float4 mValue; + Camera mCamera; + LightBase mLight; + + public Float4Param(String name) { + super(name); + } + + public void setValue(Float4 v) { + mValue = v; + } + + public Float4 getValue() { + return mValue; + } + + public void setCamera(Camera c) { + mCamera = c; + } + + public void setLight(LightBase l) { + mLight = l; + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/LightBase.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/LightBase.java new file mode 100644 index 0000000..7aad1f8 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/LightBase.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.Float3; +import android.renderscript.Matrix4f; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.util.Log; + +/** + * @hide + */ +public class LightBase extends SceneGraphBase { + Transform mTransform; + Float3 mColor; + float mIntensity; + public LightBase() { + mColor = new Float3(0.0f, 0.0f, 0.0f); + mIntensity = 1.0f; + } + + public void setTransform(Transform t) { + mTransform = t; + } + + public void setColor(Float3 c) { + mColor = c; + } + + public void setIntensity(float i) { + mIntensity = i; + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/MatrixTransform.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/MatrixTransform.java new file mode 100644 index 0000000..61f8ccc --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/MatrixTransform.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.Matrix4f; +import android.util.Log; + +/** + * @hide + */ +public class MatrixTransform extends Transform { + + Matrix4f mLocalMatrix; + public MatrixTransform() { + mLocalMatrix = new Matrix4f(); + } + + public void setMatrix(Matrix4f matrix) { + mLocalMatrix = matrix; + } + + void initLocalData() { + mTransformData = new ScriptField_SgTransform.Item(); + // "null" terminate the array + mTransformData.transformTypes[0] = RS_ID_NONE; + mTransformData.localMat = mLocalMatrix; + + mTransformData.isDirty = 1; + mTransformData.children = null; + mTransformData.name = getStringAsAllocation(mRS, getName()); + } + + public void updateRSData() { + mTransformData.localMat = mLocalMatrix; + mTransformData.isDirty = 1; + mField.set(mTransformData, 0, true); + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/PointLight.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/PointLight.java new file mode 100644 index 0000000..41a54c6 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/PointLight.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.Matrix4f; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.util.Log; + +/** + * @hide + */ +public class PointLight extends LightBase { + public PointLight() { + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderPass.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderPass.java new file mode 100644 index 0000000..0012b10 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderPass.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.util.Log; + +import android.renderscript.*; +import android.content.res.Resources; + +/** + * @hide + */ +public class RenderPass extends SceneGraphBase { + + Allocation mColorTarget; + Float4 mClearColor; + boolean mShouldClearColor; + + Allocation mDepthTarget; + float mClearDepth; + boolean mShouldClearDepth; + + ArrayList<DrawableBase> mObjectsToDraw; + + Camera mCamera; + + ScriptField_RenderPass_s.Item mRsField; + + public RenderPass() { + mObjectsToDraw = new ArrayList<DrawableBase>(); + mClearColor = new Float4(0.0f, 0.0f, 0.0f, 0.0f); + mShouldClearColor = true; + mClearDepth = 1.0f; + mShouldClearDepth = true; + } + + public void appendDrawable(Drawable d) { + mObjectsToDraw.add(d); + } + + public void setCamera(Camera c) { + mCamera = c; + } + + public void setColorTarget(Allocation colorTarget) { + mColorTarget = colorTarget; + } + public void setClearColor(Float4 clearColor) { + mClearColor = clearColor; + } + public void setShouldClearColor(boolean shouldClearColor) { + mShouldClearColor = shouldClearColor; + } + + public void setDepthTarget(Allocation depthTarget) { + mDepthTarget = depthTarget; + } + public void setClearDepth(float clearDepth) { + mClearDepth = clearDepth; + } + public void setShouldClearDepth(boolean shouldClearDepth) { + mShouldClearDepth = shouldClearDepth; + } + + ScriptField_RenderPass_s.Item getRsField(RenderScriptGL rs, Resources res) { + if (mRsField != null) { + return mRsField; + } + + mRsField = new ScriptField_RenderPass_s.Item(); + mRsField.color_target = mColorTarget; + mRsField.depth_target = mDepthTarget; + mRsField.camera = mCamera != null ? mCamera.getRSData(rs).getAllocation() : null; + + if (mObjectsToDraw.size() != 0) { + Allocation drawableData = Allocation.createSized(rs, + Element.ALLOCATION(rs), + mObjectsToDraw.size()); + Allocation[] drawableAllocs = new Allocation[mObjectsToDraw.size()]; + for (int i = 0; i < mObjectsToDraw.size(); i ++) { + Drawable dI = (Drawable)mObjectsToDraw.get(i); + drawableAllocs[i] = dI.getRsField(rs, res).getAllocation(); + } + drawableData.copyFrom(drawableAllocs); + mRsField.objects = drawableData; + } + + mRsField.clear_color = mClearColor; + mRsField.clear_depth = mClearDepth; + mRsField.should_clear_color = mShouldClearColor; + mRsField.should_clear_depth = mShouldClearDepth; + return mRsField; + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderState.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderState.java new file mode 100644 index 0000000..e8aec95 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderState.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.Matrix4f; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramRaster; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.renderscript.RSRuntimeException; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; +import android.util.Log; + +/** + * @hide + */ +public class RenderState extends SceneGraphBase { + ProgramVertex mVertex; + ProgramFragment mFragment; + ProgramStore mStore; + ProgramRaster mRaster; + + ScriptField_RenderState_s mField; + + public RenderState(ProgramVertex pv, + ProgramFragment pf, + ProgramStore ps, + ProgramRaster pr) { + mVertex = pv; + mFragment = pf; + mStore = ps; + mRaster = pr; + } + + public RenderState(RenderState r) { + mVertex = r.mVertex; + mFragment = r.mFragment; + mStore = r.mStore; + mRaster = r.mRaster; + } + + public void setProgramVertex(ProgramVertex pv) { + mVertex = pv; + } + + public void setProgramFragment(ProgramFragment pf) { + mFragment = pf; + } + + public void setProgramStore(ProgramStore ps) { + mStore = ps; + } + + public void setProgramRaster(ProgramRaster pr) { + mRaster = pr; + } + + public ScriptField_RenderState_s getRSData(RenderScriptGL rs) { + if (mField != null) { + return mField; + } + + ScriptField_RenderState_s.Item item = new ScriptField_RenderState_s.Item(); + item.pv = mVertex; + item.pf = mFragment; + item.ps = mStore; + item.pr = mRaster; + + mField = new ScriptField_RenderState_s(rs, 1); + mField.set(item, 0, true); + return mField; + } +} diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java new file mode 100644 index 0000000..b1ae365 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import android.renderscript.RenderScriptGL; +import android.renderscript.Mesh; +import android.renderscript.*; +import android.content.res.Resources; +import android.util.Log; +import android.os.AsyncTask; + +/** + * @hide + */ +public class Scene extends SceneGraphBase { + private static String TIMER_TAG = "TIMER"; + + private class ImageLoaderTask extends AsyncTask<String, Void, Boolean> { + protected Boolean doInBackground(String... names) { + long start = System.currentTimeMillis(); + for (int i = 0; i < mDrawables.size(); i ++) { + Drawable dI = (Drawable)mDrawables.get(i); + dI.updateTextures(mRS, mRes); + } + long end = System.currentTimeMillis(); + Log.v(TIMER_TAG, "Texture init time: " + (end - start)); + return new Boolean(true); + } + + protected void onPostExecute(Boolean result) { + } + } + + CompoundTransform mRootTransforms; + HashMap<String, Transform> mTransformMap; + ArrayList<RenderPass> mRenderPasses; + ArrayList<LightBase> mLights; + ArrayList<Camera> mCameras; + ArrayList<DrawableBase> mDrawables; + HashMap<String, DrawableBase> mDrawableMap; + ArrayList<Texture2D> mTextures; + + HashMap<String, ArrayList<Drawable> > mDrawableMeshMap; + + // RS Specific stuff + ScriptField_SgTransform mTransformRSData; + + RenderScriptGL mRS; + Resources mRes; + + ScriptField_RenderPass_s mRenderPassAlloc; + + public Scene() { + mRenderPasses = new ArrayList<RenderPass>(); + mLights = new ArrayList<LightBase>(); + mCameras = new ArrayList<Camera>(); + mDrawables = new ArrayList<DrawableBase>(); + mDrawableMap = new HashMap<String, DrawableBase>(); + mDrawableMeshMap = new HashMap<String, ArrayList<Drawable> >(); + mTextures = new ArrayList<Texture2D>(); + mRootTransforms = new CompoundTransform(); + mRootTransforms.setName("_scene_root_"); + mTransformMap = new HashMap<String, Transform>(); + } + + public void appendTransform(Transform t) { + mRootTransforms.appendChild(t); + } + + // temporary + public void addToTransformMap(Transform t) { + mTransformMap.put(t.getName(), t); + } + + public Transform getTransformByName(String name) { + return mTransformMap.get(name); + } + + public void appendRenderPass(RenderPass p) { + mRenderPasses.add(p); + } + + public void clearRenderPasses() { + mRenderPasses.clear(); + } + + public void appendLight(LightBase l) { + mLights.add(l); + } + + public void appendCamera(Camera c) { + mCameras.add(c); + } + + public ArrayList<Camera> getCameras() { + return mCameras; + } + + public void appendDrawable(DrawableBase d) { + mDrawables.add(d); + mDrawableMap.put(d.getName(), d); + } + + public ArrayList<DrawableBase> getDrawables() { + return mDrawables; + } + + public DrawableBase getDrawableByName(String name) { + return mDrawableMap.get(name); + } + + public void appendTextures(Texture2D tex) { + mTextures.add(tex); + } + + public void assignRenderStateToMaterial(RenderState renderState, String regex) { + Pattern pattern = Pattern.compile(regex); + int numDrawables = mDrawables.size(); + for (int i = 0; i < numDrawables; i ++) { + Drawable shape = (Drawable)mDrawables.get(i); + Matcher m = pattern.matcher(shape.mMaterialName); + if (m.find()) { + shape.setRenderState(renderState); + } + } + } + + public void assignRenderState(RenderState renderState) { + int numDrawables = mDrawables.size(); + for (int i = 0; i < numDrawables; i ++) { + Drawable shape = (Drawable)mDrawables.get(i); + shape.setRenderState(renderState); + } + } + + public void meshLoaded(Mesh m) { + ArrayList<Drawable> entries = mDrawableMeshMap.get(m.getName()); + int numEntries = entries.size(); + for (int i = 0; i < numEntries; i++) { + Drawable d = entries.get(i); + d.resolveMeshData(m); + //mDrawablesField.set(d.getRsField(mRS, mRes), d.sceneIndex, true); + } + } + + void addToMeshMap(Drawable d) { + ArrayList<Drawable> entries = mDrawableMeshMap.get(d.mMeshName); + if (entries == null) { + entries = new ArrayList<Drawable>(); + mDrawableMeshMap.put(d.mMeshName, entries); + } + entries.add(d); + } + + public void destroyRS(SceneManager sceneManager) { + mTransformRSData = null; + sceneManager.mRenderLoop.bind_gRootNode(mTransformRSData); + sceneManager.mRenderLoop.set_gDrawableObjects(null); + mRenderPassAlloc = null; + sceneManager.mRenderLoop.set_gRenderPasses(null); + sceneManager.mRenderLoop.bind_gFrontToBack(null); + sceneManager.mRenderLoop.bind_gBackToFront(null); + sceneManager.mRenderLoop.set_gCameras(null); + + mTransformMap = null; + mRenderPasses = null; + mLights = null; + mCameras = null; + mDrawables = null; + mDrawableMap = null; + mTextures = null; + mDrawableMeshMap = null; + mRootTransforms = null; + } + + public void initRenderPassRS(RenderScriptGL rs, SceneManager sceneManager) { + if (mRenderPasses.size() != 0) { + mRenderPassAlloc = new ScriptField_RenderPass_s(mRS, mRenderPasses.size()); + for (int i = 0; i < mRenderPasses.size(); i ++) { + mRenderPassAlloc.set(mRenderPasses.get(i).getRsField(mRS, mRes), i, false); + } + mRenderPassAlloc.copyAll(); + sceneManager.mRenderLoop.set_gRenderPasses(mRenderPassAlloc.getAllocation()); + } + } + + public void initRS(RenderScriptGL rs, Resources res, SceneManager sceneManager) { + mRS = rs; + long start = System.currentTimeMillis(); + mTransformRSData = mRootTransforms.getRSData(rs); + long end = System.currentTimeMillis(); + Log.v(TIMER_TAG, "Transform init time: " + (end - start)); + + start = System.currentTimeMillis(); + + sceneManager.mRenderLoop.bind_gRootNode(mTransformRSData); + end = System.currentTimeMillis(); + Log.v(TIMER_TAG, "Script init time: " + (end - start)); + + start = System.currentTimeMillis(); + Allocation drawableData = Allocation.createSized(rs, + Element.ALLOCATION(rs), + mDrawables.size()); + Allocation[] drawableAllocs = new Allocation[mDrawables.size()]; + for (int i = 0; i < mDrawables.size(); i ++) { + Drawable dI = (Drawable)mDrawables.get(i); + dI.sceneIndex = i; + addToMeshMap(dI); + drawableAllocs[i] = dI.getRsField(rs, res).getAllocation(); + } + drawableData.copyFrom(drawableAllocs); + sceneManager.mRenderLoop.set_gDrawableObjects(drawableData); + + initRenderPassRS(rs, sceneManager); + + new ImageLoaderTask().execute(); + + end = System.currentTimeMillis(); + Log.v(TIMER_TAG, "Drawable init time: " + (end - start)); + + Allocation opaqueBuffer = Allocation.createSized(rs, Element.U32(rs), mDrawables.size()); + Allocation transparentBuffer = Allocation.createSized(rs, + Element.U32(rs), mDrawables.size()); + + sceneManager.mRenderLoop.bind_gFrontToBack(opaqueBuffer); + sceneManager.mRenderLoop.bind_gBackToFront(transparentBuffer); + + Allocation cameraData = Allocation.createSized(rs, Element.ALLOCATION(rs), mCameras.size()); + Allocation[] cameraAllocs = new Allocation[mCameras.size()]; + for (int i = 0; i < mCameras.size(); i ++) { + cameraAllocs[i] = mCameras.get(i).getRSData(rs).getAllocation(); + } + cameraData.copyFrom(cameraAllocs); + sceneManager.mRenderLoop.set_gCameras(cameraData); + } +} + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraph.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraph.java new file mode 100644 index 0000000..cfb91f4 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraph.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; +import android.view.MenuInflater; +import android.view.Window; +import android.net.Uri; + +import java.lang.Runtime; + +public class SceneGraph extends Activity { + + private SceneGraphView mView; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // Create our Preview view and set it as the content of our + // Activity + mView = new SceneGraphView(this); + setContentView(mView); + } + + @Override + protected void onResume() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onResume(); + mView.resume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onPause(); + mView.pause(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.loader_menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle item selection + switch (item.getItemId()) { + case R.id.load_model: + loadModel(); + return true; + case R.id.use_blur: + mView.mRender.toggleBlur(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private static final int FIND_DAE_MODEL = 10; + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == RESULT_OK) { + if (requestCode == FIND_DAE_MODEL) { + Uri selectedImageUri = data.getData(); + Log.e("Selected Path: ", selectedImageUri.getPath()); + mView.mRender.loadModel(selectedImageUri.getPath()); + } + } + } + + public void loadModel() { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_PICK); + intent.setClassName("com.android.scenegraph", + "com.android.scenegraph.FileSelector"); + startActivityForResult(intent, FIND_DAE_MODEL); + } + +} + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphBase.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphBase.java new file mode 100644 index 0000000..f5fe7c8 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphBase.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.Matrix4f; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.renderscript.RenderScript; +import android.renderscript.RSRuntimeException; + +import android.util.Log; + +/** + * @hide + */ +public abstract class SceneGraphBase { + String mName; + public void setName(String n) { + mName = n; + } + + public String getName() { + return mName; + } + + Allocation getStringAsAllocation(RenderScript rs, String str) { + if (str == null) { + return null; + } + if (str.length() == 0) { + return null; + } + byte[] allocArray = null; + byte[] nullChar = new byte[1]; + nullChar[0] = 0; + try { + allocArray = str.getBytes("UTF-8"); + Allocation alloc = Allocation.createSized(rs, Element.U8(rs), + allocArray.length + 1, + Allocation.USAGE_SCRIPT); + alloc.copy1DRangeFrom(0, allocArray.length, allocArray); + alloc.copy1DRangeFrom(allocArray.length, 1, nullChar); + return alloc; + } + catch (Exception e) { + throw new RSRuntimeException("Could not convert string to utf-8."); + } + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphRS.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphRS.java new file mode 100644 index 0000000..04b4cd8 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphRS.java @@ -0,0 +1,629 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.AsyncTask; +import android.renderscript.*; +import android.renderscript.Allocation.MipmapControl; +import android.renderscript.Element.Builder; +import android.renderscript.Font.Style; +import android.renderscript.Program.TextureType; +import android.renderscript.ProgramStore.DepthFunc; +import android.util.Log; + +import com.android.scenegraph.SceneManager.SceneLoadedCallback; + +public class SceneGraphRS { + + private static String modelName = "orientation_test"; + private static String TAG = "SceneGraphRS"; + private final int STATE_LAST_FOCUS = 1; + private final boolean mLoadFromSD = true; + private static String mSDCardPath = "sdcard/scenegraph/"; + + int mWidth; + int mHeight; + int mRotation; + + boolean mUseBlur; + + SceneLoadedCallback mLoadedCallback = new SceneLoadedCallback() { + public void run() { + prepareToRender(mLoadedScene); + } + }; + + SceneManager mSceneManager; + + TouchHandler mTouchHandler; + + public SceneGraphRS() { + mUseBlur = false; + } + + void toggleBlur() { + mUseBlur = !mUseBlur; + + mActiveScene.clearRenderPasses(); + initRenderPasses(); + mActiveScene.initRenderPassRS(mRS, mSceneManager); + Drawable plane = (Drawable)mActiveScene.getDrawableByName("pPlaneShape1"); + if (plane != null) { + plane.setVisible(mRS, !mUseBlur); + } + } + + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + mWidth = width; + mHeight = height; + mRotation = 0; + + mTouchHandler = new TouchHandler(); + + mSceneManager = new SceneManager(); + mSceneManager.initRS(mRS, mRes, mWidth, mHeight); + + renderLoading(); + + new LoadingScreenLoaderTask().execute(); + + initRS(); + + mSceneManager.loadModel(modelName, mLoadedCallback); + } + + void loadModel(String path) { + String shortName = path.substring(path.lastIndexOf('/') + 1); + shortName = shortName.substring(0, shortName.lastIndexOf('.')); + mScript.set_gInitialized(false); + mActiveScene.destroyRS(mSceneManager); + mSceneManager.loadModel(shortName, mLoadedCallback); + } + + private Resources mRes; + private RenderScriptGL mRS; + private Sampler mSampler; + private ProgramStore mPSBackground; + private ProgramFragment mPFBackground; + private ProgramVertex mPVBackground; + private ProgramVertexFixedFunction.Constants mPVA; + + private ProgramFragment mPF_Paint; + private ProgramFragment mPF_Aluminum; + private ProgramFragment mPF_Plastic; + private ProgramFragment mPF_Diffuse; + private ProgramFragment mPF_BlurH; + private ProgramFragment mPF_BlurV; + private ProgramFragment mPF_SelectColor; + private ProgramFragment mPF_Texture; + ScriptField_FShaderParams_s mFsConst; + ScriptField_FBlurOffsets_s mFsBlurHConst; + ScriptField_FBlurOffsets_s mFsBlurVConst; + private ProgramVertex mPV_Paint; + ScriptField_VShaderParams_s mVsConst; + private ProgramVertex mPV_Blur; + + private Allocation mDefaultCube; + private Allocation mAllocPV; + private Allocation mEnvCube; + private Allocation mDiffCube; + + private Allocation mRenderTargetBlur0Color; + private Allocation mRenderTargetBlur0Depth; + private Allocation mRenderTargetBlur1Color; + private Allocation mRenderTargetBlur1Depth; + private Allocation mRenderTargetBlur2Color; + private Allocation mRenderTargetBlur2Depth; + + Scene mActiveScene; + + private ScriptC_scenegraph mScript; + + private class LoadingScreenLoaderTask extends AsyncTask<String, Void, Boolean> { + Allocation robotTex; + Mesh robotMesh; + protected Boolean doInBackground(String... names) { + long start = System.currentTimeMillis(); + robotTex = Allocation.createFromBitmapResource(mRS, mRes, R.drawable.robot, + MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + + FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot); + FileA3D.IndexEntry entry = model.getIndexEntry(0); + if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) { + robotMesh = entry.getMesh(); + } + + initPFS(); + initPF(); + initPV(); + + long end = System.currentTimeMillis(); + Log.v("TIMER", "Loading load time: " + (end - start)); + return new Boolean(true); + } + + protected void onPostExecute(Boolean result) { + mScript.set_gRobotTex(robotTex); + mScript.set_gRobotMesh(robotMesh); + } + } + + + private class ImageLoaderTask extends AsyncTask<String, Void, Boolean> { + Allocation tempEnv; + Allocation tempDiff; + + InputStream openStream(String name) { + InputStream is = null; + try { + if (!mLoadFromSD) { + is = mRes.getAssets().open(name); + } else { + File f = new File(mSDCardPath + name); + is = new BufferedInputStream(new FileInputStream(f)); + } + } catch (IOException e) { + Log.e("PAINTSHADERS", " Message: " + e.getMessage()); + } + return is; + } + + protected Boolean doInBackground(String... names) { + long start = System.currentTimeMillis(); + InputStream is = openStream("cube_env.png"); + if (is == null) { + return new Boolean(false); + } + + Bitmap b = BitmapFactory.decodeStream(is); + tempEnv = Allocation.createCubemapFromBitmap(mRS, + b, + MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + + is = openStream("cube_spec.png"); + if (is == null) { + return new Boolean(false); + } + + b = BitmapFactory.decodeStream(is); + tempDiff = Allocation.createCubemapFromBitmap(mRS, + b, + MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + long end = System.currentTimeMillis(); + Log.v("TIMER", "Image load time: " + (end - start)); + return new Boolean(true); + } + + protected void onPostExecute(Boolean result) { + mEnvCube = tempEnv; + mDiffCube = tempDiff; + + mPF_Paint.bindTexture(mEnvCube, 1); + mPF_Aluminum.bindTexture(mDiffCube, 1); + } + } + + public void onActionDown(float x, float y) { + mTouchHandler.onActionDown(x, y); + + //mSceneManager.getRenderLoop().invoke_pick((int)x, (int)y); + } + + public void onActionScale(float scale) { + mTouchHandler.onActionScale(scale); + } + + public void onActionMove(float x, float y) { + mTouchHandler.onActionMove(x, y); + } + + private void initPaintShaders() { + ProgramVertex.Builder vb = new ProgramVertex.Builder(mRS); + mVsConst = new ScriptField_VShaderParams_s(mRS, 1); + vb.addConstant(mVsConst.getAllocation().getType()); + vb.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); + vb.setShader(mRes, R.raw.shader2v); + mPV_Paint = vb.create(); + mPV_Paint.bindConstants(mVsConst.getAllocation(), 0); + + vb = new ProgramVertex.Builder(mRS); + vb.addConstant(mVsConst.getAllocation().getType()); + vb.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); + vb.setShader(mRes, R.raw.blur_vertex); + mPV_Blur = vb.create(); + mPV_Blur.bindConstants(mVsConst.getAllocation(), 0); + + ProgramFragment.Builder fb = new ProgramFragment.Builder(mRS); + mFsConst = new ScriptField_FShaderParams_s(mRS, 1); + fb.addConstant(mFsConst.getAllocation().getType()); + fb.setShader(mRes, R.raw.paintf); + fb.addTexture(TextureType.TEXTURE_2D); + fb.addTexture(TextureType.TEXTURE_CUBE); + mPF_Paint = fb.create(); + + mPF_Paint.bindConstants(mFsConst.getAllocation(), 0); + mPF_Paint.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0); + mPF_Paint.bindSampler(Sampler.CLAMP_LINEAR_MIP_LINEAR(mRS), 1); + + fb = new ProgramFragment.Builder(mRS); + fb.addConstant(mFsConst.getAllocation().getType()); + fb.setShader(mRes, R.raw.metal); + fb.addTexture(TextureType.TEXTURE_2D); + fb.addTexture(TextureType.TEXTURE_CUBE); + mPF_Aluminum = fb.create(); + + mPF_Aluminum.bindConstants(mFsConst.getAllocation(), 0); + mPF_Aluminum.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0); + mPF_Aluminum.bindSampler(Sampler.CLAMP_LINEAR_MIP_LINEAR(mRS), 1); + + fb = new ProgramFragment.Builder(mRS); + fb.addConstant(mFsConst.getAllocation().getType()); + fb.setShader(mRes, R.raw.plastic); + fb.addTexture(TextureType.TEXTURE_2D); + mPF_Plastic = fb.create(); + mPF_Plastic.bindConstants(mFsConst.getAllocation(), 0); + mPF_Plastic.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0); + + fb = new ProgramFragment.Builder(mRS); + fb.addConstant(mFsConst.getAllocation().getType()); + fb.setShader(mRes, R.raw.diffuse); + fb.addTexture(TextureType.TEXTURE_2D); + mPF_Diffuse = fb.create(); + mPF_Diffuse.bindConstants(mFsConst.getAllocation(), 0); + mPF_Diffuse.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0); + + fb = new ProgramFragment.Builder(mRS); + fb.addConstant(mFsConst.getAllocation().getType()); + fb.setShader(mRes, R.raw.texture); + fb.addTexture(TextureType.TEXTURE_2D); + mPF_Texture = fb.create(); + mPF_Texture.bindConstants(mFsConst.getAllocation(), 0); + mPF_Texture.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0); + + mFsBlurHConst = new ScriptField_FBlurOffsets_s(mRS, 1); + float xAdvance = 1.0f / (float)mRenderTargetBlur0Color.getType().getX(); + ScriptField_FBlurOffsets_s.Item item = new ScriptField_FBlurOffsets_s.Item(); + item.blurOffset0 = - xAdvance * 2.5f; + item.blurOffset1 = - xAdvance * 0.5f; + item.blurOffset2 = xAdvance * 1.5f; + item.blurOffset3 = xAdvance * 3.5f; + mFsBlurHConst.set(item, 0, true); + + fb = new ProgramFragment.Builder(mRS); + fb.addConstant(mFsBlurHConst.getAllocation().getType()); + fb.setShader(mRes, R.raw.blur_h); + fb.addTexture(TextureType.TEXTURE_2D); + mPF_BlurH = fb.create(); + mPF_BlurH.bindConstants(mFsBlurHConst.getAllocation(), 0); + mPF_BlurH.bindTexture(mRenderTargetBlur0Color, 0); + mPF_BlurH.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0); + + mFsBlurVConst = new ScriptField_FBlurOffsets_s(mRS, 1); + float yAdvance = 1.0f / (float)mRenderTargetBlur0Color.getType().getY(); + item.blurOffset0 = - yAdvance * 2.5f; + item.blurOffset1 = - yAdvance * 0.5f; + item.blurOffset2 = yAdvance * 1.5f; + item.blurOffset3 = yAdvance * 3.5f; + mFsBlurVConst.set(item, 0, true); + + fb = new ProgramFragment.Builder(mRS); + fb.addConstant(mFsBlurVConst.getAllocation().getType()); + fb.setShader(mRes, R.raw.blur_v); + fb.addTexture(TextureType.TEXTURE_2D); + mPF_BlurV = fb.create(); + mPF_BlurV.bindConstants(mFsBlurVConst.getAllocation(), 0); + mPF_BlurV.bindTexture(mRenderTargetBlur1Color, 0); + mPF_BlurV.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0); + + fb = new ProgramFragment.Builder(mRS); + //fb.addConstant(mFsBlurVConst.getAllocation().getType()); + fb.setShader(mRes, R.raw.select_color); + fb.addTexture(TextureType.TEXTURE_2D); + mPF_SelectColor = fb.create(); + //mPF_SelectColor.bindConstants(mFsBlurVConst.getAllocation(), 0); + //mPF_SelectColor.bindTexture(mRenderTargetBlur1Color, 0); + mPF_SelectColor.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0); + } + + private void initPFS() { + ProgramStore.Builder b = new ProgramStore.Builder(mRS); + + b.setDepthFunc(ProgramStore.DepthFunc.LESS); + b.setDitherEnabled(false); + b.setDepthMaskEnabled(true); + mPSBackground = b.create(); + + mScript.set_gPFSBackground(mPSBackground); + } + + private void initPF() { + Sampler.Builder bs = new Sampler.Builder(mRS); + bs.setMinification(Sampler.Value.LINEAR); + bs.setMagnification(Sampler.Value.LINEAR); + bs.setWrapS(Sampler.Value.CLAMP); + bs.setWrapT(Sampler.Value.CLAMP); + mSampler = bs.create(); + + ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS); + b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, + ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); + mPFBackground = b.create(); + mPFBackground.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0); + + mScript.set_gPFBackground(mPFBackground); + } + + private void initPV() { + ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS); + mPVBackground = pvb.create(); + + mPVA = new ProgramVertexFixedFunction.Constants(mRS); + ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVA); + + mScript.set_gPVBackground(mPVBackground); + } + + void renderLoading() { + mScript = new ScriptC_scenegraph(mRS, mRes, R.raw.scenegraph); + mRS.bindRootScript(mScript); + } + + void initSceneRS() { + + } + + void createRenderTargets() { + Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS)); + b.setX(mWidth/8).setY(mHeight/8); + Type renderType = b.create(); + mRenderTargetBlur0Color = Allocation.createTyped(mRS, renderType, + Allocation.USAGE_GRAPHICS_TEXTURE | + Allocation.USAGE_GRAPHICS_RENDER_TARGET); + mRenderTargetBlur1Color = Allocation.createTyped(mRS, renderType, + Allocation.USAGE_GRAPHICS_TEXTURE | + Allocation.USAGE_GRAPHICS_RENDER_TARGET); + mRenderTargetBlur2Color = Allocation.createTyped(mRS, renderType, + Allocation.USAGE_GRAPHICS_TEXTURE | + Allocation.USAGE_GRAPHICS_RENDER_TARGET); + + b = new Type.Builder(mRS, + Element.createPixel(mRS, Element.DataType.UNSIGNED_16, + Element.DataKind.PIXEL_DEPTH)); + b.setX(mWidth/8).setY(mHeight/8); + mRenderTargetBlur0Depth = Allocation.createTyped(mRS, + b.create(), + Allocation.USAGE_GRAPHICS_RENDER_TARGET); + + mRenderTargetBlur1Depth = Allocation.createTyped(mRS, + b.create(), + Allocation.USAGE_GRAPHICS_RENDER_TARGET); + mRenderTargetBlur2Depth = Allocation.createTyped(mRS, + b.create(), + Allocation.USAGE_GRAPHICS_RENDER_TARGET); + } + + ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) { + ProgramStore.Builder builder = new ProgramStore.Builder(rs); + builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS); + builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ONE); + builder.setDitherEnabled(false); + builder.setDepthMaskEnabled(false); + return builder.create(); + } + + Drawable getDrawableQuad(String name, RenderState state) { + Drawable quad = new Drawable(); + quad.setTransform(new MatrixTransform()); + quad.setMesh(mSceneManager.getScreenAlignedQuad()); + quad.setName(name); + quad.setRenderState(state); + quad.setCullType(1); + return quad; + } + + void addBlurPasses() { + ArrayList<DrawableBase> allDraw = mActiveScene.getDrawables(); + int numDraw = allDraw.size(); + + RenderState drawTex = new RenderState(mPV_Blur, mPF_Texture, + BLEND_ADD_DEPTH_NONE(mRS), + ProgramRaster.CULL_NONE(mRS)); + + RenderState selectCol = new RenderState(mPV_Blur, mPF_SelectColor, + ProgramStore.BLEND_NONE_DEPTH_NONE(mRS), + ProgramRaster.CULL_NONE(mRS)); + + RenderState hBlur = new RenderState(mPV_Blur, mPF_BlurH, + ProgramStore.BLEND_NONE_DEPTH_NONE(mRS), + ProgramRaster.CULL_NONE(mRS)); + + RenderState vBlur = new RenderState(mPV_Blur, mPF_BlurV, + ProgramStore.BLEND_NONE_DEPTH_NONE(mRS), + ProgramRaster.CULL_NONE(mRS)); + + RenderPass blurSourcePass = new RenderPass(); + blurSourcePass.setColorTarget(mRenderTargetBlur0Color); + blurSourcePass.setDepthTarget(mRenderTargetBlur0Depth); + blurSourcePass.setClearColor(new Float4(1.0f, 1.0f, 1.0f, 1.0f)); + blurSourcePass.setShouldClearColor(true); + blurSourcePass.setClearDepth(1.0f); + blurSourcePass.setShouldClearDepth(true); + blurSourcePass.setCamera(mActiveScene.getCameras().get(1)); + for (int i = 0; i < numDraw; i ++) { + blurSourcePass.appendDrawable((Drawable)allDraw.get(i)); + } + mActiveScene.appendRenderPass(blurSourcePass); + + RenderPass selectColorPass = new RenderPass(); + selectColorPass.setColorTarget(mRenderTargetBlur2Color); + selectColorPass.setDepthTarget(mRenderTargetBlur2Depth); + selectColorPass.setShouldClearColor(false); + selectColorPass.setShouldClearDepth(false); + selectColorPass.setCamera(mActiveScene.getCameras().get(1)); + // Make blur shape + Drawable quad = getDrawableQuad("ScreenAlignedQuadS", selectCol); + quad.updateTextures(mRS, mRenderTargetBlur0Color, 0); + selectColorPass.appendDrawable(quad); + mActiveScene.appendRenderPass(selectColorPass); + + RenderPass horizontalBlurPass = new RenderPass(); + horizontalBlurPass.setColorTarget(mRenderTargetBlur1Color); + horizontalBlurPass.setDepthTarget(mRenderTargetBlur1Depth); + horizontalBlurPass.setShouldClearColor(false); + horizontalBlurPass.setShouldClearDepth(false); + horizontalBlurPass.setCamera(mActiveScene.getCameras().get(1)); + // Make blur shape + quad = getDrawableQuad("ScreenAlignedQuadH", hBlur); + quad.updateTextures(mRS, mRenderTargetBlur2Color, 0); + horizontalBlurPass.appendDrawable(quad); + mActiveScene.appendRenderPass(horizontalBlurPass); + + RenderPass verticalBlurPass = new RenderPass(); + verticalBlurPass.setColorTarget(mRenderTargetBlur2Color); + verticalBlurPass.setDepthTarget(mRenderTargetBlur2Depth); + verticalBlurPass.setShouldClearColor(false); + verticalBlurPass.setShouldClearDepth(false); + verticalBlurPass.setCamera(mActiveScene.getCameras().get(1)); + // Make blur shape + quad = getDrawableQuad("ScreenAlignedQuadV", vBlur); + quad.updateTextures(mRS, mRenderTargetBlur1Color, 0); + verticalBlurPass.appendDrawable(quad); + mActiveScene.appendRenderPass(verticalBlurPass); + + } + + void initRenderPasses() { + ArrayList<DrawableBase> allDraw = mActiveScene.getDrawables(); + int numDraw = allDraw.size(); + + if (mUseBlur) { + addBlurPasses(); + } + + RenderPass mainPass = new RenderPass(); + mainPass.setClearColor(new Float4(1.0f, 1.0f, 1.0f, 1.0f)); + mainPass.setShouldClearColor(true); + mainPass.setClearDepth(1.0f); + mainPass.setShouldClearDepth(true); + mainPass.setCamera(mActiveScene.getCameras().get(1)); + for (int i = 0; i < numDraw; i ++) { + mainPass.appendDrawable((Drawable)allDraw.get(i)); + } + mActiveScene.appendRenderPass(mainPass); + + if (mUseBlur) { + RenderState drawTex = new RenderState(mPV_Blur, mPF_Texture, + BLEND_ADD_DEPTH_NONE(mRS), + ProgramRaster.CULL_NONE(mRS)); + + RenderPass compositePass = new RenderPass(); + compositePass.setClearColor(new Float4(1.0f, 1.0f, 1.0f, 0.0f)); + compositePass.setShouldClearColor(false); + compositePass.setClearDepth(1.0f); + compositePass.setShouldClearDepth(false); + compositePass.setCamera(mActiveScene.getCameras().get(1)); + Drawable quad = getDrawableQuad("ScreenAlignedQuad", drawTex); + quad.updateTextures(mRS, mRenderTargetBlur2Color, 0); + compositePass.appendDrawable(quad); + + mActiveScene.appendRenderPass(compositePass); + } + } + + public void prepareToRender(Scene s) { + mActiveScene = s; + RenderState plastic = new RenderState(mPV_Paint, mPF_Plastic, null, null); + RenderState diffuse = new RenderState(mPV_Paint, mPF_Diffuse, null, null); + RenderState paint = new RenderState(mPV_Paint, mPF_Paint, null, null); + RenderState aluminum = new RenderState(mPV_Paint, mPF_Aluminum, null, null); + RenderState glassTransp = new RenderState(mPV_Paint, + mPF_Paint, + ProgramStore.BLEND_ALPHA_DEPTH_TEST(mRS), + null); + + initRenderPasses(); + + mActiveScene.assignRenderState(plastic); + + mActiveScene.assignRenderStateToMaterial(diffuse, "lambert2$"); + + mActiveScene.assignRenderStateToMaterial(paint, "^#Paint"); + mActiveScene.assignRenderStateToMaterial(paint, "^#Carbon"); + mActiveScene.assignRenderStateToMaterial(paint, "^#Glass"); + mActiveScene.assignRenderStateToMaterial(paint, "^#MainGlass"); + + mActiveScene.assignRenderStateToMaterial(aluminum, "^#Metal"); + mActiveScene.assignRenderStateToMaterial(aluminum, "^#Brake"); + + mActiveScene.assignRenderStateToMaterial(glassTransp, "^#GlassLight"); + + Drawable plane = (Drawable)mActiveScene.getDrawableByName("pPlaneShape1"); + if (plane != null) { + RenderState texState = new RenderState(mPV_Paint, mPF_Texture, null, null); + plane.setRenderState(texState); + plane.setVisible(mRS, !mUseBlur); + } + + mTouchHandler.init(mActiveScene); + + long start = System.currentTimeMillis(); + mActiveScene.initRS(mRS, mRes, mSceneManager); + long end = System.currentTimeMillis(); + Log.v("TIMER", "Scene init time: " + (end - start)); + + mScript.set_gInitialized(true); + } + + private void initRS() { + + createRenderTargets(); + initPaintShaders(); + new ImageLoaderTask().execute(); + + Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.defaultcube); + mDefaultCube = Allocation.createCubemapFromBitmap(mRS, b); + mPF_Paint.bindTexture(mDefaultCube, 1); + mPF_Aluminum.bindTexture(mDefaultCube, 1); + + ScriptC_render renderLoop = mSceneManager.getRenderLoop(); + renderLoop.bind_vConst(mVsConst); + renderLoop.bind_fConst(mFsConst); + + mScript.set_gRenderLoop(renderLoop); + Allocation dummyAlloc = Allocation.createSized(mRS, Element.I32(mRS), 1); + mScript.set_gDummyAlloc(dummyAlloc); + } +} diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphView.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphView.java new file mode 100644 index 0000000..0f28501 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphView.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; + +public class SceneGraphView extends RSSurfaceView { + + public SceneGraphView(Context context) { + super(context); + mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); + } + + private RenderScriptGL mRS; + SceneGraphRS mRender; + + private ScaleGestureDetector mScaleDetector; + private static final int INVALID_POINTER_ID = -1; + private int mActivePointerId = INVALID_POINTER_ID; + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + if (mRS == null) { + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + sc.setDepth(16, 24); + mRS = createRenderScriptGL(sc); + mRS.setSurface(holder, w, h); + mRender = new SceneGraphRS(); + mRender.init(mRS, getResources(), w, h); + } + } + + @Override + protected void onDetachedFromWindow() { + if (mRS != null) { + mRender = null; + mRS = null; + destroyRenderScriptGL(); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + // break point at here + // this method doesn't work when 'extends View' include 'extends ScrollView'. + return super.onKeyDown(keyCode, event); + } + + + @Override + public boolean onTouchEvent(MotionEvent ev) { + mScaleDetector.onTouchEvent(ev); + + boolean ret = false; + float x = ev.getX(); + float y = ev.getY(); + + final int action = ev.getAction(); + + switch (action & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + mRender.onActionDown(x, y); + mActivePointerId = ev.getPointerId(0); + ret = true; + break; + } + case MotionEvent.ACTION_MOVE: { + if (!mScaleDetector.isInProgress()) { + mRender.onActionMove(x, y); + } + mRender.onActionDown(x, y); + ret = true; + break; + } + + case MotionEvent.ACTION_UP: { + mActivePointerId = INVALID_POINTER_ID; + break; + } + + case MotionEvent.ACTION_CANCEL: { + mActivePointerId = INVALID_POINTER_ID; + break; + } + + case MotionEvent.ACTION_POINTER_UP: { + final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) + >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + final int pointerId = ev.getPointerId(pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + x = ev.getX(newPointerIndex); + y = ev.getY(newPointerIndex); + mRender.onActionDown(x, y); + mActivePointerId = ev.getPointerId(newPointerIndex); + } + break; + } + } + + return ret; + } + + private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + @Override + public boolean onScale(ScaleGestureDetector detector) { + mRender.onActionScale(detector.getScaleFactor()); + return true; + } + } +} + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java new file mode 100644 index 0000000..3bb49f3 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import android.renderscript.RenderScriptGL; +import android.renderscript.Mesh; +import android.renderscript.*; +import android.renderscript.Allocation.MipmapControl; +import android.content.res.Resources; +import android.view.SurfaceHolder; +import android.util.Log; +import android.os.AsyncTask; + +/** + * @hide + */ +public class SceneManager extends SceneGraphBase { + + ScriptC_render mRenderLoop; + ScriptC_camera mCameraScript; + ScriptC_transform mTransformScript; + + RenderScriptGL mRS; + Resources mRes; + Mesh mQuad; + int mWidth; + int mHeight; + + public static class SceneLoadedCallback implements Runnable { + Scene mLoadedScene; + String mName; + public void run() { + } + } + + private void initPFS() { + ProgramStore.Builder b = new ProgramStore.Builder(mRS); + + b.setDepthFunc(ProgramStore.DepthFunc.LESS); + b.setDitherEnabled(false); + b.setDepthMaskEnabled(true); + + mRenderLoop.set_gPFSBackground(b.create()); + } + + public SceneManager() { + } + + public void loadModel(String name, SceneLoadedCallback cb) { + ColladaScene scene = new ColladaScene(name, cb); + scene.init(mRS, mRes); + } + + public Mesh getScreenAlignedQuad() { + if (mQuad != null) { + return mQuad; + } + + Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS, + 3, Mesh.TriangleMeshBuilder.TEXTURE_0); + + tmb.setTexture(0.0f, 1.0f); + tmb.addVertex(-1.0f, 1.0f, 1.0f); + + tmb.setTexture(0.0f, 0.0f); + tmb.addVertex(-1.0f, -1.0f, 1.0f); + + tmb.setTexture(1.0f, 0.0f); + tmb.addVertex(1.0f, -1.0f, 1.0f); + + tmb.setTexture(1.0f, 1.0f); + tmb.addVertex(1.0f, 1.0f, 1.0f); + + tmb.addTriangle(0, 1, 2); + tmb.addTriangle(2, 3, 0); + + mQuad = tmb.create(true); + return mQuad; + } + + public void initRS(RenderScriptGL rs, Resources res, int w, int h) { + mRS = rs; + mRes = res; + mTransformScript = new ScriptC_transform(rs, res, R.raw.transform); + mTransformScript.set_gTransformScript(mTransformScript); + + mCameraScript = new ScriptC_camera(rs, res, R.raw.camera); + + mRenderLoop = new ScriptC_render(rs, res, R.raw.render); + mRenderLoop.set_gTransformScript(mTransformScript); + mRenderLoop.set_gCameraScript(mCameraScript); + + Allocation checker = Allocation.createFromBitmapResource(mRS, mRes, R.drawable.checker, + MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + mRenderLoop.set_gTGrid(checker); + initPFS(); + } + + public ScriptC_render getRenderLoop() { + return mRenderLoop; + } +} + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ShaderParam.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ShaderParam.java new file mode 100644 index 0000000..22cd1ce --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ShaderParam.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.Matrix4f; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.renderscript.Element; +import android.util.Log; + +/** + * @hide + */ +public class ShaderParam extends SceneGraphBase { + String mParamName; + + public ShaderParam(String name) { + mParamName = name; + } + + public String getParamName() { + return mParamName; + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Texture2D.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Texture2D.java new file mode 100644 index 0000000..fdab999 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Texture2D.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.lang.Math; +import java.net.URL; +import java.util.ArrayList; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.renderscript.*; +import android.renderscript.Allocation.MipmapControl; +import android.renderscript.Matrix4f; +import android.renderscript.Type.Builder; +import android.util.Log; + +/** + * @hide + */ +public class Texture2D extends SceneGraphBase { + private static String mSDCardPath = "sdcard/scenegraph/"; + private final boolean mLoadFromSD = true; + + String mFileName; + Allocation mRsTexture; + + public Texture2D() { + } + + public void setFileName(String file) { + mFileName = file; + } + + public String getFileName() { + return mFileName; + } + + Allocation getRsData(RenderScriptGL rs, Resources res) { + if (mRsTexture != null) { + return mRsTexture; + } + + String shortName = mFileName.substring(mFileName.lastIndexOf('/') + 1); + InputStream is = null; + try { + if (!mLoadFromSD) { + is = res.getAssets().open(shortName); + } else { + File f = new File(mSDCardPath + shortName); + is = new BufferedInputStream(new FileInputStream(f)); + } + } catch (IOException e) { + Log.e("Texture2D", + "Could not open image file " + shortName + " Message: " + e.getMessage()); + return null; + } + + Bitmap b = BitmapFactory.decodeStream(is); + mRsTexture = Allocation.createFromBitmap(rs, b, + Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + return mRsTexture; + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureParam.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureParam.java new file mode 100644 index 0000000..0959d12 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureParam.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.graphics.Camera; +import android.renderscript.Float4; +import android.renderscript.Matrix4f; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.renderscript.Element; +import android.util.Log; + +/** + * @hide + */ +public class TextureParam extends ShaderParam { + + Texture2D mTexture; + + public TextureParam(String name) { + super(name); + } + + public void setTexture(Texture2D t) { + mTexture = t; + } + + public Texture2D getTexture() { + return mTexture; + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TouchHandler.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TouchHandler.java new file mode 100644 index 0000000..eacc3d0 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TouchHandler.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.AsyncTask; +import android.renderscript.*; +import android.renderscript.Allocation.MipmapControl; +import android.renderscript.Element.Builder; +import android.renderscript.Font.Style; +import android.renderscript.Program.TextureType; +import android.renderscript.ProgramStore.DepthFunc; +import android.util.Log; + +import com.android.scenegraph.SceneManager.SceneLoadedCallback; + +public class TouchHandler { + + private static String TAG = "TouchHandler"; + + public TouchHandler() { + } + + public void init(Scene scene) { + mCameraRotate = (CompoundTransform)scene.getTransformByName("CameraAim"); + mCameraDist = (CompoundTransform)scene.getTransformByName("CameraDist"); + + if (mCameraRotate != null && mCameraDist != null) { + mRotateX = mCameraRotate.mTransformComponents.get(2); + mRotateY = mCameraRotate.mTransformComponents.get(1); + mDist = mCameraDist.mTransformComponents.get(0); + } + } + + + private Resources mRes; + private RenderScriptGL mRS; + + float mLastX; + float mLastY; + + CompoundTransform mCameraRotate; + CompoundTransform mCameraDist; + + CompoundTransform.Component mRotateX; + CompoundTransform.Component mRotateY; + CompoundTransform.Component mDist; + + public void onActionDown(float x, float y) { + mLastX = x; + mLastY = y; + } + + public void onActionScale(float scale) { + if (mCameraDist == null) { + return; + } + mDist.mValue.z *= 1.0f / scale; + mDist.mValue.z = Math.max(20.0f, Math.min(mDist.mValue.z, 100.0f)); + mCameraDist.updateRSData(); + } + + public void onActionMove(float x, float y) { + if (mCameraRotate == null) { + return; + } + + float dx = mLastX - x; + float dy = mLastY - y; + + if (Math.abs(dy) <= 2.0f) { + dy = 0.0f; + } + if (Math.abs(dx) <= 2.0f) { + dx = 0.0f; + } + + mRotateY.mValue.w += dx*0.25; + if (mRotateY.mValue.w > 360) { + mRotateY.mValue.w -= 360; + } + if (mRotateY.mValue.w < 0) { + mRotateY.mValue.w += 360; + } + + mRotateX.mValue.w += dy*0.25; + mRotateX.mValue.w = Math.max(mRotateX.mValue.w, -80.0f); + mRotateX.mValue.w = Math.min(mRotateX.mValue.w, 0.0f); + + mLastX = x; + mLastY = y; + + mCameraRotate.updateRSData(); + } +} diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Transform.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Transform.java new file mode 100644 index 0000000..04793bc --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Transform.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.renderscript.*; +import android.renderscript.Matrix4f; +import android.util.Log; + +/** + * @hide + */ +public abstract class Transform extends SceneGraphBase { + + RenderScriptGL mRS; + Transform mParent; + ArrayList<Transform> mChildren; + + static final int RS_ID_NONE = 0; + static final int RS_ID_TRANSLATE = 1; + static final int RS_ID_ROTATE = 2; + static final int RS_ID_SCALE = 3; + + ScriptField_SgTransform mField; + ScriptField_SgTransform.Item mTransformData; + + public Transform() { + mChildren = new ArrayList<Transform>(); + mParent = null; + } + + public void appendChild(Transform t) { + mChildren.add(t); + t.mParent = this; + } + + abstract void initLocalData(); + public abstract void updateRSData(); + + public ScriptField_SgTransform getRSData(RenderScriptGL rs) { + if (mField != null) { + return mField; + } + + mRS = rs; + initLocalData(); + + if (mChildren.size() != 0) { + Allocation childRSData = Allocation.createSized(rs, + Element.ALLOCATION(rs), + mChildren.size()); + mTransformData.children = childRSData; + + Allocation[] childrenAllocs = new Allocation[mChildren.size()]; + for (int i = 0; i < mChildren.size(); i ++) { + Transform child = mChildren.get(i); + childrenAllocs[i] = child.getRSData(rs).getAllocation(); + } + childRSData.copyFrom(childrenAllocs); + } + + mField = new ScriptField_SgTransform(rs, 1); + mField.set(mTransformData, 0, true); + + return mField; + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TransformParam.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TransformParam.java new file mode 100644 index 0000000..fec7639 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TransformParam.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.scenegraph; + +import java.lang.Math; +import java.util.ArrayList; + +import android.graphics.Camera; +import android.renderscript.Matrix4f; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.renderscript.Element; +import android.util.Log; + +/** + * @hide + */ +public class TransformParam extends ShaderParam { + + public static final int TRANSFORM = 0; + public static final int TRANSFORM_VIEW = 1; + public static final int TRANSFORM_VIEW_PROJ = 2; + Transform mTransform; + Camera mCamera; + + public TransformParam(String name) { + super(name); + } + + public void setTransform(Transform t) { + mTransform = t; + } + + public void setCamera(Camera c) { + mCamera = c; + } +} + + + + + diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/camera.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/camera.rs new file mode 100644 index 0000000..0b7b00c --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/camera.rs @@ -0,0 +1,44 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma version(1) + +#pragma rs java_package_name(com.android.scenegraph) + +//#define DEBUG_CAMERA +#include "transform_def.rsh" + +void root(const rs_allocation *v_in, rs_allocation *v_out, const float *usrData) { + + SgCamera *cam = (SgCamera *)rsGetElementAt(*v_in, 0); + float aspect = *usrData; + cam->aspect = aspect; + const SgTransform *camTransform = (const SgTransform *)rsGetElementAt(cam->transformMatrix, 0); + + rsMatrixLoadPerspective(&cam->proj, cam->horizontalFOV, cam->aspect, cam->near, cam->far); + + rs_matrix4x4 camPosMatrix; + rsMatrixLoad(&camPosMatrix, &camTransform->globalMat); + float4 zero = {0.0f, 0.0f, 0.0f, 1.0f}; + cam->position = rsMatrixMultiply(&camPosMatrix, zero); + + rsMatrixInverse(&camPosMatrix); + rsMatrixLoad(&cam->view, &camPosMatrix); + + rsMatrixLoad(&cam->viewProj, &cam->proj); + rsMatrixMultiply(&cam->viewProj, &cam->view); +#ifdef DEBUG_CAMERA + printCameraInfo(cam); +#endif //DEBUG_CAMERA +} diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/export.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/export.rs new file mode 100644 index 0000000..1dfe633 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/export.rs @@ -0,0 +1,28 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma version(1) + +#pragma rs java_package_name(com.android.scenegraph) + +// The sole purpose of this script is to have various structs exposed +// so that java reflected classes are generated +#include "transform_def.rsh" +SgTransform *exportPtr; +SgRenderState *sExport; +SgDrawable *drExport; +SgRenderPass *pExport; +SgCamera *exportPtrCam; +FBlurOffsets *blurExport; +VertexShaderInputs *iExport;
\ No newline at end of file diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs new file mode 100644 index 0000000..2891657 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs @@ -0,0 +1,296 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma version(1) + +#pragma rs java_package_name(com.android.scenegraph) + +#include "rs_graphics.rsh" +#include "transform_def.rsh" + +rs_script gTransformScript; +rs_script gCameraScript; + +SgTransform *gRootNode; +rs_allocation gCameras; +rs_allocation gDrawableObjects; + +rs_allocation gRenderPasses; + +// Temporary shaders +rs_allocation gTGrid; +rs_program_store gPFSBackground; + +VShaderParams *vConst; +FShaderParams *fConst; + +uint32_t *gFrontToBack; +static uint32_t gFrontToBackCount = 0; +uint32_t *gBackToFront; +static uint32_t gBackToFrontCount = 0; + +static SgCamera *gActiveCamera = NULL; +static float4 gFrustumPlanes[6]; + +static rs_allocation nullAlloc; + +//#define DEBUG_RENDERABLES +static void draw(SgDrawable *obj) { + + const SgRenderState *renderState = (const SgRenderState *)rsGetElementAt(obj->render_state, 0); + const SgTransform *objTransform = (const SgTransform *)rsGetElementAt(obj->transformMatrix, 0); +#ifdef DEBUG_RENDERABLES + rsDebug("**** Drawing object with transform", obj); + printName(objTransform->name); + rsDebug("Model matrix: ", &objTransform->globalMat); + printName(obj->name); +#endif //DEBUG_RENDERABLES + + SgCamera *cam = gActiveCamera; + + rsMatrixLoad(&vConst->model, &objTransform->globalMat); + rsMatrixLoad(&vConst->viewProj, &cam->viewProj); + rsgAllocationSyncAll(rsGetAllocation(vConst)); + fConst->cameraPos = cam->position; + rsgAllocationSyncAll(rsGetAllocation(fConst)); + + if (rsIsObject(renderState->ps)) { + rsgBindProgramStore(renderState->ps); + } else { + rsgBindProgramStore(gPFSBackground); + } + + if (rsIsObject(renderState->pr)) { + rsgBindProgramRaster(renderState->pr); + } else { + rs_program_raster pr; + rsgBindProgramRaster(pr); + } + + rsgBindProgramFragment(renderState->pf); + rsgBindProgramVertex(renderState->pv); + + if (rsIsObject(obj->pf_textures[0])) { + rsgBindTexture(renderState->pf, 0, obj->pf_textures[0]); + } else { + rsgBindTexture(renderState->pf, 0, gTGrid); + } + + rsgDrawMesh(obj->mesh, obj->meshIndex); +} + +static void getTransformedSphere(SgDrawable *obj) { + obj->worldBoundingSphere = obj->boundingSphere; + obj->worldBoundingSphere.w = 1.0f; + const SgTransform *objTransform = (const SgTransform *)rsGetElementAt(obj->transformMatrix, 0); + obj->worldBoundingSphere = rsMatrixMultiply(&objTransform->globalMat, obj->worldBoundingSphere); + + const float4 unitVec = {0.57735f, 0.57735f, 0.57735f, 0.0f}; + float4 scaledVec = rsMatrixMultiply(&objTransform->globalMat, unitVec); + scaledVec.w = 0.0f; + obj->worldBoundingSphere.w = obj->boundingSphere.w * length(scaledVec); +} + +static bool frustumCulled(SgDrawable *obj) { + if (!obj->bVolInitialized) { + float minX, minY, minZ, maxX, maxY, maxZ; + rsgMeshComputeBoundingBox(obj->mesh, + &minX, &minY, &minZ, + &maxX, &maxY, &maxZ); + //rsDebug("min", minX, minY, minZ); + //rsDebug("max", maxX, maxY, maxZ); + float4 sphere; + sphere.x = (maxX + minX) * 0.5f; + sphere.y = (maxY + minY) * 0.5f; + sphere.z = (maxZ + minZ) * 0.5f; + float3 radius; + radius.x = (maxX - sphere.x); + radius.y = (maxY - sphere.y); + radius.z = (maxZ - sphere.z); + + sphere.w = length(radius); + obj->boundingSphere = sphere; + obj->bVolInitialized = 1; + //rsDebug("Sphere", sphere); + } + + getTransformedSphere(obj); + + return !rsIsSphereInFrustum(&obj->worldBoundingSphere, + &gFrustumPlanes[0], &gFrustumPlanes[1], + &gFrustumPlanes[2], &gFrustumPlanes[3], + &gFrustumPlanes[3], &gFrustumPlanes[4]); +} + +static void sortToBucket(SgDrawable *obj) { + // Not loaded yet + if (!rsIsObject(obj->mesh) || obj->cullType == 2) { + return; + } + + // check to see if we are culling this object and if it's + // outside the frustum + if (obj->cullType == 0 && frustumCulled(obj)) { +#ifdef DEBUG_RENDERABLES + rsDebug("Culled", obj); + printName(obj->name); +#endif //DEBUG_RENDERABLES + return; + } + const SgRenderState *renderState = (const SgRenderState *)rsGetElementAt(obj->render_state, 0); + if (rsIsObject(renderState->ps)) { + gBackToFront[gBackToFrontCount++] = (uint32_t)obj; + } else { + gFrontToBack[gFrontToBackCount++] = (uint32_t)obj; + } +} + +static void updateActiveCamera(rs_allocation cam) { + gActiveCamera = (SgCamera *)rsGetElementAt(cam, 0); + + rsExtractFrustumPlanes(&gActiveCamera->viewProj, + &gFrustumPlanes[0], &gFrustumPlanes[1], + &gFrustumPlanes[2], &gFrustumPlanes[3], + &gFrustumPlanes[3], &gFrustumPlanes[4]); +} + +static void prepareCameras() { + // now compute all the camera matrices + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsForEach(gCameraScript, gCameras, nullAlloc, &aspect, sizeof(aspect)); +} + +static void drawSorted() { + for (int i = 0; i < gFrontToBackCount; i ++) { + SgDrawable *current = (SgDrawable*)gFrontToBack[i]; + draw(current); + } + + for (int i = 0; i < gBackToFrontCount; i ++) { + SgDrawable *current = (SgDrawable*)gBackToFront[i]; + draw(current); + } +} + +static void drawAllObjects(rs_allocation allObj) { + if (!rsIsObject(allObj)) { + return; + } + int numDrawables = rsAllocationGetDimX(allObj); + for (int i = 0; i < numDrawables; i ++) { + rs_allocation *drawAlloc = (rs_allocation*)rsGetElementAt(allObj, i); + SgDrawable *current = (SgDrawable*)rsGetElementAt(*drawAlloc, 0); + sortToBucket(current); + } + drawSorted(); +} + +void root(const void *v_in, void *v_out) { + + //rsDebug("=============================================================================", 0); + // first step is to update the transform hierachy + rsForEach(gTransformScript, gRootNode->children, nullAlloc, 0, 0); + + prepareCameras(); + + rsgClearDepth(1.0f); + + int numDrawables = rsAllocationGetDimX(gDrawableObjects); + if (rsIsObject(gRenderPasses)) { + int numPasses = rsAllocationGetDimX(gRenderPasses); + for (uint i = 0; i < numPasses; i ++) { + gFrontToBackCount = 0; + gBackToFrontCount = 0; + SgRenderPass *pass = (SgRenderPass*)rsGetElementAt(gRenderPasses, i); + if (rsIsObject(pass->color_target)) { + rsgBindColorTarget(pass->color_target, 0); + } + if (rsIsObject(pass->depth_target)) { + rsgBindDepthTarget(pass->depth_target); + } + if (!rsIsObject(pass->color_target) && + !rsIsObject(pass->depth_target)) { + rsgClearAllRenderTargets(); + } + updateActiveCamera(pass->camera); + if (pass->should_clear_color) { + rsgClearColor(pass->clear_color.x, pass->clear_color.y, + pass->clear_color.z, pass->clear_color.w); + } + if (pass->should_clear_depth) { + rsgClearDepth(pass->clear_depth); + } + drawAllObjects(pass->objects); + } + } else { + gFrontToBackCount = 0; + gBackToFrontCount = 0; + rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgClearDepth(1.0f); + rs_allocation *camAlloc = (rs_allocation*)rsGetElementAt(gCameras, 1); + updateActiveCamera(*camAlloc); + drawAllObjects(gDrawableObjects); + } +} + +static bool intersect(const SgDrawable *obj, float3 pnt, float3 vec) { + // Solving for t^2 + Bt + C = 0 + float3 originMinusCenter = pnt - obj->worldBoundingSphere.xyz; + float B = dot(originMinusCenter, vec) * 2.0f; + float C = dot(originMinusCenter, originMinusCenter) - + obj->worldBoundingSphere.w * obj->worldBoundingSphere.w; + + float discriminant = B * B - 4.0f * C; + if (discriminant < 0.0f) { + return false; + } + discriminant = sqrt(discriminant); + + float t0 = (-B - discriminant) * 0.5f; + float t1 = (-B + discriminant) * 0.5f; + + if (t0 > t1) { + float temp = t0; + t0 = t1; + t1 = temp; + } + + // The sphere is behind us + if (t1 < 0.0f) { + return false; + } + return true; +} + +// Search through sorted and culled objects +void pick(int screenX, int screenY) { + float3 pnt, vec; + getCameraRay(gActiveCamera, screenX, screenY, &pnt, &vec); + + for (int i = 0; i < gFrontToBackCount; i ++) { + SgDrawable *current = (SgDrawable*)gFrontToBack[i]; + bool isPicked = intersect(current, pnt, vec); + if (isPicked) { + current->cullType = 2; + } + } + + for (int i = 0; i < gBackToFrontCount; i ++) { + SgDrawable *current = (SgDrawable*)gBackToFront[i]; + bool isPicked = intersect(current, pnt, vec); + if (isPicked) { + current->cullType = 2; + } + } +} diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph.rs new file mode 100644 index 0000000..421105b --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph.rs @@ -0,0 +1,90 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma version(1) + +#pragma rs java_package_name(com.android.scenegraph) + +#include "rs_graphics.rsh" +#include "transform_def.rsh" + +rs_program_vertex gPVBackground; +rs_program_fragment gPFBackground; + +rs_allocation gRobotTex; +rs_mesh gRobotMesh; + +rs_program_store gPFSBackground; + +rs_allocation gDummyAlloc; +rs_script gRenderLoop; + +bool gInitialized = false; + +float gRotate; + +void init() { + gRotate = 0.0f; +} + +static int pos = 50; +static float gRotateY = 120.0f; +static float3 gLookAt = 0; +static float gZoom = 50.0f; +static void displayLoading() { + if (rsIsObject(gRobotTex) && rsIsObject(gRobotMesh)) { + rsgBindProgramVertex(gPVBackground); + rs_matrix4x4 proj; + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f); + rsgProgramVertexLoadProjectionMatrix(&proj); + + rsgBindProgramFragment(gPFBackground); + rsgBindProgramStore(gPFSBackground); + rsgBindTexture(gPFBackground, 0, gRobotTex); + + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + // Position our models on the screen + gRotateY += rsGetDt()*100; + rsMatrixTranslate(&matrix, 0, 0, -gZoom); + rsMatrixRotate(&matrix, 20.0f, 1.0f, 0.0f, 0.0f); + rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f); + rsMatrixScale(&matrix, 0.2f, 0.2f, 0.2f); + rsgProgramVertexLoadModelMatrix(&matrix); + rsgDrawMesh(gRobotMesh); + } + + uint width = rsgGetWidth(); + uint height = rsgGetHeight(); + int left = 0, right = 0, top = 0, bottom = 0; + const char* text = "Initializing..."; + rsgMeasureText(text, &left, &right, &top, &bottom); + int centeredPos = width / 2 - (right - left) / 2; + rsgDrawText(text, centeredPos, height / 2 + height / 10); +} + +int root(void) { + rs_allocation nullAlloc; + if (!gInitialized) { + rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgClearDepth(1.0f); + displayLoading(); + return 30; + } + + rsForEach(gRenderLoop, gDummyAlloc, nullAlloc); + + return 10; +} diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform.rs new file mode 100644 index 0000000..6bc5317 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform.rs @@ -0,0 +1,111 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma version(1) + +#pragma rs java_package_name(com.android.modelviewer) + +//#define DEBUG_TRANSFORMS + +#include "transform_def.rsh" + +rs_script gTransformScript; + +typedef struct { + int changed; + rs_matrix4x4 *mat; +} ParentData; + +static void appendTransformation(int type, float4 data, rs_matrix4x4 *mat) { + rs_matrix4x4 temp; + + switch (type) { + case TRANSFORM_TRANSLATE: + rsMatrixLoadTranslate(&temp, data.x, data.y, data.z); + break; + case TRANSFORM_ROTATE: + rsMatrixLoadRotate(&temp, data.w, data.x, data.y, data.z); + break; + case TRANSFORM_SCALE: + rsMatrixLoadScale(&temp, data.x, data.y, data.z); + break; + } + rsMatrixMultiply(mat, &temp); +} + +void root(const rs_allocation *v_in, rs_allocation *v_out, const void *usrData) { + + SgTransform *data = (SgTransform *)rsGetElementAt(*v_in, 0); + const ParentData *parent = (const ParentData *)usrData; + +#ifdef DEBUG_TRANSFORMS + rsDebug("**** Transform data", (int)data); + rsDebug("Transform is dirty", data->isDirty); + rsDebug("Transform parent", (int)parent); + rsDebug("Transform child ", (int)data->children.p); + printName(data->name); +#endif //DEBUG_TRANSFORMS + + rs_matrix4x4 *localMat = &data->localMat; + rs_matrix4x4 *globalMat = &data->globalMat; + + ParentData toChild; + toChild.changed = 0; + toChild.mat = globalMat; + + // Refresh matrices if dirty + if (data->isDirty) { + toChild.changed = 1; + + bool resetLocal = false; + for (int i = 0; i < 16; i ++) { + if (data->transformTypes[i] == TRANSFORM_NONE) { + break; + } + if (!resetLocal) { + // Reset our local matrix only for component transforms + rsMatrixLoadIdentity(localMat); + resetLocal = true; + } +#ifdef DEBUG_TRANSFORMS + if (rsIsObject(data->transformNames[i])) { + rsDebug((const char*)rsGetElementAt(data->transformNames[i], 0), + data->transforms[i]); + } else { + rsDebug("Transform adding transformation type", data->transformTypes[i]); + rsDebug("Transform adding transformation", data->transforms[i]); + } +#endif //DEBUG_TRANSFORMS + appendTransformation(data->transformTypes[i], data->transforms[i], localMat); + } + } + + if (parent) { + if (parent->changed || data->isDirty) { + toChild.changed = 1; + + rsMatrixLoad(globalMat, parent->mat); + rsMatrixMultiply(globalMat, localMat); + } + } else if (data->isDirty) { + rsMatrixLoad(globalMat, localMat); + } + + if (rsIsObject(data->children)) { + rs_allocation nullAlloc; + rsForEach(gTransformScript, data->children, nullAlloc, &toChild, sizeof(toChild)); + } + + data->isDirty = 0; +} diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform_def.rsh b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform_def.rsh new file mode 100644 index 0000000..e093bf9 --- /dev/null +++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform_def.rsh @@ -0,0 +1,179 @@ +// Copyright (C) 2009 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma version(1) + +#pragma rs java_package_name(com.android.scenegraph) + +#include "rs_graphics.rsh" + +#define TRANSFORM_NONE 0 +#define TRANSFORM_TRANSLATE 1 +#define TRANSFORM_ROTATE 2 +#define TRANSFORM_SCALE 3 + +static void printName(rs_allocation name) { + rsDebug("Object Name: ", 0); + if (!rsIsObject(name)) { + rsDebug("no name", 0); + return; + } + + rsDebug((const char*)rsGetElementAt(name, 0), 0); +} + +typedef struct __attribute__((packed, aligned(4))) SgTransform { + rs_matrix4x4 globalMat; + rs_matrix4x4 localMat; + + float4 transforms[16]; + int transformTypes[16]; + rs_allocation transformNames[16]; + + int isDirty; + + rs_allocation children; + + rs_allocation name; +} SgTransform; + +typedef struct RenderState_s { + rs_program_vertex pv; + rs_program_fragment pf; + rs_program_store ps; + rs_program_raster pr; +} SgRenderState; + +typedef struct Drawable_s { + rs_allocation render_state; + rs_allocation pv_const; + rs_allocation pf_const; + rs_allocation pf_textures[8]; + int pf_num_textures; + rs_mesh mesh; + int meshIndex; + rs_allocation transformMatrix; + rs_allocation name; + float4 boundingSphere; + float4 worldBoundingSphere; + int bVolInitialized; + int cullType; // specifies whether to frustum cull +} SgDrawable; + +typedef struct RenderPass_s { + rs_allocation color_target; + rs_allocation depth_target; + rs_allocation camera; + rs_allocation objects; + + float4 clear_color; + float clear_depth; + bool should_clear_color; + bool should_clear_depth; +} SgRenderPass; + +typedef struct __attribute__((packed, aligned(4))) Camera_s { + rs_matrix4x4 proj; + rs_matrix4x4 view; + rs_matrix4x4 viewProj; + float4 position; + float near; + float far; + float horizontalFOV; + float aspect; + rs_allocation name; + rs_allocation transformMatrix; +} SgCamera; + +typedef struct VShaderParams_s { + rs_matrix4x4 model; + rs_matrix4x4 viewProj; +} VShaderParams; + +typedef struct FShaderParams_s { + float4 cameraPos; +} FShaderParams; + +typedef struct FBlurOffsets_s { + float blurOffset0; + float blurOffset1; + float blurOffset2; + float blurOffset3; +} FBlurOffsets; + +typedef struct VertexShaderInputs_s { + float4 position; + float3 normal; + float2 texture0; +} VertexShaderInputs; + +static void printCameraInfo(SgCamera *cam) { + rsDebug("***** Camera information. ptr:", cam); + printName(cam->name); + const SgTransform *camTransform = (const SgTransform *)rsGetElementAt(cam->transformMatrix, 0); + rsDebug("Transform name:", camTransform); + printName(camTransform->name); + + rsDebug("Aspect: ", cam->aspect); + rsDebug("Near: ", cam->near); + rsDebug("Far: ", cam->far); + rsDebug("Fov: ", cam->horizontalFOV); + rsDebug("Position: ", cam->position); + rsDebug("Proj: ", &cam->proj); + rsDebug("View: ", &cam->view); +} + +static void getCameraRay(const SgCamera *cam, int screenX, int screenY, float3 *pnt, float3 *vec) { + rsDebug("=================================", screenX); + rsDebug("Point X", screenX); + rsDebug("Point Y", screenY); + + rs_matrix4x4 mvpInv; + rsMatrixLoad(&mvpInv, &cam->viewProj); + rsMatrixInverse(&mvpInv); + + float width = (float)rsgGetWidth(); + float height = (float)rsgGetHeight(); + + float4 pos = {(float)screenX, height - (float)screenY, 0.0f, 1.0f}; + + pos.x /= width; + pos.y /= height; + + rsDebug("Pre Norm X", pos.x); + rsDebug("Pre Norm Y", pos.y); + + pos.xy = pos.xy * 2.0f - 1.0f; + + rsDebug("Norm X", pos.x); + rsDebug("Norm Y", pos.y); + + pos = rsMatrixMultiply(&mvpInv, pos); + float oneOverW = 1.0f / pos.w; + pos.xyz *= oneOverW; + + rsDebug("World X", pos.x); + rsDebug("World Y", pos.y); + rsDebug("World Z", pos.z); + + rsDebug("Cam X", cam->position.x); + rsDebug("Cam Y", cam->position.y); + rsDebug("Cam Z", cam->position.z); + + *vec = normalize(pos.xyz - cam->position.xyz); + rsDebug("Vec X", vec->x); + rsDebug("Vec Y", vec->y); + rsDebug("Vec Z", vec->z); + *pnt = cam->position.xyz; +} |