PhysicsSystem and FixedLogicrateGame issues

And we have compounded objects! :slight_smile: Turned out an update of odejava did the trick.



shochu, I’ll look into your problem above. Thanks for making it a compact example.

Thanks Per

Ok shochu, the problem consist in that when the physics system tries to create a compounded object from your shipModel, it doesn’t know how to, because in that Node there’s a TriMesh with no bounding volume.



To fix this you can load your model using the “bound” property, like this:


      Node shipModel = new Node();
      try {
         JmeBinaryReader jbr = new JmeBinaryReader();
         jbr.setProperty("bound", "box"); // <-- new
         InputStream loaderInput=new File("spaceship.jme").toURI().toURL().openStream();
         shipModel = jbr.loadBinaryFormat(loaderInput);
      } catch (IOException ioe) {
         LoggingSystem.getLogger().log(Level.WARNING,
         "Could not load model: ");
      }


Your problems arn't over with this though, because later down the code you resize the shipNode, but the world bounds never seem to get affected. Just spoke some with mojo about this, and he also thought this should work.. :?

I also tried extracting the trimesh and applying a modelbound to it, then add it to the shipNode, like this:


      TriMesh shipGeo = (TriMesh) ((Node) shipModel.getChild(0)).getChild(0);
      shipGeo.setLocalScale(.01f);
      shipGeo.setModelBound(new OrientedBoundingBox());
      shipGeo.updateModelBound();
      shipNode.attachChild(shipGeo);



Still with the same result :? Looks to me like those jME bounds never gets affected by the scale of the object it surrounds.

I'd advice you to solve this by opening that model of yours in a modelling software, then apply a correct scale there. Then load it with the bound property as above.

BTW: add this line: rootNode.setForceView(true) to get around jME culling the scene away.

Thanks Per … looks like it’s time to pester renase and mojo hehe. I’ll go ahead and resize the model in my modeling software.



Thanks again.

Sorry, it’s not our fault this time. As I had thought (or hoped after talking with Per), scaling affects boundings properly. I ran multiple tests (with normal shapes, models, in nodes, in trimeshes, etc) and all worked as expected. To test for yourself easily, run TestPick, press ‘B’ and observe the non-scaled behavior. Then add model.setLocalScale(0.5f); to the test and the model should be smaller, as well as the boundings, and the picking will reflect this change.

Aha! Could it be that the world bounds gets recalculated during the updateGeometricState? Because that isn’t called before the physical entity is created…

yes per, updateModelBounds are called upon updateGeometricState.



Hence why we are having troubles with world translation and rotation. Because they are calculated upon an updateGeometricState call…



DP

Then proper scaling could be achieved with something like:


shipModel.setLocalScale(0.01f);
shipModel.updateGeometricState(0, true);


NOTE: above should be before the PhysicsObject is created from it.

orr, just call rootNode.updateGeometricState(0.0f, true); when youve setup your graphical scene and before you setup your physics.



DP

Thanks for the info. Havent had a chance to check out the changes yet but I’ll let you guys know if everything is working smoothly (hopefully by friday). Thanks again.

Okay … I added in the changes but still have problems. I’m loading my model and making sure it has bounds. THe model is loaded in the shipModel Node. I then attach the shipModel Node to the shipNode.



RootNode -> shipNode -> shipModel -> Model Geometry



I then create a DynamicPhysicsObject using shipNode.



The first problem I notice is that the ship doesn’t appear at all. If you change the DyanmicPhysicsObject so that it is created using shipModel instead of shipNode the ship appears but it isn’t scaled at all. (you have to zoom out to see the ship since it will be too big)



Here’s the code


import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;

import com.jme.app.SimpleGame;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.model.XMLparser.JmeBinaryReader;
import com.jme.scene.shape.Box;
import com.jme.util.LoggingSystem;
import com.jmex.physics.DynamicPhysicsObject;
import com.jmex.physics.PhysicsWorld;
import com.jmex.physics.StaticPhysicsObject;

public class SimpleTest extends SimpleGame {

    private DynamicPhysicsObject shipPhysics;

    /**
     * Inits everything needed for this test.
     */
    protected void simpleInitGame() {
       display.setTitle("Simple Test");
       PhysicsWorld.create();
       PhysicsWorld.getInstance().setUpdateRate(100);
       PhysicsWorld.getInstance().setStepSize(2 / 100f);

       // Creates the box that makes out the floor.
       Box floorGraphics = new Box("Floor", new Vector3f(), 50, 1, 50);
       // We move it down 5 units, and away from the camera 10 units.
       floorGraphics.setLocalTranslation(new Vector3f(0, -5, 10));
       // Create static physics object
       StaticPhysicsObject floorPhysics = new StaticPhysicsObject(floorGraphics);

       // shipNode is the parent node for the shipModel and thrusterNode
       Node shipNode = new Node("my Ship");
             
       Node shipModel = new Node("ship model");
       try {
          JmeBinaryReader jbr = new JmeBinaryReader();
          jbr.setProperty("bound", "box");
          InputStream loaderInput=new File("spaceship.jme").toURI().toURL().openStream();
          shipModel = jbr.loadBinaryFormat(loaderInput);
       } catch (IOException ioe) {
          LoggingSystem.getLogger().log(Level.WARNING,
                "Could not load model: ");
       }
       // Shrink the model down
       shipModel.setLocalScale(.01f);
       // Update the geometric state of the ship
       shipModel.updateGeometricState(0, true);
       // Attach our shipModel to the shipNode
       shipNode.attachChild(shipModel);
       
       // We move it 10 units up, and 10 units away from the camera.
       shipNode.setLocalTranslation(new Vector3f(0, 0, 10));
       shipNode.updateGeometricState(0, true);
       
       // Create a dynamic physics object from it.
       shipPhysics = new DynamicPhysicsObject(shipNode, 1f);
       shipPhysics.syncWithGraphical(false);

       // Add the graphical representations to the rootNode. You could also get
       // references to them by calling PhysicsObject.getSpatial().
       rootNode.attachChild(floorGraphics);
       rootNode.attachChild(shipNode);
       rootNode.setForceView(true);

       // And the physical representations to the PhysicsWorld.
       PhysicsWorld.getInstance().addObject(floorPhysics);
       PhysicsWorld.getInstance().addObject(shipPhysics);
    }

    /**
     * Gets called on application ending.
     */
    protected void cleanup() {
       super.cleanup();
       PhysicsWorld.getInstance().cleanup();
    }

    /**
     * Gets called every frame.
     */
    protected void simpleUpdate() {
       PhysicsWorld.getInstance().update(tpf);
    }

    public static void main(String[] args) {
       SimpleTest app = new SimpleTest();
       app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG, SimpleTest.class
             .getClassLoader().getResource(
                   "jmextest/data/images/jmephysics_logo.png"));
       app.start();
    }
 } 



Thanks again for any help.

Model is here: http://www.mekamedia.com/spaceship.jme

Looking through the source code for PhysicsWorld it looks like the createNode() method doesn’t handle a Node with a Node attached to it.



So if you have



ShipNode(node) -> ShipModel(node) -> ShipGeom (TriMesh)



This won’t work as the intial ShipModel Node isn’t recognized

It will be recognised. StripNode will simply obtain all Geometries for that node…and we process that geometries. We dont actually deal with nodes, we only deal with geometry.



Also, StripNode is a recursive method, so all the Geometries will be extracted from the Node whether it wants to or not! mwaaahaaa, we are evil! }:slight_smile:



Perhaps we should call updateGeometricState(0.0f, true) on that node so we can obtain its world scale…



Theres a thought!



DP

hmm …



I’m pretty sure I am calling updateGeometricState on both the shipModel and the shipNode. before any physicsObjects are created.



And yeah you’re right about the recursing ://

oh no no, you are calling updateGeometricState on em, im not doubting that. What im saying is that we’re currently checking for the “local” scale of things. Ie. in relation to its parent, the ship’s geometry has a local scale of (1,1,1). The thing is, updateGeometricState will actually compute the “world” scale of the geometry. So if you set its parent’s parent to have a local scale of (0.1,0.1,0.1), then the ship’s geometry will have a local scale of (0.1,0.1,0.1). Can you see the difference?



Its just that making the world bounds requires a call on updateGeometricState.



Now the demos, tests and stuff always show updateGeometricState(0.0f, true) to only be called every update, and once you finish setting your scene up. But in our current demos, we’re setting up the physics before updateGeometricState is called. Now extreme newbies to the system will have trouble with this as both parties are saying do it this way and they start to get confuzzeled.



So im gonna talk this over with per, but i think we should do world/rotation and scaling by ourselves…We’l see how it goes.



Btw, this also applies to translation and rotation too! Try adding two nodes at different locations with each geometry inside the two nodes having a local translation of (0,0,0). You will be terrified! :slight_smile:



DP

Btw, this also applies to translation and rotation too! Try adding two nodes at different locations with each geometry inside the two nodes having a local translation of (0,0,0). You will be terrified! Smile


Hehe ... yeah I saw this before, I had no idea what was going on.

So lets say you aren't using the PhysicsSystem at all. And I'm just loading the model into the 'ShipModel' Node and then attaching it to the rootNode. Shouldn't calling setLocalScale() on ShipModel scale the model down?

Yes, yes it will. Umm…let me explain jme’s world/local transform groupings.



The most difficult concept to grasp in this is the local transformations. So im gonna try and explain that now. Local translation is how many units this current spatial will move RELATIVE TO ITS PARENT. This means the following:



Node H has a translation (-5, 0, 0); This is directly attached to the rootNode



Inside H is a geometry J with a translation of (-50,0,0);



Now youd think that J has a translation of (-50,0,0), after all, you did set it! But no, it has a translation of (-55,0,0). This is because the -50 is RELATIVE to its parent, and its parent has a further translation of -5.



This value of -55 is actually the world translation. And this is what gets computed on every updateGeometricState call by simply adding up all the translations of all the parents in the chain. And the world value is what we should be using in the physics system.



Now scaling, and rotation is a similar concept to the above. Your scaling RELATIVE to its parent, but its children will still have a local scale of (1,1,1) when infact its (0.1,0.1,0.1).



Hope this answers a few questions here…



DP

Yeah … thansk DP. I was just getting confused due to another demo I made where I had the main calling ANOTHER demo I made instead of the one I thought I just made.





ahhhhhhhhhh. haha. Need a beer.





Mojo pointed out my stupidity in the other thread and it all makes sense now.





To sum up …





Is there anyway with the current PhysicsSystem to have system recognize the world scale of a node.



In other words





ShipNode (scaled to 0.1) -> ShipModel (scaled to 1.0)



Thus ShipModel gets a scale of (0.1).





Thanks. If not I’ll do it in the modeling software which is what Per suggested waaaay back when.

well, being honest with you, you shouldn’t have to modify your model to be working with our physics system. Our physics system should cope with whatever jme throws at it. And currently, it does to a certain extent.



However, it is good practice when developing a game not to scale everythin using the scene graph. One can argue that all the multiplication of the matrix for very large number of scene objects can cause a slow down when you could have scaled everything up in whatever modeler you used…



But that excuse it feable really (its only multiplication right?), which ever suits ya, but i’l definetly get it fixed…ASAP!



DP

Okay,

Getting close here. I resized my model in the modelling software and now the model shows up. The problem is it goes right through the floor. Not sure why. It works when I create the DynamicPhysicsObject out of the shipModel but not when I create it out of the shipNode. The hierarchy looks like this:



RootNode -> shipNode -> shipModel -> Geometry



You’ll notice the ship appears and then flies down really fast through the floor. If I create the DynamicPhysicsObject out of shipModel so that the hierarchy looks like this:



RootNode -> shipModel -> Geometry



Then everything works perfectly.



You can get the new resized model here: http://www.mekamedia.com/spaceship.jme




import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;

import com.jme.app.SimpleGame;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.model.XMLparser.JmeBinaryReader;
import com.jme.scene.shape.Box;
import com.jme.util.LoggingSystem;
import com.jmex.physics.DynamicPhysicsObject;
import com.jmex.physics.PhysicsWorld;
import com.jmex.physics.StaticPhysicsObject;

public class SimpleTest extends SimpleGame {

    private DynamicPhysicsObject shipPhysics;

    /**
     * Inits everything needed for this test.
     */
    protected void simpleInitGame() {
       display.setTitle("Simple Test");
       PhysicsWorld.create();
       PhysicsWorld.getInstance().setUpdateRate(100);
       PhysicsWorld.getInstance().setStepSize(2 / 100f);

       // Creates the box that makes out the floor.
       Box floorGraphics = new Box("Floor", new Vector3f(), 50, 1, 50);
       // We move it down 5 units, and away from the camera 10 units.
       floorGraphics.setLocalTranslation(new Vector3f(0, -5, 10));
       floorGraphics.updateGeometricState(0.0f, true);
       // Create static physics object
       StaticPhysicsObject floorPhysics = new StaticPhysicsObject(floorGraphics);

       // shipNode is the parent node for the shipModel and thrusterNode
       Node shipNode = new Node("my Ship");
       
       Node shipModel = new Node("ship model");
       try {
          JmeBinaryReader jbr = new JmeBinaryReader();
          jbr.setProperty("bound", "box");
          InputStream loaderInput=new File("spaceship.jme").toURI().toURL().openStream();
          shipModel = jbr.loadBinaryFormat(loaderInput);
       } catch (IOException ioe) {
          LoggingSystem.getLogger().log(Level.WARNING,
                "Could not load model: ");
       }
       // Update the geometric state of the ship
       shipModel.updateGeometricState(0, true);
       
       // Attach our shipModel to the shipNode
       shipNode.attachChild(shipModel);
             
       // Update GeometricState of the shipNode
       shipNode.updateGeometricState(0, true);
             
       // Create a dynamic physics object from the shipNode (note that it works if we use the shipModel).
       shipPhysics = new DynamicPhysicsObject(shipNode, 1f);
       shipPhysics.syncWithGraphical(false);

       // Add the graphical representations to the rootNode.
       rootNode.attachChild(floorGraphics);
       rootNode.attachChild(shipNode);
       rootNode.setForceView(true);
       
       // And the physical representations to the PhysicsWorld.
       PhysicsWorld.getInstance().addObject(floorPhysics);
       PhysicsWorld.getInstance().addObject(shipPhysics);
    }

    /**
     * Gets called on application ending.
     */
    protected void cleanup() {
       super.cleanup();
       PhysicsWorld.getInstance().cleanup();
    }

    /**
     * Gets called every frame.
     */
    protected void simpleUpdate() {
       PhysicsWorld.getInstance().update(tpf);
    }

    public static void main(String[] args) {
       SimpleTest app = new SimpleTest();
       app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG, SimpleTest.class
             .getClassLoader().getResource(
                   "jmextest/data/images/jmephysics_logo.png"));
       app.start();
    }
 }