Home | History | Annotate | Download | only in opengl
      1 /*
      2  * Copyright (C) 2006 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 android.opengl;
     18 
     19 import java.io.BufferedReader;
     20 import java.io.DataInputStream;
     21 import java.io.InputStream;
     22 import java.io.InputStreamReader;
     23 import java.io.IOException;
     24 import java.nio.ByteBuffer;
     25 import java.nio.ByteOrder;
     26 import java.nio.IntBuffer;
     27 import java.util.ArrayList;
     28 import java.util.HashMap;
     29 import java.util.Iterator;
     30 import java.util.List;
     31 import java.util.Map;
     32 import javax.microedition.khronos.opengles.*;
     33 
     34 /**
     35  * {@hide}
     36  */
     37 public abstract class Object3D {
     38 
     39     private boolean mHasTexcoords = false;
     40 
     41     private float mBoundsMinX = Float.MAX_VALUE;
     42     private float mBoundsMaxX = Float.MIN_VALUE;
     43     private float mBoundsMinY = Float.MAX_VALUE;
     44     private float mBoundsMaxY = Float.MIN_VALUE;
     45     private float mBoundsMinZ = Float.MAX_VALUE;
     46     private float mBoundsMaxZ = Float.MIN_VALUE;
     47 
     48     private IntBuffer mVertexBuffer;
     49     private IntBuffer mNormalBuffer;
     50     private IntBuffer mTexcoordBuffer;
     51 
     52     // All groups, by name
     53     private Map<String, Group> mGroups;
     54 
     55     // All materials, by name
     56     private Map<String, Material> mMaterials;
     57 
     58     // All texture maps, by name
     59     private Map<String, Texture> mTextures;
     60 
     61     public Object3D() {
     62         reset();
     63     }
     64 
     65     /**
     66      * Override this method with an implementation that contructs
     67      * and InputStream from the given filename.  For example, if the
     68      * source files are to be retrieved using an AssetManager,
     69      * the implementation would use AssetManager.load() to
     70      * get the input stream.
     71      */
     72     public abstract InputStream readFile(String filename) throws IOException;
     73 
     74     private void reset() {
     75         mVertexBuffer = mNormalBuffer = mTexcoordBuffer = null;
     76 
     77         mGroups = new HashMap<String,Group>();
     78         mMaterials = new HashMap<String,Material>();
     79         mTextures = new HashMap<String,Texture>();
     80     }
     81 
     82     public Material getMaterial(String name) {
     83         Material mat = mMaterials.get(name);
     84         return mat;
     85     }
     86 
     87     public Texture getTexture(String name) {
     88         return mTextures.get(name);
     89     }
     90 
     91     public IntBuffer getVertexBuffer() {
     92         return mVertexBuffer;
     93     }
     94 
     95     public IntBuffer getNormalBuffer() {
     96         return mNormalBuffer;
     97     }
     98 
     99     public IntBuffer getTexcoordBuffer() {
    100         return mTexcoordBuffer;
    101     }
    102 
    103     public int getNumTriangles() {
    104         int numTriangles = 0;
    105         Iterator<Group> iter = mGroups.values().iterator();
    106         while (iter.hasNext()) {
    107             numTriangles += iter.next().getNumTriangles();
    108         }
    109         return numTriangles;
    110     }
    111 
    112     public boolean hasTexcoords() {
    113         return mHasTexcoords;
    114     }
    115 
    116     public float getBoundsMinX() {
    117         return mBoundsMinX;
    118     }
    119 
    120     public float getBoundsMaxX() {
    121         return mBoundsMaxX;
    122     }
    123 
    124     public float getBoundsMinY() {
    125         return mBoundsMinY;
    126     }
    127 
    128     public float getBoundsMaxY() {
    129         return mBoundsMaxY;
    130     }
    131 
    132     public float getBoundsMinZ() {
    133         return mBoundsMinZ;
    134     }
    135 
    136     public float getBoundsMaxZ() {
    137         return mBoundsMaxZ;
    138     }
    139 
    140     public void loadTexture(String name) throws IOException {
    141         InputStream is = readFile(name + ".raw");
    142         Texture texture = new Texture(is);
    143         mTextures.put(name, texture);
    144     }
    145 
    146     private static void verifyByte(DataInputStream dis, int b)
    147     throws IOException {
    148         int x = dis.read() & 0xff;
    149         if (x != b) {
    150             throw new RuntimeException("Bad byte: " +
    151                     x +
    152                     " (expected " + b + ")");
    153         }
    154     }
    155 
    156     public void load(String filename) throws IOException {
    157         reset();
    158 
    159         DataInputStream dis = new DataInputStream(readFile(filename));
    160         verifyByte(dis, 'g' + 128);
    161         verifyByte(dis, 'l');
    162         verifyByte(dis, 'e');
    163         verifyByte(dis, 's');
    164 
    165         int numTuples = dis.readInt();
    166 
    167         this.mBoundsMinX = dis.readFloat();
    168         this.mBoundsMaxX = dis.readFloat();
    169         this.mBoundsMinY = dis.readFloat();
    170         this.mBoundsMaxY = dis.readFloat();
    171         this.mBoundsMinZ = dis.readFloat();
    172         this.mBoundsMaxZ = dis.readFloat();
    173 
    174         this.mHasTexcoords = dis.readInt() == 1;
    175 
    176         int intsPerTuple = mHasTexcoords ? 8 : 6;
    177         int numInts = numTuples*intsPerTuple;
    178 
    179         int len = 4*numTuples*(mHasTexcoords ? 8 : 6);
    180 
    181         byte[] tmp = new byte[len];
    182         int tidx = 0;
    183         while (tidx < len) {
    184             tidx += dis.read(tmp, tidx, len - tidx);
    185         }
    186         if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
    187             for (int i = 0; i < len; i += 4) {
    188                 byte tmp0 = tmp[i];
    189                 byte tmp1 = tmp[i + 1];
    190                 byte tmp2 = tmp[i + 2];
    191                 byte tmp3 = tmp[i + 3];
    192                 tmp[i] = tmp3;
    193                 tmp[i + 1] = tmp2;
    194                 tmp[i + 2] = tmp1;
    195                 tmp[i + 3] = tmp0;
    196             }
    197         }
    198 
    199         ByteBuffer allbb = ByteBuffer.allocateDirect(len);
    200         allbb.order(ByteOrder.nativeOrder());
    201         allbb.put(tmp);
    202 
    203         allbb.position(0);
    204         allbb.limit(4*3*numTuples);
    205         ByteBuffer vbb = allbb.slice();
    206         this.mVertexBuffer = vbb.asIntBuffer();
    207         mVertexBuffer.position(0);
    208 
    209         if (mHasTexcoords) {
    210             allbb.position(allbb.limit());
    211             allbb.limit(allbb.position() + 4*2*numTuples);
    212             ByteBuffer tbb = allbb.slice();
    213             this.mTexcoordBuffer = tbb.asIntBuffer();
    214             mTexcoordBuffer.position(0);
    215         }
    216 
    217         allbb.position(allbb.limit());
    218         allbb.limit(allbb.position() + 4*3*numTuples);
    219         ByteBuffer nbb = allbb.slice();
    220         this.mNormalBuffer = nbb.asIntBuffer();
    221         mNormalBuffer.position(0);
    222 
    223         int numMaterials = dis.readInt();
    224         for (int i = 0; i < numMaterials; i++) {
    225             Material mat = new Material(this);
    226             mat.load(dis);
    227             mMaterials.put(mat.getName(), mat);
    228         }
    229 
    230         int numGroups = dis.readInt();
    231         for (int i = 0; i < numGroups; i++) {
    232             Group g = new Group(this);
    233             g.load(dis);
    234             mGroups.put(g.getName(), g);
    235         }
    236     }
    237 
    238     public void draw(GL10 gl) {
    239         Iterator<Group> iter = mGroups.values().iterator();
    240         while (iter.hasNext()) {
    241             iter.next().draw(gl);
    242         }
    243     }
    244 }
    245 
    246