How do lock() and unlock() methods work for physics objects?

Hi guys,



I was wondering how lock() and unlock() methods should be used. I have a bunch of boxes which I add to a static node. Then I lock the static node. I would like however to detach/attach boxes to the static node later on but I am seeing some unexpected (by me) behavior. The collision geometry doesn't seem to be updated if I have used the lock() method.

I think I am missing something or maybe I shouldn't use lock() at all in this case?



Below is an example of what I mean if somebody would like to take a quick look and tell me what I am doing wrong.

Thanks a lot.


import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme.input.KeyInput;
import com.jme.math.Vector3f;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.util.SimplePhysicsGame;
import com.jme.scene.shape.Box;
import com.jme.input.KeyBindingManager;
import com.jme.bounding.BoundingBox;

public class Main extends SimplePhysicsGame {
   
    private Box[][] tiles = new Box[4][4];
    private StaticPhysicsNode staticNode;
    private DynamicPhysicsNode dynamicNode;
    private Box cube;
 
   
    protected void simpleInitGame() {
  
        KeyBindingManager.getKeyBindingManager().set("down",KeyInput.KEY_J);
     
         staticNode = getPhysicsSpace().createStaticNode();
        
         for(int i = 0; i < 4; i++)
          for(int j = 0; j < 4; j++){
               tiles[i][j] = new Box("tile"+i+j,new Vector3f(),0.95f,0.25f,0.95f);
               tiles[i][j].setModelBound(new BoundingBox());  
               tiles[i][j].updateModelBound();
               tiles[i][j].getLocalTranslation().set(2*i, 0, 2*j);
               staticNode.attachChild(tiles[i][j]);
          }
        
        staticNode.generatePhysicsGeometry();
       
        // if I comment out the next 2 lines I don't have any problems
        staticNode.lock();
        staticNode.unlock();
       
        dynamicNode = getPhysicsSpace().createDynamicNode();
      
        cube = new Box("Cube",new Vector3f(), 1, 1, 1);
        cube.setModelBound(new BoundingBox());
       cube.updateModelBound();
       dynamicNode.attachChild(cube);
       dynamicNode.generatePhysicsGeometry();
       dynamicNode.getLocalTranslation().set( 3, 5, 3);
       dynamicNode.setAffectedByGravity(false);
   
       rootNode.attachChild(staticNode);
       rootNode.attachChild(dynamicNode);
      
       staticNode.detachAllChildren();
        staticNode.generatePhysicsGeometry();
      
    }

    @Override
    protected void simpleUpdate() {   
        if (KeyBindingManager.getKeyBindingManager().isValidCommand("down",false)){     
           dynamicNode.setAffectedByGravity(true);
    }
    }


    public static void main( String[] args ) {
        Logger.getLogger( "" ).setLevel( Level.WARNING );
        Main app = new Main();
         app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
         app.samples = 2;
         app.start();
    }
     Main() {
        stencilBits = 4;
    }
}


I used a separate static node for each box and then setActive(false) when they are not needed. This works and so far I haven't seen anyhing obviously wrong with it, but if you know of a better way, please tell!

thanks

Hi again,

sorry to answer my own post with another question  :smiley:



Even if I don't lock the static node I still can't update it with new collision geometry after it has been drawn on screen.

What is the proper way to reuse a static node, if any? Am I supposed to delete the node and create a new one?

Here's what I am ultimately trying to accomplish. Say I have a level with a few hundred boxes all attached to a single static node. The next level is different so I detach all boxes and attach new ones at different locations to the same static node. Is there a way I could update the static node to take into account the new geometry? Or do I use a static node for each box? Or how would you do it?



I changed the example above to illustrate what I mean. Just press j (and then v if you want)


import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme.input.KeyInput;
import com.jme.math.Vector3f;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.util.SimplePhysicsGame;
import com.jme.scene.shape.Box;
import com.jme.input.KeyBindingManager;
import com.jme.bounding.BoundingBox;

public class Main extends SimplePhysicsGame {
   
    private Box[][] tiles = new Box[4][4];
    private StaticPhysicsNode staticNode;
    private DynamicPhysicsNode dynamicNode;
    private Box cube;
 
   
    protected void simpleInitGame() {
  
        KeyBindingManager.getKeyBindingManager().set("down",KeyInput.KEY_J);
     
         staticNode = getPhysicsSpace().createStaticNode();
        
         for(int i = 0; i < 4; i++)
          for(int j = 0; j < 4; j++){
               tiles[i][j] = new Box("tile"+i+j,new Vector3f(),0.95f,0.25f,0.95f);
               tiles[i][j].setModelBound(new BoundingBox());  
               tiles[i][j].updateModelBound();
               tiles[i][j].getLocalTranslation().set(2*i, 0, 2*j);
               staticNode.attachChild(tiles[i][j]);
          }
        
        staticNode.generatePhysicsGeometry();
       
        // if I comment out the next 2 lines I don't have any problems
        //staticNode.lock();
       // staticNode.unlock();
       
        dynamicNode = getPhysicsSpace().createDynamicNode();
      
        cube = new Box("Cube",new Vector3f(), 1, 1, 1);
        cube.setModelBound(new BoundingBox());
       cube.updateModelBound();
       dynamicNode.attachChild(cube);
       dynamicNode.generatePhysicsGeometry();
       dynamicNode.getLocalTranslation().set( 3, 5, 3);
       dynamicNode.setAffectedByGravity(false);
   
       rootNode.attachChild(staticNode);
       rootNode.attachChild(dynamicNode);
    }

    @Override
    protected void simpleUpdate() {   
        if (KeyBindingManager.getKeyBindingManager().isValidCommand("down",false)){     
           dynamicNode.setAffectedByGravity(true);
          
           staticNode.detachAllChildren();
            staticNode.attachChild(tiles[0][0]);
             staticNode.updateModelBound();
            staticNode.generatePhysicsGeometry();
    }
    }


    public static void main( String[] args ) {
        Logger.getLogger( "" ).setLevel( Level.WARNING );
        Main app = new Main();
         app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
         app.samples = 2;
         app.start();
    }
     Main() {
        stencilBits = 4;
    }
}

Thats the correct way of doing it.

Perfect. Thanks very much nymon. Now I can sleep at night  :smiley:

You can add multiple collision geometries to a single static node, but it gets cumbersome when you want to remove one of them. Its just easier to keep track of nodes.