Cookbook

The Nodal Scene Interface (NSI) is a simple yet expressive API to describe a scene to a renderer. From geometry declaration, to instancing, to attribute inheritance and shader assignments, everything fits in 12 API calls. The following recipes demonstrate how to achieve most common manipulations.

Geometry Creation

Creating geometry nodes is simple. The content of each node is filled using the NSISetAttribute call.

Geometry Creation
1## Polygonal meshes can be created minimally by specifying "P".
2## NSI's C++ API provides an easy interface to pass parameters to all NSI
3## API calls through the Args class.
4
5Create "simple polygon" "mesh"
6SetAttribute "simple polygon"
7    "P" "point" 1 [ -1  1  0   1  1  0   1 -1  0   -1 -1  0 ]

Geometry Creation in C++

 1/*
 2    Polygonal meshes can be created minimally by specifying "P".
 3    NSI's C++ API provides an easy interface to pass parameters
 4    to all NSI API calls through the Args class.
 5*/
 6const char *k_poly_handle = "simple polygon"; /* avoids typos */
 7
 8nsi.Create( k_poly_handle, "mesh" );
 9
10NSI::ArgumentList mesh_args;
11float points[3*4] = { -1, 1, 0,  1, 1, 0, 1, -1, 0, -1, -1, 0 };
12mesh_args.Add(
13    NSI::Argument::New( "P" )
14        ->SetType( NSITypePoint )
15        ->SetCount( 4 )
16        ->SetValuePointer( points ) );
17nsi.SetAttribute( k_poly_handle, mesh_args );

Specifying normals and other texture coordinates follows the same logic. Constant attributes can be declared in a concise form too:

Adding constant attributes
1SetAttribute "simple polygon"
2    "subdivision.scheme" "string" 1 ["catmull-clark"]

Adding constant attributes in C++

1/** Turn our mesh into a subdivision surface */
2nsi.SetAttribute( k_poly_handle,
3    NSI::CStringPArg("subdivision.scheme", "catmull-clark") );

Transforming Geometry

In NSI, a geometry is rendered only if connected to the scene’s root (which has the special handle “.root”). It is possible to directly connect a geometry node (such as the simple polygon above) to scene’s root but it wouldn’t be very useful. To place/instance a geometry anywhere in the 3D world a transform node is used as in the code snippet below.

Adding constant attributes
 1Create "my translation" "transform"
 2Connect "translation"  "" ".root" "objects"
 3Connect "simple polygon" "" "translation" "objects" );
 4
 5# Transalte 1 unit in Y
 6SetAttribute "my translation"
 7    "transformationmatrix" "matrix" 1 [
 8    1 0 0 0
 9    0 1 0 0
10    0 0 1 0
11    0 1 0 1]

Adding constant attributes in C++

 1const char *k_instance1 = "my translation";
 2
 3nsi.Create( k_instance1, "transform" );
 4nsi.Connect( k_instance1, "", NSI_SCENE_ROOT, "objects" );
 5nsi.Connect( k_poly_handle, "", k_instance1, "objects" );
 6
 7/*
 8    Matrices in NSI are in double format to allow for greater
 9    range and precision.
10*/
11double trs[16] =
12{
13    1., 0., 0., 0.,
14    0., 1., 0., 0.,
15    0., 0., 1., 0.,
16    0., 1., 0., 1. /* transalte 1 unit in Y */
17};
18
19nsi.SetAttribute( k_instance1,
20    NSI::DoubleMatrixArg("transformationmatrix", trs) );

Instancing is as simple as connecting a geometry to different attributes. Instances of instances do work as expected too.

1const char *k_instance2 = "another translation";
2trs[13] += 1.0; /* translate in Y+ */
3
4nsi.Create( k_instance2, "transform" );
5nsi.Connect( k_poly_handle, "", k_instance2, "objects" );
6nsi.Connect( k_instance2, "", NSI_SCENE_ROOT, "objects" );
7
8/* We know have two instances of the same polygon in the scene */