1a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk/*
2a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * Copyright (C) 2011 The Android Open Source Project
3a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk *
4a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License");
5a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * you may not use this file except in compliance with the License.
6a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * You may obtain a copy of the License at
7a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk *
8a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk *      http://www.apache.org/licenses/LICENSE-2.0
9a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk *
10a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * Unless required by applicable law or agreed to in writing, software
11a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS,
12a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * See the License for the specific language governing permissions and
14a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * limitations under the License.
15a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk */
16a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
17a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukpackage com.android.scenegraph;
18a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
19a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.io.File;
20a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.io.IOException;
21a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.io.InputStream;
22a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.io.FileInputStream;
23a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.io.BufferedInputStream;
24a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.io.Writer;
25a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.util.ArrayList;
26a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.util.HashMap;
27a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.util.Map;
28a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.util.Vector;
29a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
30a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.content.res.Resources;
31a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.graphics.Bitmap;
32a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.graphics.BitmapFactory;
33a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.os.AsyncTask;
34a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.renderscript.*;
35a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.renderscript.Allocation.MipmapControl;
36a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.renderscript.Element.Builder;
37a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.renderscript.Font.Style;
38a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.renderscript.Program.TextureType;
39a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.renderscript.ProgramStore.DepthFunc;
40a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.util.Log;
41a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport com.android.scenegraph.SceneManager.SceneLoadedCallback;
42a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
43a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
44a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukpublic class ColladaScene {
45a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
46a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private String modelName;
47a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private static String TAG = "ColladaScene";
48a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private final int STATE_LAST_FOCUS = 1;
491168868e766f0696c30f644292a5a833ee3983e4Alex Sakhartchouk    boolean mLoadFromSD = false;
50a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
51a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    SceneLoadedCallback mCallback;
52a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
53a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    public ColladaScene(String name, SceneLoadedCallback cb) {
54a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        modelName = name;
55a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        mCallback = cb;
56a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    }
57a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
58a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    public void init(RenderScriptGL rs, Resources res) {
59a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        mRS = rs;
60a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        mRes = res;
61a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
62f92189d2aea9856c11c26ebe392cd53dd969c0b8Alex Sakhartchouk        mLoadFromSD = SceneManager.isSDCardPath(modelName);
631168868e766f0696c30f644292a5a833ee3983e4Alex Sakhartchouk
641168868e766f0696c30f644292a5a833ee3983e4Alex Sakhartchouk        new ColladaLoaderTask().execute(modelName);
65a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    }
66a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
67a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private Resources mRes;
68a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private RenderScriptGL mRS;
69a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    Scene mActiveScene;
70a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
71a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private class ColladaLoaderTask extends AsyncTask<String, Void, Boolean> {
72a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        ColladaParser sceneSource;
73a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        protected Boolean doInBackground(String... names) {
741168868e766f0696c30f644292a5a833ee3983e4Alex Sakhartchouk            String rootDir = names[0].substring(0, names[0].lastIndexOf('/') + 1);
75a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            long start = System.currentTimeMillis();
76a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            sceneSource = new ColladaParser();
77a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            InputStream is = null;
78a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            try {
79a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                if (!mLoadFromSD) {
80a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                    is = mRes.getAssets().open(names[0]);
81a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                } else {
821168868e766f0696c30f644292a5a833ee3983e4Alex Sakhartchouk                    File f = new File(names[0]);
83a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                    is = new BufferedInputStream(new FileInputStream(f));
84a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                }
85a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            } catch (IOException e) {
86a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                Log.e(TAG, "Could not open collada file");
87a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                return new Boolean(false);
88a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            }
89a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            long end = System.currentTimeMillis();
90a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            Log.v("TIMER", "Stream load time: " + (end - start));
91a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
92a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            start = System.currentTimeMillis();
931168868e766f0696c30f644292a5a833ee3983e4Alex Sakhartchouk            sceneSource.init(is, rootDir);
94a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            end = System.currentTimeMillis();
95a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            Log.v("TIMER", "Collada parse time: " + (end - start));
96a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            return new Boolean(true);
97a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
98a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
99a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        protected void onPostExecute(Boolean result) {
100a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mActiveScene = sceneSource.getScene();
101a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            if (mCallback != null) {
102a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                mCallback.mLoadedScene = mActiveScene;
103a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                mCallback.run();
104a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            }
105a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
1061168868e766f0696c30f644292a5a833ee3983e4Alex Sakhartchouk            String shortName = modelName.substring(0, modelName.lastIndexOf('.'));
1071168868e766f0696c30f644292a5a833ee3983e4Alex Sakhartchouk            new A3DLoaderTask().execute(shortName + ".a3d");
108a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
109a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    }
110a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
111a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private class A3DLoaderTask extends AsyncTask<String, Void, Boolean> {
112a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        protected Boolean doInBackground(String... names) {
113a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            long start = System.currentTimeMillis();
114a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            FileA3D model;
115a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            if (!mLoadFromSD) {
116a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                model = FileA3D.createFromAsset(mRS, mRes.getAssets(), names[0]);
117a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            } else {
1181168868e766f0696c30f644292a5a833ee3983e4Alex Sakhartchouk                model = FileA3D.createFromFile(mRS, names[0]);
119a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            }
120a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            int numModels = model.getIndexEntryCount();
121a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            for (int i = 0; i < numModels; i ++) {
122a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                FileA3D.IndexEntry entry = model.getIndexEntry(i);
123a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
124a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                    mActiveScene.meshLoaded(entry.getMesh());
125a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                }
126a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            }
127a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            long end = System.currentTimeMillis();
128a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            Log.v("TIMER", "A3D load time: " + (end - start));
129a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            return new Boolean(true);
130a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
131a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
132a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        protected void onPostExecute(Boolean result) {
133a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
134a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    }
135a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
136a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk}
137a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
138a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
139a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
140