package rajawali.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.zip.GZIPOutputStream;
import rajawali.BaseObject3D;
import rajawali.Geometry3D;
import rajawali.SerializedObject3D;
import rajawali.animation.mesh.VertexAnimationFrame;
import rajawali.animation.mesh.VertexAnimationObject3D;
import rajawali.materials.TextureManager;
import rajawali.parser.ObjParser;
import android.content.Context;
import android.os.Environment;
public class MeshExporter {
private BaseObject3D mObject;
private String mFileName;
private boolean mCompressed;
private File mExportDir = null;
public enum ExportType {
SERIALIZED,
OBJ
}
public MeshExporter(BaseObject3D objectToExport) {
mObject = objectToExport;
}
public void setExportDirectory(File exportDir) {
// The path's validity is the user's responsibility.
// Any problems are taken care of by the try blocks in the private export methods.
mExportDir = exportDir;
}
public void export(String fileName, ExportType type) {
export(fileName, type, false);
}
public void export(String fileName, ExportType type, boolean compressed) {
mFileName = fileName;
mCompressed = compressed;
switch (type) {
case SERIALIZED:
exportToSerialized();
break;
case OBJ:
exportToObj();
break;
}
}
private File getExportFile() {
File path;
if (mExportDir == null)
path = Environment.getExternalStorageDirectory();
else
path = mExportDir;
return new File(path, mFileName);
}
private void exportToObj() {
RajLog.d("Exporting " + mObject.getName() + " as .obj file");
Geometry3D g = mObject.getGeometry();
StringBuffer sb = new StringBuffer();
sb.append("# Exported by Rajawali 3D Engine for Android\n");
sb.append("o ");
sb.append(mObject.getName());
sb.append("\n");
for (int i = 0; i < g.getVertices().capacity(); i += 3) {
sb.append("v ");
sb.append(g.getVertices().get(i));
sb.append(" ");
sb.append(g.getVertices().get(i + 1));
sb.append(" ");
sb.append(g.getVertices().get(i + 2));
sb.append("\n");
}
sb.append("\n");
for (int i = 0; i < g.getTextureCoords().capacity(); i += 2) {
sb.append("vt ");
sb.append(g.getTextureCoords().get(i));
sb.append(" ");
sb.append(g.getTextureCoords().get(i + 1));
sb.append("\n");
}
sb.append("\n");
for (int i = 0; i < g.getNormals().capacity(); i += 3) {
sb.append("vn ");
sb.append(g.getNormals().get(i));
sb.append(" ");
sb.append(g.getNormals().get(i + 1));
sb.append(" ");
sb.append(g.getNormals().get(i + 2));
sb.append("\n");
}
sb.append("\n");
boolean isIntBuffer = g.getIndices() instanceof IntBuffer;
for (int i = 0; i < g.getIndices().capacity(); i++) {
if (i % 3 == 0)
sb.append("\nf ");
int index = isIntBuffer ? ((IntBuffer) g.getIndices()).get(i) + 1
: ((ShortBuffer) g.getIndices()).get(i) + 1;
sb.append(index);
sb.append("/");
sb.append(index);
sb.append("/");
sb.append(index);
sb.append(" ");
}
try {
File f = getExportFile();
FileWriter writer = new FileWriter(f);
writer.append(sb.toString());
writer.flush();
writer.close();
RajLog.d(".obj export successful: " + f.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Make sure this line is in your AndroidManifer.xml file, under <manifest>: <uses-permission
* android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
*/
private void exportToSerialized() {
FileOutputStream fos;
try {
File f = getExportFile();
fos = new FileOutputStream(f);
ObjectOutputStream os = null;
if (mCompressed) {
GZIPOutputStream gz = new GZIPOutputStream(fos);
os = new ObjectOutputStream(gz);
} else {
os = new ObjectOutputStream(fos);
}
SerializedObject3D ser = mObject.toSerializedObject3D();
if (mObject instanceof VertexAnimationObject3D) {
VertexAnimationObject3D o = (VertexAnimationObject3D) mObject;
int numFrames = o.getNumFrames();
float[][] vs = new float[numFrames][];
float[][] ns = new float[numFrames][];
String[] frameNames = new String[numFrames];
for (int i = 0; i < numFrames; ++i) {
VertexAnimationFrame frame = (VertexAnimationFrame) o.getFrame(i);
Geometry3D geom = frame.getGeometry();
float[] v = new float[geom.getVertices().limit()];
geom.getVertices().get(v);
float[] n = new float[geom.getNormals().limit()];
geom.getNormals().get(n);
vs[i] = v;
ns[i] = n;
frameNames[i] = frame.getName();
}
ser.setFrameVertices(vs);
ser.setFrameNormals(ns);
ser.setFrameNames(frameNames);
}
os.writeObject(ser);
os.close();
RajLog.i("Successfully serialized " + mFileName);
} catch (Exception e) {
RajLog.e("Serializing " + mFileName + " was unsuccessfull.");
e.printStackTrace();
}
}
public static void serializeObj(Context context, TextureManager textureManager, int resourceId, String outputName){
serializeObj(context, textureManager, resourceId, outputName, false, null);
}
public static void serializeObj(Context context, TextureManager textureManager, int resourceId, String outputName, Boolean compress){
serializeObj(context, textureManager, resourceId, outputName, compress, null);
}
public static void serializeObj(Context context, TextureManager textureManager, int resourceId, String outputName, File exportDir){
serializeObj(context, textureManager, resourceId, outputName, false, exportDir);
}
public static void serializeObj(Context context, TextureManager textureManager, int resourceId, String outputName, Boolean compress, File exportDir){
final ObjParser objParser = new ObjParser(context.getResources(), textureManager, resourceId);
try {
objParser.parse();
final BaseObject3D obj = objParser.getParsedObject();
final MeshExporter exporter = new MeshExporter(obj);
exporter.setExportDirectory(exportDir);
exporter.export(outputName, ExportType.SERIALIZED, compress);
} catch (Exception e) {
RajLog.e("Failed to serialize obj: " + e.getMessage());
e.printStackTrace();
}
}
}