123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- package min3d.parser;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.util.Calendar;
- import java.util.StringTokenizer;
- import app.mar.utils.files.FileManager;
- import min3d.Min3d;
- import min3d.Shared;
- import min3d.core.Object3dContainer;
- import min3d.vos.Color4;
- import min3d.vos.Number3d;
- import min3d.vos.Uv;
- import android.content.Context;
- import android.content.res.Resources;
- import android.graphics.Bitmap;
- import android.util.Log;
- /**
- * Parses Wavefront OBJ files. Basic version, this is still a work in progress!
- *
- * TODO: proper error handling TODO: handle multiple objects TODO: handle groups
- * TODO: a lot more :-) *
- *
- * @author dennis.ippel
- *
- */
- public class ObjParser extends AParser implements IParser {
- private final String VERTEX = "v";
- private final String FACE = "f";
- private final String TEXCOORD = "vt";
- private final String NORMAL = "vn";
- private final String OBJECT = "o";
- private final String MATERIAL_LIB = "mtllib";
- private final String USE_MATERIAL = "usemtl";
- private final String NEW_MATERIAL = "newmtl";
- private final String DIFFUSE_COLOR = "Kd";
- private final String DIFFUSE_TEX_MAP = "map_Kd";
- /**
- * Creates a new OBJ parser instance
- *
- * @param resources
- * @param resourceID
- */
- public ObjParser(Context a, Resources resources, String resourceID, boolean generateMipMap) {
- super(a, resources, resourceID, generateMipMap);
- System.out.println("Parser:"+resourceID);
- System.err.println("Parser:"+resourceID);
- }
- public ObjParser(Context a, String is, boolean generateMipMap) {
- super(a, is, generateMipMap);
- System.out.println("Parser:"+resourceID);
- System.err.println("Parser:"+resourceID);
- }
- @Override
- public void parse() {
- long startTime = Calendar.getInstance().getTimeInMillis();
- InputStream fileIn = null;
- if(mStream==null)
- {
- fileIn =resources.openRawResource(resources.getIdentifier(
- resourceID, null, null));
- }else fileIn = mStream;
- BufferedReader buffer = new BufferedReader(
- new InputStreamReader(fileIn));
- String line;
- co = new ParseObjectData(vertices, texCoords, normals);
- parseObjects.add(co);
- Log.d(Min3d.TAG, "Start parsing object " + resourceID);
- Log.d(Min3d.TAG, "Start time " + startTime);
- try {
- while ((line = buffer.readLine()) != null) {
- // remove duplicate whitespace
- // line = line.replaceAll("\\s+", " ");
- // String[] parts = line.split(" ");
- StringTokenizer parts = new StringTokenizer(line, " ");
- int numTokens = parts.countTokens();
- if (numTokens == 0)
- continue;
- String type = parts.nextToken();
- if (type.equals(VERTEX)) {
- Number3d vertex = new Number3d();
- vertex.x = Float.parseFloat(parts.nextToken());
- vertex.y = Float.parseFloat(parts.nextToken());
- vertex.z = Float.parseFloat(parts.nextToken());
- vertices.add(vertex);
- } else if (type.equals(FACE)) {
- if (numTokens == 4) {
- co.numFaces++;
- co.faces.add(new ObjFace(line, currentMaterialKey, 3));
- } else if (numTokens == 5) {
- co.numFaces += 2;
- co.faces.add(new ObjFace(line, currentMaterialKey, 4));
- }
- } else if (type.equals(TEXCOORD)) {
- Uv texCoord = new Uv();
- texCoord.u = Float.parseFloat(parts.nextToken());
- texCoord.v = Float.parseFloat(parts.nextToken()) * -1f;
- texCoords.add(texCoord);
- } else if (type.equals(NORMAL)) {
- Number3d normal = new Number3d();
- normal.x = Float.parseFloat(parts.nextToken());
- normal.y = Float.parseFloat(parts.nextToken());
- normal.z = Float.parseFloat(parts.nextToken());
- normals.add(normal);
- } else if (type.equals(MATERIAL_LIB)) {
- readMaterialLib(parts.nextToken());
- } else if (type.equals(USE_MATERIAL)) {
- currentMaterialKey = parts.nextToken();
- } else if (type.equals(OBJECT)) {
- String objName = parts.hasMoreTokens() ? parts.nextToken() : "";
- if(firstObject)
- {
- Log.d(Min3d.TAG, "Create object " + objName);
- co.name = objName;
- firstObject = false;
- }
- else
- {
- Log.d(Min3d.TAG, "Create object " + objName);
- co = new ParseObjectData(vertices, texCoords, normals);
- co.name = objName;
- parseObjects.add(co);
- }
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- long endTime = Calendar.getInstance().getTimeInMillis();
- Log.d(Min3d.TAG, "End time " + (endTime - startTime));
- }
- public Object3dContainer getParsedObject() {
- Log.d(Min3d.TAG, "Start object creation");
- Object3dContainer obj = new Object3dContainer(0, 0);
- int numObjects = parseObjects.size();
- Bitmap texture = null;
- if(textureAtlas.hasBitmaps())
- {
- textureAtlas.generate();
- texture = textureAtlas.getBitmap();
- Shared.textureManager().addTextureId(texture, textureAtlas.getId(), generateMipMap);
- }
-
- for (int i = 0; i < numObjects; i++) {
- ParseObjectData o = parseObjects.get(i);
- Log.d(Min3d.TAG, "Creating object " + o.name);
- obj.addChild(o.getParsedObject(materialMap, textureAtlas));
- }
-
- if(textureAtlas.hasBitmaps())
- {
- if(texture != null) texture.recycle();
- }
- Log.d(Min3d.TAG, "Object creation finished");
-
- cleanup();
-
- return obj;
- }
- private void readMaterialLib(String libID) {
- InputStream fileIn=null;
- StringBuffer libIDSbuf = new StringBuffer(libID);
- int dotIndex = libIDSbuf.lastIndexOf(".");
- if (dotIndex > -1)
- libIDSbuf = libIDSbuf.replace(dotIndex, dotIndex + 1, "_");
- if(mStream==null) {
- StringBuffer resourceID = new StringBuffer(packageID);
- resourceID.append(":raw/");
- resourceID.append(libIDSbuf.toString());
- Log.e("OBJParser", "Load MTL '" + resourceID.toString() + "'");
- fileIn = resources.openRawResource(resources.getIdentifier(
- resourceID.toString(), null, null));
- }else {
- try {
- fileIn = FileManager.openFile(mContext, packageID+libID);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- BufferedReader buffer = new BufferedReader(
- new InputStreamReader(fileIn));
- String line;
- String currentMaterial = "";
- try {
- while ((line = buffer.readLine()) != null) {
- String[] parts = line.split(" ");
- if (parts.length == 0)
- continue;
- String type = parts[0];
- if (type.equals(NEW_MATERIAL)) {
- if (parts.length > 1) {
- currentMaterial = parts[1];
- materialMap.put(currentMaterial, new Material(
- currentMaterial));
- }
- } else if(type.equals(DIFFUSE_COLOR) && !type.equals(DIFFUSE_TEX_MAP)) {
- Color4 diffuseColor = new Color4(Float.parseFloat(parts[1]) * 255.0f, Float.parseFloat(parts[2]) * 255.0f, Float.parseFloat(parts[3]) * 255.0f, 255.0f);
- materialMap.get(currentMaterial).diffuseColor = diffuseColor;
- } else if (type.equals(DIFFUSE_TEX_MAP)) {
- if (parts.length > 1) {
- materialMap.get(currentMaterial).diffuseTextureMap = parts[1];
- StringBuffer texture = new StringBuffer(packageID);
- if(mStream==null) texture.append(":drawable/");
-
- StringBuffer textureName = new StringBuffer(parts[1]);
- dotIndex = textureName.lastIndexOf(".");
- if (dotIndex > -1)
- texture.append(textureName.substring(0, dotIndex));
- else
- texture.append(textureName);
- System.out.println("Drawable = "+texture.toString());
- /*int bmResourceID = resources.getIdentifier(texture
- .toString(), null, null);
- Bitmap b = Utils.makeBitmapFromResourceId(bmResourceID);*/
- textureAtlas.addBitmapAsset(new BitmapAsset(currentMaterial, texture.toString()));
- }
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- @Override
- protected void cleanup() {
- super.cleanup();
- materialMap.clear();
- }
- private class ObjFace extends ParseObjectFace {
- public ObjFace(String line, String materialKey, int faceLength) {
- super();
- this.materialKey = materialKey;
- this.faceLength = faceLength;
- boolean emptyVt = line.indexOf("//") > -1;
- if(emptyVt) line = line.replace("//", "/");
- StringTokenizer parts = new StringTokenizer(line);
- parts.nextToken();
- StringTokenizer subParts = new StringTokenizer(parts.nextToken(), "/");
- int partLength = subParts.countTokens();
- hasuv = partLength >= 2 && !emptyVt;
- hasn = partLength == 3 || (partLength == 2 && emptyVt);
- v = new int[faceLength];
- if (hasuv)
- uv = new int[faceLength];
- if (hasn)
- n = new int[faceLength];
- for (int i = 1; i < faceLength + 1; i++) {
- if (i > 1)
- subParts = new StringTokenizer(parts.nextToken(), "/");
- int index = i - 1;
- v[index] = (short) (Short.parseShort(subParts.nextToken()) - 1);
- if (hasuv)
- uv[index] = (short) (Short.parseShort(subParts.nextToken()) - 1);
- if (hasn)
- n[index] = (short) (Short.parseShort(subParts.nextToken()) - 1);
- }
- }
- }
- }
|