Recently I finally got some spare time again to go on with some of my long-planned-but-never-attempted modding projects, among these also the glide-based flight approach I intended for my dragon race mod for several years now.
As usual I'm going way too far in its implementation again, until down deep into actual aero-dynamics and force->acceleration->velocity math. I'm trying to simplify and abstract some concepts along the road, but it's basically still very convoluted physics formulae and vector math.
Anyways, I randomly stumbled across the observation I can get away without a floating invisible platform below the actor's feet even, by using the velocity functions provided by OBSE on the actor itself directly. Interestingly this also leaves most of the physics calculations still within the Havok engine, performed inbetween the frames, and I don't have to re-invent the entire physics engine all over again in my scripts instead.
This admittedly needs some more fine-tuning, as apparently by simply determining the current velocity and reapplying it unaltered in the same frame I already created a gliding movement with slowly decreasing horizontal motion and only little to almost no vertical declination so far, as if gravity almost didn't exist, but this aside what's giving me real headache is wrapping my head around the matrix-vector-calculations in regards to transformations from one coordinate system (the world's absolute, x, y, z) into another (the player's relative, right, forward, up) and vice versa by the player's x/y/z rotation angles exclusively.
For example I want to apply some movement upwards from a wing stroke, but according to the player's current pitch angle (GetAngle X), so it'll also go backwards some, if he's looking upwards above the horizon, or forwards, if looking downwards some. And of course the yaw angle (GetAngle Z) isn't unimportant here either, as there may be some velocity sideways still which shouldn't just get 'lost' by a wing stroke.
So having a 3-dimensional velocity vector in world coordinates describing the player's current motion, I need to convert this into components relative to the player's point of view (right, forward, upward), then add the relative motion from the player's gliding, or wing strokes, into it, and convert it back into the resulting new velocity vector in world coordinates again.
Now, I already have two conversion user functions doing the vector math for me:
Scn zzzGetVectorLocalfloat fVecXfloat fVecYfloat fVecZfloat fAngleXfloat fAngleYfloat fAngleZarray_var vVecarray_var vVecLocarray_var mRotationXarray_var mRotationYarray_var mRotationZarray_var mRotationYXZarray_var mRotationInvBegin Function {fVecX fVecY fVecZ} let vVec := ar_Construct Array let vVec[0] := fVecX let vVec[1] := fVecY let vVec[2] := fVecZ let vVec := ForceColumnVector vVec let fAngleX := GetAngle X let fAngleY := GetAngle Y let fAngleZ := GetAngle Z let mRotationX := GenerateRotationMatrix X fAngleX let mRotationY := GenerateRotationMatrix Y fAngleX let mRotationZ := GenerateRotationMatrix Z fAngleX let mRotationYXZ := MatrixMultiply mRotationX mRotationY let mRotationYXZ := MatrixMultiply mRotationZ mRotationYXZ let mRotationInv := MatrixInvert mRotationYXZ let vVec := MatrixMultiply mRotationInv vVec let vVecLoc := ar_Construct Array let vVecLoc[0] := vVec[0][0] let vVecLoc[1] := vVec[1][0] let vVecLoc[2] := vVec[2][0] SetFunctionValue vVecLocEnd
And
Scn zzzGetVectorGlobalfloat fVecLocXfloat fVecLocYfloat fVecLocZfloat fAngleXfloat fAngleYfloat fAngleZarray_var vVecLocarray_var vVecarray_var mRotationXarray_var mRotationYarray_var mRotationZarray_var mRotationYXZBegin Function {fVecLocX fVecLocY fVecLocZ} let vVecLoc := ar_Construct Array let vVecLoc[0] := fVecLocX let vVecLoc[1] := fVecLocY let vVecLoc[2] := fVecLocZ let vVecLoc := ForceColumnVector vVecLoc let fAngleX := GetAngle X let fAngleY := GetAngle Y let fAngleZ := GetAngle Z let mRotationX := GenerateRotationMatrix X fAngleX let mRotationY := GenerateRotationMatrix Y fAngleX let mRotationZ := GenerateRotationMatrix Z fAngleX let mRotationYXZ := MatrixMultiply mRotationX mRotationY let mRotationYXZ := MatrixMultiply mRotationZ mRotationYXZ let vVecLoc := MatrixMultiply mRotationYXZ vVecLoc let vVec := ar_Construct Array let vVec[0] := vVecLoc[0][0] let vVec[1] := vVecLoc[1][0] let vVec[2] := vVecLoc[2][0] SetFunctionValue vVecEnd
But something about the results not being even remotely correct tells me I'm missing some vital parts of the conversion between player and world coordinates here somewhere.
Perhaps my rotation matrix is all wrong, or the matrix inversion can't work the way I did it, or maybe I messed up basic coordinate system transformation 101 as learned several years ago in university and my whole conversion attempt is nonsense from the ground up.
But maybe I'm just missing some little less-known facts about the conversion process necessary between player and world coordinate systems and vice versa here.
I know this is again overly convoluted and everything, but so is every scripting approach of mine.
So if anybody knows anything obvious I missed or messed up in my formulae, please enlighten me.
In the meantime I'll be trying to wrap my head around this math problem myself some more. It's been several years since I last did any scripting, and complicated linear algebra such as this was last done several years before that even. Saying I'm "out of it" for a while would be an understatement.
edit: Wait a second... what's this 3-times "fAngleX" for all of the rotation matrices doing there?! That's not right at all. I need to fix that immediately and see if it fixes things up already!