Hbm-s-Nuclear-Tech-GIT/com/hbm/render/loader/S_WavefrontObject.java
2020-03-08 13:34:52 +01:00

634 lines
20 KiB
Java

package com.hbm.render.loader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.resources.IResource;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ModelFormatException;
import net.minecraftforge.client.model.obj.TextureCoordinate;
import net.minecraftforge.client.model.obj.Vertex;
@SideOnly(Side.CLIENT)
public class S_WavefrontObject extends S_ModelCustom
{
private static Pattern vertexPattern = Pattern.compile("(v( (\\-){0,1}\\d+\\.\\d+){3,4} *\\n)|(v( (\\-){0,1}\\d+\\.\\d+){3,4} *$)");
private static Pattern vertexNormalPattern = Pattern.compile("(vn( (\\-){0,1}\\d+\\.\\d+){3,4} *\\n)|(vn( (\\-){0,1}\\d+\\.\\d+){3,4} *$)");
private static Pattern textureCoordinatePattern = Pattern.compile("(vt( (\\-){0,1}\\d+\\.\\d+){2,3} *\\n)|(vt( (\\-){0,1}\\d+\\.\\d+){2,3} *$)");
private static Pattern face_V_VT_VN_Pattern = Pattern.compile("(f( \\d+/\\d+/\\d+){3,4} *\\n)|(f( \\d+/\\d+/\\d+){3,4} *$)");
private static Pattern face_V_VT_Pattern = Pattern.compile("(f( \\d+/\\d+){3,4} *\\n)|(f( \\d+/\\d+){3,4} *$)");
private static Pattern face_V_VN_Pattern = Pattern.compile("(f( \\d+//\\d+){3,4} *\\n)|(f( \\d+//\\d+){3,4} *$)");
private static Pattern face_V_Pattern = Pattern.compile("(f( \\d+){3,4} *\\n)|(f( \\d+){3,4} *$)");
private static Pattern groupObjectPattern = Pattern.compile("([go]( [-\\$\\w\\d]+) *\\n)|([go]( [-\\$\\w\\d]+) *$)");
private static Matcher vertexMatcher;
private static Matcher vertexNormalMatcher;
private static Matcher textureCoordinateMatcher;
private static Matcher face_V_VT_VN_Matcher;
private static Matcher face_V_VT_Matcher;
private static Matcher face_V_VN_Matcher;
private static Matcher face_V_Matcher;
private static Matcher groupObjectMatcher;
public ArrayList<Vertex> vertices = new ArrayList();
public ArrayList<Vertex> vertexNormals = new ArrayList();
public ArrayList<TextureCoordinate> textureCoordinates = new ArrayList();
public ArrayList<S_GroupObject> groupObjects = new ArrayList();
private S_GroupObject currentS_GroupObject;
private String fileName;
public S_WavefrontObject(ResourceLocation resource)
throws ModelFormatException
{
this.fileName = resource.toString();
try
{
IResource res = Minecraft.getMinecraft().getResourceManager().getResource(resource);
loadObjModel(res.getInputStream());
}
catch (IOException e)
{
throw new ModelFormatException("IO Exception reading model format", e);
}
}
public S_WavefrontObject(String fileName, URL resource)
throws ModelFormatException
{
this.fileName = fileName;
try
{
loadObjModel(resource.openStream());
}
catch (IOException e)
{
throw new ModelFormatException("IO Exception reading model format", e);
}
}
public S_WavefrontObject(String filename, InputStream inputStream)
throws ModelFormatException
{
this.fileName = filename;
loadObjModel(inputStream);
}
public boolean containsPart(String partName)
{
for (S_GroupObject groupObject : this.groupObjects) {
if (partName.equalsIgnoreCase(groupObject.name)) {
return true;
}
}
return false;
}
private void loadObjModel(InputStream inputStream)
throws ModelFormatException
{
BufferedReader reader = null;
String currentLine = null;
int lineCount = 0;
try
{
reader = new BufferedReader(new InputStreamReader(inputStream));
while ((currentLine = reader.readLine()) != null)
{
lineCount++;
currentLine = currentLine.replaceAll("\\s+", " ").trim();
if ((!currentLine.startsWith("#")) && (currentLine.length() != 0)) {
if (currentLine.startsWith("v "))
{
Vertex vertex = parseVertex(currentLine, lineCount);
if (vertex != null)
{
checkMinMax(vertex);
this.vertices.add(vertex);
}
}
else if (currentLine.startsWith("vn "))
{
Vertex vertex = parseVertexNormal(currentLine, lineCount);
if (vertex != null) {
this.vertexNormals.add(vertex);
}
}
else if (currentLine.startsWith("vt "))
{
TextureCoordinate textureCoordinate = parseTextureCoordinate(currentLine, lineCount);
if (textureCoordinate != null) {
this.textureCoordinates.add(textureCoordinate);
}
}
else if (currentLine.startsWith("f "))
{
if (this.currentS_GroupObject == null) {
this.currentS_GroupObject = new S_GroupObject("Default");
}
S_Face face = parseFace(currentLine, lineCount);
if (face != null) {
this.currentS_GroupObject.faces.add(face);
}
}
else if (((currentLine.startsWith("g ") | currentLine.startsWith("o "))) &&
(currentLine.charAt(2) == '$'))
{
S_GroupObject group = parseS_GroupObject(currentLine, lineCount);
if (group != null) {
if (this.currentS_GroupObject != null) {
this.groupObjects.add(this.currentS_GroupObject);
}
}
this.currentS_GroupObject = group;
}
}
}
this.groupObjects.add(this.currentS_GroupObject); return;
}
catch (IOException e)
{
throw new ModelFormatException("IO Exception reading model format", e);
}
finally
{
checkMinMaxFinal();
try
{
reader.close();
}
catch (IOException e) {}
try
{
inputStream.close();
}
catch (IOException e) {}
}
}
public void renderAll()
{
Tessellator tessellator = Tessellator.instance;
if (this.currentS_GroupObject != null) {
tessellator.startDrawing(this.currentS_GroupObject.glDrawingMode);
} else {
tessellator.startDrawing(4);
}
tessellateAll(tessellator);
tessellator.draw();
}
public void tessellateAll(Tessellator tessellator)
{
for (S_GroupObject groupObject : this.groupObjects) {
groupObject.render(tessellator);
}
}
public void renderOnly(String... groupNames)
{
for (S_GroupObject groupObject : this.groupObjects) {
for (String groupName : groupNames) {
if (groupName.equalsIgnoreCase(groupObject.name)) {
groupObject.render();
}
}
}
}
public void tessellateOnly(Tessellator tessellator, String... groupNames)
{
for (S_GroupObject groupObject : this.groupObjects) {
for (String groupName : groupNames) {
if (groupName.equalsIgnoreCase(groupObject.name)) {
groupObject.render(tessellator);
}
}
}
}
public void renderPart(String partName)
{
for (S_GroupObject groupObject : this.groupObjects) {
if (partName.equalsIgnoreCase(groupObject.name)) {
groupObject.render();
}
}
}
public void tessellatePart(Tessellator tessellator, String partName)
{
for (S_GroupObject groupObject : this.groupObjects) {
if (partName.equalsIgnoreCase(groupObject.name)) {
groupObject.render(tessellator);
}
}
}
public void renderAllExcept(String... excludedGroupNames)
{
for (S_GroupObject groupObject : this.groupObjects)
{
boolean skipPart = false;
for (String excludedGroupName : excludedGroupNames) {
if (excludedGroupName.equalsIgnoreCase(groupObject.name)) {
skipPart = true;
}
}
if (!skipPart) {
groupObject.render();
}
}
}
public void tessellateAllExcept(Tessellator tessellator, String... excludedGroupNames)
{
for (S_GroupObject groupObject : this.groupObjects)
{
boolean exclude = false;
for (String excludedGroupName : excludedGroupNames) {
if (excludedGroupName.equalsIgnoreCase(groupObject.name)) {
exclude = true;
}
}
if (!exclude) {
groupObject.render(tessellator);
}
}
}
private Vertex parseVertex(String line, int lineCount)
throws ModelFormatException
{
Vertex vertex = null;
if (isValidVertexLine(line))
{
line = line.substring(line.indexOf(" ") + 1);
String[] tokens = line.split(" ");
try
{
if (tokens.length == 2) {
return new Vertex(Float.parseFloat(tokens[0]), Float.parseFloat(tokens[1]));
}
if (tokens.length == 3) {
return new Vertex(Float.parseFloat(tokens[0]), Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]));
}
}
catch (NumberFormatException e)
{
throw new ModelFormatException(String.format("Number formatting error at line %d", new Object[] { Integer.valueOf(lineCount) }), e);
}
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + this.fileName + "' - Incorrect format");
}
return vertex;
}
private Vertex parseVertexNormal(String line, int lineCount)
throws ModelFormatException
{
Vertex vertexNormal = null;
if (isValidVertexNormalLine(line))
{
line = line.substring(line.indexOf(" ") + 1);
String[] tokens = line.split(" ");
try
{
if (tokens.length == 3) {
return new Vertex(Float.parseFloat(tokens[0]), Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]));
}
}
catch (NumberFormatException e)
{
throw new ModelFormatException(String.format("Number formatting error at line %d", new Object[] { Integer.valueOf(lineCount) }), e);
}
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + this.fileName + "' - Incorrect format");
}
return vertexNormal;
}
private TextureCoordinate parseTextureCoordinate(String line, int lineCount)
throws ModelFormatException
{
TextureCoordinate textureCoordinate = null;
if (isValidTextureCoordinateLine(line))
{
line = line.substring(line.indexOf(" ") + 1);
String[] tokens = line.split(" ");
try
{
if (tokens.length == 2) {
return new TextureCoordinate(Float.parseFloat(tokens[0]), 1.0F - Float.parseFloat(tokens[1]));
}
if (tokens.length == 3) {
return new TextureCoordinate(Float.parseFloat(tokens[0]), 1.0F - Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]));
}
}
catch (NumberFormatException e)
{
throw new ModelFormatException(String.format("Number formatting error at line %d", new Object[] { Integer.valueOf(lineCount) }), e);
}
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + this.fileName + "' - Incorrect format");
}
return textureCoordinate;
}
private S_Face parseFace(String line, int lineCount)
throws ModelFormatException
{
S_Face face = null;
if (isValidFaceLine(line))
{
face = new S_Face();
String trimmedLine = line.substring(line.indexOf(" ") + 1);
String[] tokens = trimmedLine.split(" ");
String[] subTokens = null;
if (tokens.length == 3)
{
if (this.currentS_GroupObject.glDrawingMode == -1) {
this.currentS_GroupObject.glDrawingMode = 4;
} else if (this.currentS_GroupObject.glDrawingMode != 4) {
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + this.fileName + "' - Invalid number of points for face (expected 4, found " + tokens.length + ")");
}
}
else if (tokens.length == 4) {
if (this.currentS_GroupObject.glDrawingMode == -1) {
this.currentS_GroupObject.glDrawingMode = 7;
} else if (this.currentS_GroupObject.glDrawingMode != 7) {
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + this.fileName + "' - Invalid number of points for face (expected 3, found " + tokens.length + ")");
}
}
if (isValidFace_V_VT_VN_Line(line))
{
face.vertices = new Vertex[tokens.length];
face.textureCoordinates = new TextureCoordinate[tokens.length];
face.vertexNormals = new Vertex[tokens.length];
for (int i = 0; i < tokens.length; i++)
{
subTokens = tokens[i].split("/");
face.vertices[i] = ((Vertex)this.vertices.get(Integer.parseInt(subTokens[0]) - 1));
face.textureCoordinates[i] = ((TextureCoordinate)this.textureCoordinates.get(Integer.parseInt(subTokens[1]) - 1));
face.vertexNormals[i] = ((Vertex)this.vertexNormals.get(Integer.parseInt(subTokens[2]) - 1));
}
face.faceNormal = face.calculateFaceNormal();
}
else if (isValidFace_V_VT_Line(line))
{
face.vertices = new Vertex[tokens.length];
face.textureCoordinates = new TextureCoordinate[tokens.length];
for (int i = 0; i < tokens.length; i++)
{
subTokens = tokens[i].split("/");
face.vertices[i] = ((Vertex)this.vertices.get(Integer.parseInt(subTokens[0]) - 1));
face.textureCoordinates[i] = ((TextureCoordinate)this.textureCoordinates.get(Integer.parseInt(subTokens[1]) - 1));
}
face.faceNormal = face.calculateFaceNormal();
}
else if (isValidFace_V_VN_Line(line))
{
face.vertices = new Vertex[tokens.length];
face.vertexNormals = new Vertex[tokens.length];
for (int i = 0; i < tokens.length; i++)
{
subTokens = tokens[i].split("//");
face.vertices[i] = ((Vertex)this.vertices.get(Integer.parseInt(subTokens[0]) - 1));
face.vertexNormals[i] = ((Vertex)this.vertexNormals.get(Integer.parseInt(subTokens[1]) - 1));
}
face.faceNormal = face.calculateFaceNormal();
}
else if (isValidFace_V_Line(line))
{
face.vertices = new Vertex[tokens.length];
for (int i = 0; i < tokens.length; i++) {
face.vertices[i] = ((Vertex)this.vertices.get(Integer.parseInt(tokens[i]) - 1));
}
face.faceNormal = face.calculateFaceNormal();
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + this.fileName + "' - Incorrect format");
}
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + this.fileName + "' - Incorrect format");
}
return face;
}
private S_GroupObject parseS_GroupObject(String line, int lineCount)
throws ModelFormatException
{
S_GroupObject group = null;
if (isValidS_GroupObjectLine(line))
{
String trimmedLine = line.substring(line.indexOf(" ") + 1);
if (trimmedLine.length() > 0) {
group = new S_GroupObject(trimmedLine);
}
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + this.fileName + "' - Incorrect format");
}
return group;
}
private static boolean isValidVertexLine(String line)
{
if (vertexMatcher != null) {
vertexMatcher.reset();
}
vertexMatcher = vertexPattern.matcher(line);
return vertexMatcher.matches();
}
private static boolean isValidVertexNormalLine(String line)
{
if (vertexNormalMatcher != null) {
vertexNormalMatcher.reset();
}
vertexNormalMatcher = vertexNormalPattern.matcher(line);
return vertexNormalMatcher.matches();
}
private static boolean isValidTextureCoordinateLine(String line)
{
if (textureCoordinateMatcher != null) {
textureCoordinateMatcher.reset();
}
textureCoordinateMatcher = textureCoordinatePattern.matcher(line);
return textureCoordinateMatcher.matches();
}
private static boolean isValidFace_V_VT_VN_Line(String line)
{
if (face_V_VT_VN_Matcher != null) {
face_V_VT_VN_Matcher.reset();
}
face_V_VT_VN_Matcher = face_V_VT_VN_Pattern.matcher(line);
return face_V_VT_VN_Matcher.matches();
}
private static boolean isValidFace_V_VT_Line(String line)
{
if (face_V_VT_Matcher != null) {
face_V_VT_Matcher.reset();
}
face_V_VT_Matcher = face_V_VT_Pattern.matcher(line);
return face_V_VT_Matcher.matches();
}
private static boolean isValidFace_V_VN_Line(String line)
{
if (face_V_VN_Matcher != null) {
face_V_VN_Matcher.reset();
}
face_V_VN_Matcher = face_V_VN_Pattern.matcher(line);
return face_V_VN_Matcher.matches();
}
private static boolean isValidFace_V_Line(String line)
{
if (face_V_Matcher != null) {
face_V_Matcher.reset();
}
face_V_Matcher = face_V_Pattern.matcher(line);
return face_V_Matcher.matches();
}
private static boolean isValidFaceLine(String line)
{
return (isValidFace_V_VT_VN_Line(line)) || (isValidFace_V_VT_Line(line)) || (isValidFace_V_VN_Line(line)) || (isValidFace_V_Line(line));
}
private static boolean isValidS_GroupObjectLine(String line)
{
if (groupObjectMatcher != null) {
groupObjectMatcher.reset();
}
groupObjectMatcher = groupObjectPattern.matcher(line);
return groupObjectMatcher.matches();
}
public String getType()
{
return "obj";
}
public void renderAllLine(int startLine, int maxLine)
{
Tessellator tessellator = Tessellator.instance;
tessellator.startDrawing(1);
renderAllLine(tessellator, startLine, maxLine);
tessellator.draw();
}
public void renderAllLine(Tessellator tessellator, int startLine, int maxLine)
{
int lineCnt = 0;
for (S_GroupObject groupObject : this.groupObjects) {
if (groupObject.faces.size() > 0) {
for (S_Face face : groupObject.faces) {
for (int i = 0; i < face.vertices.length / 3; i++)
{
Vertex v1 = face.vertices[(i * 3 + 0)];
Vertex v2 = face.vertices[(i * 3 + 1)];
Vertex v3 = face.vertices[(i * 3 + 2)];
lineCnt++;
if (lineCnt > maxLine) {
return;
}
tessellator.addVertex(v1.x, v1.y, v1.z);
tessellator.addVertex(v2.x, v2.y, v2.z);
lineCnt++;
if (lineCnt > maxLine) {
return;
}
tessellator.addVertex(v2.x, v2.y, v2.z);
tessellator.addVertex(v3.x, v3.y, v3.z);
lineCnt++;
if (lineCnt > maxLine) {
return;
}
tessellator.addVertex(v3.x, v3.y, v3.z);
tessellator.addVertex(v1.x, v1.y, v1.z);
}
}
}
}
}
public int getVertexNum()
{
return this.vertices.size();
}
public int getFaceNum()
{
return getVertexNum() / 3;
}
public void renderAll(int startFace, int maxFace)
{
if (startFace < 0) {
startFace = 0;
}
Tessellator tessellator = Tessellator.instance;
tessellator.startDrawing(4);
renderAll(tessellator, startFace, maxFace);
tessellator.draw();
}
public void renderAll(Tessellator tessellator, int startFace, int maxLine)
{
int faceCnt = 0;
for (S_GroupObject groupObject : this.groupObjects) {
if (groupObject.faces.size() > 0) {
for (S_Face face : groupObject.faces)
{
faceCnt++;
if (faceCnt >= startFace)
{
if (faceCnt > maxLine) {
return;
}
face.addFaceForRender(tessellator);
}
}
}
}
}
}