diff --git a/src/java/com/threerings/jme/model/Model.java b/src/java/com/threerings/jme/model/Model.java index 37b0e013f..cb3988b1a 100644 --- a/src/java/com/threerings/jme/model/Model.java +++ b/src/java/com/threerings/jme/model/Model.java @@ -175,6 +175,13 @@ public class Model extends ModelNode _scale = scale; } + public void apply (Spatial target) + { + target.getLocalTranslation().set(_translation); + target.getLocalRotation().set(_rotation); + target.getLocalScale().set(_scale); + } + /** * Blends between this transform and the next, applying the result to * the given target. @@ -297,6 +304,31 @@ public class Model extends ModelNode _anims = new HashMap(); } _anims.put(name, anim); + + // store the original transforms + Transform[] oxforms = new Transform[anim.transformTargets.length]; + for (int ii = 0; ii < anim.transformTargets.length; ii++) { + Spatial target = anim.transformTargets[ii]; + oxforms[ii] = new Transform( + new Vector3f(target.getLocalTranslation()), + new Quaternion(target.getLocalRotation()), + new Vector3f(target.getLocalScale())); + } + + // run through every frame of the animation, expanding the bounding + // volumes of any deformable meshes + for (int ii = 0; ii < anim.transforms.length; ii++) { + for (int jj = 0; jj < anim.transforms[ii].length; jj++) { + anim.transforms[ii][jj].apply(anim.transformTargets[jj]); + } + updateWorldData(0f); + expandModelBounds(); + } + + // restore the original transforms + for (int ii = 0; ii < anim.transformTargets.length; ii++) { + oxforms[ii].apply(anim.transformTargets[ii]); + } } /** @@ -447,7 +479,15 @@ public class Model extends ModelNode public void writeExternal (ObjectOutput out) throws IOException { + // don't serialize the emission node; it contains transient geometry + // created by controllers + if (_emissionNode != null) { + detachChild(_emissionNode); + } super.writeExternal(out); + if (_emissionNode != null) { + attachChild(_emissionNode); + } out.writeObject(_props); out.writeObject(_anims); out.writeObject(getControllers()); diff --git a/src/java/com/threerings/jme/model/ModelMesh.java b/src/java/com/threerings/jme/model/ModelMesh.java index f0d44ccfa..68cbdb926 100644 --- a/src/java/com/threerings/jme/model/ModelMesh.java +++ b/src/java/com/threerings/jme/model/ModelMesh.java @@ -35,8 +35,7 @@ import java.nio.channels.FileChannel; import java.util.Properties; -import com.jme.bounding.BoundingBox; -import com.jme.bounding.BoundingSphere; +import com.jme.bounding.BoundingVolume; import com.jme.math.Quaternion; import com.jme.math.Vector3f; import com.jme.renderer.CloneCreator; @@ -89,8 +88,7 @@ public class ModelMesh extends TriMesh public void configure ( boolean solid, String texture, boolean transparent, Properties props) { - _boundingType = "sphere".equals(props.getProperty("bound")) ? - SPHERE_BOUND : BOX_BOUND; + _textures = (texture == null) ? null : StringUtil.parseStringArray( props.getProperty(texture, texture)); _solid = solid; @@ -118,13 +116,6 @@ public class ModelMesh extends TriMesh _textureByteBuffer = textures; _indexByteBuffer = indices; - if (_boundingType == BOX_BOUND) { - setModelBound(new BoundingBox()); - } else { // _boundingType == SPHERE_BOUND - setModelBound(new BoundingSphere()); - } - updateModelBound(); - // initialize the model if we're displaying if (DisplaySystem.getDisplaySystem() == null) { return; @@ -231,12 +222,12 @@ public class ModelMesh extends TriMesh out.writeObject(getLocalTranslation()); out.writeObject(getLocalRotation()); out.writeObject(getLocalScale()); + out.writeObject(getModelBound()); out.writeInt(_vertexBufferSize); out.writeInt(_normalBufferSize); out.writeInt(_colorBufferSize); out.writeInt(_textureBufferSize); out.writeInt(_indexBufferSize); - out.writeInt(_boundingType); out.writeObject(_textures); out.writeBoolean(_solid); out.writeBoolean(_transparent); @@ -250,17 +241,23 @@ public class ModelMesh extends TriMesh 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(); - _boundingType = in.readInt(); _textures = (String[])in.readObject(); _solid = in.readBoolean(); _transparent = in.readBoolean(); } + // documentation inherited from interface ModelSpatial + public void expandModelBounds () + { + // no-op + } + // documentation inherited from interface ModelSpatial public void setReferenceTransforms () { @@ -489,11 +486,5 @@ public class ModelMesh extends TriMesh /** The shared state for checking, but not writing to, the z buffer. */ protected static ZBufferState _overlayZBuffer; - /** Indicates that this mesh should use a bounding box. */ - protected static final int BOX_BOUND = 0; - - /** Indicates that this mesh should use a bounding sphere. */ - protected static final int SPHERE_BOUND = 1; - private static final long serialVersionUID = 1; } diff --git a/src/java/com/threerings/jme/model/ModelNode.java b/src/java/com/threerings/jme/model/ModelNode.java index cd847b1b3..166299a8f 100644 --- a/src/java/com/threerings/jme/model/ModelNode.java +++ b/src/java/com/threerings/jme/model/ModelNode.java @@ -103,6 +103,16 @@ public class ModelNode extends Node } } + @Override // documentation inherited + public void updateWorldBound () + { + // if the node is culled, there are no mesh descendants and thus no + // bounds + if (cullMode != CULL_ALWAYS) { + super.updateWorldBound(); + } + } + @Override // documentation inherited public void updateWorldVectors () { @@ -159,6 +169,16 @@ public class ModelNode extends Node } } + // documentation inherited from interface ModelSpatial + public void expandModelBounds () + { + for (Object child : getChildren()) { + if (child instanceof ModelSpatial) { + ((ModelSpatial)child).expandModelBounds(); + } + } + } + // documentation inherited from interface ModelSpatial public void setReferenceTransforms () { diff --git a/src/java/com/threerings/jme/model/ModelSpatial.java b/src/java/com/threerings/jme/model/ModelSpatial.java index b73ee1d77..030a9092c 100644 --- a/src/java/com/threerings/jme/model/ModelSpatial.java +++ b/src/java/com/threerings/jme/model/ModelSpatial.java @@ -36,6 +36,12 @@ import com.jme.scene.Spatial; */ public interface ModelSpatial { + /** + * Recursively expands the model bounds of any deformable meshes so that + * they include the current vertex positions. + */ + public void expandModelBounds (); + /** * Recursively sets the reference transforms for any bones in the model. */ diff --git a/src/java/com/threerings/jme/model/SkinMesh.java b/src/java/com/threerings/jme/model/SkinMesh.java index b2c12f46d..f233b4790 100644 --- a/src/java/com/threerings/jme/model/SkinMesh.java +++ b/src/java/com/threerings/jme/model/SkinMesh.java @@ -32,6 +32,7 @@ import java.nio.IntBuffer; import java.util.HashMap; +import com.jme.bounding.BoundingVolume; import com.jme.math.Matrix4f; import com.jme.math.Vector3f; import com.jme.renderer.CloneCreator; @@ -184,6 +185,14 @@ public class SkinMesh extends ModelMesh _weightGroups = (WeightGroup[])in.readObject(); } + @Override // documentation inherited + public void expandModelBounds () + { + BoundingVolume obound = (BoundingVolume)getModelBound().clone(null); + updateModelBound(); + getModelBound().mergeLocal(obound); + } + @Override // documentation inherited public void setReferenceTransforms () { @@ -280,7 +289,6 @@ public class SkinMesh extends ModelMesh BufferUtils.setInBuffer(_normal, nbuf, idx); } } - updateModelBound(); } /** diff --git a/src/java/com/threerings/jme/tools/CompileModelTask.java b/src/java/com/threerings/jme/tools/CompileModelTask.java index b92e61e4a..5049d974f 100644 --- a/src/java/com/threerings/jme/tools/CompileModelTask.java +++ b/src/java/com/threerings/jme/tools/CompileModelTask.java @@ -39,6 +39,7 @@ import org.apache.tools.ant.types.FileSet; import com.jme.scene.Spatial; import com.jme.util.LoggingSystem; +import com.jmex.model.XMLparser.Converters.DummyDisplaySystem; import com.samskivert.util.PropertiesUtil; import com.samskivert.util.StringUtil; @@ -103,6 +104,7 @@ public class CompileModelTask extends Task ModelDef mdef = _mparser.parseModel(content.toString()); HashMap nodes = new HashMap(); Model model = mdef.createModel(props, nodes); + model.initPrototype(); // load the animations, if any for (int ii = 0; ii < anims.length; ii++) { @@ -122,11 +124,16 @@ public class CompileModelTask extends Task _filesets.add(set); } + public void init () throws BuildException + { + // create a dummy display system + new DummyDisplaySystem(); + LoggingSystem.getLogger().setLevel(Level.WARNING); + } + public void execute () throws BuildException { - LoggingSystem.getLoggingSystem().setLevel(Level.WARNING); - for (int ii = 0, nn = _filesets.size(); ii < nn; ii++) { FileSet fs = _filesets.get(ii); DirectoryScanner ds = fs.getDirectoryScanner(getProject()); diff --git a/src/java/com/threerings/jme/tools/ModelDef.java b/src/java/com/threerings/jme/tools/ModelDef.java index 7892f8225..628170c5f 100644 --- a/src/java/com/threerings/jme/tools/ModelDef.java +++ b/src/java/com/threerings/jme/tools/ModelDef.java @@ -34,6 +34,8 @@ import java.util.Iterator; import java.util.Map; import java.util.Properties; +import com.jme.bounding.BoundingBox; +import com.jme.bounding.BoundingSphere; import com.jme.math.FastMath; import com.jme.scene.Spatial; import com.jme.util.geom.BufferUtils; @@ -49,7 +51,8 @@ import com.threerings.jme.model.ModelNode; import com.threerings.jme.model.SkinMesh; /** - * An intermediate representation for model nodes using in XML parsing. + * An intermediate representation for models used to store data parsed from + * XML and convert it into JME nodes. */ public class ModelDef { @@ -211,6 +214,10 @@ public class ModelDef } _mesh.reconstruct(vbbuf, nbbuf, null, tbbuf, ibbuf); + _mesh.setModelBound("sphere".equals(props.getProperty("bound")) ? + new BoundingSphere() : new BoundingBox()); + _mesh.updateModelBound(); + // set the mesh's origin to the center of its bounding box _mesh.centerVertices(); } diff --git a/src/java/com/threerings/jme/tools/ModelViewer.java b/src/java/com/threerings/jme/tools/ModelViewer.java index d3201c406..2a7d51273 100644 --- a/src/java/com/threerings/jme/tools/ModelViewer.java +++ b/src/java/com/threerings/jme/tools/ModelViewer.java @@ -423,7 +423,6 @@ public class ModelViewer extends JmeCanvasApp _status.setText(_msg.get("m.compiling_model", file)); Model model = CompileModelTask.compileModel(file); if (model != null) { - model.initPrototype(); setModel(model, file); return; } @@ -456,7 +455,6 @@ public class ModelViewer extends JmeCanvasApp } _ctx.getGeometry().attachChild(_model = model); _model.lockStaticMeshes(_ctx.getRenderer(), true, true); - _model.getLocalTranslation().set(-20f, 0f, 0f); // resolve the textures from the file's directory final File dir = file.getParentFile();