I make my models in a 3d progaram and export as .obj format. Then I use a OBJLoader to take that mesh and render it in the game. I have one that's not really working the best, however I'm editing it. I may post the code what it's done. Most OBJ format loaders use the GL11.glGenList(1) and GL11.glNewList() to store all the data. That was giving me errors with the GenList part, so I made one that just stores it in arrays, which is just as fast as rendering the mesh normally because the only other speed decrease is a "for(face f:faces)"
Here is a rudementary version of how to load an object file and render it:
package org.ic3d.render;
import java.io.*;
import org.lwjgl.opengl.GL11;
public class ObjReader {
public ObjReader(String file){
try{
BufferedReader reader = new BufferedReader(new FileReader(new File(file)));
parseFile(reader);
}catch(IOException e){
System.out.println(file+" Failed To Load! Can't continue.");
System.exit(0);
}
}
/**
* Parse all lines in the BufferedReader to convert the .obj file
*
* @param br - A bufferedReader object pointing to the desired .obj file
* @throws IllegalStateException If the obj file is malformed and vertice are added to a face of different shape (tri - quad)
* @throws IOException - If the obj file can not be read for any reason.
*/
public void parseFile(BufferedReader br) throws IllegalStateException, IOException
{
String s="";
Vertex[] v1 = new Vertex[15000];
Vertex[] n1 = new Vertex[15000];
while((s = br.readLine())!=null)
{
if(s.startsWith("v"))
{
String[] pv = s.split(" ");
Vertex vert_0x = new Vertex(Float.parseFloat(pv[1]), Float.parseFloat(pv[2]), Float.parseFloat(pv[3]));
appendVert(v1, vert_0x);
}
if(s.startsWith("vn"))
{
String[] pv = s.split(" ");
Vertex vert_0x = new Vertex(Float.parseFloat(pv[1]), Float.parseFloat(pv[2]), Float.parseFloat(pv[3]));
appendVert(n1, vert_0x);
}
if(s.startsWith("f"))
{
String[] pv = s.split(" ");
Vertex[] temp = new Vertex[pv.length-1];
for(int i=1;i<pv.length;i++)
{
String[] vn = pv[i].split("//");
Vertex v = v1[Integer.parseInt(vn[0])];
Vertex n = n1[Integer.parseInt(vn[1])];
v.setNormals(n.getX(), n.getY(), n.getZ());
appendVert(temp, v);
}
try
{
Face f = new Face(temp.length==3?Face.GL_FACE_TRI:Face.GL_FACE_QUAD, temp);
if(temp.length==3){
appendFace(t_faces, f);
}else{
appendFace(q_faces, f);
}
}
catch(IllegalStateException e)
{
throw e;
}
}
}
}
private void appendVert(Vertex[] l, Vertex v)
{
for(int i=0;i<l.length;i++)
{
if(l[i]==null)
{
l[i] = v;
}
}
System.out.println("Vertex[] can only hold "+l.length+" Vertices at one time");
}
private void appendFace(Face[] l, Face f)
{
for(int i=0;i<l.length;i++)
{
if(l[i]==null)
{
l[i] = f;
}
}
System.out.println("Vertex[] can only hold "+l.length+" Vertices at one time");
}
public void renderTri(Face f, float x, float y, float z)
{
Vertex[] v = f.getVerts();
Vertex cv = v[0];
GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ());
GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ());
cv = v[1];
GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ());
GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ());
cv = v[2];
GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ());
GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ());
}
public void renderQuad(Face f, float x, float y, float z)
{
Vertex[] v = f.getVerts();
Vertex cv = v[0];
GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ());
GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ());
cv = v[2];
GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ());
GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ());
cv = v[2];
GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ());
GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ());
cv = v[3];
GL11.glNormal3f(cv.getNormalX(), cv.getNormalY(), cv.getNormalZ());
GL11.glVertex3f(x+cv.getX(), y+cv.getY(), z+cv.getZ());
}
public void render(float x, float y, float z)
{
//Push matrix out of the way so we can edit the scene and then load
//The current matrix settings
GL11.glPushMatrix();
GL11.glBegin(GL11.GL_QUADS)l
for(Face f : q_faces)
{
if(f==null)
{
break;
}
else
{
renderQuad(f, x, y, z);
}
}
GL11.glBegin(GL11.GL_TRIANGLES)l
for(Face f : T_faces)
{
if(f==null)
{
break;
}
else
{
renderTri(f, x, y, z);
}
}
GL11.glEnd();
GL11.glPopMatrix();
}
public int listid=0;
public Face[] q_faces = new Face[15000];
public Face[] t_faces = new Face[15000];
public class Face{
/**
*
*
* @param shape
* @param verts
* @throws IllegalStateException - If the number of vertice in the Vertex[] is not equal to the face type set.
*/
public Face(int shape, Vertex[] vertlist) throws IllegalStateException{
int vert_n = GL_FACE_NONE-shape;
if(vertlist.length>vert_n){
throw new IllegalStateException(vert_n+" Vertice faces can not hold "+verts.length+" vertices");
}
if(vertlist.length<vert_n){
throw new IllegalStateException(vert_n+" Vertice faces must hold "+vert_n+" vertice, not "+verts.length+" vertices");
}
if(vert_n!=3 && vert_n!=4){
throw new IllegalStateException("Faces can only be 3 or 4 vertice. Shapes besides QUAD and TRI are not allowed.");
}
type=vert_n;
verts=vertlist;
}
public Vertex[] getVerts(){
return verts;
}
public int getType(){
return type;
}
public String getType(int i){
if(i==1){
return(type==3?"TRI":"QUAD");
}else{
return(type==3?"TRIANGLE":"QUAD");
}
}
private Vertex[] verts;
public static int GL_FACE_QUAD = 3;
public static int GL_FACE_TRI = 4;
public static int GL_FACE_NONE = 7;
private int type=7;
}
public class Vertex{
public Vertex(float x, float y, float z){
_x=x;
_y=y;
_z=z;
}
public void setNormals(float x, float y, float z){
_nx=x;
_ny=y;
_nz=z;
}
public float getX(){
return _x;
}
public float getY(){
return _y;
}
public float getZ(){
return _z;
}
public float getNormalX(){
return _nx;
}
public float getNormalY(){
return _ny;
}
public float getNormalZ(){
return _nz;
}
public float[] getNormalXYZ(){
return new float[]{_nx, _ny, _nz};
}
public void setXYZ(float x, float y, float z){
_x=x;
_y=y;
_z=z;
}
public float[] getXYZ(){
return new float[]{_x, _y, _z};
}
private float _x;
private float _y;
private float _z;
private float _nx;
private float _ny;
private float _nz;
}
}
Hope this helps some, just put that in and then either use external files, or modify the constructor to use internal files. Only load the object once somewhere around the GL initializing, then just call objectname.render().