Sample scene graph

Change-Id: I65b210b770121ac02c5857b48d2ec0d053133dd6
This commit is contained in:
Alex Sakhartchouk
2011-12-08 11:39:14 -08:00
parent 8030bfd9c8
commit a7a211b8a6
50 changed files with 4506 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
#
# 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.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
LOCAL_PACKAGE_NAME := SceneGraphTest
include $(BUILD_PACKAGE)

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.scenegraph">
<uses-permission
android:name="android.permission.INTERNET" />
<application android:label="SceneGraphTest">
<activity android:name="SceneGraph"
android:label="SceneGraphTest">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="FileSelector"
android:label="FileSelector"
android:hardwareAccelerated="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* 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.
*/
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/load_model"
android:title="@string/load_model" />
<item android:id="@+id/use_blur"
android:title="@string/use_blur" />
</menu>

View File

@@ -0,0 +1,15 @@
varying vec2 varTex0;
void main() {
vec2 blurCoord = varTex0;
blurCoord.x = varTex0.x + UNI_blurOffset0;
vec3 col = texture2D(UNI_Tex0, blurCoord).rgb;
blurCoord.x = varTex0.x + UNI_blurOffset1;
col += texture2D(UNI_Tex0, blurCoord).rgb;
blurCoord.x = varTex0.x + UNI_blurOffset2;
col += texture2D(UNI_Tex0, blurCoord).rgb;
blurCoord.x = varTex0.x + UNI_blurOffset3;
col += texture2D(UNI_Tex0, blurCoord).rgb;
gl_FragColor = vec4(col * 0.25, 0.0); //texture2D(UNI_Tex0, varTex0);
}

View File

@@ -0,0 +1,17 @@
varying vec2 varTex0;
void main() {
vec2 blurCoord = varTex0;
blurCoord.y = varTex0.y + UNI_blurOffset0;
vec3 col = texture2D(UNI_Tex0, blurCoord).rgb;
blurCoord.y = varTex0.y + UNI_blurOffset1;
col += texture2D(UNI_Tex0, blurCoord).rgb;
blurCoord.y = varTex0.y + UNI_blurOffset2;
col += texture2D(UNI_Tex0, blurCoord).rgb;
blurCoord.y = varTex0.y + UNI_blurOffset3;
col += texture2D(UNI_Tex0, blurCoord).rgb;
col = col * 0.25;
gl_FragColor = vec4(col, 0.0); //texture2D(UNI_Tex0, varTex0);
}

View File

@@ -0,0 +1,7 @@
varying vec2 varTex0;
void main() {
gl_Position = ATTRIB_position;
varTex0 = ATTRIB_texture0;
}

View File

@@ -0,0 +1,19 @@
varying vec3 varWorldPos;
varying vec3 varWorldNormal;
varying vec2 varTex0;
void main() {
vec3 V = normalize(UNI_cameraPos.xyz - varWorldPos.xyz);
vec3 worldNorm = (varWorldNormal);
vec3 light0Vec = V;
vec3 light0R = reflect(light0Vec, worldNorm);
float light0_Diffuse = dot(worldNorm, light0Vec);
vec2 t0 = varTex0.xy;
lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
col.xyz = col.xyz * light0_Diffuse * 1.2;
gl_FragColor = col; //vec4(0.0, 1.0, 0.0, 0.0);
}

View File

@@ -0,0 +1,23 @@
varying vec3 varWorldPos;
varying vec3 varWorldNormal;
varying vec2 varTex0;
void main() {
vec3 V = normalize(UNI_cameraPos.xyz - varWorldPos.xyz);
vec3 worldNorm = normalize(varWorldNormal);
vec3 light0Vec = V;
vec3 light0R = reflect(light0Vec, worldNorm);
float light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0);
float light0Spec = clamp(dot(-light0R, V), 0.001, 1.0);
float light0_Specular = pow(light0Spec, 15.0) * 0.5;
vec2 t0 = varTex0.xy;
lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
col.xyz = col.xyz * (textureCube(UNI_Tex1, worldNorm).rgb * 0.5 + vec3(light0_Diffuse));
col.xyz += light0_Specular * vec3(0.8, 0.8, 1.0);
gl_FragColor = col;
}

View File

@@ -0,0 +1,26 @@
varying vec3 varWorldPos;
varying vec3 varWorldNormal;
varying vec2 varTex0;
void main() {
vec3 V = normalize(UNI_cameraPos.xyz - varWorldPos.xyz);
vec3 worldNorm = normalize(varWorldNormal);
vec3 light0Vec = V;
vec3 light0R = reflect(light0Vec, worldNorm);
float light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.01, 0.99);
float light0Spec = clamp(dot(-light0R, V), 0.001, 1.0);
float light0_Specular = pow(light0Spec, 150.0) * 0.5;
vec2 t0 = varTex0.xy;
lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
col.xyz = col.xyz * light0_Diffuse * 1.1;
col.xyz += light0_Specular * vec3(0.8, 0.8, 1.0);
float fresnel = mix(pow(1.0 - light0_Diffuse, 15.0), 1.0, 0.1);
col.xyz = mix(col.xyz, textureCube(UNI_Tex1, -light0R).rgb * 2.4, fresnel);
col.w = 0.8;
gl_FragColor = col;
}

View File

@@ -0,0 +1,22 @@
varying vec3 varWorldPos;
varying vec3 varWorldNormal;
varying vec2 varTex0;
void main() {
vec3 V = normalize(UNI_cameraPos.xyz - varWorldPos.xyz);
vec3 worldNorm = normalize(varWorldNormal);
vec3 light0Vec = V;
vec3 light0R = reflect(light0Vec, worldNorm);
float light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0);
float light0Spec = clamp(dot(-light0R, V), 0.001, 1.0);
float light0_Specular = pow(light0Spec, 10.0) * 0.5;
vec2 t0 = varTex0.xy;
lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
col.xyz = col.xyz * light0_Diffuse * 1.2;
col.xyz += light0_Specular * vec3(0.8, 0.8, 1.0);
gl_FragColor = col;
}

Binary file not shown.

View File

@@ -0,0 +1,13 @@
varying vec2 varTex0;
void main() {
vec3 col = texture2D(UNI_Tex0, varTex0).rgb;
vec3 desat = vec3(0.299, 0.587, 0.114);
float lum = dot(desat, col);
float stepVal = step(lum, 0.8);
col = mix(col, vec3(0.0), stepVal)*0.8;
gl_FragColor = vec4(col, 0.0);
}

View File

@@ -0,0 +1,17 @@
varying vec3 varWorldPos;
varying vec3 varWorldNormal;
varying vec2 varTex0;
// This is where actual shader code begins
void main() {
vec4 objPos = ATTRIB_position;
vec4 worldPos = UNI_model * objPos;
gl_Position = UNI_viewProj * worldPos;
mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz);
vec3 worldNorm = model3 * ATTRIB_normal;
varWorldPos = worldPos.xyz;
varWorldNormal = worldNorm;
varTex0 = ATTRIB_texture0;
}

View File

@@ -0,0 +1,7 @@
varying vec2 varTex0;
void main() {
lowp vec4 col = texture2D(UNI_Tex0, varTex0).rgba;
gl_FragColor = col;
}

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* 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.
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<skip />
<string name="load_model">Load Model</string>
<string name="use_blur">Use Blur</string>
</resources>

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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) {
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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() {
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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() {
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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.");
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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
}

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}