1 /* 2 * Copyright (C) 2011 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 17 package com.android.scenegraph; 18 19 import java.lang.Math; 20 import java.util.ArrayList; 21 import java.util.HashMap; 22 import java.util.regex.Matcher; 23 import java.util.regex.Pattern; 24 25 import com.android.scenegraph.Camera; 26 import com.android.scenegraph.CompoundTransform; 27 import com.android.scenegraph.RenderPass; 28 import com.android.scenegraph.Renderable; 29 import com.android.scenegraph.SceneManager; 30 import com.android.scenegraph.TextureBase; 31 32 import android.content.res.Resources; 33 import android.os.AsyncTask; 34 import android.renderscript.*; 35 import android.renderscript.Mesh; 36 import android.renderscript.RenderScriptGL; 37 import android.util.Log; 38 39 /** 40 * @hide 41 */ 42 public class Scene extends SceneGraphBase { 43 private static String TIMER_TAG = "TIMER"; 44 45 CompoundTransform mRootTransforms; 46 HashMap<String, Transform> mTransformMap; 47 ArrayList<RenderPass> mRenderPasses; 48 ArrayList<LightBase> mLights; 49 ArrayList<Camera> mCameras; 50 ArrayList<FragmentShader> mFragmentShaders; 51 ArrayList<VertexShader> mVertexShaders; 52 ArrayList<RenderableBase> mRenderables; 53 HashMap<String, RenderableBase> mRenderableMap; 54 ArrayList<Texture2D> mTextures; 55 56 HashMap<String, ArrayList<Renderable> > mRenderableMeshMap; 57 58 // RS Specific stuff 59 ScriptField_SgTransform mTransformRSData; 60 61 RenderScriptGL mRS; 62 Resources mRes; 63 64 ScriptField_RenderPass_s mRenderPassAlloc; 65 66 public Scene() { 67 mRenderPasses = new ArrayList<RenderPass>(); 68 mLights = new ArrayList<LightBase>(); 69 mCameras = new ArrayList<Camera>(); 70 mFragmentShaders = new ArrayList<FragmentShader>(); 71 mVertexShaders = new ArrayList<VertexShader>(); 72 mRenderables = new ArrayList<RenderableBase>(); 73 mRenderableMap = new HashMap<String, RenderableBase>(); 74 mRenderableMeshMap = new HashMap<String, ArrayList<Renderable> >(); 75 mTextures = new ArrayList<Texture2D>(); 76 mRootTransforms = new CompoundTransform(); 77 mRootTransforms.setName("_scene_root_"); 78 mTransformMap = new HashMap<String, Transform>(); 79 } 80 81 public void appendTransform(Transform t) { 82 if (t == null) { 83 throw new RuntimeException("Adding null object"); 84 } 85 mRootTransforms.appendChild(t); 86 } 87 88 public CompoundTransform appendNewCompoundTransform() { 89 CompoundTransform t = new CompoundTransform(); 90 appendTransform(t); 91 return t; 92 } 93 94 public MatrixTransform appendNewMatrixTransform() { 95 MatrixTransform t = new MatrixTransform(); 96 appendTransform(t); 97 return t; 98 } 99 100 // temporary 101 public void addToTransformMap(Transform t) { 102 mTransformMap.put(t.getName(), t); 103 } 104 105 public Transform getTransformByName(String name) { 106 return mTransformMap.get(name); 107 } 108 109 public void appendRenderPass(RenderPass p) { 110 if (p == null) { 111 throw new RuntimeException("Adding null object"); 112 } 113 mRenderPasses.add(p); 114 } 115 116 public RenderPass appendNewRenderPass() { 117 RenderPass p = new RenderPass(); 118 appendRenderPass(p); 119 return p; 120 } 121 122 public void clearRenderPasses() { 123 mRenderPasses.clear(); 124 } 125 126 public void appendLight(LightBase l) { 127 if (l == null) { 128 throw new RuntimeException("Adding null object"); 129 } 130 mLights.add(l); 131 } 132 133 public void appendCamera(Camera c) { 134 if (c == null) { 135 throw new RuntimeException("Adding null object"); 136 } 137 mCameras.add(c); 138 } 139 140 public Camera appendNewCamera() { 141 Camera c = new Camera(); 142 appendCamera(c); 143 return c; 144 } 145 146 public void appendShader(FragmentShader f) { 147 if (f == null) { 148 throw new RuntimeException("Adding null object"); 149 } 150 mFragmentShaders.add(f); 151 } 152 153 public void appendShader(VertexShader v) { 154 if (v == null) { 155 throw new RuntimeException("Adding null object"); 156 } 157 mVertexShaders.add(v); 158 } 159 160 public ArrayList<Camera> getCameras() { 161 return mCameras; 162 } 163 164 public ArrayList<LightBase> getLights() { 165 return mLights; 166 } 167 168 public void appendRenderable(RenderableBase d) { 169 if (d == null) { 170 throw new RuntimeException("Adding null object"); 171 } 172 mRenderables.add(d); 173 if (d.getName() != null) { 174 mRenderableMap.put(d.getName(), d); 175 } 176 } 177 178 public Renderable appendNewRenderable() { 179 Renderable r = new Renderable(); 180 appendRenderable(r); 181 return r; 182 } 183 184 public ArrayList<RenderableBase> getRenderables() { 185 return mRenderables; 186 } 187 188 public RenderableBase getRenderableByName(String name) { 189 return mRenderableMap.get(name); 190 } 191 192 public void appendTextures(Texture2D tex) { 193 if (tex == null) { 194 throw new RuntimeException("Adding null object"); 195 } 196 mTextures.add(tex); 197 } 198 199 public void assignRenderStateToMaterial(RenderState renderState, String regex) { 200 Pattern pattern = Pattern.compile(regex); 201 int numRenderables = mRenderables.size(); 202 for (int i = 0; i < numRenderables; i ++) { 203 Renderable shape = (Renderable)mRenderables.get(i); 204 Matcher m = pattern.matcher(shape.mMaterialName); 205 if (m.find()) { 206 shape.setRenderState(renderState); 207 } 208 } 209 } 210 211 public void assignRenderState(RenderState renderState) { 212 int numRenderables = mRenderables.size(); 213 for (int i = 0; i < numRenderables; i ++) { 214 Renderable shape = (Renderable)mRenderables.get(i); 215 shape.setRenderState(renderState); 216 } 217 } 218 219 public void meshLoaded(Mesh m) { 220 ArrayList<Renderable> entries = mRenderableMeshMap.get(m.getName()); 221 int numEntries = entries.size(); 222 for (int i = 0; i < numEntries; i++) { 223 Renderable d = entries.get(i); 224 d.resolveMeshData(m); 225 } 226 } 227 228 void addToMeshMap(Renderable d) { 229 ArrayList<Renderable> entries = mRenderableMeshMap.get(d.mMeshName); 230 if (entries == null) { 231 entries = new ArrayList<Renderable>(); 232 mRenderableMeshMap.put(d.mMeshName, entries); 233 } 234 entries.add(d); 235 } 236 237 public void destroyRS() { 238 SceneManager sceneManager = SceneManager.getInstance(); 239 mTransformRSData = null; 240 sceneManager.mRenderLoop.bind_gRootNode(mTransformRSData); 241 sceneManager.mRenderLoop.set_gRenderableObjects(null); 242 mRenderPassAlloc = null; 243 sceneManager.mRenderLoop.set_gRenderPasses(null); 244 sceneManager.mRenderLoop.bind_gFrontToBack(null); 245 sceneManager.mRenderLoop.bind_gBackToFront(null); 246 sceneManager.mRenderLoop.set_gCameras(null); 247 248 mTransformMap = null; 249 mRenderPasses = null; 250 mLights = null; 251 mCameras = null; 252 mRenderables = null; 253 mRenderableMap = null; 254 mTextures = null; 255 mRenderableMeshMap = null; 256 mRootTransforms = null; 257 } 258 259 public void initRenderPassRS(RenderScriptGL rs, SceneManager sceneManager) { 260 if (mRenderPasses.size() != 0) { 261 mRenderPassAlloc = new ScriptField_RenderPass_s(mRS, mRenderPasses.size()); 262 for (int i = 0; i < mRenderPasses.size(); i ++) { 263 mRenderPassAlloc.set(mRenderPasses.get(i).getRsField(mRS, mRes), i, false); 264 } 265 mRenderPassAlloc.copyAll(); 266 sceneManager.mRenderLoop.set_gRenderPasses(mRenderPassAlloc.getAllocation()); 267 } 268 } 269 270 private void addDrawables(RenderScriptGL rs, Resources res, SceneManager sceneManager) { 271 Allocation drawableData = Allocation.createSized(rs, 272 Element.ALLOCATION(rs), 273 mRenderables.size()); 274 Allocation[] drawableAllocs = new Allocation[mRenderables.size()]; 275 for (int i = 0; i < mRenderables.size(); i ++) { 276 Renderable dI = (Renderable)mRenderables.get(i); 277 addToMeshMap(dI); 278 drawableAllocs[i] = dI.getRsField(rs, res).getAllocation(); 279 } 280 drawableData.copyFrom(drawableAllocs); 281 sceneManager.mRenderLoop.set_gRenderableObjects(drawableData); 282 283 initRenderPassRS(rs, sceneManager); 284 } 285 286 private void addShaders(RenderScriptGL rs, Resources res, SceneManager sceneManager) { 287 if (mVertexShaders.size() > 0) { 288 Allocation shaderData = Allocation.createSized(rs, Element.ALLOCATION(rs), 289 mVertexShaders.size()); 290 Allocation[] shaderAllocs = new Allocation[mVertexShaders.size()]; 291 for (int i = 0; i < mVertexShaders.size(); i ++) { 292 VertexShader sI = mVertexShaders.get(i); 293 shaderAllocs[i] = sI.getRSData().getAllocation(); 294 } 295 shaderData.copyFrom(shaderAllocs); 296 sceneManager.mRenderLoop.set_gVertexShaders(shaderData); 297 } 298 299 if (mFragmentShaders.size() > 0) { 300 Allocation shaderData = Allocation.createSized(rs, Element.ALLOCATION(rs), 301 mFragmentShaders.size()); 302 Allocation[] shaderAllocs = new Allocation[mFragmentShaders.size()]; 303 for (int i = 0; i < mFragmentShaders.size(); i ++) { 304 FragmentShader sI = mFragmentShaders.get(i); 305 shaderAllocs[i] = sI.getRSData().getAllocation(); 306 } 307 shaderData.copyFrom(shaderAllocs); 308 sceneManager.mRenderLoop.set_gFragmentShaders(shaderData); 309 } 310 } 311 312 public void initRS() { 313 SceneManager sceneManager = SceneManager.getInstance(); 314 mRS = SceneManager.getRS(); 315 mRes = SceneManager.getRes(); 316 long start = System.currentTimeMillis(); 317 mTransformRSData = mRootTransforms.getRSData(); 318 long end = System.currentTimeMillis(); 319 Log.v(TIMER_TAG, "Transform init time: " + (end - start)); 320 321 start = System.currentTimeMillis(); 322 323 sceneManager.mRenderLoop.bind_gRootNode(mTransformRSData); 324 end = System.currentTimeMillis(); 325 Log.v(TIMER_TAG, "Script init time: " + (end - start)); 326 327 start = System.currentTimeMillis(); 328 addDrawables(mRS, mRes, sceneManager); 329 end = System.currentTimeMillis(); 330 Log.v(TIMER_TAG, "Renderable init time: " + (end - start)); 331 332 addShaders(mRS, mRes, sceneManager); 333 334 Allocation opaqueBuffer = null; 335 if (mRenderables.size() > 0) { 336 opaqueBuffer = Allocation.createSized(mRS, Element.U32(mRS), mRenderables.size()); 337 } 338 Allocation transparentBuffer = null; 339 if (mRenderables.size() > 0) { 340 transparentBuffer = Allocation.createSized(mRS, Element.U32(mRS), mRenderables.size()); 341 } 342 343 sceneManager.mRenderLoop.bind_gFrontToBack(opaqueBuffer); 344 sceneManager.mRenderLoop.bind_gBackToFront(transparentBuffer); 345 346 if (mCameras.size() > 0) { 347 Allocation cameraData; 348 cameraData = Allocation.createSized(mRS, Element.ALLOCATION(mRS), mCameras.size()); 349 Allocation[] cameraAllocs = new Allocation[mCameras.size()]; 350 for (int i = 0; i < mCameras.size(); i ++) { 351 cameraAllocs[i] = mCameras.get(i).getRSData().getAllocation(); 352 } 353 cameraData.copyFrom(cameraAllocs); 354 sceneManager.mRenderLoop.set_gCameras(cameraData); 355 } 356 357 if (mLights.size() > 0) { 358 Allocation lightData = Allocation.createSized(mRS, 359 Element.ALLOCATION(mRS), 360 mLights.size()); 361 Allocation[] lightAllocs = new Allocation[mLights.size()]; 362 for (int i = 0; i < mLights.size(); i ++) { 363 lightAllocs[i] = mLights.get(i).getRSData().getAllocation(); 364 } 365 lightData.copyFrom(lightAllocs); 366 sceneManager.mRenderLoop.set_gLights(lightData); 367 } 368 } 369 } 370 371 372 373 374