diff --git a/src/java/com/threerings/jme/JmeApp.java b/src/java/com/threerings/jme/JmeApp.java index 20ddad542..d80cc5d29 100644 --- a/src/java/com/threerings/jme/JmeApp.java +++ b/src/java/com/threerings/jme/JmeApp.java @@ -91,7 +91,7 @@ public class JmeApp } // create an appropriate timer - _timer = Timer.getTimer(_api); + _timer = Timer.getTimer(); // start with the target FPS equal to the refresh rate (but // sometimes the refresh rate is reported as zero so don't let that diff --git a/src/java/com/threerings/jme/model/EmissionController.java b/src/java/com/threerings/jme/model/EmissionController.java index 73e22bc0f..26907cdb1 100644 --- a/src/java/com/threerings/jme/model/EmissionController.java +++ b/src/java/com/threerings/jme/model/EmissionController.java @@ -68,7 +68,7 @@ public abstract class EmissionController extends ModelController { if (_target instanceof Geometry) { BufferUtils.populateFromBuffer(result, - ((Geometry)_target).getNormalBuffer(), 0); + ((Geometry)_target).getNormalBuffer(0), 0); } else { result.set(0f, 0f, -1f); } diff --git a/src/java/com/threerings/jme/model/Model.java b/src/java/com/threerings/jme/model/Model.java index b97e02b29..cb0a63088 100644 --- a/src/java/com/threerings/jme/model/Model.java +++ b/src/java/com/threerings/jme/model/Model.java @@ -49,7 +49,6 @@ import com.jme.math.Matrix4f; import com.jme.math.Quaternion; import com.jme.math.Vector3f; import com.jme.renderer.Camera; -import com.jme.renderer.CloneCreator; import com.jme.renderer.Renderer; import com.jme.scene.Controller; import com.jme.scene.Node; @@ -222,6 +221,71 @@ public class Model extends ModelNode private static final long serialVersionUID = 1; } + /** Customized clone creator for models. */ + public static class CloneCreator + { + /** A shared seed used to select textures consistently. */ + public int random; + + /** Maps original objects to their copies. */ + public HashMap originalToCopy = new HashMap(); + + public CloneCreator (Model toCopy) + { + _toCopy = toCopy; + addProperty("vertices"); + addProperty("colors"); + addProperty("normals"); + addProperty("texcoords"); + addProperty("vboinfo"); + addProperty("indices"); + addProperty("obbtree"); + addProperty("displaylistid"); + addProperty("bound"); + } + + /** + * Sets the named property. + */ + public void addProperty (String name) + { + _properties.add(name); + } + + /** + * Clears the named property. + */ + public void removeProperty (String name) + { + _properties.remove(name); + } + + /** + * Checks whether the named property has been set. + */ + public boolean isSet (String name) + { + return _properties.contains(name); + } + + /** + * Creates a new copy of the target model. + */ + public Model createCopy () + { + random = RandomUtil.getInt(Integer.MAX_VALUE); + Model copy = (Model)_toCopy.putClone(null, this); + originalToCopy.clear(); // make sure no references remain + return copy; + } + + /** The model to copy. */ + protected Model _toCopy; + + /** The set of added properties. */ + protected HashSet _properties = new HashSet(); + } + /** * Attempts to read a model from the specified file. * @@ -464,8 +528,13 @@ public class Model extends ModelNode public Node getEmissionNode () { if (_emissionNode == null) { - attachChild(_emissionNode = new Node("emissions")); - _emissionNode.setTransformable(false); + attachChild(_emissionNode = new Node("emissions") { + public void updateWorldVectors () { + worldTranslation.set(localTranslation); + worldRotation.set(localRotation); + worldScale.set(localScale); + } + }); } return _emissionNode; } @@ -530,30 +599,17 @@ public class Model extends ModelNode } /** - * Creates and returns a new instance of this model's default - * variant. - */ + * Creates and returns a new instance of this model. + */ public Model createInstance () - { - return createInstance(null); - } - - /** - * Creates and returns a new instance of this model. - * - * @param variant the name of the variant desired, or null - * for the default variant - */ - public Model createInstance (String variant) { if (_prototype != null) { - return _prototype.createInstance(variant); + return _prototype.createInstance(); } if (_ccreator == null) { - _ccreator = new ModelCloneCreator(this); + _ccreator = new CloneCreator(this); } - _ccreator.variant = variant; - Model instance = (Model)_ccreator.createCopy(); + Model instance = _ccreator.createCopy(); instance.initInstance(); return instance; } @@ -764,7 +820,7 @@ public class Model extends ModelNode /** For prototype models, a customized clone creator used to generate * instances. */ - protected ModelCloneCreator _ccreator; + protected CloneCreator _ccreator; /** For instances, maps prototype nodes to their corresponding instance * nodes. */ @@ -872,50 +928,7 @@ public class Model extends ModelNode protected String _name; } - /** Customized clone creator for models. */ - protected static class ModelCloneCreator extends CloneCreator - { - /** The model variant desired, or null for the default. */ - public String variant; - - /** A shared seed used to select textures consistently. */ - public int random; - - public ModelCloneCreator (Model toCopy) - { - super(toCopy); - addProperty("vertices"); - addProperty("colors"); - addProperty("normals"); - addProperty("texcoords"); - addProperty("vboinfo"); - addProperty("indices"); - addProperty("obbtree"); - addProperty("displaylistid"); - addProperty("bound"); - } - - @Override // documentation inherited - public void addProperty (String name) - { - props.put(name, Boolean.TRUE); - } - - @Override // documentation inherited - public void removeProperty (String name) - { - props.remove(name); - } - - @Override // documentation inherited - public Spatial createCopy () - { - random = RandomUtil.getInt(Integer.MAX_VALUE); - Spatial copy = super.createCopy(); - originalToCopy.clear(); // make sure no references remain - return copy; - } - } + private static final long serialVersionUID = 1; } diff --git a/src/java/com/threerings/jme/model/ModelController.java b/src/java/com/threerings/jme/model/ModelController.java index cfe7f3683..f129c7f71 100644 --- a/src/java/com/threerings/jme/model/ModelController.java +++ b/src/java/com/threerings/jme/model/ModelController.java @@ -30,7 +30,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.Properties; -import com.jme.renderer.CloneCreator; import com.jme.scene.Controller; import com.jme.scene.Node; import com.jme.scene.Spatial; @@ -85,18 +84,21 @@ public abstract class ModelController extends Controller } } - @Override // documentation inherited - public Controller putClone (Controller store, CloneCreator properties) + /** + * Creates or populates and returns a clone of this object using the given + * clone properties. + * + * @param store an instance of this class to populate, or null + * to create a new instance + */ + public Controller putClone ( + Controller store, Model.CloneCreator properties) { if (store == null) { return null; } ModelController mstore = (ModelController)store; - mstore._target = (Spatial)properties.originalToCopy.get(_target); - if (mstore._target == null) { - properties.originalToCopy.put(_target, - mstore._target = _target.putClone(null, properties)); - } + mstore._target = ((ModelSpatial)_target).putClone(null, properties); mstore._animations = _animations; return mstore; } diff --git a/src/java/com/threerings/jme/model/ModelMesh.java b/src/java/com/threerings/jme/model/ModelMesh.java index d31417436..40915e39d 100644 --- a/src/java/com/threerings/jme/model/ModelMesh.java +++ b/src/java/com/threerings/jme/model/ModelMesh.java @@ -38,14 +38,16 @@ import java.util.Properties; import com.jme.bounding.BoundingVolume; import com.jme.math.Quaternion; import com.jme.math.Vector3f; -import com.jme.renderer.CloneCreator; import com.jme.renderer.Renderer; +import com.jme.scene.Controller; import com.jme.scene.SharedMesh; import com.jme.scene.Spatial; import com.jme.scene.TriMesh; import com.jme.scene.VBOInfo; +import com.jme.scene.batch.TriangleBatch; import com.jme.scene.state.AlphaState; import com.jme.scene.state.CullState; +import com.jme.scene.state.RenderState; import com.jme.scene.state.TextureState; import com.jme.scene.state.ZBufferState; import com.jme.system.DisplaySystem; @@ -138,11 +140,11 @@ public class ModelMesh extends TriMesh */ public void centerVertices () { - Vector3f offset = getModelBound().getCenter().negate(); + Vector3f offset = getBatch(0).getModelBound().getCenter().negate(); if (!offset.equals(Vector3f.ZERO)) { getLocalTranslation().subtractLocal(offset); - getModelBound().getCenter().set(Vector3f.ZERO); - getBatch().translatePoints(offset); + getBatch(0).getModelBound().getCenter().set(Vector3f.ZERO); + getBatch(0).translatePoints(offset); } } @@ -173,8 +175,8 @@ public class ModelMesh extends TriMesh _textureBufferSize = (textures == null) ? 0 : textures.capacity(); } - @Override // documentation inherited - public Spatial putClone (Spatial store, CloneCreator properties) + // documentation inherited from interface ModelSpatial + public Spatial putClone (Spatial store, Model.CloneCreator properties) { ModelMesh mstore = (ModelMesh)properties.originalToCopy.get(this); if (mstore != null) { @@ -184,17 +186,65 @@ public class ModelMesh extends TriMesh } else { mstore = (ModelMesh)store; } - super.putClone(mstore, properties); + properties.originalToCopy.put(this, mstore); + mstore.normalsMode = normalsMode; + mstore.cullMode = cullMode; + for (int ii = 0; ii < RenderState.RS_MAX_STATE; ii++) { + RenderState rstate = getRenderState(ii); + if (rstate != null) { + mstore.setRenderState(rstate); + } + } + mstore.renderQueueMode = renderQueueMode; + mstore.lockedMode = lockedMode; + mstore.lightCombineMode = lightCombineMode; + mstore.textureCombineMode = textureCombineMode; + mstore.name = name; + mstore.isCollidable = isCollidable; + mstore.localRotation.set(localRotation); + mstore.localTranslation.set(localTranslation); + mstore.localScale.set(localScale); + for (Object controller : getControllers()) { + if (controller instanceof ModelController) { + mstore.addController( + ((ModelController)controller).putClone(null, properties)); + } + } + TriangleBatch batch = (TriangleBatch)getBatch(0), + mbatch = (TriangleBatch)mstore.getBatch(0); + mbatch.setVertexBuffer(properties.isSet("vertices") ? + batch.getVertexBuffer() : + BufferUtils.clone(batch.getVertexBuffer())); + mbatch.setColorBuffer(properties.isSet("colors") ? + batch.getColorBuffer() : + BufferUtils.clone(batch.getColorBuffer())); + mbatch.setNormalBuffer(properties.isSet("normals") ? + batch.getNormalBuffer() : + BufferUtils.clone(batch.getNormalBuffer())); + FloatBuffer texcoords; + for (int ii = 0; (texcoords = batch.getTextureBuffer(ii)) != null; + ii++) { + mbatch.setTextureBuffer(properties.isSet("texcoords") ? + texcoords : BufferUtils.clone(texcoords), ii); + } + mbatch.setIndexBuffer(properties.isSet("indices") ? + batch.getIndexBuffer() : + BufferUtils.clone(batch.getIndexBuffer())); + if (properties.isSet("vboinfo")) { + mbatch.setVBOInfo(batch.getVBOInfo()); + } + if (properties.isSet("obbtree")) { + mbatch.setCollisionTree(batch.getCollisionTree()); + } if (properties.isSet("displaylistid")) { - mstore.batch.setDisplayListID(getDisplayListID()); + mbatch.setDisplayListID(batch.getDisplayListID()); } - if (properties.isSet("bound")) { - mstore.setModelBound(getModelBound()); + if (batch.getModelBound() != null) { + mbatch.setModelBound(properties.isSet("bound") ? + batch.getModelBound() : batch.getModelBound().clone(null)); } - if (_textures != null && _textures.length > 1 && - properties instanceof Model.ModelCloneCreator) { - int tidx = ((Model.ModelCloneCreator)properties).random % - _textures.length; + if (_textures != null && _textures.length > 1) { + int tidx = properties.random % _textures.length; mstore._textures = new String[] { _textures[tidx] }; mstore._tstates = new TextureState[] { _tstates[tidx] }; mstore.setRenderState(_tstates[tidx]); @@ -221,7 +271,7 @@ public class ModelMesh extends TriMesh out.writeObject(getLocalTranslation()); out.writeObject(getLocalRotation()); out.writeObject(getLocalScale()); - out.writeObject(getModelBound()); + out.writeObject(getBatch(0).getModelBound()); out.writeInt(_vertexBufferSize); out.writeInt(_normalBufferSize); out.writeInt(_colorBufferSize); diff --git a/src/java/com/threerings/jme/model/ModelNode.java b/src/java/com/threerings/jme/model/ModelNode.java index 166299a8f..ccc2841fd 100644 --- a/src/java/com/threerings/jme/model/ModelNode.java +++ b/src/java/com/threerings/jme/model/ModelNode.java @@ -36,10 +36,11 @@ import java.util.HashSet; import com.jme.math.Matrix4f; import com.jme.math.Quaternion; import com.jme.math.Vector3f; -import com.jme.renderer.CloneCreator; import com.jme.renderer.Renderer; +import com.jme.scene.Controller; import com.jme.scene.Node; import com.jme.scene.Spatial; +import com.jme.scene.state.RenderState; import com.threerings.jme.Log; @@ -128,8 +129,8 @@ public class ModelNode extends Node } } - @Override // documentation inherited - public Spatial putClone (Spatial store, CloneCreator properties) + // documentation inherited from interface ModelSpatial + public Spatial putClone (Spatial store, Model.CloneCreator properties) { ModelNode mstore = (ModelNode)properties.originalToCopy.get(this); if (mstore != null) { @@ -139,8 +140,37 @@ public class ModelNode extends Node } else { mstore = (ModelNode)store; } - super.putClone(mstore, properties); + properties.originalToCopy.put(this, mstore); + mstore.normalsMode = normalsMode; mstore.cullMode = cullMode; + for (int ii = 0; ii < RenderState.RS_MAX_STATE; ii++) { + RenderState rstate = getRenderState(ii); + if (rstate != null) { + mstore.setRenderState(rstate); + } + } + mstore.renderQueueMode = renderQueueMode; + mstore.lockedMode = lockedMode; + mstore.lightCombineMode = lightCombineMode; + mstore.textureCombineMode = textureCombineMode; + mstore.name = name; + mstore.isCollidable = isCollidable; + mstore.localRotation.set(localRotation); + mstore.localTranslation.set(localTranslation); + mstore.localScale.set(localScale); + for (Object controller : getControllers()) { + if (controller instanceof ModelController) { + mstore.addController( + ((ModelController)controller).putClone(null, properties)); + } + } + for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { + Spatial child = getChild(ii); + if (child instanceof ModelSpatial) { + mstore.attachChild( + ((ModelSpatial)child).putClone(null, properties)); + } + } return mstore; } @@ -163,16 +193,19 @@ public class ModelNode extends Node 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)); + ArrayList children = (ArrayList)in.readObject(); + if (children != null) { + for (Spatial child : children) { + attachChild(child); + } } } // documentation inherited from interface ModelSpatial public void expandModelBounds () { - for (Object child : getChildren()) { + for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { + Spatial child = getChild(ii); if (child instanceof ModelSpatial) { ((ModelSpatial)child).expandModelBounds(); } @@ -183,10 +216,11 @@ public class ModelNode extends Node public void setReferenceTransforms () { updateWorldVectors(); - for (Object child : getChildren()) { + for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { + Spatial child = getChild(ii); if (child instanceof ModelSpatial) { ((ModelSpatial)child).setReferenceTransforms(); - } + } } } @@ -194,7 +228,8 @@ public class ModelNode extends Node public void lockStaticMeshes ( Renderer renderer, boolean useVBOs, boolean useDisplayLists) { - for (Object child : getChildren()) { + for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { + Spatial child = getChild(ii); if (child instanceof ModelSpatial) { ((ModelSpatial)child).lockStaticMeshes(renderer, useVBOs, useDisplayLists); @@ -205,7 +240,8 @@ public class ModelNode extends Node // documentation inherited from interface ModelSpatial public void resolveTextures (TextureProvider tprov) { - for (Object child : getChildren()) { + for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { + Spatial child = getChild(ii); if (child instanceof ModelSpatial) { ((ModelSpatial)child).resolveTextures(tprov); } @@ -216,7 +252,8 @@ public class ModelNode extends Node public void writeBuffers (FileChannel out) throws IOException { - for (Object child : getChildren()) { + for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { + Spatial child = getChild(ii); if (child instanceof ModelSpatial) { ((ModelSpatial)child).writeBuffers(out); } @@ -227,7 +264,8 @@ public class ModelNode extends Node public void readBuffers (FileChannel in) throws IOException { - for (Object child : getChildren()) { + for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { + Spatial child = getChild(ii); if (child instanceof ModelSpatial) { ((ModelSpatial)child).readBuffers(in); } @@ -237,7 +275,8 @@ public class ModelNode extends Node // documentation inherited from interface ModelSpatial public void sliceBuffers (MappedByteBuffer map) { - for (Object child : getChildren()) { + for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { + Spatial child = getChild(ii); if (child instanceof ModelSpatial) { ((ModelSpatial)child).sliceBuffers(map); } diff --git a/src/java/com/threerings/jme/model/ModelSpatial.java b/src/java/com/threerings/jme/model/ModelSpatial.java index 030a9092c..4f7efec53 100644 --- a/src/java/com/threerings/jme/model/ModelSpatial.java +++ b/src/java/com/threerings/jme/model/ModelSpatial.java @@ -63,6 +63,15 @@ public interface ModelSpatial */ public void resolveTextures (TextureProvider tprov); + /** + * Creates or populates and returns a clone of this object using the given + * clone properties. + * + * @param store an instance of this class to populate, or null + * to create a new instance + */ + public Spatial putClone (Spatial store, Model.CloneCreator properties); + /** * Recursively writes any data buffers to the output channel. */ diff --git a/src/java/com/threerings/jme/model/Rotator.java b/src/java/com/threerings/jme/model/Rotator.java index fd7ed0eab..e99da213f 100644 --- a/src/java/com/threerings/jme/model/Rotator.java +++ b/src/java/com/threerings/jme/model/Rotator.java @@ -29,7 +29,6 @@ import java.util.Properties; import com.jme.math.Quaternion; import com.jme.math.Vector3f; -import com.jme.renderer.CloneCreator; import com.jme.scene.Controller; import com.jme.scene.Spatial; @@ -83,7 +82,8 @@ public class Rotator extends ModelController } @Override // documentation inherited - public Controller putClone (Controller store, CloneCreator properties) + public Controller putClone ( + Controller store, Model.CloneCreator properties) { Rotator rstore; if (store == null) { diff --git a/src/java/com/threerings/jme/model/SkinMesh.java b/src/java/com/threerings/jme/model/SkinMesh.java index ef7c78581..943cdc02b 100644 --- a/src/java/com/threerings/jme/model/SkinMesh.java +++ b/src/java/com/threerings/jme/model/SkinMesh.java @@ -38,7 +38,6 @@ import java.util.HashSet; import com.jme.bounding.BoundingVolume; import com.jme.math.Matrix4f; import com.jme.math.Vector3f; -import com.jme.renderer.CloneCreator; import com.jme.renderer.Renderer; import com.jme.scene.Spatial; import com.jme.scene.VBOInfo; @@ -182,7 +181,7 @@ public class SkinMesh extends ModelMesh } @Override // documentation inherited - public Spatial putClone (Spatial store, CloneCreator properties) + public Spatial putClone (Spatial store, Model.CloneCreator properties) { SkinMesh mstore = (SkinMesh)properties.originalToCopy.get(this); if (mstore != null) { @@ -235,9 +234,10 @@ public class SkinMesh extends ModelMesh @Override // documentation inherited public void expandModelBounds () { - BoundingVolume obound = (BoundingVolume)getModelBound().clone(null); + BoundingVolume obound = + (BoundingVolume)getBatch(0).getModelBound().clone(null); updateModelBound(); - getModelBound().mergeLocal(obound); + getBatch(0).getModelBound().mergeLocal(obound); } @Override // documentation inherited @@ -336,7 +336,7 @@ public class SkinMesh extends ModelMesh } // copy it from array to buffer - FloatBuffer vbuf = getVertexBuffer(), nbuf = getNormalBuffer(); + FloatBuffer vbuf = getVertexBuffer(0), nbuf = getNormalBuffer(0); vbuf.rewind(); vbuf.put(_vbuf); nbuf.rewind(); @@ -348,7 +348,7 @@ public class SkinMesh extends ModelMesh */ protected void storeOriginalBuffers () { - FloatBuffer vbuf = getVertexBuffer(), nbuf = getNormalBuffer(); + FloatBuffer vbuf = getVertexBuffer(0), nbuf = getNormalBuffer(0); vbuf.rewind(); nbuf.rewind(); FloatBuffer.wrap(_ovbuf = new float[vbuf.capacity()]).put(vbuf); diff --git a/src/java/com/threerings/jme/tools/ModelDef.java b/src/java/com/threerings/jme/tools/ModelDef.java index bf6548458..84f2f3fd0 100644 --- a/src/java/com/threerings/jme/tools/ModelDef.java +++ b/src/java/com/threerings/jme/tools/ModelDef.java @@ -508,13 +508,13 @@ public class ModelDef HashSet referenced) { boolean hasValidChildren = false; - for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) { - Spatial child = (Spatial)it.next(); + for (int ii = node.getQuantity() - 1; ii >= 0; ii--) { + Spatial child = node.getChild(ii); if (!(child instanceof ModelNode) || pruneUnusedNodes((ModelNode)child, nodes, referenced)) { hasValidChildren = true; } else { - it.remove(); + node.detachChildAt(ii); nodes.remove(child.getName()); } } diff --git a/src/java/com/threerings/jme/tools/ModelViewer.java b/src/java/com/threerings/jme/tools/ModelViewer.java index 74cd17e49..f3d24de38 100644 --- a/src/java/com/threerings/jme/tools/ModelViewer.java +++ b/src/java/com/threerings/jme/tools/ModelViewer.java @@ -333,7 +333,7 @@ public class ModelViewer extends JmeCanvasApp } Line grid = new Line("grid", points, null, null, null); - grid.getDefaultColor().set(0.25f, 0.25f, 0.25f, 1f); + grid.getBatch(0).getDefaultColor().set(0.25f, 0.25f, 0.25f, 1f); grid.setLightCombineMode(LightState.OFF); grid.setModelBound(new BoundingBox()); grid.updateModelBound(); diff --git a/tests/src/java/com/threerings/jme/client/JabberApp.java b/tests/src/java/com/threerings/jme/client/JabberApp.java index ebb28092c..523ea4dbb 100644 --- a/tests/src/java/com/threerings/jme/client/JabberApp.java +++ b/tests/src/java/com/threerings/jme/client/JabberApp.java @@ -75,7 +75,7 @@ public class JabberApp extends JmeApp for (int i = 0; i < 24; i++) { colors[i] = ColorRGBA.randomColor(); } - t.setColorBuffer(BufferUtils.createFloatBuffer(colors)); + t.setColorBuffer(0, BufferUtils.createFloatBuffer(colors)); _root.attachChild(t); _root.updateRenderState(); @@ -90,7 +90,7 @@ public class JabberApp extends JmeApp _camera.update(); // speed up key input - _input.setKeySpeed(100f); + _input.setActionSpeed(100f); return true; }