18,700
edits
m (link fix) |
m (copy-edit) |
||
Line 1: | Line 1: | ||
{{XML_File_Header | type=OBAN | prev=Mtrl | next=OBOA | name=Object Animation }} | {{XML_File_Header | type=OBAN | prev=Mtrl | next=OBOA | name=Object Animation }} | ||
== | ==General information== | ||
* The | * The XML on this page was tested with OniSplit '''v0.9.61.0''', '''v0.9.68.0''', '''v0.9.82.0''', '''v0.9.96.0'''. | ||
** With v0.9.82.0, you can also convert the OBAN into a DAE file: | |||
:: "-extract:dae output src\OBANElevator.oni" exports the animation with a null node | |||
::: In [[Mod_Tool#Scripting|Mod Tool]] the null node is named "unique" and holds keyframes; it can be replicated with ''activesceneroot.AddModel , "unique"'' | |||
:: "-extract:dae output src\OBANElevator.oni -geom:M3GMdebris.oni" exports animation with specified geometry | |||
:: "-extract:dae output src\OBANElevator.oni -geom:camera" exports animation with camera | |||
:* With v0.9.90.0, you can convert a camera DAE to OBAN (a camera root is not supported) | |||
:: "-create:oban output src\file.dae" | |||
* [[XML:TRIG|Laser trigger]] and [[XML:DOOR|door]] files use '''global''' OBANs. | |||
* Some cutscene TRAMs, animated cutscene objects and camera shots/animations use '''level-specific''' OBANs. | |||
* If you want to update level-specific OBANs used by an ONLV, you must provide the ONLV along with the OBANs in the package. | |||
* Trivia: the [[:Image:Dream_obj_images_spawned.jpg|Dream Lab images]] use OBANs. | |||
* Tutorial: [[Authoring_custom_camera_animations|Creating camera animations]] | |||
==BSL support== | |||
{| class="wikitable" width=100% | {| class="wikitable" width=100% | ||
| ''' | | '''Animate object''' | ||
| ''' | | '''Animate character''' | ||
| ''' | | '''Animate camera''' | ||
|- | |- | ||
| valign="top" | | | valign="top" | | ||
Line 36: | Line 29: | ||
cm_anim <nowiki>[look | move | both]</nowiki> ''oban_name'' | cm_anim <nowiki>[look | move | both]</nowiki> ''oban_name'' | ||
|- | |- | ||
| ''' | | '''Animate object (range)''' | ||
| ''' | | '''Stop animating character''' | ||
| ''' | | '''Interpolate between current and new camera position''' | ||
|- | |- | ||
| valign="top" | | | valign="top" | | ||
Line 48: | Line 41: | ||
|} | |} | ||
==XML structure== | |||
{| class="wikitable" width=100% | {| class="wikitable" width=100% | ||
|width=120px| ''' | |width=120px| '''Tag''' | ||
|width=60px| ''' | |width=60px| '''Type''' | ||
| ''' | | '''Description''' | ||
|- | |- | ||
| <OBAN id="0"> | | <OBAN id="0"> | ||
| | | | ||
| ID required. Unlike | | ID required. Unlike OBJC collections, this tag needs its ID attribute to be set. Since it's the first and only instance, it should be 0. | ||
|- | |- | ||
|valign=top| <Flags> | |valign=top| <Flags> | ||
Line 66: | Line 58: | ||
: RandomStartFrame | : RandomStartFrame | ||
: Autostart | : Autostart | ||
:: autostart animation (after an animated object is created | :: autostart animation (after an animated object is created) | ||
: ZAxisUp | : ZAxisUp | ||
:: door | :: door OBANs use this | ||
:: has Z axis pointing up | :: has Z axis pointing up | ||
:: OBAN rotations and translations are treated relatively ( | :: OBAN rotations and translations are treated relatively (as changes to the door's spawn rotation/position) | ||
|- | |- | ||
|valign=top| <InitialTransform> | |valign=top| <InitialTransform> | ||
|valign=top| matrix4x3 | |valign=top| matrix4x3 | ||
| Initial position transform matrix | | Initial position transform matrix. Last 3 values are the position in X, Y, Z. The position seem to be always {0, 0, 0} (or nearly so) in door OBANs. That would make sense because of their global use. | ||
|- | |- | ||
| <BaseTransform> | | <BaseTransform> | ||
| matrix4x3 | | matrix4x3 | ||
| | | Fixed transform matrix | ||
|- | |- | ||
|valign=top| <FrameLength> | |valign=top| <FrameLength> | ||
Line 86: | Line 78: | ||
| <FrameCount> | | <FrameCount> | ||
| int16 | | int16 | ||
| | | The value must be equal to the last <Time> value plus 1, because <Time>0</Time> is also a frame; Oni crashes if you use a wrong value for <FrameCount>. | ||
|- | |- | ||
| <HalfStopFrame> | | <HalfStopFrame> | ||
| int16 | | int16 | ||
| | | Stop frame for the first "half" of the animation; used by door animations to distinguish between open and close sequences. | ||
|- | |- | ||
| <KeyFrames> | | <KeyFrames> | ||
| | | | ||
| | | Holds <OBANKeyFrame> tags. | ||
|- | |- | ||
| <Rotation> | | <Rotation> | ||
| quaternion | | quaternion | ||
| | | Object rotation; can be harvested from TRAM files. | ||
|- | |- | ||
| <Translation> | | <Translation> | ||
| vector3 | | vector3 | ||
| | | {X, Y, Z} object position | ||
|- | |- | ||
| <Time> | | <Time> | ||
| int32 | | int32 | ||
| | | Elapsed time in frames; use short intervals for smooth animations. | ||
|} | |} | ||
;Transform matrices | ;Transform matrices | ||
:Like all matrices in Oni, they are composed of 3 vectors defining rotation/scaling/shearing and a 4th vector defining a translation. | :Like all matrices in Oni, they are composed of 3 vectors defining rotation/scaling/shearing and a 4th vector defining a translation. | ||
:In the above table the 4 vectors are presented as rows | :In the above table, the 4 vectors are presented as rows per [[Wikipedia:row-major_order|Direct3D convention]], although OpenGL and Oni use them as columns. | ||
:[[Wikipedia:Transformation_matrix#Affine_transformations|Affine transformations]] use a 4x4 matrix with 4 extra coefficients (in the presentation above, one would add one column on the right): | :[[Wikipedia:Transformation_matrix#Affine_transformations|Affine transformations]] use a 4x4 matrix with 4 extra coefficients (in the presentation above, one would add one column on the right): | ||
:: | ::Three [[Wikipedia:3D_projection|projection transform]] coefficients (all of them are zero here); one final coefficient (always 1.0 for an affine transform matrix). | ||
: | :Alternately, one can think of the 3x4 matrix as a 3x3 rotation/scaling matrix and a position vector: | ||
::*Let X=(x, y, z) be the position of a vertex in the M3GM | ::*Let X=(x, y, z) be the position of a vertex in the M3GM | ||
::*Let M=(m11, m21, m31; m12, m22, m32; m13, m23, m33) be the 3x3 matrix | ::*Let M=(m11, m21, m31; m12, m22, m32; m13, m23, m33) be the 3x3 matrix | ||
Line 127: | Line 119: | ||
:The only transform that can't be handled by the quaternion+position is scaling/mirroring. | :The only transform that can't be handled by the quaternion+position is scaling/mirroring. | ||
:Thus, the fixed transform is a scaling matrix most of the time (no rotation or translation). | :Thus, the fixed transform is a scaling matrix most of the time (no rotation or translation). | ||
: | :In the example on the [[OBD:OBAN|OBD page]], the fixed transform scales the van up by 1.82 (along all three axes). | ||
;Quaternions | ;Quaternions | ||
:Those are used in Oni whenever interpolation of 3D rotation is involved (e.g. | :Those are used in Oni whenever interpolation of 3D rotation is involved (e.g. [[OBD_talk:TRAM/raw0x34#Quaternions|TRAM rotation]]). | ||
:In this case, rotation | :In this case, the rotation in intermediate frames is interpolated from the keyframe quaternions. | ||
== | ==XML sample== | ||
'''''[...]''''' means other | Below, '''''[...]''''' means other blocks of <OBANKeyFrame>...</OBANKeyFrame>. | ||
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||
Line 160: | Line 152: | ||
</Oni> | </Oni> | ||
==Calculating a quaternion== | |||
An early attempt to harvest quaternions and positions from TRAM files with OniSplit [http://mods.oni2.net/node/38 v0.9.54.0] can be found [http://oni.bungie.org/forum/viewtopic.php?id=2276 over here]. But that script runs inside an Excel file, and Excel isn't a free program, nor is the code compatible with OpenOffice. | |||
VBS code snippets for use with Mod Tool can be found here: | |||
* [[Mod_Tool/Scripting#euler_rotation_-.3E_quaternion|euler rotation to quaternion]] | * [[Mod_Tool/Scripting#euler_rotation_-.3E_quaternion|euler rotation to quaternion]] | ||
* [[Mod_Tool/Scripting#quaternion_-.3E_euler_rotation|quaternion to euler rotation]] | * [[Mod_Tool/Scripting#quaternion_-.3E_euler_rotation|quaternion to euler rotation]] | ||
==Calculating a transform matrix== | |||
In some scenarios we need to build a new transform matrix, e.g. when making a new weapon particle emitter. The first 9 values belong to a 3x3 rotation matrix. The last 3 values are the start positions. | |||
In some scenarios we need to build a new transform matrix, e.g. when making a new weapon particle emitter. | |||
The first 9 values belong to a 3x3 rotation matrix. | |||
The last 3 values are the start positions. | |||
[[Image:rotation_of_transform_matrix.png|right|thumb|single rotation matrices]] | [[Image:rotation_of_transform_matrix.png|right|thumb|single rotation matrices]] | ||
x = 60 | x = 60 | ||
Line 188: | Line 171: | ||
<InitialTransform><span style="background-color:#FF7">0.5 0 -0.8660254</span> <span style="background-color:#F7F">0 1 0</span> <span style="background-color:#7FF">0.8660254 0 0.5</span> <font style="color:#AAAAAA">0 0 0</font></InitialTransform> | <InitialTransform><span style="background-color:#FF7">0.5 0 -0.8660254</span> <span style="background-color:#F7F">0 1 0</span> <span style="background-color:#7FF">0.8660254 0 0.5</span> <font style="color:#AAAAAA">0 0 0</font></InitialTransform> | ||
<span style="background-color:#FF7">cos(y) 0 -sin(y)</span> <span style="background-color:#F7F">0 1 0</span> <span style="background-color:#7FF">sin(y) 0 cos(y)</span> | <span style="background-color:#FF7">cos(y) 0 -sin(y)</span> <span style="background-color:#F7F">0 1 0</span> <span style="background-color:#7FF">sin(y) 0 cos(y)</span> | ||
z = 60 | z = 60 | ||
<InitialTransform><span style="background-color:#777">0.5 0.8660254 0</span> <span style="background-color:#AAA">-0.8660254 0.5 0</span> <span style="background-color:#DDD">0 0 1</span> <font style="color:#AAAAAA">0 0 0</font></InitialTransform> | <InitialTransform><span style="background-color:#777">0.5 0.8660254 0</span> <span style="background-color:#AAA">-0.8660254 0.5 0</span> <span style="background-color:#DDD">0 0 1</span> <font style="color:#AAAAAA">0 0 0</font></InitialTransform> | ||
<span style="background-color:#777">cos(z) sin(z) 0</span> <span style="background-color:#AAA">-sin(z) cos(z) 0</span> <span style="background-color:#DDD">0 0 1</span> | <span style="background-color:#777">cos(z) sin(z) 0</span> <span style="background-color:#AAA">-sin(z) cos(z) 0</span> <span style="background-color:#DDD">0 0 1</span> | ||
{| class="wikitable" style="float:right;" | {| class="wikitable" style="float:right;" | ||
Line 201: | Line 180: | ||
[[User:Neo|Neo]] provided a little '''[http://mods.oni2.net/node/381 matrix program]'''. | [[User:Neo|Neo]] provided a little '''[http://mods.oni2.net/node/381 matrix program]'''. | ||
|} | |} | ||
The final rotation matrix becomes calculated from multiplication of all single rotation matrices whereby the order must be Z, then Y, then X. | The final rotation matrix becomes calculated from multiplication of all single rotation matrices whereby the order must be Z, then Y, then X. | ||
Line 211: | Line 189: | ||
: '''final rotation matrix; position X; position Y; position Z''' | : '''final rotation matrix; position X; position Y; position Z''' | ||
Mod Tool VBS code (rotations only): | |||
* [[Mod_Tool/Scripting#euler_rotation_-.3E_matrix|Euler rotation to matrix]] | |||
* [[Mod_Tool/Scripting#matrix_-.3E_euler_rotation|matrix to Euler rotation]] | |||
==Wish list== | |||
* TRAM import: DAE + XML | |||
** The DAE section in the XML file should have an option to create a pelvis OBAN along with the TRAM (see [[XML:TRAM]]'s RealWorld flag for details) | |||
* DAE to .oni creation should also allow for OBANs (currently OBANs can only be imported via the level's master XML file) | |||
** This would be very useful for editing/creating single OBAN files if the rest of the level doesn't need changes | |||
* TRAM import: | |||
** | |||
* | |||
** | |||
==Camera OBAN creation with XSI== | |||
Watch out for drag and drop workflow. You better work with free object. | Watch out for the drag-and-drop workflow. You'd better work with a free object. | ||
[[Image:XML_OBAN_camera_with_XSI.jpg|thumb|300px]] | [[Image:XML_OBAN_camera_with_XSI.jpg|thumb|300px]] | ||
* [http://mods.oni2.net/node/383 | * [http://mods.oni2.net/node/383 Old Excel macro] | ||
{{XML}} | {{XML}} |