Cleanup OBJLoader parse function and fix issues related to JVM differences.
Also fix support for sopme of the spec that was partially respected.
This commit is contained in:
parent
fb0bdd1276
commit
07a2b67b7f
1 changed files with 114 additions and 161 deletions
|
@ -45,6 +45,7 @@ import net.minecraftforge.common.property.IUnlistedProperty;
|
|||
import net.minecraftforge.fml.common.FMLLog;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.core.helpers.Strings;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Function;
|
||||
|
@ -201,146 +202,95 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
|
|||
return this.groupList;
|
||||
}
|
||||
|
||||
private float[] parseFloats(String[] data) // Helper converting strings to floats
|
||||
{
|
||||
float[] ret = new float[data.length];
|
||||
for (int i = 0; i < data.length; i++)
|
||||
ret[i] = Float.parseFloat(data[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//Partial reading of the OBJ format. Documentation taken from http://paulbourke.net/dataformats/obj/
|
||||
public OBJModel parse() throws IOException
|
||||
{
|
||||
String currentLine = "";
|
||||
Material material = new Material();
|
||||
material.setName(Material.DEFAULT_NAME);
|
||||
int usemtlCounter = 0;
|
||||
|
||||
// float[] minUVBounds = new float[] {0.0f, 0.0f};
|
||||
// float[] maxUVBounds = new float[] {1.0f, 1.0f};
|
||||
int lineNum = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
lineNum++;
|
||||
currentLine = objReader.readLine();
|
||||
if (currentLine == null) break;
|
||||
currentLine.trim();
|
||||
if (currentLine.isEmpty() || currentLine.startsWith("#")) continue;
|
||||
|
||||
try
|
||||
{
|
||||
String[] fields = WHITE_SPACE.split(currentLine, 2);
|
||||
String key = fields[0];
|
||||
String data = fields[1];
|
||||
String[] splitData = WHITE_SPACE.split(data);
|
||||
|
||||
if (key.equalsIgnoreCase("mtllib"))
|
||||
{
|
||||
this.materialLibrary.parseMaterials(manager, data, objFrom);
|
||||
}
|
||||
else if (key.equalsIgnoreCase("usemtl"))
|
||||
{
|
||||
material = this.materialLibrary.materials.get(data);
|
||||
usemtlCounter++;
|
||||
}
|
||||
else if (key.equalsIgnoreCase("v"))
|
||||
else if (key.equalsIgnoreCase("v")) // Vertices: x y z [w] - w Defaults to 1.0
|
||||
{
|
||||
float[] floatSplitData = new float[splitData.length];
|
||||
for (int i = 0; i < splitData.length; i++)
|
||||
floatSplitData[i] = Float.parseFloat(splitData[i]);
|
||||
Vector4f pos = new Vector4f(floatSplitData[0], floatSplitData[1], floatSplitData[2], floatSplitData.length == 4 ? floatSplitData[3] : 1);
|
||||
Vertex vertex = new Vertex(pos, material);
|
||||
this.vertices.add(vertex);
|
||||
float[] coords = parseFloats(splitData);
|
||||
Vector4f pos = new Vector4f(coords[0], coords[1], coords[2], coords.length == 4 ? coords[3] : 1.0F);
|
||||
this.vertices.add(new Vertex(pos, material));
|
||||
}
|
||||
else if (key.equalsIgnoreCase("vn"))
|
||||
else if (key.equalsIgnoreCase("vn")) // Vertex normals: x y z
|
||||
{
|
||||
float[] floatSplitData = new float[splitData.length];
|
||||
for (int i = 0; i < splitData.length; i++)
|
||||
floatSplitData[i] = Float.parseFloat(splitData[i]);
|
||||
Normal normal = new Normal(floatSplitData);
|
||||
this.normals.add(normal);
|
||||
this.normals.add(new Normal(parseFloats(splitData)));
|
||||
}
|
||||
else if (key.equalsIgnoreCase("vt"))
|
||||
else if (key.equalsIgnoreCase("vt")) // Vertex Textures: u [v] [w] - v/w Defaults to 0
|
||||
{
|
||||
float[] floatSplitData = new float[splitData.length];
|
||||
for (int i = 0; i < splitData.length; i++)
|
||||
floatSplitData[i] = Float.parseFloat(splitData[i]);
|
||||
TextureCoordinate texCoord = new TextureCoordinate(new Vector3f(floatSplitData[0], floatSplitData[1], floatSplitData.length == 3 ? floatSplitData[2] : 1));
|
||||
float[] coords = parseFloats(splitData);
|
||||
TextureCoordinate texCoord = new TextureCoordinate(coords[0],
|
||||
coords.length >= 2 ? coords[1] : 0.0F,
|
||||
coords.length >= 3 ? coords[2] : 0.0F);
|
||||
if (texCoord.u < 0.0f || texCoord.u > 1.0f || texCoord.v < 0.0f || texCoord.v > 1.0f)
|
||||
throw new UVsOutOfBoundsException(this.objFrom);
|
||||
// this.UVsOutOfBounds = (texCoord.u < 0.0f || texCoord.u > 1.0f || texCoord.v < 0.0f || texCoord.v > 1.0f);
|
||||
|
||||
// if (texCoord.u < 0.0f || texCoord.u > 1.0f || texCoord.v < 0.0f || texCoord.v > 1.0f)
|
||||
// {
|
||||
// this.UVsOutOfBounds = true;
|
||||
// texCoord.u -= Math.floor(texCoord.u);
|
||||
// texCoord.v -= Math.floor(texCoord.v);
|
||||
// }
|
||||
|
||||
// minUVBounds[0] = floatSplitData[0] < minUVBounds[0] ? floatSplitData[0] : minUVBounds[0];
|
||||
// minUVBounds[1] = floatSplitData[1] < minUVBounds[1] ? floatSplitData[1] : minUVBounds[1];
|
||||
// maxUVBounds[0] = floatSplitData[0] > maxUVBounds[0] ? floatSplitData[0] : maxUVBounds[0];
|
||||
// maxUVBounds[1] = floatSplitData[1] > maxUVBounds[1] ? floatSplitData[1] : maxUVBounds[1];
|
||||
// FMLLog.info("u: [%f, %f] v: [%f, %f]", minUVBounds[]);
|
||||
this.texCoords.add(texCoord);
|
||||
}
|
||||
else if (key.equalsIgnoreCase("f"))
|
||||
else if (key.equalsIgnoreCase("f")) // Face Elements: f v1[/vt1][/vn1] ...
|
||||
{
|
||||
String[][] splitSlash = new String[splitData.length][];
|
||||
if (splitData.length > 4) FMLLog.warning("OBJModel.Parser: found a face ('f') with more than 4 vertices, only the first 4 of these vertices will be rendered!");
|
||||
|
||||
int vert = 0;
|
||||
int texCoord = 0;
|
||||
int norm = 0;
|
||||
if (splitData.length > 4)
|
||||
FMLLog.warning("OBJModel.Parser: found a face ('f') with more than 4 vertices, only the first 4 of these vertices will be rendered!");
|
||||
|
||||
List<Vertex> v = Lists.newArrayListWithCapacity(splitData.length);
|
||||
// List<TextureCoordinate> t = Lists.newArrayListWithCapacity(splitData.length);
|
||||
// List<Normal> n = Lists.newArrayListWithCapacity(splitData.length);
|
||||
|
||||
for (int i = 0; i < splitData.length; i++)
|
||||
{
|
||||
if (splitData[i].contains("//"))
|
||||
{
|
||||
splitSlash[i] = splitData[i].split("//");
|
||||
String[] pts = splitData[i].split("/");
|
||||
|
||||
int vert = Integer.parseInt(pts[0]);
|
||||
Integer texture = pts.length < 2 || Strings.isEmpty(pts[1]) ? null : Integer.parseInt(pts[1]);
|
||||
Integer normal = pts.length < 3 || Strings.isEmpty(pts[2]) ? null : Integer.parseInt(pts[2]);
|
||||
|
||||
vert = Integer.parseInt(splitSlash[i][0]);
|
||||
vert = vert < 0 ? this.vertices.size() - 1 : vert - 1;
|
||||
norm = Integer.parseInt(splitSlash[i][1]);
|
||||
norm = norm < 0 ? this.normals.size() - 1 : norm - 1;
|
||||
|
||||
Vertex newV = new Vertex(new Vector4f(this.vertices.get(vert).getPos()), this.vertices.get(vert).getMaterial());
|
||||
newV.setNormal(this.normals.get(norm));
|
||||
|
||||
if (texture != null)
|
||||
newV.setTextureCoordinate(this.texCoords.get(texture < 0 ? this.texCoords.size() - 1 : texture - 1));
|
||||
if (normal != null)
|
||||
newV.setNormal(this.normals.get(normal < 0 ? this.normals.size() - 1 : normal - 1));
|
||||
|
||||
v.add(newV);
|
||||
// n.add(this.normals.get(norm));
|
||||
}
|
||||
else if (splitData[i].contains("/"))
|
||||
{
|
||||
splitSlash[i] = splitData[i].split("/");
|
||||
|
||||
vert = Integer.parseInt(splitSlash[i][0]);
|
||||
vert = vert < 0 ? this.vertices.size() - 1 : vert - 1;
|
||||
texCoord = Integer.parseInt(splitSlash[i][1]);
|
||||
texCoord = texCoord < 0 ? this.texCoords.size() - 1 : texCoord - 1;
|
||||
if (splitSlash[i].length > 2)
|
||||
{
|
||||
norm = Integer.parseInt(splitSlash[i][2]);
|
||||
norm = norm < 0 ? this.normals.size() - 1 : norm - 1;
|
||||
}
|
||||
|
||||
Vertex newV = new Vertex(new Vector4f(this.vertices.get(vert).getPos()), this.vertices.get(vert).getMaterial());
|
||||
newV.setTextureCoordinate(this.texCoords.get(texCoord));
|
||||
newV.setNormal(splitSlash[i].length > 2 ? this.normals.get(norm) : null);
|
||||
Vertex[] va = v.toArray(new Vertex[v.size()]);
|
||||
|
||||
v.add(newV);
|
||||
// t.add(this.texCoords.get(texCoord));
|
||||
// if (splitSlash[i].length > 2) n.add(this.normals.get(norm));
|
||||
}
|
||||
else
|
||||
{
|
||||
splitSlash[i] = splitData[i].split("");
|
||||
|
||||
vert = Integer.parseInt(splitSlash[i][0]);
|
||||
vert = vert < 0 ? this.vertices.size() - 1 : vert - 1;
|
||||
|
||||
Vertex newV = new Vertex(new Vector4f(this.vertices.get(vert).getPos()), this.vertices.get(vert).getMaterial());
|
||||
v.add(newV);
|
||||
}
|
||||
}
|
||||
|
||||
Vertex[] va = new Vertex[v.size()];
|
||||
v.toArray(va);
|
||||
// TextureCoordinate[] ta = new TextureCoordinate[t.size()];
|
||||
// t.toArray(ta);
|
||||
// Normal[] na = new Normal[n.size()];
|
||||
// n.toArray(na);
|
||||
Face face = new Face(va, material.name);
|
||||
if (usemtlCounter < this.vertices.size())
|
||||
{
|
||||
|
@ -399,14 +349,17 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
|
|||
if (!unknownObjectCommands.contains(key))
|
||||
{
|
||||
unknownObjectCommands.add(key);
|
||||
FMLLog.info("OBJLoader.Parser: command '%s' (model: '%s') is not currently supported, skipping", key, objFrom);
|
||||
FMLLog.info("OBJLoader.Parser: command '%s' (model: '%s') is not currently supported, skipping. Line: %d '%s'", key, objFrom, lineNum, currentLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
throw new RuntimeException(String.format("OBJLoader.Parser: Exception parsing line #%d: `%s`", lineNum, currentLine), e);
|
||||
}
|
||||
}
|
||||
|
||||
OBJModel model = new OBJModel(this.materialLibrary, this.objFrom);
|
||||
// model.getMatLib().setUVBounds(minUVBounds[0], maxUVBounds[0], minUVBounds[1], maxUVBounds[1]);
|
||||
return model;
|
||||
return new OBJModel(this.materialLibrary, this.objFrom);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue