Authoring custom camera animations: Difference between revisions
Script 10k (talk | contribs) m (typo) |
Script 10k (talk | contribs) m (Undo revision 20145 by Script 10k (talk)) |
||
Line 30: | Line 30: | ||
</Instance> | </Instance> | ||
</Oni> | </Oni> | ||
This is as simple as an OBAN gets. Both the initial/base matrices and the keyframe information (quaternion and 3-vector) correspond to the neutral transformation: stay at origin, don't rotate at all. Now create an OBANshpadoinkle.oni from that, using '''[[OniSplit]].exe -create . OBANshpadoinkle. | This is as simple as an OBAN gets. Both the initial/base matrices and the keyframe information (quaternion and 3-vector) correspond to the neutral transformation: stay at origin, don't rotate at all. Now create an OBANshpadoinkle.oni from that, using '''[[OniSplit]].exe -create . OBANshpadoinkle.xml''' It should look like this: | ||
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F | Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F | ||
Revision as of 11:18, 12 September 2012
This explains how to author single-keyframe OBAN and use them for linearly interpolated camera movements. The primary motivation is the recording of high-quality (scripted) scenes for the trailer (although actual new cutscenes for the game could eventually be authored in the same way). Two major drawbacks of manual camera:
- Camera turning, be it mouse or keyboard, is not affected by gs_input_accel. Therefore, slow, smooth camera movements are limited to fixed-orientation panning, and that only along a limited set of lines (up to 3 simultaneous keypresses of movement keys).
- Although the panning velocity is affected by gs_input_accel, the movement occurs in real-time, not in game-time. Therefore, you can't use Ctrl+Shift+L, which is the only way to capture lossless, lag-free footage even for the most complex scenes.
Arguably the player camera (or player orbiting, which is affected by the same parameters) can be used in creative ways to emulate smooth panning and rotation (all the more so if a special camera character is designed for that purpose) but I felt like interpolation was badly needed in any case.
Interpolation of camera movement between single-keyframe OBAN is actually quite common. Whenever the view snaps to a door that's being unlocked, that's typically a call like:
cm_interpolate name_of_a_static_OBAN_that_points_at_the_door 0
When the camera snaps to a new location/direction and then smoothly pans/rotates to another location/direction, it's typically something like this:
cm_interpolate name_of_a_static_OBAN_that_corresponds_to_the_start_of_the_interpolated_sequence 0 cm_interpolate_block name_of_a_static_OBAN_that_corresponds_to_the_start_of_the_interpolated_sequence 300
The "_block" here is not actually needed (see below for an explanation), but it doesn't hurt. The 300 means 300 frames (5 seconds), which is the length of the interpolation in this case. The 0 just means that the camera interpolates from wherever it was to the new position as fast as it can, i.e., in 0 frames.
Anyway. Look for "cm_interpolate" in the original scripts if you want to see how it's done. What we are going to do now is create a new OBAN from scratch. Make an OBANshpadoinkle.xml file looking like this:
<?xml version="1.0" encoding="utf-8"?> <Oni Version="0.9.27.0"> <Instance id="0" type="OBAN" name="shpadoinkle"> <Flags></Flags> <InitialTransform>1 0 0 0 1 0 0 0 1 0 0 0</InitialTransform> <BaseTransform>1 0 0 0 1 0 0 0 1 0 0 0</BaseTransform> <FrameLength>1</FrameLength> <FrameCount>1</FrameCount> <HalfStopFrame>0</HalfStopFrame> <KeyFrames> <OBANKeyFrame> <Rotation>0 0 0 1</Rotation> <Translation>0 0 0</Translation> </OBANKeyFrame> </KeyFrames> </Instance> </Oni>
This is as simple as an OBAN gets. Both the initial/base matrices and the keyframe information (quaternion and 3-vector) correspond to the neutral transformation: stay at origin, don't rotate at all. Now create an OBANshpadoinkle.oni from that, using OniSplit.exe -create . OBANshpadoinkle.xml It should look like this:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 1F 27 DC 33 DF BC 03 00 32 33 52 56 40 00 14 00 .'Ü3ß¼..23RV@... 00000010 10 00 08 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ 00000020 60 00 00 00 A0 00 00 00 00 01 00 00 10 00 00 00 `... ........... 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040 4E 41 42 4F 08 00 00 00 00 00 00 00 A0 00 00 00 NABO........ ... 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000060 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000070 00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00 ..........€?.... 00000080 00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00 ..........€?.... 00000090 00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00 ..........€?.... 000000A0 00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00 ..........€?.... 000000B0 00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00 ..........€?.... 000000C0 00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00 ..........€?.... 000000D0 00 00 00 00 00 00 00 00 01 00 01 00 00 00 01 00 ................ 000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 3F ..............€? 000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000100 4F 42 41 4E 73 68 70 61 64 6F 69 6E 6B 6C 65 00 OBANshpadoinkle.
Emphasized in bold and bold italics respectively are the 2 matrices. The first starts at byte 0x78, the second at byte 0xA8. Both are 0x30=48 bytes long. Actually, as you've noticed, they're both exactly the same, and we'll just keep it that way to avoid confusion.
Now comes the actual authoring part. Grab THIS plugin (PC-only, because make_corpse is missing on the Mac) and put it in your GameDataFolder. Run Oni, enable the dev mode and shapeshift to the camera character. This character can only turn, not move, so you can just as well set chr_pin_character=1 or chr_nocollision 0 1, to allow the camera to float in the air at the desired location. Go to the location of your choice with the manual camera, then teleport the camera character there with the End hotkey. Now set the orientation by aiming around.
The main issue here is that the "player camera" will not exactly reflect the orientation of the "body" of the camera character. You'll obtain the best accuracy with the following settings:
cm_height=1 cm_distance=0.1 cm_canter_unarmed=0 cm_canter_weapon=0
Also note that the character's vertical aiming is unrestricted, so if you want to aim the camera extra-high or extra-low, the player camera won't be reflecting the actual elevation of the camera's "body": in that case, you may be better off going into manual camera mode 1 again, so as to look at the character a bit from the side, or roughly along the desired axis.
Once the orientation is correct, enter make_corpse shpadoinkle. This will create a file in the Oni folder called level#_shpadoinkle_corpse.dat, that looks a bit like this (and a bit like CRSA, not surprisingly):
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 63 61 6D 65 72 61 00 00 00 00 00 00 00 00 00 00 camera.......... 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000080 00 00 00 00 69 BE 40 BF 00 00 00 00 1F 7B 28 BF ....i¾@¿.....{(¿ 00000090 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 2B B8 24 3F ?œ.>ÖHz?é."¾+¸$? 000000A0 D3 2B 57 BE C9 70 3C BF 02 C0 F5 44 84 4B A5 C1 Ó+W¾Ép<¿.ÀõD„K¥Á 000000B0 CC 8B 5C C4 65 BE 40 BF 05 CC 9D B3 23 7B 28 BF Ì‹\Äe¾@¿.Ì.³#{(¿ 000000C0 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 2F B8 24 3F ?œ.>ÖHz?é."¾/¸$? 000000D0 D3 2B 57 BE C5 70 3C BF 02 C0 F5 44 84 4B A5 C1 Ó+W¾Åp<¿.ÀõD„K¥Á 000000E0 CC 8B 5C C4 61 BE 40 BF 05 CC 1D B4 27 7B 28 BF Ì‹\Äa¾@¿.Ì.´'{(¿ 000000F0 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 33 B8 24 3F ?œ.>ÖHz?é."¾3¸$? 00000100 D3 2B 57 BE C1 70 3C BF 02 C0 F5 44 84 4B A5 C1 Ó+W¾Áp<¿.ÀõD„K¥Á 00000110 CC 8B 5C C4 5D BE 40 BF 08 B2 6C B4 2B 7B 28 BF Ì‹\Ä]¾@¿.²l´+{(¿ 00000120 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 37 B8 24 3F ?œ.>ÖHz?é."¾7¸$? 00000130 D3 2B 57 BE BD 70 3C BF 02 C0 F5 44 84 4B A5 C1 Ó+W¾½p<¿.ÀõD„K¥Á 00000140 CC 8B 5C C4 65 BE 40 BF 05 CC 9D B3 23 7B 28 BF Ì‹\Äe¾@¿.Ì.³#{(¿ 00000150 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 2F B8 24 3F ?œ.>ÖHz?é."¾/¸$? 00000160 D3 2B 57 BE C5 70 3C BF 02 C0 F5 44 84 4B A5 C1 Ó+W¾Åp<¿.ÀõD„K¥Á 00000170 CC 8B 5C C4 61 BE 40 BF 05 CC 1D B4 27 7B 28 BF Ì‹\Äa¾@¿.Ì.´'{(¿ 00000180 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 33 B8 24 3F ?œ.>ÖHz?é."¾3¸$? 00000190 D3 2B 57 BE C1 70 3C BF 02 C0 F5 44 84 4B A5 C1 Ó+W¾Áp<¿.ÀõD„K¥Á 000001A0 CC 8B 5C C4 5D BE 40 BF 08 B2 6C B4 2B 7B 28 BF Ì‹\Ä]¾@¿.²l´+{(¿ 000001B0 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 37 B8 24 3F ?œ.>ÖHz?é."¾7¸$? 000001C0 D3 2B 57 BE BD 70 3C BF 02 C0 F5 44 84 4B A5 C1 Ó+W¾½p<¿.ÀõD„K¥Á 000001D0 CC 8B 5C C4 FA B6 24 BF D2 2B 57 3E D2 71 3C 3F Ì‹\Äú¶$¿Ò+W>Òq<? 000001E0 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 6C BF 40 BF ?œ.>ÖHz?é."¾l¿@¿ 000001F0 94 C8 A9 36 F5 79 28 BF 02 C0 F5 44 84 4B A5 C1 ”È©6õy(¿.ÀõD„K¥Á 00000200 CC 8B 5C C4 FE B6 24 BF D2 2B 57 3E CE 71 3C 3F Ì‹\Äþ¶$¿Ò+W>Îq<? 00000210 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 68 BF 40 BF ?œ.>ÖHz?é."¾h¿@¿ 00000220 64 51 A7 36 F9 79 28 BF 02 C0 F5 44 84 4B A5 C1 dQ§6ùy(¿.ÀõD„K¥Á 00000230 CC 8B 5C C4 02 B7 24 BF D2 2B 57 3E CA 71 3C 3F Ì‹\Ä.·$¿Ò+W>Êq<? 00000240 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 64 BF 40 BF ?œ.>ÖHz?é."¾d¿@¿ 00000250 34 DA A4 36 FD 79 28 BF 02 C0 F5 44 84 4B A5 C1 4Ú¤6ýy(¿.ÀõD„K¥Á 00000260 CC 8B 5C C4 06 B7 24 BF D2 2B 57 3E C6 71 3C 3F Ì‹\Ä.·$¿Ò+W>Æq<? 00000270 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 60 BF 40 BF ?œ.>ÖHz?é."¾`¿@¿ 00000280 04 63 A2 36 01 7A 28 BF 02 C0 F5 44 84 4B A5 C1 .c¢6.z(¿.ÀõD„K¥Á 00000290 CC 8B 5C C4 06 B7 24 BF D2 2B 57 3E C6 71 3C 3F Ì‹\Ä.·$¿Ò+W>Æq<? 000002A0 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 60 BF 40 BF ?œ.>ÖHz?é."¾`¿@¿ 000002B0 04 63 A2 36 01 7A 28 BF 02 C0 F5 44 84 4B A5 C1 .c¢6.z(¿.ÀõD„K¥Á 000002C0 CC 8B 5C C4 0A B7 24 BF D2 2B 57 3E C2 71 3C 3F Ì‹\Ä.·$¿Ò+W>Âq<? 000002D0 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 5C BF 40 BF ?œ.>ÖHz?é."¾\¿@¿ 000002E0 D4 EB 9F 36 05 7A 28 BF 02 C0 F5 44 84 4B A5 C1 ÔëŸ6.z(¿.ÀõD„K¥Á 000002F0 CC 8B 5C C4 0E B7 24 BF D2 2B 57 3E BE 71 3C 3F Ì‹\Ä.·$¿Ò+W>¾q<? 00000300 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 58 BF 40 BF ?œ.>ÖHz?é."¾X¿@¿ 00000310 A4 74 9D 36 09 7A 28 BF 02 C0 F5 44 84 4B A5 C1 ¤t.6.z(¿.ÀõD„K¥Á 00000320 CC 8B 5C C4 12 B7 24 BF D2 2B 57 3E BA 71 3C 3F Ì‹\Ä.·$¿Ò+W>ºq<? 00000330 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 54 BF 40 BF ?œ.>ÖHz?é."¾T¿@¿ 00000340 74 FD 9A 36 0D 7A 28 BF 02 C0 F5 44 84 4B A5 C1 týš6.z(¿.ÀõD„K¥Á 00000350 CC 8B 5C C4 06 B7 24 BF D2 2B 57 3E C6 71 3C 3F Ì‹\Ä.·$¿Ò+W>Æq<? 00000360 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 60 BF 40 BF ?œ.>ÖHz?é."¾`¿@¿ 00000370 04 63 A2 36 01 7A 28 BF 02 C0 F5 44 84 4B A5 C1 .c¢6.z(¿.ÀõD„K¥Á 00000380 CC 8B 5C C4 0A B7 24 BF D2 2B 57 3E C2 71 3C 3F Ì‹\Ä.·$¿Ò+W>Âq<? 00000390 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 5C BF 40 BF ?œ.>ÖHz?é."¾\¿@¿ 000003A0 D4 EB 9F 36 05 7A 28 BF 02 C0 F5 44 84 4B A5 C1 ÔëŸ6.z(¿.ÀõD„K¥Á 000003B0 CC 8B 5C C4 0E B7 24 BF D2 2B 57 3E BE 71 3C 3F Ì‹\Ä.·$¿Ò+W>¾q<? 000003C0 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 58 BF 40 BF ?œ.>ÖHz?é."¾X¿@¿ 000003D0 A4 74 9D 36 09 7A 28 BF 02 C0 F5 44 84 4B A5 C1 ¤t.6.z(¿.ÀõD„K¥Á 000003E0 CC 8B 5C C4 12 B7 24 BF D2 2B 57 3E BA 71 3C 3F Ì‹\Ä.·$¿Ò+W>ºq<? 000003F0 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE 54 BF 40 BF ?œ.>ÖHz?é."¾T¿@¿ 00000400 74 FD 9A 36 0D 7A 28 BF 02 C0 F5 44 84 4B A5 C1 týš6.z(¿.ÀõD„K¥Á 00000410 CC 8B 5C C4 02 80 F5 44 C2 A5 16 C2 CC 0B 5D C4 Ì‹\Ä.€õDÂ¥.ÂÌ.]Ä 00000420 02 00 F6 44 28 87 B3 C0 CC 0B 5C C4 ..öD(‡³ÀÌ.\Ä
The 48 bytes emphasized in bold, starting at 0x84, correspond to the transform matrix of the "pelvis" of our camera character. We want this matrix to replace both of the matrices in our OBANshpadoinkle.oni, making it look like this:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 1F 27 DC 33 DF BC 03 00 32 33 52 56 40 00 14 00 .'Ü3ß¼..23RV@... 00000010 10 00 08 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ 00000020 60 00 00 00 E0 00 00 00 40 01 00 00 0D 00 00 00 `...à...@....... 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040 4E 41 42 4F 08 00 00 00 00 00 00 00 E0 00 00 00 NABO........à... 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000060 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000070 00 00 00 00 00 00 00 00 69 BE 40 BF 00 00 00 00 ........i¾@¿.... 00000080 1F 7B 28 BF 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE .{(¿?œ.>ÖHz?é."¾ 00000090 2B B8 24 3F D3 2B 57 BE C9 70 3C BF 02 C0 F5 44 +¸$?Ó+W¾Ép<¿.ÀõD 000000A0 84 4B A5 C1 CC 8B 5C C4 69 BE 40 BF 00 00 00 00 „K¥ÁÌ‹\Äi¾@¿.... 000000B0 1F 7B 28 BF 3F 9C 0D 3E D6 48 7A 3F E9 00 22 BE .{(¿?œ.>ÖHz?é."¾ 000000C0 2B B8 24 3F D3 2B 57 BE C9 70 3C BF 02 C0 F5 44 +¸$?Ó+W¾Ép<¿.ÀõD 000000D0 84 4B A5 C1 CC 8B 5C C4 01 00 01 00 00 00 01 00 „K¥ÁÌ‹\Ä........ 000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 3F ..............€? 000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000100 4F 42 41 4E 73 68 70 61 64 6F 69 6E 6B 6C 65 00 OBANshpadoinkle.
Now import OBANshpadoinkle.oni in a level, say, level3 and enjoy your new "shpadoinkle" animation. In order to enjoy it you type this:
cm_interpolate shpadoinkle 0
and then you can interpolate to another camera OBAN, for example:
cm_interpolate shpadoinkle 0 dmsg "the camera instantly snaps to the shpadoinkle position and orientation" cm_interpolate BomberCam01 300 dmsg "then starts interpolating towards BomberCam01, over 5 seconds" cm_interpolate_block BomberCam02 300 dmsg "the third interpolation won't start until the second is done, and will also delay this message"
Basically, all you need to know is that cm_interpolate shpadoinkle 0 instantly places the camera at the position and orientation defined by OBANshpadoinkle. cm_interpolate shpadoinkle 300 will interpolate position and rotation linearly from the current ones, over 300 frames. As for cm_interpolate_block shpadoinkle 300, it will wait until all previous camera interpolations (if any) are done, and from then and there it will interpolate position and rotation linearly, over 300 frames. All script commands placed after cm_interpolate_block shpadoinkle 300 will be blocked until cm_interpolate_block shpadoinkle 300 starts, i.e., until all interpolations before cm_interpolate_block shpadoinkle 300 are done intrerpolating.
You can also use non-blocked interpolations, interrupting the previous ones, like this:
cm_interpolate shpadoinkle 600 dmsg "the camera starts moving to shpadoinkle, expecting to get there in 10 seconds" sleep 300 dmsg "five seconds later..." cm_interpolate BomberCam01 600 dmsg "the journey to shpadoinkle is interrupted and we start moving to BomberCam01" dmsg "from wherever we were, that is, from halfway between out starting point and shpadoinkle" dmsg "at such a speed that we expect to get to BomberCam01 in 10 seconds, counting from now" dmsg "the now, of course, being five seconds later than when we started" sleep 300 dmsg "another five seconds later" cm_interpolate BomberCam01 600 dmsg "the journey to BomberCam01 is also interrupted and we take the short way to BomberCam02" dmsg "from wherever we were, that is, from halfway between BomberCam01 and that other point" dmsg "that other point being halfway between shpadoinkle and where we started"
That should get you started. A mini example featuring the DeLorean will be provided Soon Enough.