Difference between revisions of "User:DavidJCobb/Rotation Library"
User:DavidJCobb/Rotation Library (edit)
Revision as of 17:53, 26 August 2014
, 17:53, 26 August 2014Fixed the problems!
imported>DavidJCobb (errors found! will correct!) |
imported>DavidJCobb (Fixed the problems!) |
||
Line 1: | Line 1: | ||
I've created a rotation library that makes it easier to work with rotation math in Skyrim. Among other things, it can position and rotate one object relative to another for you. [[User:DavidJCobb/Rotation Library Tutorial|This tutorial]] takes you through creating a basic demo of the library, and assumes that you've compiled the (interdependent) scripts below. | I've created a rotation library that makes it easier to work with rotation math in Skyrim. Among other things, it can position and rotate one object relative to another for you. [[User:DavidJCobb/Rotation Library Tutorial|This tutorial]] takes you through creating a basic demo of the library, and assumes that you've compiled the (interdependent) scripts below. | ||
Please use different [[Scriptname|script names]] if you choose to use these libraries, so as to avoid collisions with any edits or enhancements that other users may make in other mods. | Please use different [[Scriptname|script names]] if you choose to use these libraries, so as to avoid collisions with any edits or enhancements that other users may make in other mods. You should probably strip out all of the Debug.Trace() statements as well. | ||
The relative-position code was adapted from [[Spatial functions and snippets#Rotation matrix|code originally written by Chesko]]. | The relative-position code was adapted from [[Spatial functions and snippets#Rotation matrix|code originally written by Chesko]]. | ||
Line 7: | Line 7: | ||
Other editors: feel free to add this to whatever Papyrus categories you feel are relevant. :) | Other editors: feel free to add this to whatever Papyrus categories you feel are relevant. :) | ||
== Changelog == | |||
;8/26/2014 | |||
:*I appear to have successfully fixed issues that arose when converting rotation matrices to axis angles, when the resulting axis-angle had an angle of exactly 180. | |||
== Main code == | == Main code == | ||
Line 83: | Line 79: | ||
{Converts a rotation matrix to axis angle, returning [x, y, z, angle]. The angle is in degrees. Tailored for Skyrim (extrinsic left-handed ZYX Euler).} | {Converts a rotation matrix to axis angle, returning [x, y, z, angle]. The angle is in degrees. Tailored for Skyrim (extrinsic left-handed ZYX Euler).} | ||
Float[] fOutput = new Float[4] | Float[] fOutput = new Float[4] | ||
; | |||
; Determine the angle. | |||
; | |||
Float fTrace = MatrixTrace(afMatrix) | |||
fOutput[3] = Math.acos((fTrace - 1) / 2) | |||
; | ; | ||
; Determine the axis. | ; Determine the axis. | ||
Line 89: | Line 90: | ||
fOutput[1] = afMatrix[2] - afMatrix[6] | fOutput[1] = afMatrix[2] - afMatrix[6] | ||
fOutput[2] = afMatrix[3] - afMatrix[1] | fOutput[2] = afMatrix[3] - afMatrix[1] | ||
If fOutput[3] == 180 | |||
; | |||
; A 180-degree angle tends to lead to a zero vector as our axis. | |||
; There seems to be a way to correct that... | |||
; | |||
; Source for the math: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm | |||
; Source for the math: http://sourceforge.net/p/mjbworld/discussion/122133/thread/912b44f7 | |||
; | |||
fOutput[0] = Math.sqrt((afMatrix[0] + 1) / 2) | |||
fOutput[1] = Math.sqrt((afMatrix[4] + 1) / 2) | |||
fOutput[2] = Math.sqrt((afMatrix[8] + 1) / 2) | |||
; | |||
; We don't know the signs of the above terms. Per our second | |||
; source, we can start to figure that out by finding the largest | |||
; term... | |||
; | |||
Int iLargestIndex = 0 | |||
Float fTemporary = fOutput[0] | |||
If fTemporary < fOutput[1] | |||
fTemporary = fOutput[1] | |||
iLargestIndex = 1 | |||
EndIf | |||
If fTemporary < fOutput[2] | |||
fTemporary = fOutput[2] | |||
iLargestIndex = 2 | |||
EndIf | |||
Int iIterator = 0 | |||
While iIterator < 3 | |||
Int iIndex = (iLargestIndex - 1) * 3 + iIterator | |||
If iIterator != iLargestIndex | |||
fOutput[iIterator] = fOutput[iIterator] * Sign(afMatrix[iIndex]) | |||
EndIf | |||
iIterator += 1 | |||
EndWhile | |||
EndIf | |||
; | ; | ||
; Normalize the axis. | ; Normalize the axis. | ||
Line 96: | Line 132: | ||
Else | Else | ||
; | ; | ||
; Edge-case caused a zero vector! | ; Edge-case caused a zero vector! Dumb fallback to the Z-axis. | ||
; | ; | ||
fOutput[0] = 0 | fOutput[0] = 0 | ||
Line 106: | Line 138: | ||
fOutput[2] = 1 | fOutput[2] = 1 | ||
EndIf | EndIf | ||
; | ; | ||
; Done! | ; Done! |