Making an object hover purely by applying forces [FIXED]

Is there a way to make objects hover by applying a force to compensate for the gravity? A simple testcase does not what I expected it to do:

[java]package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.bullet.BulletAppState;

import com.jme3.bullet.PhysicsSpace;

import com.jme3.bullet.PhysicsTickListener;

import com.jme3.bullet.control.RigidBodyControl;

import com.jme3.light.AmbientLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.shape.Box;



/**

  • test
  • @author normenhansen

    /

    public class Main extends SimpleApplication implements PhysicsTickListener

    {

    Node ship;

    RigidBodyControl ship_phy;



    public static void main(String[] args) {

    Main app = new Main();

    app.start();

    }



    @Override

    public void simpleInitApp() {



    BulletAppState bulletAppState = new BulletAppState();

    stateManager.attach(bulletAppState);

    bulletAppState.getPhysicsSpace().addTickListener(this);

    bulletAppState.getPhysicsSpace().setMaxSubSteps(4);

    bulletAppState.getPhysicsSpace().setGravity(new Vector3f(0f,-10f,0f));





    ship = new Node();





    Box b = new Box(Vector3f.ZERO, 1, 0.1f, 1);

    Geometry geom = new Geometry("Box", b);



    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat.setColor("Color", ColorRGBA.Blue);

    geom.setMaterial(mat);



    Box bx = new Box(new Vector3f(0, 1, 0), 0.1f, 0.1f, 0.1f);

    Geometry geomx = new Geometry("Box", bx);

    Material matx = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    matx.setColor("Color", ColorRGBA.Red);

    geomx.setMaterial(matx);



    AmbientLight al = new AmbientLight();

    al.setColor(ColorRGBA.White.mult(1.3f));

    rootNode.addLight(al);





    ship.attachChild(geomx);



    ship_phy = new RigidBodyControl(1f);

    ship.addControl(ship_phy);

    rootNode.attachChild(ship);

    bulletAppState.getPhysicsSpace().add(ship_phy);

    ship_phy.setPhysicsLocation(new Vector3f(0, 0.5f, 0));





    rootNode.attachChild(geom);





    }



    @Override

    public void simpleUpdate(float tpf) {

    //TODO: add update code

    }



    @Override

    public void simpleRender(RenderManager rm) {

    //TODO: add render code

    }



    public void prePhysicsTick(PhysicsSpace space, float f)

    {

    ship_phy.applyForce(new Vector3f(0,10f,0), ship_phy.getPhysicsLocation());

    //ship_phy.applyImpulse(new Vector3f(0,0.1f,0), new Vector3f(0,0,0));

    }



    public void physicsTick(PhysicsSpace space, float f)

    {

    //throw new UnsupportedOperationException("Not supported yet.");

    }

    }

    [/java]





    The red box will be pushed up, while the force applied to it is equal to the force of gravity. I assume it is not as easy as in real world, but can somebody explain to me why this is happening? Normally, I would say that the force to compensate for the gravity would be m
    g, but in this case this does not work. I have set g to -10, mass to 1 and the counterforce to 10, but still the box is pushed up.

Try 10f*f instead of 10f in prePhysicsTick.

1 Like

Darn!



Almost works, just had to do applyImpuls instead of applyForce, together with the 10ff @zarch suggested:



[java]ship_phy.applyImpulse(new Vector3f(0,10f
f,0), new Vector3f(0,0,0));[/java]



This makes the block perfectly steady in the air.



I have been fiddling around a lot with applyImpulse, just not added the f! :roll:



Now back to the drawing board of the ship simulator to work on the buoyance a little bit more :smiley:

1 Like

Yeeh. I don’t know the physics system but in real system a force has to be applied over time to do anything.



I guessed that the incoming f was the physics equivalent of tpf and applied it to the force :slight_smile:

yh f is tpf, I applied a patch to this a few weeks ago, as usual I just get ignored :slight_smile: normen <3



here it is again, hopefully the file hasn’t changed as I just copy and pasted it from my other post:

[patch]

This patch file was generated by NetBeans IDE

It uses platform neutral UTF-8 encoding and n newlines.

— Base (BASE)

+++ Locally Modified (Based On LOCAL)

@@ -1,5 +1,5 @@

/*

    • Copyright © 2009-2010 jMonkeyEngine
    • Copyright © 2009-2012 jMonkeyEngine
  • All rights reserved.

    *
  • Redistribution and use in source and binary forms, with or without

    @@ -42,13 +42,13 @@
  • @param space the physics space
  • @param tpf the time per frame in seconds

    */
  • public void prePhysicsTick(PhysicsSpace space, float f);
  • public void prePhysicsTick(PhysicsSpace space, float tpf);



    /**
  • Called after the physics has been stepped, use to check for forces etc.
  • @param space the physics space
  • @param tpf the time per frame in seconds

    */
  • public void physicsTick(PhysicsSpace space, float f);
  • public void physicsTick(PhysicsSpace space, float tpf);

    }

    [/patch]
1 Like

I just want to call attention to this, it seems to be a bug. Like @husky, I had to use applyimpulse() instead of applyforce(). Is this a bug?

Correct me if I’m wrong. I want to know if this is a bug so we fix this.

Edit: This is not a bug. See the following post.

@Pixelapp said: I just want to call attention to this, it seems to be a bug. Like @husky, I had to use applyimpulse() instead of applyforce(). Is this a bug?

Correct me if I’m wrong. I want to know if this is a bug so we fix this.

Well, a force of 10 is a teeny tiny force by any standards and certainly no where near large enough to counteract gravity… which would mass * 10 as a force.

F = ma… so forces must include mass.

Yes, with mass = 400 and gravity = 10 this works.

public void prePhysicsTick(PhysicsSpace space, float tpf) 
{
    
    player.applyForce(new Vector3f(0,400*10,0f), new Vector3f(0,0,0));

}

Thanks for the explanation. @pspeed :).

Just a sidenote, why not just set the Gravity to 0,0,0 ? does the same actually without applying gravity and couterforce for each tick

This leads me to consider a thrust vectoring controller class that can be added to a spatial where you can then tinker with impulse points as offsets from the local position of the spatial and the thrust vector values themselves. Could make for a handy class for lunar landers and beyond. :roll: