Zone

From Crash Bandicoot Hacking Wiki
Revision as of 01:44, 1 March 2020 by Mddass (talk | contribs) (Item 3+n: Camera Path)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

Format

Item 1: Header

Offset Field Size Value
0x0 World Count 4 bytes w
0x4 Reserved for World Models 8 x 0x40 bytes *
0x204 Index of First Camera Path Item 4 bytes h
0x208 Camera Path Count 4 bytes c
0x20C Entity Count 4 bytes e
0x210 Neighbor Zone Count 4 bytes n
0x214 Neighbor Zone EIDs 8 x 4 bytes *
0x234 Texture Page Entry Count 4 bytes p
0x238 "Obligatory" Chunk CID Count 4 bytes t
0x23C Texture Page Entry EIDs 8 x 4 bytes *
0x25C Chunk CIDs 32 x 4 bytes *
0x2DC Zone Spawn Flags 4 bytes *
0x2E0 VRAM Upper Fill Height 4 bytes *
0x2E4 unknown 4 bytes *
0x2E8 Draw distance (affects fog) - note that objects that are not "drawn" thanks to this will still be processed 4 bytes *
0x2EC unknown (affects the way objects are drawn) 4 bytes *
0x2F0 unknown 4 bytes *
0x2F4 unknown 4 bytes *
0x2F8 unknown 4 bytes *
0x2FC Zone Flags 4 bytes *
0x300 Max Death Height? Max Water Height? 4 bytes *
0x304 Music entry reference 4 bytes *
0x308 unknown 4 bytes *
0x30C VRAM Fill Color 4 bytes *
0x310 VRAM Clear Color 4 bytes *
0x313 unused 1 byte *
0x314 unknown 4 bytes *
0x318 Object Light Source Matrix L11 2 bytes *
0x31A Object Light Source Matrix L12 2 bytes *
0x31C Object Light Source Matrix L13 2 bytes *
0x31E Object Light Source Matrix L21 2 bytes *
0x320 Object Light Source Matrix L22 2 bytes *
0x322 Object Light Source Matrix L23 2 bytes *
0x324 Object Light Source Matrix L31 2 bytes *
0x326 Object Light Source Matrix L32 2 bytes *
0x328 Object Light Source Matrix L33 2 bytes *
0x32A Object Background Color R 2 bytes *
0x32C Object Background Color G 2 bytes *
0x32E Object Background Color B 2 bytes *
0x330 Object Light Color Matrix LR1 2 bytes *
0x332 Object Light Color Matrix LR2 2 bytes *
0x334 Object Light Color Matrix LR3 2 bytes *
0x336 Object Light Color Matrix LG1 2 bytes *
0x338 Object Light Color Matrix LG2 2 bytes *
0x33A Object Light Color Matrix LG3 2 bytes *
0x33C Object Light Color Matrix LB1 2 bytes *
0x33E Object Light Color Matrix LB2 2 bytes *
0x340 Object Light Color Matrix LB3 2 bytes *
0x342 Object Background Color Intensity R 2 bytes *
0x344 Object Background Color Intensity G 2 bytes *
0x346 Object Background Color Intensity B 2 bytes *
0x348 Player Light Source Matrix L11 2 bytes *
0x34A Player Light Source Matrix L12 2 bytes *
0x34C Player Light Source Matrix L13 2 bytes *
0x34E Player Light Source Matrix L21 2 bytes *
0x350 Player Light Source Matrix L22 2 bytes *
0x352 Player Light Source Matrix L23 2 bytes *
0x354 Player Light Source Matrix L31 2 bytes *
0x356 Player Light Source Matrix L32 2 bytes *
0x358 Player Light Source Matrix L33 2 bytes *
0x35A Player Background Color R 2 bytes *
0x35C Player Background Color G 2 bytes *
0x35E Player Background Color B 2 bytes *
0x360 Player Light Color Matrix LR1 2 bytes *
0x362 Player Light Color Matrix LR2 2 bytes *
0x364 Player Light Color Matrix LR3 2 bytes *
0x366 Player Light Color Matrix LG1 2 bytes *
0x368 Player Light Color Matrix LG2 2 bytes *
0x36A Player Light Color Matrix LG3 2 bytes *
0x36C Player Light Color Matrix LB1 2 bytes *
0x36E Player Light Color Matrix LB2 2 bytes *
0x370 Player Light Color Matrix LB3 2 bytes *
0x372 Player Background Color Intensity R 2 bytes *
0x374 Player Background Color Intensity G 2 bytes *
0x376 Player Background Color Intensity B 2 bytes *

Prototype Header

Unplayably old versions of Crash 1 (circa 1995) have a slightly different format for this item.

Offset Field Size Value
0x0 World Count 4 bytes w
0x4 Reserved for World Models 8 x 0x40 bytes *
0x204 Index of First Camera Path Item 4 bytes h
0x208 Camera Path Count 4 bytes c
0x20C Entity Count 4 bytes e
0x210 Neighbor Zone Count 4 bytes n
0x214 Neighbor Zone EIDs 5 x 4 bytes *
0x228 Texture Page Entry Count 4 bytes p
0x22C "Obligatory" Chunk CID Count 4 bytes t
0x230 Texture Page Entry EIDs 8 x 4 bytes *
0x250 Chunk CIDs 32 x 4 bytes *
0x2D0 Zone Spawn Flags 4 bytes *
0x2D4 VRAM Fill Height for clearing draw buffer 4 bytes
0x2D8 unknown 4 bytes *
0x2DC unknown 4 bytes *
0x2E0 unknown 4 bytes *
0x2E4 unknown 4 bytes *
0x2E8 unknown 4 bytes *
0x2EC Object Light Source Matrix L11 2 bytes *
0x2EE Object Light Source Matrix L12 2 bytes *
0x2F0 Object Light Source Matrix L13 2 bytes *
0x2F2 Object Light Source Matrix L21 2 bytes *
0x2F4 Object Light Source Matrix L22 2 bytes *
0x2F6 Object Light Source Matrix L23 2 bytes *
0x2F8 Object Light Source Matrix L31 2 bytes *
0x2FA Object Light Source Matrix L32 2 bytes *
0x2FC Object Light Source Matrix L33 2 bytes *
0x2FE Object Background Color R 2 bytes *
0x300 Object Background Color G 2 bytes *
0x302 Object Background Color B 2 bytes *
0x304 Object Light Color Matrix LR1 2 bytes *
0x306 Object Light Color Matrix LR2 2 bytes *
0x308 Object Light Color Matrix LR3 2 bytes *
0x30A Object Light Color Matrix LG1 2 bytes *
0x30C Object Light Color Matrix LG2 2 bytes *
0x30E Object Light Color Matrix LG3 2 bytes *
0x310 Object Light Color Matrix LB1 2 bytes *
0x312 Object Light Color Matrix LB2 2 bytes *
0x314 Object Light Color Matrix LB3 2 bytes *
0x316 Object Background Color Intensity R 2 bytes *
0x318 Object Background Color Intensity G 2 bytes *
0x31A Object Background Color Intensity B 2 bytes *
0x31C Player Light Source Matrix L11 2 bytes *
0x31E Player Light Source Matrix L12 2 bytes *
0x320 Player Light Source Matrix L13 2 bytes *
0x322 Player Light Source Matrix L21 2 bytes *
0x324 Player Light Source Matrix L22 2 bytes *
0x326 Player Light Source Matrix L23 2 bytes *
0x328 Player Light Source Matrix L31 2 bytes *
0x32A Player Light Source Matrix L32 2 bytes *
0x32C Player Light Source Matrix L33 2 bytes *
0x32E Player Background Color R 2 bytes *
0x330 Player Background Color G 2 bytes *
0x332 Player Background Color B 2 bytes *
0x334 Player Light Color Matrix LR1 2 bytes *
0x336 Player Light Color Matrix LR2 2 bytes *
0x338 Player Light Color Matrix LR3 2 bytes *
0x33A Player Light Color Matrix LG1 2 bytes *
0x33C Player Light Color Matrix LG2 2 bytes *
0x33E Player Light Color Matrix LG3 2 bytes *
0x340 Player Light Color Matrix LB1 2 bytes *
0x342 Player Light Color Matrix LB2 2 bytes *
0x344 Player Light Color Matrix LB3 2 bytes *
0x346 Player Background Color Intensity R 2 bytes *
0x348 Player Background Color Intensity G 2 bytes *
0x34A Player Background Color Intensity B 2 bytes *

Item 2: Dimensions/Collision Octree

Offset Field Size Value
0x0 Zone Location X 4 bytes *
0x4 Zone Location Y 4 bytes *
0x8 Zone Location Z 4 bytes *
0xC Zone Width 4 bytes *
0x10 Zone Height 4 bytes *
0x14 Zone Depth 4 bytes *
0x18 unknown 4 bytes *
Collision Octree
0x1C Root Node Index 2 bytes *
0x1E Maximum Depth X 2 bytes *
0x20 Maximum Depth Y 2 bytes *
0x22 Maximum Depth Z 2 bytes *
0x24 Octree Nodes * x 2 bytes *

Item 3+n: Camera Path

Offset Field Size Value
0x0 [Polygon] Sort List EID 4 bytes *
0x4 Reserved for pointer to parent zone (entry) 4 bytes garbage?
0x8 Neighboring Path Count 4 bytes *
0xC Neighboring Paths 4 x 4 x 1 byte *
Neighbor Path Structure d
0xC + (d x 4) +0x0 Relation [to this path] 1 byte *
0xC + (d x 4) +0x1 Parent Zone Index [in neighbor zone list] 1 byte *
0xC + (d x 4) +0x2 Path Item Index 1 byte *
0xC + (d x 4) +0x3 Relation to Goal/Misc Flag 1 byte *
end
0x1C Rel. Index of Entry Point [furthest from goal] 1 byte *
0x1D Rel. Index of Exit Point [closest to goal] 1 byte *
0x1E Path Length/Point Count 2 bytes L
0x20 Camera Mode 2 bytes *
0x22 Direction Scale 2 bytes *
0x24 Camera Z Zoom/Y Pan Factor 2 bytes *
0x26 unknown 2 bytes *
0x28 unknown 2 bytes *
0x2A unknown 2 bytes *
0x2C Path Direction X 2 bytes *
0x2E Path Direction Y 2 bytes *
0x30 Path Direction Z 2 bytes *
0x32 Camera Path Points L x 12 bytes *
Camera Path Point Structure p (*point/trans location relative to parent zone location)
0x32 + (p x 12) + 0x0 Point X/Camera Trans X 2 bytes *
0x32 + (p x 12) + 0x2 Point Y/Camera Trans Y 2 bytes *
0x32 + (p x 12) + 0x4 Point Z/Camera Trans Z 2 bytes *
0x32 + (p x 12) + 0x6 Camera Rotation X 2 bytes *
0x32 + (p x 12) + 0x8 Camera Rotation Y 2 bytes *
0x32 + (p x 12) + 0xA Camera Rotation Z 2 bytes *

Item 3+c+n: Entity

Offset Field Size Value
0x0 Reserved for pointer to parent zone (entry) 4 bytes garbage?
0x4 Spawn Configuration Flags 2 bytes *
0x6 Object Process Type 2 bytes *
0x8 ID 2 bytes *
0xA Path Point Count 2 bytes L
0xC Mode Flags A (or initial Y rot) 2 bytes *
0xE Mode Flags B (or initial X rot) 2 bytes *
0x10 Mode Flags C (or initial Z rot) 2 bytes *
0x12 Object Type 1 byte *
0x13 Object Subtype 1 byte *
0x14 Object Path Points L x 6 bytes *
Object Path Point Structure p
0x14 + (p x 6) + 0x0 Point X 2 bytes *
0x14 + (p x 6) + 0x2 Point Y 2 bytes *
0x14 + (p x 6) + 0x4 Point Z 2 bytes *
end
0x14 + (L x 6) unknown? 2 bytes if L = 1, otherwise 4 0x0

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:

Parent Depth Condition Children Group [format/arrangement] A B C D E F G H
(d < min) && max AA AA BB BB CC CC DD DD EE EE FF FF GG GG HH HH ULF ULB DLF DLB URF URB DRF DRB
cond = (d >= min && d < min2 && min != min2)
cond && min == maxx AA AA BB BB CC CC DD DD UL UR DL DR n/a n/a n/a n/a
cond && min == maxy AA AA BB BB CC CC DD DD LF LB RF RB n/a n/a n/a n/a
cond && min == maxz AA AA BB BB CC CC DD DD UF UB DF DB n/a n/a n/a n/a
cond = (d >= min2 && (min != min2 || min2 != max)) [|| (d >= min && (min == min2 || min2 == max)) ]
cond && min2 == maxx AA AA BB BB L R n/a n/a n/a n/a n/a n/a
cond && min2 == maxy AA AA BB BB top bot n/a n/a n/a n/a n/a n/a
cond && min2 == maxz AA AA BB BB F B n/a n/a n/a n/a n/a n/a
  • 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:

Type Description
0 Solid and Interactive
1 Solid Floor/Ground
2 Level Boundary Wall
3 Pit Area
4 Trigger Misc Death on Collision
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:

Subtype Description Event
0 ? ?
1 ? ?
2 Spin, Fall Over, and Die (death sequence) 0x700
3 ? 0xC00
4 Drown 0x2100
5 Burn to Ash 0x1F00
6 Explode 0x1E00
7 ? 0xD00
8 ? 0x1200
9 ? 0x1200
10 ? 0x1200
11 ? 0x1200
12 Fall in a Hole and Die 0x900
13 ? 0x2300

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 nth 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=1st/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).