diff options
4 files changed, 249 insertions, 23 deletions
diff --git a/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3DataStore.java b/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3DataStore.java new file mode 100644 index 0000000..2300a5b --- /dev/null +++ b/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3DataStore.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.model.md3; + +import java.util.List; + +import com.ardor3d.extension.model.util.KeyframeController; +import com.ardor3d.scenegraph.Mesh; +import com.google.common.collect.Lists; + +public class Md3DataStore { + + private final Mesh _mainMesh; + private final KeyframeController<Mesh> _controller; + + private final List<String> _frameNames = Lists.newArrayList(); + + private final List<String> _skinNames = Lists.newArrayList(); + + public Md3DataStore(final Mesh mainMesh, final KeyframeController<Mesh> controller) { + super(); + _mainMesh = mainMesh; + _controller = controller; + } + + public Mesh getScene() { + return _mainMesh; + } + + public KeyframeController<Mesh> getController() { + return _controller; + } + + public List<String> getFrameNames() { + return _frameNames; + } + + public int getFrameIndex(final String frameName) { + return _frameNames.indexOf(frameName); + } + + public List<String> getSkinNames() { + return _skinNames; + } +} diff --git a/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Header.java b/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Header.java index ddc96ab..ac1ee27 100644 --- a/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Header.java +++ b/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Header.java @@ -30,7 +30,7 @@ final class Md3Header { */ final int _numTags; /** Number of Surface objects, with a maximum of MD3_MAX_SURFACES. Current value of MD3_MAX_SURFACES is 32. */ - final int _numSurface; + final int _numSurfaces; /** Number of Skin objects, unused */ final int _numSkins; /** @@ -46,7 +46,7 @@ final class Md3Header { final int _offsetEnd; Md3Header(final int magic, final int version, final String name, final int flags, final int numFrames, - final int numTags, final int numSurface, final int numSkins, final int offsetFrame, final int offsetTag, + final int numTags, final int numSurfaces, final int numSkins, final int offsetFrame, final int offsetTag, final int offsetSurface, final int offsetEnd) { super(); _magic = magic; @@ -55,7 +55,7 @@ final class Md3Header { _flags = flags; _numFrames = numFrames; _numTags = numTags; - _numSurface = numSurface; + _numSurfaces = numSurfaces; _numSkins = numSkins; _offsetFrame = offsetFrame; _offsetTag = offsetTag; diff --git a/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Importer.java b/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Importer.java new file mode 100644 index 0000000..34f6601 --- /dev/null +++ b/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Importer.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.extension.model.md3; + +import java.io.InputStream; + +import com.ardor3d.math.Matrix3; +import com.ardor3d.math.Vector2; +import com.ardor3d.math.Vector3; +import com.ardor3d.util.Ardor3dException; +import com.ardor3d.util.LittleEndianRandomAccessDataInput; +import com.ardor3d.util.resource.ResourceSource; + +public class Md3Importer { + + private static final float XYZ_SCALE = 1.0f / 64; + + /** + * Reads an MD3 file from the given resource + * + * @param resource + * a resource pointing to the model we wish to load. + * @return an Md3DataStore data object containing the scene and other useful elements. + */ + public Md3DataStore load(final ResourceSource resource) { + if (resource == null) { + throw new NullPointerException("Unable to load null resource"); + } + + try { + final InputStream md3Stream = resource.openStream(); + if (md3Stream == null) { + throw new NullPointerException("Unable to load null streams"); + } + final LittleEndianRandomAccessDataInput bis = new LittleEndianRandomAccessDataInput(md3Stream); + + // parse the header + final Md3Header header = new Md3Header(bis.readInt(), bis.readInt(), bis.readString(64), bis.readInt(), + bis.readInt(), bis.readInt(), bis.readInt(), bis.readInt(), bis.readInt(), bis.readInt(), + bis.readInt(), bis.readInt()); + + // Check magic word and version + if (header._magic != ('3' << 24) + ('P' << 16) + ('D' << 8) + 'I') { + throw new Ardor3dException("Not an MD3 file."); + } + if (header._version != 15) { + throw new Ardor3dException("Invalid file version (Version not 15)!"); + } + + // Parse out frames + final Md3Frame[] frames = new Md3Frame[header._numFrames]; + bis.seek(header._offsetFrame); + final Vector3 minBounds = new Vector3(); + final Vector3 maxBounds = new Vector3(); + final Vector3 localOrigin = new Vector3(); + for (int i = 0; i < header._numFrames; i++) { + minBounds.set(bis.readFloat(), bis.readFloat(), bis.readFloat()); + maxBounds.set(bis.readFloat(), bis.readFloat(), bis.readFloat()); + localOrigin.set(bis.readFloat(), bis.readFloat(), bis.readFloat()); + frames[i] = new Md3Frame(minBounds, maxBounds, localOrigin, bis.readFloat(), bis.readString(16)); + } + + // Parse out tags + final Md3Tag[] tags = new Md3Tag[header._numTags]; + bis.seek(header._offsetTag); + final Vector3 origin = new Vector3(); + final Matrix3 axis = new Matrix3(); + for (int i = 0; i < header._numTags; i++) { + final String name = bis.readString(64); + origin.set(bis.readFloat(), bis.readFloat(), bis.readFloat()); + axis.set(bis.readFloat(), bis.readFloat(), bis.readFloat(), bis.readFloat(), bis.readFloat(), + bis.readFloat(), bis.readFloat(), bis.readFloat(), bis.readFloat()); + tags[i] = new Md3Tag(name, origin, axis); + } + + // Parse out surfaces + final Md3Surface[] surfaces = new Md3Surface[header._numSurfaces]; + bis.seek(header._offsetSurface); + for (int i = 0; i < header._numSurfaces; i++) { + final int surfaceStart = bis.position(); + final int magic = bis.readInt(); + if (magic != ('3' << 24) + ('P' << 16) + ('D' << 8) + 'I') { + throw new Ardor3dException("Not an MD3 surface."); + } + surfaces[i] = new Md3Surface(magic, bis.readString(64), bis.readInt(), bis.readInt(), bis.readInt(), + bis.readInt(), bis.readInt(), bis.readInt(), bis.readInt(), bis.readInt(), bis.readInt(), + bis.readInt()); + // Parse out shaders + bis.seek(surfaceStart + surfaces[i]._offsetShaders); + for (int j = 0; j < surfaces[i]._numShaders; j++) { + // final String name = bis.readString(64); + // final int index = bis.readInt(); + // unused yet + } + // Parse out triangles + bis.seek(surfaceStart + surfaces[i]._offsetTriangles); + for (int j = 0; j < surfaces[i]._triIndexes.length; j++) { + surfaces[i]._triIndexes[j] = bis.readInt(); + } + // Parse out texture coordinates + bis.seek(surfaceStart + surfaces[i]._offsetTexCoords); + for (final int j = 0; j < surfaces[i]._texCoords.length; i++) { + surfaces[i]._texCoords[j] = new Vector2(bis.readFloat(), bis.readFloat()); + } + // Parse out vertices + bis.seek(surfaceStart + surfaces[i]._offsetXyzNormals); + for (int j = 0; j < surfaces[i]._numFrames; j++) { + for (int k = 0; k < surfaces[i]._numVerts; k++) { + surfaces[i]._verts[j][k] = new Vector3(bis.readShort(), bis.readShort(), bis.readShort()) + .multiplyLocal(Md3Importer.XYZ_SCALE); + final int zenith = bis.readByte(); + final int azimuth = bis.readByte(); + final float lat = (float) (zenith * 2 * Math.PI / 255); + final float lng = (float) (azimuth * 2 * Math.PI / 255); + surfaces[i]._norms[j][k] = new Vector3(Math.cos(lat) * Math.sin(lng), Math.sin(lat) + * Math.sin(lng), Math.cos(lng)); + } + } + } + + for (int i = 0; i < header._numSurfaces; i++) { + final Md3Surface surface = surfaces[i]; + + for (int j = 0; j < surface._numFrames; j++) { + final Md3Frame frame = frames[j]; + + } + // TODO + } + + // Make a store object to return + final Md3DataStore store = new Md3DataStore(/* mesh, controller */null, null); + + // store names + for (final Md3Frame frame : frames) { + store.getFrameNames().add(frame._name); + } + + // TODO look for the textures filenames in the .skin files + + return store; + } catch (final Exception e) { + throw new Error("Unable to load md3 resource from URL: " + resource, e); + } + } +} diff --git a/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Surface.java b/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Surface.java index 03905c0..ba28df2 100644 --- a/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Surface.java +++ b/ardor3d-extras/src/main/java/com/ardor3d/extension/model/md3/Md3Surface.java @@ -18,44 +18,63 @@ import com.ardor3d.math.Vector3; */ final class Md3Surface { + final int _magic; /** name */ - String name; + final String _name; /** flags */ - int flags; + final int _flags; /** Number of animation frames. This should match NUM_FRAMES in the MD3 header. */ - int numFrames; + final int _numFrames; /** * Number of Shader objects defined in this Surface, with a limit of MD3_MAX_SHADERS. Current value of * MD3_MAX_SHADERS is 256. */ - int numShaders; + final int _numShaders; /** Number of Vertex objects defined in this Surface, up to MD3_MAX_VERTS. Current value of MD3_MAX_VERTS is 4096. */ - int numVerts; + final int _numVerts; /** * Number of Triangle objects defined in this Surface, maximum of MD3_MAX_TRIANGLES. Current value of * MD3_MAX_TRIANGLES is 8192. */ - int numTriangles; + final int _numTriangles; /** Relative offset from SURFACE_START where the list of Triangle objects starts. */ - int offsetTriangles; + final int _offsetTriangles; /** Relative offset from SURFACE_START where the list of Shader objects starts. */ - int offsetShaders; + final int _offsetShaders; /** Relative offset from SURFACE_START where the list of ST objects (s-t texture coordinates) starts. */ - int offsetTexCoord; + final int _offsetTexCoords; /** Relative offset from SURFACE_START where the list of Vertex objects (X-Y-Z-N vertices) starts. */ - int offsetXyzNormal; + final int _offsetXyzNormals; /** Relative offset from SURFACE_START to where the Surface object ends. */ - int offsetEnd; - /** */ - int[] triIndexes; - /** */ - Vector2[] texCoords; - /** */ - Vector3[][] verts; - /** */ - Vector3[][] norms; + final int _offsetEnd; + /** Indices of triangles' vertices */ + final int[] _triIndexes; + /** Texture coordinates of triangles' vertices */ + final Vector2[] _texCoords; + /** Triangles' vertices */ + final Vector3[][] _verts; + /** Triangles' normals */ + final Vector3[][] _norms; - Md3Surface() { + Md3Surface(final int magic, final String name, final int flags, final int numFrames, final int numShaders, + final int numVerts, final int numTriangles, final int offsetTriangles, final int offsetShaders, + final int offsetTexCoords, final int offsetXyzNormals, final int offsetEnd) { super(); + _magic = magic; + _name = name; + _flags = flags; + _numFrames = numFrames; + _numShaders = numShaders; + _numVerts = numVerts; + _numTriangles = numTriangles; + _offsetTriangles = offsetTriangles; + _offsetShaders = offsetShaders; + _offsetTexCoords = offsetTexCoords; + _offsetXyzNormals = offsetXyzNormals; + _offsetEnd = offsetEnd; + _triIndexes = new int[_numTriangles * 3]; + _texCoords = new Vector2[_numVerts]; + _verts = new Vector3[_numFrames][_numVerts]; + _norms = new Vector3[_numFrames][_numVerts]; } } |