setActive not working [JOODE - use ODE instead]

Hi again.



I'm having issues playing with physics nodes.



I create a dynamic physics node, and call setActive(false).



when I call setActive(true), it does not interact with the rest of the world. It seems to have accumulated force and velocity, but hasn't moved.

clearDynamics fixes that (but it shouldn't need to be called).



I did use the physicsSpace.create() method, so that should be no problem.



? perhaps the abstract getPhysycsSpace method should be implemented in the abstract class with a direct object reference to the creating physics space? I noticed the impl is doing something funny… but I was tired, so I just thought 'note to self: forums'



I was not rendering it either, but now I leave the gamestate switched on. Its a basicGameState, not a physicsGameState… don't know if that would make a difference.

I'm using setActive myself successfully. Can you provide a testcase?

fine, I'll send you a source jar with my 1/2 built app (and update from cvs before I do). no website, so I'll presume email is ok unless you tell me otherwise.

Please don't. Create a short testcase, not more than one file. It's impossible to find an error in your whole project in a short time.

Started making a test case… put in control and everything… and then realised I only had to add a few boxes.



Time has become scarse again… but, I do have a little additional information…



I'm using the PhysicsNode.setActive(boolean) call, not the PhysicsGameState… which gives me the option of controlling rendering and physics independently.

As it turns out, I can just change my code to use the PhysicsGameState, and it will work… but there is still a problem with the PhysicsNode setActive call.



it seems like it creates its own physics space (sort of), but still gets ticked by the source physics space.



test case still to come…

hey - back again.



this demonstrates the issues I am having:


  1. delay 5 seconds - the box falls through the floor… seems to be re fetching via a static method rather than keeping a reference itself.
  2. have to call clearforce, etc, when re-making active - it is being updated, just its position isn't… I would expect it to 'pause', not to stop and still be updated
  3. move the ball & hit the box… when travelling right, it get trapped… go round, no problem.



    1 & 2 are 'fixable'… 3, I don't know.


/*
 * Created on 26 Sep 2007
 *
 */
package koncept.hs.game;

import java.util.concurrent.*;

import com.jme.bounding.*;
import com.jme.input.*;
import com.jme.light.*;
import com.jme.math.*;
import com.jme.renderer.*;
import com.jme.scene.*;
import com.jme.scene.shape.*;
import com.jme.scene.state.*;
import com.jme.system.*;
import com.jme.util.*;
import com.jmex.game.*;
import com.jmex.game.state.*;
import com.jmex.physics.*;
import com.jmex.physics.callback.*;
import com.jmex.physics.util.states.*;

public class SetStateMarbleDemo implements MouseInputListener{
   public static int FORCE_MAX = 100;
   public static int MOUSE_MULT = 15;

   StandardPhysicsGame game = null;
   DynamicPhysicsNode sphereNode = null;

   public static void main(String[] args) {
      new SetStateMarbleDemo();
   }

   public SetStateMarbleDemo() {
      game = new StandardPhysicsGame("SetStateDemo");
      game.start();
      init();
   }

   private void init() {
      game.lock();
      BasicGameState floorState = new BasicGameState("floor");
      PhysicsNode floor = game.getPhysicsSpace().createStaticNode();
      float boxSize = 15f;
      Box tile = new Box("floor",
            new Vector3f(0,-3,0), boxSize, 0.2f, boxSize);
      tile.setModelBound(new BoundingBox());
      tile.updateModelBound();
      floor.attachChild(tile);
      floor.generatePhysicsGeometry();
      floorState.getRootNode().attachChild(floor);
      normaliseNode(floorState.getRootNode());
      floorState.setActive(true);
      GameStateManager.create().attachChild(floorState);

      createSphere();
      MouseInput.get().addListener(this);

      BasicGameState bumpState = new BasicGameState("BumpState");
      DynamicPhysicsNode bumpNode = createBox("BumpMeOnMyLeftSide");
      bumpNode.setLocalTranslation(new Vector3f(2,2,10));
      bumpState.getRootNode().attachChild(bumpNode);
      normaliseNode(bumpState.getRootNode());
      bumpState.setActive(true);
      GameStateManager.getInstance().attachChild(bumpState);

      BasicGameState dropState = new BasicGameState("DropState");
      final DynamicPhysicsNode dropNode = createBox("NewPhysicsSpace");
      dropNode.setLocalTranslation(new Vector3f(-2,2,10));

      dropState.getRootNode().attachChild(dropNode);
      normaliseNode(dropState.getRootNode());
      dropState.setActive(true);
      dropNode.setActive(false);

      GameStateManager.getInstance().attachChild(dropState);

      game.unlock();
      
      
      Thread PhysicsSwitch = new Thread() {
         public void run() {
            Thread t = Thread.currentThread();
            synchronized (t) {
               try {
                  TimeUnit.SECONDS.sleep(5);
               }
               catch (InterruptedException e) { } // who cares - its a demo
            }
            GameTaskQueueManager.getManager().getQueue(GameTaskQueue.UPDATE).enqueue(new Callable<Boolean>() {
               public Boolean call() throws Exception {
                  dropNode.clearForce(); //WHY should I STILL need to clear the force (etc)... it was DISABLED
                  dropNode.clearDynamics();
                  dropNode.setActive(true);
                  return true;
               }
            });
         }
      };
      PhysicsSwitch.start();
   }

   private void normaliseNode(Node n) {
      ZBufferState zBuf = DisplaySystem.getDisplaySystem().getRenderer().createZBufferState();
      zBuf.setEnabled(true);
      zBuf.setFunction(ZBufferState.CF_LEQUAL);
      n.setRenderState(zBuf);
      n.updateRenderState();

      DirectionalLight light = new DirectionalLight();
      light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
      light.setAmbient(new ColorRGBA(0.3f, 0.3f, 0.3f, 1.0f));
      light.setDirection(new Vector3f(-0.3f, -0.8f, -0.3f));
      light.setEnabled(true);

      /** Attach the light to a lightState and the lightState to rootNode. */
      LightState lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
      lightState.setEnabled(true);
      lightState.attach(light);

      n.setRenderState(lightState);
      n.updateRenderState();
   }

   private DynamicPhysicsNode createBox(String name) {
      float size = 0.45f;
      Geometry box = new Box("name", new Vector3f(), size, size, size);
      box.setModelBound(new BoundingBox());
      box.updateModelBound();
      DynamicPhysicsNode boxNode = game.physicsSpace.createDynamicNode();
      boxNode.attachChild(box);
      boxNode.setMass(1); //arbitrary
      boxNode.generatePhysicsGeometry();

      MaterialState boxMaterial = DisplaySystem.getDisplaySystem().getRenderer().createMaterialState();

      boxMaterial.setAmbient(new ColorRGBA(0f, 0f, 0f, 1f));
      boxMaterial.setEmissive(new ColorRGBA(0.1f, 0.1f, 0.1f, 1f));
      boxMaterial.setDiffuse(new ColorRGBA(0.6f, 0.3f, 0.5f, 1f));
      boxMaterial.setSpecular(new ColorRGBA(0.5f, 0.7f, 0.5f, 1f));
      boxMaterial.setShininess(70);

      boxNode.setRenderState(boxMaterial);
      boxNode.updateRenderState();
      return boxNode;
   }
   
   private void createSphere() {
      PhysicsGameState sphereState = new PhysicsGameState("SphereState");
      int detail = 10;
      Sphere s = new Sphere("Sphere", detail, detail, 0.20f); //RADIUS
//      s.setDefaultColor(ColorRGBA.cyan);
      s.setModelBound(new BoundingSphere());
      s.updateModelBound();
      sphereNode = game.getPhysicsSpace().createDynamicNode();
      sphereNode.clearForce();
      sphereNode.clearTorque();
      sphereNode.setMass(1.5f); // kg?
      sphereNode.setLocalTranslation(new Vector3f(0,1,10));
      sphereNode.attachChild(s);
      sphereNode.generatePhysicsGeometry();
      sphereState.getRootNode().attachChild(sphereNode);
      normaliseNode(sphereState.getRootNode());

      MaterialState ms = DisplaySystem.getDisplaySystem().getRenderer().createMaterialState();

      ms.setAmbient(new ColorRGBA(0f, 0f, 0f, 1f));
      ms.setEmissive(new ColorRGBA(0.1f, 0.1f, 0.1f, 1f));
      ms.setDiffuse(new ColorRGBA(0.2f, 0.9f, 0.9f, 1f));
      ms.setSpecular(new ColorRGBA(0.5f, 0.5f, 0.5f, 1f));
      ms.setShininess(70);

      sphereNode.setRenderState(ms);
      sphereNode.updateRenderState();

      FrictionCallback fc = new FrictionCallback();
      game.physicsSpace.addToUpdateCallbacks(fc);
      fc.add(sphereNode, 0, 5);
      
      sphereState.setActive(true);
      GameStateManager.getInstance().attachChild(sphereState);
   }

   public void onButton(int button, boolean pressed, int x, int y) {
      Vector3f force = new Vector3f(0, 30 * MOUSE_MULT, 0);
      sphereNode.addForce(force);
   }

   public void onWheel(int wheelDelta, int x, int y) { }

   public void onMove(int xDelta, int yDelta, int newX, int newY) {
      System.out.println("onMove:" + xDelta + ":" + yDelta);
      Vector3f force = sphereNode.getForce(null);

      int xForce = MOUSE_MULT * xDelta;
      int zForce = MOUSE_MULT * -yDelta;
      xForce += (int)force.x;
      zForce += (int)force.z;

      if (xForce > FORCE_MAX) xForce = FORCE_MAX;
      else if (xForce < -FORCE_MAX) xForce = -FORCE_MAX;

      if (zForce > FORCE_MAX) zForce = FORCE_MAX;
      else if (zForce < -FORCE_MAX) zForce = -FORCE_MAX;

      xForce -= (int)force.x;
      zForce -= (int)force.y;

      force.x = xForce;
      force.z = zForce;
      sphereNode.clearForce();
      sphereNode.addForce(force);
   }


   class StandardPhysicsGame extends StandardGame {
      private PhysicsSpace physicsSpace = null;

      public StandardPhysicsGame(String name) {
         super(name);
         physicsSpace = PhysicsSpace.create();
      }

      public PhysicsSpace getPhysicsSpace() {
         return physicsSpace;
      }

      @Override
      protected void update(float interpolation) {
         super.update(interpolation);
         physicsSpace.update(interpolation);
      }

   }
}

I still have to guess what you mean, I'll try:



1+2) While active==false everything is fine, right? While active==true it's fine, too. The thing that bothers you is, that the dynamic node does not have the same velocity at the time you re-activate it like it had when you disable it, right? That should be fixed, now.



3) No idea what you are talking about. I can hit the box with the ball and push it away, etc…

not matching velocity was a minor niggle… but thanks anyway. With zero values, its easy to clear, but if (ever) it was set to false while in motion, then it would be wrong. Anyway, fixed now.



Just updated from cvs and rebuilt (no change in native libs)…



same thing. On my PC, the left box falls through the floor, and the ball can get trapped in the left face or the box on the right (from original orientation). Using JoodePhysicsSpace (which is the one created, verified with debugger)… Ode doesn't work, haven't set it up because joode works (except for this).



*looked at the code, was sure I had seen something that looked fishy. I might have been wrong… Either way, it looks fine now. Perhaps it not being 2am helps.



If there is anyone else following this thread - please, run the demo & report back your results. It could be my setup, or something else.

just slave the main(String[]) from a working app…



guess I'll just go on and hope a few people report having the same problem.



–ebola

Ok, so it really runs differently on you system… but it has nothing to do with setActive, right?

What platform are you running it on? win/lin/osx? Does it happen only with StandardGame? If yes, do you have multi core or hyperthreading?

Hi.

Happens with your SimplePhysicsGame as well (too bad I can't disable mouselook… just took a little practice), no different. ball gets trapped, drop box doesn't collide.

also happens in my app - seperate physics thread, and posted (single thread)



yes, I know… no concurrent physics / render activity, just independant speeds.



win32 (xp), p3 M (one core, one register set)… T43 Thinkpad.



and the issue that made me post was that setActive (->false ->true) results in the object not colliding any more… though the ball getting trapped is really annoying me as well… though I can add a force_external for each ball / box collision.



I guess I can code around the setActive as well… but its a bug (on my pc anyway).

hmm, no threading, win32… this must work! It does over here. I have no good idea why it should be different on your system. Did you try to reboot your system to sort out floating point precision error due to directx apps?



Maybe you can set up a webstart link for it, to let other people test if the problems can be reproduced on other systems (and which systems)?


ebola said:

SimplePhysicsGame as well (too bad I can't disable mouselook...

you can: cameraInputHandler.setEnabled(false)

k… with JOODE, I still have the trapping & non-interacting problems I described (setActive (–> false --> true) results in the box falling and not interacting) (and all bounce angles from static 'walls' are surface normals - 90… just didn't have any before)

I finally got it working with ODE, and geuss what - its fine.



rather than PhysicsSpace.create(), I have to go new OdePhysicsSpace()…

and because I really want to see if it works - if you change the line in the StandardPhysicsGame posted to new JoodePhysicsSpace(), does it still work fine?





Work around found - use Ode not Joode… but it was far easier to set up joode.



Thanks anyway - and if you have the time, does it still work properly with joode?



nK

ebola said:

rather than PhysicsSpace.create(), I have to go new OdePhysicsSpace()...

If there is only one physics implementation in the classpath PhysicsSpace.create() creates an instance of exactly that space - accessing the implementation directly is not recommended (you should not have any compile time dependency to the ODE impl).

It is possible that activation is not working in the JOODE implementation, I did not check that. JOODE is pretty incomplete either way and it does not seem to be developed actively any more :(.
ebola said:

I went and set up the Joode impl because it seemed to have clearer instructions...

really? - where did you find them?

it was a while ago… and I have forgotten



looks familiar (though I wouldn't be surprised if I 'abridged' it to what looks right…):

http://www.jmonkeyengine.com/wiki/doku.php?id=setting_up_eclipse_to_build_jme-physics



? perhaps it wasn't working anyway, and so returned a joode (which is theoretically pure java)… I can check to see if its loading any native libraries…





** JOODE isn't loading any native libraries **