Naming Convention Redesign
Status: Draft
Rationale
The current ɴsɪ attribute names grew organically and suffer from several inconsistencies that make the API harder to learn and use than it needs to be.
No word separation. Most multi-word names are run together, forcing users to mentally parse where words begin and end — and the conventions are unpredictable:
| Name | Intended meaning |
|---|---|
numberofthreads | number of threads |
texturememory | texture memory |
renderatlowpriority | render at low priority |
clockwisewinding | clockwise winding |
importancesamplefilter | importance sample filter |
unitlengthmillimeters | unit length millimeters |
Inconsistent grouping. Some attributes use dot-separated groups, others don’t — even for closely related settings:
| Grouped | Not grouped |
|---|---|
subdivision.cornervertices | clockwisewinding |
subdivision.creasesharpness | outlinecreasethreshold |
visibility.camera | surfaceshader |
quality.shadingsamples | texturememory |
show.displacement | renderatlowpriority |
Cryptic abbreviations alongside verbose names. Single-letter names coexist with long compound words:
| Terse | Verbose |
|---|---|
P | transformationmatrices |
N | emissionintensitygrid |
fov | quality.samplevolumeemission |
id | stoppedcallbackdata |
Node type names baked into attributes. Some attributes redundantly include the node type, others don’t:
| Redundant | Clean |
|---|---|
shaderfilename (on shader node) | filter (on outputlayer node) |
shaderobject (on shader node) | angle (on environment node) |
vdbfilename (on volume node) | width (on particles node) |
imagefilename (on outputdriver node) | basis (on curves node) |
This document proposes a systematic naming convention that resolves these inconsistencies. The complete mapping from current to proposed names is in the attribute mapping below.
Why Separate Words at All?
Concatenated names like maximumraylength or importancesamplefilter are hard to read — especially for non-native English speakers, who may not immediately see where one word ends and the next begins. Word separators make attribute names accessible to a wider audience without any downside: attribute name strings are interned by the renderer, so separators have zero runtime cost. They add a few bytes to the source but nothing to render time.
A common objection is that separators mean more typing. In practice this matters less than it used to: code is increasingly written with AI assistance and autocompletion, so keystroke count is a non-issue. What matters is how easily a human can read and review the code — and depth-of-field.focal-length is unambiguously clearer than depthoffield.focallength.
Redesign Proposal
Hyphenate Multi-Word Attributes
Attribute names use hyphens (-) as word separators, not underscores (_). This is a deliberate choice: almost no programming language allows hyphens in identifiers (variable-name is invalid in C, C++, Python, Rust, Lua, etc.), so attribute name strings are instantly distinguishable from code identifiers in any language. When you see reflection.ray-depth-max in source code, it can only be an attribute name — never a variable, function, or type.
Core Convention
.(dots) separate hierarchy levels — these correspond to what would be groups/rollouts/sections in UI/attribute editor.-(hyphens) separate words within a single label.- Singular nouns when used as modifiers in compound names (English compound noun rule).
- Example:
point-gridnotpoints-grid— “point” modifies “grid”.
- Example:
- Plain English over jargon (governing principle — R9).
- Example
field-of-viewnotfov.
- Example
- Compound node type names also use hyphens:
vdb-particles,output-driver,output-layer,face-set,perspective-camera,fisheye-camera, etc. - Example:
subdivision.corner-sharpness— group “Subdivision”, label “Corner Sharpness”.
Rulings
R1: Type-first grouping for ray settings
Ray depth/length settings on the global node are grouped by ray type, since each type has multiple related attributes (depth + length):
reflection.ray-depth-max
reflection.ray-length-max
diffuse.ray-depth-max
diffuse.ray-length-max
R2: 2+ related attributes required to form a dot-group
Only use dot-separated hierarchy when there are 2 or more related attributes that form a logical group. Single standalone attributes use flat hyphenated naming:
Groups (dot-separated):
subdivision.scheme
subdivision.corner-index
subdivision.corner-sharpness
visibility.camera
visibility.diffuse
visibility.reflection
Flat (hyphen-separated):
vertex-count
hole-count
clockwise
reference-time
quadratic-motion
R3: The grouping level is context-dependent, not concept-fixed
The same concept (e.g., “reflection”) can be a group in one context and a leaf in another. The rule is: whichever level has 2+ siblings becomes the group.
On the global node — each ray type has 2+ settings (depth + length), so the ray type is the group:
reflection.ray-depth-max
reflection.ray-length-max
On the attributes node — each ray type has only ONE visibility flag, but “visibility” has 8+ flags, so visibility is the group:
visibility.reflection
visibility.diffuse
visibility.camera
The alternative (type-first everywhere: reflection.visibility, diffuse.visibility, etc.) would create 8 singleton groups, violating R2. The 2+ rule takes precedence over concept consistency.
R4: Node type is an implicit top-level group
The node type itself provides context, so attribute names should not redundantly include the node type. On a curves node, the attribute is basis, not curve-basis. On a particles node, the attribute is id, not particle-id.
R5: Rename everything, including legacy single-letter names
No grandfather clause for industry-standard abbreviations:
P→positionN→normalnvertices→vertex-countnholes→hole-count
Single-word names that are already clear stay as-is: width, basis, id, matte, clockwise.
R6: Hyphen-separate compound domain terms
No concatenated words. All multi-word terms get hyphens:
depthoffield→depth-of-fieldfstop→focal-stopfocallength→focal-lengthfocaldistance→focal-distance
This applies within both group names and leaf labels:
depth-of-field.enable
depth-of-field.focal-stop
depth-of-field.focal-length
depth-of-field.aperture.enable ← sub-group (3 attrs: enable, sides, angle)
depth-of-field.aperture.sides
depth-of-field.aperture.angle
R7: Connection attribute plurality matches cardinality
If a connection attribute accepts multiple connections, use plural. If it accepts only one, use singular.
Plural (multi-connection):
objects (root, transform — multiple geometry nodes)
attributes (root, transform — multiple attribute nodes)
members (set — multiple objects)
screens (camera — multiple screen nodes)
output-layers (screen — multiple layer nodes)
output-drivers (output-layer — multiple driver nodes)
Singular (single-connection):
shader.surface (attributes — one surface shader)
shader.displacement (attributes — one displacement shader)
shader.volume (attributes — one volume shader)
background-layer (output-layer — one background layer)
R8: Group by concern, not by concept
Attributes are grouped by what kind of setting they are, not by what rendering concept they relate to. This keeps groups semantically coherent:
quality.*= how much effort the renderer spends (sampling counts, performance)shading.*= which shading features are enabled/disabled (feature toggles){type}.*= per-ray-type limits (depth, length)
quality.shading-samples ← sampling effort
quality.volume-samples ← sampling effort
quality.denoise ← quality toggle
quality.volume-emission-sampling ← quality toggle
quality.preview.global-update ← preview/IPR quality
quality.preview.interpolate ← preview/IPR quality
quality.preview.speed-multiplier ← preview/IPR quality
shading.displacement ← feature toggle
shading.atmosphere ← feature toggle
shading.multiple-scattering ← feature toggle
shading.osl-subsurface ← feature toggle
volume.ray-depth-max ← ray limit
volume.ray-length-max ← ray limit
This avoids scattering quality-related attrs across concept groups (which would make it hard to find “all the knobs that affect render speed”).
R9: Plain English over jargon (governing principle)
This is a governing principle that applies across all naming decisions. When choosing between a technical abbreviation/jargon term and a plain English equivalent, always prefer plain English. Names should be understandable without domain-specific knowledge.
ipr→preview(Interactive Progressive Rendering → just “preview”)fov→field-of-viewfstop→focal-stop(kept because it’s the actual name of the unit, not jargon)
The group quality.ipr.* becomes quality.preview.*:
quality.preview.global-update
quality.preview.interpolate
quality.preview.speed-multiplier
R10: Use .enable suffix for booleans in mixed groups
When a boolean on/off attribute belongs to a group that also has non-boolean attrs, append .enable to distinguish the toggle from the group:
depth-of-field.enable ← mixed group (has focal-stop, focal-length, etc.)
depth-of-field.focal-stop
depth-of-field.focal-length
cryptomatte.enable ← mixed group (has level)
cryptomatte.level
When the group is all-toggles or the boolean is standalone, no .enable needed:
shading.displacement ← all-toggle group, obviously a toggle
shading.atmosphere
quality.denoise ← obviously a toggle from context
R11: Unify callbacks under callback.* group
All callback/handler function pointers across the API follow a consistent pattern: callback.{purpose} for the function pointer and callback.{purpose}.data for the associated userdata.
This applies across different API calls — the callback group is a cross-cutting convention:
# NSIBegin
callback.error ← error handler function (was: errorhandler)
callback.error.data ← error handler userdata (was: errorhandler.data)
# NSIRenderControl
callback.stop ← stopped callback function (was: stoppedcallback)
callback.stop.data ← stopped callback userdata (was: stoppedcallbackdata)
R12: Singular nouns as modifiers in compound names
When a noun serves as a modifier (adjective) in a compound name, use its singular form. This follows standard English compound noun formation: “dog house” not “dogs house”, “vertex count” not “vertices count”.
vertex-count ✓ (not vertices-count)
hole-count ✓ (not holes-count)
face-index ✓ (not faces-index)
point-grid ✓ (not points-grid)
object-index ✓ (not objects-index)
Plurals are reserved for R7 (connection cardinality), where the attribute name IS the thing, not a modifier:
objects ✓ (the attribute is multiple objects, not a modifier)
members ✓
output-layers ✓
Open Question: Node Granularity
The convention above renames attributes consistently, but it doesn’t resolve a deeper inconsistency in how ɴsɪ models primitives. Three different patterns are in play across the existing node types:
| Primitive | Pattern | Examples |
|---|---|---|
| Meshes | One node, type attribute | mesh (polygons and Catmull-Clark via subdivision.scheme) |
| Volumes | One node, but only one backend | volume (renders OpenVDB exclusively) |
| Particles | Split by backend | particles, vdbparticles |
| Cameras | Split by projection | perspectivecamera, fisheyecamera, cylindricalcamera, sphericalcamera, orthographiccamera |
mesh collapses polygons and subdivision surfaces behind a subdivision.scheme attribute. Cameras do the opposite — five separate node types that differ only in their projection function. Volumes name themselves generically while only one backend is implemented. Particles are split by the data format their control points hold, not by what the renderer sees.
Three coherent resolutions, from least to most invasive:
Option 1 — Honest names, same shape
Keep one node per concern and rename for honesty. The mapping later in this document already adopts these names:
volume→vdb-volume(it only renders OpenVDB).vdbparticles→vdb-particles(hyphenated).- Cameras keep their five hyphenated names (
perspective-camera, …). meshstays as the one merged exception.
The inconsistency with mesh remains. This is a pure rename — no API change.
Option 2 — Collapse to one canonical primitive
Bring volumes, particles, and cameras in line with mesh’s “one node, type attribute” pattern:
vdb-volumeandvdb-particlescollapse into a singlevdbnode withkind = "volume" | "particles"(or distinguished by which data attribute is supplied).- The five camera nodes collapse into one
cameranode withprojection = "perspective" | "fisheye" | "cylindrical" | "spherical" | "orthographic". Projection-specific attributes live behind the projection’s prefix (e.g.fisheye.mapping).
Every scene-graph entity ends up with a single canonical primitive. Migration is “rename node type, add a kind / projection attribute”. The renderer’s dispatch table has to flatten, but no user-side attribute is lost.
Option 3 — Split mesh to match the rest
Adopt the honest renames from Option 1 — volume → vdb-volume, vdbparticles → vdb-particles — and additionally replace mesh with polygon-mesh and subdivision-mesh. Each mesh node carries only the attributes meaningful for its surface kind; subdivision.scheme disappears entirely.
This is the most invasive option: every existing scene using subdivision surfaces has to re-target the new node, and the subdivision.* attributes migrate from prefix-grouped on mesh to top-level on subdivision-mesh.
Trade-offs
- Option 1 is cheapest to deliver; it preserves the inconsistency under prettier names.
- Option 2 matches the mesh pattern. Requires backend dispatch work but no user-facing data loss.
- Option 3 is the cleanest in isolation but invalidates the largest existing-asset footprint.
No recommendation in this draft. The decision belongs in the API roadmap, not in a renaming pass.
Open Question: ᴏsʟ Built-In Variable Alignment
ɴsɪ is designed to feed ᴏsʟ shaders. When the renderer puts the control-point position into an attribute named P on a mesh node, an ᴏsʟ shader reads it as the built-in global variable P without any plumbing in between. That 1:1 mapping is part of what makes ᴏsʟ shaders portable across renderers, and it directly conflicts with R5.
R5 currently renames the legacy single-letter attribute names:
| Current | R5 proposal | ᴏsʟ built-in |
|---|---|---|
P | position | point P |
N | normal | normal N |
Adopting R5 as written means the attribute name and the ᴏsʟ global diverge. The renderer either has to translate position → P at the ᴏsʟ binding step — hidden machinery that surprises anyone debugging by attribute name — or the cross-renderer ᴏsʟ contract has to break for ɴsɪ specifically.
The ᴏsʟ globals that overlap with current ɴsɪ attribute names are: P, N, Ng, u, v, dPdu, dPdv, I.
Option A — Carve out an exception in R5
Legacy single-letter names that match an ᴏsʟ global stay as-is, even where the surrounding convention would rename them. This preserves the ɴsɪ ↔ ᴏsʟ alignment.
Affected rows revert in the rename mapping:
mesh:Pstays.nurbs:Pstays.Pwstays (semantics flow into the same ᴏsʟ binding).curves:Pstays.particles:Pstays,Nstays.
nvertices, nholes, clockwisewinding etc. still rename — they aren’t ᴏsʟ globals.
Option B — Rename and translate
Adopt R5 as written. The renderer translates position → P (and normal → N, …) when binding attributes to ᴏsʟ shader globals.
This keeps ɴsɪ-level naming uniform but introduces hidden translation. Shader authors writing portable code now read about P in the ᴏsʟ docs and position in the ɴsɪ docs and have to internalise the mapping. Debugging tools that show attribute names won’t match what the shader sees.
Trade-off
The decision turns on which contract matters more:
- ᴏsʟ portability (Option A) — the convention that “the attribute named
Pis what the shader reads asP” is sacred. - ɴsɪ-internal consistency (Option B) — single-letter names are jargon and R5’s reasoning applies uniformly; the ᴏsʟ binding layer can absorb the cost.
No recommendation in this draft.
Complete Attribute Mapping
Every attribute across all node types, with current → new name and the ruling(s) that apply. Attributes where current = new are omitted.
global Node
| Current | New | Rules |
|---|---|---|
numberofthreads | thread-count | R2 (1 attr, flat), R5, R6 |
texturememory | texture-memory | R2 (1 attr, flat), R6 |
networkcache.size | network-cache.size | R6 |
networkcache.directory | network-cache.directory | R6 |
networkcache.mipmap | network-cache.mipmap | R6 |
networkcache.write | network-cache.write | R6 |
renderatlowpriority | low-priority | R6, R9 |
bucketorder | bucket-order | R6 |
hidemessages | messages.hide | R2 (2 message attrs: hide + timestamp) |
maximumraydepth.diffuse | diffuse.ray-depth-max | R1 |
maximumraydepth.hair | hair.ray-depth-max | R1 |
maximumraydepth.reflection | reflection.ray-depth-max | R1 |
maximumraydepth.refraction | refraction.ray-depth-max | R1 |
maximumraydepth.volume | volume.ray-depth-max | R1 |
maximumraylength.diffuse | diffuse.ray-length-max | R1 |
maximumraylength.hair | hair.ray-length-max | R1 |
maximumraylength.reflection | reflection.ray-length-max | R1 |
maximumraylength.refraction | refraction.ray-length-max | R1 |
maximumraylength.specular | specular.ray-length-max | R1 (pattern consistency) |
maximumraylength.volume | volume.ray-length-max | R1 |
quality.denoise | quality.denoise | R8 |
quality.iprglobalupdate | quality.preview.global-update | R8, R9 |
quality.iprinterpolate | quality.preview.interpolate | R8, R9 |
quality.iprspeedmultiplier | quality.preview.speed-multiplier | R8, R9 |
quality.shadingsamples | quality.shading-samples | R8, R6 |
quality.volumesamples | quality.volume-samples | R8, R6 |
quality.samplevolumeemission | quality.volume-emission-sampling | R8, R6 |
referencetime | reference-time | R6 |
show.displacement | shading.displacement | R8 |
show.atmosphere | shading.atmosphere | R8 |
show.multiplescattering | shading.multiple-scattering | R8, R6 |
show.osl.subsurface | shading.osl-subsurface | R8, R6 |
exclusiveshading | exclusive-shading | R6 |
messages.timestamp | messages.timestamp | — |
Unchanged: license.server, license.wait, license.hold, frame, statistics.progress, statistics.filename, verbose
root Node
| Current | New | Rules |
|---|---|---|
geometryattributes | attributes | R6, R7 (multi-conn → plural) |
Unchanged: objects
set Node
Unchanged: members
mesh Node
| Current | New | Rules |
|---|---|---|
P | position | R5 |
nvertices | vertex-count | R5, R6 |
nholes | hole-count | R5, R6 |
clockwisewinding | clockwise | R6 (simplification) |
subdivision.cornervertices | subdivision.corner.index | R2 (3 corner attrs → sub-group) |
subdivision.cornersharpness | subdivision.corner.sharpness | R2 |
subdivision.smoothcreasecorners | subdivision.corner.automatic | R2 |
subdivision.creasevertices | subdivision.crease.index | R2 (2 crease attrs → sub-group) |
subdivision.creasesharpness | subdivision.crease.sharpness | R2 |
referencetime | reference-time | R6 |
quadraticmotion | quadratic-motion | R6 |
outlinecreasethreshold | outline-crease-threshold | R6 |
Unchanged: subdivision.scheme
nurbs Node
The u and v axes each have five related attributes (count, order, knot, min, max), so per R3 each axis becomes a group.
| Current | New | Rules |
|---|---|---|
nu | u.count | R3 (axis group), R5, R6 |
nv | v.count | R3 (axis group), R5, R6 |
uorder | u.order | R3, R6 |
vorder | v.order | R3, R6 |
uknot | u.knot | R3, R6 |
vknot | v.knot | R3, R6 |
umin | u.min | R3, R6 |
umax | u.max | R3, R6 |
vmin | v.min | R3, R6 |
vmax | v.max | R3, R6 |
P | position | R5 |
Pw | weighted-position | R5, R6 (alternative to position) |
trimcurves.nloops | trim-curves.loop-count | R5, R6 |
trimcurves.ncurves | trim-curves.curve-count | R5, R6 |
trimcurves.n | trim-curves.point-count | R5 (n and cv are jargon), R9 |
trimcurves.order | trim-curves.order | R6 (group prefix only) |
trimcurves.knot | trim-curves.knot | R6 |
trimcurves.min | trim-curves.min | R6 |
trimcurves.max | trim-curves.max | R6 |
trimcurves.u, .v | trim-curves.position | API change (consolidation); mirrors surface |
trimcurves.u, .v, .w | trim-curves.weighted-position | API change (consolidation); mirrors surface |
trimcurves.sense | trim-curves.sense | R6 |
Consolidation note (API change, not pure rename). The current API stores trim-curve control points as three parallel arrays (trimcurves.u, trimcurves.v, trimcurves.w) — a structure-of-arrays layout. The surface stores its control points as one interleaved array (P or Pw) — an array-of-structures layout. The redesign aligns the two:
trim-curves.position—float[2], non-rational(u, v)pairs. Replacestrimcurves.uandtrimcurves.v.trim-curves.weighted-position—float[3], rational(u, v, w)triples. Replacestrimcurves.u,trimcurves.v, andtrimcurves.w.
Supply one of the two; never both. This is the same supply-one-of pattern the surface uses for position / weighted-position.
face-set Node
| Current | New | Rules |
|---|---|---|
faces | face-index | R9 (descriptive) |
curves Node
| Current | New | Rules |
|---|---|---|
nvertices | vertex-count | R5, R6 |
P | position | R5 |
Unchanged: width, basis, extrapolate
particles Node
| Current | New | Rules |
|---|---|---|
P | position | R5 |
N | normal | R5 |
reverseorientation | reverse-orientation | R6 |
quadraticmotion | quadratic-motion | R6 |
Unchanged: width, id
procedural Node
| Current | New | Rules |
|---|---|---|
boundingbox | bounding-box | R6 |
environment Node
Unchanged: angle
shader Node
| Current | New | Rules |
|---|---|---|
shaderfilename | filename | R4 (node type provides context) |
shaderobject | object | R4 |
attributes (geometry) Node
| Current | New | Rules |
|---|---|---|
surfaceshader | shader.surface | R2, R7 (single-conn → singular) |
displacementshader | shader.displacement | R2, R7 |
volumeshader | shader.volume | R2, R7 |
visibility.set.subsurface | visibility.subsurface-set | R6 |
regularemission | emission.regular | R2 (2 emission attrs → group) |
quantizedemission | emission.quantized | R2 |
Unchanged: ATTR.priority, visibility.camera, visibility.diffuse, visibility.hair, visibility.reflection, visibility.refraction, visibility.shadow, visibility.specular, visibility.volume, visibility, matte, bounds
transform Node
| Current | New | Rules |
|---|---|---|
transformationmatrix | matrix | R4 |
geometryattributes | attributes | R6, R7 |
shaderattributes | shader-attributes | R6 |
Unchanged: objects
instances Node
| Current | New | Rules |
|---|---|---|
sourcemodels | objects | R7 (multi-conn), R9 |
transformationmatrices | matrices | R4, R6 |
modelindices | object-index | R6, R9 |
disabledinstances | disabled-index | R6 |
output-driver Node
| Current | New | Rules |
|---|---|---|
drivername | driver-name | R6 |
imagefilename | filename | R4 |
embedstatistics | embed-statistics | R6 |
output-layer Node
| Current | New | Rules |
|---|---|---|
variablename | variable-name | R6 |
variablesource | variable-source | R6 |
layername | layer-name | R6 |
scalarformat | scalar-format | R6 |
layertype | layer-type | R6 |
colorprofile | color-profile | R6 |
withalpha | with-alpha | R6 |
sortkey | sort-key | R6 |
lightset | light-set | R6 |
lightsetname | light-set-name | R6 |
outputdrivers | output-drivers | R6, R7 |
filterwidth | filter.width | R2 (2 filter attrs → group) |
filter | filter.name | R2 |
backgroundvalue | background.value | R2 (2 background attrs → group) |
backgroundlayer | background.layer | R2, R7 (single-conn) |
lightdepth | light-depth | R6 |
Unchanged: dithering, cryptomatte.enable, cryptomatte.level
screen Node
| Current | New | Rules |
|---|---|---|
outputlayers | output-layers | R6, R7 |
prioritywindow | priority-window | R6 |
screenwindow | screen-window | R6 |
pixelaspectratio | pixel-aspect-ratio | R6 |
staticsamplingpattern | static-sampling-pattern | R6 |
importancesamplefilter | importance-sample-filter | R6 |
Unchanged: resolution, oversampling, crop, overscan
vdb-particles Node
| Current | New | Rules |
|---|---|---|
vdbfilename | filename | R4 |
pointsgrid | point-grid | R6, R12 |
velocityreferencetime | velocity.reference-time | R2 (2 velocity attrs → group) |
velocityscale | velocity.scale | R2 |
enablepscale | use-point-scale | R9 (plain English) |
widthscale | width-scale | R6 |
Unchanged: width
volume Node
| Current | New | Rules |
|---|---|---|
vdbfilename | filename | R4 |
densitygrid | grid.density | R2 (6 grid attrs → group) |
colorgrid | grid.color | R2 |
emissiongrid | grid.emission | R2 |
emissionintensitygrid | grid.emission-intensity | R2, R6 |
temperaturegrid | grid.temperature | R2 |
velocitygrid | grid.velocity | R2 |
velocityreferencetime | velocity.reference-time | R2 |
velocityscale | velocity.scale | R2 |
Camera Nodes (perspective-camera, fisheye-camera, cylindrical-camera)
Common (all cameras):
| Current | New | Rules |
|---|---|---|
screens | screens | R7 |
shutterrange | shutter.range | R2 (2 shutter attrs → group) |
shutteropening | shutter.opening | R2 |
clippingrange | clipping-range | R6 |
perspective-camera:
| Current | New | Rules |
|---|---|---|
fov | field-of-view | R9 |
depthoffield.enable | depth-of-field.enable | R6, R10 |
depthoffield.fstop | depth-of-field.focal-stop | R6 |
depthoffield.focallength | depth-of-field.focal-length | R6 |
depthoffield.focallengthratio | depth-of-field.focal-length-ratio | R6 |
depthoffield.focaldistance | depth-of-field.focal-distance | R6 |
depthoffield.aperture.enable | depth-of-field.aperture.enable | R6, R10 |
depthoffield.aperture.sides | depth-of-field.aperture.sides | R6 |
depthoffield.aperture.angle | depth-of-field.aperture.angle | R6 |
unitlengthmillimeters | unit-length-millimeters | R6 |
fisheye-camera:
| Current | New | Rules |
|---|---|---|
fov | field-of-view | R9 |
Unchanged: mapping
cylindrical-camera:
| Current | New | Rules |
|---|---|---|
fov | field-of-view.vertical | R2 (2 fov attrs → group), R9 |
horizontalfov | field-of-view.horizontal | R2, R6, R9 |
eyeoffset | eye-offset | R6 |
API Parameter Mapping
NSIBegin
| Current | New | Rules |
|---|---|---|
streamfilename | stream.filename | R2 (4 stream attrs → group) |
streamformat | stream.format | R2 |
streamcompression | stream.compression | R2 |
streampathreplacement | stream.path-replacement | R2, R6 |
separateprocess | separate-process | R6 |
errorhandler | callback.error | R11 (unified callback group) |
errorhandler.data | callback.error.data | R11 |
executeprocedurals | evaluate-replace | R9 |
Unchanged: type
NSIDelete
Unchanged: recursive
NSIConnect
Unchanged: value, priority, strength
NSIEvaluate
| Current | New | Rules |
|---|---|---|
backgroundload | background-load | R6 |
Unchanged: type, filename, script, buffer, size
NSIRenderControl
| Current | New | Rules |
|---|---|---|
stoppedcallback | callback.stop | R11 (unified callback group) |
stoppedcallbackdata | callback.stop.data | R11 |
Unchanged: action, progressive, interactive, frame
Open question — action as a positional argument: Every meaningful NSIRenderControl call needs an action value — one of start, wait, synchronize, suspend, resume, stop. The call is a no-op without it. Yet the current signature carries action inside the optional-parameter bag, peer to the genuinely-optional progressive / interactive / callback parameters.
Promoting action to a required positional argument would make intent visible at the call site:
typedef enum {
NSIRenderStart,
NSIRenderWait,
NSIRenderSynchronize,
NSIRenderSuspend,
NSIRenderResume,
NSIRenderStop,
} NSIRenderAction;
void NSIRenderControl(
NSIContext_t ctx,
NSIRenderAction action,
int nparams,
const NSIParam_t *params);
A string overload can be kept for the Lua and Python bindings, where "start" / "wait" / "stop" read idiomatically. The enum form catches typos at compile time and surfaces the closed set of allowed values to IDE completion.
If adopted, action leaves this rename table entirely — there is nothing left to rename.