Conventions
Conventions are strict requirements for users on how to use and develop OmniGraph nodes. If ignored, OmniGraph will not behave correctly or be confusing for other users.
Naming Conventions
The mandatory naming conventions are noted where applicable. The rest of these conventions have been set up to make it as easy as possible for you to write your own nodes, and to be able to read the nodes that others have written.
File And Class Names
Class and file naming is InterCaps
with the prefix Ogn
. For example, OgnMyNode.ogn, OgnYourNode.py,
class OgnMyNode, and OgnHerNode.cpp.
As with regular writing, active phrasing (verb-noun) is preferred over passive phrasing when a node name refers to its function.
Weak |
Preferred |
---|---|
OgnSumOfTwoValues |
OgnAddTwoValues |
OgnAttributeRemoval |
OgnRemoveAttribute |
OgnTextGenerator |
OgnGenerateText |
Tip
Some of the automated processes use the Ogn
prefix to more quickly recognize node files. Using it helps
them work at peak efficiency.
If the node outputs multiple objects (bundles, prims, etc) then reflect that in the name. (i.e. GetPrimPath for a single path vs GetPrimPaths for an array of paths)
The following is a list of common actions/prefixes. These should be used whenever possible for consistency and readability:
Action/Prefix |
Purpose |
---|---|
Constant |
A constant value (i.e. ConstantBool) |
Read |
Reading the value of a prim from fabric or USD (i.e. ReadPrimAttribute) |
Write |
Writing the value of a prim to fabric or USD (i.e. WritePrimAttribute) |
Set |
Setting the value of an object (i.e. SetPrimActive) |
Get |
Computing the value of an object (i.e. GetPrimPath) |
Find |
Search data for a result (i.e. FindPrims) |
To |
Converting from one value to another (i.e. ToString) |
Insert |
inserting an object into a bundle/array (i.e. InsertPrim) |
Extract |
extracting an object from a bundle/array (i.e. ExtractPrim) |
Remove |
remove an object from a bundle/array (i.e. RemoveAttribute) |
Build/Make |
Constructing a value from one or more objects. (i.e. BuildString) |
Is |
Query for object matching (i.e. IsPrimSelected) |
Has |
Query for object exists on another object (i.e. HasAttr) |
On |
Event node; used for action graph specific nodes. (i.e OnTick) |
Node Names
Although the only real restriction on node names is that they consist of alphanumeric, or underscore characters there are some conventions established to make it easier to work with nodes, both familiar and unfamiliar.
A node will generally have two names - a unique name to identify it to OmniGraph, and a user-friendly name for viewing in the UI. The name of the node should be generally related to the name of the class, to make them easy to find.
The name will be made unique within the larger space by prepending the extension as a namespace. The name specified
in the file only need be unique within its extension, and by convention is in uppercase CamelCase
, also known as
PascalCase
. It’s a good idea to keep your name related to the class name so that you can correlate the two easily.
Warning
You can override the prepending of the extension name if you want your node name to be something different, but
if you do, you must be prepared to ensure its uniqueness. To override the name simply put it in a namespace by
including a .
character, e.g. omni.deformer.Visualizer
. Note that the omni.
prefix is reserved for NVIDIA
developed extensions.
The user-friendly name can be anything, even an entire phrase, in Title Case
. Although any name is acceptable
always keep in mind that your node name will appear in the user interface and its function should be immediately
identifiable from its name. If you do not specify a user-friendly name then the unique name will be used in the user
interface instead.
Here are a few examples from the OmniGraph extensions:
Class Name |
Name in the .ogn file |
Unique Extended Name |
User Facing Node Name |
---|---|---|---|
OgnTutorialTupleData |
TupleData |
omni.graph.tutorials.TupleData |
Tutorial Node: Tuple Attributes |
OgnVersionedDeformer |
VersionedDeformer |
omni.graph.examples.cpp.VersionedDeformer |
Example Node: Versioned Deformer |
OgnAdd |
Add |
omni.graph.nodes.Add |
Add |
Attention
The unique node name is restricted to the alphanumeric characters and underscore (_
). Any
other characters in the node name will cause the code generation to fail with an error message.
Attribute Names
As you will learn, every node has a set of attributes which describe the data it requires to perform its operations. The attributes also have naming conventions. The mandatory part is that attributes may only contain alphanumeric characters, underscore, and optional colon-separated namespacing.
The preferred naming for attributes is camelCase
and, as with nodes, both a unique name and a user-friendly
name may be specified where the user-friendly name has no real restrictions.
Attributes have some predefined namespaces depending on their location with the node as well (inputs:
, outputs:
,
and state:
) so you can use this to have inputs and outputs with the same name since they will be in different
namespaces. Here is an example of attribute names on a node that adds two values together:
Name in the .ogn file |
Full Name |
User Facing Name |
---|---|---|
a |
inputs:a |
First Addend |
b |
inputs:b |
Second Addend |
sum |
outputs:sum |
Sum Of Inputs |
Attention
The unique attribute name is restricted to the alphanumeric characters, underscore (_
), and colon (:
). Any
other characters in the attribute name will cause the code generation to fail with an error message.
Suggest multiplicity in the name when using arrays or when target
or bundle
attributes are expected to have
multiple entries. (ex. prims for multiple prims and prim for a single prim)
The following is a list of common attribute names/suffixes that can be used when appropriate:
Name/Suffix |
Purpose |
---|---|
prim / target |
|
prims / targets |
|
bundle |
|
primBundle |
|
primsBundle |
|
pattern |
|
value |
attribute name for constants and math functions inputs/outputs |
name |
|
A…Z |
Dynamic attribute names |
Tip
You will find that your node will be easier to use if you minimize the use of attribute namespaces. It has
some implications in generated code due to the special meaning of the colon in C++, Python, and USD. For example
an output bundle you name internal:color:bundle
will be accessed in code as outputs_internal_color_bundle
.
Illegal Attribute Names
Attributes cannot use C++ or python keywords as their name. The following attribute names are illegal and should be avoided regardless of the method of implementing your node.
C++ |
|||||
---|---|---|---|---|---|
alignas |
char16_t |
do |
mutable |
return |
typeid |
alignof |
char32_t |
double |
namespace |
short |
typename |
and |
class |
dynamic_cast |
new |
signed |
union |
and_eq |
compl |
else |
noexcept |
sizeof |
unsigned |
asm |
concept |
enum |
not |
static |
using |
atomic_cancel |
const |
explicit |
not_eq |
static_assert |
virtual |
atomic_commit |
consteval |
export |
nullptr |
static_cast |
void |
atomic_noexcept |
constexpr |
extern |
operator |
struct |
volatile |
auto |
constinit |
false |
or |
switch |
wchar_t |
bitand |
const_cast |
float |
or_eq |
synchronized |
while |
bitor |
continue |
for |
private |
template |
xor |
bool |
co_await |
friend |
protected |
this |
xor_eq |
break |
co_return |
goto |
public |
thread_local |
|
case |
co_yield |
if |
reflexpr |
throw |
|
catch |
decltype |
inline |
register |
true |
|
char |
default |
int |
reinterpret_cast |
try |
|
char8_t |
delete |
long |
requires |
typedef |
Python |
|||||
---|---|---|---|---|---|
False |
async |
del |
from |
lambda |
raise |
None |
await |
elif |
global |
nonlocal |
return |
True |
break |
else |
if |
not |
try |
and |
class |
except |
import |
or |
while |
as |
continue |
finally |
in |
pass |
with |
assert |
def |
for |
is |
property |
yield |
Code Conventions
Errors & Warnings
OmniGraph has two ways to communicate to the user when the compute function of a node has failed. Either of these methods take a formatted string that describes the failure.
Python |
C++ |
Description |
---|---|---|
|
|
Used when a compute encounters unusual data but can still provide an output. This should not trigger the compute to halt. Ex. Request to deform an empty mesh. |
|
|
Used when a compute encounters inconsistent, invalid or unexpected data and it cannot compute an output. This should trigger the compute to halt. Ex. Request to add two vectors with incompatible sizes. |
Return Conditions
There are two types of compute functions that can be used in nodes; compute
and computeVectorized
.
For nodes using compute
return a bool
type. The convention for these nodes is to return true
if the
function was successful and false
otherwise.
static bool compute(GraphContextObj const& contextObj, NodeObj const& nodeObj)
{
if (db.inputs.value().isValid())
{
db.outputs.value() = db.inputs.value();
return true;
}
return false;
}
For nodes using computeVectorized
return a size_t
value that represents the number of successful instance
computations.
static size_t computeVectorized(GraphContextObj const& contextObj, NodeObj const& nodeObj, size_t count)
{
size_t ret = 0;
for(size_t idx = 0; idx < count; ++idx)
{
if (db.inputs.value().isValid())
{
db.outputs.value() = db.inputs.value();
db.moveToNextInstance();
++ret;
}
}
return ret;
}
Warning
The return value of these functions are not currently used for anything, but this could change in the future.
Data Conventions
Prim Path Data
Tip
Use
target
attributes when a node or bundle needs to consume a prim path.Use the first path in the
target
array when accessing a single path.
Previously, OmniGraph offered several methods of consuming a prim path; bundles, path strings and path tokens. These
methods have been replaced with a new target
type.
target
attributes are backed by USD relationships, so paths will repair if referenced or if the namespace hierarchy changes.They are arrays, so consuming multiple paths is possible. When a single path is required, the first path in the array should be used.
Output
target
attributes are possible, so nodes can construct a path array that is read by another node.
In the future, previous methods of consuming a path may be deprecated. If any nodes currently use these methods,
they must be upgraded to use target
attributes.
To be able to select multiple targets, add the ogn metadata:
allowMultiInputs: "1"
To disallow incoming connections, add the ogn metadata:
literalOnly: "1"
Code should not use the USD API to read paths, otherwise incoming connections will be ignored.
Prim Bundle Data
Tip
All prim bundle attributes are containers of one or more child bundles.
Nodes referencing a single prim bundle access the first child bundle from the attribute.
When reading a prim bundle into a graph, users must use a ReadPrims node.
The
sourcePrimPath
andsourcePrimType
attributes define a bundle as a prim bundle.All data added to bundles should conform with USD standards for naming and types.
Bundles are a flexible data type that is designed to pass a large amount of attribute data through a single connection. Prim bundles are special bundles that represent a prim within OmniGraph. Moving forward all prim bundle attributes in OmniGraph will act as containers for one or more child bundles containing the attributes for each prim (i.e multiple prims in bundles) rather than have attributes on the root of the bundle (i.e single prim in bundle).
Deeper documentation about the multiple prim bundle structure can be found in the Bundles User Guide.
Single Prim Bundle
There are cases where a node needs to access only a single prim bundle, such as extracting attributes from a bundle for
a specific prim. When referencing a single prim bundle, the convention is to access the first child bundle from the
bundle attribute. This can be accomplished with get_child_bundle(0)
in python and getChildBundle(0)
in C++.
Full documentation about how to access child bundles can be found in the Bundle Python API Documentation or Bundle C++ API Documentation.
Prim Bundle Attributes
When constructing a bundle with a ReadPrims node, there are several special attributes added to each child prim bundle.
The sourcePrimPath
and sourcePrimType
are required attributes that define a prim bundle, and worldMatrix
is
used to track the transformation of each prim. There are also optional attributes generated for bounding boxes and
skeletal binding (when applicable). Users should refrain from altering these attributes manually unless it is
absolutely necessary.
Required Attributes
Attribute Name |
Type |
Purpose |
---|---|---|
sourcePrimPath |
token |
Path to the prim in the bundle (ex |
sourcePrimType |
token |
Type of the prim in the bundle (ex |
worldMatrix |
matrix4d |
The world space matrix of the prim |
Optional Attributes
Attribute Name |
Type |
Purpose |
---|---|---|
bboxTransform |
matrix4d |
The transform of the bounding box of the prim. |
bboxMinCorner |
point3d |
The lower corner of the bounding box in world space. |
bboxMaxCorner |
point3d |
The upper corner of the bounding box in world space. |
USD Prim Bundle Data
There are a set of standard attributes when handling prims that users should use when constructing bundles. These are consistent with the USD naming and types. To allow for maximum compatibility through all nodes, these attributes should be the only ones used when referencing prims.
Imageable Attributes
Base attributes for all prims that may require rendering or visualization of some sort.
Attribute Name |
Type |
Purpose |
---|---|---|
purpose |
token |
Purpose is a classification of geometry into categories that can each be independently included or excluded from traversals of prims on a stage, such as rendering or bounding-box computation traversals. [“default”, “render”, “proxy”, “guide”] |
visibility |
token |
Visibility is meant to be the simplest form of “pruning” visibility that is supported by most DCC apps. [“inherited”, “invisible”] |
proxyPrim |
target |
The proxyPrim relationship allows us to link a prim whose purpose is “render” to its (single target) purpose=”proxy” prim. This is entirely optional, but can be useful in several scenarios. |
Xformable Attributes
Base attributes for all transformable prims, which allows arbitrary sequences of component affine transformations to be
encoded. These transformation attributes also allow a separate suffix (ex. xformOp:translate:pivot
) that can allow
multiple attributes of the same type on a single prim.
Attribute Name |
Type |
Purpose |
---|---|---|
xformOp:translate |
double3 |
Translation |
xformOp:translate:pivot |
double3 |
Pivot translation |
xformOp:rotateX |
double |
Single X axis rotation in degrees |
xformOp:rotateY |
double |
Single Y axis rotation in degrees |
xformOp:rotateZ |
double |
Single Z axis rotation in degrees |
xformOp:rotateXYZ |
double3 |
Euler Rotation in XYZ in degrees |
xformOp:rotateXZY |
double3 |
Euler Rotation in XZY in degrees |
xformOp:rotateYXZ |
double3 |
Euler Rotation in YXZ in degrees |
xformOp:rotateYZX |
double3 |
Euler Rotation in YZX in degrees |
xformOp:rotateZXY |
double3 |
Euler Rotation in ZXY in degrees |
xformOp:rotateZYX |
double3 |
Euler Rotation in ZYX in degrees |
xformOp:scale |
double3 |
Scale |
xformOp:orient |
quatd |
Quaternion rotate |
xformOp:transform |
matrix4d |
Transformation Matrix |
xformOpOrder |
token[] |
Encodes the sequence of transformation operations in the order in which they should be pushed onto a transform stack while visiting a UsdStage’s prims in a graph traversal that will effect the desired positioning for this prim and its descendant prims. |
Kit will also automatically convert from Z to Y up or from a mismatch in units using xformOp:rotateX:unitsResolve
or
xformOp:scale:unitsResolve
respectively.
Boundable Attributes
Boundable attributes introduce the ability for a prim to persistently cache a rectilinear, local-space, extent.
Attribute Name |
Type |
Purpose |
---|---|---|
extent |
float3[] |
Extent is a three dimensional range measuring the geometric extent of the authored gprim in its own local space (i.e. its own transform not applied), without accounting for any shader-induced displacement. This space is aligned to world. |
Geometric Prim Attributes
Base attributes for all geometric primitives.
Attribute Name |
Type |
Purpose |
---|---|---|
doublesided |
bool |
Setting a gprim’s doubleSided attribute to true instructs all renderers to disable optimizations such as backface culling for the gprim, and attempt (not all renderers are able to do so, but the USD reference GL renderer always will) to provide forward-facing normals on each side of the surface for lighting calculations. |
orientation |
token |
Orientation specifies whether the gprim’s surface normal should be computed using the right hand rule, or the left hand rule. Please see for a deeper explanation and generalization of orientation to composed scenes with transformation hierarchies. [“rightHanded”, “leftHanded”] |
primvars:displayColor |
color3f[] |
A colorSet that can be used as a display or modeling color, even in the absence of any specified shader for a gprim. |
primvars:displayOpacity |
float[] |
Companion to displayColor that specifies opacity, broken out as an independent attribute rather than an rgba color, both so that each can be independently overridden, and because shaders rarely consume rgba parameters. |
Point Based Attributes
Base attributes for all prims that possess points, providing common attributes such as normals and velocities.
Attribute Name |
Type |
Purpose |
---|---|---|
points |
point3f[] |
The primary geometry attribute for all PointBased prims. Describes points in local space |
normals |
normal3f[] |
Provide an object-space orientation for individual points, which, depending on subclass, may define a surface, curve, or free points. |
velocities |
vector3f[] |
If provided, ‘velocities’ should be used by renderers to compute positions between samples for the ‘points’ attribute, rather than interpolating between neighboring ‘points’ samples. Velocity is measured in position units per second, as per most simulation software. |
acceleration |
vector3f[] |
If provided, ‘accelerations’ should be used with velocities to compute positions between samples for the ‘points’ attribute rather than interpolating between neighboring ‘points’ samples. Acceleration is measured in position units per second-squared. |
Material Attributes
Attributes used for prims that include shading data (bindings, uvs, etc.).
Attribute Name |
Type |
Purpose |
---|---|---|
material:binding |
rel (target) |
Relationship that targets the bound material. |
primvars:st |
texCoord2f[] |
Standard UV set. |
Mesh Attributes
Attributes used for mesh prims.
Attribute Name |
Type |
Purpose |
---|---|---|
cornerIndices |
int[] |
The indices of points for which a corresponding sharpness value is specified in cornerSharpnesses (so the size of this array must match that of cornerSharpnesses) |
cornerSharpness |
float[] |
The sharpness values associated with a corresponding set of points specified in cornerIndices (so the size of this array must match that of cornerIndices). Use the constant |
creaseIndices |
int[] |
The indices of points grouped into sets of successive pairs that identify edges to be creased. The size of this array must be equal to the sum of all elements of the creaseLengths attribute. |
creaseLengths |
int[] |
The length of this array specifies the number of creases (sets of adjacent sharpened edges) on the mesh. Each element gives the number of points of each crease, whose indices are successively laid out in the creaseIndices attribute. Since each crease must be at least one edge long, each element of this array must be at least two. |
creaseSharpness |
float[] |
The per-crease or per-edge sharpness values for all creases. Since creaseLengths encodes the number of points in each crease, the number of elements in this array will be either len(creaseLengths) or the sum over all X of (creaseLengths[X] - 1). Note that while the RI spec allows each crease to have either a single sharpness or a value per-edge, USD will encode either a single sharpness per crease on a mesh, or sharpnesses for all edges making up the creases on a mesh. Use the constant |
faceVaryingLinearInterpolation |
token |
Specifies how elements of a primvar of interpolation type “faceVarying” are interpolated for subdivision surfaces. Interpolation can be as smooth as a “vertex” primvar or constrained to be linear at features specified by several options. [“none”, “cornersOnly”, “cornersPlus1”, “cornersPlus2”, “boundaries”, “all”] |
faceVertexCounts |
int[] |
Provides the number of vertices in each face of the mesh, which is also the number of consecutive indices in faceVertexIndices that define the face. The length of this attribute is the number of faces in the mesh. If this attribute has more than one timeSample, the mesh is considered to be topologically varying. |
faceVertexIndices |
int[] |
Flat list of the index (into the points attribute) of each vertex of each face in the mesh. If this attribute has more than one timeSample, the mesh is considered to be topologically varying. |
holeIndices |
int[] |
The indices of all faces that should be treated as holes, i.e. made invisible. This is traditionally a feature of subdivision surfaces and not generally applied to polygonal meshes. |
interpolateBoundary |
token |
Specifies how subdivision is applied for faces adjacent to boundary edges and boundary points. [“none”, “edgeOnly”, “edgeAndCorner”] |
subdivisionScheme |
token |
The subdivision scheme to be applied to th surface. [“catmullClark”, “loop”, “bilinear”, “none”] |
triangleSubdivisionRule |
token |
Specifies an option to the subdivision rules for the Catmull-Clark scheme to try and improve undesirable artifacts when subdividing triangles. [“catmullClark”, “smooth”] |