Rot Matrix Formula
-
**I just found another use for it…
In DFM files, there is a node called ‘Bone To Root’, it turns out after writing the scripter for it that it is a 3x4 matrix. It is normally an identity matrix so in this case I may be able to use the DX matrix decomposition command.
So far I have scripters for the DFM nodes of…
Fractions
Tristrip_Indices
Point_Indices
UV0_Indices
Points
Point_Bone_First
Point_Bone_Count
Bone_ID_Chain
Bone_Weight_Chain
Vertex_Normals
UV0
Bone To RootIf I am able to build the matrix conversion routine I will start working on creating a whole skeletal export routine that exports the entire .dfm as a single script, hopefully as a MS3D file.
Created by my scripter…
[Bone_To_Root] bone = 1.000000, 0.000000, 0.000000 ; 0 bone = 0.000000, 1.000000, 0.000000 ; 1 bone = 0.000000, 0.000000, 1.000000 ; 2 bone = 0.000000, 0.000000, 0.000000 ; 3 ```**
-
I tried doing it in C, but must’ve got it wrong, 'cos it didn’t work, which is why I stuck with the straight asm rip. However, I’ve just had another go and seem to have got it right, this time.
if (dist <= 1.0f/524288.0f) { vec.x = atan2f( -z.y, y.y ); vec.y = atan2f( -x.z, dist ); vec.z = 0; } else { vec.x = atan2f( y.z, z.z ); vec.y = atan2f( -x.z, dist ); vec.z = atan2f( x.y, x.x ); } ```There's an exported function in common.dll going the other way, can you use that?
// ?EulerMatrix@@YA?AVMatrix@@ABVVector@@@Z
Matrix EulerMatrix( const Vector& ); -
I’ll test it out tonight after work. BTW, what is the dist comparison for? For the orientation there shouldn’t be any dist part of it since it is for the hardpoint rotation…
-
**The second one worked with some adjustments. Turns out I had already figured out this formula over 15 years ago to convert rectangular to polar coordinates. I tested it with my original routine and it came up with the correct values as well. This means I already have the routine to convert it back into a matrix but just didn’t know it.
Since the matrix uses 9 values and the routine above only uses 5 of them, I will need to work on it a bit more to include all of the values. I will dig back into my college textbooks on trig and see if it can help with the rest of the entries.
Thanks, you taught an old dog a new trick he should have remembered :P**
-
Lancer Solurus wrote:
I’ll test it out tonight after work. BTW, what is the dist comparison for? For the orientation there shouldn’t be any dist part of it since it is for the hardpoint rotation…Dist is just what I called it, since that’s what it looked like - hypot might be better. I just blindly copied what the save game routine does.
-
**After doing tons of testing with the formula you provided (thanks alot btw) it appears that HardCMP is shortening the rotations to whole numbers and it’s not in the same order.
This is the final coding I worked out based on your initial help…
rd=180.0f/3.141592654f; // radians to degrees // set 1 ax=rd*atan2f(yz,zz); ay=rd*atan2f(-xz,zz); az=rd*atan2f(-yx,xx); // set 2 ax=rd*atan2f(-zy,yy); ay=rd*atan2f(zx,xx); az=rd*atan2f(xy,yy);
Once I can get these combined properly, it will contain the entire matrix layout and it will be a simple matter of using sin and cos to rebuild the matrix.**
-
There’s also an Excel spreadsheet that converts rotation to orientation.
-
It’s saying it’s password protected in both the xl viewer and MS Works…
-
**Perfect, thanks! That will give me something to check it by…
This is psuedo code Im using atm to work with…
public final void rotX(double angle) { double c = Math.cos(angle); double s = Math.sin(angle); m00 = 1.0; m01 = 0.0; m02 = 0.0; m10 = 0.0; m11 = c; m12 = s; yy,yz m20 = 0.0; m21 = -s; m22 = c; -zy,zz } public final void rotY(double angle) { Double c = Math.cos(angle); double s = Math.sin(angle); m00 = c; m01 = 0.0; m02 = -s; xx,-xz m10 = 0.0; m11 = 1; m12 = 0.0; m20 = s; m21 = 0.0; m22 = c; zx,zz } public final void rotZ(double angle) { Double c = Math.cos(angle); double s = Math.sin(angle); m00 = c; m01 = s; m02 = 0.0; xx,xy m10 = -s; m11 = c; m12 = 0.0; -yx,yy m20 = 0.0; m21 = 0.0; m22 = 1.0; } ```**
-
I also found 4 other nodes that can use this code, the Fix, Rev, Pris and Sphere nodes stored in the Cons section. Once I get it to convert from matrix to rot and back to matrix with no loss, I will post the code for it.
-
**Well I finally succeeded in converting the matrix to rotation angles. I ended up scraping all of the code from before and simply did it thru matrix decomposition, which is where I started out initially.
I have also managed to get it to show the same as it appears in Hard CMP and it’s a much higher precision. HCMP rounds off the rotation values to whole numbers.
I am also able to convert back into the matrix format without any changes to it. The code is still buried in the orientation edit routine in the CMP Editor, I will post it in full form once it is relegated to subroutines. It does require use of DX though unless you are a math guru and can roll your own matrix conversion code. You will see what I mean once the code is posted.
The code uses quaternions but does not require understanding of them. I used those for 2 reasons, no gimbal lock and DX supports only them for decompositions.
A block diagram of the way it works is….
Decompose the FL orientation matrix (3 by 3) by converting it to a 4 x 4 matrix first using D3DXMatrixDecompose.
Convert the Quat to Euler angles. Only X and Y needed, the Z rot is either 0 or 180 degrees, if it’s 180 it requires a special case handling for each + and - states. -90 degrees X also swaps the Y and Z value, simply switching them is enough.
Converting back to quaternions requires simply pocessing the angles in reverse order of the first conversion.
Then simply do a D3DXMatrixTransformation back into a matrix and store it.Anyways, the code will show how to do it without you needing to fully understand what I did, feel free to dig into the math if you want.**