Simulating a Space Ship

I’m trying to model the flight behavior of a space ship using the physics engine. The behavior I want is more like an airplane where the ship’s linear velocity is always in the direction it’s facing, and there is friction on angular velocities. Just like X-Wing or other popular space sims.



I got most of it worked out expect the “roll” aspect of the ship. When the ship rolls (I’m applying angular velocity on UNIT_Z) all the other rotation controls are still relative to the original roll of the ship. So if i roll the ship on it’s side, Up becomes Right, Right becomes Down, etc.



I need to somehow take into account the current roll of the ship when applying angular velocities for pitch and yaw.



Any ideas?



Here is the code I’m working with:

[java]

if (name == “INPUT_Left”) {

entity.setAngularVelocity(entity.getAngularVelocity().add(new Vector3f(0f, 1f, 0f).mult(tpf)));

}

else if (name == “INPUT_Right”) {

entity.setAngularVelocity(entity.getAngularVelocity().add(new Vector3f(0f, -1f, 0f).mult(tpf)));

}

else if (name == “INPUT_Up”) {

entity.setAngularVelocity(entity.getAngularVelocity().add(new Vector3f(-1f, 0f, 0f).mult(tpf)));

}

else if (name == “INPUT_Down”) {

entity.setAngularVelocity(entity.getAngularVelocity().add(new Vector3f(1f, 0f, 0f).mult(tpf)));

}

if (name == “INPUT_RollLeft”) {

entity.setAngularVelocity(entity.getAngularVelocity().add(new Vector3f(0f, 0f, 1f).mult(tpf)));

}

else if (name == “INPUT_RollRight”) {

entity.setAngularVelocity(entity.getAngularVelocity().add(new Vector3f(0f, 0f, -1f).mult(tpf)));

}

if (name == “INPUT_ThrottleUp”) {

throttle += 5f * tpf;

entity.setLinearVelocity(entity.getRotation().getRotationColumn(2).mult(throttle));

}

else if (name == “INPUT_ThrottleDown”) {

throttle += -5f * tpf;

entity.setLinearVelocity(entity.getRotation().getRotationColumn(2).mult(throttle));

}

[/java]

Take a look at TestHoveringTank and PhysicsHoverControl in the jme3tests. Setting the velocities directly like this instead of applying forces will probably not give you very realistic looking results however creating a fly-by-wire system that properly controls a vehicle in a physics environment is something even NASA struggles with so its not exactly easy.

I have the same issue while using applyTorque instead of manipulating the angularVelocity directly. The problem is with my 3D math skills, I would have the same issue even if i wasn’t using the physics engine.



Let me illustrate:




  1. Imagine the box as the ship. I can pitch (X axis) and yaw (Y axis) without any issues.


  2. I roll the ship roughly 45 degrees. Notice how the X and Y axis do not rotate with the ship. Pitching and yawing now do not move the ship like you would expect.


  3. This is how it should be. Pitching and yawing now move the ship as you would expect.



    I need someway to have the axis of rotation roll with the ship, or some equations that translate the angularVelocity X and Y taking in account the roll.



    Hopefully that’s a little more clear.

Yeah, I can pretty much imagine what you want. Again, look at the PhysicsHoverControl and maybe start with reading this:

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:math_for_dummies

I had already gone through the primers. Good work BTW!



The HoverTank sample doesn’t really apply since tanks don’t roll or otherwise really behave how a spaceship does.



The solution isn’t apparent to me unfortunately.



I was hoping someone had a quick solution, guess I"ll have to dig into it more myself.



Thanks!

The solution is for you. A spaceship also needs to move around, counter forces etc… did you even look at the code??

Yes I examined the source closely before I posted here, and again after you suggested it.



The Hovertank only has to be steerable left and right (around the Y axis). A spaceship needs to steerable around X,Y, and Z. The Hovertank doesn’t have to worry about the issue I’m having.



My spaceship is working in all other ways. I can steer X and Y… Accelerate and decelerate. I’m applying an angular friction to slow turning, etc.



It’s really just this one issue.

You understand that this issue has been solved around another axis in the control already? X,Y,Z or just Y is not much of a difference.

After further experimentation I’ve decided not to use the physics engine to control the ship. I just set it to kinematic so I can set the rotation and position manually. I still get collision detection, which is really what i was after anyway. This seems to simplify rotating the ship and everything is working as expected.

Thanks for the help, appreciate it.

I think you should really try and implement a movement delay like in the HoverTank example.

It will give your game such an realistic feel, that it will be worth all the effort.

The problem is your giving vectors in world space along static axis’

What you need to do is get the current rotation matrix of the ship and use the Up, Left (or Right), and Forward vectors from the matrix as your inputs…



EDIT: To get these just grab the columns… Column 1 is the XAxis, Column 2 is the YAxis, and Column 3 is the ZAxis…

Thanks aeon, that worked!



I still might go with a non physics solution (I think i can fake a lot of the feel nego was talking about) but at least I have choices now.



Here is the fixed code for references purposes.

[java]

Vector3f xRotation = entity.getRotation().getRotationColumn(0).normalize();

Vector3f yRotation = entity.getRotation().getRotationColumn(1).normalize();

Vector3f zRotation = entity.getRotation().getRotationColumn(2).normalize();





if (name == "INPUT_Left") {

entity.setAngularVelocity(entity.getAngularVelocity().add(yRotation.mult(tpf)));

}

else if (name == "INPUT_Right") {

entity.setAngularVelocity(entity.getAngularVelocity().add(yRotation.mult(-tpf)));

}

else if (name == "INPUT_Up") {

entity.setAngularVelocity(entity.getAngularVelocity().add(xRotation.mult(tpf)));

}

else if (name == "INPUT_Down") {

entity.setAngularVelocity(entity.getAngularVelocity().add(xRotation.mult(-tpf)));

}



if (name == "INPUT_RollLeft") {

entity.setAngularVelocity(entity.getAngularVelocity().add(zRotation.mult(-tpf)));

}

else if (name == "INPUT_RollRight") {

entity.setAngularVelocity(entity.getAngularVelocity().add(zRotation.mult(tpf)));

}

[/java]

Actually it is pretty simple to solve physically fi you want some pseude real bahaviour

Set some abitraty points 100 meters in each direction of the ship(local coordiante system), these are you engine points.

now if you want to roll for example, apply on the upper a rightgoing force in the local coordiante system and on the bottom one a left going.

(This can of course be adjusted to fit the real engine positions, depending on how real the ship is modeld)