Home | History | Annotate | Download | only in scenegraph
      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