OBJ loader: fixed another whitespace-related issue; removed unused "modifyUVs" property for now; added the "flip-v" property to switch between OpenGL-style and DirextX-style model UVs; fixed normals - they are now correct in-world, still a bit strange for the items; fixed normals a little bit for B3D models too.

This commit is contained in:
RainWarrior 2015-10-29 22:50:45 +03:00
parent c3b15e3f6c
commit 12e6fe9db7
3 changed files with 255 additions and 286 deletions

View file

@ -582,11 +582,11 @@ public class B3DLoader implements ICustomModelLoader
case NORMAL:
if(v.getNormal() != null)
{
builder.put(e, v.getNormal().x, v.getNormal().y, v.getNormal().z, 1);
builder.put(e, v.getNormal().x, v.getNormal().y, v.getNormal().z, 0);
}
else
{
builder.put(e, faceNormal.x, faceNormal.y, faceNormal.z, 1);
builder.put(e, faceNormal.x, faceNormal.y, faceNormal.z, 0);
}
break;
default:

View file

@ -17,6 +17,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.vecmath.Matrix3f;
import javax.vecmath.Matrix4f;
import javax.vecmath.Quat4f;
import javax.vecmath.Vector2f;
@ -625,7 +626,8 @@ public class B3DModel
bm.mul(bone.getLeft());
t.add(bm);
}
if(totalWeight != 0) t.mul(1f / totalWeight);
if(Math.abs(totalWeight) > 1e-4) t.mul(1f / totalWeight);
else t.setIdentity();
}
// pos
@ -635,12 +637,12 @@ public class B3DModel
Vector3f rPos = new Vector3f(newPos.x / newPos.w, newPos.y / newPos.w, newPos.z / newPos.w);
// normal
t.invert();
t.transpose();
Vector4f normal = new Vector4f(this.normal), newNormal = new Vector4f();
normal.w = 1;
t.transform(normal, newNormal);
Vector3f rNormal = new Vector3f(newNormal.x / newNormal.w, newNormal.y / newNormal.w, newNormal.z / newNormal.w);
Matrix3f tm = new Matrix3f();
t.getRotationScale(tm);
tm.invert();
tm.transpose();
Vector3f normal = new Vector3f(this.normal), rNormal = new Vector3f();
tm.transform(normal, rNormal);
rNormal.normalize();
// texCoords TODO

View file

@ -14,6 +14,7 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.vecmath.Matrix3f;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector2f;
import javax.vecmath.Vector3f;
@ -69,7 +70,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
public OBJModel(MaterialLibrary matLib, ResourceLocation modelLocation)
{
this(matLib, modelLocation, null);
this(matLib, modelLocation, new CustomData());
}
public OBJModel(MaterialLibrary matLib, ResourceLocation modelLocation, CustomData customData)
@ -131,16 +132,11 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
{
return this.matLib;
}
public boolean hasCustomData()
{
return this.customData != null;
}
@Override
public IModel process(ImmutableMap<String, String> customData)
{
OBJModel ret = new OBJModel(this.matLib, this.modelLocation, new CustomData(customData));
OBJModel ret = new OBJModel(this.matLib, this.modelLocation, new CustomData(this.customData, customData));
return ret;
}
@ -150,35 +146,44 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
OBJModel ret = new OBJModel(this.matLib.makeLibWithReplacements(textures), this.modelLocation, this.customData);
return ret;
}
public static class CustomData
static class CustomData
{
public boolean ambientOcclusion = true;
public boolean gui3d = true;
public boolean modifyUVs = false;
public CustomData(ImmutableMap<String, String> customData)
{
this.process(customData);
}
public void process(ImmutableMap<String, String> customData)
{
for (Map.Entry<String, String> e : customData.entrySet())
{
if (e.getKey().equals("ambient"))
this.ambientOcclusion = Boolean.valueOf(e.getValue());
else if (e.getKey().equals("gui3d"))
this.gui3d = Boolean.valueOf(e.getValue());
else if (e.getKey().equals("modifyUVs"))
this.modifyUVs = Boolean.valueOf(e.getValue());
}
}
public boolean ambientOcclusion = true;
public boolean gui3d = true;
// should be an enum, TODO
//public boolean modifyUVs = false;
public boolean flipV = false;
public CustomData(CustomData parent, ImmutableMap<String, String> customData)
{
this.ambientOcclusion = parent.ambientOcclusion;
this.gui3d = parent.gui3d;
this.flipV = parent.flipV;
this.process(customData);
}
public CustomData() {}
public void process(ImmutableMap<String, String> customData)
{
for (Map.Entry<String, String> e : customData.entrySet())
{
if (e.getKey().equals("ambient"))
this.ambientOcclusion = Boolean.valueOf(e.getValue());
else if (e.getKey().equals("gui3d"))
this.gui3d = Boolean.valueOf(e.getValue());
/*else if (e.getKey().equals("modifyUVs"))
this.modifyUVs = Boolean.valueOf(e.getValue());*/
else if (e.getKey().equals("flip-v"))
this.flipV = Boolean.valueOf(e.getValue());
}
}
}
public static class Parser
{
private static final Pattern WHITE_SPACE = Pattern.compile("\\s+");
private static final Pattern WHITE_SPACE = Pattern.compile("\\s+");
private static Set<String> unknownObjectCommands = new HashSet<String>();
public MaterialLibrary materialLibrary = new MaterialLibrary();
private IResourceManager manager;
@ -209,7 +214,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
String currentLine = "";
Material material = new Material();
int usemtlCounter = 0;
// float[] minUVBounds = new float[] {0.0f, 0.0f};
// float[] maxUVBounds = new float[] {1.0f, 1.0f};
@ -217,8 +222,9 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
{
currentLine = objReader.readLine();
if (currentLine == null) break;
currentLine.trim();
if (currentLine.isEmpty() || currentLine.startsWith("#")) continue;
String[] fields = WHITE_SPACE.split(currentLine, 2);
String key = fields[0];
String data = fields[1];
@ -255,14 +261,14 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
floatSplitData[i] = Float.parseFloat(splitData[i]);
TextureCoordinate texCoord = new TextureCoordinate(new Vector3f(floatSplitData[0], floatSplitData[1], floatSplitData.length == 3 ? floatSplitData[2] : 1));
if (texCoord.u < 0.0f || texCoord.u > 1.0f || texCoord.v < 0.0f || texCoord.v > 1.0f)
throw new UVsOutOfBoundsException(this.objFrom);
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);
// 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];
@ -297,7 +303,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
norm = norm < 0 ? this.normals.size() - 1 : norm - 1;
this.vertices.get(vert).setNormal(this.normals.get(norm));
v.add(this.vertices.get(vert));
// n.add(this.normals.get(norm));
}
@ -314,7 +320,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
norm = Integer.parseInt(splitSlash[i][2]);
norm = norm < 0 ? this.normals.size() - 1 : norm - 1;
}
this.vertices.get(vert).setTextureCoordinate(this.texCoords.get(texCoord));
this.vertices.get(vert).setNormal(splitSlash[i].length > 2 ? this.normals.get(norm) : null);
@ -401,8 +407,8 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
}
}
}
OBJModel model = new OBJModel(this.materialLibrary, this.objFrom, null);
OBJModel model = new OBJModel(this.materialLibrary, this.objFrom);
// model.getMatLib().setUVBounds(minUVBounds[0], maxUVBounds[0], minUVBounds[1], maxUVBounds[1]);
return model;
}
@ -410,7 +416,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
public static class MaterialLibrary
{
private static final Pattern WHITE_SPACE = Pattern.compile("\\s+");
private static final Pattern WHITE_SPACE = Pattern.compile("\\s+");
private Set<String> unknownMaterialCommands = new HashSet<String>();
private Map<String, Material> materials = new HashMap<String, Material>();
private Map<String, Group> groups = new HashMap<String, Group>();
@ -424,9 +430,9 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
{
this.groups.put(Group.DEFAULT_NAME, new Group(Group.DEFAULT_NAME, null));
}
public MaterialLibrary makeLibWithReplacements(ImmutableMap<String, String> replacements)
{
{
Map<String, Material> mats = new HashMap<String, Material>();
for (Map.Entry<String, Material> e : this.materials.entrySet())
{
@ -453,14 +459,14 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
return ret;
}
// public float[] getMinUVBounds()
// public float[] getMinUVBounds()
// {
// return this.minUVBounds;
// return this.minUVBounds;
// }
// public float[] getMaxUVBounds()
// {
// return this.maxUVBounds;
// return this.maxUVBounds;
// }
// public void setUVBounds(float minU, float maxU, float minV, float maxV)
@ -512,8 +518,8 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
boolean hasSetTexture = false;
boolean hasSetColor = false;
String domain = from.getResourceDomain();
if (!path.contains("/"))
path = from.getResourcePath().substring(0, from.getResourcePath().lastIndexOf("/") + 1) + path;
if (!path.contains("/"))
path = from.getResourcePath().substring(0, from.getResourcePath().lastIndexOf("/") + 1) + path;
mtlStream = new InputStreamReader(manager.getResource(new ResourceLocation(domain, path)).getInputStream(), Charsets.UTF_8);
mtlReader = new BufferedReader(mtlStream);
@ -528,6 +534,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
{
currentLine = mtlReader.readLine();
if (currentLine == null) break;
currentLine.trim();
if (currentLine.isEmpty() || currentLine.startsWith("#")) continue;
String[] fields = WHITE_SPACE.split(currentLine, 2);
@ -582,11 +589,11 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
}
else if (key.equalsIgnoreCase("d") || key.equalsIgnoreCase("Tr"))
{
//d <-optional key here> float[0.0:1.0, 1.0]
//Tr r g b OR Tr spectral map file OR Tr xyz r g b (CIEXYZ colorspace)
String[] splitData = WHITE_SPACE.split(data);
float alpha = Float.parseFloat(splitData[splitData.length - 1]);
material.getColor().setW(alpha);
//d <-optional key here> float[0.0:1.0, 1.0]
//Tr r g b OR Tr spectral map file OR Tr xyz r g b (CIEXYZ colorspace)
String[] splitData = WHITE_SPACE.split(data);
float alpha = Float.parseFloat(splitData[splitData.length - 1]);
material.getColor().setW(alpha);
}
else
{
@ -756,11 +763,11 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
{
this(verts, Material.DEFAULT_NAME);
}
public Face(Vertex[] verts, String materialName) {
this.verts = verts != null && verts.length > 2 ? verts : null;
setMaterialName(materialName);
checkData();
this.verts = verts != null && verts.length > 2 ? verts : null;
setMaterialName(materialName);
checkData();
}
// public Face(Vertex[] verts, Normal[] norms)
@ -780,9 +787,9 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
// public Face(Vertex[] verts, Normal[] norms, TextureCoordinate[] texCoords, String materialName)
// {
// this.verts = verts != null && verts.length > 2 ? verts : null;
// this.norms = norms != null && norms.length > 2 ? norms : null;
// this.texCoords = texCoords != null && texCoords.length > 2 ? texCoords : null;
// this.verts = verts != null && verts.length > 2 ? verts : null;
// this.norms = norms != null && norms.length > 2 ? norms : null;
// this.texCoords = texCoords != null && texCoords.length > 2 ? texCoords : null;
// setMaterialName(materialName);
// checkData();
// }
@ -791,7 +798,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
{
if (this.verts != null && this.verts.length == 3)
{
this.isTri = true;
this.isTri = true;
this.verts = new Vertex[]{this.verts[0], this.verts[1], this.verts[2], this.verts[2]};
}
}
@ -822,40 +829,40 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
// public boolean areUVsNormalized()
// {
// for (Vertex v : this.verts)
// if (!v.hasNormalizedUVs())
// return false;
// if (!v.hasNormalizedUVs())
// return false;
// return true;
// }
// public void normalizeUVs(float[] min, float[] max)
// {
// if (!this.areUVsNormalized())
// {
// for (int i = 0; i < this.verts.length; i++) {
// TextureCoordinate texCoord = this.verts[i].getTextureCoordinate();
// min[0] = texCoord.u < min[0] ? texCoord.u : min[0];
// max[0] = texCoord.u > max[0] ? texCoord.u : max[0];
// min[1] = texCoord.v < min[1] ? texCoord.v : min[1];
// max[1] = texCoord.v > max[1] ? texCoord.v : max[1];
// }
//
// for (Vertex v : this.verts) {
// v.texCoord.u = (v.texCoord.u - min[0]) / (max[0] - min[0]);
// v.texCoord.v = (v.texCoord.v - min[1]) / (max[1] - max[1]);
// }
// }
// if (!this.areUVsNormalized())
// {
// for (int i = 0; i < this.verts.length; i++) {
// TextureCoordinate texCoord = this.verts[i].getTextureCoordinate();
// min[0] = texCoord.u < min[0] ? texCoord.u : min[0];
// max[0] = texCoord.u > max[0] ? texCoord.u : max[0];
// min[1] = texCoord.v < min[1] ? texCoord.v : min[1];
// max[1] = texCoord.v > max[1] ? texCoord.v : max[1];
// }
//
// for (Vertex v : this.verts) {
// v.texCoord.u = (v.texCoord.u - min[0]) / (max[0] - min[0]);
// v.texCoord.v = (v.texCoord.v - min[1]) / (max[1] - max[1]);
// }
// }
// }
public Face bake(TRSRTransformation transform)
{
Matrix4f m = transform.getMatrix();
Matrix3f mn = null;
Vertex[] vertices = new Vertex[verts.length];
// Normal[] normals = norms != null ? new Normal[norms.length] : null;
// TextureCoordinate[] textureCoords = texCoords != null ? new TextureCoordinate[texCoords.length] : null;
for (int i = 0; i < verts.length; i++)
{
m = transform.getMatrix();
Vertex v = verts[i];
// Normal n = norms != null ? norms[i] : null;
// TextureCoordinate t = texCoords != null ? texCoords[i] : null;
@ -864,34 +871,25 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
pos.w = 1;
m.transform(pos, newPos);
vertices[i] = new Vertex(newPos, v.getMaterial());
if (v.hasNormal())
{
m.invert();
Vector4f normal = new Vector4f(v.getNormal().getData()), newNormal = new Vector4f();
normal.w = 1.0f;
m.transform(normal, newNormal);
Vector3f rNormal = new Vector3f(newNormal.x / newNormal.w, newNormal.y / newNormal.w, newNormal.z / newNormal.w);
rNormal.normalize();
vertices[i].setNormal(new Normal(rNormal));
if(mn == null)
{
mn = new Matrix3f();
m.getRotationScale(mn);
mn.invert();
mn.transpose();
}
Vector3f normal = new Vector3f(v.getNormal().getData()), newNormal = new Vector3f();
mn.transform(normal, newNormal);
newNormal.normalize();
vertices[i].setNormal(new Normal(newNormal));
}
else v.setNormal(new Normal(0.0f, 1.0f, 0.0f));
if (v.hasTextureCoordinate()) vertices[i].setTextureCoordinate(v.getTextureCoordinate());
else v.setTextureCoordinate(TextureCoordinate.getDefaultUVs()[i]);
// if (n != null)
// {
// m.invert();
// m.transpose();
// Vector4f normal = new Vector4f(n.getData()), newNormal = new Vector4f();
// normal.w = 1;
// m.transform(normal, newNormal);
// Vector3f rNormal = new Vector3f(newNormal.x / newNormal.w, newNormal.y / newNormal.w, newNormal.z / newNormal.w);
// rNormal.normalize();
// normals[i] = new Normal(rNormal);
// }
//texCoords TODO
// if (t != null) textureCoords[i] = t;
}
@ -900,40 +898,13 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
public Normal getNormal()
{
for (Vertex v : this.verts)
{
if (!v.hasNormal())
{
Vector3f vPos = v.getPos3();
vPos.normalize();
v.setNormal(new Normal(vPos));
}
}
Vector3f a = this.verts[1].getNormal().getData();
a.sub(this.verts[0].getNormal().getData());
Vector3f b = this.verts[2].getNormal().getData();
b.sub(this.verts[0].getNormal().getData());
Vector3f c = new Vector3f();
c.cross(a, b);
c.normalize();
if (this.isTri) return new Normal(c);
else
{
a = this.verts[1].getNormal().getData();
a.sub(this.verts[3].getNormal().getData());
b = this.verts[2].getNormal().getData();
b.sub(this.verts[3].getNormal().getData());
Vector3f c1 = new Vector3f();
c1.cross(a, b);
c1.normalize();
Vector3f normal = new Vector3f();
normal.add(c, c1);
normal.scale(0.5f);
normal.normalize();
return new Normal(normal);
}
Vector3f a = this.verts[2].getPos3();
a.sub(this.verts[0].getPos3());
Vector3f b = this.verts[3].getPos3();
b.sub(this.verts[1].getPos3());
a.cross(a, b);
a.normalize();
return new Normal(a);
}
}
@ -959,45 +930,45 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
{
return this.position;
}
public Vector3f getPos3()
{
return new Vector3f(this.position.x, this.position.y, this.position.z);
return new Vector3f(this.position.x, this.position.y, this.position.z);
}
public boolean hasNormal()
{
return this.normal != null;
return this.normal != null;
}
public void setNormal(Normal normal)
{
this.normal = normal;
this.normal = normal;
}
public Normal getNormal()
{
return this.normal;
return this.normal;
}
public boolean hasTextureCoordinate()
{
return this.texCoord != null;
return this.texCoord != null;
}
public void setTextureCoordinate(TextureCoordinate texCoord)
{
this.texCoord = texCoord;
this.texCoord = texCoord;
}
public TextureCoordinate getTextureCoordinate()
{
return this.texCoord;
return this.texCoord;
}
// public boolean hasNormalizedUVs()
// {
// return this.texCoord.u >= 0.0f && this.texCoord.u <= 1.0f && this.texCoord.v >= 0.0f && this.texCoord.v <= 1.0f;
// return this.texCoord.u >= 0.0f && this.texCoord.u <= 1.0f && this.texCoord.v >= 0.0f && this.texCoord.v <= 1.0f;
// }
public void setMaterial(Material material)
@ -1020,78 +991,78 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
return builder.toString();
}
}
public static class Normal
{
public float x, y, z;
public Normal()
{
this(0.0f, 0.0f, 0.0f);
}
public Normal(float[] data)
{
this(data[0], data[1], data[2]);
}
public Normal(Vector3f vector3f)
{
this(vector3f.x, vector3f.y, vector3f.z);
}
public Normal(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector3f getData()
{
return new Vector3f(this.x, this.y, this.z);
}
public float x, y, z;
public Normal()
{
this(0.0f, 0.0f, 0.0f);
}
public Normal(float[] data)
{
this(data[0], data[1], data[2]);
}
public Normal(Vector3f vector3f)
{
this(vector3f.x, vector3f.y, vector3f.z);
}
public Normal(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector3f getData()
{
return new Vector3f(this.x, this.y, this.z);
}
}
public static class TextureCoordinate
{
public float u, v, w;
public TextureCoordinate()
{
this(0.0f, 0.0f, 1.0f);
}
public TextureCoordinate(float[] data)
{
this(data[0], data[1], data[2]);
}
public TextureCoordinate(Vector3f data)
{
this(data.x, data.y, data.z);
}
public TextureCoordinate(float u, float v, float w)
{
this.u = u;
this.v = v;
this.w = w;
}
public Vector3f getData()
{
return new Vector3f(this.u, this.v, this.w);
}
public static TextureCoordinate[] getDefaultUVs()
{
TextureCoordinate[] texCoords = new TextureCoordinate[4];
texCoords[0] = new TextureCoordinate(0.0f, 0.0f, 1.0f);
texCoords[1] = new TextureCoordinate(1.0f, 0.0f, 1.0f);
texCoords[2] = new TextureCoordinate(1.0f, 1.0f, 1.0f);
texCoords[3] = new TextureCoordinate(0.0f, 1.0f, 1.0f);
return texCoords;
}
public float u, v, w;
public TextureCoordinate()
{
this(0.0f, 0.0f, 1.0f);
}
public TextureCoordinate(float[] data)
{
this(data[0], data[1], data[2]);
}
public TextureCoordinate(Vector3f data)
{
this(data.x, data.y, data.z);
}
public TextureCoordinate(float u, float v, float w)
{
this.u = u;
this.v = v;
this.w = w;
}
public Vector3f getData()
{
return new Vector3f(this.u, this.v, this.w);
}
public static TextureCoordinate[] getDefaultUVs()
{
TextureCoordinate[] texCoords = new TextureCoordinate[4];
texCoords[0] = new TextureCoordinate(0.0f, 0.0f, 1.0f);
texCoords[1] = new TextureCoordinate(1.0f, 0.0f, 1.0f);
texCoords[2] = new TextureCoordinate(1.0f, 1.0f, 1.0f);
texCoords[3] = new TextureCoordinate(0.0f, 1.0f, 1.0f);
return texCoords;
}
}
public static class Group implements IModelPart
@ -1118,7 +1089,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
LinkedHashSet<Face> faceSet = new LinkedHashSet<Face>();
for (Face f : this.faces)
{
// if (minUVBounds != null && maxUVBounds != null) f.normalizeUVs(minUVBounds, maxUVBounds);
// if (minUVBounds != null && maxUVBounds != null) f.normalizeUVs(minUVBounds, maxUVBounds);
faceSet.add(f.bake(transform));
}
return faceSet;
@ -1302,10 +1273,10 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
private Set<BakedQuad> quads;
private ImmutableMap<String, TextureAtlasSprite> textures;
private TextureAtlasSprite sprite = ModelLoader.White.instance;
public OBJBakedModel(OBJModel model, IModelState state, VertexFormat format, ImmutableMap<String, TextureAtlasSprite> textures)
{
this.model = model;
this.model = model;
this.state = state;
if (this.state instanceof OBJState) this.updateStateVisibilityMap((OBJState) this.state);
this.format = format;
@ -1333,16 +1304,16 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
TRSRTransformation transform = TRSRTransformation.identity();
for (Group g : this.model.getMatLib().getGroups().values())
{
// g.minUVBounds = this.model.getMatLib().minUVBounds;
// g.maxUVBounds = this.model.getMatLib().maxUVBounds;
// FMLLog.info("Group: %s u: [%f, %f] v: [%f, %f]", g.name, g.minUVBounds[0], g.maxUVBounds[0], g.minUVBounds[1], g.maxUVBounds[1]);
// g.minUVBounds = this.model.getMatLib().minUVBounds;
// g.maxUVBounds = this.model.getMatLib().maxUVBounds;
// FMLLog.info("Group: %s u: [%f, %f] v: [%f, %f]", g.name, g.minUVBounds[0], g.maxUVBounds[0], g.minUVBounds[1], g.maxUVBounds[1]);
if (this.state instanceof OBJState)
{
OBJState state = (OBJState) this.state;
if (state.parent != null && state.parent instanceof TRSRTransformation)
if (state.parent != null)
{
transform = (TRSRTransformation) state.parent;
transform = state.parent.apply(model);
}
//TODO: can this be replaced by updateStateVisibilityMap(OBJState)?
if (state.getGroupNamesFromMap().contains(Group.ALL))
@ -1377,14 +1348,9 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
faces.addAll(g.applyTransform(transform));
}
}
else if (this.state instanceof TRSRTransformation)
{
transform = (TRSRTransformation) this.state;
faces.addAll(g.applyTransform(transform));
}
else
{
transform = TRSRTransformation.identity();
transform = state.apply(model);
faces.addAll(g.applyTransform(transform));
}
}
@ -1404,10 +1370,11 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(format);
builder.setQuadOrientation(EnumFacing.getFacingFromVector(f.getNormal().x, f.getNormal().y, f.getNormal().z));
builder.setQuadColored();
putVertexData(builder, f.verts[0], f.getNormal(), TextureCoordinate.getDefaultUVs()[0], sprite);
putVertexData(builder, f.verts[1], f.getNormal(), TextureCoordinate.getDefaultUVs()[1], sprite);
putVertexData(builder, f.verts[2], f.getNormal(), TextureCoordinate.getDefaultUVs()[2], sprite);
putVertexData(builder, f.verts[3], f.getNormal(), TextureCoordinate.getDefaultUVs()[3], sprite);
Normal faceNormal = f.getNormal();
putVertexData(builder, f.verts[0], faceNormal, TextureCoordinate.getDefaultUVs()[0], sprite);
putVertexData(builder, f.verts[1], faceNormal, TextureCoordinate.getDefaultUVs()[1], sprite);
putVertexData(builder, f.verts[2], faceNormal, TextureCoordinate.getDefaultUVs()[2], sprite);
putVertexData(builder, f.verts[3], faceNormal, TextureCoordinate.getDefaultUVs()[3], sprite);
quads.add(builder.build());
}
}
@ -1426,37 +1393,37 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
break;
case COLOR:
float d;
if (v.hasNormal())
d = LightUtil.diffuseLight(v.getNormal().x, v.getNormal().y, v.getNormal().z);
else
d = LightUtil.diffuseLight(faceNormal.x, faceNormal.y, faceNormal.z);
if (v.getMaterial() != null)
builder.put(e,
d * v.getMaterial().getColor().x,
d * v.getMaterial().getColor().y,
d * v.getMaterial().getColor().z,
v.getMaterial().getColor().w);
else
builder.put(e, d, d, d, 1);
if (v.hasNormal())
d = LightUtil.diffuseLight(v.getNormal().x, v.getNormal().y, v.getNormal().z);
else
d = LightUtil.diffuseLight(faceNormal.x, faceNormal.y, faceNormal.z);
if (v.getMaterial() != null)
builder.put(e,
d * v.getMaterial().getColor().x,
d * v.getMaterial().getColor().y,
d * v.getMaterial().getColor().z,
v.getMaterial().getColor().w);
else
builder.put(e, d, d, d, 1);
break;
case UV:
if (!v.hasTextureCoordinate())
builder.put(e,
sprite.getInterpolatedU(defUV.u * 16),
sprite.getInterpolatedV(defUV.v * 16),
0, 1);
else
builder.put(e,
sprite.getInterpolatedU(v.getTextureCoordinate().u * 16),
sprite.getInterpolatedV(v.getTextureCoordinate().v * 16),
0, 1);
if (!v.hasTextureCoordinate())
builder.put(e,
sprite.getInterpolatedU(defUV.u * 16),
sprite.getInterpolatedV((model.customData.flipV ? 1 - defUV.v: defUV.v) * 16),
0, 1);
else
builder.put(e,
sprite.getInterpolatedU(v.getTextureCoordinate().u * 16),
sprite.getInterpolatedV((model.customData.flipV ? 1 - v.getTextureCoordinate().v : v.getTextureCoordinate().v) * 16),
0, 1);
break;
case NORMAL:
if (!v.hasNormal())
builder.put(e, faceNormal.x, faceNormal.y, faceNormal.z, 1);
else
builder.put(e, v.getNormal().x, v.getNormal().y, v.getNormal().z, 1);
if (!v.hasNormal())
builder.put(e, faceNormal.x, faceNormal.y, faceNormal.z, 0);
else
builder.put(e, v.getNormal().x, v.getNormal().y, v.getNormal().z, 0);
break;
default:
builder.put(e);
@ -1467,13 +1434,13 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
@Override
public boolean isAmbientOcclusion()
{
return model != null && model.hasCustomData() ? model.customData.ambientOcclusion : true;
return model != null ? model.customData.ambientOcclusion : true;
}
@Override
public boolean isGui3d()
{
return model != null && model.hasCustomData() ? model.customData.gui3d : true;
return model != null ? model.customData.gui3d : true;
}
@Override
@ -1527,7 +1494,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
}
return this;
}
private void updateStateVisibilityMap(OBJState state)
{
if (state.visibilityMap.containsKey(Group.ALL))
@ -1602,16 +1569,16 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
return this.model.modelLocation.toString();
}
}
@SuppressWarnings("serial")
public static class UVsOutOfBoundsException extends RuntimeException
{
public ResourceLocation modelLocation;
public UVsOutOfBoundsException(ResourceLocation modelLocation)
{
super(String.format("Model '%s' has UVs ('vt') out of bounds 0-1! The missing model will be used instead. Support for UV processing will be added to the OBJ loader in the future.", modelLocation));
this.modelLocation = modelLocation;
}
public ResourceLocation modelLocation;
public UVsOutOfBoundsException(ResourceLocation modelLocation)
{
super(String.format("Model '%s' has UVs ('vt') out of bounds 0-1! The missing model will be used instead. Support for UV processing will be added to the OBJ loader in the future.", modelLocation));
this.modelLocation = modelLocation;
}
}
}