Home / Scene format
Scene format
Exhaustive reference for the JSON schema read by
SceneParser. Every key documented here comes straight from the parser
(srcs/core/scene/SceneParser.cpp) : nothing is invented. Keys not listed on
this page are silently ignored.
File structure
A scene is a .json file (the extension is checked : any other suffix throws
INVALID_FILE_EXTENSION). The root document is an object that may contain four
sections :
| Section | Type | Required? | Purpose |
|---|---|---|---|
camera | object | required | Viewpoint and render quality. Missing it throws "Missing camera section". |
objects | array | required | Primitives, lights and groups. Missing it throws "Missing objects section". |
environment | object | optional | Global lighting coefficients. |
materials | array | optional | Library of materials referenced by name. |
The parser only reads keys it knows about. Any unknown root
key (for example a document-level name or description field, or any
metadata) is simply ignored, with no warning.
{
"environment": { "ambient": 0.4, "diffuse": 0.6 },
"camera": { "resolution": [1920, 1080], "position": [0,-100,20], "rotation": [0,0,0], "fieldOfView": 72.0 },
"objects": [ { "type": "sphere", "position": [60,5,40], "radius": 25 } ],
"materials": [ { "name": "Red", "model": "phong", "base_color": [255,64,64] } ]
}
The environment section
Optional. Controls the global lighting coefficients. Both keys must be numbers ; any non-numeric value is ignored and the default is kept.
| Key | Type | Default | Purpose |
|---|---|---|---|
ambient | number | 0.4 | Global ambient light coefficient. |
diffuse | number | 0.6 | Global diffuse contribution coefficient. |
The camera section
Required. Parsed by parseCamera. Four keys are required ;
their absence (or an invalid shape) throws an exception that aborts scene loading.
| Key | Type | Required? | Purpose / error if missing |
|---|---|---|---|
resolution | [width, height] (2 numbers) | required | Image dimensions in pixels. Missing : "Missing camera resolution". Wrong shape : "Camera resolution must be [width, height]". |
position | [x, y, z] | required | Camera position in world space. Missing : "Missing camera position". |
rotation | [x, y, z] in degrees | required | Euler orientation. Missing : "Missing camera rotation". |
fieldOfView | number | required | Field of view (degrees). Missing : "Missing camera fov". |
samplesPerPixel | integer > 0 | optional | Samples per pixel (anti-aliasing). Default : 5. A value ≤ 0 throws "camera samplesPerPixel must be greater than 0". |
samples_per_pixel | integer > 0 | alias | snake_case alias of samplesPerPixel, used only when samplesPerPixel is absent. |
"camera": {
"resolution": [1920, 1080],
"position": [0.0, -100.0, 20.0],
"rotation": [0.0, 0.0, 0.0],
"fieldOfView": 72.0,
"samplesPerPixel": 128
}
The objects section
Required : an array (otherwise "objects must be a list"). Each
element is an object with a type key (string, required) that
selects the primitive, light or group to build. General shape of an object :
{
"type": "sphere", // required — selects the object type
"name": "My sphere", // optional — label shown in the interface
"position": [60, 5, 40], // type-specific properties (see table below)
"radius": 25,
"material": "Red" // optional — name of a "materials" entry
}
The parser applies a handler table : for each object it walks the known
keys and only assigns those present. A key not listed for that type (or entirely unknown) is
ignored. If a present key has a malformed value, the object is dropped (error
on stderr) but the rest of the scene keeps loading.
Unlike camera, an invalid object does not abort loading : the
error is written to standard error and the object is simply skipped. Only missing
camera/objects sections stop the parser.
Object types and recognized keys
Accepted values for type and keys read by the parser for each. The keys
position, rotation, scale, name and
material are accepted generically ; the columns below list the
specific keys each type actually uses.
type | Type-specific keys | Notes |
|---|---|---|
sphere | position, radius, scale | Sphere centered on position. |
plane | axis ("x"/"y"/"z"), position, size | Axis-aligned plane. See the warning below. |
cube | position, rotation, scale, size | Cube with edge size. |
cylinder | position, rotation, radius, height | Cylinder. |
cone | position, rotation, radius, height | Cone. |
triangle | vertex0, vertex1, vertex2 | Three [x,y,z] vertices. |
torus | position, rotation, radius, height | Torus ; height acts as the tube radius. |
tanglecube | position, rotation, size, threshold | Implicit surface (isovalue threshold). |
fractal | position, size, power, iterations | Fractal (Mandelbulb-style). |
mesh | file (.obj) or vertices / faces / normals, position, rotation, scale, vertex_overrides | Mesh loaded from a file or defined inline. |
point_light | position, color, intensity | Point light. |
directional_light | direction, color, intensity | Directional light. |
group | name, position, rotation, scale, children | Hierarchical container ; children is an array of nested objects. |
A plane is defined by axis, never by
normal/origin. The axis key expects the string
"x", "y" or "z" (any other value throws
"Unknown axis"). Keys such as normal or origin are
ignored : a plane defined that way falls back to its default axis. Use
position (not origin) to offset it along the axis.
Additional generic keys recognized by the handler table : direction,
power, threshold, intensity, iterations,
vertices, faces, normals, vertex_overrides.
Each vertex_overrides entry is an object
{ "index": n, "position": [x,y,z] } ; an entry without index or
position throws an error.
There is also an obj type (distinct from mesh) that
imports a .obj directly via the path key (required) and accepts
position, rotation, size. It produces a list of triangles
rather than a single mesh primitive.
Value conventions
| Concept | Shape | Detail |
|---|---|---|
| Vector | [x, y, z] | Array of 3 numbers. Used for position, scale, direction, vertices… A wrong length throws "expected an array of 3 numbers [x, y, z]". |
| Rotation | [x, y, z] | Euler angles in degrees. |
| Color | [r, g, b] | Three integer components between 0 and 255. Alpha is fixed at 255. Wrong length : "expected an array of 3 numbers [r, g, b]". |
| Resolution | [width, height] | Two integer numbers. |
The materials section and referencing by name
Optional : an array of materials (otherwise "materials must be a list"). Each entry
must have a name (without it : "Missing material name") and usually a
model ("phong" or "pbr"). An object references a material
through its material key, which must match exactly the
name of a materials entry.
If an object's material value matches no loaded material, the
parser throws "Unknown material "…"" and that object is dropped.
For the full list of material fields (base_color,
metallic, roughness, transmission, texture and normal
maps, etc.), see the Materials page. Note : the model is
read from model and not type ; a type
key on a material is ignored and the model falls back to phong.
Full commented example
Faithful excerpt from tests/configs/subject.json (two spheres, a plane and a light) :
{
"environment": { "ambient": 0.4, "diffuse": 0.6 },
"camera": {
"resolution": [1920, 1080], // width x height in pixels (required)
"position": [0.0, -100.0, 20.0],
"rotation": [0.0, 0.0, 0.0], // degrees (required)
"fieldOfView": 72.0, // degrees (required)
"samplesPerPixel": 128 // anti-aliasing (default 5)
},
"objects": [
{
"name": "Sphere A",
"type": "sphere",
"position": [60.0, 5.0, 40.0],
"radius": 25,
"material": "Material A" // reference by name
},
{
"name": "Plane",
"type": "plane",
"axis": "z", // "x" | "y" | "z" — NOT "normal"/"origin"
"position": [0.0, 0.0, -20.0],
"material": "Material C"
},
{
"name": "Point light",
"type": "point_light",
"intensity": 1000000.0,
"position": [400.0, 100.0, 500.0]
}
],
"materials": [
// The model is read from "model" (phong | pbr) ; "base_color" in [r,g,b] 0-255.
{ "name": "Material A", "model": "phong", "base_color": [255, 64, 64] },
{ "name": "Material C", "model": "phong", "base_color": [64, 64, 255] }
]
}
Parser error messages
Fatal errors abort loading (a LoadingSceneException).
Per-object errors are written to stderr and the offending object
is simply skipped.
| Message | Scope | Cause |
|---|---|---|
Missing camera section | fatal | No camera key at the root. |
Missing objects section | fatal | No objects key at the root. |
Missing camera resolution | fatal | camera.resolution absent. |
Camera resolution must be [width, height] | fatal | resolution is not an array of 2 numbers. |
Missing camera position | fatal | camera.position absent. |
Missing camera rotation | fatal | camera.rotation absent. |
Missing camera fov | fatal | camera.fieldOfView absent. |
camera samplesPerPixel must be greater than 0 | fatal | samplesPerPixel ≤ 0. |
objects must be a list | fatal | objects is not an array. |
materials must be a list | fatal | materials is not an array. |
Missing material name | fatal | A materials entry has no name. |
Missing object type | per object | Object without a type key (or non-string type) : object skipped. |
object "<type>": Unknown or incomplete object definition | per object | Unknown type or insufficient properties to build the object. |
object "<type>" <key>: … | per object | A property is malformed (e.g. non-numeric radius). |
Unknown material "<name>" | per object | material matches no loaded material. |
Unknown axis "<value>" | per object | axis outside "x"/"y"/"z". |
Missing object path | per object | obj type without a path key. |