package min3d.parser; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import app.ara.utils.files.FileManager; import min3d.Min3d; import min3d.Shared; import min3d.Utils; import min3d.animation.AnimationObject3d; 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.graphics.Bitmap.Config; import android.util.Log; /** * Abstract parser class with basic parsing functionality. * * @author dennis.ippel * */ public abstract class AParser implements IParser { protected Resources resources; protected String resourceID; protected String packageID; protected String currentMaterialKey; protected ArrayList parseObjects; protected ParseObjectData co; protected boolean firstObject; protected TextureAtlas textureAtlas; protected ArrayList vertices; protected ArrayList texCoords; protected ArrayList normals; protected boolean generateMipMap; protected HashMap materialMap; protected InputStream mStream=null; protected String mPath; protected Context mContext=null; public AParser(Context a) { mContext=a; vertices = new ArrayList(); texCoords = new ArrayList(); normals = new ArrayList(); parseObjects = new ArrayList(); textureAtlas = new TextureAtlas(); firstObject = true; materialMap = new HashMap(); } public AParser(Context a, Resources resources, String resourceID, Boolean generateMipMap) { this(a); mContext=a; this.resources = resources; this.resourceID = resourceID; if (resourceID.indexOf(":") > -1) this.packageID = resourceID.split(":")[0]; this.generateMipMap = generateMipMap; } public AParser(Context a, String path, Boolean generateMipMap) { this(a); mContext=a; mPath=path; try { mStream= FileManager.openFile(a,path); } catch (Exception e) { e.printStackTrace(); } int d = mPath.lastIndexOf('/'); if(d>=0) packageID=mPath.substring(0,d); else packageID=""; this.generateMipMap = generateMipMap; } protected void cleanup() { parseObjects.clear(); textureAtlas.cleanup(); vertices.clear(); texCoords.clear(); normals.clear(); } /** * Override this in the concrete parser */ public Object3dContainer getParsedObject() { return null; } /** * Override this in the concrete parser if applicable */ public AnimationObject3d getParsedAnimationObject() { return null; } protected String readString(InputStream stream) throws IOException { String result = new String(); byte inByte; while ((inByte = (byte) stream.read()) != 0) result += (char) inByte; return result; } protected int readInt(InputStream stream) throws IOException { return stream.read() | (stream.read() << 8) | (stream.read() << 16) | (stream.read() << 24); } protected int readShort(InputStream stream) throws IOException { return (stream.read() | (stream.read() << 8)); } protected float readFloat(InputStream stream) throws IOException { return Float.intBitsToFloat(readInt(stream)); } /** * Override this in the concrete parser */ public void parse() { } /** * Contains texture information. UV offsets and scaling is stored here. * This is used with texture atlases. * * @author dennis.ippel * */ protected class BitmapAsset { /** * The texture bitmap */ public Bitmap bitmap; /** * The texture identifier */ public String key; /** * Resource ID */ public String resourceID; /** * U-coordinate offset */ public float uOffset; /** * V-coordinate offset */ public float vOffset; /** * U-coordinate scaling value */ public float uScale; /** * V-coordinate scaling value */ public float vScale; public boolean useForAtlasDimensions; /** * Creates a new BitmapAsset object * @param * @param key */ public BitmapAsset(String key, String resourceID) { this.key = key; this.resourceID = resourceID; useForAtlasDimensions = false; } } /** * When a model contains per-face textures a texture atlas is created. This * combines multiple textures into one and re-calculates the UV coordinates. * * @author dennis.ippel * */ protected class TextureAtlas { /** * The texture bitmaps that should be combined into one. */ private ArrayList bitmaps; /** * The texture atlas bitmap */ private Bitmap atlas; /** * Creates a new texture atlas instance. */ public TextureAtlas() { bitmaps = new ArrayList(); } private String atlasId; /** * Adds a bitmap to the atlas * * @param */ public void addBitmapAsset(BitmapAsset ba) { BitmapAsset existingBA = getBitmapAssetByResourceID(ba.resourceID); if(existingBA == null) { Bitmap b=null; if(mStream==null) { int bmResourceID = resources.getIdentifier(ba.resourceID, null, null); if (bmResourceID == 0) { return; } b = Utils.makeBitmapFromResourceId(bmResourceID); }else { try { b=FileManager.openImage(mContext, ba.resourceID); } catch (Exception e) { e.printStackTrace(); } } ba.useForAtlasDimensions = true; ba.bitmap = b; } else { ba.bitmap = existingBA.bitmap; } bitmaps.add(ba); } public BitmapAsset getBitmapAssetByResourceID(String resourceID) { int numBitmaps = bitmaps.size(); for(int i=0; i 0; } /** * Compares the height of two BitmapAsset objects. * * @author dennis.ippel * */ private class BitmapHeightComparer implements Comparator { public int compare(BitmapAsset b1, BitmapAsset b2) { int height1 = b1.bitmap.getHeight(); int height2 = b2.bitmap.getHeight(); if (height1 < height2) { return 1; } else if (height1 == height2) { return 0; } else { return -1; } } } /** * Returns a bitmap asset with a specified name. * * @param materialKey * @return */ public BitmapAsset getBitmapAssetByName(String materialKey) { int numBitmaps = bitmaps.size(); for (int i = 0; i < numBitmaps; i++) { if (bitmaps.get(i).key.equals(materialKey)) return bitmaps.get(i); } return null; } public void cleanup() { int numBitmaps = bitmaps.size(); for (int i = 0; i < numBitmaps; i++) { bitmaps.get(i).bitmap.recycle(); } if(atlas != null) atlas.recycle(); bitmaps.clear(); vertices.clear(); texCoords.clear(); normals.clear(); } public void setId(String newAtlasId) { atlasId = newAtlasId; } public String getId() { return atlasId; } } protected class Material { public String name; public String diffuseTextureMap; public Color4 diffuseColor; public Material(String name) { this.name = name; } } }