Locking rotation of dynamic physics object

I have a problem i tried to solve for some time but i just can’t get it done and find myself hacking around with ugly code in the end. As i also didn’t find any hints in the forum, i hoped you could help me out…

I am making a game with 2D-Gameplay. It’s about navigating a spaceship around “planets” (multiple gravity sources) using orbits. Much like Lunar Lander but with more complex gravity.
Locking movement on the z-axis was no problem. The physics work fine, theres just the problem that i want the ship to only rotate on the z-Axis. When the player is hitting left or right arrow buttons, i apply a torque force to rotate the ship (CW/CCW). Now when it bumps into something, it can happen that it starts rotating in other dircetions, too. Is there any way i can prevent this? Any approach i could try?
I was messing around with Quaternions until it melted my brain, but i don’t seem to get it to work.

Thanks a lot in advance!

You could try switching to a 2D physics engine like dyn4j. You will get a much simpler and more performant engine out of the deal, too. 3D physics is an order of magnitude more complicated than 2D physics and performance scales accordingly.

thanks, i am aware a 3D-game needs more recources, but it WILL BE a 3D-Game, just the gameplay will happen on a 2D basis.
Apart from using a different engine, do you have any suggestions on how to handle this?
Thanks again!

dyn4j is just a physics engine. It’s a 2D physics engine and thus vastly simpler than bullet. I’m saying… use JME but do your physics with dyn4j. Integration is not hard and it solves all of your problems.

Thank you! I will look into that!
I realized that what i want is exactly what the BetterCharacterControl does - it is always “upright” on the y-axis and the Character can never tip over. I just need this for the z-axis, so i will try to look into how BetterCharacterControl does it, maybe i can adapt it.
I i don’t succeed, i’ll have to try the physics engine you mentioned. Thanks again for the hint!

Cool… let us know if you head down the dyn4j path and have issues. Quite a few have used dyn4j in their games, I think (I’m one of them)… so you should be able to get help if you get stuck.

I just tried to get the WIP plugin for integration of dyn4j with jme3 mentioned here working: Dyn4j integration
…unfortunately there is no documentation whatsoever and it also appears that it’s far from complete. How complicated is it to integrate dyn4j in a specific project from scratch? I am really interested in 2D-Physics for jme3 - for this and also future projects!
EDIT: Or DOES this plugin already work and i just don’t understand how to use it?

I don’t know anything about that plugin.

In my case, I just setup things myself. An app state to setup the dyn4j “world” and add some bodies to it… then I sync the body position to the nodes. Hard for me to explain further because I use an entity system in my games so it would probably get confusing. :slight_smile:

I succeeded integrating it into my project and i like the idea a lot. Somehow things stopped moving after 2 seconds and i don’t know why - but it looks like an interesting approach, i will look into it for future needs.
Anyway, i have the impression it’s not the right way to go for my current project. I will keep trying to solve this problem and report back.
Thanks again!

Just FYI i also used dyn4j with that plugin and it’s worked pretty well, but i had to use a physics joint (motor joint) to move my character, i don’t know if it’s was good solution. Looking forward for yours.

BTW i think you can also lock a rotation with a physic joint (they reduce a degree of freedom see : here )

dyn4j physics joints : https://code.google.com/p/dyn4j/wiki/Joints (with nice pictures)

I succeeded locking and controlling rotation of the physics object by using .setAngularVelocity(…)…

Vector3f angV = physics.getAngularVelocity();
physics.setAngularVelocity(new Vector3f(0 ,0 ,angV.z));

Note that “physics” here is the RigidBodyControl of the object of interest.
It works perfectly for me.
Nonetheless i love the possibility to use 2D physics and will use it in the future! Thank you guys for introducing me to dyn4j!

I’m currently playing around with physics, and I’m wondering about your solution. What happens if the space ship bumps into something that would make the rigid body spin on another axis? (something hits you on the side)

The reason for me asking is that I had to prevent that effect by using setAngularFactor(0). Otherwise simply falling onto a surface would change body orientation (unless the surface is perfectly perpendicular to the movement direction). But that affects ALL rotations, so applying an angular velocity manually would not result in a rotation anymore.

Note that you can set the velocity in the prePhysics method, but when a collision happens during the physics tick, an impulse will be applied automatically, and its resulting movement will be executed in the current tick. you can set it back to 0 before the next physics tick is executed, but you can’t prevent the initial impulse that way. It will always result in a possibly unwanted rotation for exactly tpf seconds.

Just set the rotational velocity to zero on the physics tick, that should be okay.

Unfortunately, that does not prevent the movement. It only cancels it after it has been initialized (and executed once) by the physics engine.

Simple test: warp into the air and set the velocities to zero each tick. No matter where you put that line of code, the body still falls. Slowly, because the acceleration is stopped immediately each tick, but it still falls.
The physicsTick method in the PhysicsTickListener is more of a postPhysicsTick method. It seems to be called after the physics have executed all the calculated movement.
For this method to completely cancel the movement, it would have to be called after the physics tick does its calculations, but before the movements are actually executed.

EDIT: added test code:

package start;

import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AppState;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.PhysicsTickListener;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.objects.PhysicsRigidBody;
import com.jme3.math.Vector3f;

public class GravityTest extends SimpleApplication implements
PhysicsTickListener {

public GravityTest() {
}

public GravityTest(AppState... initialStates) {
    super(initialStates);
}

public static void main(String[] args) {
    GravityTest app = new GravityTest();
    app.start();
}

private CollisionShape shape = new BoxCollisionShape(new Vector3f(1, 1, 1));
private float mass = 100;
private PhysicsRigidBody player = new PhysicsRigidBody(shape, mass);
private Vector3f gravity = new Vector3f(0f, -9.81f, 0f);

@Override
public void simpleInitApp() {
    player.setGravity(gravity);
    BulletAppState bulletAppState = new BulletAppState();
    stateManager.attach(bulletAppState);
    bulletAppState.getPhysicsSpace().addTickListener(this);
    bulletAppState.getPhysicsSpace().add(player);
}

@Override
public void physicsTick(PhysicsSpace space, float tpf) {
    player.setLinearVelocity(Vector3f.ZERO);
    }

@Override
public void prePhysicsTick(PhysicsSpace space, float tpf) {
    player.setLinearVelocity(Vector3f.ZERO);
}

/**
 * game loop
 */
@Override
public void simpleUpdate(float tpf) {
    System.out.println("position: " + player.getPhysicsLocation());
}

}

Its possible that its computing position by doing this:

velocity += acceleration;
position += velocity;

instead of doing this:

position += velocity;
velocity += acceleration;

In that case, even if you set velocity to zero every tick, the position will still change.

Well, even aside from that… when a collision happens then it has to be resolved and the resolution might spin the object slightly.

The best way to do 2D physics is with a 2D physics engine, really.

I don’t know if Bullet lets you set your own interia tensor but that’s another way to mitigate the twisting… or you could just post-correct every frame. Doing 2D physics in a 3D physics engine is going to have these sorts of edge cases.

Bullet does allow setting the inertia (3D vector):

Native Bullet:
http://bulletphysics.org/Bullet/BulletFull/classbtRigidBody.html#a912b4a273bcd6fe9af25c47106db900c

JBullet:
http://jbullet.advel.cz/javadoc/com/bulletphysics/dynamics/RigidBody.html#setMassProps(float,%20javax.vecmath.Vector3f)

I totally feel for you :smile:, but I managed to struggle myself through the rarely documented class of Quaternions and found the holy grail of rotation:
exampleQuaternion.lookAt(Vector3f direction, Vector3f up)
This will make your character look at whatever direction you desire. So to always ensure your character to stand up the direction you want, put the according unity vector Vector3f.UNITY_? into the up direction. Then turn your char by putting a slightly rotated version of your former “forward” direction into the forward variable and there you go :wink:

:point_right: Be warned :point_left: that rotating your char that way will not satisfy the rules of physics, because it is instant and analogue to the method warpTo(Vector3f position).

To then cancel any unwanted rotations arising from angular forces you may use the already mentioned

function.

I hope I could help :smile:

It does work, the BetterCharcterControl does the same, theres a prePhysicsTick and physicsTick method.

You can also use a 6DOF joint and constrain the object to two dimensional movement like done here
edit : the link don’t show a solution with a constraint (or joint) but with the RigidBody. I don’t know if this is supported with jBullet.