Camera¶
The views the game shows and where each puts the camera: camera.cpp, with the projection from Surrender's srAPI.cpp. src/engine/game/camera.zig and srapi.zig state the same rules.
Projection¶
sr_set_projection (0x004C3A60) takes a viewport, its edges as fractions of the screen, and a factor across and one down. A point at (x, y, z) in the camera's frame falls on the screen at:
(width / 2 + x / z * (width - 0.1) * across, height / 2 + y / z * (height - 0.1) * down)
whatever the viewport; the viewport only bounds what is drawn. Every view but one uses the factors 0.6 and 0.8: the screen spans 5/6 of a view unit either side of the middle across and 5/8 up and down, about 80 by 64 degrees, with square pixels on a 4:3 screen. View 0x20, a launch's bay, uses 0.35 and 0.467, about 110 degrees across, over the whole screen whatever the bars.
The game runs in the display modes the device lists, which it keeps in dmodes.bin, and starts at 640x480.
OpenReliant keeps the factor down and chooses the factor across that keeps pixels square, 0.8 * (height - 0.1) / (width - 0.1): on a 4:3 screen the game's 0.6, on a wider one a wider view.
Views¶
camera_view (0x539A34) holds the view and camera_object (0x539A8C) the object it shows. camera_set_view (0x0045F1B0) switches view and places the camera at once; camera_frame (0x0045FC90) places it once a frame. Views from 7 on are the game's cutaways, of launches, landings, jumps and deaths among others.
| View | Key | Camera | Named |
|---|---|---|---|
| 0 | Cockpit | From the cockpit, ahead, as the cockpit mode says | Cockpit View |
| 1, 2, 3 | Left, right, rear view | From the cockpit, turned -90, 90 and 180 degrees about the ship's down axis | Left View, Right View, Rear View |
| 4, 0x1E | Chase | a space | |
| 6 | Target | Round the player's target | Target Camera |
| 0xC | External | Round the player's ship | External Camera |
| 7 | Round the pilot's pod as the pilot ejects (The ejection's views) | Eject Camera | |
| 8 | Behind the object, turning with it about its own Y at 0.005 a tick and pulling away from 3000 at 10 a tick, as the player's ship is destroyed |
Death Cam | |
| 9 | During Warp Out, starts at (0, -350, -2000) in the saved departure frame, turned about Y by 0.5 - ticks * 0.0005 |
a space | |
| 10 | Holds the preparation camera while the ship enters its warp tunnel | a space | |
| 11 | 10000 units along the arrival tunnel's axis at high detail, 3000 at lower detail, watching the ship with roll ticks * -0.003 |
a space | |
| 0x2B | Beside the Nanny, watching the player's ship dock and rearm | a space | |
| 0x0F | Beside the player's ship during the Yamato launch, rising and following it (Launches) | a space | |
| 0x10 | Ahead of the Yamato's launching ship, held still with a fixed orientation | a space | |
| 0x11 | Beside the Yamato's launch bay, held still and watching the player fly out | a space | |
| 0x12 | Missile | Behind a missile the object launched (Missiles) | Missile Camera |
| 0x1A | From where the camera was, watching the object | a space | |
| 0x1B | From where the camera was, watching where the player's ship burst (explode_marker), which drifts on at a quarter of its velocity a frame |
a space | |
| 0x1C | Round the ship picking up the player's pod, closing in | a space | |
| 0x1D | From behind the player's pod, at the Sabre that shoots it down | a space | |
| 0x17 | Close ahead of the player's ship and above it, looking back at it as it jumps in (The jumps' views) | a space | |
| 0x18 | Far ahead of where the player's ship jumps in, held | a space | |
| 0x19 | Beside where the player's ship jumps in, watching it | a space | |
| 0x27 | Out along each of the player's ship's axes, watching it jump out | a space | |
| 0x20 | From within a launch's bay, beside the ship, looking down after it as it drops (Launches) | a space | |
| 0x21 | From far below a launching ship, looking up at it | a space | |
| 0x22 | From beside and below a launching ship, looking at it, the whole scene shown | a space | |
| 0x24 | Flyby | From a point the player flies past | a space |
| 0xD | Along the mission's curves, or at a ship, for the script's shots (The director's view) | a space |
The view table (camera_view_table, 0x4F72A8) holds four bytes a view, for views 0 to 0x2B: the language string that names the view, whether cinematic bars slide in, and whether it is from the cockpit. camera/views.zig transcribes it; make view-tables derives it again. The bars slide in for views 7 to 0x27 and 0x2B, but not the external view; views 0 to 3 are from the cockpit. The names are strings 170 to 182 of language.dll; string 174, Chase Camera, is none of them, the chase views and most cutaways taking 181, a single space. From the cockpit the object's flag bit 0 is set, except in the chase mode, and cleared when the view moves off it. The bars grow by 0.001 of the screen a tick to 0.1, top and bottom; a view without them clears them at once.
camera_locked (0x539ACC) holds the camera for a script: camera_set_view refuses a switch unless forced, and the camera keys do nothing. frame_controls (0x00414060), once a frame, maps the camera keys to views. The cockpit key, pressed in the cockpit view, first moves cockpit_mode (0x539A9C) on:
| Mode | Cockpit view |
|---|---|
| 0 | From the eye, no cockpit drawn |
| 1 | From the eye, the cockpit's model drawn over the view |
| 2 | The chase view |
The options' cockpit setting (cockpit_mode_setting, 0x5D5A78), which WinMain reads from the ini's [Device] View as the game starts (0x004A9064), 0 where the ini has none, picks the mode: 0 for mode 1, 1 for mode 2 and any other for mode 0. A mission's start sets the mode it picks (mission_start, 0x0049359E). The Reliant's launch holds the camera in view 0 in mode 1 from its start, shows one of three cutaways, views 0x20 to 0x22, and at its last step sets the mode the setting picks and switches from a cutaway to view 0, no longer held (Launches). Resuming from the pause (game_pause, 0x00491E20) switches to view 0 again when the setting changed while paused.
OpenReliant keeps the setting with the camera, which --view sets. A ship that does not launch starts in view 0; one too large for the chase mode's distance starts in the external view instead, as OpenReliant flies ships the game never gives the player.
Cockpit¶
The camera's orientation is the ship's turned by the view's angle, and its position the ship's plus the model's eye point, the .SHP header's vector at 0x08, turned likewise, so the rear view looks back from behind the ship. The Kamov (ship type 0x2D) looks back from 1500 behind it instead.
In view 0 outside the chase mode, camera_frame also moves the cockpit's model (rendering.md), whose root hangs from the camera's frame. With each of the ship's rates of turn taken over its flight model's full rate, and its speed over its cruise speed, each held between -1 and 1:
- The root turns by the pitch rate times -0.1, the yaw rate times -0.15 and the roll rate times -0.1, so the cockpit sways against a turn, and stands at 50 times the speed along
Zless the cockpit model's own eye point, so that the eye is at the camera and the cockpit slides back as the ship speeds up. - The hands, the model's second part, turn by the pitch rate times 0.15 in pitch and the roll and yaw rates together times 0.2 in roll, about their part's mount point; they stand at their part's position less the object's centre, less 30 along
Ztimes the guns' kick (0x005636E0), which the player's guns set to 1 as they fire (0x0047BE3A) and which loses a twentieth each frame.
Each frame, camera_frame first caps hit_shake (0x00588724) at 2, takes a tenth of it as the shake, and lowers hit_shake by 0.02 a tick. The root then jitters in yaw and roll by a random amount of up to half the shake either way, from two rand numbers drawn every frame, the first for the roll. While the shake is above zero, the camera also turns by a random amount of up to half of 0.03 times the remaining hit_shake, in the world's frame. Blows to the player's ship raise hit_shake (damage_feedback), and so does object_move while the player's ship flies faster than its cruise speed (see Motion). Before any of that, while hit_shake is above 0.1 and the joystick has force feedback, camera_frame plays the Shake effect on it (Controls).
Chase¶
camera_chase (0x0045ED60) puts the camera at (0, h, d) in the ship's frame, turned:
| Ship type | h |
Distance at no throttle |
|---|---|---|
| 2, Grendel | -650 | 1800 |
| 8, Wolverine | -850 | 2000 |
| 9, Reaper | -800 | 2400 |
| 0x2D, Kamov | -1000 | 3400 |
| Others | -750 | 1800 |
d moves a tenth of the way to -(400t + distance) each frame, with t the throttle, 1.5 on the afterburner; switching to the view starts it at 1500, ahead of the ship. The camera swings against the ship's rates of turn, in radians per update: toward -5.7 times the pitch rate, within a sixteenth of a turn and then halved when negative and one and a half times when positive, -5 times the yaw rate and -3 times the roll rate, within a tenth of a turn, each 5% of the way a frame, the roll adding 5% of the yaw's target too. The offset is turned by the ship's orientation, then the pitch about X, then the yaw about Y; the camera's orientation is the ship's turned by the roll about Z. Objects whose type is 0x100 or more have no chase view and fall back to the cockpit.
Orbits¶
The target and external views put the camera at (0, 0, d) turned by the yaw about Y and then the pitch about X, in the world's axes, from the object, and look at it. d is kept between 1.8 radii of the object and 5.8 for the target or 3.8 for the player's ship; switching to either view zeroes the yaw, the pitch, their speeds and d.
frame_controls steers them from the arrow keys, fixed, whatever the bindings, in ticks of a hundredth of a second:
- Left and right change the yaw's speed by 0.1 degrees a tick, within 5 degrees a tick; then it slows by 0.05 toward 0. The yaw moves by the speed and wraps into 0 to 360.
- Shift with up or down moves the camera in or out by 60 a tick.
- Up and down change the pitch's speed likewise, which slows likewise and then keeps within 5. The pitch keeps within 89.5 degrees either way, and stops there.
The target view needs the player to have a target; without one it switches to the cockpit.
Flyby¶
The flyby view starts a radius below the player's ship and four ahead, in its frame, and stays there, looking at the ship, until the ship is more than 23000 away; then it moves there again. It keeps at least a radius from the ship.
An object's radius is its farthest vertex from its origin, over its parts' finest levels (object_bounds, 0x00476680).
The ejection's views¶
The views of the player's ejection stand off from what they watch by an offset
(camera_cutaway, 0x00539A44) that camera_set_view works out as it switches to them, with t
the ticks since:
- View 7, Eject Camera, as the pilot ejects: the object's
Xaxis times 5000 (0x0045F479), from the object as it stands then. The camera stands that far out from the object, the offset turned about the world'sYby 0.005 a tick timest, and looks at it. - View
0x1C, as a nanny ship or the Antanov picks the pod up: half the way from the object, the ship, to the player's pod. The camera is turned as the ship, turned further about its ownYby 0.002 a tick timestand a quarter turn (0x004DC74C,0x004DC51C), and stands back from the point the offset marks along its own axis ahead by10000 - 2t, no nearer than 1000. - View
0x1D, as a Sabre shoots the pod down: the way from the pod to the object, the Sabre. The camera stands behind the pod the other way, 1000 off, and looks at the Sabre. While the pod has not begun to explode the view's time holds at 0 (camera_switchedmoves on); then it pulls back by 20 a tick.
Improvement: with smooth motion, views 7, 8, 0x1C and 0x1D go on by the share of a tick
the frame is drawn past its tick as well (objects.pastTick), so they move every frame, as the
objects they watch do; the game moves them a tick at a time, which a display's frames fall between
unevenly. --no-smooth-motion and --original move them on ticks.
Improvement: view 0x1C's quarter turn is exact; the game's is 0.785398.
The jumps' views¶
The player's jumps switch to their views held and forced, with the player's ship as the
object. camera_set_view places the camera, and camera_frame moves it, with t the ticks since:
- View
0x27, as Jump Out begins: the camera stands 8000 out along each of the ship's axes, from where the ship stands then (0x0045FB18), and looks at it. - View
0x17, one of Jump In's three: the camera stands 200 to the right of the ship, 500 above it and ahead of it by 1200, from 50 ticks on by1200 + 10 (t - 50), and from 70 on by 1400 (0x00460EC5), looking at it, in the ship's frame each frame. While hits shake the cockpit (hit_shake), the camera shakes with them as it does in view 0; Jump In's flight sets the shake.camera_set_viewfirst places it 50000 ahead of the ship and 500 above it, whichcamera_framereplaces at once. - View
0x18: the camera stands 27000 ahead of the ship and 300 below it as the ship stands placed to fly in, 25000 behind where it arrives (0x0045F8E7), and holds there, looking at where the ship stood, level in the ship's frame: the look is taken with both points turned into the ship's frame, and turned out of it again. - View
0x19: the camera stands 2000 to the ship's left, 100 above it and 25000 ahead, likewise (0x0045F91E), and looks at the ship each frame.
camera_set_view moves the camera's marker (0x00588390) to where views 0x18 and 0x19 stand.
OpenReliant's camera keeps its own place for them, as for the flyby and target views.
Improvement: with smooth motion, view 0x17 pulls away by the share of a tick the frame is
drawn past its tick as well, as the ejection's views do.
The landing's views¶
The Reliant's landing picks one of two views at random, held and forced, with
the landing ship as the object. camera_frame places the camera each frame off the middle of the
launch tube the ship lands in, which the landing keeps, turned as the carrier is:
- View
0x23: 500 to the tube's right and 500 behind it, level with it (0x00460A17), looking at the player's ship (camera_ease_to_player, all the way). The tube lies within the carrier's hull, so the view looks out through its opening upper door. - View
0x26: 3500 to the tube's left, 1000 above it and 3000 behind (0x00460AB9), looking at the view's object.
The display names view 0x23, but not 0x26. Improvement: from within the tube, the sound is
heard as in a hangar (Sound). The Yamato's landing picks views 0x0E and 0x25,
which OpenReliant has not ported (#349).
The director's view¶
View 13 shows the shots a mission's script stacks for the director's camera, which
flies the camera along the mission's curves or stands it at a ship. The first shot switches to it,
held and forced, and the director moves the camera each frame. Once the director has gone back to
view 0, camera_frame ends the shot and begins the next waiting. camera_set_view holds the shot's
ships still as it switches to the view, and lets them go as it switches away
(The ships a shot holds).
This page leaves out the cockpit's model and its motion, the shake from hits (hit_shake, 0x588724) and the other cutaways.