Page 1 of 1

convert vector normals to angles-maxscript

Posted: Tue Apr 25, 2006 5:15 am
by bdbodger
I am working on a maxscript for gmax to import cod xmodel_export files and I need to know how to convert vectors to angles

BONE 70
OFFSET -19.514948 -16.768861 39.989041
SCALE 1.000001 1.000000 1.000000
X 0.836715 0.280328 -0.470451
Y 0.071690 0.795593 0.601575
Z 0.542926 -0.537073 0.645588

x , y and z are vectors I need to be able to find angles so that I can rotate the bones the offset is the position in the editor

Posted: Tue Apr 25, 2006 5:40 am
by jv_map
To do this, you need to know the exact convention for the angles you need.

You need to know:
- The order in which the rotations are applied.
- The axis around which each rotation is applied.

Determining the order of rotation is tricky but absolutely necessary. One way to find out which order is used is by applying a rotation of 90 degrees on 2 angles, and from the end result determine which was applied first. Do this another 2 times on the remaining set of angles and you know the order.

Posted: Tue Apr 25, 2006 10:02 am
by bdbodger
Well math is not my strong suit all I want to do is rotate the bone useing the x , y and z values given . I am afraid you have lost me already :( In the gmax listener window I get

$.rotation
(quat 0.0606951 -0.00584427 0.138267 0.289882)

$.rotation.x
0.0606951

$.rotation.y
-0.00584427

$.rotation.z
0.138267

where $ is the selcted object . I can use rotate $ 90 [1,0,0] to rotate on the x axis or just use $.rotation.x = 90 I am lost on this .

Posted: Tue Apr 25, 2006 10:32 am
by bdbodger
hmm found this in another script
local x = ReadFloat bstream
local y = ReadFloat bstream
local z = ReadFloat bstream
origin = [x, y, z]
x = ReadFloat bstream
y = ReadFloat bstream
z = ReadFloat bstream
axisRow1 = [x, y, z]
x = ReadFloat bstream
y = ReadFloat bstream
z = ReadFloat bstream

axisRow2 = [x, y, z]
x = ReadFloat bstream
y = ReadFloat bstream
z = ReadFloat bstream
axisRow3 = [x, y, z]

tagMatrix = matrix3 axisRow1 axisRow2 axisRow3 origin
so what I did was use the x ,y z and offset from the bone seemed to work at least gmax didn't complain

$.rotation = quat (matrix3 [0.554198, -0.245197, -0.795452][0.453435, 0.890324, 0.041473][0.698040, -0.383671 ,0.604596][-19.604893, -17.765507 ,41.269524])
(quat -0.121736 -0.427647 0.200047 0.873086)

The max script reference has in part
Matrix3 Values
The Matrix3 class implements a 4x3 3D transformation matrix object. The transform matrix is a 3D homogeneous matrix typically used to hold object coordinate systems and transformations.

Constructors

matrix3 <row1_point3> <row2_point3> <row3_point3> <row4_point3>

matrix from row vectors
Quat Values
The Quat class provides a compact representation for orientation in three space and provides methods to perform Quaternion algebra. Quaternions are used to store object rotations in 3ds max. A quaternion is made up of four terms: a real scalar part which specifies the amount of rotation and an imaginary vector part which defines the axis of rotation. If the quaternion is normalized, the scalar term equals the cosine of half the angle of rotation, the vector term is the axis of rotation, and the magnitude of the vector term equals the sine of half the angle of rotation.

Interpolation between two key frame orientations is much easier using quaternions and produces smooth and natural motion. Unlike Euler angles, no numerical integration is necessary; quaternions provide an analytic result (no approximations).

Rotations in MAXScript follow the right-hand-rule, namely positive angles rotate counter-clockwise about positive axes, consistent with the convention in the 3ds max UI.

Constructors

quat <x_float> <y_float> <z_float> <w_float>

The x, y, z values make up the vector portion. w is the angle of rotation about the vector.

quat <degrees_float> <axis_point3>

<angleaxis> as quat

<eulerangle> as quat

<matrix3> as quat -- extracts the rotation component as a quat
I don't totally understand it but I knew I could set the rotation from a quat . I wonder if this is what I was looking for

Posted: Tue Apr 25, 2006 6:40 pm
by jv_map
Hmm well there is a 1-to-1 correspondence between the orthonormal matrix [X Y Z] and the associated normalized quaternion, but whether this approach is convenient really depends on the application.

Where are you getting the X Y Z data from?

Can't you rotate the bone directly using the [X Y Z] matrix?

P.S. I'm unfamiliar with the scripting language but it seems like

<matrix3> as quat

would do the conversion from matrix to quaternion.

Posted: Tue Apr 25, 2006 11:48 pm
by bdbodger
well that was wrong anyway . The x y z are from the xmodel_export file for cod

BONE 41
OFFSET 19.040640 -13.171670 43.321545
SCALE 1.000000 1.000000 1.000000
X -0.766464 -0.594188 -0.243871
Y 0.525111 -0.361068 -0.770641
Z 0.369852 -0.718728 0.588762

and this is from the anim file

FRAME 1
PART 0
OFFSET 58.057384 -11.493357 31.342108
SCALE 1.000000 1.000000 1.000000
X -0.149580 -0.500161 -0.852915
Y 0.732539 -0.635432 0.244158
Z -0.664088 -0.588272 0.461436

it starts off with a frame number then bone number I guess then the position and rotation I assume . Maybe this will help I don't understand it but you may it is a tut that rotates a ball on a path http://cuneytozdas.com/tutorials/maxscript/

Posted: Wed Apr 26, 2006 1:58 am
by bdbodger
here is a pic of the bones with no rotation in gmax I guess i'll just move on to the verts and faces for now

Image

Posted: Wed Apr 26, 2006 5:48 am
by jv_map
Hmm I'm still unsure where the problem lies :?

What was wrong anyway?

Posted: Wed Apr 26, 2006 6:02 am
by bdbodger
Ok well this maybe above me but anyway this is from the xmodel_export file
NUMBONES 73
BONE 0 -1 "TAG_ORIGIN"
BONE 1 0 "Bip01 Pelvis"
....
BONE 0
OFFSET 0.000002 -2.222280 0.000042
SCALE 1.000000 1.000000 1.000000
X 0.000000 -1.000000 -0.000001
Y 1.000000 0.000000 0.000000
Z -0.000000 -0.000001 1.000000

BONE 1
OFFSET 0.000000 1.218488 37.227966
SCALE 1.000000 1.000000 1.000000
X -0.000001 -0.000000 1.000000
Y 0.000003 -1.000000 0.000000
Z 1.000000 0.000003 0.000001
and this is in the dumpfile from lr3d
Bone 2 of 73 <Bip01 Pelvis> parent <TAG_ORIGIN>:
WPos = (0.000000,1.218488,37.227966)
WRot = (0.000000,90.000000,180.000000)
--> Bone
-0.000001 -0.000000 1.000000 0.000000
0.000003 -1.000000 -0.000000 0.000000
1.000000 0.000003 0.000001 0.000000
0.000000 1.218488 37.227966 1.000000
--> Parent
0.000000 -1.000000 -0.000001 0.000000
1.000000 0.000000 0.000000 0.000000
0.000000 -0.000001 1.000000 0.000000
0.000002 -2.222280 0.000042 1.000000
--> Inverse Parent
0.000000 1.000000 0.000000 0.000000
-1.000000 0.000000 -0.000001 0.000000
-0.000001 0.000000 1.000000 0.000000
-2.222280 -0.000002 -0.000044 1.000000
--> Local
-0.000001 -0.000001 1.000000 0.000000
1.000000 0.000003 0.000001 0.000000
-0.000003 1.000000 0.000001 0.000000
-3.440805 -0.000002 37.227921 1.000000
LPos = (-3.440805,-0.000002,37.227921)
LRot = (-42.001240,90.000000,129.411743)
I just want to be able to figure out how they did that in lr3d how to convert the information into angles etc for rotation . How did they get WRot = (0.000000,90.000000,180.000000) or LRot = (-42.001240,90.000000,129.411743) with just the offsett and x y z values , offset being it's location in the world from 0,0,0 like I said I am a total math idiot at this level so I need help . Another thing the bone has 4 values the first one is the x value with 0.0000 at the end makeing 4 values ok that maybe the quat or matrix3 values or something the last one is the offset with 1.000000 at the end the bones seem to follow that pattern x y z with 0 at the end and offset again with 1 at the end . so you can see how I am getting lost .

Posted: Wed Apr 26, 2006 10:03 am
by bdbodger
Well don't know it this will help but this is what I got in the listener window $ was the selected bone

a=$.rotation as eulerangles
(eulerAngles -90 0 0)
b=$.rotation as quat
(quat 0.707107 0 0 0.707107)
c=$.rotation as matrix3
(matrix3 [1,0,0] [0,0,-1] [0,1,0] [0,0,0])

Posted: Wed Apr 26, 2006 11:58 am
by bdbodger
Hi me again :)

Well I think I have something here

The bone in the xmodel_export file
BONE 3
OFFSET -4.866636 1.218480 37.227966
SCALE 1.000000 1.000000 1.000000
X 0.008941 0.033732 -0.999391
Y 0.004871 -0.999420 -0.033689
Z -0.999948 -0.004567 -0.009100

The same bone in the lr3d dump file
Bone 3 of 73 <Bip01 L Thigh> parent <Bip01 Pelvis>:
WPos = (4.866636,1.218493,37.227966)
WRot = (74.884132,-88.000313,-104.845436)
The gmax listener window
$.rotation = (matrix3 [0.008941,0.033732,-0.999391][0.004871,-0.999420,-0.033689][-0.999948,-0.004567,-0.009100][0,0,1])
(matrix3 [0.008941,0.033732,-0.999391] [0.004871,-0.99942,-0.033689] [-0.999948,-0.004567,-0.0091] [0,0,1])

b=$.rotation as eulerangles
(eulerAngles -105.116 88.0002 75.1548)
The angles seem reversed in gmax but are simular
jv_map wrote:Hmm well there is a 1-to-1 correspondence between the orthonormal matrix [X Y Z] and the associated normalized quaternion, but whether this approach is convenient really depends on the application.
....
....
Can't you rotate the bone directly using the [X Y Z] matrix?
Ok smart guy you seem to know what you are talking about too bad I don't :) Thanks for your time jv I appreciate it .

Posted: Wed Apr 26, 2006 2:03 pm
by bdbodger
I got it to work but all the angles are positive when in the lr3d dump file they are negative and vise versa negative angles are positive hmm

Posted: Wed Apr 26, 2006 6:09 pm
by jv_map
Hmm well just to clarify things.. 3 angles mean nothing unless you know which convention is applied... similarly you cannot find 'the' 3 angles unless you specify the convention. Different programs can use different conventions. In this case there seems to be good correspondence between the numbers but in theory they could be completely different and still relate to the same rotation.

Matrices and quaternions are not bound to a specific convention. A quaternion can directly be converted to a 3x3 matrix and vice-versa. A matrix cannot always be converted to a set of angles, even if the convention is specified. This is because a fixed set of angles cannot describe all orientations (this is the Euler angle singularity a.k.a gimbal lock). The other way around (from angles to 3x3 matrix) is always possible (provided the convention is known).

WRot is world rotation, LRot is local rotation. WRot describes the orientation of the bone with respect to a global, fixed coordinate system (the origin of the model). LRot describes the orientation of the bone w.r.t to its parent bone.

I honestly don't know why lr3d gives you 4x4 matrices. In 3D space, there are only 6 degrees of freedom (3 translations and 3 rotations), so that in a 4x4 matrix there are 10 variables with redundant information.

It looks like the 3x3 section on the top left corner is the rotation matrix and the bottom row (the 1x3 section) is the offset. The 4th column seems to add no information.

Well hope at least this little story clarifies why you cannot compare lr3d angles with gmax angles :)

Posted: Thu Apr 27, 2006 1:29 am
by bdbodger
well still don't understand but

xmodel_export ( bones listed 0 to 72)
BONE 51
OFFSET 18.615028 -13.125027 40.729116
SCALE 1.000000 1.000000 1.000000
X 0.521571 -0.691415 -0.499909
Y 0.718469 0.039903 0.694413
Z -0.460180 -0.721355 0.517573
lr3d dump file ( bones listed 1 to 73)
Bone 52 of 73 <TAG_WEAPON_LEFT> parent <Bip01 L Hand>:
WPos = (18.615028,-13.125027,40.729115)
WRot = (-53.301407,-29.993980,52.970814)
my maxscript mbones[bn][10] to [12] are x values [13] to [15] are y values and [16] to [18] are z values from xmodel_export file

a=b.pos

b.rotation= inverse ( matrix3[mbones[bn][10],mbones[bn][11],mbones[bn][12]][mbones[bn][13],mbones[bn][14],mbones[bn][15]][mbones[bn][16],mbones[bn][17],mbones[bn][18]][0,0,1])
--inverse(matrix3 x y z [0,0,1]))

b.pos = a
gmax listener window
$.rotation as eulerangles
(eulerAngles -54.3405 27.3987 54.0223)
rotateing in gmax seems to change the position of the model but after restoreing it's position the ( inverse ) angles from gmax match the angles from the lr3d dump file although not exactly . I am just wondering how this relates to animation which will be a change in position and angles . If I apply the rotation first then set the position and then the key frame I wonder if I can reproduce the animation that is in this form
FRAME 26
PART 0
OFFSET 31.521326 -12.612732 38.596418
SCALE 1.000000 1.000000 1.000000
X -0.867006 -0.365461 -0.338731
Y 0.497697 -0.601747 -0.624659
Z 0.024458 -0.710168 0.703607

PART 1
OFFSET 47.410333 -2.438188 35.440558
SCALE 1.000000 1.000000 1.000000
X -0.476539 -0.877572 -0.052698
Y 0.876466 -0.469545 -0.106465
Z 0.068686 -0.096923 0.992919