Tutorial 7 - Role-Based Data Node

The role-based data node creates one input attribute and one output attribute of each of the role-based type. A role-based type is defined as data with an underlying simple data type, with an interpretation of that simple data, called a “role”.

Examples of roles are color, quat, and timecode. For consistency the tuple counts for each of the roles are included in the declaration so that the “shape” of the underlying data is more obvious.

OgnTutorialRoleData.ogn

The ogn file shows the implementation of a node named “omni.graph.tutorials.RoleData”, which has one input and one output attribute of each Role type.

  1{
  2    "RoleData" : {
  3        "version": 1,
  4        "categories": "tutorials",
  5        "scheduling": ["threadsafe"],
  6        "description": [
  7            "This is a tutorial node. It creates both an input and output attribute of every supported ",
  8            "role-based data type. The values are modified in a simple way so that the compute modifies values. "
  9        ],
 10        "metadata":
 11        {
 12            "uiName": "Tutorial Node: Role-Based Attributes"
 13        },
 14        "inputs": {
 15            "a_color3d": {
 16                "type": "colord[3]",
 17                "description": ["This is an attribute interpreted as a double-precision 3d color"],
 18                "default": [0.0, 0.0, 0.0]
 19            },
 20            "a_color3f": {
 21                "type": "colorf[3]",
 22                "description": ["This is an attribute interpreted as a single-precision 3d color"],
 23                "default": [0.0, 0.0, 0.0]
 24            },
 25            "a_color3h": {
 26                "type": "colorh[3]",
 27                "description": ["This is an attribute interpreted as a half-precision 3d color"],
 28                "default": [0.0, 0.0, 0.0]
 29            },
 30            "a_color4d": {
 31                "type": "colord[4]",
 32                "description": ["This is an attribute interpreted as a double-precision 4d color"],
 33                "default": [0.0, 0.0, 0.0, 0.0]
 34            },
 35            "a_color4f": {
 36                "type": "colorf[4]",
 37                "description": ["This is an attribute interpreted as a single-precision 4d color"],
 38                "default": [0.0, 0.0, 0.0, 0.0]
 39            },
 40            "a_color4h": {
 41                "type": "colorh[4]",
 42                "description": ["This is an attribute interpreted as a half-precision 4d color"],
 43                "default": [0.0, 0.0, 0.0, 0.0]
 44            },
 45            "a_frame": {
 46                "type": "frame[4]",
 47                "description": ["This is an attribute interpreted as a coordinate frame"],
 48                "default": [[1.0,0.0,0.0,0.0], [0.0,1.0,0.0,0.0], [0.0,0.0,1.0,0.0], [0.0,0.0,0.0,1.0]]
 49            },
 50            "a_matrix2d": {
 51                "type": "matrixd[2]",
 52                "description": ["This is an attribute interpreted as a double-precision 2d matrix"],
 53                "default": [[1.0, 0.0], [0.0, 1.0]]
 54            },
 55            "a_matrix3d": {
 56                "type": "matrixd[3]",
 57                "description": ["This is an attribute interpreted as a double-precision 3d matrix"],
 58                "default": [[1.0,0.0,0.0], [0.0,1.0,0.0], [0.0,0.0,1.0]]
 59            },
 60            "a_matrix4d": {
 61                "type": "matrixd[4]",
 62                "description": ["This is an attribute interpreted as a double-precision 4d matrix"],
 63                "default": [[1.0,0.0,0.0,0.0], [0.0,1.0,0.0,0.0], [0.0,0.0,1.0,0.0], [0.0,0.0,0.0,1.0]]
 64            },
 65            "a_normal3d": {
 66                "type": "normald[3]",
 67                "description": ["This is an attribute interpreted as a double-precision 3d normal"],
 68                "default": [0.0, 0.0, 0.0]
 69            },
 70            "a_normal3f": {
 71                "type": "normalf[3]",
 72                "description": ["This is an attribute interpreted as a single-precision 3d normal"],
 73                "default": [0.0, 0.0, 0.0]
 74            },
 75            "a_normal3h": {
 76                "type": "normalh[3]",
 77                "description": ["This is an attribute interpreted as a half-precision 3d normal"],
 78                "default": [0.0, 0.0, 0.0]
 79            },
 80            "a_point3d": {
 81                "type": "pointd[3]",
 82                "description": ["This is an attribute interpreted as a double-precision 3d point"],
 83                "default": [0.0, 0.0, 0.0]
 84            },
 85            "a_point3f": {
 86                "type": "pointf[3]",
 87                "description": ["This is an attribute interpreted as a single-precision 3d point"],
 88                "default": [0.0, 0.0, 0.0]
 89            },
 90            "a_point3h": {
 91                "type": "pointh[3]",
 92                "description": ["This is an attribute interpreted as a half-precision 3d point"],
 93                "default": [0.0, 0.0, 0.0]
 94            },
 95            "a_quatd": {
 96                "type": "quatd[4]",
 97                "description": ["This is an attribute interpreted as a double-precision 4d quaternion"],
 98                "default": [0.0, 0.0, 0.0, 0.0]
 99            },
100            "a_quatf": {
101                "type": "quatf[4]",
102                "description": ["This is an attribute interpreted as a single-precision 4d quaternion"],
103                "default": [0.0, 0.0, 0.0, 0.0]
104            },
105            "a_quath": {
106                "type": "quath[4]",
107                "description": ["This is an attribute interpreted as a half-precision 4d quaternion"],
108                "default": [0.0, 0.0, 0.0, 0.0]
109            },
110            "a_texcoord2d": {
111                "type": "texcoordd[2]",
112                "description": ["This is an attribute interpreted as a double-precision 2d texcoord"],
113                "default": [0.0, 0.0]
114            },
115            "a_texcoord2f": {
116                "type": "texcoordf[2]",
117                "description": ["This is an attribute interpreted as a single-precision 2d texcoord"],
118                "default": [0.0, 0.0]
119            },
120            "a_texcoord2h": {
121                "type": "texcoordh[2]",
122                "description": ["This is an attribute interpreted as a half-precision 2d texcoord"],
123                "default": [0.0, 0.0]
124            },
125            "a_texcoord3d": {
126                "type": "texcoordd[3]",
127                "description": ["This is an attribute interpreted as a double-precision 3d texcoord"],
128                "default": [0.0, 0.0, 0.0]
129            },
130            "a_texcoord3f": {
131                "type": "texcoordf[3]",
132                "description": ["This is an attribute interpreted as a single-precision 3d texcoord"],
133                "default": [0.0, 0.0, 0.0]
134            },
135            "a_texcoord3h": {
136                "type": "texcoordh[3]",
137                "description": ["This is an attribute interpreted as a half-precision 3d texcoord"],
138                "default": [0.0, 0.0, 0.0]
139            },
140            "a_timecode": {
141                "type": "timecode",
142                "description": ["This is a computed attribute interpreted as a timecode"],
143                "default": 1.0
144            },
145            "a_vector3d": {
146                "type": "vectord[3]",
147                "description": ["This is an attribute interpreted as a double-precision 3d vector"],
148                "default": [0.0, 0.0, 0.0]
149            },
150            "a_vector3f": {
151                "type": "vectorf[3]",
152                "description": ["This is an attribute interpreted as a single-precision 3d vector"],
153                "default": [0.0, 0.0, 0.0]
154            },
155            "a_vector3h": {
156                "type": "vectorh[3]",
157                "description": ["This is an attribute interpreted as a half-precision 3d vector"],
158                "default": [0.0, 0.0, 0.0]
159            }
160        },
161        "outputs": {
162            "a_color3d": {
163                "type": "colord[3]",
164                "description": ["This is a computed attribute interpreted as a double-precision 3d color"]
165            },
166            "a_color3f": {
167                "type": "colorf[3]",
168                "description": ["This is a computed attribute interpreted as a single-precision 3d color"]
169            },
170            "a_color3h": {
171                "type": "colorh[3]",
172                "description": ["This is a computed attribute interpreted as a half-precision 3d color"]
173            },
174            "a_color4d": {
175                "type": "colord[4]",
176                "description": ["This is a computed attribute interpreted as a double-precision 4d color"]
177            },
178            "a_color4f": {
179                "type": "colorf[4]",
180                "description": ["This is a computed attribute interpreted as a single-precision 4d color"]
181            },
182            "a_color4h": {
183                "type": "colorh[4]",
184                "description": ["This is a computed attribute interpreted as a half-precision 4d color"]
185            },
186            "a_frame": {
187                "type": "frame[4]",
188                "description": ["This is a computed attribute interpreted as a coordinate frame"]
189            },
190            "a_matrix2d": {
191                "type": "matrixd[2]",
192                "description": ["This is a computed attribute interpreted as a double-precision 2d matrix"]
193            },
194            "a_matrix3d": {
195                "type": "matrixd[3]",
196                "description": ["This is a computed attribute interpreted as a double-precision 3d matrix"]
197            },
198            "a_matrix4d": {
199                "type": "matrixd[4]",
200                "description": ["This is a computed attribute interpreted as a double-precision 4d matrix"]
201            },
202            "a_normal3d": {
203                "type": "normald[3]",
204                "description": ["This is a computed attribute interpreted as a double-precision 3d normal"]
205            },
206            "a_normal3f": {
207                "type": "normalf[3]",
208                "description": ["This is a computed attribute interpreted as a single-precision 3d normal"]
209            },
210            "a_normal3h": {
211                "type": "normalh[3]",
212                "description": ["This is a computed attribute interpreted as a half-precision 3d normal"]
213            },
214            "a_point3d": {
215                "type": "pointd[3]",
216                "description": ["This is a computed attribute interpreted as a double-precision 3d point"]
217            },
218            "a_point3f": {
219                "type": "pointf[3]",
220                "description": ["This is a computed attribute interpreted as a single-precision 3d point"]
221            },
222            "a_point3h": {
223                "type": "pointh[3]",
224                "description": ["This is a computed attribute interpreted as a half-precision 3d point"]
225            },
226            "a_quatd": {
227                "type": "quatd[4]",
228                "description": ["This is a computed attribute interpreted as a double-precision 4d quaternion"]
229            },
230            "a_quatf": {
231                "type": "quatf[4]",
232                "description": ["This is a computed attribute interpreted as a single-precision 4d quaternion"]
233            },
234            "a_quath": {
235                "type": "quath[4]",
236                "description": ["This is a computed attribute interpreted as a half-precision 4d quaternion"]
237            },
238            "a_texcoord2d": {
239                "type": "texcoordd[2]",
240                "description": ["This is a computed attribute interpreted as a double-precision 2d texcoord"]
241            },
242            "a_texcoord2f": {
243                "type": "texcoordf[2]",
244                "description": ["This is a computed attribute interpreted as a single-precision 2d texcoord"]
245            },
246            "a_texcoord2h": {
247                "type": "texcoordh[2]",
248                "description": ["This is a computed attribute interpreted as a half-precision 2d texcoord"]
249            },
250            "a_texcoord3d": {
251                "type": "texcoordd[3]",
252                "description": ["This is a computed attribute interpreted as a double-precision 3d texcoord"]
253            },
254            "a_texcoord3f": {
255                "type": "texcoordf[3]",
256                "description": ["This is a computed attribute interpreted as a single-precision 3d texcoord"]
257            },
258            "a_texcoord3h": {
259                "type": "texcoordh[3]",
260                "description": ["This is a computed attribute interpreted as a half-precision 3d texcoord"]
261            },
262            "a_timecode": {
263                "type": "timecode",
264                "description": ["This is a computed attribute interpreted as a timecode"]
265            },
266            "a_vector3d": {
267                "type": "vectord[3]",
268                "description": ["This is a computed attribute interpreted as a double-precision 3d vector"]
269            },
270            "a_vector3f": {
271                "type": "vectorf[3]",
272                "description": ["This is a computed attribute interpreted as a single-precision 3d vector"]
273            },
274            "a_vector3h": {
275                "type": "vectorh[3]",
276                "description": ["This is a computed attribute interpreted as a half-precision 3d vector"]
277            }
278        },
279        "tests": [
280            {
281                "description": "Compute method just increments the component values",
282                "inputs:a_color3d": [1.0, 2.0, 3.0], "outputs:a_color3d": [2.0, 3.0, 4.0],
283                "inputs:a_color3f": [11.0, 12.0, 13.0], "outputs:a_color3f": [12.0, 13.0, 14.0],
284                "inputs:a_color3h": [21.0, 22.0, 23.0], "outputs:a_color3h": [22.0, 23.0, 24.0],
285                "inputs:a_color4d": [1.0, 2.0, 3.0, 4.0], "outputs:a_color4d": [2.0, 3.0, 4.0, 5.0],
286                "inputs:a_color4f": [11.0, 12.0, 13.0, 14.0], "outputs:a_color4f": [12.0, 13.0, 14.0, 15.0],
287                "inputs:a_color4h": [21.0, 22.0, 23.0, 24.0], "outputs:a_color4h": [22.0, 23.0, 24.0, 25.0],
288                "inputs:a_frame": [[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0]],
289                "outputs:a_frame": [[2.0, 3.0, 4.0, 5.0], [6.0, 7.0, 8.0, 9.0], [10.0, 11.0, 12.0, 13.0], [14.0, 15.0, 16.0, 17.0]],
290                "inputs:a_matrix2d": [[1.0, 2.0], [3.0, 4.0]], "outputs:a_matrix2d": [[2.0, 3.0], [4.0, 5.0]],
291                "inputs:a_matrix3d": [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]],
292                "outputs:a_matrix3d": [[2.0, 3.0, 4.0], [5.0, 6.0, 7.0], [8.0, 9.0, 10.0]],
293                "inputs:a_matrix4d": [[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0]],
294                "outputs:a_matrix4d": [[2.0, 3.0, 4.0, 5.0], [6.0, 7.0, 8.0, 9.0], [10.0, 11.0, 12.0, 13.0], [14.0, 15.0, 16.0, 17.0]],
295                "inputs:a_normal3d": [1.0, 2.0, 3.0], "outputs:a_normal3d": [2.0, 3.0, 4.0],
296                "inputs:a_normal3f": [11.0, 12.0, 13.0], "outputs:a_normal3f": [12.0, 13.0, 14.0],
297                "inputs:a_normal3h": [21.0, 22.0, 23.0], "outputs:a_normal3h": [22.0, 23.0, 24.0],
298                "inputs:a_point3d": [1.0, 2.0, 3.0], "outputs:a_point3d": [2.0, 3.0, 4.0],
299                "inputs:a_point3f": [11.0, 12.0, 13.0], "outputs:a_point3f": [12.0, 13.0, 14.0],
300                "inputs:a_point3h": [21.0, 22.0, 23.0], "outputs:a_point3h": [22.0, 23.0, 24.0],
301                "inputs:a_quatd": [1.0, 2.0, 3.0, 4.0], "outputs:a_quatd": [2.0, 3.0, 4.0, 5.0],
302                "inputs:a_quatf": [11.0, 12.0, 13.0, 14.0], "outputs:a_quatf": [12.0, 13.0, 14.0, 15.0],
303                "inputs:a_quath": [21.0, 22.0, 23.0, 24.0], "outputs:a_quath": [22.0, 23.0, 24.0, 25.0],
304                "inputs:a_texcoord2d": [1.0, 2.0], "outputs:a_texcoord2d": [2.0, 3.0],
305                "inputs:a_texcoord2f": [11.0, 12.0], "outputs:a_texcoord2f": [12.0, 13.0],
306                "inputs:a_texcoord2h": [21.0, 22.0], "outputs:a_texcoord2h": [22.0, 23.0],
307                "inputs:a_texcoord3d": [1.0, 2.0, 3.0], "outputs:a_texcoord3d": [2.0, 3.0, 4.0],
308                "inputs:a_texcoord3f": [11.0, 12.0, 13.0], "outputs:a_texcoord3f": [12.0, 13.0, 14.0],
309                "inputs:a_texcoord3h": [21.0, 22.0, 23.0], "outputs:a_texcoord3h": [22.0, 23.0, 24.0],
310                "inputs:a_timecode": 10.0, "outputs:a_timecode": 11.0,
311                "inputs:a_vector3d": [1.0, 2.0, 3.0], "outputs:a_vector3d": [2.0, 3.0, 4.0],
312                "inputs:a_vector3f": [11.0, 12.0, 13.0], "outputs:a_vector3f": [12.0, 13.0, 14.0],
313                "inputs:a_vector3h": [21.0, 22.0, 23.0], "outputs:a_vector3h": [22.0, 23.0, 24.0]
314            }
315        ]
316    }
317}

OgnTutorialRoleData.cpp

The cpp file contains the implementation of the compute method, which modifies each of the inputs by adding 1.0 to all components to create outputs that have different, testable, values.

  1// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
  2// SPDX-License-Identifier: LicenseRef-NvidiaProprietary
  3//
  4// NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
  5// property and proprietary rights in and to this material, related
  6// documentation and any modifications thereto. Any use, reproduction,
  7// disclosure or distribution of this material and related documentation
  8// without an express license agreement from NVIDIA CORPORATION or
  9// its affiliates is strictly prohibited.
 10#include <OgnTutorialRoleDataDatabase.h>
 11
 12// This class exercises access to the DataModel through the generated database class for all role-based data types
 13
 14namespace
 15{
 16// Helper values to make it easy to add 1 to values of different lengths
 17GfHalf h1{ 1.0f };
 18GfVec2d increment2d{ 1.0, 1.0 };
 19GfVec2f increment2f{ 1.0f, 1.0f };
 20GfVec2h increment2h{ h1, h1 };
 21GfVec3d increment3d{ 1.0, 1.0, 1.0 };
 22GfVec3f increment3f{ 1.0f, 1.0f, 1.0f };
 23GfVec3h increment3h{ h1, h1, h1 };
 24GfVec4d increment4d{ 1.0, 1.0, 1.0, 1.0 };
 25GfVec4f increment4f{ 1.0f, 1.0f, 1.0f, 1.0f };
 26GfVec4h increment4h{ h1, h1, h1, h1 };
 27GfQuatd incrementQd{ 1.0, 1.0, 1.0, 1.0 };
 28GfQuatf incrementQf{ 1.0f, 1.0f, 1.0f, 1.0f };
 29GfQuath incrementQh{ h1, h1, h1, h1 };
 30GfMatrix4d incrementM4d{ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
 31GfMatrix3d incrementM3d{ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
 32GfMatrix2d incrementM2d{ 1.0, 1.0, 1.0, 1.0 };
 33}
 34
 35// Helper macro to simplify the code but include all of the error checking
 36#define ComputeOne(ATTRIBUTE_NAME, INCREMENT_VARIABLE, ROLE_EXPECTED)                                                  \
 37    foundError = false;                                                                                                \
 38    if (db.inputs.ATTRIBUTE_NAME.role() != ROLE_EXPECTED)                                                              \
 39    {                                                                                                                  \
 40        db.logWarning("Input role type %d != %d", (int)db.inputs.ATTRIBUTE_NAME.role(), (int)ROLE_EXPECTED);           \
 41        foundError = true;                                                                                             \
 42        foundAnyErrors = true;                                                                                         \
 43    }                                                                                                                  \
 44    if (db.outputs.ATTRIBUTE_NAME.role() != ROLE_EXPECTED)                                                             \
 45    {                                                                                                                  \
 46        db.logWarning("output role type %d != %d", (int)db.outputs.ATTRIBUTE_NAME.role(), (int)ROLE_EXPECTED);         \
 47        foundError = true;                                                                                             \
 48        foundAnyErrors = true;                                                                                         \
 49    }                                                                                                                  \
 50    if (!foundError)                                                                                                   \
 51    {                                                                                                                  \
 52        db.outputs.ATTRIBUTE_NAME() = db.inputs.ATTRIBUTE_NAME() + INCREMENT_VARIABLE;                                 \
 53    }
 54
 55class OgnTutorialRoleData
 56{
 57public:
 58    static bool compute(OgnTutorialRoleDataDatabase& db)
 59    {
 60        // The roles for the attributes only serve to guide how to interpret them. When accessed from the
 61        // database they take the form of their raw underlying type. For example a point3d will have the
 62        // same GfVec3d type as a double[3], as will a vector3d and a normal3d.
 63
 64        // Keep track if any role errors were found with this, continuing to the end of evaluation after errors
 65        bool foundAnyErrors{ false }; // Toggled on as soon as any error is found
 66        bool foundError{ false }; // Toggled off and on for each attribute
 67
 68        // Walk through all of the data types, using the macro to perform error checking
 69        ComputeOne(a_color3d, increment3d, AttributeRole::eColor);
 70        ComputeOne(a_color3f, increment3f, AttributeRole::eColor);
 71        ComputeOne(a_color3h, increment3h, AttributeRole::eColor);
 72        //
 73        ComputeOne(a_color4d, increment4d, AttributeRole::eColor);
 74        ComputeOne(a_color4f, increment4f, AttributeRole::eColor);
 75        ComputeOne(a_color4h, increment4h, AttributeRole::eColor);
 76        //
 77        ComputeOne(a_frame, incrementM4d, AttributeRole::eFrame);
 78        //
 79        ComputeOne(a_matrix2d, incrementM2d, AttributeRole::eMatrix);
 80        ComputeOne(a_matrix3d, incrementM3d, AttributeRole::eMatrix);
 81        ComputeOne(a_matrix4d, incrementM4d, AttributeRole::eMatrix);
 82        //
 83        ComputeOne(a_normal3d, increment3d, AttributeRole::eNormal);
 84        ComputeOne(a_normal3f, increment3f, AttributeRole::eNormal);
 85        ComputeOne(a_normal3h, increment3h, AttributeRole::eNormal);
 86        //
 87        ComputeOne(a_point3d, increment3d, AttributeRole::ePosition);
 88        ComputeOne(a_point3f, increment3f, AttributeRole::ePosition);
 89        ComputeOne(a_point3h, increment3h, AttributeRole::ePosition);
 90        //
 91        ComputeOne(a_quatd, incrementQd, AttributeRole::eQuaternion);
 92        ComputeOne(a_quatf, incrementQf, AttributeRole::eQuaternion);
 93        ComputeOne(a_quath, incrementQh, AttributeRole::eQuaternion);
 94        //
 95        ComputeOne(a_texcoord2d, increment2d, AttributeRole::eTexCoord);
 96        ComputeOne(a_texcoord2f, increment2f, AttributeRole::eTexCoord);
 97        ComputeOne(a_texcoord2h, increment2h, AttributeRole::eTexCoord);
 98        //
 99        ComputeOne(a_texcoord3d, increment3d, AttributeRole::eTexCoord);
100        ComputeOne(a_texcoord3f, increment3f, AttributeRole::eTexCoord);
101        ComputeOne(a_texcoord3h, increment3h, AttributeRole::eTexCoord);
102        //
103        ComputeOne(a_timecode, 1.0, AttributeRole::eTimeCode);
104        //
105        ComputeOne(a_vector3d, increment3d, AttributeRole::eVector);
106        ComputeOne(a_vector3f, increment3f, AttributeRole::eVector);
107        ComputeOne(a_vector3h, increment3h, AttributeRole::eVector);
108
109        return foundAnyErrors;
110    }
111};
112
113REGISTER_OGN_NODE()

Role-Based Attribute Access

Here is a subset of the generated role-based attributes from the database. It contains color attributes, a matrix attribute, and a timecode attribute. Notice how the underlying data types of the attributes are provided, again with the ability to cast to different interface classes with the same memory layout.

Database Function

Returned Type

inputs.a_color3d()

const GfVec3d&

inputs.a_color4f()

const GfVec4f&

inputs.a_frame()

const GfMatrix4d&

inputs.a_timecode()

const double&

outputs.a_color3d()

GfVec3d&

outputs.a_color4f()

GfVec4f&

outputs.a_frame()

GfMatrix4d&

outputs.a_timecode()

double&

The full set of corresponding data types can be found in omni.graph.docs.ogn_attribute_roles.

This role information is available on all attribute interfaces through the role() method. For example you can find that the first attribute is a color by making this check:

static bool compute(OgnTutorialRoleDataDatabase& db)
{
    if (db.inputs.a_color3d.role == eColor )
    {
        processValueAsAColor( db.inputs.a_color3d() );
    }
}