I’m trying to make a ship auto level so that the belly of the ship stays facing the planet. I found the answer in 2.5D*, but I can’t get it to work in 3D.
//world rotation * up
Vector3f spatialY = control.getPhsicsRotation().mult(Vector3f.UNIT_Y);
Vector3f cross = spatialY.crossLocal(Vector3f.UNIT_Y).normalizeLocal();
* Stuck on the ground with no roll (like Doom, COD, etc.).
I’m trying to find a rotation perpendicular to the center/surface of the planet. The math is at the edge of my understanding. I found a great link on wiki, but I don’t understand the formulas.
I can not tell if I am looking for
- The final vector to adjust, over time,
- The cross-product difference between what I have and what I want,
- A ‘normal’ perpendicular to a plane,
- A normal to the tangent plane,
Or if I am trying to align the x and z angles to the plane. How do I get the plane?
The next step will be to rotate the ship on the Y (up) axis and face prograde – with orbit, retrograde – opposite orbit, orbit +/- to align the plane with another orbiting body.
Vector3f startVector;
Vector3f currentVector;
Vector3f endVector;
Vector3f upVector;
Vector3f tempVector;
Vector3f spatialY;
Vector3f cross;
Vector3f v;
public void autoLevel(String action, boolean isPressed){
autoLevel = (autoLevel == false);
if (autoLevel){
upVector = Vector3f.UNIT_Y;
//start
float[] rad = new float[3];
spatial.getWorldRotation().toAngles(rad);//local
//start vector
startVector = new Vector3f(rad[0], rad[1], rad[2]);
//current vector
currentVector = new Vector3f(rad[0], rad[1], rad[2]);
//end vector
endVector = new Vector3f(rad[0], rad[1], rad[2]);
//test
spatialY = endVector.mult(Vector3f.UNIT_Y);
cross = spatialY.cross(Vector3f.UNIT_Y);
}
}
private void doAutoLevel(float tpf){
//current
float[] rad = new float[3];
spatial.getWorldRotation().toAngles(rad);
currentVector = new Vector3f(rad[0], rad[1], rad[2]);
//if cross it the difference between my current and end rotations...
massControl.rotate(cross);
autoLevel = false;//shut off for testing
if (true) return;
//Or...
if (currentVector.x < endVector.x - 0.01f)
pitchDown("PitchUp", true);
else if (currentVector.x > endVector.x + 0.01f)
pitchUp("PitchDown", true);
else{
currentVector.x = endVector.x;
pitchDown("PitchDown", false);
pitchUp("PitchUp", false);
massControl.setSpin(0, 0f);
}
if (currentVector.y < endVector.y - 0.01f)
yawRight("YawRight", true);
else if (currentVector.y > endVector.y + 0.01f)
yawLeft("YawLeft", true);
else{
massControl.setSpin(1, 0f);
yawLeft("YawLeft", false);
yawRight("YawRight", false);
currentVector.y = endVector.y;
}
//
if (currentVector.z < endVector.z - 0.01f)
rollLeft("RollLeft", true);
else if (currentVector.z > endVector.z + 0.01f)
rollRight("RollRight", true);
else{
massControl.setSpin(2, 0f);
rollLeft("RollLeft", false);
rollRight("RollRight", false);
currentVector.z = endVector.z;
}
}//doAutoLevel
//And the gravity routine that I found after searching for years...
private synchronized void doGravity(){
//delay -= 1.0f;
//if (delay > 0) return;
//delay = app.getTimer().getFrameRate();
//ArrayList<Node> bodyList = getBodyList();
List list = getMasses(rootNode);
for (int a = 0;a < list.size();a++){
Node p1 = (Node)list.get(a);
MassControl massControl = p1.getControl(MassControl.class);
float m1 = massControl.getMass();
//System.out.println("EnvironmentalControl.doGravity()" + ", processing p1=" + p1.getName());
Vector3f acc = new Vector3f();
if (list.size() > 1){
//if (p.getName().equals("Moon")) System.out.print("acc=");
for (int b = 0;b < list.size();b++){
Node p2 = (Node)list.get(b);
if (p1.equals(p2)) continue;
Vector3f unit = new Vector3f(p2.getWorldTranslation().subtract(p1.getWorldTranslation()));
float magnitude = (float)Math.sqrt((unit.x * unit.x) + (unit.y * unit.y) + (unit.z * unit.z));
float m2 = p2.getControl(MassControl.class).getMass();
//if (p1.getName().equals("Ship 01") && p2.getName().equals("Earth") || p2.getName().equals("Ship 01") && p1.getName().equals("Earth"))
//System.out.println("OrbitMaker.doGravity(" + p1.getName() + ")(" + p2.getName() + ") m1=" + m1 + ", m2=" + m2 + ", unit=" + unit + ", magnitude=" + magnitude);//do gravity
if (magnitude != 0.0f && (m1 * m2 != 0.0)){
float factor = (G * (
(m1 * m2) / (magnitude * magnitude * magnitude)
)) / m1;
unit = unit.mult(factor);
//if (p1.getName().equals("Ship 01")) System.out.println("OrbitMaker.doGravity(" + p1.getName() + ")(" + p2.getName() + "): factor=" + factor + ", unit=" + unit + ", acc=" + acc);
}
else{
unit.set(0.0f, 0.0f, 0.0f);
}
acc = acc.add(unit.clone());//.mult(tpf));
//collision check
if (areClose(p1, p2)){
collisionQueue.add(new CollisionGroup(p1, p2));
}
}
}
//if (p.getName().equals("Moon")) System.out.println(acc + ", ");
//Vector3f velocity = p.getControl(MassControl.class).getVelocity();
//if (p.getName().equals("Moon")) System.out.println("OrbitMaker.doGravity(" + p.getName() + "): acc=" + acc);
massControl.addToVelocity(acc);
}
//System.out.println();
}//doGravity