From 684904b91585b031ef78ce1d09b928e98cbcfb40 Mon Sep 17 00:00:00 2001 From: Caspian Rychlik-Prince Date: Tue, 20 Apr 2004 20:39:52 +0000 Subject: [PATCH] Now does meshed models as well as boned ones --- src/java/org/lwjgl/util/model/BoneFrame.java | 65 ++++++ src/java/org/lwjgl/util/model/BonedModel.java | 79 +++++++ .../org/lwjgl/util/model/BonedVertex.java | 68 ++++++ src/java/org/lwjgl/util/model/Frame.java | 26 +-- src/java/org/lwjgl/util/model/MeshFrame.java | 64 ++++++ .../org/lwjgl/util/model/MeshedModel.java | 66 ++++++ src/java/org/lwjgl/util/model/Model.java | 37 ++-- src/java/org/lwjgl/util/model/Vertex.java | 27 +-- .../util/model/{Skin.java => Weight.java} | 4 +- .../org/lwjgl/util/model/loader/Loader.java | 200 ++++++++++++++---- .../lwjgl/util/model/renderer/Renderer.java | 8 +- 11 files changed, 533 insertions(+), 111 deletions(-) create mode 100644 src/java/org/lwjgl/util/model/BoneFrame.java create mode 100644 src/java/org/lwjgl/util/model/BonedModel.java create mode 100644 src/java/org/lwjgl/util/model/BonedVertex.java create mode 100644 src/java/org/lwjgl/util/model/MeshFrame.java create mode 100644 src/java/org/lwjgl/util/model/MeshedModel.java rename src/java/org/lwjgl/util/model/{Skin.java => Weight.java} (96%) diff --git a/src/java/org/lwjgl/util/model/BoneFrame.java b/src/java/org/lwjgl/util/model/BoneFrame.java new file mode 100644 index 00000000..0eea1c8f --- /dev/null +++ b/src/java/org/lwjgl/util/model/BoneFrame.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2003 Shaven Puppy Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Shaven Puppy' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.util.model; + +import org.lwjgl.util.vector.Matrix4f; + +/** + * $Id$ + * A BoneFrame describes a set of new positions for Bones in an animation. + * @author $Author$ + * @version $Revision$ + */ +public class BoneFrame extends Frame { + + public static final long serialVersionUID = 1L; + + /** The new transformations for each Bone in the Skeleton */ + private final Matrix4f[] bone; + + /** + * C'tor + * @param time + * @param bone[] + */ + public BoneFrame(float time, Matrix4f[] bone) { + super(time); + this.bone = bone; + } + + /** + * @return the Bones + */ + public Matrix4f[] getBone() { + return bone; + } +} diff --git a/src/java/org/lwjgl/util/model/BonedModel.java b/src/java/org/lwjgl/util/model/BonedModel.java new file mode 100644 index 00000000..b28a0326 --- /dev/null +++ b/src/java/org/lwjgl/util/model/BonedModel.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002 Light Weight Java Game Library Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Light Weight Java Game Library' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.lwjgl.util.model; + +import java.util.Map; + +import org.lwjgl.util.vector.Vector2f; + + +/** + * $Id$ + * + * A simple animated, skinned, boned 3D model, consisting of a single mesh + * with a single material. The model's internal format is optimised for RAM storage; + * no metadata is held in memory - in other words this is not a good class to use + * for, say, a 3d modelling application. + * + * @author $Author$ + * @version $Revision$ + */ +public class BonedModel extends Model { + + public static final long serialVersionUID = 1L; + + /** Vertices */ + private final BonedVertex[] vertex; + + /** + * C'tor + * @param material + * @param triangle + * @param skin[] + * @param animation + * @param vertex + */ + public BonedModel(String material, Triangle[] triangle, Vector2f[] skin, Map animation, BonedVertex[] vertex) { + super(material, triangle, skin, animation); + this.vertex = vertex; + } + + /** + * @return Returns the vertices + */ + public BonedVertex[] getVertex() { + return vertex; + } + + +} diff --git a/src/java/org/lwjgl/util/model/BonedVertex.java b/src/java/org/lwjgl/util/model/BonedVertex.java new file mode 100644 index 00000000..e50580ae --- /dev/null +++ b/src/java/org/lwjgl/util/model/BonedVertex.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003 Shaven Puppy Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Shaven Puppy' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.util.model; + +import org.lwjgl.util.vector.ReadableVector3f; + +/** + * $Id$ + * + * A BonedVerex is a Vertex influenced by bone Weights + * + * @author $Author$ + * @version $Revision$ + */ +public class BonedVertex extends Vertex { + + public static final long serialVersionUID = 1L; + + /** Bone weights */ + private final Weight[] weight; + + /** + * C'tor + * @param coords + * @param normal + * @param skin + */ + public BonedVertex(ReadableVector3f coords, ReadableVector3f normal, Weight[] skin) { + super(coords, normal); + this.weight = skin; + } + + /** + * @return Returns the skin. + */ + public Weight[] getWeight() { + return weight; + } +} diff --git a/src/java/org/lwjgl/util/model/Frame.java b/src/java/org/lwjgl/util/model/Frame.java index 8207b943..861f42ad 100644 --- a/src/java/org/lwjgl/util/model/Frame.java +++ b/src/java/org/lwjgl/util/model/Frame.java @@ -33,41 +33,31 @@ package org.lwjgl.util.model; import java.io.Serializable; -import org.lwjgl.util.vector.Matrix4f; - /** - * A Frame describes a set of new positions for Bones. + * $Id$ + * The base class for animation frames. + * @author $Author$ + * @version $Revision$ */ -public class Frame implements Serializable { +public abstract class Frame implements Serializable { public static final long serialVersionUID = 1L; - /** The new transformations for each Bone in the Skeleton */ - private final Matrix4f[] bone; - /** Frame time */ private final float time; /** * C'tor - * @param bone[] + * @param time */ - public Frame(float time, Matrix4f[] bone) { + public Frame(float time) { this.time = time; - this.bone = bone; - } - - /** - * @return the Bones - */ - public Matrix4f[] getBone() { - return bone; } /** * @return the frame time */ - public float getTime() { + public final float getTime() { return time; } } diff --git a/src/java/org/lwjgl/util/model/MeshFrame.java b/src/java/org/lwjgl/util/model/MeshFrame.java new file mode 100644 index 00000000..2d747b02 --- /dev/null +++ b/src/java/org/lwjgl/util/model/MeshFrame.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003 Shaven Puppy Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Shaven Puppy' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.lwjgl.util.model; + + +/** + * $Id$ + * A MeshFrame describes a set of new positions for Vertices in an animation. + * @author $Author$ + * @version $Revision$ + */ +public class MeshFrame extends Frame { + + public static final long serialVersionUID = 1L; + + /** The vertices */ + private final Vertex[] vertex; + + /** + * C'tor + * @param time + * @param bone[] + */ + public MeshFrame(float time, Vertex[] vertex) { + super(time); + this.vertex = vertex; + } + + /** + * @return the Vertices + */ + public Vertex[] getVertex() { + return vertex; + } +} diff --git a/src/java/org/lwjgl/util/model/MeshedModel.java b/src/java/org/lwjgl/util/model/MeshedModel.java new file mode 100644 index 00000000..4fbe5f9f --- /dev/null +++ b/src/java/org/lwjgl/util/model/MeshedModel.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002 Light Weight Java Game Library Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Light Weight Java Game Library' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.lwjgl.util.model; + +import java.util.Map; + +import org.lwjgl.util.vector.Vector2f; + + +/** + * $Id$ + * + * A simple animated 3d mesh, consisting of multiple vertex positions. + * with a single material. The model's internal format is optimised for RAM storage; + * no metadata is held in memory - in other words this is not a good class to use + * for, say, a 3d modelling application. + * + * @author $Author$ + * @version $Revision$ + */ +public class MeshedModel extends Model { + + public static final long serialVersionUID = 1L; + + /** + * C'tor + * @param material + * @param triangle + * @param skin[] + * @param animation + */ + public MeshedModel(String material, Triangle[] triangle, Vector2f[] skin, Map animation) { + super(material, triangle, skin, animation); + } + +} diff --git a/src/java/org/lwjgl/util/model/Model.java b/src/java/org/lwjgl/util/model/Model.java index 37cf64d0..200f9050 100644 --- a/src/java/org/lwjgl/util/model/Model.java +++ b/src/java/org/lwjgl/util/model/Model.java @@ -35,45 +35,45 @@ package org.lwjgl.util.model; import java.io.Serializable; import java.util.Map; +import org.lwjgl.util.vector.Vector2f; + /** * $Id$ * - * A simple animated, skinned, boned 3D model, consisting of a single mesh - * with a single material. The model's internal format is optimised for RAM storage; - * no metadata is held in memory - in other words this is not a good class to use - * for, say, a 3d modelling application. + * Base class for the two kinds of model supported. A Model has a single "material" + * and a single triangular mesh with a single skin, and any number of animations. * * @author $Author$ * @version $Revision$ */ -public class Model implements Serializable { +public abstract class Model implements Serializable { public static final long serialVersionUID = 1L; /** Material */ private final String material; - /** Vertices */ - private final Vertex[] vertex; - /** Triangles */ private final Triangle[] triangle; + /** Skin */ + private final Vector2f[] skin; + /** The animations: a Map of string names to Frame[] arrays */ private final Map animation; /** * C'tor * @param material - * @param vertex * @param triangle + * @param skin[] * @param animation */ - public Model(String material, Vertex[] vertex, Triangle[] triangle, Map animation) { + public Model(String material, Triangle[] triangle, Vector2f[] skin, Map animation) { this.material = material; - this.vertex = vertex; this.triangle = triangle; + this.skin = skin; this.animation = animation; } @@ -82,30 +82,29 @@ public class Model implements Serializable { * @param name The name of the animation * @return the Frames of an animation (or null, if no such animation exists) */ - public Frame[] getAnimation(String name) { - return (Frame[]) animation.get(name); + public final BoneFrame[] getAnimation(String name) { + return (BoneFrame[]) animation.get(name); } /** * @return Returns the material. */ - public String getMaterial() { + public final String getMaterial() { return material; } /** * @return Returns the triangles. */ - public Triangle[] getTriangle() { + public final Triangle[] getTriangle() { return triangle; } /** - * @return Returns the vertices + * @return Returns the skin. */ - public Vertex[] getVertex() { - return vertex; + public final Vector2f[] getSkin() { + return skin; } - } diff --git a/src/java/org/lwjgl/util/model/Vertex.java b/src/java/org/lwjgl/util/model/Vertex.java index bd7e3b78..2443f2f7 100644 --- a/src/java/org/lwjgl/util/model/Vertex.java +++ b/src/java/org/lwjgl/util/model/Vertex.java @@ -33,7 +33,6 @@ package org.lwjgl.util.model; import java.io.Serializable; -import org.lwjgl.util.vector.ReadableVector2f; import org.lwjgl.util.vector.ReadableVector3f; /** @@ -54,24 +53,14 @@ public class Vertex implements Serializable { /** Normal */ private final ReadableVector3f normal; - /** Texture coordinates */ - private final ReadableVector2f texCoords; - - /** Skin */ - private final Skin[] skin; - /** * C'tor * @param coords * @param normal - * @param texCoords - * @param skin */ - public Vertex(ReadableVector3f coords, ReadableVector3f normal, ReadableVector2f texCoords, Skin[] skin) { + public Vertex(ReadableVector3f coords, ReadableVector3f normal) { this.coords = coords; this.normal = normal; - this.texCoords = texCoords; - this.skin = skin; } /** @@ -87,18 +76,4 @@ public class Vertex implements Serializable { public ReadableVector3f getNormal() { return normal; } - - /** - * @return Returns the skin. - */ - public Skin[] getSkin() { - return skin; - } - - /** - * @return Returns the texCoords. - */ - public ReadableVector2f getTexCoords() { - return texCoords; - } } diff --git a/src/java/org/lwjgl/util/model/Skin.java b/src/java/org/lwjgl/util/model/Weight.java similarity index 96% rename from src/java/org/lwjgl/util/model/Skin.java rename to src/java/org/lwjgl/util/model/Weight.java index 0864897b..05804a44 100644 --- a/src/java/org/lwjgl/util/model/Skin.java +++ b/src/java/org/lwjgl/util/model/Weight.java @@ -39,7 +39,7 @@ import java.io.Serializable; * @author $Author$ * @version $Revision$ */ -public class Skin implements Serializable { +public class Weight implements Serializable { public static final long serialVersionUID = 1L; @@ -52,7 +52,7 @@ public class Skin implements Serializable { /** * C'tor */ - public Skin(int bone, float weight) { + public Weight(int bone, float weight) { this.bone = bone; this.weight = weight; } diff --git a/src/java/org/lwjgl/util/model/loader/Loader.java b/src/java/org/lwjgl/util/model/loader/Loader.java index 27109ac6..b30f725e 100644 --- a/src/java/org/lwjgl/util/model/loader/Loader.java +++ b/src/java/org/lwjgl/util/model/loader/Loader.java @@ -36,11 +36,14 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.lwjgl.util.model.Frame; -import org.lwjgl.util.model.Model; -import org.lwjgl.util.model.Skin; +import org.lwjgl.util.model.*; +import org.lwjgl.util.model.BoneFrame; +import org.lwjgl.util.model.BonedModel; +import org.lwjgl.util.model.BonedVertex; +import org.lwjgl.util.model.MeshedModel; import org.lwjgl.util.model.Triangle; import org.lwjgl.util.model.Vertex; +import org.lwjgl.util.model.Weight; import org.lwjgl.util.vector.Matrix4f; import org.lwjgl.util.vector.Vector2f; import org.lwjgl.util.vector.Vector3f; @@ -74,30 +77,61 @@ public class Loader { * @throws Exception */ public Model load() throws Exception { - return new Model( - XMLUtil.getString(src.getDocumentElement(), "material"), - loadVertices(), - loadTriangles(), - loadAnimations(XMLUtil.getInt(src.getDocumentElement(), "bones")) - ); + String material = XMLUtil.getString(src.getDocumentElement(), "material"); + if (XMLUtil.getString(src.getDocumentElement(), "type").equals("boned")) { + // It's a boned model + return new BonedModel( + material, + loadTriangles(), + loadSkin(), + loadBoneAnimations(XMLUtil.getInt(src.getDocumentElement(), "bones", 0)), + loadBonedVertices() + ); + } else if (XMLUtil.getString(src.getDocumentElement(), "type").equals("meshed")) { + // It's a mesh keyframe model + return new MeshedModel( + material, + loadTriangles(), + loadSkin(), + loadMeshAnimations() + ); + } else { + throw new Exception("Unsupported model type."); + } } /** - * Load all the Vertices + * Load all the BonedVertices * @return Vertex[] * @throws Exception */ - private Vertex[] loadVertices() throws Exception { + private BonedVertex[] loadBonedVertices() throws Exception { List vertexElements = XMLUtil.getChildren(src.getDocumentElement(), "vertex"); - Vertex[] vertices = new Vertex[vertexElements.size()]; + BonedVertex[] vertices = new BonedVertex[vertexElements.size()]; int vertexCount = 0; for (Iterator i = vertexElements.iterator(); i.hasNext(); ) { Element vertexElement = (Element) i.next(); - vertices[vertexCount++] = loadVertex(vertexElement); + vertices[vertexCount++] = loadBonedVertex(vertexElement); } return vertices; } + /** + * Load the skin + * @return Vector2f[] + * @throws Exception + */ + private Vector2f[] loadSkin() throws Exception { + List skinElements = XMLUtil.getChildren(src.getDocumentElement(), "skin"); + Vector2f[] skins = new Vector2f[skinElements.size()]; + int skinCount = 0; + for (Iterator i = skinElements.iterator(); i.hasNext(); ) { + Element skinElement = (Element) i.next(); + skins[skinCount++] = loadTexCoord(skinElement); + } + return skins; + } + /** * Load all the Triangles * @return Triangle[] @@ -115,17 +149,32 @@ public class Loader { } /** - * Load all the animations + * Load all the bone animations * @param numBones The number of bones in the animations - * @return Map of animation names to Frame[] animations + * @return Map of animation names to BoneFrame[] animations * @throws Exception */ - private Map loadAnimations(int numBones) throws Exception { + private Map loadBoneAnimations(int numBones) throws Exception { List animationElements = XMLUtil.getChildren(src.getDocumentElement(), "animation"); Map animations = new HashMap(animationElements.size()); for (Iterator i = animationElements.iterator(); i.hasNext(); ) { Element animationElement = (Element) i.next(); - animations.put(XMLUtil.getString(animationElement, "name"), loadAnimation(animationElement, numBones)); + animations.put(XMLUtil.getString(animationElement, "name"), loadBonedAnimation(animationElement, numBones)); + } + return animations; + } + + /** + * Load all the mesh keyframe animations + * @return Map of animation names to MeshFrame[] animations + * @throws Exception + */ + private Map loadMeshAnimations() throws Exception { + List animationElements = XMLUtil.getChildren(src.getDocumentElement(), "animation"); + Map animations = new HashMap(animationElements.size()); + for (Iterator i = animationElements.iterator(); i.hasNext(); ) { + Element animationElement = (Element) i.next(); + animations.put(XMLUtil.getString(animationElement, "name"), loadMeshAnimation(animationElement)); } return animations; } @@ -136,16 +185,16 @@ public class Loader { * @return a Vertex * @throws Exception */ - private Vertex loadVertex(Element vertexElement) throws Exception { - List skinElements = XMLUtil.getChildren(vertexElement, "skin"); - Skin[] skins = new Skin[skinElements.size()]; - int skinCount = 0; - for (Iterator i = skinElements.iterator(); i.hasNext(); ) { - Element skinElement = (Element) i.next(); - skins[skinCount++] = loadSkin(skinElement); + private BonedVertex loadBonedVertex(Element vertexElement) throws Exception { + List weightElements = XMLUtil.getChildren(vertexElement, "weight"); + Weight[] weights = new Weight[weightElements.size()]; + int weightCount = 0; + for (Iterator i = weightElements.iterator(); i.hasNext(); ) { + Element weightElement = (Element) i.next(); + weights[weightCount++] = loadWeight(weightElement); } - return new Vertex( + return new BonedVertex( new Vector3f( XMLUtil.getFloat(vertexElement, "x"), XMLUtil.getFloat(vertexElement, "y"), @@ -156,22 +205,39 @@ public class Loader { XMLUtil.getFloat(vertexElement, "ny"), XMLUtil.getFloat(vertexElement, "nz") ), - new Vector2f( - XMLUtil.getFloat(vertexElement, "u"), - XMLUtil.getFloat(vertexElement, "v") - ), - skins + weights ); } /** - * Load a Skin from XML + * Load a Vertex from XML + * @param vertexElement + * @return a Vertex + * @throws Exception + */ + private Vertex loadMeshVertex(Element vertexElement) throws Exception { + return new Vertex( + new Vector3f( + XMLUtil.getFloat(vertexElement, "x"), + XMLUtil.getFloat(vertexElement, "y"), + XMLUtil.getFloat(vertexElement, "z") + ), + new Vector3f( + XMLUtil.getFloat(vertexElement, "nx"), + XMLUtil.getFloat(vertexElement, "ny"), + XMLUtil.getFloat(vertexElement, "nz") + ) + ); + } + + /** + * Load a Weight from XML * @param element * @return a Skin * @throws Exception */ - private Skin loadSkin(Element element) throws Exception { - return new Skin( + private Weight loadWeight(Element element) throws Exception { + return new Weight( XMLUtil.getInt(element, "bone"), XMLUtil.getFloat(element, "weight") ); @@ -193,19 +259,49 @@ public class Loader { } /** - * Load an Animation from XML + * Load a texture coordinate from XML * @param element - * @param numBones - * @return Frame[] + * @return a Vector2f * @throws Exception */ - private Frame[] loadAnimation(Element element, int numBones) throws Exception { + private Vector2f loadTexCoord(Element element) throws Exception { + return new Vector2f( + XMLUtil.getFloat(element, "u"), + XMLUtil.getFloat(element, "v") + ); + } + + /** + * Load a boned Animation from XML + * @param element + * @param numBones + * @return BoneFrame[] + * @throws Exception + */ + private BoneFrame[] loadBonedAnimation(Element element, int numBones) throws Exception { List frameElements = XMLUtil.getChildren(element, "frame"); - Frame[] frames = new Frame[frameElements.size()]; + BoneFrame[] frames = new BoneFrame[frameElements.size()]; int frameCount = 0; for (Iterator i = frameElements.iterator(); i.hasNext(); ) { Element frameElement = (Element) i.next(); - frames[frameCount++] = loadFrame(frameElement, numBones); + frames[frameCount++] = loadBoneFrame(frameElement, numBones); + } + return frames; + } + + /** + * Load a mesh Animation from XML + * @param element + * @return MeshFrame[] + * @throws Exception + */ + private MeshFrame[] loadMeshAnimation(Element element) throws Exception { + List frameElements = XMLUtil.getChildren(element, "frame"); + MeshFrame[] frames = new MeshFrame[frameElements.size()]; + int frameCount = 0; + for (Iterator i = frameElements.iterator(); i.hasNext(); ) { + Element frameElement = (Element) i.next(); + frames[frameCount++] = loadMeshFrame(frameElement); } return frames; } @@ -214,10 +310,10 @@ public class Loader { * Load a Frame from XML * @param element * @param numBones - * @return Frame + * @return BoneFrame * @throws Exception */ - private Frame loadFrame(Element element, int numBones) throws Exception { + private BoneFrame loadBoneFrame(Element element, int numBones) throws Exception { List boneElements = XMLUtil.getChildren(element, "bone"); if (boneElements.size() != numBones) { throw new Exception("Expected "+numBones+" bones in frame, only got "+boneElements.size()); @@ -228,12 +324,32 @@ public class Loader { Element boneElement = (Element) i.next(); bones[boneCount++] = loadBone(boneElement); } - return new Frame( + return new BoneFrame( XMLUtil.getFloat(element, "time", 0.0f), bones ); } + /** + * Load a Frame from XML + * @param element + * @return MeshFrame + * @throws Exception + */ + private MeshFrame loadMeshFrame(Element element) throws Exception { + List vertexElements = XMLUtil.getChildren(element, "vertex"); + Vertex[] vertices = new Vertex[vertexElements.size()]; + int vertexCount = 0; + for (Iterator i = vertexElements.iterator(); i.hasNext(); ) { + Element vertexElement = (Element) i.next(); + vertices[vertexCount++] = loadMeshVertex(vertexElement); + } + return new MeshFrame( + XMLUtil.getFloat(element, "time", 0.0f), + vertices + ); + } + /** * Load a Bone from XML * @param element diff --git a/src/java/org/lwjgl/util/model/renderer/Renderer.java b/src/java/org/lwjgl/util/model/renderer/Renderer.java index cdfb9395..ca3ed709 100644 --- a/src/java/org/lwjgl/util/model/renderer/Renderer.java +++ b/src/java/org/lwjgl/util/model/renderer/Renderer.java @@ -34,8 +34,8 @@ package org.lwjgl.util.model.renderer; import java.util.HashMap; import java.util.Map; -import org.lwjgl.util.model.Frame; -import org.lwjgl.util.model.Model; +import org.lwjgl.util.model.BoneFrame; +import org.lwjgl.util.model.BonedModel; /** * $Id$ @@ -67,7 +67,7 @@ public class Renderer { * @param animation The name of the animation * @param time The time for the animation */ - public void render(Model model, String animation, float time) { + public void render(BonedModel model, String animation, float time) { // 1. Set up GL state from the Model's material Renderable material = (Renderable) materials.get(model.getMaterial()); @@ -76,7 +76,7 @@ public class Renderer { } // 2. Get the animation - Frame[] frame = model.getAnimation(animation); + BoneFrame[] frame = model.getAnimation(animation); if (frame == null) { return; }