Camera Update

**UNFINISHED**

Each game tracks the camera's current progress within a level with the following:

* Current zone in which the camera resides
* Current path, in that zone, that the camera is travelling
* Current progress of the camera along that path

...

## Camera Follow Mode

In Camera Follow Mode, updating the camera refers to the process of recalculating the camera's current progress and updating the level [with the recalculated progress] as the player progresses towards (or digresses from) the goal. This may include updating the current zone if the camera and player venture into a neighboring zone and/or updating the current path if the camera and player pass either of its endpoints into territory of a neighboring path, along which the camera would follow closer to-providing a more appropriate view of the player.

The camera's current progress is determined by the index of the point in the current path that is closest to-not the player, but instead-a point otherwise known as the *unprojected camera location*, which is located a number of units to the left or right (in the X direction), above or below (in the Y direction), and behind the player (in the Z direction). The camera is ultimately positioned at the location of the point with index equal to the current progress value. Note that, without the additional adjustments, the camera would be positioned directly at the player's approximate location along the path [i.e. closest point], which may fail to provide a full view of the player. For example, in forward/backward zones this would provide a sort of first-person view rather than a full view of the player; however, if the point were adjusted somewhat backwards, its closest point on the path would be a point that were approximately behind the player. In left/right zones this may not matter as their paths span left to right and are typically already positioned somewhat behind the player's roaming area.

At any instant there may be some point among [the current path's] neighboring paths that is closer to the unprojected camera location than any other point in the current path. This would mean that the player has progressed/retrogressed so far such that the unprojected camera location is now closer to [the point in] some neighboring path-and thus projects to a point that either passes the end or backtracks before the beginning of the current path. In these cases, the neighboring path with the point closest to the unprojected camera location is chosen to replace the current path.

### Camera Follow Routine

The *camera follow routine* handles updating the camera in Camera Follow Mode. Its generalized operation is as follows:

1. Calculate [updated] unprojected camera location
2. Find the path among the current path and its neighbors [with point] closest to the unprojected camera location
3. Update level with potentially any combination of the following:
	* A new current zone = if it is different from the current, the parent zone of the path closest to the unprojected camera location
	* A new current path = if it is different from the current, the path closest to the unprojected camera location
	* A new current progress = the index of the point closest to the unprojected camera location, in the path that contains it

#### Operation

Note: camera *looks forward* or *looks backward* do not actually refer to the *camera* looking forward or back. Instead, these refer to the camera looking to a point that is *adjusted* either forward or backward as the *player* looks forward or back.

1. Calculate [updated] unprojected camera location
	* Determine the nearest neighboring camera paths [to the camera]
		+ If current progress at less than half way or at most 50 points into the current path, nearest neighbors include all preceding neighbors
		+ If current progress at or more than half way or at most 50 points from the end of the current path, nearest neighbors include all proceeding neighbors
	* Determine z look/x pan flags
		+ If current zone intended for forward/backward travel
			- If up is pressed, [set flag for] camera *looks forward*
			- If down is pressed, [set flag for] camera *looks backward*
		+ If current zone intended for left/right travel
			- If left pressed, [set flag for] camera *pans left*
			- If right pressed, [set flag for] camera *pans right*
		+ If current zone not intended for forward/backward travel
			- Camera is forced to either look forward or back, depending on zone flag
	* Determine z look/x pan factors
		+ Increase or decrease *z look* factor at rate of 50 m/frame, depending on whether cam looks forward or backward; restrict this factor to the range -300m to 300m (\*Cortex Power: -1200m to 1200m)
		+ Increase or decrease *x pan* factor at rate of 100 m/frame, depending on whether cam pans left or right; restrict this factor to the range -300m to 0m [offsets left] if the current path travels left or to the range 0m to 300m [offsets right] if the current path travels right
	* Determine y pan/z zoom factors
		+ If the current or at least one nearest neighbor path travels forward/backward and the current progress is at least 10 points into and from the end of the current path
			- If the current path travels forward/backward, seek *z zoom* factor from its previous value towards the current path's `camzoom` value at a rate of 25 m/frame.
			- Else if there exists a nearest forward/backward [travelling] neighbor, set *z zoom* factor to the neighbor's `camzoom` value
		+ If the current or at least one nearest neighbor path travels up/down
			- If the current path travels up/down, seek *y pan* factor from its previous value towards the current path's `camzoom` value at a rate of 100 m/frame.
			- Else if there exists a nearest up/down [travelling] neighbor, set *y pan* factor to the neighbor's `camzoom` value.
	* Determine total z adjustment factor by sum of *z look*, *z zoom*, and player's `camzoom` value; let total x and y adjustment factors be *x* and *y pan* factors, respectively.
	* Calculate unprojected camera location by adding x, y, and z adjustment factors respectively to player location.
2. Find the path among the current path and its neighbors that is *closest* to the unprojected camera location
	* For the current path
		+ If the current path travels forward/backward
			- TBD
		+ If the current path does not travel forward/backward
			- Calculate the unprojected camera location's projected progress along the current path
				* Calculate vector *a* as the direction vector that spans from the current path's start location (i.e. position of initial point 0) to the unprojected camera location
				* Let vector *b* be the current path's direction vector; graphically this refers to a unit vector that is a linear approximation of the path, starting at its start location and pointing in its direction
				* Calculate the camera's projected distance along the current path by computing the scalar projection of *a* onto *b*. Since *b*-the path's direction vector-is already a unit vector, this is just the dot product of *a* and *b*.
				* Divide the camera's projected distance along the current path by the average distance between its path points. This directly converts the camera's projected distance along the path to the index of a point [along the path]-i.e. the camera's projected progress along the path.
			- If the projected progress refers to a point before the path entrance or past the path exit (i.e. is an invalid point index)
				* Reset progress to either the index of the first point or the last point in the path
				* Mark the projected change in progress as non-existent
			- Get the actual [projected] camera location at the projected progress point
				* If this camera location is any more than 12.5 m from the unprojected camera location in either the x, y, or z dimension, then eliminate this path from being a potential closest
			- Calculate and record euclidean distance from unprojected camera location to actual camera location; this is the equivalently the distance from the unprojected camera location to the [nearest point on the] path
		+ If the path is still a potential closest
			- Calculate and record the [absolute] projected change in progress by computing absolute value of the difference between current progress and projected progress
			- If the [non-absolute] projected change shows a decrease in progress, mark the projected change as a digression; else if it shows an increase in progress, mark it as a progression
	* For each of the current path's nearest neighbors
		+ If that neighbor path travels forward/backward
			- TBD
		+ If that neighbor path does not travel forward/backward
			- Calculate the unprojected camera location's projected progress along that [neighbor] path
				* This is done in the same way as for the current path
			- If the path's parent zone header flags bit 19 set: if the path travels left/right and the unprojected camera location is more than 50m under the [initial point of] the path, eliminate this path from being a potential closest
			- If this path and the current path both travel in the same y and z direction (i.e. either up-left, up-right, down-left, down-right, or do not at all travel up/down and left/right)
				* If this path is in front of the current path (i.e. such that, if chosen as the new/closest path, the camera would 'enter' at its *entrance* point)
					+ If the projected progress lies before the path's entrance cutoff point, then eliminate this path from being a potential closest
					+ Else if the projected progress lies before the path's default entrance point (0), eliminate this path from being a potential closest
				* Else if this path is behind the current path (i.e. such that, if chosen as the new/closest path, the camera would 'enter' at its *exit* point)
					+ If the projected progress lies after the path's exit cutoff point, then eliminate this path from being a potential closest
					+ Else if the projected progress lies after the end of the path/the path's default exit point, eliminate this path from being a potential closest
			- Get the actual [projected] camera location at the projected progress point
				* If this camera location is any more than 12.5 meters from the unprojected camera location in either the x, y, or z dimension, then eliminate this path from being a potential closest
			- Calculate and record euclidean distance from unprojected camera location to actual camera location
		+ If this path is still a potential closest, then calculate and record the total [absolute] projected change in progress:
			- If this path is further from the goal than the current path
				* *From the perspective of the player as it faces towards the goal:* if this path is in *front* of the current path
					+ This doesn't make sense. From the perspective of the player as it faces towards the goal, a path that is further from the goal than the current path must either be behind, to the left, to the right, above, or below it. this path could not possibly be in front of the current path if it is supposedly further from the goal; such paths do not exist in any zone entry of any NSF; an incorrect progress calculation will ensue for such paths
				* *From the perspective of the player as it faces towards the goal:* if this path is *behind* the current path
					+ -the camera will 'exit' from the current path's *front endpoint* as the *exit* point
					+ -the camera will 'enter' at the new path's *back endpoint* as the *entrance* point
					+ Get the amount of progress so far accumulated in relation to the *exit* point or *front* of the *current* path-this is just the current progress. (The camera would first have to move back this amount to reach *this* path.)
					+ Get the projected amount of progress along *this* path [if it were chosen] in relation to its *back* endpoint (i.e. last point) as the *entrance* point
						- Compute the absolute difference between current progress and projected progress
						- Subtract the computed difference from the length of the path/index of its last progress point
					+ Sum the 2 progress amounts to get the total projected change in progress; record this value
			- If this path is closer to the goal than the current path
				* *From the perspective of the player as it faces towards the goal:* If this path is *in front* of the current path
					+ - the camera will 'exit' from the current path's *back endpoint* as the *exit* point
					+ - the camera will 'enter' at the new path's *front endpoint* as the *entrance* point
					+ Get the amount of progress that would need to be accumulated to reach the *exit* point of the *current path*
						- Compute difference of current path length [index of its last progress point] and current progress to find remaining progress
					+ Get projected amount of progress along *this* path [if it were chosen] in relation to its *front* *endpoint* (i.e. first point) as the *entrance* point
						- Compute the absolute difference between current progress and projected progress
					+ Sum the 2 progress amounts to get the total projected change in progress; record this value
				* *From the perspective of the player as it faces towards the goal:* If this path is *behind* the current path
					+ This doesn't make sense; see above. An incorrect progress calculation will ensue.
	* Using the information recorded for each of the potentially closest paths
		+ Choose the closest path to the unprojected [updated] camera location (i.e. with minimum euclidean distance) for which it, preferably, would exhibit a projected change in progress [upon updating current progress using the total projected change]
		+ If no path exists for which the updated camera location corresponds to a projected change in progress
			- Return without updating level; not necessary
3. Update level:
	* Approximate the distance between the current camera location and the new [updated] projected camera location: multiply change in progress recorded [for the chosen path] by the average distance between points in the current path (this converts the change in progress to a change in distance).
		+ If this distance is less than .45778m?
			- Record the projected change in progress as camera speed
			- Update the level with new projected progress as the current progress; the camera will not have moved far and will thus remain on the current path, so there will be no change in and no updating of current path or zone
		+ If this distance is greater than [or equal to] .45778m?
			- Update camera speed
				* If the projected change in progress is less than or equal to 2 points
					+ Set camera speed to half the projected change in progress
				* If the projected change in progress is between 2 and 5 points
					+ Set camera speed to 2 points/frame
				* If the projected change in progress is 5 or more points (impossible delta)
					+ Set camera speed to half the projected change in progress if it is more than camera speed; else increment camera speed by 1 point/frame
			- Update the level with a new progress, given the updated camera speed
				* If the projected change in progress would bring the camera *closer to* the goal
					+ If the chosen path [closest to the approximate camera location] is the current path
						- Calculate an *alternate new progress* (used rather than the new projected progress) by adding camera speed to the current progress.
						- Update the level with the alternate new progress as the current progress; the camera will remain on the current path, so there will be no change in and no updating of current path or zone
					+ If the chosen path is a neighboring path [rather than the current path], then the projected change in progress should bring the camera out of the current path and into that neighboring path-which is past the current path:
						- Also, calculate an *alternate new progress* by adding camera speed to the current progress. For further verification that, at its ultimate new progress, the camera will indeed be brought into that neighboring path, if the alternate new progress would exceed the length of the path (i.e. cross the *back endpoint*), then it would be an invalid progress-a progress which would instead refer to a point in the neighboring path past the current path:  (else treat as if the chosen path were the current path; see above)
							* Readjust the alternate new progress in relation to the *front* *endpoint* of the neighboring path
								+ Subtract length of the current path from the alternate new progress to get the amount of [the alternate new] progress that would exceed the *back endpoint* of the current path into the neighboring path
								+ If the neighboring path is behind the current path, negate the amount of exceeding progress
								+ Add this to the index of the neighboring path's *front endpoint*
								+ Set the alternate new progress to this readjusted value
							* Update the level with:
								+ The neighboring path's parent zone as the current zone
								+ The neighboring path as the current path
								+ Whichever is less: either the projected new progress or the alternate new progress, as the current progress.
				* If the projected change in progress would bring the camera further from the goal
					+ If the chosen path [closest to the approximate camera location] is the current path
						- Calculate an *alternate new progress* [used rather than the new projected progress] by subtracting camera speed from the current progress.
						- Update the level with the alternate new progress as the current progress; the camera will remain on the current path, so there will be no change in and no updating of current path or zone
					+ If the chosen path is a neighboring path [rather than the current path], then the projected change in progress should bring the camera out of the current path and into that neighboring path-which is behind the current path.
						- Also, calculate an *alternate new progress* by subtracting camera speed from the current progress. For further verification that, at its ultimate new progress, the camera will indeed be brought into that neighboring path, if the alternate new progress would be less than 0 (i.e. cross the *front endpoint*), then it would be an invalid progress-a progress which would instead refer to a point in the neighboring path that falls short of the current path:  (else treat as if the chosen path were the current path; see above)
							* Readjust the alternate new progress in relation to the *back endpoint* of the neighboring path
								+ The amount of progress that exceeds the *front endpoint* of the current path into the neighboring path is just the current progress
								+ If the neighboring path is *in front* of the current path, negate the amount of exceeding progress
								+ Add this to the index of the neighboring path's *back endpoint*
								+ Set the alternate new progress to this readjusted value
							* Update the level with:
								+ The neighboring path's parent zone as the current zone
								+ The neighboring path as the current path
								+ Whichever is less: either the projected new progress or the alternate new progress, as the current progress.