CloneCreator Bug

Its seems that CloneCreator does not clone the KeyFrameController but instead uses the same instance for every cloned spatial.

That’s strange. I queue them up. Is it like this for a special case for all KeframeControllers for any model?

for md2 models. the strange thing is that although System.identityHashCode returns a different value for each one the setNewAnimationTimes affects every loaded model

Check out the following code!

By hitting the space the animation changes for both clones!

The Keyframe controller for every clone behaves the same affecting them all!



import com.jme.animation.KeyframeController;
import com.jme.app.SimpleGame;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.scene.CloneCreator;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.model.XMLparser.Converters.Md2ToJme;
import com.jme.scene.model.XMLparser.JmeBinaryReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;

/**
 *
 * @author kman
 */
public class TestClone extends SimpleGame{
   Spatial model;
   Node tmp2;
   /** Creates a new instance of TestClone */
   public TestClone() {
      setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
      start();
   }
   
   public static void main(String args[]){
      new TestClone();
   }
   
   protected void simpleInitGame(){
      rootNode.attachChild(getClone());
      tmp2 = (Node)getClone();
      tmp2.setLocalTranslation(new Vector3f(10,0,10));
      KeyBindingManager.getKeyBindingManager().set("anim",KeyInput.KEY_SPACE);
      
      rootNode.attachChild(tmp2);
   }
   
   public void simpleUpdate(){
      if(KeyBindingManager.getKeyBindingManager().isValidCommand("anim")){
         KeyframeController kc=(KeyframeController) tmp2.getChild(0).getController(0);
         kc.setSpeed(5);
         kc.setActive(true);
         kc.setRepeatType(KeyframeController.RT_WRAP);
         kc.setNewAnimationTimes(40,44);
      }
   }
   
   public Spatial getClone(){
      if(model ==null){
         model = getMd2("jmetest/data/model/drfreak.md2");
      }
      CloneCreator cr = new CloneCreator(model);
      cr.addProperty("colors");
      cr.addProperty("texcoords");
      cr.addProperty("vertices");
      cr.addProperty("normals");
      cr.addProperty("indices");
      cr.addProperty("keyframecontroller");
      return cr.createCopy();
   }
   
   private Spatial getMd2(String model){
      try{
         Md2ToJme converter=new Md2ToJme();
         ByteArrayOutputStream BO=new ByteArrayOutputStream();
         URL freak=getClass().getClassLoader().getResource(model);
         Node freakmd2=null;
         converter.convert(freak.openStream(),BO);
         JmeBinaryReader jbr=new JmeBinaryReader();
         jbr.setProperty("bound","box");
         freakmd2=jbr.loadBinaryFormat(new ByteArrayInputStream(BO.toByteArray()));
         freakmd2.getChild(0).setLocalScale(0.2f);
         freakmd2.getChild(0).getLocalRotation().fromAngleAxis(-FastMath.PI/2,new Vector3f(0,1,0));
         return freakmd2;
      } catch (IOException e) {
         System.out.println("damn exceptions:" + e.getMessage());
         return null;
      }
   }
   
}

[/code]

Ah ha! This needs to be documented, so I’ll put it in. You can’t use the original and the Clones at the same time. And you don’t want too because you want your Clones to all be rendered at the same time and the original won’t have the Clone RenderQueue flag.



Create your clones from the original and discard the original to be garbage collected. In this case, create two clones and use both of them instead of one clone and one original.

Why do clones need to have there own bucket in the render query?

They reuse the various buffer data. see http://www.mojomonkeycoding.com/jmeforum/viewtopic.php?t=904