Created
January 2, 2020 16:07
-
-
Save Zeitheron/5941be95e8fc0ccc1dddfe8938f5bd81 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.zeitheron.thaumicadditions.client.models.base; | |
import org.lwjgl.opengl.GL11; | |
import org.lwjgl.util.vector.Vector2f; | |
import org.lwjgl.util.vector.Vector3f; | |
import java.io.File; | |
import java.io.FileNotFoundException; | |
import java.io.InputStream; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.List; | |
import java.util.Scanner; | |
import static org.lwjgl.opengl.GL11.*; | |
public class OBJLoader | |
{ | |
public int createDisplayList(Obj model) | |
{ | |
int displayList = GL11.glGenLists(1); | |
GL11.glNewList(displayList, GL_COMPILE); | |
{ | |
this.render(model); | |
} | |
GL11.glEndList(); | |
return displayList; | |
} | |
/** | |
* Renders a given <code>Obj</code> file. | |
* | |
* @param model the <code>Obj</code> file to be rendered | |
*/ | |
public void render(Obj model) | |
{ | |
GL11.glMaterialf(GL_FRONT, GL_SHININESS, 120); | |
GL11.glBegin(GL_TRIANGLES); | |
{ | |
for(Obj.Face face : model.getFaces()) | |
{ | |
Vector3f[] normals = new Vector3f[]{ | |
model.getNormals().get(face.getNormals()[0] - 1), | |
model.getNormals().get(face.getNormals()[1] - 1), | |
model.getNormals().get(face.getNormals()[2] - 1) | |
}; | |
Vector2f[] texCoords = new Vector2f[]{ | |
model.getTextureCoordinates().get(face.getTextureCoords()[0] - 1), | |
model.getTextureCoordinates().get(face.getTextureCoords()[1] - 1), | |
model.getTextureCoordinates().get(face.getTextureCoords()[2] - 1) | |
}; | |
Vector3f[] vertices = new Vector3f[]{ | |
model.getVertices().get(face.getVertices()[0] - 1), | |
model.getVertices().get(face.getVertices()[1] - 1), | |
model.getVertices().get(face.getVertices()[2] - 1) | |
}; | |
{ | |
GL11.glNormal3f(normals[0].getX(), normals[0].getY(), normals[0].getZ()); | |
GL11.glTexCoord2f(texCoords[0].getX(), texCoords[0].getY()); | |
GL11.glVertex3f(vertices[0].getX(), vertices[0].getY(), vertices[0].getZ()); | |
GL11.glNormal3f(normals[1].getX(), normals[1].getY(), normals[1].getZ()); | |
GL11.glTexCoord2f(texCoords[1].getX(), texCoords[1].getY()); | |
GL11.glVertex3f(vertices[1].getX(), vertices[1].getY(), vertices[1].getZ()); | |
GL11.glNormal3f(normals[2].getX(), normals[2].getY(), normals[2].getZ()); | |
GL11.glTexCoord2f(texCoords[2].getX(), texCoords[2].getY()); | |
GL11.glVertex3f(vertices[2].getX(), vertices[2].getY(), vertices[2].getZ()); | |
} | |
} | |
} | |
GL11.glEnd(); | |
} | |
/** | |
* @param file the file to be loaded | |
* @return the loaded <code>Obj</code> | |
* @throws java.io.FileNotFoundException thrown if the Obj file is not found | |
*/ | |
public Obj loadModel(File file) throws FileNotFoundException | |
{ | |
return this.loadModel(new Scanner(file)); | |
} | |
/** | |
* @param stream the stream to be loaded | |
* @return the loaded <code>Obj</code> | |
*/ | |
public Obj loadModel(InputStream stream) | |
{ | |
return this.loadModel(new Scanner(stream)); | |
} | |
/** | |
* @param sc the <code>Obj</code> to be loaded | |
* @return the loaded <code>Obj</code> | |
*/ | |
public Obj loadModel(Scanner sc) | |
{ | |
Obj model = new Obj(); | |
while(sc.hasNextLine()) | |
{ | |
String ln = sc.nextLine(); | |
if(ln == null || ln.equals("") || ln.startsWith("#")) | |
{ | |
} else | |
{ | |
String[] split = ln.split(" "); | |
switch(split[0]) | |
{ | |
case "v": | |
model.getVertices().add(new Vector3f( | |
Float.parseFloat(split[1]), | |
Float.parseFloat(split[2]), | |
Float.parseFloat(split[3]) | |
)); | |
break; | |
case "vn": | |
model.getNormals().add(new Vector3f( | |
Float.parseFloat(split[1]), | |
Float.parseFloat(split[2]), | |
Float.parseFloat(split[3]) | |
)); | |
break; | |
case "vt": | |
model.getTextureCoordinates().add(new Vector2f( | |
Float.parseFloat(split[1]), | |
Float.parseFloat(split[2]) | |
)); | |
break; | |
case "f": | |
model.getFaces().add(new Obj.Face( | |
new int[]{ | |
Integer.parseInt(split[1].split("/")[0]), | |
Integer.parseInt(split[2].split("/")[0]), | |
Integer.parseInt(split[3].split("/")[0]) | |
}, | |
new int[]{ | |
Integer.parseInt(split[1].split("/")[1]), | |
Integer.parseInt(split[2].split("/")[1]), | |
Integer.parseInt(split[3].split("/")[1]) | |
}, | |
new int[]{ | |
Integer.parseInt(split[1].split("/")[2]), | |
Integer.parseInt(split[2].split("/")[2]), | |
Integer.parseInt(split[3].split("/")[2]) | |
} | |
)); | |
break; | |
case "s": | |
model.setSmoothShadingEnabled(!ln.contains("off")); | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
sc.close(); | |
return model; | |
} | |
public static class Obj | |
extends Object | |
{ | |
private final List<Vector3f> vertices; | |
private final List<Vector2f> textureCoords; | |
private final List<Vector3f> normals; | |
private final List<Face> faces; | |
private boolean enableSmoothShading; | |
public Obj(List<Vector3f> vertices, List<Vector2f> textureCoords, | |
List<Vector3f> normals, List<Face> faces, boolean enableSmoothShading) | |
{ | |
super(); | |
this.vertices = vertices; | |
this.textureCoords = textureCoords; | |
this.normals = normals; | |
this.faces = faces; | |
this.enableSmoothShading = enableSmoothShading; | |
} | |
public Obj() | |
{ | |
this(new ArrayList<Vector3f>(), new ArrayList<Vector2f>(), | |
new ArrayList<Vector3f>(), new ArrayList<Face>(), true); | |
} | |
public void enableStates() | |
{ | |
if(this.isSmoothShadingEnabled()) | |
{ | |
GL11.glShadeModel(GL_SMOOTH); | |
} else | |
{ | |
GL11.glShadeModel(GL_FLAT); | |
} | |
} | |
public boolean hasTextureCoordinates() | |
{ | |
return this.getTextureCoordinates().size() > 0; | |
} | |
public boolean hasNormals() | |
{ | |
return this.getNormals().size() > 0; | |
} | |
public List<Vector3f> getVertices() | |
{ | |
return this.vertices; | |
} | |
public List<Vector2f> getTextureCoordinates() | |
{ | |
return this.textureCoords; | |
} | |
public List<Vector3f> getNormals() | |
{ | |
return this.normals; | |
} | |
public List<Face> getFaces() | |
{ | |
return this.faces; | |
} | |
public boolean isSmoothShadingEnabled() | |
{ | |
return this.enableSmoothShading; | |
} | |
public void setSmoothShadingEnabled(boolean isSmoothShadingEnabled) | |
{ | |
this.enableSmoothShading = isSmoothShadingEnabled; | |
} | |
public static class Face | |
extends Object | |
{ | |
private final int[] vertexIndices; | |
private final int[] normalIndices; | |
private final int[] textureCoordinateIndices; | |
public boolean hasNormals() | |
{ | |
return this.normalIndices != null; | |
} | |
public boolean hasTextureCoords() | |
{ | |
return this.textureCoordinateIndices != null; | |
} | |
public int[] getVertices() | |
{ | |
return this.vertexIndices; | |
} | |
public int[] getTextureCoords() | |
{ | |
return this.textureCoordinateIndices; | |
} | |
public int[] getNormals() | |
{ | |
return this.normalIndices; | |
} | |
public Face(int[] vertexIndices, int[] textureCoordinateIndices, | |
int[] normalIndices) | |
{ | |
super(); | |
this.vertexIndices = vertexIndices; | |
this.normalIndices = normalIndices; | |
this.textureCoordinateIndices = textureCoordinateIndices; | |
} | |
@Override | |
public String toString() | |
{ | |
return String.format("Face[vertexIndices%s normalIndices%s textureCoordinateIndices%s]", | |
Arrays.toString(vertexIndices), Arrays.toString(normalIndices), Arrays.toString(textureCoordinateIndices)); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment