Get the global rotation of a DC
-
As the title suggests, how do I get the global rotation of a DC?
For example:
- Make a simple DC cube
- Rotate it 45 deg left on z (using the move tool)
- Then 45 deg up on x (also using the move tool)
- look at the rotation values in the DC Attibutes
The values should be [35,-30,-36]
I know that SketchUp uses local rotation values.
I'm creating a specialised exporter and need to know the DC's global rotation of [45,0,-45]Is there some mathematical way to do it? Or even better, an inbuilt ruby command?
Thanks
-
Rotations are not linear.
Take a cube, with all 3 lengths different. Copy it. Rotate it 90 degrees on the X, then 90 degrees on the new Y. Take the same cube, rotate it 90 degrees on Y, then 90 degrees on the new X. It's different. This is because rotations are not linear - a + b != b + a.
Sooo, what to do is realize how sketchup works. Sketchup rotates first on X, then on Y, then on Z. Thus, by rotating along X by 35, then on the new Y by -30, then finally by -36. This creates the same as 45 on Z, then 45 on new X.
The two are equivalent. http://en.wikipedia.org/wiki/Euler_angles#Table_of_matrices will demonstrate. Sketchup system has a basic rotation matrix using the xyz. This is EQUIVALENT to your system (using ZXY, for example, with a rotation about Y of 0). Do the math yourself, you'll see that you wind up with the same matrix or you'll wind up with a transposed matrix, or to say the least a rearranged matrix. (i.e. what was in row 1 is now in row 2, and what was in column 1 is now in column 2, etc)
Back to your original question though - those are the global X,Y,Z rotations, assuming that the rotations you are reading are not nested inside of another component- but they are in rotate X, then Y, then Z notation.
Side note - if you do have a nested dynamic component, and need to get the global rotations of a nested dc, you need to take the rotations of the parent, assemble the rotation matrix as explained in the wikipedia article. Then construct the nested component's rotation matrix. Finally multiply the two matrices together. Once you've done that, deconstruct the product (beware of gimbal lock when you deconstruct the matrix; this occurs if the middle rotation is 0 degrees - however as long as you can deal with a rotation of 2 degrees in the X and 3 degrees in the Z being the equivalent to 3 degrees in the X and then 2 degrees in the Z, you'll be ok).
-
@lachlan said:
Is there some mathematical way to do it? Or even better, an inbuilt ruby command?
Well, yes and no.
Take components transformation matrix. Do a transformation.to_a.
Matrix is 4x4. I'll work with the top row for this example, the other rows are similar.
1, 2, 3, 0 for top row. Then this is a stretched x-axis, so you must normalize the axis. To do this, divide it by it's magnitude (in this case, it's 1^2+2^2+3^2, or 14. 1/14 = .072, 2/14 = .143, 3/14 = .214) This is the unscaled x-axis (since the transformation matrix is multiplied by the scale factor). Repeat for rows 2 and 3. Four relates to positioning.
Multiply these 3x3 matrices by itself for nested components. This will get you the global transformation (at least for rotations). Note that you can just normalize the axis at the end of transformation as well - this will allow you to recover the global scale as well. Then use the euler angle formulas to find out the angles (http://en.wikipedia.org/wiki/Euler_angles#Derivation_of_the_Euler_angles_of_a_given_frame)
-
Thanks for the help, it makes sense, but it doesn't solve my problem entirely.
I think I'll have to explain the scenario.
I'm making a level editor for a game (SU has easy 3D nav and editing + good exporting via ruby).
The game rotates its objects in the order x,z,y unlike SU's x,y,z.
In addition, all z rotations are "global". I'll give an example.
If an arrow pointing north (0,0,0) is rotated to have x=45 y=0 and z=180 then in the game it will be pointing south, but upwards at 45 deg, whereas SU will have the arrow pointing down.
The game rotates objects through the global z axis (always vertical), not the objects z axis.I'd like to know how to get rotations that can be used in the game.
Thankyou
-
Ahh, I see.
The rotation matrix of a rotation about global x is [[1, 0, 0][0, c, -s][0, s, c]]; rotation about global z is [[c, -s, 0][s, c, 0][0, 0, 1]].
Rotation about LOCAL y is a bit harder - are you sure this is not global? For this, we use http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula.
` V(rot) = V*c + (Z x V)s + (ZV)Z(1-c), where:
Lower case are scalars
Upper case are Vectors
V(rot) is the new vector
V is the old vector
Z is the global rotation vector
c is cosine
s is sine- indicates dot multiplication
x indicates cross multiplication`
Combined, this can get you where you need to go - sorta. Lemme know if you need help on the matrix multiplication.
- indicates dot multiplication
-
Alright, did the matrix math for ya. Ready?
Your complete rotation matrix for your system is:
(C_C)(C_B)+(S_A)(S_C)(S_B); (S_A)(S_C)(C_B)-(S_B)(C_C); (C_A)(S_C);;
(C_A)(S_B); (C_A)(C_B); -(S_A);;
(S_A)(S_B)(C_C)-(C_B)(S_C); (S_A)(C_B)(C_C)+(S_B)(S_C); (C_A)(C_C);;;WHERE:
S_ represents sine, C_ represents cosine
A is first angle (rotation about global/local X) - doesn't matter which since global is local for first rotation.
B is second angle (rotation about global Z)
C is final angle (rotation about local Y)So, you need to make the .to_a matrix of your rotation be equal to this matrix (after normalizing the axis vectors), then solve for A, B, and C. This matrix is very similar to rotation of Z, then X, then Y, but still different.
Advertisement