diff --git a/src/java/com/threerings/jme/model/EmissionController.java b/src/java/com/threerings/jme/model/EmissionController.java index 8512b9871..73e22bc0f 100644 --- a/src/java/com/threerings/jme/model/EmissionController.java +++ b/src/java/com/threerings/jme/model/EmissionController.java @@ -58,7 +58,7 @@ public abstract class EmissionController extends ModelController */ protected void getEmitterLocation (Vector3f result) { - result.set(_target.getWorldBound().getCenter()); + result.set(_target.getWorldTranslation()); } /** diff --git a/src/java/com/threerings/jme/model/Model.java b/src/java/com/threerings/jme/model/Model.java index 52e4350ba..c9fb6e2a1 100644 --- a/src/java/com/threerings/jme/model/Model.java +++ b/src/java/com/threerings/jme/model/Model.java @@ -233,10 +233,8 @@ public class Model extends ModelNode FileChannel fc = fis.getChannel(); if (map) { long pos = fc.position(); - MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, - pos, fc.size() - pos); - buf.order(ByteOrder.LITTLE_ENDIAN); - model.sliceBuffers(buf); + model.sliceBuffers(fc.map(FileChannel.MapMode.READ_ONLY, + pos, fc.size() - pos)); } else { model.readBuffers(fc); } @@ -343,6 +341,9 @@ public class Model extends ModelNode */ public Animation getAnimation (String name) { + if (_anims == null) { + return null; + } Animation anim = _anims.get(name); if (anim != null) { return anim; diff --git a/src/java/com/threerings/jme/model/ModelMesh.java b/src/java/com/threerings/jme/model/ModelMesh.java index b6cd2737c..99ab60ee0 100644 --- a/src/java/com/threerings/jme/model/ModelMesh.java +++ b/src/java/com/threerings/jme/model/ModelMesh.java @@ -128,25 +128,18 @@ public class ModelMesh extends TriMesh // initialize the model if we're displaying if (DisplaySystem.getDisplaySystem() == null) { return; - } + } if (_backCull == null) { initSharedStates(); } if (_solid) { setRenderState(_backCull); - } else { - setRenderState(_noCull); } if (_transparent) { setRenderQueueMode(Renderer.QUEUE_TRANSPARENT); setRenderState(_blendAlpha); setRenderState(_overlayZBuffer); - } else { - setRenderQueueMode(Renderer.QUEUE_OPAQUE); - setRenderState(_noAlpha); - setRenderState(_lequalZBuffer); } - setTextureCombineMode(TextureState.REPLACE); } /** @@ -432,15 +425,11 @@ public class ModelMesh extends TriMesh Renderer renderer = DisplaySystem.getDisplaySystem().getRenderer(); _backCull = renderer.createCullState(); _backCull.setCullMode(CullState.CS_BACK); - _noCull = renderer.createCullState(); _blendAlpha = renderer.createAlphaState(); _blendAlpha.setBlendEnabled(true); - _noAlpha = renderer.createAlphaState(); _overlayZBuffer = renderer.createZBufferState(); _overlayZBuffer.setFunction(ZBufferState.CF_LEQUAL); _overlayZBuffer.setWritable(false); - _lequalZBuffer = renderer.createZBufferState(); - _lequalZBuffer.setFunction(ZBufferState.CF_LEQUAL); } /** The sizes of the various buffers (zero for null). */ @@ -469,21 +458,12 @@ public class ModelMesh extends TriMesh /** The shared state for back face culling. */ protected static CullState _backCull; - /** The shared state for no back face culling. */ - protected static CullState _noCull; - /** The shared state for alpha blending. */ protected static AlphaState _blendAlpha; - /** The shared state for no blending. */ - protected static AlphaState _noAlpha; - /** The shared state for checking, but not writing to, the z buffer. */ protected static ZBufferState _overlayZBuffer; - /** The shared state for checking and writing to the z buffer. */ - protected static ZBufferState _lequalZBuffer; - /** Indicates that this mesh should use a bounding box. */ protected static final int BOX_BOUND = 0; diff --git a/src/java/com/threerings/jme/tools/ModelDef.java b/src/java/com/threerings/jme/tools/ModelDef.java index b6c9c0a60..a4fc29bdb 100644 --- a/src/java/com/threerings/jme/tools/ModelDef.java +++ b/src/java/com/threerings/jme/tools/ModelDef.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; import java.util.Properties; @@ -90,11 +91,13 @@ public class ModelDef public abstract Spatial createSpatial (Properties props); /** Resolves any name references using the supplied map. */ - public void resolveReferences (HashMap nodes) + public void resolveReferences ( + HashMap nodes, HashSet referenced) { 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 + "]."); @@ -226,9 +229,10 @@ public class ModelDef } @Override // documentation inherited - public void resolveReferences (HashMap nodes) + public void resolveReferences ( + HashMap nodes, HashSet referenced) { - super.resolveReferences(nodes); + super.resolveReferences(nodes, referenced); if (_mesh == null) { return; } @@ -258,6 +262,7 @@ public class ModelDef SkinMesh.WeightGroup wgroup = new SkinMesh.WeightGroup(); wgroup.indices = toArray(entry.getValue().indices); HashSet bones = entry.getKey(); + referenced.addAll(bones); wgroup.bones = bones.toArray(new ModelNode[bones.size()]); wgroup.weights = toArray(entry.getValue().weights); wgroups[ii++] = wgroup; @@ -403,9 +408,10 @@ public class ModelDef // then go through again, resolving any name references and attaching // root children + HashSet referenced = new HashSet(); for (int ii = 0, nn = spatials.size(); ii < nn; ii++) { SpatialDef sdef = spatials.get(ii); - sdef.resolveReferences(nodes); + sdef.resolveReferences(nodes, referenced); if (sdef.getSpatial(props).getParent() == null) { model.attachChild(sdef.getSpatial(props)); } @@ -429,6 +435,9 @@ public class ModelDef } } + // get rid of any nodes that serve no purpose + pruneUnusedNodes(model, referenced); + return model; } @@ -450,6 +459,23 @@ public class ModelDef return ctrl; } + /** Recursively removes any unused nodes. */ + protected boolean pruneUnusedNodes ( + ModelNode node, HashSet referenced) + { + boolean hasValidChildren = false; + for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) { + Spatial child = (Spatial)it.next(); + if (!(child instanceof ModelNode) || + pruneUnusedNodes((ModelNode)child, referenced)) { + hasValidChildren = true; + } else { + it.remove(); + } + } + return referenced.contains(node) || hasValidChildren; + } + /** Converts a boxed Integer list to an unboxed int array. */ protected static int[] toArray (ArrayList list) {