Zone

A Crash level is composed of invisible *zones*. Each zone is a cubic region of 3 dimensional space, with dimensions (width, height, depth) and unique location/position, within its containing level. The space occupied by a zone approximately encompasses [the evidently interactive portions of] up to 8 worlds. All together as a whole, a level's zones encompass all of the apparently interactive space occupied by its worlds and any additional surrounding 'atmosphere'; this complete enclosure defines the approximate boundaries for the entire level.

## Description

In an instance of a Crash game, when initially entering a level, the player character (Crash/Willie) is spawned at a specific location within the level's *first zone*-(i.e. its *initial entry point*). At this point, the worlds encompassed by the zone, and possibly other nearby worlds, are visible to the player, and the player character is typically in a location where it appears to be supported by some aspect of the worlds-usually terrain. The player is now free to complete one or more level objectives for furthering its overall game progress.

In a Crash 1 [non-boss] level, the player's primary objective is to progress towards and ultimately reach the goal-i.e. the warp platform located at the end. Crash 2 and 3 extend this objective by requiring that the crystal be collected at some point along the path to the goal. Together, the zones provide the play area through which the player is to roam towards its goal. The player progresses from zone to zone, encountering various obstacles along the way, until it either reaches the goal, or dies in its pursuit.

TBD: introduction for header, dimensions/collision octree, camera paths, and entities

## Structure

TBD: zonecollisions, entity

```
struct zoneheader
{
 unsigned long worldcount;
 wgeomodel world[8];
 unsigned long headercount;
 unsigned long campathcount;
 unsigned long entitycount;
 unsigned long neighborcount;
 union
 {
 entry \*neighbor[8];
 unsigned long neighboreid[8];
 };
 unsigned long tpagecount;
 unsigned long tchunkcount;
 unsigned long tpage[8];
 unsigned long tchunk[32];
 unsigned long loadflags;
 unsigned long vramfillh;
 unsigned long unknownA;
 unsigned long visibilitydepth;
 unsigned long unknownB;
 unsigned long unknownC;
 unsigned long unknownD;
 unsigned long unknownE;
 unsigned long flags;
 unsigned long deathy;
 unsigned long unknownF;
 unsigned long unknownG;
 unsigned long unknownH;
 unsigned char vramfillr;
 unsigned char vramfillg;
 unsigned char vramfillb;
 unsigned char unused\_a;
 unsigned char farcolorr;
 unsigned char farcolorg;
 unsigned char farcolorb;
 unsigned char unused\_b;
 struct slightmatrix objectlightmatrix;
 struct scolor objectcolor;
 struct scolormatrix objectcolormatrix;
 struct scolor objectlightintensity;
 struct slightmatrix playerlightmatrix;
 struct scolor playercolor;
 struct scolormatrix playercolormatrix;
 struct scolor playerlightintensity;
};

struct zonepathdescriptor
{
 unsigned char relation;
 unsigned char neighborzoneindex;
 unsigned char campathindex;
 unsigned char goal;
};

struct zonecampathpoint
{
 signed short x;
 signed short y;
 signed short z;
 signed short rotx;
 signed short roty;
 signed short rotz;
};

struct zonecampath
{
 unsigned long slsteid;
 union
 {
 entry \*parentzone;
 unsigned long parentzoneeid;
 }
 unsigned long neighborpathcount;
 struct zonepathdescriptor neighborpathdescriptor[4];
 unsigned char entranceindex;
 unsigned char exitindex;
 unsigned short length;
 unsigned short cammode;
 signed short avgptdist;
 signed short camzoom;
 unsigned short unknownA;
 unsigned short unknownB;
 unsigned short unknownC;
 struct svector direction;
 struct zonecampathpoint point[];
};

```

## Zone Dimensions/Collision Octree

### Collision Octree

Each node in the zone's collision octree, except for the root node, is the child of a parent node. Each parent node has either 8, 4, or 2 children nodes.

Each node corresponds to a portion of 3-dimensional space occupied by the zone. The root node corresponds to the entire region of space occupied by the zone (specified at offsets 0x0 to 0x14). Each child node corresponds to a separate subdivision of the space occupied by its parent. The location and dimensions of a subdivision respectively vary based on the corresponding node's index among its siblings and its depth within the tree.

In relation to its corresponding node's parent's associated region of space, a subdivision can be any region resulting from an even partitioning by any combination of 1 to 3 coordinate axis-aligned hyperplanes:

* Upper left front, upper left back, lower left front, lower left back, upper right front, upper right back, lower right front, or lower right back octant
* Upper left, Lower left, Upper right, Lower right, Front left, Back left, Front right, Back right, Upper front, Upper back, Lower front, or Lower back quadrant
* Left, right, top, bottom, front, or back half

Thus, if a node's parent's associated region of space were split in half along a line parallel to either the x, y, or z axis, then optionally split in half along a line parallel to either one of the remaining axes, and then optionally split in half along a line parallel to the remaining axis, the node's associated region of space could be any of either the resulting halves, quadrants, or octants. In these terms, 3 factors determine the location and dimensions of a subdivision: the number of split lines (1 to 3), the respective axes/axis parallel to those/that split line(s) (x and/or y and/or z), and the number/index of the resulting half, quadrant, or octant that encompasses its space.

For any parent node with depth less than the minimum of the respective maximum x, y, and z depths (specified at offsets 0x1E,0x20,0x22), 3 split lines-each respectively parallel to the x, y, and z axes-determine the 8 octants that, respectively, encompass its children's corresponding subdivisions of space. For the children of parent nodes with a depth greater than or equal to the minimum, the split line(s) parallel to the axis/axes for which is/are specified that minimum are eliminated when determining the corresponding subdivisions. For the children of parent nodes with a depth greater than or equal to the second minimum, i.e. the minimum of the remaining 2 maximums (if any), the respective split lines parallel to the axes for which are specified the minimum *and* second minimum are eliminated when determining the corresponding subdivisions. The maximum of the 3 maximum depths determines the height of the tree.

For example, suppose maximum depth x were the minimum of the maximum depths-3, for example. Suppose also that maximum depth z were the second minimum-7, for example. For any parent node with depth less than 3, each of its children's corresponding subdivisions is a separate octant of its (the parent's) associated region of space. For any parent node with depth greater than or equal to 3 but less than 7, the *x* split line is eliminated in determining the subdivisions of its associated region-thus, it is only split in half y-wise and z-wise; equivalently, it is only split into 4 quadrants-an upper front, lower front, upper back, and lower back quadrant. Such a parent node could then have only 4 children, each respectively corresponding to a separate one of the 4 subdivisions/quadrants. For any parent node with depth greater than or equal to 7, the *x* and *z* split lines are eliminated in determining the subdivisions of its associated region-thus, it is only split in half y-wise; equivalently, it is only split into 2 halves-a left half and a right half. Such a parent node could then have only 2 children, each respectively corresponding to a separate one of the 2 subdivisions/halves.

* Parent nodes with depth less than the minimum have 8 children-but only if the minimum is nonzero.
	+ If a unique minimum [max] depth of 0 is specified for only one of the 3 axes, parent nodes with depth less than the second minimum have 4 children.
	+ If a minimum depth of 0 is specified for 2 of the 3 axes, all parent nodes have 2 children.
	+ If a minimum depth of 0 is specified for all axes, the tree is empty.
* Parent nodes with depth greater than or equal to the minimum and less than the second minimum(if it exists) have 4 children-but only if the minimum is unique.
	+ If the same minimum depth is specified for 2 of the 3 axes, parent nodes with depth greater than or equal to the minimum have 2 children.
	+ If the same nonzero minimum/maximum depth is specified for all axes-that is, there does not exist a second minimum-then all parent nodes have 8 children.
* Parent nodes with depth greater than or equal to the second minimum have 2 children-but only if the [first] minimum or second minimum is unique.
* Height of the tree is given by the maximum [of the max] depth(s).

### Octree Node Format

Each node in the octree is specified as an unsigned short (2 bytes). The relative offset of the root node within the item is specified at offset 0x1C.

#### Internal/parent nodes

Internal/parent nodes are indicated by a cleared LSB (least significant bit); consequently, their [nonzero] value refers to the relative offset of [the first of] their children in the *item*. Child nodes are stored contiguously as groups of 8, 4, or 2. The cardinality and arrangement of a parent's group of child nodes depends on its depth in relation to the axis associated maximum depths:

* The Parent Depth Condition column lists conditions under which a parent node's contiguous group of children have the associated formats. Only the bolded conditions are relevant if max depths are unique. The following symbols are used for brevity:
	+ `d` = parent node depth
	+ `max*` = max depth \*
	+ `M` = {`max*`} (for `*`=`x`,`y`,`z`)
	+ `min` = `min(M)`
	+ `min2` = `min(M - {min})`
	+ `max = max(M)`
* The Children Group column lists the arrangement or byte format of the parent's group of child nodes; depending on conditions, there are either 8 children [A-H], 4 children [A-D], or 2 children [A-B] in the group.
* Each of the A-H columns identifies that child's corresponding subdivision with an abbreviation:
	+ L = left, R = right, U = upper, D = lower, F = front, B = back

#### Non-existent nodes

Non-existent nodes are indicated with a value of `0`. A non-existent node refers to empty space; there is nothing particularly interesting about its corresponding subdivision, since the player will never interact/collide with it.

#### Leaf nodes

Leaf nodes are indicated by a set LSB; the remaining 15 bits describe collision attributes for the node's corresponding subdivision:

`UUUUUUSSSSSSTTT1`

* `T` = Node type
* `S` = Node subtype
* `U` = Unknown/unused?

Node type and subtype refer to type and subtype of the node's corresponding collidable subdivision of 3 space.

##### Node Type

Node type determines the primary type of corresponding collidable space:

 1
 2
 3
 4

##### Node Subtype

Solid and Interactive, Pit Area, and Trigger Misc Death on Collision type nodes (types 0, 3, and 4) may optionally specify a node subtype. This subtype determines a specific event sent to the player upon collision with the node:

It is yet to be determined whether there are additional subtypes with other purposes.

## Camera Paths

In each game, the camera follows behind the player as it makes progress towards the goal. The camera, too, along with the player, makes progress towards the goal, albeit somewhat less advanced but at the same rate; thus, the player's progress within the level and the camera's progress within the level are directly related. In each game, the camera appears to travel a fixed path as it follows behind the player, zooming and panning accordingly.

A zone typically includes one or more connected *paths* along which the camera is to travel as the player character makes progress within that zone. As a whole, all paths [of all zones] in the level connect to form a *central path* from the initial player location to the goal, with possibly several divergences at any arbitrary point(s). Each divergence may or may not converge back into to the central path to trace out an alternate route.

### Path Points

Each path is composed of a number of closely positioned points that typically trace out an approximate line or smooth curve. Each point corresponds to a position of the camera, and is also associated with a camera orientation. The line or curve traced by a path connects its points in sequence, where points in the path are stored sequentially. Path points are commonly referred to as *progress points*.

* When the camera is **at** a point in a path, it is positioned at the location of that point and oriented according to the point's associated orientation.
* After the camera **moves** from the point that it is currently *at* to another point in the path, it will be *at* that other point.
* To move *along* a path, or move *further into* its trail, the camera moves from one point on the path to the next, and so on, until it reaches [is at] some desired destination point.

#### Path Progression

As the player *makes* *progress* within a zone, the camera consequently *makes* *progress* along the paths in that zone, thus keeping up with the player. As the camera progresses further along a path, it moves further into the path's trail. At any point on the path, by moving to the next point, the camera will have progressed one point further. The camera can progress from one point on the path to the next, and so on, until it reaches a desired destination point. The amount of progress made by the camera in a complete progression is the number of points that it has progressed further.

If the camera begins at the first point in a path and progresses to the *n*th point, it will have made an amount of progress equal to *1* point less than *n*. For example, if the camera begins at the first point in a path and progresses to the first point=*1*st/th point (*n*=*1*), then it will have made an amount of progress equal to *1-1=0* (no progress at all). The length of a path is just the number of points that it contains. If the camera begins at the first point in a path and progresses to the last point, it will have made an amount of progress equal to 1 less than the length of the path. The index of a [zero-indexed] path point is equivalent to the amount of progress that the camera will have made [after moving from the beginning/first point] at that point within the path. Thus, **each [progress] point is indexed by its corresponding progress value**.

#### Path Retrogression

Nothing prevents the player from *retrogressing* within a zone [unless it is at the initial entry point]; the player may return all the way back to its initial entry point in the first zone if it wishes. As the player retrogresses within a zone, its progress will *rewind*, as it is counterbalanced by a subtraction in amount. The camera consequently must retrogress along with the player for its continued viewing. As the camera retrogresses along a path, it moves back towards the beginning of (i.e the first point in) the path's trail. At any point on the path, by moving to the previous point, the camera will have retrogressed one point back towards the beginning. The camera can retrogress from a point on the path to its previous point, and so on, until it reaches any desired destination point that is closer to the beginning of the path's trail. The amount of progress lost by the camera in a complete retrogression is the number of points that it has retrogressed.

#### Retrogressing too close - problem

At any point on the path, by moving to the previous point, the camera will have retrogressed one point back towards the beginning. However, at the first point, the camera is already at the beginning, and there is no previous point to move to within that path. At the first point on that path, the camera's *current progress* will be 0, as it has not progressed to any point further. If the camera were to retrogress any closer back to the initial entry point [in the first zone] from [its current position at] the beginning of (i.e. the first point within) the path, its current progress would decumulate to become (1 less than 0 =) -1. However, this refers to an invalid point index; there does not exist a point with this index (i.e. one point before the first point) at which the camera could be positioned.

#### Progressing too far - problem

At any point on the path, by moving to the next point, the camera will have progressed one point further. However, at the last point, there is no next point to move to within that path. At the last point on that path, the camera's current progress will be 1 less than the length of the path-i.e. the index of the last point on the path. If the camera were to progress any further past [its current position at] the end of (i.e. the last point within) the path, its current progress would accumulate to become (1 less than the length of the path + 1 =) the length of the path. Path points are zero-indexed, however, so this would refer to an invalid point index; there does not exist a point with this index (i.e. one point past the last point) at which the camera could be positioned. If the path were extended past its current last point, this *would* be a valid index-that of a point that continued the path.

### Neighbor Paths - solution

Even unextended, the path still actually *does* continue past its last point. Recall that several paths in a zone can be *connected*: a single path may reference one or more connected *neighboring paths*. A path's neighboring paths may be:

* any path in its parent zone, other than itself
* any path in any of its parent's neighboring zones

Each of a path's neighboring paths contain either points that continue the path past its last point, or points that retrogress before its first point. The path's own points are a retrogression of the neighbor path [points] that continue past its last point, and are a continuation of the neighbor path [points] that retrogress before its first point.

#### Progressing too far - solution

When the camera reaches the [invalid] progress that is an invalid index of a point that would be *one point past the last point* in the path, the *current path* is changed to a neighbor path [with points] that continue(s) the path past its last point; the camera is said to have *entered* this path, particularly at its *entrance* (i.e. beginning/first point). As it has only just reached the beginning of/first point in this connected path, the camera's current progress along that path is also set to 0 (index of first point). The camera can then continue to progress within that path as necessary along with the player, just as it had done in the previous path.

#### Retrogressing too close - solution

When the camera reaches the [invalid] progress that is an invalid index of a point that would be *one point before the first point* in the path, the current path is changed to a neighbor path [with points] that retrogress(es) from the path before its first point; the camera is said to have *re-entered* this path, particularly, at its *exit* (i.e. end/last point). As it has re-entered the connected path at its exit point, the camera's current progress along that path is also set to 1 less than its length (index of last point). The camera can then continue to retrogress within that path as necessary along with the player, just as it had done in the previous path.

#### Specification

A path specifies up to 4 neighboring paths by including the following information for each path:

1. The zone that contains the neighboring path
2. The index of the neighboring path within that zone
3. Whether the neighboring path, in relation to this path, is a *continuation* or a *retrogression*
	* A continuation indicates that the neighboring path is closer to the goal than this path
	* A retrogression indicates that the neighboring path is further from the goal than this path
4. Whether the neighboring path, from the perspective of the player as it faces in the direction of the goal, is:
	* In front of the path
	* Behind the path
	* Above/Below the path

#### Divergence and Convergence

More than one of a path's neighbors can be either a continuation or a retrogression of the path. Each is either an alternate continuation or retrogression of the path and equivalently either a divergence or convergence from/into the path. For example, at the beginning of the split in route towards the end of N. Sanity Beach, there is a path with 3 neighbors: one a retrogression (the path that leads into it), and the other 2 continuations the left and right branches, respectively, of the path. Right before the goal, the 2 branches meet up again, converging to a singular central path; the point of convergence is of a path with 3 neighbors: one a continuation, which is the final path of all paths in all zones of the level, whose last point is located right behind the goal, and the other 2 retrogressions the left and right branches, respectively, that lead into the path.

### Additional Parameters

Each camera path includes the following additional information:

* [Polygon] Sort list
* Parent zone
* Camera mode
* Camera zoom/pan factor
* Length of the path
* Alternate entrance and exit point relative indices
* Average distance between each path point
* Approximate direction of the path (a unit vector)

Average distance between each path point and approximate direction of the path are used to convert the camera's location within the level to a progress along the path. The camera typically has an idea of how much it should move from its current location to keep up with the player, but not in terms of how much it should progress along the path. Usually the camera would *like* to move to a location that lies outside of the path, but can not since its movement is restricted following along that path. Thus, the scalar projection of the camera's desired, *unprojected* location onto a linear approximation of the path (i.e. path direction) is computed to determine its approximate projected location or distance along the path. This distance is then divided by the average distance between each path point to determine its actual progress along the path.

Purposes of the other fields are explained elsewhere (See: camera update routine TBD).