blob: 340c6a7881559717794327321655ba805f26bd79 [file] [log] [blame]
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.opengl;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.microedition.khronos.opengles.*;
/**
* {@hide}
*/
public abstract class Object3D {
private boolean mHasTexcoords = false;
private float mBoundsMinX = Float.MAX_VALUE;
private float mBoundsMaxX = Float.MIN_VALUE;
private float mBoundsMinY = Float.MAX_VALUE;
private float mBoundsMaxY = Float.MIN_VALUE;
private float mBoundsMinZ = Float.MAX_VALUE;
private float mBoundsMaxZ = Float.MIN_VALUE;
private IntBuffer mVertexBuffer;
private IntBuffer mNormalBuffer;
private IntBuffer mTexcoordBuffer;
// All groups, by name
private Map<String, Group> mGroups;
// All materials, by name
private Map<String, Material> mMaterials;
// All texture maps, by name
private Map<String, Texture> mTextures;
public Object3D() {
reset();
}
/**
* Override this method with an implementation that contructs
* and InputStream from the given filename. For example, if the
* source files are to be retrieved using an AssetManager,
* the implementation would use AssetManager.load() to
* get the input stream.
*/
public abstract InputStream readFile(String filename) throws IOException;
private void reset() {
mVertexBuffer = mNormalBuffer = mTexcoordBuffer = null;
mGroups = new HashMap<String,Group>();
mMaterials = new HashMap<String,Material>();
mTextures = new HashMap<String,Texture>();
}
public Material getMaterial(String name) {
Material mat = mMaterials.get(name);
return mat;
}
public Texture getTexture(String name) {
return mTextures.get(name);
}
public IntBuffer getVertexBuffer() {
return mVertexBuffer;
}
public IntBuffer getNormalBuffer() {
return mNormalBuffer;
}
public IntBuffer getTexcoordBuffer() {
return mTexcoordBuffer;
}
public int getNumTriangles() {
int numTriangles = 0;
Iterator<Group> iter = mGroups.values().iterator();
while (iter.hasNext()) {
numTriangles += iter.next().getNumTriangles();
}
return numTriangles;
}
public boolean hasTexcoords() {
return mHasTexcoords;
}
public float getBoundsMinX() {
return mBoundsMinX;
}
public float getBoundsMaxX() {
return mBoundsMaxX;
}
public float getBoundsMinY() {
return mBoundsMinY;
}
public float getBoundsMaxY() {
return mBoundsMaxY;
}
public float getBoundsMinZ() {
return mBoundsMinZ;
}
public float getBoundsMaxZ() {
return mBoundsMaxZ;
}
public void loadTexture(String name) throws IOException {
InputStream is = readFile(name + ".raw");
Texture texture = new Texture(is);
mTextures.put(name, texture);
}
private static void verifyByte(DataInputStream dis, int b)
throws IOException {
int x = dis.read() & 0xff;
if (x != b) {
throw new RuntimeException("Bad byte: " +
x +
" (expected " + b + ")");
}
}
public void load(String filename) throws IOException {
reset();
DataInputStream dis = new DataInputStream(readFile(filename));
verifyByte(dis, 'g' + 128);
verifyByte(dis, 'l');
verifyByte(dis, 'e');
verifyByte(dis, 's');
int numTuples = dis.readInt();
this.mBoundsMinX = dis.readFloat();
this.mBoundsMaxX = dis.readFloat();
this.mBoundsMinY = dis.readFloat();
this.mBoundsMaxY = dis.readFloat();
this.mBoundsMinZ = dis.readFloat();
this.mBoundsMaxZ = dis.readFloat();
this.mHasTexcoords = dis.readInt() == 1;
int intsPerTuple = mHasTexcoords ? 8 : 6;
int numInts = numTuples*intsPerTuple;
int len = 4*numTuples*(mHasTexcoords ? 8 : 6);
byte[] tmp = new byte[len];
int tidx = 0;
while (tidx < len) {
tidx += dis.read(tmp, tidx, len - tidx);
}
if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
for (int i = 0; i < len; i += 4) {
byte tmp0 = tmp[i];
byte tmp1 = tmp[i + 1];
byte tmp2 = tmp[i + 2];
byte tmp3 = tmp[i + 3];
tmp[i] = tmp3;
tmp[i + 1] = tmp2;
tmp[i + 2] = tmp1;
tmp[i + 3] = tmp0;
}
}
ByteBuffer allbb = ByteBuffer.allocateDirect(len);
allbb.order(ByteOrder.nativeOrder());
allbb.put(tmp);
allbb.position(0);
allbb.limit(4*3*numTuples);
ByteBuffer vbb = allbb.slice();
this.mVertexBuffer = vbb.asIntBuffer();
mVertexBuffer.position(0);
if (mHasTexcoords) {
allbb.position(allbb.limit());
allbb.limit(allbb.position() + 4*2*numTuples);
ByteBuffer tbb = allbb.slice();
this.mTexcoordBuffer = tbb.asIntBuffer();
mTexcoordBuffer.position(0);
}
allbb.position(allbb.limit());
allbb.limit(allbb.position() + 4*3*numTuples);
ByteBuffer nbb = allbb.slice();
this.mNormalBuffer = nbb.asIntBuffer();
mNormalBuffer.position(0);
int numMaterials = dis.readInt();
for (int i = 0; i < numMaterials; i++) {
Material mat = new Material(this);
mat.load(dis);
mMaterials.put(mat.getName(), mat);
}
int numGroups = dis.readInt();
for (int i = 0; i < numGroups; i++) {
Group g = new Group(this);
g.load(dis);
mGroups.put(g.getName(), g);
}
}
public void draw(GL10 gl) {
Iterator<Group> iter = mGroups.values().iterator();
while (iter.hasNext()) {
iter.next().draw(gl);
}
}
}