TestAppRS.java revision c71343acc469db7ec351db2344032801e0e1b30a
1/*
2 * Copyright (C) 2011-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 TestAppRS {
37
38    private static String modelName = "orientation_test.dae";
39    private static String TAG = "TestAppRS";
40    private static String mFilePath = "";
41
42    int mWidth;
43    int mHeight;
44
45    boolean mUseBlur;
46
47    TestAppLoadingScreen mLoadingScreen;
48
49    // Used to asynchronously load scene elements like meshes and transform hierarchies
50    SceneLoadedCallback mLoadedCallback = new SceneLoadedCallback() {
51        public void run() {
52            prepareToRender(mLoadedScene);
53        }
54    };
55
56    // Top level class that initializes all the elements needed to use the scene graph
57    SceneManager mSceneManager;
58
59    // Used to move the camera around in the 3D world
60    TouchHandler mTouchHandler;
61
62    private Resources mRes;
63    private RenderScriptGL mRS;
64
65    // Shaders
66    private FragmentShader mPaintF;
67    private FragmentShader mLightsF;
68    private FragmentShader mAluminumF;
69    private FragmentShader mPlasticF;
70    private FragmentShader mDiffuseF;
71    private FragmentShader mTextureF;
72    private VertexShader mGenericV;
73
74    Scene mActiveScene;
75
76    // This is a part of the test app, it's used to tests multiple render passes and is toggled
77    // on and off in the menu, off by default
78    void toggleBlur() {
79        mUseBlur = !mUseBlur;
80
81        mActiveScene.clearRenderPasses();
82        initRenderPasses();
83        mActiveScene.initRenderPassRS(mRS, mSceneManager);
84
85        // This is just a hardcoded object in the scene that gets turned on and off for the demo
86        // to make things look a bit better. This could be deleted in the cleanup
87        Renderable plane = (Renderable)mActiveScene.getRenderableByName("pPlaneShape1");
88        if (plane != null) {
89            plane.setVisible(!mUseBlur);
90        }
91    }
92
93    public void init(RenderScriptGL rs, Resources res, int width, int height) {
94        mUseBlur = false;
95        mRS = rs;
96        mRes = res;
97        mWidth = width;
98        mHeight = height;
99
100        mTouchHandler = new TouchHandler();
101
102        mSceneManager = SceneManager.getInstance();
103        // Initializes all the RS specific scenegraph elements
104        mSceneManager.initRS(mRS, mRes, mWidth, mHeight);
105
106        mLoadingScreen = new TestAppLoadingScreen(mRS, mRes);
107
108        // Initi renderscript stuff specific to the app. This will need to be abstracted out later.
109        FullscreenBlur.createRenderTargets(mRS, mWidth, mHeight);
110        initPaintShaders();
111
112        // Load a scene to render
113        mSceneManager.loadModel(mFilePath + modelName, mLoadedCallback);
114    }
115
116    // When a new model file is selected from the UI, this function gets called to init everything
117    void loadModel(String path) {
118        mLoadingScreen.showLoadingScreen(true);
119        mActiveScene.destroyRS();
120        mSceneManager.loadModel(path, mLoadedCallback);
121    }
122
123    public void onActionDown(float x, float y) {
124        mTouchHandler.onActionDown(x, y);
125    }
126
127    public void onActionScale(float scale) {
128        mTouchHandler.onActionScale(scale);
129    }
130
131    public void onActionMove(float x, float y) {
132        mTouchHandler.onActionMove(x, y);
133    }
134
135    FragmentShader createFromResource(int id, boolean addCubemap, Type constType) {
136        FragmentShader.Builder fb = new FragmentShader.Builder(mRS);
137        fb.setShaderConst(constType);
138        fb.setShader(mRes, id);
139        fb.addTexture(TextureType.TEXTURE_2D, "diffuse");
140        if (addCubemap) {
141            fb.addShaderTexture(TextureType.TEXTURE_CUBE, "reflection");
142        }
143        FragmentShader pf = fb.create();
144        pf.getProgram().bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0);
145        if (addCubemap) {
146            pf.getProgram().bindSampler(Sampler.CLAMP_LINEAR_MIP_LINEAR(mRS), 1);
147        }
148        return pf;
149    }
150
151    private void initPaintShaders() {
152        mGenericV = SceneManager.getDefaultVS();
153
154        ScriptField_CameraParams camParams = new ScriptField_CameraParams(mRS, 1);
155        Type camParamType = camParams.getAllocation().getType();
156        ScriptField_LightParams lightParams = new ScriptField_LightParams(mRS, 1);
157
158        mPaintF = createFromResource(R.raw.paintf, true, camParamType);
159        // Assign a reflection map
160        TextureCube envCube = new TextureCube("sdcard/scenegraph/", "cube_env.png");
161        mPaintF.appendSourceParams(new TextureParam("reflection", envCube));
162
163        mAluminumF = createFromResource(R.raw.metal, true, camParamType);
164        TextureCube diffCube = new TextureCube("sdcard/scenegraph/", "cube_spec.png");
165        mAluminumF.appendSourceParams(new TextureParam("reflection", diffCube));
166
167        mPlasticF = createFromResource(R.raw.plastic, false, camParamType);
168        mDiffuseF = createFromResource(R.raw.diffuse, false, camParamType);
169        mTextureF = SceneManager.getTextureFS();
170
171        FragmentShader.Builder fb = new FragmentShader.Builder(mRS);
172        fb.setObjectConst(lightParams.getAllocation().getType());
173        fb.setShader(mRes, R.raw.plastic_lights);
174        mLightsF = fb.create();
175
176        FullscreenBlur.initShaders(mRes, mRS);
177    }
178
179    void initRenderPasses() {
180        ArrayList<RenderableBase> allDraw = mActiveScene.getRenderables();
181        int numDraw = allDraw.size();
182
183        if (mUseBlur) {
184            FullscreenBlur.addBlurPasses(mActiveScene, mRS, mTouchHandler.getCamera());
185        }
186
187        RenderPass mainPass = new RenderPass();
188        mainPass.setClearColor(new Float4(1.0f, 1.0f, 1.0f, 1.0f));
189        mainPass.setShouldClearColor(true);
190        mainPass.setClearDepth(1.0f);
191        mainPass.setShouldClearDepth(true);
192        mainPass.setCamera(mTouchHandler.getCamera());
193        for (int i = 0; i < numDraw; i ++) {
194            mainPass.appendRenderable((Renderable)allDraw.get(i));
195        }
196        mActiveScene.appendRenderPass(mainPass);
197
198        if (mUseBlur) {
199            FullscreenBlur.addCompositePass(mActiveScene, mRS, mTouchHandler.getCamera());
200        }
201    }
202
203    private void addShadersToScene() {
204        mActiveScene.appendShader(mPaintF);
205        mActiveScene.appendShader(mLightsF);
206        mActiveScene.appendShader(mAluminumF);
207        mActiveScene.appendShader(mPlasticF);
208        mActiveScene.appendShader(mDiffuseF);
209        mActiveScene.appendShader(mTextureF);
210    }
211
212    public void prepareToRender(Scene s) {
213        mSceneManager.setActiveScene(s);
214        mActiveScene = s;
215        mTouchHandler.init(mActiveScene);
216        addShadersToScene();
217        RenderState plastic = new RenderState(mGenericV, mPlasticF, null, null);
218        RenderState diffuse = new RenderState(mGenericV, mDiffuseF, null, null);
219        RenderState paint = new RenderState(mGenericV, mPaintF, null, null);
220        RenderState aluminum = new RenderState(mGenericV, mAluminumF, null, null);
221        RenderState lights = new RenderState(mGenericV, mLightsF, null, null);
222        RenderState glassTransp = new RenderState(mGenericV, mPaintF,
223                                                  ProgramStore.BLEND_ALPHA_DEPTH_TEST(mRS), null);
224
225        initRenderPasses();
226
227        mActiveScene.assignRenderState(plastic);
228
229        mActiveScene.assignRenderStateToMaterial(diffuse, "lambert2$");
230
231        mActiveScene.assignRenderStateToMaterial(paint, "^Paint");
232        mActiveScene.assignRenderStateToMaterial(paint, "^Carbon");
233        mActiveScene.assignRenderStateToMaterial(paint, "^Glass");
234        mActiveScene.assignRenderStateToMaterial(paint, "^MainGlass");
235
236        mActiveScene.assignRenderStateToMaterial(aluminum, "^Metal");
237        mActiveScene.assignRenderStateToMaterial(aluminum, "^Brake");
238
239        mActiveScene.assignRenderStateToMaterial(glassTransp, "^GlassLight");
240
241        mActiveScene.assignRenderStateToMaterial(lights, "^LightBlinn");
242
243        Renderable plane = (Renderable)mActiveScene.getRenderableByName("pPlaneShape1");
244        if (plane != null) {
245            RenderState texState = new RenderState(mGenericV, mTextureF, null, null);
246            plane.setRenderState(texState);
247            plane.setVisible(!mUseBlur);
248        }
249
250        long start = System.currentTimeMillis();
251        mActiveScene.initRS();
252        long end = System.currentTimeMillis();
253        Log.v("TIMER", "Scene init time: " + (end - start));
254
255        mLoadingScreen.showLoadingScreen(false);
256    }
257}
258