Creating Levels
Creating a level for Hallways is simple. A level is just a collection of files hosted on the internet, tied together by a central manifest.
Manifest
Here is an example manifest:
{
"_version": "coco",
"model": "model.glb",
"collider": "collision.glb",
"material": {
"MyMaterial": {
"frames": ["texture1.png", "texture2.png"],
"animation_speed": 1.0,
"color": [255, 255, 255, 255],
"texture_addressing": "Linear"
}
},
"portal": {
"portal_a": {
"collider": "portal_a.glb",
"target": { "href": "other_level.json", "name": "portal_b" }
}
}
}Manifest Fields
| Field | Status | Use |
|---|---|---|
| _version | required | Manifest version. Must be "coco". |
| model | required | Level render model (.glb). |
| collider | optional | Separate collision model (.glb). If omitted, model is used for collision. |
| spawn | optional | Player spawn position [x, y, z]. Defaults to origin. |
| track | optional | Background music file. Must be an Ogg container with Vorbis audio. |
| material | required | Material map keyed by glTF material name. |
| portal | required | Portal map. May be empty, but cannot contain more than 4 entries. |
| portal.<name>.collider | required | Portal collider (.glb). |
| portal.<name>.target | optional | Destination object with href and name. |
Materials
Each material entry is keyed by a glTF material name from the level model. Every material referenced by the model should have a matching entry.
{
"frames": ["frame1.png", "frame2.png"],
"animation_speed": 1.0,
"color": [255, 255, 255, 255],
"texture_addressing": "Linear"
}- frames defaults to an empty list.
- animation_speed defaults to 0.5.
- color defaults to white.
- texture_addressing is Linear or Nearest and defaults to Linear.
- Diffuse alpha is evaluated after texture and color tinting, so both the texture alpha and color alpha can affect the final result.
- A final diffuse alpha of 0.0 is discarded entirely, which is useful for cut-out holes and masks.
- A final diffuse alpha of 1.0 is rendered as opaque geometry.
- A final diffuse alpha between 0.0 and 1.0 is rendered as transparent geometry with OIT.
Texture Limits
Texture dimensions must match one of these sizes. The max column is the maximum number of textures at that size per level.
| Size | Max |
|---|---|
| 2048x2048 | 1 |
| 1024x1024 | 4 |
| 512x512 | 8 |
| 256x256 | 32 |
| 128x128 | 64 |
| 64x64 | 256 |
Portals
- Portal geometry can be any coplanar polygon.
- Portals must be Horizontal wall-aligned surfaces or Vertical floor/ceiling-aligned surfaces.
- Vertical portals need one magenta vertex (#FF00FFFF) so player rotation can be derived.
- target.href is a relative URL to the destination manifest.
- target.name is the destination portal name in that manifest.
- Horizontal portals only link to horizontal portals.
- Vertical portals only link to vertical portals, and their normals must match.
- Linked portals should have the same polygon shape.
Tips
- Keep vertex counts low.
- Vertices that should meet must share the exact same position.
- Keep open space on both sides of every portal.
- Use a separate collider mesh for complex scenes so visual detail does not all become collision geometry.
- Host levels on any static file host. GitHub Pages is a good place to start.