Point gravity?

As i understand the physics code, right now there is just one gravity force applyed to all DynamicPhysicObjects in one direction much like directional lighting.



Do You plan to support point gravity (like point lights) at a future release ?



This’s a theoretical question at the moment but i think of a solar system with gravity centers for each of the planets here, merged automagically by the physics system and applyed to the DynamicPhysicsObjects in the PhysicsWorld - or just one planet that has a gravity center dragging all objects to it’s surface.

Hehe, i have actually implemented something exactly like that!



In short, im not sure if it would make it to the core…I have to speak to per about it…



But if you can’t wait that long, heres a little snippet from an experiment I did that does exactly what you want:



public class PlanetManager {

   // the singleton instance of this manager
   private static PlanetManager instance;

   // an arraylist containing all the planets
   private ArrayList planets;

   // some temporary variables that used inside the update method
   private DynamicPhysicsObject currentObj;
   private Vector3f currentObjPos;
   private DynamicPhysicsObject effectorObj;
   private Vector3f effectorObjPos;
   private Vector3f directionOfForce;

   /**
    * Constructor for this manager.
    */
   private PlanetManager() {
      planets = new ArrayList();
   }

   /**
    * Obtains the single instance of this manager in the JVM. If it doesn't
    * exist, a new one is made
    *
    * @return
    */
   public static PlanetManager getInstance() {
      if (instance == null) {
         instance = new PlanetManager();
      }
      return instance;
   }

   /**
    * Add a planet to this manager
    *
    * @param obj
    */
   public void addPlanet(PhysicsObject obj) {
      planets.add(obj);
   }

   /**
    * Remove a planet from this manager so that its gravitational force can now
    * be ignored
    *
    * @param obj
    */
   public void removePlanet(PhysicsObject obj) {
      planets.remove(obj);
   }

   /**
    * Remove all planets. Good when changing levels.
    */
   public void clear() {
      planets.clear();
   }

   /**
    * Apply the forces of the planets onto this object
    *
    * @param obj
    */
   public void applyForcesOnto(DynamicPhysicsObject obj) {
      for (int j = 0; j < planets.size(); j++) {
         // loop through all planets except the current one
         DynamicPhysicsObject effector = (DynamicPhysicsObject) planets.get(j);
         // get their positions
         Vector3f effectorPos = effector.getJmeGeometry()
               .getLocalTranslation();
         // obtain the distance squared between them
         float distance2 = effectorPos.distanceSquared(obj.getJmeGeometry()
               .getLocalTranslation());
         // calculate the GMm
         float GMm = (float) (obj.getMass() * effector
               .getMass());
         // obtain the total force
         float force = GMm / distance2;

         // calculate the distance between the two objects.
         directionOfForce = effectorPos.subtract(obj.getJmeGeometry().getLocalTranslation());
         // normalise to obtain a direction
         directionOfForce.normalize();
         // multiply the scalar force by the directional vector
         directionOfForce.mult(force);

         // add the force obtain from this planet onto the
         // current
         // one
         obj.addForce(directionOfForce);
      }
   }

   /**
    * @param time
    */
   public void update(float time) {
      for (int i = 0; i < planets.size(); i++) {
         // obtain the current physics object that the rest will apply their
         // gravity on
         currentObj = (DynamicPhysicsObject) planets.get(i);
         // also get its position
         currentObjPos = currentObj.getJmeGeometry().getLocalTranslation();
         // make sure the object is not static. Otherwise, the force that is
         // calculated
         // would have no effect
         if (currentObj.isStatic() == false) {
            for (int j = 0; j < planets.size(); j++) {
               // make sure you dont need to carry out unnessary
               // calculations
               if (i != j) {
                  // loop through all planets except the current one
                  effectorObj = (DynamicPhysicsObject) planets.get(j);
                  // get their positions
                  effectorObjPos = effectorObj.getJmeGeometry()
                        .getLocalTranslation();
                  // obtain the distance squared between them
                  float distance2 = effectorObjPos
                        .distanceSquared(currentObjPos);
                  // calculate the GMm
                  float GMm = (float) (6.6765e-11 * currentObj.getMass() * effectorObj
                        .getMass());
                  // obtain the total force
                  float force = GMm / distance2;

                  // calculate the distance between the two objects.
                  directionOfForce = effectorObjPos
                        .subtract(currentObjPos);
                  // normalise to obtain a direction
                  directionOfForce.normalize();
                  // multiply the scalar force by the directional vector
                  directionOfForce.mult(force);

                  // add the force obtain from this planet onto the
                  // current
                  // one
                  currentObj.addForce(directionOfForce);
               }
            }
         }
      }
   }
}



Basically, add physics objects (whether they are dynamic or not) and call update...

the rest is history :)

If you want centripetal gravity (i.e planets), just make sure to give the object a force that is perpedicular to the point of gravity, so that the "Moon" will revolve around the planet.

DP

DP

Oh yer, theres another method in there “applyForcesOnto” which calculates the force at which the arguments’ dynamicPhysicsObject is taking on and adds it onto that object. It will not affect the gravity of other planets or whatnot…



So basically apply the forces onto the player :slight_smile:



DP

Hey, one can get the impression that You jme/physics guys have a full fledged game system in the hat and unvail parts of it as people ask for it 8-O



ok, kidding :wink: but i have a hard time trying out all this new jme / physics stuff as it emerges.



In short: thanks, that is what i thought of.



My 2 cent are that this should go into the core although something generalized (names changed to reflect this is a more general solution than to drive planets) and eventually a constructor that automtically retrieves all phys objects in a phys world (i’m all for keeping things simple for the user (erm… thats me in this case :wink: ))

I spoke with per about it for some time last night and we decided to include it for v0.5. Ive done that and its ready to go into CVS as soon as I can get home!



DP

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

great :slight_smile:



i can’t wait till i get the time to try this out