Here's some handy code from the 3D space shooter we're working on. It's just about everything needed to do basic Newtonian motion in 3D. It's in Actionscript, but the general ideas apply anywhere.
//apply a force to position "forcePos" with force vector "force" in either local or global coordinates
public function ApplyForce(forcePos:Vector3D, force:Vector3D, dt:Number, localCoords:Boolean = true) : void
{
var torque:Vector3D = new Vector3D(0, 0, 0, 1);
var accel:Vector3D = new Vector3D(0, 0, 0, 1);
if(localCoords) //------- if data given relative to local space --------
{
torque.x = (forcePos.y*force.z-forcePos.z*force.y); //find torque
torque.y = (forcePos.z*force.x-forcePos.x*force.z);
torque.z = (forcePos.x*force.y-forcePos.y*force.x);
accel.x = force.x/mass; //local coordinate acceleration
accel.y = force.y/mass;
accel.z = force.z/mass;
accel = MatrixMult.Multiply(rot.GetMatrix(), accel); //rotate to global coords
}
else //------- if data given relative to global space -------
{
accel.x = force.x/mass; //global coordinate acceleration
accel.y = force.y/mass;
accel.z = force.z/mass;
//get inverse rotation
var invRot:Vector.<Number> = MatrixMult.InvMatrix(rot.GetMatrix());
//local position w/o de-rotating
forcePos.x -= pos.x;
forcePos.y -= pos.y;
forcePos.z -= pos.z;
//rotate to local space
forcePos = MatrixMult.Multiply(invRot, forcePos);
force = MatrixMult.Multiply(invRot, force);
torque.x = (forcePos.y*force.z-forcePos.z*force.y); //find torque
torque.y = (forcePos.z*force.x-forcePos.x*force.z);
torque.z = (forcePos.x*force.y-forcePos.y*force.x);
}
velocity.x += dt*accel.x; //apply acceleration
velocity.y += dt*accel.y;
velocity.z += dt*accel.z;
//calculate angular velocity change based on mass and angular inertia from shape of object
var deltaRotVel:Vector3D = rotMoment.CalcVelocity(torque, dt);
rotVel.x += deltaRotVel.x; //apply angular acceleration
rotVel.y += deltaRotVel.y;
rotVel.z += deltaRotVel.z;
}
public function Update(dt:Number) : void
{
//update rotation
var mag:Number = Math.sqrt(rotVel.x*rotVel.x+rotVel.y*rotVel.y+rotVel.z*rotVel.z);
if(mag != 0)
{
var rotation:Quatern = new Quatern(rotVel.x/mag, rotVel.y/mag, rotVel.z/mag, mag*dt);
rot = Quatern.Mult(rotation, rot);
}
//update position
pos.x += velocity.x*dt;
pos.y += velocity.y*dt;
pos.z += velocity.z*dt;
}
A couple notes on meaning of some called functions and actionscript-isms:
dt is the change in time since the previous update (pretty obvious)
variables are declared with the syntax 'var VarName:VarType' in actionscript
Vector3D is just a wrapper for a 4 element vector, with elements x,y,z,w (in that order)
'Number' is the class for floating point values
Vector.<Number> is a resizeable array of floating point values
MatrixMult has a bunch of handy static function for matrix operations; both multiplying matrices together and matrices multiplied by a Vector3D
rot is a quaternion keeping track of the object's rotation (makes things a hell of a lot easier, learn about quaternion rotations
here)
rot.GetMatrix() returns the rotation matrix of the object
the Quatern class takes in the x, y, z orientation of the axis of rotation, and the scalar of magnitude of the rotation around that axis in radians and turns it into a quaternion using the following code:
public function Quatern(xPart:Number=0, yPart:Number=0, zPart:Number=0, theta:Number=0)
{
w = Math.cos(theta/2);
var si:Number = Math.sin(theta/2);
x = xPart*si;
y = yPart*si;
z = zPart*si;
}
rotMoment.CalcVelocity takes the torque, multiplies it by dt, then divides it by the moment of inertia; in this case, equations from
this list of moments of inertia for different shapes of objects. It essentially goes through the equation 'angular acceleration = torque/moment of inertia,' then finds the change in angular velocity by factoring in the change in time.
If you can find a force acting on an object and the place at which it is acting, it does all the rest for you; both motion and rotation
tldr; yay Euler Integration!