Rotating an object about local angles/axes

From the Oblivion ConstructionSet Wiki
Revision as of 19:53, 2 June 2011 by imported>ThePhilanthropy
Jump to navigation Jump to search

The functions SetAngle and Rotate rotate objects about the world axes. In order to apply local rotations, the angles need to be derived first. It is possible to rotate an object about local angles by first specifying the local angles, then extracting the world angles from the local rotation and applying those to the object.

Example

These declarations are needed:

;the object one wishes to rotate
  ref myObject


;the local angles
  float localAngX
  float localAngY
  float localAngZ


;the world angles
  float worldAngX
  float worldAngY
  float worldAngZ


;sine and cosine of local x, y, z angles
  float sx
  float cx
  float sy
  float cy
  float sz
  float cz


;temporary arguments for trigonometric functions
  float arg1
  float arg2


The actual rotation code:

;sine and cosine of local x, y, z angles
  set sx to sin localAngX
  set cx to cos localAngX
  set sy to sin localAngY
  set cy to cos localAngY
  set sz to sin localAngZ
  set cz to cos localAngZ


;extraction of world x angle
  set arg1 to -( cx * -sy *  cz +  sx *  sz)
  set arg2 to        ( cy *  cz)
  set worldAngX to atan2 arg1 arg2


;extraction of world y angle
  set arg1 to -(-sx * -sy *  cz +  cx *  sz)
  set worldAngY to asin arg1


;extraction of world z angle
  set arg1 to       -(-sx *  cy)
  set arg2 to  (-sx * -sy * -sz +  cx *  cz)
  set worldAngZ to atan2 arg1 arg2


;apply extracted rotation
  myObject.setAngle x worldAngX
  myObject.setAngle y worldAngY
  myObject.setAngle z worldAngZ


Special Note

This code has been tested ingame and works reliably well. It is advised to experiment with the order of the local angles to get the desired result.
E.g. this...

set localAngX to 0
set localAngY to player.getangle y
set localAngZ to player.getangle z

...will result in a different rotation than this:

set localAngX to player.getangle z
set localAngY to player.getangle x
set localAngZ to 0

Notes

  • Some types of object, specifically Actors, do not allow for rotation about all three axes. Other objects, such as activators have all three degrees of freedom.
  • The equations were determined via matrix multiplication of standard rotation matrices in X*Y*Z axis order. Unused matrix elements are omitted in the code.
  • Gimbal Lock will occur when (-sx * -sy * cz + cx * sz) equals 1 or -1. No reliable solution is implemented yet.
  • It is not certain to the author whether Oblivion actually uses an axis order of XYZ, but it is assumed. Falsification / Verification of this claim is hereby requested.
  • For a more in-depth discussion of the math behind this, see wikipedia.org and euclideanspace.com.


See Also