Planet/Point Gravity in JME Physics 2

Hi I am looking for a way get point gravity in jME Physics 2.



Is there any example of Planet or Point Gravity out there?



As of April 1st 2005 according to DarkProphet:


Whats in CVS now:

Plane Gravity:
This is just like normal whereby you move towards an infinite plane/direction. I.e what we currently have and that is the default. This also happens to be the fastest as ode can handle it

Point Gravity:
All the DynamicPhysicsObjects will be attracted towards a point in space that is settable. Thing like a blackhole that doesnt suck everything up. Things can collide and whatnot...
This is slow, but faster than Planet as there only needs to be one loop through the array of physicsObjects

Planet Gravity:
All the DynamicPhysicsObjects will be attracted towards each other as tho they are a planet and a moon. Notice i said ALL, i.e. whatever is in the physics system that is dynamic will be affected. This is good for simulations of a solar system whereby the sun is in the middle and all the planets revolve around it. Now the equations i used are highly dependant on the mass of the object. I.e an object with a mass of 1 will have less of a force on the player than an object with a mass of 1000. Thus the sun should have a very high mass so that all the others are attracted to it. This is the slowest of the lot as we have two inner loops both looping through the physicsObjects list. No object creation happens in those loops,  so I've optimised as much as I can in that area, its up to HotSpot to do the rest...

Those are all the gravity modes we currently support and their limitations are known. I.e you cant have 3 different rooms whereby each one has a different gravity mode. But im thinking of a way to do this..so stay tuned!

Ive included a test called TestGravityModes, thats also in CVS. Check it out.

DP


Have you given up on this or can I somehow use Point or Planet Gravity in jME Physics 2  as well?

Please respond.

//Considerate

You can implement it easily in a physics callback. Have a look into the classes for dampening/friction (don't have the name present, sorry). Essentially you would be applying a force dependant on the distance from the gravity point on each dynamic physics node.

i made a small PhysicsUpdateCallback which represents a black hole or magnet.

Basically it does the following:

  • get the distance between the dynamic node and the black hole
  • get the direction from the node to the hole
  • apply force based on the initial force of the black hole, the dynamic nodes mass and the distance.



    So you could add one of those Callbacks per planet.



    Its pretty interesting to watch the how the physic objects react, if two or more black holes or magnets are in the scene.



import com.jme.bounding.BoundingSphere;
import com.jme.input.InputHandler;
import com.jme.input.KeyInput;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.shape.Sphere;
import com.jmetest.physics.Utils;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.PhysicsNode;
import com.jmex.physics.PhysicsSpace;
import com.jmex.physics.PhysicsUpdateCallback;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.material.Material;
import com.jmex.physics.util.SimplePhysicsGame;

public class TestPointGravity extends SimplePhysicsGame {

    @Override
    protected void simpleInitGame() {
        display.getRenderer().setBackgroundColor(ColorRGBA.lightGray);
        // turn off directional gravity
        getPhysicsSpace().setDirectionalGravity(new Vector3f());
       
        // create black holes, which are basically like a magnet
        Node blackHole = createBlackHole();
        blackHole.setLocalTranslation(-15, 5, -5);
        rootNode.attachChild(blackHole);
        getPhysicsSpace().addToUpdateCallbacks(
                new PointGravityCallback(blackHole.getLocalTranslation(), 5000));
       
        blackHole = createBlackHole();
        blackHole.setLocalTranslation(0, -15, -10);
        rootNode.attachChild(blackHole);
        getPhysicsSpace().addToUpdateCallbacks(
                new PointGravityCallback(blackHole.getLocalTranslation(), 5000));
       
        blackHole = createBlackHole();
        blackHole.setLocalTranslation(15, -5, -4);
        rootNode.attachChild(blackHole);
        getPhysicsSpace().addToUpdateCallbacks(
                new PointGravityCallback(blackHole.getLocalTranslation(), 5000));
       
 
       
        // create a new physics object
        input.addAction( new InputAction() {
            public void performAction( InputActionEvent evt ) {
                if ( evt.getTriggerPressed() ) {
                    DynamicPhysicsNode node = getPhysicsSpace().createDynamicNode();
                    Sphere ball = new Sphere( "ball", 10, 10, (float)Math.random()+0.2f);
                    ball.setModelBound(new BoundingSphere());
                    ball.updateModelBound();
                    Utils.color( ball, ColorRGBA.blue, 10 );
                    node.attachChild( ball );
                    node.generatePhysicsGeometry();
                    node.setMaterial( Material.RUBBER );
                    node.computeMass();
                    node.setLocalTranslation(cam.getLocation().clone());
                    node.addForce(cam.getDirection().mult(node.getMass()*1000));
                    rootNode.attachChild( node );
                    rootNode.updateRenderState();
                }
            }
        }, InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_SPACE, InputHandler.AXIS_NONE, false );
    }

    /** a static sphere representing a black hole */
    private Node createBlackHole() {
        Sphere blackHole = new Sphere("blackHole", 15, 15, 1);
        blackHole.setModelBound(new BoundingSphere());
        blackHole.updateModelBound();
        Utils.color(blackHole, ColorRGBA.black, 128);
        StaticPhysicsNode blackHoleNode = getPhysicsSpace().createStaticNode();
        blackHoleNode.attachChild(blackHole);
        blackHoleNode.generatePhysicsGeometry();
        return blackHoleNode;
    }

    /** a Physics callback, which represents a black hole or Magnet
     *  with a location, initial force and max range.
     */
    private class PointGravityCallback implements PhysicsUpdateCallback {
        private Vector3f position;
        private float force;
        private float maxRadius = 10;
       
        public PointGravityCallback (final Vector3f position, float force) {
            this.position = position;
            this.force = force;
        }
       
        /** add the point gravity to all dynamic nodes */
        public void afterStep(PhysicsSpace space, float time) {
            for (PhysicsNode n: space.getNodes()) {
                if (n instanceof DynamicPhysicsNode) {
                    DynamicPhysicsNode dyn = (DynamicPhysicsNode)n;
                    // found a dynamic physics node, apply gravity
                    float distance = n.getLocalTranslation().distance(position);
                   
                    // check in which direction we need to apply the force
                    // subtract the location of the dynamic node from the
                    // black holes location and normalize it
                    Vector3f direction = position.subtract(n.getLocalTranslation()).normalize();
                   
                    // add the force
                    dyn.addForce(direction.mult(force*dyn.getMass()).divide(100/maxRadius*distance));
                }
            }
        }
        public void beforeStep(PhysicsSpace space, float time) {
        }
    }
   
    public static void main(String[] args) {
        new TestPointGravity().start();
    }
}

Hi



Now I've set up a method in simpleUpdate() of SimplePhysicsGame.

So what I have is simply this:


      java.util.List l = getPhysicsSpace().getNodes();
      Object[] myArr = l.toArray();
      for(Object currNode : myArr)
      {
         if(currNode instanceof DynamicPhysicsNode)
         {
         DynamicPhysicsNode currDynaNode = (DynamicPhysicsNode) currNode;
         currDynaNode.clearForce();
         Vector3f myPosition = currDynaNode.getLocalTranslation();
         Vector3f appliedForce = new Vector3f();
         appliedForce.set(myPosition.negate());
         currDynaNode.addForce(appliedForce);
         }
      }



How can I specify it to only move about 10 co-ordinates in that direction the first second and 20 more the next?
Right now I get the correct angle but I can't control it much.

One more thing, if I add mass to an object it moves even slower, opposite of what it would do reality.
Is there anything other than applying forces I should do?

I want a realistic gravity in my game and I need some help with this.

//Considerate

maybe you need to multiply the gravity force with the mass of the object.



when you apply the gravity force to the dynamic node, you shouldn't call clearForce(), you want to add the force of the gravity to the already existing forces on the node.

reminds of the effects package don't even have to do to much with it get explosions either consider adding it to Physics Fun, its been useful.



thanks on both counts

Thank you,

you have made it a lot easier for me.

This example works great but there is one thing that needs fixing with this.

When a ball get stuck by a black hole it doesn't stop. It keeps rotating around it with high speed.

If i change the ball to a box it gets jiggly when on the surface of the planets.



And does this really increase the speed for each second?



Thank you



//Considerate

The problem with the jiggly boxes were just that the spheres were too fine in structure, they had too many segments.

That made it impossible for a box or a sphere to stand still on the surface which made them move all the time.

Then I've also changed the force to this:


appliedForce.set(direction.mult( 9.81f*dyn.getMass()).divide(distance*distance/100f)  );



Now there is only the increasing speed issue left.
If you have any idea on how to solve that please post here

Thank you for all your help.

//Considerate

why do you want increasing speed over time ?

Is it not enough if it speeds up based on the distance from object <-> magnet ?