diff --git a/src/java/com/threerings/jme/model/EmissionController.java b/src/java/com/threerings/jme/model/EmissionController.java index 07d8499f..f0e872f1 100644 --- a/src/java/com/threerings/jme/model/EmissionController.java +++ b/src/java/com/threerings/jme/model/EmissionController.java @@ -22,13 +22,15 @@ package com.threerings.jme.model; import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; import java.util.Properties; import com.jme.scene.Controller; import com.jme.scene.Spatial; +import com.jme.util.export.JMEExporter; +import com.jme.util.export.JMEImporter; +import com.jme.util.export.InputCapsule; +import com.jme.util.export.OutputCapsule; /** * A model controller whose target represents an emitter. @@ -71,19 +73,21 @@ public abstract class EmissionController extends ModelController } @Override // documentation inherited - public void writeExternal (ObjectOutput out) + public void read (JMEImporter im) throws IOException { - super.writeExternal(out); - out.writeBoolean(_hideTarget); + super.read(im); + InputCapsule capsule = im.getCapsule(this); + _hideTarget = capsule.readBoolean("hideTarget", true); } @Override // documentation inherited - public void readExternal (ObjectInput in) - throws IOException, ClassNotFoundException + public void write (JMEExporter ex) + throws IOException { - super.readExternal(in); - _hideTarget = in.readBoolean(); + super.write(ex); + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(_hideTarget, "hideTarget", true); } /** Whether or not the target should be hidden from view. */ diff --git a/src/java/com/threerings/jme/model/Model.java b/src/java/com/threerings/jme/model/Model.java index eda95c72..edbc5e46 100644 --- a/src/java/com/threerings/jme/model/Model.java +++ b/src/java/com/threerings/jme/model/Model.java @@ -21,20 +21,15 @@ package com.threerings.jme.model; -import java.io.Externalizable; 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.io.Serializable; -import java.nio.ByteOrder; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; +import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.Collections; @@ -52,6 +47,13 @@ import com.jme.renderer.Renderer; import com.jme.scene.Controller; import com.jme.scene.Node; import com.jme.scene.Spatial; +import com.jme.util.export.JMEExporter; +import com.jme.util.export.JMEImporter; +import com.jme.util.export.InputCapsule; +import com.jme.util.export.OutputCapsule; +import com.jme.util.export.Savable; +import com.jme.util.export.binary.BinaryExporter; +import com.jme.util.export.binary.BinaryImporter; import com.samskivert.util.ObserverList; import com.samskivert.util.PropertiesUtil; @@ -99,7 +101,7 @@ public class Model extends ModelNode /** An animation for the model. */ public static class Animation - implements Serializable + implements Savable { /** The rate of the animation in frames per second. */ public int frameRate; @@ -171,30 +173,52 @@ public class Model extends ModelNode } } - private void writeObject (ObjectOutputStream out) + // documentation inherited + public Class getClassTag () + { + return getClass(); + } + + // documentation inherited + public void read (JMEImporter im) throws IOException { - out.defaultWriteObject(); - out.writeInt(transforms.length); + InputCapsule capsule = im.getCapsule(this); + frameRate = capsule.readInt("frameRate", 0); + repeatType = capsule.readInt("repeatType", Controller.RT_CLAMP); + Savable[] ttargs = capsule.readSavableArray( + "transformTargets", null); + transformTargets = new Spatial[ttargs.length]; + System.arraycopy(ttargs, 0, transformTargets, 0, ttargs.length); + FloatBuffer pxforms = capsule.readFloatBuffer("transforms", null); + transforms = new Transform[pxforms.capacity() / + Transform.PACKED_SIZE / transformTargets.length][]; for (int ii = 0; ii < transforms.length; ii++) { - for (int jj = 0; jj < transformTargets.length; jj++) { - transforms[ii][jj].writeExternal(out); + Transform[] frame = transforms[ii] = + new Transform[transformTargets.length]; + for (int jj = 0; jj < frame.length; jj++) { + frame[jj] = new Transform(pxforms); } } } - private void readObject (ObjectInputStream in) - throws IOException, ClassNotFoundException + // documentation inherited + public void write (JMEExporter ex) + throws IOException { - in.defaultReadObject(); - transforms = new Transform[in.readInt()][transformTargets.length]; - for (int ii = 0; ii < transforms.length; ii++) { - for (int jj = 0; jj < transformTargets.length; jj++) { - transforms[ii][jj] = new Transform(new Vector3f(), - new Quaternion(), new Vector3f()); - transforms[ii][jj].readExternal(in); + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(frameRate, "frameRate", 0); + capsule.write(repeatType, "repeatType", Controller.RT_CLAMP); + capsule.write(transformTargets, "transformTargets", null); + FloatBuffer pxforms = FloatBuffer.allocate(transforms.length * + transformTargets.length * Transform.PACKED_SIZE); + for (Transform[] frame : transforms) { + for (Transform xform : frame) { + xform.writeToBuffer(pxforms); } } + pxforms.rewind(); + capsule.write(pxforms, "transforms", null); } private static final long serialVersionUID = 1; @@ -202,8 +226,10 @@ public class Model extends ModelNode /** A frame element that manipulates the target's transform. */ public static final class Transform - implements Externalizable { + /** The number of floats required to store a packed transform. */ + public static final int PACKED_SIZE = 3 + 4 + 3; + public Transform ( Vector3f translation, Quaternion rotation, Vector3f scale) { @@ -212,6 +238,14 @@ public class Model extends ModelNode _scale = scale; } + public Transform (FloatBuffer buf) + { + _translation = new Vector3f(buf.get(), buf.get(), buf.get()); + _rotation = new Quaternion(buf.get(), buf.get(), buf.get(), + buf.get()); + _scale = new Vector3f(buf.get(), buf.get(), buf.get()); + } + public void apply (Spatial target) { target.getLocalTranslation().set(_translation); @@ -234,29 +268,29 @@ public class Model extends ModelNode target.getLocalScale().interpolate(_scale, next._scale, alpha); } - // documentation inherited from interface Externalizable - public void writeExternal (ObjectOutput out) - throws IOException + /** + * Writes this transform to the current position in the supplied + * buffer. + */ + public void writeToBuffer (FloatBuffer buf) { - _translation.writeExternal(out); - _rotation.writeExternal(out); - _scale.writeExternal(out); + buf.put(_translation.x); + buf.put(_translation.y); + buf.put(_translation.z); + + buf.put(_rotation.x); + buf.put(_rotation.y); + buf.put(_rotation.z); + buf.put(_rotation.w); + + buf.put(_scale.x); + buf.put(_scale.y); + buf.put(_scale.z); } - // documentation inherited from interface Externalizable - public void readExternal (ObjectInput in) - throws IOException, ClassNotFoundException - { - _translation.readExternal(in); - _rotation.readExternal(in); - _scale.readExternal(in); - } - /** The transform at this frame. */ protected Vector3f _translation, _scale; protected Quaternion _rotation; - - private static final long serialVersionUID = 1; } /** Customized clone creator for models. */ @@ -326,34 +360,14 @@ 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) + public static Model readFromFile (File file) 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(); + Model model = (Model)BinaryImporter.getInstance().load(fis); + fis.close(); // initialize the model as a prototype model.initPrototype(); @@ -677,17 +691,44 @@ public class Model extends ModelNode { // 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(); + BinaryExporter.getInstance().save(this, fos); + fos.close(); } @Override // documentation inherited - public void writeExternal (ObjectOutput out) + public void read (JMEImporter im) + throws IOException + { + super.read(im); + InputCapsule capsule = im.getCapsule(this); + String[] propNames = capsule.readStringArray("propNames", null), + propValues = capsule.readStringArray("propValues", null); + _props = new Properties(); + for (int ii = 0; ii < propNames.length; ii++) { + _props.setProperty(propNames[ii], propValues[ii]); + } + String[] animNames = capsule.readStringArray("animNames", null); + if (animNames != null) { + Savable[] animValues = capsule.readSavableArray( + "animValues", null); + _anims = new HashMap(); + for (int ii = 0; ii < animNames.length; ii++) { + _anims.put(animNames[ii], (Animation)animValues[ii]); + } + } else { + _anims = null; + } + ArrayList controllers = capsule.readSavableArrayList( + "controllers", null); + if (controllers != null) { + for (Object ctrl : controllers) { + addController((Controller)ctrl); + } + } + } + + @Override // documentation inherited + public void write (JMEExporter ex) throws IOException { // don't serialize the emission node; it contains transient geometry @@ -695,28 +736,24 @@ public class Model extends ModelNode if (_emissionNode != null) { detachChild(_emissionNode); } - super.writeExternal(out); + super.write(ex); if (_emissionNode != null) { attachChild(_emissionNode); } - out.writeObject(_props); - out.writeObject(_anims); - out.writeObject(getControllers()); + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(_props.keySet().toArray(new String[_props.size()]), + "propNames", null); + capsule.write(_props.values().toArray(new String[_props.size()]), + "propValues", null); + if (_anims != null) { + capsule.write(_anims.keySet().toArray( + new String[_anims.size()]), "animNames", null); + capsule.write(_anims.values().toArray( + new Animation[_anims.size()]), "animValues", null); + } + capsule.writeSavableArrayList(getControllers(), "controllers", null); } - @Override // documentation inherited - public void readExternal (ObjectInput in) - throws IOException, ClassNotFoundException - { - super.readExternal(in); - _props = (Properties)in.readObject(); - _anims = (HashMap)in.readObject(); - ArrayList controllers = (ArrayList)in.readObject(); - for (Object ctrl : controllers) { - addController((Controller)ctrl); - } - } - @Override // documentation inherited public void resolveTextures (TextureProvider tprov) { diff --git a/src/java/com/threerings/jme/model/ModelController.java b/src/java/com/threerings/jme/model/ModelController.java index e3d8b18d..c0a81e34 100644 --- a/src/java/com/threerings/jme/model/ModelController.java +++ b/src/java/com/threerings/jme/model/ModelController.java @@ -21,10 +21,7 @@ package com.threerings.jme.model; -import java.io.Externalizable; import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; import java.util.Collections; import java.util.HashSet; @@ -33,6 +30,10 @@ import java.util.Properties; import com.jme.scene.Controller; import com.jme.scene.Node; import com.jme.scene.Spatial; +import com.jme.util.export.JMEExporter; +import com.jme.util.export.JMEImporter; +import com.jme.util.export.InputCapsule; +import com.jme.util.export.OutputCapsule; import com.samskivert.util.StringUtil; @@ -40,7 +41,6 @@ import com.samskivert.util.StringUtil; * The superclass of procedural animation controllers for models. */ public abstract class ModelController extends Controller - implements Externalizable { /** * Configures this controller based on the supplied (sub-)properties and @@ -113,20 +113,30 @@ public abstract class ModelController extends Controller return mstore; } - // documentation inherited from interface Externalizable - public void writeExternal (ObjectOutput out) + @Override // documentation inherited + public void read (JMEImporter im) throws IOException { - out.writeObject(_target); - out.writeObject(_animations); + InputCapsule capsule = im.getCapsule(this); + _target = (Spatial)capsule.readSavable("target", null); + String[] anims = capsule.readStringArray("animations", null); + if (anims != null) { + _animations = new HashSet(); + Collections.addAll(_animations, anims); + } else { + _animations = null; + } } - // documentation inherited from interface Externalizable - public void readExternal (ObjectInput in) - throws IOException, ClassNotFoundException + @Override // documentation inherited + public void write (JMEExporter ex) + throws IOException { - _target = (Spatial)in.readObject(); - _animations = (HashSet)in.readObject(); + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(_target, "target", null); + capsule.write((_animations == null) ? + null : _animations.toArray(new String[_animations.size()]), + "animations", null); } /** diff --git a/src/java/com/threerings/jme/model/ModelMesh.java b/src/java/com/threerings/jme/model/ModelMesh.java index b91b16b5..ae08a9ad 100644 --- a/src/java/com/threerings/jme/model/ModelMesh.java +++ b/src/java/com/threerings/jme/model/ModelMesh.java @@ -21,17 +21,12 @@ 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.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Properties; @@ -58,6 +53,10 @@ import com.jme.scene.state.RenderState; import com.jme.scene.state.TextureState; import com.jme.scene.state.ZBufferState; import com.jme.system.DisplaySystem; +import com.jme.util.export.JMEExporter; +import com.jme.util.export.JMEImporter; +import com.jme.util.export.InputCapsule; +import com.jme.util.export.OutputCapsule; import com.jme.util.geom.BufferUtils; import com.samskivert.util.PropertiesUtil; @@ -69,7 +68,7 @@ import com.threerings.jme.Log; * A {@link TriMesh} with a serialization mechanism tailored to stored models. */ public class ModelMesh extends TriMesh - implements Externalizable, ModelSpatial + implements ModelSpatial { /** * No-arg constructor for deserialization. @@ -127,37 +126,6 @@ public class ModelMesh extends TriMesh Boolean.parseBoolean(tprops.getProperty("translucent")); } - /** - * Sets the buffers as {@link ByteBuffer}s, because we can't create byte - * views of non-byte buffers. This method is where the model is - * initialized after loading. - */ - 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()); - for (int ii = 1, nn = getTextureCount(); ii < nn; ii++) { - setTextureBuffer(0, getTextureBuffer(0, 0), ii); - } - _vertexByteBuffer = vertices; - _normalByteBuffer = normals; - _colorByteBuffer = colors; - _textureByteBuffer = textures; - _indexByteBuffer = indices; - - // store any buffers that will be manipulated on a per-instance basis - storeOriginalBuffers(); - - // initialize the model if we're displaying - setRenderStates(); - } - /** * Adjusts the vertices and the transform of the mesh so that the mesh's * position lies at the center of its bounding volume. @@ -209,27 +177,11 @@ public class ModelMesh extends TriMesh setTextureBuffer(0, getTextureBuffer(0, 0), ii); } - _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(); - } - - @Override // documentation inherited - public void reconstruct ( - FloatBuffer vertices, FloatBuffer normals, FloatBuffer colors, - FloatBuffer textures) - { - super.reconstruct(vertices, normals, colors, textures); - for (int ii = 1, nn = getTextureCount(); ii < nn; ii++) { - setTextureBuffer(0, getTextureBuffer(0, 0), ii); - } + // store any buffers that will be manipulated on a per-instance basis + storeOriginalBuffers(); - _vertexBufferSize = (vertices == null) ? 0 : vertices.capacity(); - _normalBufferSize = (normals == null) ? 0 : normals.capacity(); - _colorBufferSize = (colors == null) ? 0 : colors.capacity(); - _textureBufferSize = (textures == null) ? 0 : textures.capacity(); + // initialize the model if we're displaying + setRenderStates(); } // documentation inherited from interface ModelSpatial @@ -331,56 +283,64 @@ public class ModelMesh extends TriMesh } } - // documentation inherited from interface Externalizable - public void writeExternal (ObjectOutput out) + @Override // documentation inherited + public void read (JMEImporter im) throws IOException { - out.writeUTF(getName()); - out.writeObject(getLocalTranslation()); - out.writeObject(getLocalRotation()); - out.writeObject(getLocalScale()); - out.writeObject(getBatch(0).getModelBound()); - out.writeInt(_vertexBufferSize); - out.writeInt(_normalBufferSize); - out.writeInt(_colorBufferSize); - out.writeInt(_textureBufferSize); - out.writeInt(_indexBufferSize); - out.writeObject(_textureKey); - out.writeObject(_textures); - out.writeBoolean(_sphereMapped); - out.writeInt(_filterMode); - out.writeInt(_mipMapMode); - out.writeObject(_emissiveMap); - out.writeBoolean(_solid); - out.writeBoolean(_transparent); - out.writeFloat(_alphaThreshold); - out.writeBoolean(_translucent); + InputCapsule capsule = im.getCapsule(this); + setName(capsule.readString("name", null)); + setLocalTranslation((Vector3f)capsule.readSavable( + "localTranslation", null)); + setLocalRotation((Quaternion)capsule.readSavable( + "localRotation", null)); + setLocalScale((Vector3f)capsule.readSavable( + "localScale", null)); + TriangleBatch batch = (TriangleBatch)getBatch(0); + batch.setModelBound((BoundingVolume)capsule.readSavable( + "modelBound", null)); + _textureKey = capsule.readString("textureKey", null); + _textures = capsule.readStringArray("textures", null); + _sphereMapped = capsule.readBoolean("sphereMapped", false); + _filterMode = capsule.readInt("filterMode", Texture.FM_LINEAR); + _mipMapMode = capsule.readInt("mipMapMode", Texture.MM_LINEAR_LINEAR); + _emissiveMap = capsule.readString("emissiveMap", null); + _solid = capsule.readBoolean("solid", true); + _transparent = capsule.readBoolean("transparent", false); + _alphaThreshold = capsule.readFloat("alphaThreshold", + DEFAULT_ALPHA_THRESHOLD); + _translucent = capsule.readBoolean("translucent", false); + + reconstruct(capsule.readFloatBuffer("vertexBuffer", null), + capsule.readFloatBuffer("normalBuffer", null), null, + capsule.readFloatBuffer("textureBuffer", null), + capsule.readIntBuffer("indexBuffer", null)); } - // documentation inherited from interface Externalizable - public void readExternal (ObjectInput in) - throws IOException, ClassNotFoundException + @Override // documentation inherited + public void write (JMEExporter ex) + throws IOException { - setName(in.readUTF()); - setLocalTranslation((Vector3f)in.readObject()); - setLocalRotation((Quaternion)in.readObject()); - setLocalScale((Vector3f)in.readObject()); - setModelBound((BoundingVolume)in.readObject()); - _vertexBufferSize = in.readInt(); - _normalBufferSize = in.readInt(); - _colorBufferSize = in.readInt(); - _textureBufferSize = in.readInt(); - _indexBufferSize = in.readInt(); - _textureKey = (String)in.readObject(); - _textures = (String[])in.readObject(); - _sphereMapped = in.readBoolean(); - _filterMode = in.readInt(); - _mipMapMode = in.readInt(); - _emissiveMap = (String)in.readObject(); - _solid = in.readBoolean(); - _transparent = in.readBoolean(); - _alphaThreshold = in.readFloat(); - _translucent = in.readBoolean(); + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(getName(), "name", null); + capsule.write(getLocalTranslation(), "localTranslation", null); + capsule.write(getLocalRotation(), "localRotation", null); + capsule.write(getLocalScale(), "localScale", null); + capsule.write(getBatch(0).getModelBound(), "modelBound", null); + capsule.write(getVertexBuffer(0), "vertexBuffer", null); + capsule.write(getNormalBuffer(0), "normalBuffer", null); + capsule.write(getTextureBuffer(0, 0), "textureBuffer", null); + capsule.write(getIndexBuffer(0), "indexBuffer", null); + capsule.write(_textureKey, "textureKey", null); + capsule.write(_textures, "textures", null); + capsule.write(_sphereMapped, "sphereMapped", false); + capsule.write(_filterMode, "filterMode", Texture.FM_LINEAR); + capsule.write(_mipMapMode, "mipMapMode", Texture.MM_LINEAR_LINEAR); + capsule.write(_emissiveMap, "emissiveMap", null); + capsule.write(_solid, "solid", true); + capsule.write(_transparent, "transparent", false); + capsule.write(_alphaThreshold, "alphaThreshold", + DEFAULT_ALPHA_THRESHOLD); + capsule.write(_translucent, "translucent", false); } // documentation inherited from interface ModelSpatial @@ -463,121 +423,6 @@ public class ModelMesh extends TriMesh // no-op } - // documentation inherited from interface ModelSpatial - public void writeBuffers (FileChannel out) - throws IOException - { - if (_vertexBufferSize > 0) { - _vertexByteBuffer.rewind(); - convertOrder(_vertexByteBuffer, ByteOrder.LITTLE_ENDIAN); - out.write(_vertexByteBuffer); - convertOrder(_vertexByteBuffer, ByteOrder.nativeOrder()); - } - if (_normalBufferSize > 0) { - _normalByteBuffer.rewind(); - convertOrder(_normalByteBuffer, ByteOrder.LITTLE_ENDIAN); - out.write(_normalByteBuffer); - convertOrder(_normalByteBuffer, ByteOrder.nativeOrder()); - } - if (_colorBufferSize > 0) { - _colorByteBuffer.rewind(); - convertOrder(_colorByteBuffer, ByteOrder.LITTLE_ENDIAN); - out.write(_colorByteBuffer); - convertOrder(_colorByteBuffer, ByteOrder.nativeOrder()); - } - if (_textureBufferSize > 0) { - _textureByteBuffer.rewind(); - convertOrder(_textureByteBuffer, ByteOrder.LITTLE_ENDIAN); - out.write(_textureByteBuffer); - convertOrder(_textureByteBuffer, ByteOrder.nativeOrder()); - } - if (_indexBufferSize > 0) { - _indexByteBuffer.rewind(); - convertOrder(_indexByteBuffer, ByteOrder.LITTLE_ENDIAN); - out.write(_indexByteBuffer); - convertOrder(_indexByteBuffer, ByteOrder.nativeOrder()); - } - } - - // documentation inherited from interface ModelSpatial - public void readBuffers (FileChannel in) - throws IOException - { - ByteBuffer vbbuf = null, nbbuf = null, cbbuf = null, tbbuf = null, - ibbuf = null; - ByteOrder le = ByteOrder.LITTLE_ENDIAN; - if (_vertexBufferSize > 0) { - vbbuf = ByteBuffer.allocateDirect(_vertexBufferSize*4).order(le); - in.read(vbbuf); - vbbuf.rewind(); - convertOrder(vbbuf, ByteOrder.nativeOrder()); - } - if (_normalBufferSize > 0) { - nbbuf = ByteBuffer.allocateDirect(_normalBufferSize*4).order(le); - in.read(nbbuf); - nbbuf.rewind(); - convertOrder(nbbuf, ByteOrder.nativeOrder()); - } - if (_colorBufferSize > 0) { - cbbuf = ByteBuffer.allocateDirect(_colorBufferSize*4).order(le); - in.read(cbbuf); - cbbuf.rewind(); - convertOrder(cbbuf, ByteOrder.nativeOrder()); - } - if (_textureBufferSize > 0) { - tbbuf = ByteBuffer.allocateDirect(_textureBufferSize*4).order(le); - in.read(tbbuf); - tbbuf.rewind(); - convertOrder(tbbuf, ByteOrder.nativeOrder()); - } - if (_indexBufferSize > 0) { - ibbuf = ByteBuffer.allocateDirect(_indexBufferSize*4).order(le); - in.read(ibbuf); - ibbuf.rewind(); - convertOrder(ibbuf, ByteOrder.nativeOrder()); - } - 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; - int total = 0; - if (_vertexBufferSize > 0) { - int npos = map.position() + _vertexBufferSize*4; - map.limit(npos); - vbbuf = map.slice().order(ByteOrder.LITTLE_ENDIAN); - map.position(npos); - } - if (_normalBufferSize > 0) { - int npos = map.position() + _normalBufferSize*4; - map.limit(npos); - nbbuf = map.slice().order(ByteOrder.LITTLE_ENDIAN); - map.position(npos); - } - if (_colorBufferSize > 0) { - int npos = map.position() + _colorBufferSize*4; - map.limit(npos); - cbbuf = map.slice().order(ByteOrder.LITTLE_ENDIAN); - map.position(npos); - } - if (_textureBufferSize > 0) { - int npos = map.position() + _textureBufferSize*4; - map.limit(npos); - tbbuf = map.slice().order(ByteOrder.LITTLE_ENDIAN); - map.position(npos); - } - if (_indexBufferSize > 0) { - int npos = map.position() + _indexBufferSize*4; - map.limit(npos); - ibbuf = map.slice().order(ByteOrder.LITTLE_ENDIAN); - map.position(npos); - } - reconstruct(vbbuf, nbbuf, cbbuf, tbbuf, ibbuf); - } - @Override // documentation inherited protected void setupBatchList () { @@ -675,21 +520,6 @@ public class ModelMesh extends TriMesh } } - /** - * Imposes the specified order on the given buffer of 32 bit values. - */ - protected static void convertOrder (ByteBuffer buf, ByteOrder order) - { - if (buf.order() == order) { - return; - } - IntBuffer obuf = buf.asIntBuffer(), - nbuf = buf.order(order).asIntBuffer(); - while (obuf.hasRemaining()) { - nbuf.put(obuf.get()); - } - } - /** * Initializes the states shared between all models. Requires an active * display. @@ -879,14 +709,6 @@ public class ModelMesh extends TriMesh new RenderState[RenderState.RS_MAX_STATE]; } - /** The sizes of the various buffers (zero for null). */ - protected int _vertexBufferSize, _normalBufferSize, _colorBufferSize, - _textureBufferSize, _indexBufferSize; - - /** The backing byte buffers for the various buffers. */ - protected ByteBuffer _vertexByteBuffer, _normalByteBuffer, - _colorByteBuffer, _textureByteBuffer, _indexByteBuffer; - /** The type of bounding volume that this mesh should use. */ protected int _boundingType; diff --git a/src/java/com/threerings/jme/model/ModelNode.java b/src/java/com/threerings/jme/model/ModelNode.java index 8811dba9..d1ac0f80 100644 --- a/src/java/com/threerings/jme/model/ModelNode.java +++ b/src/java/com/threerings/jme/model/ModelNode.java @@ -22,13 +22,7 @@ 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 java.util.HashSet; @@ -41,6 +35,10 @@ import com.jme.scene.Controller; import com.jme.scene.Node; import com.jme.scene.Spatial; import com.jme.scene.state.RenderState; +import com.jme.util.export.JMEExporter; +import com.jme.util.export.JMEImporter; +import com.jme.util.export.InputCapsule; +import com.jme.util.export.OutputCapsule; import com.threerings.jme.Log; @@ -48,7 +46,7 @@ import com.threerings.jme.Log; * A {@link Node} with a serialization mechanism tailored to stored models. */ public class ModelNode extends Node - implements Externalizable, ModelSpatial + implements ModelSpatial { /** * No-arg constructor for deserialization. @@ -174,33 +172,38 @@ public class ModelNode extends Node return mstore; } - // documentation inherited from interface Externalizable - public void writeExternal (ObjectOutput out) + @Override // documentation inherited + public void read (JMEImporter im) 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, ClassNotFoundException - { - setName(in.readUTF()); - setLocalTranslation((Vector3f)in.readObject()); - setLocalRotation((Quaternion)in.readObject()); - setLocalScale((Vector3f)in.readObject()); - ArrayList children = (ArrayList)in.readObject(); + InputCapsule capsule = im.getCapsule(this); + setName(capsule.readString("name", null)); + setLocalTranslation((Vector3f)capsule.readSavable( + "localTranslation", null)); + setLocalRotation((Quaternion)capsule.readSavable( + "localRotation", null)); + setLocalScale((Vector3f)capsule.readSavable( + "localScale", null)); + ArrayList children = capsule.readSavableArrayList("children", null); if (children != null) { - for (Spatial child : children) { - attachChild(child); + for (Object child : children) { + attachChild((Spatial)child); } } } + @Override // documentation inherited + public void write (JMEExporter ex) + throws IOException + { + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(getName(), "name", null); + capsule.write(getLocalTranslation(), "localTranslation", null); + capsule.write(getLocalRotation(), "localRotation", null); + capsule.write(getLocalScale(), "localScale", null); + capsule.writeSavableArrayList(getChildren(), "children", null); + } + // documentation inherited from interface ModelSpatial public void expandModelBounds () { @@ -300,41 +303,6 @@ public class ModelNode extends Node return _forceCull; } - // documentation inherited from interface ModelSpatial - public void writeBuffers (FileChannel out) - throws IOException - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).writeBuffers(out); - } - } - } - - // documentation inherited from interface ModelSpatial - public void readBuffers (FileChannel in) - throws IOException - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).readBuffers(in); - } - } - } - - // documentation inherited from interface ModelSpatial - public void sliceBuffers (MappedByteBuffer map) - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).sliceBuffers(map); - } - } - } - /** * Sets the cull state of any nodes that do not contain geometric * descendants to {@link CULL_ALWAYS} so that they don't waste diff --git a/src/java/com/threerings/jme/model/ModelSpatial.java b/src/java/com/threerings/jme/model/ModelSpatial.java index bb85ce6d..2456f0f5 100644 --- a/src/java/com/threerings/jme/model/ModelSpatial.java +++ b/src/java/com/threerings/jme/model/ModelSpatial.java @@ -21,13 +21,6 @@ package com.threerings.jme.model; -import java.io.Externalizable; -import java.io.IOException; - -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; - -import com.jme.math.Matrix4f; import com.jme.renderer.Renderer; import com.jme.scene.Spatial; @@ -95,21 +88,4 @@ public interface ModelSpatial * to create a new instance */ public Spatial putClone (Spatial store, Model.CloneCreator properties); - - /** - * 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); } diff --git a/src/java/com/threerings/jme/model/Rotator.java b/src/java/com/threerings/jme/model/Rotator.java index 15fcbd0d..4054f8e0 100644 --- a/src/java/com/threerings/jme/model/Rotator.java +++ b/src/java/com/threerings/jme/model/Rotator.java @@ -22,8 +22,6 @@ package com.threerings.jme.model; import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; import java.util.Properties; @@ -31,6 +29,10 @@ import com.jme.math.Quaternion; import com.jme.math.Vector3f; import com.jme.scene.Controller; import com.jme.scene.Spatial; +import com.jme.util.export.JMEExporter; +import com.jme.util.export.JMEImporter; +import com.jme.util.export.InputCapsule; +import com.jme.util.export.OutputCapsule; import com.samskivert.util.StringUtil; @@ -97,24 +99,26 @@ public class Rotator extends ModelController return rstore; } - // documentation inherited from interface Externalizable - public void writeExternal (ObjectOutput out) + @Override // documentation inherited + public void read (JMEImporter im) throws IOException { - super.writeExternal(out); - out.writeObject(_axis); - out.writeFloat(_velocity); + super.read(im); + InputCapsule capsule = im.getCapsule(this); + _axis = (Vector3f)capsule.readSavable("axis", null); + _velocity = capsule.readFloat("velocity", 0f); } - // documentation inherited from interface Externalizable - public void readExternal (ObjectInput in) - throws IOException, ClassNotFoundException + @Override // documentation inherited + public void write (JMEExporter ex) + throws IOException { - super.readExternal(in); - _axis = (Vector3f)in.readObject(); - _velocity = in.readFloat(); + super.write(ex); + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(_axis, "axis", null); + capsule.write(_velocity, "velocity", 0f); } - + /** The axis about which to rotate. */ protected Vector3f _axis; diff --git a/src/java/com/threerings/jme/model/SkinMesh.java b/src/java/com/threerings/jme/model/SkinMesh.java index 5e366363..99f55658 100644 --- a/src/java/com/threerings/jme/model/SkinMesh.java +++ b/src/java/com/threerings/jme/model/SkinMesh.java @@ -22,9 +22,7 @@ package com.threerings.jme.model; import java.io.IOException; -import java.io.ObjectInput; import java.io.ObjectInputStream; -import java.io.ObjectOutput; import java.io.Serializable; import java.nio.ByteBuffer; @@ -45,6 +43,11 @@ import com.jme.scene.VBOInfo; import com.jme.scene.batch.SharedBatch; import com.jme.scene.batch.TriangleBatch; import com.jme.system.DisplaySystem; +import com.jme.util.export.JMEExporter; +import com.jme.util.export.JMEImporter; +import com.jme.util.export.InputCapsule; +import com.jme.util.export.OutputCapsule; +import com.jme.util.export.Savable; import com.jme.util.geom.BufferUtils; import com.samskivert.util.HashIntMap; @@ -59,7 +62,7 @@ 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 + implements Savable { /** The number of vertices in this weight group. */ public int vertexCount; @@ -89,12 +92,40 @@ public class SkinMesh extends ModelMesh return wgroup; } + // documentation inherited + public Class getClassTag () + { + return getClass(); + } + + // documentation inherited + public void read (JMEImporter im) + throws IOException + { + InputCapsule capsule = im.getCapsule(this); + vertexCount = capsule.readInt("vertexCount", 0); + Savable[] sbones = capsule.readSavableArray("bones", null); + bones = new Bone[sbones.length]; + System.arraycopy(sbones, 0, bones, 0, sbones.length); + weights = capsule.readFloatArray("weights", null); + } + + // documentation inherited + public void write (JMEExporter ex) + throws IOException + { + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(vertexCount, "vertexCount", 0); + capsule.write(bones, "bones", null); + capsule.write(weights, "weights", null); + } + private static final long serialVersionUID = 1; } /** Represents a bone that influences the mesh. */ public static class Bone - implements Serializable + implements Savable { /** The node that defines the bone's position. */ public ModelNode node; @@ -107,7 +138,12 @@ public class SkinMesh extends ModelMesh public Bone (ModelNode node) { + this(); this.node = node; + } + + public Bone () + { transform = new Matrix4f(); } @@ -124,16 +160,28 @@ public class SkinMesh extends ModelMesh return bone; } - /** - * Initializes the bone's transient state. - */ - private void readObject (ObjectInputStream in) - throws IOException, ClassNotFoundException + // documentation inherited + public Class getClassTag () { - in.defaultReadObject(); - transform = new Matrix4f(); + return getClass(); } - + + // documentation inherited + public void read (JMEImporter im) + throws IOException + { + InputCapsule capsule = im.getCapsule(this); + node = (ModelNode)capsule.readSavable("node", null); + } + + // documentation inherited + public void write (JMEExporter ex) + throws IOException + { + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(node, "node", null); + } + private static final long serialVersionUID = 1; } @@ -170,8 +218,8 @@ public class SkinMesh extends ModelMesh @Override // documentation inherited public void reconstruct ( - ByteBuffer vertices, ByteBuffer normals, ByteBuffer colors, - ByteBuffer textures, ByteBuffer indices) + FloatBuffer vertices, FloatBuffer normals, FloatBuffer colors, + FloatBuffer textures, IntBuffer indices) { super.reconstruct(vertices, normals, colors, textures, indices); @@ -218,19 +266,24 @@ public class SkinMesh extends ModelMesh } @Override // documentation inherited - public void writeExternal (ObjectOutput out) + public void read (JMEImporter im) throws IOException { - super.writeExternal(out); - out.writeObject(_weightGroups); + super.read(im); + InputCapsule capsule = im.getCapsule(this); + Savable[] swgroups = capsule.readSavableArray("weightGroups", null); + WeightGroup[] wgroups = new WeightGroup[swgroups.length]; + System.arraycopy(swgroups, 0, wgroups, 0, swgroups.length); + setWeightGroups(wgroups); } @Override // documentation inherited - public void readExternal (ObjectInput in) - throws IOException, ClassNotFoundException + public void write (JMEExporter ex) + throws IOException { - super.readExternal(in); - setWeightGroups((WeightGroup[])in.readObject()); + super.write(ex); + OutputCapsule capsule = ex.getCapsule(this); + capsule.write(_weightGroups, "weightGroups", null); } @Override // documentation inherited diff --git a/src/java/com/threerings/jme/tools/ModelDef.java b/src/java/com/threerings/jme/tools/ModelDef.java index 713640a9..ad66c0b7 100644 --- a/src/java/com/threerings/jme/tools/ModelDef.java +++ b/src/java/com/threerings/jme/tools/ModelDef.java @@ -199,23 +199,17 @@ public class ModelDef // set the various buffers int vsize = vertices.size(); - ByteOrder no = ByteOrder.nativeOrder(); - ByteBuffer vbbuf = ByteBuffer.allocateDirect(vsize*3*4).order(no), - nbbuf = ByteBuffer.allocateDirect(vsize*3*4).order(no), - tbbuf = tcoords ? - ByteBuffer.allocateDirect(vsize*2*4).order(no) : null, - ibbuf = ByteBuffer.allocateDirect(indices.size()*4).order(no); - FloatBuffer vbuf = vbbuf.asFloatBuffer(), - nbuf = nbbuf.asFloatBuffer(), - tbuf = tcoords ? tbbuf.asFloatBuffer() : null; + FloatBuffer vbuf = BufferUtils.createVector3Buffer(vsize), + nbuf = BufferUtils.createVector3Buffer(vsize), + tbuf = tcoords ? BufferUtils.createVector2Buffer(vsize) : null; for (int ii = 0; ii < vsize; ii++) { vertices.get(ii).setInBuffers(vbuf, nbuf, tbuf); } - IntBuffer ibuf = ibbuf.asIntBuffer(); + IntBuffer ibuf = BufferUtils.createIntBuffer(indices.size()); for (int ii = 0, nn = indices.size(); ii < nn; ii++) { ibuf.put(indices.get(ii)); } - _mesh.reconstruct(vbbuf, nbbuf, null, tbbuf, ibbuf); + _mesh.reconstruct(vbuf, nbuf, null, tbuf, ibuf); _mesh.setModelBound("sphere".equals(props.getProperty("bound")) ? new BoundingSphere() : new BoundingBox()); diff --git a/src/java/com/threerings/jme/tools/ModelViewer.java b/src/java/com/threerings/jme/tools/ModelViewer.java index b4907865..f43517e0 100644 --- a/src/java/com/threerings/jme/tools/ModelViewer.java +++ b/src/java/com/threerings/jme/tools/ModelViewer.java @@ -624,7 +624,7 @@ public class ModelViewer extends JmeCanvasApp throws IOException { _status.setText(_msg.get("m.loading_model", file)); - setModel(Model.readFromFile(file, false), file); + setModel(Model.readFromFile(file), file); } /**