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