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 subsection 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. 

/**
	Polygonal meshes can be created minimally by specifying P.
    C++ API provides an easy interface to pass parameters to all NSI
	API calls through the Args class.
*/
NSI::Context nsi;
nsi.Create( "simply polygon", "mesh" );

NSI::ArgumentList mesh_args;
float points[3*4] = { ... /* insert your favorite 4 points here */}; 
mesh_args.Add(
	NSI::Argument::New( "P" )
        ->SetType( NSITypePoint )
        ->SetCount( 4 )
        ->SetValuePointer( const_cast<float*>(points) );
nsi.SetAttribute( "simple polgyon", mesh_args );


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

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


Transforming Geometry

In NSI, a geometry is only considered if connected to the scene 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. It is common to place geometry using a transform and NSI has a special node for it.

nsi.Create( "translation", "transform" );
nsi.Connect( "translation", NSI_SCENE_ROOT );
nsi.Connect( "simple polygon", "", "translation", "objects" );

double trs[16] =
{
	1., 0., 0., 0.,
	0., 1., 0., 0.,
	0., 0., 1., 0.,
	0., 1., 0., 1. /* transalte 1 unit in Y */
};

nsi.SetAttribute( "translation",
	NSI::DoubleMatrixArg("transformationmatrix", trs) );


Assigning Shaders

Shaders are created as any other nodes using the NSICreate API call. They are not assigned directly on geometry but through an intermediate attributes nodes. Having an extra indirection allows for more flexible export as we will see in the following chapters.

/**
	Create a simple shader node using the standard OSL "emitter" shader.
	Set it's parameter to something different than defaults.
*/
nsi.Create( "simpleshader", "shader" );
float red[3] = {1,0,0};
nsi.SetAttribute( "simpleshader",
	(
		NSI::CStringPArg("shaderfilename", "emitter"),
		NSI::ColorArg( "Cs", red),
		NSI::FloatArg( "power", 4.f )
	) );

/** Create an attributes nodes and connect our shader to it */
nsi.Create( "attr", "attributes" );
nsi.Connect( "simpleshader", "", "attr", "surfaceshader" );

/* Connecting the attributes node to the mesh assign completes the assignment */
nsi.Connect( "attr", "", "simple mesh", "geometryattributes" );

Creating shading networks uses the same NSIConnect calls as for scene description.

/** We can inline OSL source code directly */
const char *sourcecode = "shader uv() { Ci = emission() * color(u, v, 0); } ";
nsi.Create( "uv", "shader" );
nsi.SetAttribute( "uvshader", NSI::CStringPArg("shadersource", sourcecode) );

/** We can now connect our new shader node into our simple emitter */
nsi.Connect( "uvshader", "Ci", "simplesshader", "Cs" );


Multi-Camera output, in One Render.