1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.testapp;
18
19import java.util.ArrayList;
20import java.util.HashMap;
21import java.util.Map;
22import java.util.Vector;
23
24import com.android.scenegraph.*;
25import com.android.scenegraph.SceneManager.SceneLoadedCallback;
26
27import android.content.res.Resources;
28import android.graphics.Bitmap;
29import android.graphics.BitmapFactory;
30import android.os.AsyncTask;
31import android.renderscript.*;
32import android.renderscript.Program.TextureType;
33import android.util.Log;
34
35// This is where the scenegraph and the rendered objects are initialized and used
36public class SimpleAppRS {
37    SceneManager mSceneManager;
38
39    RenderScriptGL mRS;
40    Resources mRes;
41
42    Scene mScene;
43    Mesh mSimpleMesh;
44    Mesh mSphereMesh;
45    Mesh mCubeMesh;
46
47    public void init(RenderScriptGL rs, Resources res, int width, int height) {
48        mRS = rs;
49        mRes = res;
50        mSceneManager = SceneManager.getInstance();
51        mSceneManager.initRS(mRS, mRes, width, height);
52
53        mScene = new Scene();
54
55        setupGeometry();
56        setupColoredQuad();
57        setupTexturedQuad();
58        setupShadedGeometry();
59        setupCamera();
60        setupRenderPass();
61
62        mSceneManager.setActiveScene(mScene);
63
64        mScene.initRS();
65        mRS.bindRootScript(mSceneManager.getRenderLoop());
66    }
67
68    private void setupGeometry() {
69        Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS, 3,
70                                                         Mesh.TriangleMeshBuilder.TEXTURE_0);
71
72        // Create four vertices with texture coordinates
73        tmb.setTexture(0.0f, 1.0f).addVertex(-1.0f, 1.0f, 0.0f);
74        tmb.setTexture(0.0f, 0.0f).addVertex(-1.0f, -1.0f, 0.0f);
75        tmb.setTexture(1.0f, 0.0f).addVertex(1.0f, -1.0f, 0.0f);
76        tmb.setTexture(1.0f, 1.0f).addVertex(1.0f, 1.0f, 0.0f);
77
78        tmb.addTriangle(0, 1, 2);
79        tmb.addTriangle(2, 3, 0);
80        mSimpleMesh = tmb.create(true);
81
82        // Load a file that constains two pieces of geometry, a sphere and a cube
83        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.unit_obj);
84        for (int i = 0; i < model.getIndexEntryCount(); i ++) {
85            FileA3D.IndexEntry entry = model.getIndexEntry(i);
86            if (entry != null && entry.getName().equals("CubeMesh")) {
87                mCubeMesh = entry.getMesh();
88            } else if (entry != null && entry.getName().equals("SphereMesh")) {
89                mSphereMesh = entry.getMesh();
90            }
91        }
92    }
93
94    private void setupColoredQuad() {
95        // Built-in shader that provides position, texcoord and normal
96        VertexShader genericV = SceneManager.getDefaultVS();
97        // Built-in shader that displays a color
98        FragmentShader colorF = SceneManager.getColorFS();
99        RenderState colorRS = new RenderState(genericV, colorF, null, null);
100
101        // Draw a simple colored quad
102        Renderable quad = mScene.appendNewRenderable();
103        quad.setMesh(mSimpleMesh);
104        // Our shader has a constant input called "color"
105        // This tells the scenegraph to assign the following float3 to that input
106        quad.appendSourceParams(new Float4Param("color", 0.2f, 0.3f, 0.4f));
107        quad.setRenderState(colorRS);
108    }
109
110    private void setupTexturedQuad() {
111        // Built-in shader that provides position, texcoord and normal
112        VertexShader genericV = SceneManager.getDefaultVS();
113        // Built-in shader that displays a texture
114        FragmentShader textureF = SceneManager.getTextureFS();
115        // We want to use transparency based on the alpha channel of the texture
116        ProgramStore alphaBlend = ProgramStore.BLEND_ALPHA_DEPTH_TEST(mRS);
117        RenderState texRS = new RenderState(genericV, textureF, alphaBlend, null);
118
119        // Draw a textured quad
120        Renderable quad = mScene.appendNewRenderable();
121        quad.setMesh(mSimpleMesh);
122        // Make a transform to position the quad
123        CompoundTransform t = mScene.appendNewCompoundTransform();
124        t.addTranslate("position", new Float3(2, 2, 0));
125        quad.setTransform(t);
126        // Our fragment shader has a constant texture input called "color"
127        // This will assign an icon from drawables to that input
128        quad.appendSourceParams(new TextureParam("color", new Texture2D(R.drawable.icon)));
129        quad.setRenderState(texRS);
130    }
131
132    private FragmentShader createLambertShader() {
133        // Describe what constant inputs our shader wants
134        Element.Builder b = new Element.Builder(mRS);
135        b.add(Element.F32_4(mRS), "cameraPos");
136
137        // Create a shader from a text file in resources
138        FragmentShader.Builder fb = new FragmentShader.Builder(mRS);
139        // Tell the shader what constants we want
140        fb.setShaderConst(new Type.Builder(mRS, b.create()).setX(1).create());
141        // Shader code location
142        fb.setShader(mRes, R.raw.diffuse);
143        // We want a texture called diffuse on our shader
144        fb.addTexture(TextureType.TEXTURE_2D, "diffuse");
145        FragmentShader shader = fb.create();
146        mScene.appendShader(shader);
147        return shader;
148    }
149
150    private void setupShadedGeometry() {
151        // Built-in shader that provides position, texcoord and normal
152        VertexShader genericV = SceneManager.getDefaultVS();
153        // Custom shader
154        FragmentShader diffuseF = createLambertShader();
155        RenderState diffuseRS = new RenderState(genericV, diffuseF, null, null);
156
157        // Draw a sphere
158        Renderable sphere = mScene.appendNewRenderable();
159        // Use the sphere geometry loaded earlier
160        sphere.setMesh(mSphereMesh);
161        // Make a transform to position the sphere
162        CompoundTransform t = mScene.appendNewCompoundTransform();
163        t.addTranslate("position", new Float3(-1, 2, 3));
164        t.addScale("scale", new Float3(1.4f, 1.4f, 1.4f));
165        sphere.setTransform(t);
166        // Tell the renderable which texture to use when we draw
167        // This will mean a texture param in the shader called "diffuse"
168        // will be assigned a texture called red.jpg
169        sphere.appendSourceParams(new TextureParam("diffuse", new Texture2D("", "red.jpg")));
170        sphere.setRenderState(diffuseRS);
171
172        // Draw a cube
173        Renderable cube = mScene.appendNewRenderable();
174        cube.setMesh(mCubeMesh);
175        t = mScene.appendNewCompoundTransform();
176        t.addTranslate("position", new Float3(-2, -2.1f, 0));
177        t.addRotate("rotateX", new Float3(1, 0, 0), 30);
178        t.addRotate("rotateY", new Float3(0, 1, 0), 30);
179        t.addScale("scale", new Float3(2, 2, 2));
180        cube.setTransform(t);
181        cube.appendSourceParams(new TextureParam("diffuse", new Texture2D("", "orange.jpg")));
182        cube.setRenderState(diffuseRS);
183    }
184
185    private void setupCamera() {
186        Camera camera = mScene.appendNewCamera();
187        camera.setFar(200);
188        camera.setNear(0.1f);
189        camera.setFOV(60);
190        CompoundTransform cameraTransform = mScene.appendNewCompoundTransform();
191        cameraTransform.addTranslate("camera", new Float3(0, 0, 10));
192        camera.setTransform(cameraTransform);
193    }
194
195    private void setupRenderPass() {
196        RenderPass mainPass = mScene.appendNewRenderPass();
197        mainPass.setClearColor(new Float4(1.0f, 1.0f, 1.0f, 1.0f));
198        mainPass.setShouldClearColor(true);
199        mainPass.setClearDepth(1.0f);
200        mainPass.setShouldClearDepth(true);
201        mainPass.setCamera(mScene.getCameras().get(0));
202        ArrayList<RenderableBase> allRender = mScene.getRenderables();
203        for (RenderableBase renderable : allRender) {
204            mainPass.appendRenderable((Renderable)renderable);
205        }
206    }
207}
208