Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/main/java/no/myke/parser/ModelObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
*
*/
public class ModelObject {
private String name;
public float[] vertices;
private final String name;
public Vector[] vectors;
public short[] polygons;
public java.util.HashMap<Short,String> materialType = new java.util.HashMap(); //Key is the face number as a short, value is the face material as a string
public float[] textureCoordinates;

public ModelObject(String name) {
Expand Down
71 changes: 60 additions & 11 deletions src/main/java/no/myke/parser/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* This parser understands the layout of the 3ds file and is
* able to construct a Model from a reader.
*
* @author Kjetil �ster�s
* @author Kjetil Østerås
*/
public class Parser {

Expand Down Expand Up @@ -41,29 +41,33 @@ private int readChunk() throws IOException {

private void parseChunk(short type, int size) throws IOException {
switch (type) {
case 0x0002:
case 0x0002: //M3D Version
parseVersionChunk();
break;
case 0x3d3d:
case 0x3d3d: //Start of object mesh data.
break;
case 0x4000:
case 0x4000: //first item of Subchunk 4000 is an ASCIIZ string of the objects name. Remember an object can be a mesh, a light or a camera.
parseObjectChunk();
break;
case 0x4100:
case 0x4100: //Header for Triangular Polygon Object (Just an identifier, no actual information)
parseTriangularMesh();
break;
case 0x4110:
case 0x4110: //Count of verticus, followed by X,Y,Z co-ords
parseVerticesList();
break;
case 0x4120:
case 0x4120: //Faces Description / Point List
parseFacesDescription();
break;
case 0x4140:
case 0x4130: //Face Material
parseFaceMaterial();
break;
case 0x4140: //Mapping Coordinates List
parseMappingCoordinates();
break;
case 0x4160:
case 0x4160: //Local Coordinates System / Translation Matrix
parseLocalCoordinateSystem();
break;
case 0x4d4d:
case 0x4d4d: //A 3ds file has the Primary chunk ID 0x4D4D. This is always the first chunk of the file. With in the primary chunk are the main chunks.
parseMainChunk();
break;
case (short)0xafff: // Material block
Expand Down Expand Up @@ -105,20 +109,55 @@ private void parseObjectChunk() throws IOException {
currentObject = model.newModelObject(name);
}

private void parseTriangularMesh() throws IOException {
log("Found Mesh Header");
}

private void parseVerticesList() throws IOException {
//byte range: 0-1
//Size: 2
//Type: short int
//Description: Total vertices in object
short numVertices = reader.getShort();
//vertices always come in multiples of 3 (X,Y,Z) co-ordinates
float[] vertices = new float[numVertices * 3];

//byte range: 2-5, 6-9, 10-13
//Size: 4 (each)
//Type: float (each)
//Description: X, Y and Z values as a float
//These 12 bytes are repeated for however many vertices are in the object, with the next 3 (X,Y,Z) being in the byte range 14-25.
for (int i=0; i<vertices.length; i++) {
vertices[i] = reader.getFloat();
}

currentObject.vertices = vertices;
//Create vectors from groups of 3 vertices (X, Y, Z).
//Use the values from 0x4120 (Faces Description / Point List) to find faces.
Vector[] vectors = new Vector[numVertices];
for (int i = 0; i < numVertices; i++)
{
//Create vector with 3 points
vectors[i] = new Vector(vertices[i*3], vertices[i*3 + 1], vertices[i*3 + 2]);
}
currentObject.vectors = vectors;
log("Found %d vertices", numVertices);
}

private void parseFacesDescription() throws IOException {
//byte range: 0-1
//Size: 2
//Type: short int
//Description: Total polygons in object - numFaces
short numFaces = reader.getShort();
short[] faces = new short[numFaces * 3];

//byte range: 2-3, 4-5, 6-7
//Size: 2 (each)
//Type: short int (each)
//Description: point1, point2 and point3 values as a short.
//These points refer to the corresponding vertex of the triangular polygon from the vertex list.
//Points are organized in a clock-wise order.
//Repeats 'numFaces' times for each polygon.
for (int i=0; i<numFaces; i++) {
faces[i*3] = reader.getShort();
faces[i*3 + 1] = reader.getShort();
Expand All @@ -129,6 +168,16 @@ private void parseFacesDescription() throws IOException {
currentObject.polygons = faces;
}

private void parseFaceMaterial() throws IOException {
String name = reader.readString();
short n_faces = reader.getShort();
log("%d faces with material %s", n_faces, name);
for(short i = 0 ; i < n_faces ; i++)
{
currentObject.materialType.put(reader.getShort(), name);
}
}

private void parseLocalCoordinateSystem() throws IOException {
float[] x1 = new float[3];
float[] x2 = new float[3];
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/no/myke/parser/Vector.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package no.myke.parser;

public class Vector
{
float x, y, z;

Vector (float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
public float X()
{
return x;
}

public float Y()
{
return y;
}

public float Z()
{
return z;
}
}
14 changes: 7 additions & 7 deletions src/test/java/no/myke/parser/ComplexModelTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public void testComplexModel() throws Exception {

private void debugModel(Model model) {
for (ModelObject object : model.objects) {
if (object.vertices != null)
maxMin(object.vertices);
if (object.vectors != null)
maxMin(object.vectors);
}

System.out.println();
Expand All @@ -47,18 +47,18 @@ private void debugModel(Model model) {
float g_z_min = Float.MAX_VALUE;


private void maxMin(float[] v) {
private void maxMin(Vector[] v) {
float x_max = Float.MIN_VALUE;
float x_min = Float.MAX_VALUE;
float y_max = Float.MIN_VALUE;
float y_min = Float.MAX_VALUE;
float z_max = Float.MIN_VALUE;
float z_min = Float.MAX_VALUE;

for (int i=0; i*3 < v.length; i+=3) {
float x = v[i*3 + 0];
float y = v[i*3 + 1];
float z = v[i*3 + 2];
for (int i=0; i < v.length; i++) {
float x = v.X();
float y = v.Y();
float z = v.Z();
x_max = Math.max(x_max, x);
x_min = Math.min(x_min, x);
y_max = Math.max(y_max, y);
Expand Down
14 changes: 7 additions & 7 deletions src/test/java/no/myke/parser/RenderModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -177,23 +177,23 @@ public void createModel(GL2 gl) {

for (ModelObject modelObject : model.objects) {
short[] p = modelObject.polygons;
float[] v = modelObject.vertices;
Vector[] v = modelObject.vectors;
float[] t = modelObject.textureCoordinates;

for (int i = 0; i < p.length; i += 3) {
int a = p[i + 0] * 3;
int b = p[i + 1] * 3;
int c = p[i + 2] * 3;
int a = p[i + 0];
int b = p[i + 1];
int c = p[i + 2];
int at = p[i + 0] * 2;
int bt = p[i + 1] * 2;
int ct = p[i + 2] * 2;
gl.glBegin(GL2.GL_POLYGON);
gl.glTexCoord2f(t[at], t[at + 1]);
gl.glVertex3f(v[a + 0], v[a + 1], v[a + 2]);
gl.glVertex3f(v[a].X(), v[a].Y(), v[a].Z());
gl.glTexCoord2f(t[bt], t[bt + 1]);
gl.glVertex3f(v[b + 0], v[b + 1], v[b + 2]);
gl.glVertex3f(v[b].X(), v[b].Y(), v[b].Z());
gl.glTexCoord2f(t[ct], t[ct + 1]);
gl.glVertex3f(v[c + 0], v[c + 1], v[c + 2]);
gl.glVertex3f(v[c].X(), v[c].Y(), v[c].Z());
gl.glEnd();
}
}
Expand Down