|
From: <tre...@us...> - 2007-07-10 17:43:14
|
Revision: 222
http://ogoglio.svn.sourceforge.net/ogoglio/?rev=222&view=rev
Author: trevorolio
Date: 2007-07-10 10:43:14 -0700 (Tue, 10 Jul 2007)
Log Message:
-----------
Added obj writing (mostly for parse debug).
Fixed my incorrect assumption that negative vertex indices aren't invalid in obj files.
Modified Paths:
--------------
spaces/trunk/src/com/ogoglio/OgoglioTestSuite.java
spaces/trunk/src/com/ogoglio/persist/resources/door.obj
spaces/trunk/src/com/ogoglio/util/ArgumentUtils.java
spaces/trunk/src/com/ogoglio/viewer/j3d/obj/MtlParser.java
spaces/trunk/src/com/ogoglio/viewer/j3d/obj/Obj.java
spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjMtl.java
spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjParser.java
spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjTest.java
Modified: spaces/trunk/src/com/ogoglio/OgoglioTestSuite.java
===================================================================
--- spaces/trunk/src/com/ogoglio/OgoglioTestSuite.java 2007-07-09 01:57:48 UTC (rev 221)
+++ spaces/trunk/src/com/ogoglio/OgoglioTestSuite.java 2007-07-10 17:43:14 UTC (rev 222)
@@ -19,11 +19,13 @@
import com.ogoglio.client.ClientTests;
import com.ogoglio.persist.PersistTests;
import com.ogoglio.sim.script.ScriptTests;
+import com.ogoglio.viewer.j3d.obj.ObjTest;
import com.ogoglio.xml.XMLTests;
public class OgoglioTestSuite {
public static Test suite() {
TestSuite suite = new TestSuite();
+ suite.addTestSuite(ObjTest.class);
suite.addTestSuite(XMLTests.class);
suite.addTestSuite(PersistTests.class);
suite.addTestSuite(ClientTests.class);
Modified: spaces/trunk/src/com/ogoglio/persist/resources/door.obj
===================================================================
--- spaces/trunk/src/com/ogoglio/persist/resources/door.obj 2007-07-09 01:57:48 UTC (rev 221)
+++ spaces/trunk/src/com/ogoglio/persist/resources/door.obj 2007-07-10 17:43:14 UTC (rev 222)
@@ -67,7 +67,7 @@
v 0.527804 1.098068 0.053800
v 0.527804 1.098068 -0.053800
usemtl Material.001
-s off
+s 1
f 2 1 65
f 66 33 34
f 65 3 2
@@ -182,7 +182,7 @@
vt 1.000000 0.000000 0.0
vt 0.000000 0.000000 0.0
usemtl Material.001
-s off
+s 2
f 67/1 70/2 69/3 68/4
f 71/1 72/2 73/3 74/4
f 67/1 68/2 75/3 76/4
@@ -227,7 +227,7 @@
v 0.884366 0.110502 0.100000
v 0.884367 0.110503 -0.100000
usemtl Material.001
-s off
+s 3
f 79 83 84 80
f 81 85 86 82
f 87 81 82 88
@@ -268,7 +268,7 @@
v -0.821776 0.110503 -0.023613
v -0.821776 2.310503 -0.023613
usemtl Material
-s off
+s 4
f 111 112 113 114
f 115 118 117 116
f 111 115 116 112
Modified: spaces/trunk/src/com/ogoglio/util/ArgumentUtils.java
===================================================================
--- spaces/trunk/src/com/ogoglio/util/ArgumentUtils.java 2007-07-09 01:57:48 UTC (rev 221)
+++ spaces/trunk/src/com/ogoglio/util/ArgumentUtils.java 2007-07-10 17:43:14 UTC (rev 222)
@@ -59,6 +59,13 @@
}
}
+ public static void assertReadableFile(String path) {
+ File file = new File(path);
+ if(!file.exists() || !file.canRead() || !file.isFile()) {
+ throw new IllegalArgumentException("No readable file at " + path);
+ }
+ }
+
public static void assertReadableDir(File file, boolean createIfPossible) {
if (file == null) {
throw new IllegalArgumentException("Null directory");
@@ -93,4 +100,5 @@
}
}
+
}
Modified: spaces/trunk/src/com/ogoglio/viewer/j3d/obj/MtlParser.java
===================================================================
--- spaces/trunk/src/com/ogoglio/viewer/j3d/obj/MtlParser.java 2007-07-09 01:57:48 UTC (rev 221)
+++ spaces/trunk/src/com/ogoglio/viewer/j3d/obj/MtlParser.java 2007-07-10 17:43:14 UTC (rev 222)
@@ -23,7 +23,7 @@
public class MtlParser extends AbstractParser {
- private ObjMtl mtl = new ObjMtl();
+ private ObjMtl mtl = null;
private LineTokenizer tokenizer = null;
@@ -33,7 +33,8 @@
private ObjMtl.Material workingMaterial = null;
- public MtlParser(InputStream materialStream, GeometryProvider geoProvider) {
+ public MtlParser(String resourceName, InputStream materialStream, GeometryProvider geoProvider) {
+ mtl = new ObjMtl(resourceName);
this.materialStream = materialStream;
tokenizer = new LineTokenizer(materialStream);
}
Modified: spaces/trunk/src/com/ogoglio/viewer/j3d/obj/Obj.java
===================================================================
--- spaces/trunk/src/com/ogoglio/viewer/j3d/obj/Obj.java 2007-07-09 01:57:48 UTC (rev 221)
+++ spaces/trunk/src/com/ogoglio/viewer/j3d/obj/Obj.java 2007-07-10 17:43:14 UTC (rev 222)
@@ -14,6 +14,8 @@
package com.ogoglio.viewer.j3d.obj;
+import java.io.IOException;
+import java.io.Writer;
import java.util.Vector;
import javax.vecmath.Point3f;
@@ -64,6 +66,95 @@
private ObjMtl mtl = null;
+ public void writeObj(Writer writer) throws IOException {
+ writer.write("# created by Ogoglio Obj library\n");
+ if (mtl != null) {
+ writer.write("mtllib " + mtl.getResourceName() + "\n");
+ }
+
+ for (int i = 1; i <= vertices.size(); i++) {
+ Point3f point = getVertex(i);
+ writer.write("v " + point.x + " " + point.y + " " + point.z + "\n");
+ }
+
+ for (int i = 1; i <= textureVertices.size(); i++) {
+ Point3f point = getTextureVertex(i);
+ writer.write("vt " + point.x + " " + point.y + " " + point.z + "\n");
+ }
+
+ for (int i = 1; i <= normals.size(); i++) {
+ Vector3f normal = getNormal(i);
+ writer.write("vn " + normal.x + " " + normal.y + " " + normal.z + "\n");
+ }
+
+ int[][] groupRangeStarts = getRangeStarts(getGroups());
+ int[][] smoothingGroupRangeStarts = getRangeStarts(getSmoothingGroups());
+ int[][] materialRangeStarts = getRangeStarts(getMaterialGroups());
+
+ for (int i = 1; i <= faces.size(); i++) {
+
+ for (int j = 0; j < groupRangeStarts.length; j++) {
+ if(groupRangeStarts[j][0] == i) {
+ writer.write("g " + getGroup(groupRangeStarts[j][1]).getName() + "\n");
+ break;
+ }
+ }
+
+ for (int j = 0; j < smoothingGroupRangeStarts.length; j++) {
+ if(smoothingGroupRangeStarts[j][0] == i) {
+ writer.write("s " + getSmoothingGroup(smoothingGroupRangeStarts[j][1]).getID() + "\n");
+ break;
+ }
+ }
+
+ for (int j = 0; j < materialRangeStarts.length; j++) {
+ if(materialRangeStarts[j][0] == i) {
+ writer.write("usemtl " + getMaterialGroup(materialRangeStarts[j][1]).getName() + "\n");
+ break;
+ }
+ }
+ int[][] indices = getFaceIndices(i);
+ writer.write("f ");
+ for (int j = 0; j < indices.length; j++) {
+ if (indices[j][1] == -1 && indices[j][2] == -1) {
+ writer.write(indices[j][0] + "");
+ } else if (indices[j][1] == -1) {
+ writer.write(indices[j][0] + "//" + indices[j][2]);
+ } else if (indices[j][2] == -1) {
+ writer.write(indices[j][0] + "/" + indices[j][1]);
+ } else {
+ writer.write(indices[j][0] + "/" + indices[j][1] + "/" + indices[j][2]);
+ }
+
+ if (j != indices.length - 1) {
+ writer.write(" ");
+ }
+ }
+ writer.write("\n");
+ }
+ }
+
+ /**
+ * @return an int array [startingFace][ranged item index (starts index at 1)]
+ */
+ private int[][] getRangeStarts(RangedItem[] rangedItems){
+ int totalRanges = 0;
+ for (int i = 0; i < rangedItems.length; i++) {
+ totalRanges += rangedItems[i].getRanges().length;
+ }
+ int[][] rangeStarts = new int[totalRanges][2];
+ int startsIndex = 0;
+ for (int i = 0; i < rangedItems.length; i++) {
+ Range[] ranges = rangedItems[i].getRanges();
+ for (int j = 0; j < ranges.length; j++) {
+ rangeStarts[startsIndex][0] = ranges[j].lower;
+ rangeStarts[startsIndex][1] = i + 1;
+ startsIndex++;
+ }
+ }
+ return rangeStarts;
+ }
+
public int vertexCount() {
return vertices.size();
}
@@ -96,6 +187,13 @@
return (Group[]) groups.toArray(new Group[0]);
}
+ public Group getGroup(int index) {
+ if (index <= 0 || index > groups.size()) {
+ throw new IllegalArgumentException("Out of bounds: Face indices start at 1");
+ }
+ return (Group)groups.get(index - 1);
+ }
+
public Group getOrCreateGroup(String name) {
Group[] groups = getGroups();
for (int i = 0; i < groups.length; i++) {
@@ -136,6 +234,14 @@
return null;
}
+ public MaterialGroup getMaterialGroup(int index) {
+ if (index <= 0 || index > materialGroups.size()) {
+ throw new IllegalArgumentException("Texture vertices are indexed starting at 1 so " + index + " is invalid");
+ }
+ return (MaterialGroup) materialGroups.get(index - 1);
+ }
+
+
public MaterialGroup getOrCreateMaterialGroup(String name) {
MaterialGroup[] groups = getMaterialGroups();
for (int i = 0; i < groups.length; i++) {
@@ -194,8 +300,15 @@
}
public Vector3f[] getNormals() {
- return (Vector3f[])normals.toArray(new Vector3f[0]);
+ return (Vector3f[]) normals.toArray(new Vector3f[0]);
}
+
+ public Vector3f getNormal(int index) {
+ if (index <= 0 || index > normals.size()) {
+ throw new IllegalArgumentException("Texture vertices are indexed starting at 1 so " + index + " is invalid");
+ }
+ return (Vector3f) normals.get(index - 1);
+ }
public void addSmoothingGroup(SmoothingGroup sGroup) {
smoothingGroups.add(sGroup);
@@ -205,6 +318,14 @@
return (SmoothingGroup[]) smoothingGroups.toArray(new SmoothingGroup[0]);
}
+ public SmoothingGroup getSmoothingGroup(int index) {
+ if (index <= 0 || index > smoothingGroups.size()) {
+ throw new IllegalArgumentException("Indices start at 1 in obj so " + index + " is invalid");
+ }
+ return (SmoothingGroup) smoothingGroups.get(index - 1);
+
+ }
+
public SmoothingGroup getOrCreateSmoothingGroup(int id) {
SmoothingGroup[] groups = getSmoothingGroups();
for (int i = 0; i < groups.length; i++) {
@@ -260,7 +381,11 @@
}
}
- public class Group {
+ public interface RangedItem {
+ public Range[] getRanges();
+ }
+
+ public class Group implements RangedItem {
String name = null;
@@ -287,7 +412,7 @@
}
}
- public static class MaterialGroup {
+ public static class MaterialGroup implements RangedItem {
String name = null;
@@ -310,7 +435,7 @@
}
}
- public static class SmoothingGroup {
+ public static class SmoothingGroup implements RangedItem {
int id = -1;
Vector ranges = new Vector();
Modified: spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjMtl.java
===================================================================
--- spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjMtl.java 2007-07-09 01:57:48 UTC (rev 221)
+++ spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjMtl.java 2007-07-10 17:43:14 UTC (rev 222)
@@ -14,6 +14,8 @@
package com.ogoglio.viewer.j3d.obj;
+import java.io.IOException;
+import java.io.Writer;
import java.util.HashMap;
import javax.vecmath.Color3f;
@@ -73,6 +75,16 @@
private HashMap materials = new HashMap();
+ private String resourceName = null; //e.g. foo.mtl
+
+ public ObjMtl(String resourceName) {
+ this.resourceName = resourceName;
+ }
+
+ public String getResourceName() {
+ return resourceName;
+ }
+
public void addMaterial(Material material) {
materials.put(material.getName(), material);
}
@@ -85,6 +97,37 @@
return (Material[]) materials.values().toArray(new Material[0]);
}
+ public void writeMtl(Writer writer) throws IOException {
+ writer.write("# created by Ogoglio Obj library\n");
+ Material[] materials = getMaterials();
+ Color3f workingColor = new Color3f();
+ for (int i = 0; i < materials.length; i++) {
+ writer.write("\n");
+ writer.write("newmtl " + materials[i].getName() + "\n");
+
+ materials[i].getAmbientColor(workingColor);
+ writer.write("Ka " + workingColor.x + " " + workingColor.y + " " + workingColor.z + "\n");
+ materials[i].getDiffuseColor(workingColor);
+ writer.write("Kd " + workingColor.x + " " + workingColor.y + " " + workingColor.z + "\n");
+ materials[i].getSpecularColor(workingColor);
+ writer.write("Ks " + workingColor.x + " " + workingColor.y + " " + workingColor.z + "\n");
+
+ writer.write("d " + materials[i].getDissolve() + "\n");
+ writer.write("illum " + materials[i].getIlluminationModel() + "\n");
+ writer.write("Ns " + materials[i].getSpecularExponent() + "\n");
+
+ if(materials[i].getAmbientMapName() != null) {
+ writer.write("map_Ka " + materials[i].getAmbientMapName());
+ }
+ if(materials[i].getDiffuseMapName() != null) {
+ writer.write("map_Kd " + materials[i].getDiffuseMapName());
+ }
+ if(materials[i].getSpecularMapName() != null) {
+ writer.write("map_Ks " + materials[i].getSpecularMapName());
+ }
+ }
+ }
+
public static class Material {
private String name = DEFAULT_MATERIAL_NAME;
Modified: spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjParser.java
===================================================================
--- spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjParser.java 2007-07-09 01:57:48 UTC (rev 221)
+++ spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjParser.java 2007-07-10 17:43:14 UTC (rev 222)
@@ -102,7 +102,7 @@
}
String fileName = toString(tokens, 1, tokens.length - 1);
InputStream materialStream = geoProvider.getSubGeometryStream(fileName);
- MtlParser parser = new MtlParser(materialStream, geoProvider);
+ MtlParser parser = new MtlParser(fileName, materialStream, geoProvider);
ObjMtl mtl = parser.parse();
obj.setMtl(mtl);
}
@@ -226,7 +226,9 @@
continue;
}
results[i] = Integer.parseInt(inputs[i]);
- results[i] = Math.abs(results[i]); //try to work around f'ing stupid Max2Obj script writers
+ if(results[i] < 0) {
+ results[i] = obj.vertexCount() + results[i] + 1; //handle relative negative indices (which I originally thought was non-spec)
+ }
}
return results;
} catch (NumberFormatException e) {
Modified: spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjTest.java
===================================================================
--- spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjTest.java 2007-07-09 01:57:48 UTC (rev 221)
+++ spaces/trunk/src/com/ogoglio/viewer/j3d/obj/ObjTest.java 2007-07-10 17:43:14 UTC (rev 222)
@@ -15,19 +15,28 @@
package com.ogoglio.viewer.j3d.obj;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import junit.framework.TestCase;
+import com.ogoglio.client.model.GeometryProvider;
+import com.ogoglio.util.ArgumentUtils;
+
public class ObjTest extends TestCase {
- //ResourceCache resourceCache = null;
+ private static final String OBJ_DIR_PATH = "src/com/ogoglio/persist/resources/";
+ TestGeometryProvider geoProvider1 = null;
+
public void setUp() {
try {
- //resourceCache = new ResourceCache(new URL("http://localhost:8080/oc/"));
+ geoProvider1 = new TestGeometryProvider(OBJ_DIR_PATH + "door.obj", OBJ_DIR_PATH + "door.mtl");
} catch (Exception e) {
fail("Could not setup:" + e);
}
@@ -41,15 +50,30 @@
}
public void testBasics() {
- assertIsValidObj("test1.obj");
- assertIsValidObj("test2.obj");
+ assertIsValidObj(geoProvider1);
}
- public void assertIsValidObj(String objName) {
- /*
+ private void printParsed(GeometryProvider geoProvider) {
try {
- ObjParser parser = new ObjParser(2, resourceCache);
+ ObjParser parser = new ObjParser(geoProvider1, 0);
Obj obj = parser.parse();
+ StringWriter writer = new StringWriter();
+ obj.writeObj(writer);
+ System.out.println(writer);
+ System.out.println("===================");
+ writer = new StringWriter();
+ obj.getMtl().writeMtl(writer);
+ System.out.println(writer);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public void assertIsValidObj(GeometryProvider geoProvider) {
+ try {
+ ObjParser parser = new ObjParser(geoProvider, 0);
+ Obj obj = parser.parse();
assertNotNull(obj);
try {
@@ -133,7 +157,6 @@
e.printStackTrace();
fail();
}
- */
}
private static void assertValidVertex(Point3f vertex) {
@@ -172,4 +195,36 @@
}
}
+ private class TestGeometryProvider implements GeometryProvider {
+
+ private String objPath = null;
+
+ private String mtlPath = null;
+
+ public TestGeometryProvider(String objPath, String mtlPath) {
+ ArgumentUtils.assertReadableFile(objPath);
+ this.objPath = objPath;
+ ArgumentUtils.assertReadableFile(mtlPath);
+ this.mtlPath = mtlPath;
+ }
+
+ public InputStream getAnimationStream(long animationID) throws IOException {
+ return null;
+ }
+
+ public InputStream getGeometryStream(int lodIndex) throws IOException {
+ return new FileInputStream(objPath);
+ }
+
+ public InputStream getSkinMapStream() throws IOException {
+ return null;
+ }
+
+ public InputStream getSubGeometryStream(String name) throws IOException {
+ if (name.endsWith(".mtl")) {
+ return new FileInputStream(mtlPath);
+ }
+ return null;
+ }
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|