Checkpoint checkin for new model exporting/loading/animating code.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4013 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.model;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
|
||||
import com.jme.scene.Node;
|
||||
|
||||
import com.jme.math.Quaternion;
|
||||
import com.jme.math.TransformMatrix;
|
||||
import com.jme.math.Vector3f;
|
||||
|
||||
import com.threerings.jme.Log;
|
||||
|
||||
/**
|
||||
* Represents a bone in a scene. Bones can have simple meshes as children,
|
||||
* or they can be used to deform {@link SkinMesh}es.
|
||||
*/
|
||||
public class BoneNode extends ModelNode
|
||||
{
|
||||
/**
|
||||
* No-arg constructor for deserialization.
|
||||
*/
|
||||
public BoneNode ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* @param name the name of the node
|
||||
*/
|
||||
public BoneNode (String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void setReferenceTransforms ()
|
||||
{
|
||||
super.setReferenceTransforms();
|
||||
|
||||
// store the inverse of the reference transform
|
||||
_invRefTransform.set(worldRotation, worldTranslation);
|
||||
_invRefTransform.setScale(worldScale);
|
||||
_invRefTransform.inverse();
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void updateWorldVectors ()
|
||||
{
|
||||
super.updateWorldVectors();
|
||||
_skinTransform.set(worldRotation, worldTranslation);
|
||||
_skinTransform.setScale(worldScale);
|
||||
_skinTransform.multLocal(_invRefTransform, _tempStore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the matrix that transforms vertices in the
|
||||
* reference position to vertices in the current position.
|
||||
*/
|
||||
public TransformMatrix getSkinTransform ()
|
||||
{
|
||||
return _skinTransform;
|
||||
}
|
||||
|
||||
/** The inverse of the bone's world space reference transform. */
|
||||
protected TransformMatrix _invRefTransform = new TransformMatrix();
|
||||
|
||||
/** The bone's current skin transform. */
|
||||
protected TransformMatrix _skinTransform = new TransformMatrix();
|
||||
|
||||
/** A temporary vector for transformations. */
|
||||
protected Vector3f _tempStore = new Vector3f();
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.model;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
import com.threerings.jme.Log;
|
||||
|
||||
/**
|
||||
* The base node for models.
|
||||
*/
|
||||
public class Model extends ModelNode
|
||||
{
|
||||
/**
|
||||
* Attempts to read a model from the specified file.
|
||||
*
|
||||
* @param map if true, map buffers into memory directly from the
|
||||
* file
|
||||
*/
|
||||
public static Model readFromFile (File file, boolean map)
|
||||
throws IOException
|
||||
{
|
||||
// read the serialized model and its children
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
ObjectInputStream ois = new ObjectInputStream(fis);
|
||||
Model model;
|
||||
try {
|
||||
model = (Model)ois.readObject();
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.warning("Encountered unknown class [error=" + e + "].");
|
||||
return null;
|
||||
}
|
||||
|
||||
// then either read or map the buffers
|
||||
FileChannel fc = fis.getChannel();
|
||||
if (map) {
|
||||
long pos = fc.position();
|
||||
model.sliceBuffers(fc.map(FileChannel.MapMode.READ_ONLY,
|
||||
pos, fc.size() - pos));
|
||||
} else {
|
||||
model.readBuffers(fc);
|
||||
}
|
||||
ois.close();
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* No-arg constructor for deserialization.
|
||||
*/
|
||||
public Model ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard constructor.
|
||||
*/
|
||||
public Model (String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes this model out to a file.
|
||||
*/
|
||||
public void writeToFile (File file)
|
||||
throws IOException
|
||||
{
|
||||
// start out by writing this node and its children
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||
oos.writeObject(this);
|
||||
|
||||
// now traverse the scene graph appending buffers to the
|
||||
// end of the file
|
||||
writeBuffers(fos.getChannel());
|
||||
oos.close();
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void writeExternal (ObjectOutput out)
|
||||
throws IOException
|
||||
{
|
||||
super.writeExternal(out);
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void readExternal (ObjectInput in)
|
||||
throws IOException
|
||||
{
|
||||
super.readExternal(in);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.model;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
import com.jme.math.Quaternion;
|
||||
import com.jme.math.Vector3f;
|
||||
import com.jme.scene.TriMesh;
|
||||
|
||||
import com.threerings.jme.Log;
|
||||
|
||||
/**
|
||||
* A {@link TriMesh} with a serialization mechanism tailored to stored models.
|
||||
*/
|
||||
public class ModelMesh extends TriMesh
|
||||
implements Externalizable, ModelSpatial
|
||||
{
|
||||
/**
|
||||
* No-arg constructor for deserialization.
|
||||
*/
|
||||
public ModelMesh ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mesh with no vertex data.
|
||||
*/
|
||||
public ModelMesh (String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and populates a mesh.
|
||||
*/
|
||||
public ModelMesh (
|
||||
String name, FloatBuffer vertices, FloatBuffer normals,
|
||||
FloatBuffer colors, FloatBuffer tcoords, IntBuffer indices)
|
||||
{
|
||||
super(name, vertices, normals, colors, tcoords, indices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the buffers as {@link ByteBuffer}s, because we can't create byte
|
||||
* views of non-byte buffers.
|
||||
*/
|
||||
public void reconstruct (
|
||||
ByteBuffer vertices, ByteBuffer normals, ByteBuffer colors,
|
||||
ByteBuffer textures, ByteBuffer indices)
|
||||
{
|
||||
reconstruct(
|
||||
vertices == null ? null : vertices.asFloatBuffer(),
|
||||
normals == null ? null : normals.asFloatBuffer(),
|
||||
colors == null ? null : colors.asFloatBuffer(),
|
||||
textures == null ? null : textures.asFloatBuffer(),
|
||||
indices == null ? null : indices.asIntBuffer());
|
||||
_vertexByteBuffer = vertices;
|
||||
_normalByteBuffer = normals;
|
||||
_colorByteBuffer = colors;
|
||||
_textureByteBuffer = textures;
|
||||
_indexByteBuffer = indices;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void reconstruct (
|
||||
FloatBuffer vertices, FloatBuffer normals, FloatBuffer colors,
|
||||
FloatBuffer textures, IntBuffer indices)
|
||||
{
|
||||
super.reconstruct(vertices, normals, colors, textures, indices);
|
||||
|
||||
_vertexBufferSize = (vertices == null) ? 0 : vertices.capacity();
|
||||
_normalBufferSize = (normals == null) ? 0 : normals.capacity();
|
||||
_colorBufferSize = (colors == null) ? 0 : colors.capacity();
|
||||
_textureBufferSize = (textures == null) ? 0 : textures.capacity();
|
||||
_indexBufferSize = (indices == null) ? 0 : indices.capacity();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void reconstruct (
|
||||
FloatBuffer vertices, FloatBuffer normals, FloatBuffer colors,
|
||||
FloatBuffer textures)
|
||||
{
|
||||
super.reconstruct(vertices, normals, colors, textures);
|
||||
|
||||
_vertexBufferSize = (vertices == null) ? 0 : vertices.capacity();
|
||||
_normalBufferSize = (normals == null) ? 0 : normals.capacity();
|
||||
_colorBufferSize = (colors == null) ? 0 : colors.capacity();
|
||||
_textureBufferSize = (textures == null) ? 0 : textures.capacity();
|
||||
}
|
||||
|
||||
// documentation inherited from interface Externalizable
|
||||
public void writeExternal (ObjectOutput out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeUTF(getName());
|
||||
out.writeObject(getLocalTranslation());
|
||||
out.writeObject(getLocalRotation());
|
||||
out.writeObject(getLocalScale());
|
||||
out.writeInt(_vertexBufferSize);
|
||||
out.writeInt(_normalBufferSize);
|
||||
out.writeInt(_colorBufferSize);
|
||||
out.writeInt(_textureBufferSize);
|
||||
out.writeInt(_indexBufferSize);
|
||||
}
|
||||
|
||||
// documentation inherited from interface Externalizable
|
||||
public void readExternal (ObjectInput in)
|
||||
throws IOException
|
||||
{
|
||||
setName(in.readUTF());
|
||||
try {
|
||||
setLocalTranslation((Vector3f)in.readObject());
|
||||
setLocalRotation((Quaternion)in.readObject());
|
||||
setLocalScale((Vector3f)in.readObject());
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.warning("Encounted unknown class [mesh=" + getName() +
|
||||
", exception=" + e + "].");
|
||||
}
|
||||
_vertexBufferSize = in.readInt();
|
||||
_normalBufferSize = in.readInt();
|
||||
_colorBufferSize = in.readInt();
|
||||
_textureBufferSize = in.readInt();
|
||||
_indexBufferSize = in.readInt();
|
||||
}
|
||||
|
||||
// documentation inherited from interface ModelSpatial
|
||||
public void writeBuffers (FileChannel out)
|
||||
throws IOException
|
||||
{
|
||||
if (_vertexBufferSize > 0) {
|
||||
_vertexByteBuffer.rewind();
|
||||
out.write(_vertexByteBuffer);
|
||||
}
|
||||
if (_normalBufferSize > 0) {
|
||||
_normalByteBuffer.rewind();
|
||||
out.write(_normalByteBuffer);
|
||||
}
|
||||
if (_colorBufferSize > 0) {
|
||||
_colorByteBuffer.rewind();
|
||||
out.write(_colorByteBuffer);
|
||||
}
|
||||
if (_textureBufferSize > 0) {
|
||||
_indexByteBuffer.rewind();
|
||||
out.write(_indexByteBuffer);
|
||||
}
|
||||
if (_indexBufferSize > 0) {
|
||||
_indexByteBuffer.rewind();
|
||||
out.write(_indexByteBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface ModelSpatial
|
||||
public void readBuffers (FileChannel in)
|
||||
throws IOException
|
||||
{
|
||||
ByteBuffer vbbuf = null, nbbuf = null, cbbuf = null, tbbuf = null,
|
||||
ibbuf = null;
|
||||
if (_vertexBufferSize > 0) {
|
||||
vbbuf = ByteBuffer.allocateDirect(_vertexBufferSize*3*4);
|
||||
in.read(vbbuf);
|
||||
vbbuf.rewind();
|
||||
}
|
||||
if (_normalBufferSize > 0) {
|
||||
nbbuf = ByteBuffer.allocateDirect(_normalBufferSize*3*4);
|
||||
in.read(nbbuf);
|
||||
nbbuf.rewind();
|
||||
}
|
||||
if (_colorBufferSize > 0) {
|
||||
cbbuf = ByteBuffer.allocateDirect(_colorBufferSize*4*4);
|
||||
in.read(cbbuf);
|
||||
cbbuf.rewind();
|
||||
}
|
||||
if (_textureBufferSize > 0) {
|
||||
tbbuf = ByteBuffer.allocateDirect(_textureBufferSize*2*4);
|
||||
in.read(tbbuf);
|
||||
tbbuf.rewind();
|
||||
}
|
||||
if (_indexBufferSize > 0) {
|
||||
ibbuf = ByteBuffer.allocateDirect(_indexBufferSize*4);
|
||||
in.read(ibbuf);
|
||||
ibbuf.rewind();
|
||||
}
|
||||
reconstruct(vbbuf, nbbuf, cbbuf, tbbuf, ibbuf);
|
||||
}
|
||||
|
||||
// documentation inherited from interface ModelSpatial
|
||||
public void sliceBuffers (MappedByteBuffer map)
|
||||
{
|
||||
ByteBuffer vbbuf = null, nbbuf = null, cbbuf = null, tbbuf = null,
|
||||
ibbuf = null;
|
||||
if (_vertexBufferSize > 0) {
|
||||
int npos = map.position() + _vertexBufferSize*3*4;
|
||||
map.limit(npos);
|
||||
vbbuf = map.slice();
|
||||
map.position(npos);
|
||||
}
|
||||
if (_normalBufferSize > 0) {
|
||||
int npos = map.position() + _normalBufferSize*3*4;
|
||||
map.limit(npos);
|
||||
nbbuf = map.slice();
|
||||
map.position(npos);
|
||||
}
|
||||
if (_colorBufferSize > 0) {
|
||||
int npos = map.position() + _colorBufferSize*4*4;
|
||||
map.limit(npos);
|
||||
cbbuf = map.slice();
|
||||
map.position(npos);
|
||||
}
|
||||
if (_textureBufferSize > 0) {
|
||||
int npos = map.position() + _textureBufferSize*2*4;
|
||||
map.limit(npos);
|
||||
tbbuf = map.slice();
|
||||
map.position(npos);
|
||||
}
|
||||
if (_indexBufferSize > 0) {
|
||||
int npos = map.position() + _indexBufferSize*4;
|
||||
map.limit(npos);
|
||||
ibbuf = map.slice();
|
||||
map.position(npos);
|
||||
}
|
||||
reconstruct(vbbuf, nbbuf, cbbuf, tbbuf, ibbuf);
|
||||
}
|
||||
|
||||
/** The sizes of the various buffers (zero for <code>null</code>). */
|
||||
protected int _vertexBufferSize, _normalBufferSize, _colorBufferSize,
|
||||
_textureBufferSize, _indexBufferSize;
|
||||
|
||||
/** The backing byte buffers for the various buffers. */
|
||||
protected ByteBuffer _vertexByteBuffer, _normalByteBuffer,
|
||||
_colorByteBuffer, _textureByteBuffer, _indexByteBuffer;
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.model;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.jme.math.Quaternion;
|
||||
import com.jme.math.Vector3f;
|
||||
import com.jme.scene.Node;
|
||||
import com.jme.scene.Spatial;
|
||||
|
||||
import com.threerings.jme.Log;
|
||||
|
||||
/**
|
||||
* A {@link Node} with a serialization mechanism tailored to stored models.
|
||||
*/
|
||||
public class ModelNode extends Node
|
||||
implements Externalizable, ModelSpatial
|
||||
{
|
||||
/**
|
||||
* No-arg constructor for deserialization.
|
||||
*/
|
||||
public ModelNode ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard constructor.
|
||||
*/
|
||||
public ModelNode (String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively sets the reference transforms for any {@link BoneNode}s in
|
||||
* the model.
|
||||
*/
|
||||
public void setReferenceTransforms ()
|
||||
{
|
||||
for (Object child : getChildren()) {
|
||||
if (child instanceof ModelNode) {
|
||||
((ModelNode)child).setReferenceTransforms();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface Externalizable
|
||||
public void writeExternal (ObjectOutput out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeUTF(getName());
|
||||
out.writeObject(getLocalTranslation());
|
||||
out.writeObject(getLocalRotation());
|
||||
out.writeObject(getLocalScale());
|
||||
out.writeObject(getChildren());
|
||||
}
|
||||
|
||||
// documentation inherited from interface Externalizable
|
||||
public void readExternal (ObjectInput in)
|
||||
throws IOException
|
||||
{
|
||||
setName(in.readUTF());
|
||||
try {
|
||||
setLocalTranslation((Vector3f)in.readObject());
|
||||
setLocalRotation((Quaternion)in.readObject());
|
||||
setLocalScale((Vector3f)in.readObject());
|
||||
ArrayList children = (ArrayList)in.readObject();
|
||||
for (int ii = 0, nn = children.size(); ii < nn; ii++) {
|
||||
attachChild((Spatial)children.get(ii));
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.warning("Encounted unknown class [node=" + getName() +
|
||||
", exception=" + e + "].");
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface ModelSpatial
|
||||
public void writeBuffers (FileChannel out)
|
||||
throws IOException
|
||||
{
|
||||
for (Object child : getChildren()) {
|
||||
if (child instanceof ModelSpatial) {
|
||||
((ModelSpatial)child).writeBuffers(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface ModelSpatial
|
||||
public void readBuffers (FileChannel in)
|
||||
throws IOException
|
||||
{
|
||||
for (Object child : getChildren()) {
|
||||
if (child instanceof ModelSpatial) {
|
||||
((ModelSpatial)child).readBuffers(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface ModelSpatial
|
||||
public void sliceBuffers (MappedByteBuffer map)
|
||||
{
|
||||
for (Object child : getChildren()) {
|
||||
if (child instanceof ModelSpatial) {
|
||||
((ModelSpatial)child).sliceBuffers(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.model;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
/**
|
||||
* Contains method common to both {@link ModelNode}s and {@link ModelMesh}es.
|
||||
*/
|
||||
public interface ModelSpatial
|
||||
{
|
||||
/**
|
||||
* Recursively writes any data buffers to the output channel.
|
||||
*/
|
||||
public void writeBuffers (FileChannel out)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Recursively reads any data buffers from the input channel.
|
||||
*/
|
||||
public void readBuffers (FileChannel in)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Recursively slices any data buffers from the buffer map.
|
||||
*/
|
||||
public void sliceBuffers (MappedByteBuffer map);
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.model;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import com.threerings.jme.Log;
|
||||
|
||||
/**
|
||||
* A triangle mesh that deforms according to a bone hierarchy.
|
||||
*/
|
||||
public class SkinMesh extends ModelMesh
|
||||
{
|
||||
/** Represents the vertex weights of a group of vertices influenced by the
|
||||
* same set of bones. */
|
||||
public static class WeightGroup
|
||||
implements Serializable
|
||||
{
|
||||
/** The indices of the affected vertices. */
|
||||
public int[] indices;
|
||||
|
||||
/** The bones influencing this group. */
|
||||
public BoneNode[] bones;
|
||||
|
||||
/** The array of interleaved weights (of length <code>indices.length *
|
||||
* bones.length</code>): weights for first vertex, weights for second,
|
||||
* etc. */
|
||||
public float[] weights;
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* No-arg constructor for deserialization.
|
||||
*/
|
||||
public SkinMesh ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty mesh.
|
||||
*/
|
||||
public SkinMesh (String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and populates a mesh.
|
||||
*/
|
||||
public SkinMesh (
|
||||
String name, FloatBuffer vertices, FloatBuffer normals,
|
||||
FloatBuffer color, FloatBuffer texture, IntBuffer indices)
|
||||
{
|
||||
super(name, vertices, normals, color, texture, indices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the weight groups that determine how vertices are affected by
|
||||
* bones.
|
||||
*/
|
||||
public void setWeightGroups (WeightGroup[] weightGroups)
|
||||
{
|
||||
_weightGroups = weightGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the array of weight groups.
|
||||
*/
|
||||
public WeightGroup[] getWeightGroups ()
|
||||
{
|
||||
return _weightGroups;
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void writeExternal (ObjectOutput out)
|
||||
throws IOException
|
||||
{
|
||||
super.writeExternal(out);
|
||||
out.writeObject(_weightGroups);
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void readExternal (ObjectInput in)
|
||||
throws IOException
|
||||
{
|
||||
super.readExternal(in);
|
||||
try {
|
||||
_weightGroups = (WeightGroup[])in.readObject();
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.warning("Encounted unknown class [mesh=" + getName() +
|
||||
", exception=" + e + "].");
|
||||
}
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void updateWorldData (float time)
|
||||
{
|
||||
super.updateWorldData(time);
|
||||
|
||||
// deform the mesh according to the positions of the bones
|
||||
for (int ii = 0; ii < _weightGroups.length; ii++) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** The groups of vertices influenced by different sets of bones. */
|
||||
protected WeightGroup[] _weightGroups;
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.tools;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A basic representation for keyframe animations.
|
||||
*/
|
||||
public class AnimationDef
|
||||
{
|
||||
/** A single frame of the animation. */
|
||||
public static class Frame
|
||||
{
|
||||
/** Transforms for affected nodes. */
|
||||
public ArrayList<Transform> transforms = new ArrayList<Transform>();
|
||||
|
||||
public void addTransform (Transform transform)
|
||||
{
|
||||
transforms.add(transform);
|
||||
}
|
||||
}
|
||||
|
||||
/** A transform for a single node. */
|
||||
public static class Transform
|
||||
{
|
||||
/** The name of the node to transform. */
|
||||
public String name;
|
||||
|
||||
/** The transformation parameters. */
|
||||
public float[] translation;
|
||||
public float[] rotation;
|
||||
public float[] scale;
|
||||
}
|
||||
|
||||
/** The individual frames of the animation. */
|
||||
public ArrayList<Frame> frames = new ArrayList<Frame>();
|
||||
|
||||
public void addFrame (Frame frame)
|
||||
{
|
||||
frames.add(frame);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.apache.tools.ant.Task;
|
||||
import org.apache.tools.ant.types.FileSet;
|
||||
|
||||
import com.threerings.jme.model.BoneNode;
|
||||
import com.threerings.jme.model.Model;
|
||||
import com.threerings.jme.model.ModelMesh;
|
||||
import com.threerings.jme.model.ModelNode;
|
||||
import com.threerings.jme.model.SkinMesh;
|
||||
import com.threerings.jme.tools.xml.ModelParser;
|
||||
|
||||
/**
|
||||
* An ant task for compiling 3D models defined in XML to fast-loading binary
|
||||
* files.
|
||||
*/
|
||||
public class CompileModelTask extends Task
|
||||
{
|
||||
public void addFileset (FileSet set)
|
||||
{
|
||||
_filesets.add(set);
|
||||
}
|
||||
|
||||
public void execute ()
|
||||
throws BuildException
|
||||
{
|
||||
for (int ii = 0, nn = _filesets.size(); ii < nn; ii++) {
|
||||
FileSet fs = _filesets.get(ii);
|
||||
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
|
||||
File fromDir = fs.getDir(getProject());
|
||||
String[] srcFiles = ds.getIncludedFiles();
|
||||
|
||||
for (int f = 0; f < srcFiles.length; f++) {
|
||||
File cfile = new File(fromDir, srcFiles[f]);
|
||||
String target = srcFiles[f];
|
||||
int didx = target.lastIndexOf(".");
|
||||
target = (didx == -1) ? target : target.substring(0, didx);
|
||||
target += ".dat";
|
||||
compileModel(cfile, new File(fromDir, target));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void compileModel (File source, File target)
|
||||
{
|
||||
if (source.lastModified() < target.lastModified()) {
|
||||
return;
|
||||
}
|
||||
System.out.println("Compiling " + source + "...");
|
||||
|
||||
ModelDef mdef;
|
||||
try {
|
||||
mdef = _mparser.parseModel(source.toString());
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error parsing '" + source + "': " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
Model model = mdef.createModel("model");
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(target);
|
||||
new ObjectOutputStream(fos).writeObject(model);
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error writing '" + target + "': " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/** A list of filesets that contain XML models. */
|
||||
protected ArrayList<FileSet> _filesets = new ArrayList<FileSet>();
|
||||
|
||||
/** A parser for the model definitions. */
|
||||
protected ModelParser _mparser = new ModelParser();
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.tools;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import com.jme.scene.Spatial;
|
||||
import com.jme.util.geom.BufferUtils;
|
||||
|
||||
import com.threerings.jme.Log;
|
||||
import com.threerings.jme.model.BoneNode;
|
||||
import com.threerings.jme.model.Model;
|
||||
import com.threerings.jme.model.ModelMesh;
|
||||
import com.threerings.jme.model.ModelNode;
|
||||
import com.threerings.jme.model.SkinMesh;
|
||||
|
||||
/**
|
||||
* An intermediate representation for model nodes using in XML parsing.
|
||||
*/
|
||||
public class ModelDef
|
||||
{
|
||||
/** The base class of nodes in the model. */
|
||||
public abstract static class SpatialDef
|
||||
{
|
||||
/** The node's name. */
|
||||
public String name;
|
||||
|
||||
/** The name of the node's parent. */
|
||||
public String parent;
|
||||
|
||||
/** The node's transformation. */
|
||||
public float[] translation;
|
||||
public float[] rotation;
|
||||
public float[] scale;
|
||||
|
||||
/** Returns a JME node for this definition. */
|
||||
public Spatial getSpatial ()
|
||||
{
|
||||
if (_spatial == null) {
|
||||
_spatial = createSpatial();
|
||||
setTransform();
|
||||
}
|
||||
return _spatial;
|
||||
}
|
||||
|
||||
/** Sets the transform of the created node. */
|
||||
protected void setTransform ()
|
||||
{
|
||||
_spatial.getLocalTranslation().set(translation[0], translation[1],
|
||||
translation[2]);
|
||||
_spatial.getLocalRotation().set(rotation[0], rotation[1],
|
||||
rotation[2], rotation[3]);
|
||||
_spatial.getLocalScale().set(scale[0], scale[1], scale[2]);
|
||||
}
|
||||
|
||||
/** Creates a JME node for this definition. */
|
||||
public abstract Spatial createSpatial ();
|
||||
|
||||
/** Resolves any name references using the supplied map. */
|
||||
public void resolveReferences (HashMap<String, Spatial> nodes)
|
||||
{
|
||||
Spatial pnode = nodes.get(parent);
|
||||
if (pnode instanceof ModelNode) {
|
||||
((ModelNode)pnode).attachChild(_spatial);
|
||||
} else if (parent != null) {
|
||||
Log.warning("Missing or invalid parent node [spatial=" +
|
||||
name + ", parent=" + parent + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/** The JME node created for this definition. */
|
||||
protected Spatial _spatial;
|
||||
}
|
||||
|
||||
/** A rigid triangle mesh. */
|
||||
public static class TriMeshDef extends SpatialDef
|
||||
{
|
||||
/** The vertices of the mesh. */
|
||||
public ArrayList<Vertex> vertices = new ArrayList<Vertex>();
|
||||
|
||||
/** The triangle indices. */
|
||||
public ArrayList<Integer> indices = new ArrayList<Integer>();
|
||||
|
||||
/** Whether or not any of the vertices have texture coordinates. */
|
||||
public boolean tcoords;
|
||||
|
||||
public void addVertex (Vertex vertex)
|
||||
{
|
||||
int idx = vertices.indexOf(vertex);
|
||||
if (idx != -1) {
|
||||
indices.add(idx);
|
||||
} else {
|
||||
indices.add(vertices.size());
|
||||
vertices.add(vertex);
|
||||
}
|
||||
tcoords = tcoords || vertex.tcoords != null;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public Spatial createSpatial ()
|
||||
{
|
||||
return setBuffers(new ModelMesh(name));
|
||||
}
|
||||
|
||||
/** Sets the mesh's geometry buffers and returns it. */
|
||||
protected ModelMesh setBuffers (ModelMesh mmesh)
|
||||
{
|
||||
int vsize = vertices.size();
|
||||
ByteBuffer vbbuf = ByteBuffer.allocateDirect(vsize*3*4),
|
||||
nbbuf = ByteBuffer.allocateDirect(vsize*3*4),
|
||||
tbbuf = tcoords ? ByteBuffer.allocateDirect(vsize*2*4) : null,
|
||||
ibbuf = ByteBuffer.allocateDirect(indices.size()*4);
|
||||
FloatBuffer vbuf = vbbuf.asFloatBuffer(),
|
||||
nbuf = nbbuf.asFloatBuffer(),
|
||||
tbuf = tcoords ? tbbuf.asFloatBuffer() : null;
|
||||
for (int ii = 0; ii < vsize; ii++) {
|
||||
vertices.get(ii).setInBuffers(vbuf, nbuf, tbuf);
|
||||
}
|
||||
IntBuffer ibuf = ibbuf.asIntBuffer();
|
||||
for (int ii = 0, nn = indices.size(); ii < nn; ii++) {
|
||||
ibuf.put(indices.get(ii));
|
||||
}
|
||||
mmesh.reconstruct(vbbuf, nbbuf, null, tbbuf, ibbuf);
|
||||
return mmesh;
|
||||
}
|
||||
}
|
||||
|
||||
/** A triangle mesh that deforms according to bone positions. */
|
||||
public static class SkinMeshDef extends TriMeshDef
|
||||
{
|
||||
// documentation inherited
|
||||
public Spatial createSpatial ()
|
||||
{
|
||||
return setBuffers(new SkinMesh(name));
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void resolveReferences (HashMap<String, Spatial> nodes)
|
||||
{
|
||||
super.resolveReferences(nodes);
|
||||
|
||||
// divide the vertices up by weight groups
|
||||
HashMap<HashSet<String>, WeightGroupDef> groups =
|
||||
new HashMap<HashSet<String>, WeightGroupDef>();
|
||||
for (int ii = 0, nn = vertices.size(); ii < nn; ii++) {
|
||||
SkinVertex svertex = (SkinVertex)vertices.get(ii);
|
||||
HashSet<String> bones = svertex.getBoneNames();
|
||||
WeightGroupDef group = groups.get(bones);
|
||||
if (group == null) {
|
||||
groups.put(bones, group = new WeightGroupDef());
|
||||
}
|
||||
group.indices.add(ii);
|
||||
for (String bone : bones) {
|
||||
group.weights.add(svertex.getWeight(bone));
|
||||
}
|
||||
}
|
||||
|
||||
// resolve names and set in mesh
|
||||
SkinMesh.WeightGroup[] wgroups =
|
||||
new SkinMesh.WeightGroup[groups.size()];
|
||||
int ii = 0;
|
||||
for (Map.Entry<HashSet<String>, WeightGroupDef> entry :
|
||||
groups.entrySet()) {
|
||||
SkinMesh.WeightGroup wgroup = new SkinMesh.WeightGroup();
|
||||
wgroup.indices = toArray(entry.getValue().indices);
|
||||
wgroup.bones = new BoneNode[entry.getKey().size()];
|
||||
int jj = 0;
|
||||
for (String bone : entry.getKey()) {
|
||||
Spatial node = nodes.get(bone);
|
||||
if (!(node instanceof BoneNode)) {
|
||||
Log.warning("Missing or invalid bone reference " +
|
||||
"[mesh=" + name + ", bone=" + bone + "].");
|
||||
return;
|
||||
}
|
||||
wgroup.bones[jj++] = (BoneNode)node;
|
||||
}
|
||||
wgroup.weights = toArray(entry.getValue().weights);
|
||||
wgroups[ii++] = wgroup;
|
||||
}
|
||||
((SkinMesh)_spatial).setWeightGroups(wgroups);
|
||||
}
|
||||
}
|
||||
|
||||
/** A generic node. */
|
||||
public static class NodeDef extends SpatialDef
|
||||
{
|
||||
// documentation inherited
|
||||
public Spatial createSpatial ()
|
||||
{
|
||||
return new ModelNode(name);
|
||||
}
|
||||
}
|
||||
|
||||
/** A bone that influences skinned meshes. */
|
||||
public static class BoneNodeDef extends NodeDef
|
||||
{
|
||||
// documentation inherited
|
||||
public Spatial createSpatial ()
|
||||
{
|
||||
return new BoneNode(name);
|
||||
}
|
||||
}
|
||||
|
||||
/** A basic vertex. */
|
||||
public static class Vertex
|
||||
{
|
||||
public float[] location;
|
||||
public float[] normal;
|
||||
public float[] tcoords;
|
||||
|
||||
public void setInBuffers (
|
||||
FloatBuffer vbuf, FloatBuffer nbuf, FloatBuffer tbuf)
|
||||
{
|
||||
vbuf.put(location);
|
||||
nbuf.put(normal);
|
||||
if (tbuf != null) {
|
||||
tbuf.put(tcoords);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals (Object obj)
|
||||
{
|
||||
Vertex overt = (Vertex)obj;
|
||||
return Arrays.equals(location, overt.location) &&
|
||||
Arrays.equals(normal, overt.normal) &&
|
||||
Arrays.equals(tcoords, overt.tcoords);
|
||||
}
|
||||
}
|
||||
|
||||
/** A vertex influenced by a number of bones. */
|
||||
public static class SkinVertex extends Vertex
|
||||
{
|
||||
/** The bones influencing the vertex. */
|
||||
public ArrayList<BoneWeight> boneWeights = new ArrayList<BoneWeight>();
|
||||
|
||||
public void addBoneWeight (BoneWeight weight)
|
||||
{
|
||||
boneWeights.add(weight);
|
||||
}
|
||||
|
||||
/** Returns the set of names of the bones influencing this vertex. */
|
||||
public HashSet<String> getBoneNames ()
|
||||
{
|
||||
HashSet<String> names = new HashSet<String>();
|
||||
for (BoneWeight bweight : boneWeights) {
|
||||
names.add(bweight.bone);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
/** Returns the weight of the named bone. */
|
||||
public float getWeight (String bone)
|
||||
{
|
||||
for (BoneWeight bweight : boneWeights) {
|
||||
if (bweight.bone.equals(bone)) {
|
||||
return bweight.weight;
|
||||
}
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
/** The influence of a bone on a vertex. */
|
||||
public static class BoneWeight
|
||||
{
|
||||
/** The name of the influencing bone. */
|
||||
public String bone;
|
||||
|
||||
/** The amount of influence. */
|
||||
public float weight;
|
||||
}
|
||||
|
||||
/** A group of vertices influenced by the same bone. */
|
||||
public static class WeightGroupDef
|
||||
{
|
||||
/** The indices of the affected vertex. */
|
||||
public ArrayList<Integer> indices = new ArrayList<Integer>();
|
||||
|
||||
/** The interleaved vertex weights. */
|
||||
public ArrayList<Float> weights = new ArrayList<Float>();
|
||||
}
|
||||
|
||||
/** The meshes and bones comprising the model. */
|
||||
public ArrayList<SpatialDef> spatials = new ArrayList<SpatialDef>();
|
||||
|
||||
public void addSpatial (SpatialDef spatial)
|
||||
{
|
||||
spatials.add(spatial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the model node defined herein.
|
||||
*/
|
||||
public Model createModel (String name)
|
||||
{
|
||||
Model model = new Model(name);
|
||||
|
||||
// start by creating the spatials and mapping them to their names
|
||||
HashMap<String, Spatial> nodes = new HashMap<String, Spatial>();
|
||||
for (int ii = 0, nn = spatials.size(); ii < nn; ii++) {
|
||||
Spatial spatial = spatials.get(ii).getSpatial();
|
||||
nodes.put(spatial.getName(), spatial);
|
||||
}
|
||||
|
||||
// then go through again, resolving any name references and attaching
|
||||
// root children
|
||||
for (int ii = 0, nn = spatials.size(); ii < nn; ii++) {
|
||||
SpatialDef sdef = spatials.get(ii);
|
||||
sdef.resolveReferences(nodes);
|
||||
if (sdef.getSpatial().getParent() == null) {
|
||||
model.attachChild(sdef.getSpatial());
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/** Converts a boxed Integer list to an unboxed int array. */
|
||||
protected static int[] toArray (ArrayList<Integer> list)
|
||||
{
|
||||
int[] array = new int[list.size()];
|
||||
for (int ii = 0, nn = list.size(); ii < nn; ii++) {
|
||||
array[ii] = list.get(ii);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Converts a boxed Float list to an unboxed float array. */
|
||||
protected static float[] toArray (ArrayList<Float> list)
|
||||
{
|
||||
float[] array = new float[list.size()];
|
||||
for (int ii = 0, nn = list.size(); ii < nn; ii++) {
|
||||
array[ii] = list.get(ii);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// $Id: SceneParser.java 3749 2005-11-09 04:00:16Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.tools.xml;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
import org.apache.commons.digester.Digester;
|
||||
|
||||
import com.samskivert.xml.SetPropertyFieldsRule;
|
||||
|
||||
import com.threerings.jme.tools.AnimationDef;
|
||||
|
||||
/**
|
||||
* Parses XML files containing animations.
|
||||
*/
|
||||
public class AnimationParser
|
||||
{
|
||||
public AnimationParser ()
|
||||
{
|
||||
// create and configure our digester
|
||||
_digester = new Digester();
|
||||
|
||||
// add the rules
|
||||
String anim = "animation";
|
||||
_digester.addObjectCreate(anim, AnimationDef.class.getName());
|
||||
_digester.addSetNext(anim, "setAnimation",
|
||||
AnimationDef.class.getName());
|
||||
|
||||
String frame = anim + "/frame";
|
||||
_digester.addObjectCreate(frame, AnimationDef.Frame.class.getName());
|
||||
_digester.addSetNext(frame, "addFrame",
|
||||
AnimationDef.Frame.class.getName());
|
||||
|
||||
String xform = frame + "/transform";
|
||||
_digester.addObjectCreate(xform,
|
||||
AnimationDef.Transform.class.getName());
|
||||
_digester.addRule(xform, new SetPropertyFieldsRule());
|
||||
_digester.addSetNext(xform, "addTransform",
|
||||
AnimationDef.Transform.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the XML file at the specified path into an animation
|
||||
* definition.
|
||||
*/
|
||||
public AnimationDef parseAnimation (String path)
|
||||
throws IOException, SAXException
|
||||
{
|
||||
_animation = null;
|
||||
_digester.push(this);
|
||||
_digester.parse(new FileInputStream(path));
|
||||
return _animation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the parser once the animation is parsed.
|
||||
*/
|
||||
public void setAnimation (AnimationDef animation)
|
||||
{
|
||||
_animation = animation;
|
||||
}
|
||||
|
||||
protected Digester _digester;
|
||||
protected AnimationDef _animation;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// $Id: SceneParser.java 3749 2005-11-09 04:00:16Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.tools.xml;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
import org.apache.commons.digester.Digester;
|
||||
|
||||
import com.samskivert.xml.SetPropertyFieldsRule;
|
||||
|
||||
import com.threerings.jme.tools.ModelDef;
|
||||
|
||||
/**
|
||||
* Parses XML files containing 3D models.
|
||||
*/
|
||||
public class ModelParser
|
||||
{
|
||||
public ModelParser ()
|
||||
{
|
||||
// create and configure our digester
|
||||
_digester = new Digester();
|
||||
|
||||
// add the rules
|
||||
String model = "model";
|
||||
_digester.addObjectCreate(model, ModelDef.class.getName());
|
||||
_digester.addSetNext(model, "setModel", ModelDef.class.getName());
|
||||
|
||||
String tmesh = model + "/triMesh";
|
||||
_digester.addObjectCreate(tmesh, ModelDef.TriMeshDef.class.getName());
|
||||
_digester.addRule(tmesh, new SetPropertyFieldsRule());
|
||||
_digester.addSetNext(tmesh, "addSpatial",
|
||||
ModelDef.SpatialDef.class.getName());
|
||||
|
||||
String smesh = model + "/skinMesh";
|
||||
_digester.addObjectCreate(smesh,
|
||||
ModelDef.SkinMeshDef.class.getName());
|
||||
_digester.addRule(smesh, new SetPropertyFieldsRule());
|
||||
_digester.addSetNext(smesh, "addSpatial",
|
||||
ModelDef.SpatialDef.class.getName());
|
||||
|
||||
String node = model + "/node";
|
||||
_digester.addObjectCreate(node, ModelDef.NodeDef.class.getName());
|
||||
_digester.addRule(node, new SetPropertyFieldsRule());
|
||||
_digester.addSetNext(node, "addSpatial",
|
||||
ModelDef.SpatialDef.class.getName());
|
||||
|
||||
String bnode = model + "/boneNode";
|
||||
_digester.addObjectCreate(bnode, ModelDef.BoneNodeDef.class.getName());
|
||||
_digester.addRule(bnode, new SetPropertyFieldsRule());
|
||||
_digester.addSetNext(bnode, "addSpatial",
|
||||
ModelDef.SpatialDef.class.getName());
|
||||
|
||||
String vertex = tmesh + "/vertex";
|
||||
_digester.addObjectCreate(vertex, ModelDef.Vertex.class.getName());
|
||||
_digester.addObjectCreate(smesh + "/vertex",
|
||||
ModelDef.SkinVertex.class.getName());
|
||||
_digester.addRule("*/vertex", new SetPropertyFieldsRule());
|
||||
|
||||
String bweight = smesh + "/vertex/boneWeight";
|
||||
_digester.addObjectCreate(bweight,
|
||||
ModelDef.BoneWeight.class.getName());
|
||||
_digester.addRule(bweight, new SetPropertyFieldsRule());
|
||||
_digester.addSetNext(bweight, "addBoneWeight",
|
||||
ModelDef.BoneWeight.class.getName());
|
||||
|
||||
_digester.addSetNext("*/vertex", "addVertex",
|
||||
ModelDef.Vertex.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the XML file at the specified path into a model definition.
|
||||
*/
|
||||
public ModelDef parseModel (String path)
|
||||
throws IOException, SAXException
|
||||
{
|
||||
_model = null;
|
||||
_digester.push(this);
|
||||
_digester.parse(new FileInputStream(path));
|
||||
return _model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the parser once the model is parsed.
|
||||
*/
|
||||
public void setModel (ModelDef model)
|
||||
{
|
||||
_model = model;
|
||||
}
|
||||
|
||||
protected Digester _digester;
|
||||
protected ModelDef _model;
|
||||
}
|
||||
Reference in New Issue
Block a user