- 1. Foreword
- 2. Introduction
- 3. Concepts
- 3.1. Graphs
- 3.2. Nodes and Sockets
- 3.3. Types
- 3.4. Custom Events
- 3.5. Custom Variables
- 3.6. Node Types
- 3.6.1. Math Nodes
- 3.6.1.1. Constants
- 3.6.1.2. Arithmetic Nodes
- 3.6.1.2.1. Absolute Value
- 3.6.1.2.2. Sign
- 3.6.1.2.3. Truncate
- 3.6.1.2.4. Floor
- 3.6.1.2.5. Ceil
- 3.6.1.2.6. Fraction
- 3.6.1.2.7. Negation
- 3.6.1.2.8. Addition
- 3.6.1.2.9. Subtraction
- 3.6.1.2.10. Multiplication
- 3.6.1.2.11. Division
- 3.6.1.2.12. Remainder
- 3.6.1.2.13. Minimum
- 3.6.1.2.14. Maximum
- 3.6.1.2.15. Clamp
- 3.6.1.2.16. Saturate
- 3.6.1.2.17. Interpolate
- 3.6.1.3. Comparison Nodes
- 3.6.1.4. Special Nodes
- 3.6.1.5. Angle and Trigonometry Nodes
- 3.6.1.6. Hyperbolic Nodes
- 3.6.1.7. Exponential Nodes
- 3.6.1.8. Vector Nodes
- 3.6.1.9. Matrix Nodes
- 3.6.1.10. Integer Arithmetic Nodes
- 3.6.1.11. Integer Comparison Nodes
- 3.6.1.12. Integer Bitwise Nodes
- 3.6.1.13. Boolean Arithmetic Nodes
- 3.6.2. Type Conversion Nodes
- 3.6.3. Control Flow Nodes
- 3.6.4. State Manipulation Nodes
- 3.6.5. Event Nodes
- 3.6.1. Math Nodes
- 3.7. Extending glTF Object Model
- 4. JSON Syntax
Note
|
Note
Khronos posts the AsciiDoc source of the glTF specification to enable community feedback and remixing under CC-BY 4.0. Published versions of the Specification are located in the glTF Registry. |
Copyright 2013-2023 The Khronos Group Inc.
This specification is protected by copyright laws and contains material proprietary to Khronos. Except as described by these terms, it or any components may not be reproduced, republished, distributed, transmitted, displayed, broadcast, or otherwise exploited in any manner without the express prior written permission of Khronos.
This specification has been created under the Khronos Intellectual Property Rights Policy, which is Attachment A of the Khronos Group Membership Agreement available at https://www.khronos.org/files/member_agreement.pdf. Khronos grants a conditional copyright license to use and reproduce the unmodified specification for any purpose, without fee or royalty, EXCEPT no licenses to any patent, trademark or other intellectual property rights are granted under these terms. Parties desiring to implement the specification and make use of Khronos trademarks in relation to that implementation, and receive reciprocal patent license protection under the Khronos IP Policy must become Adopters under the process defined by Khronos for this specification; see https://www.khronos.org/conformance/adopters/file-format-adopter-program.
Some parts of this Specification are non-normative through being explicitly identified as purely informative, and do not define requirements necessary for compliance and so are outside the Scope of this Specification.
Where this Specification includes normative references to external documents, only the specifically identified sections and functionality of those external documents are in Scope. Requirements defined by external documents not created by Khronos may contain contributions from non-members of Khronos not covered by the Khronos Intellectual Property Rights Policy.
Khronos makes no, and expressly disclaims any, representations or warranties, express or implied, regarding this specification, including, without limitation: merchantability, fitness for a particular purpose, non-infringement of any intellectual property, correctness, accuracy, completeness, timeliness, and reliability. Under no circumstances will Khronos, or any of its Promoters, Contributors or Members, or their respective partners, officers, directors, employees, agents or representatives be liable for any damages, whether direct, indirect, special or consequential damages for lost revenues, lost profits, or otherwise, arising from or in connection with these materials.
Khronos® and Vulkan® are registered trademarks, and ANARI™, WebGL™, glTF™, NNEF™, OpenVX™, SPIR™, SPIR‑V™, SYCL™, OpenVG™ and 3D Commerce™ are trademarks of The Khronos Group Inc. OpenXR™ is a trademark owned by The Khronos Group Inc. and is registered as a trademark in China, the European Union, Japan and the United Kingdom. OpenCL™ is a trademark of Apple Inc. and OpenGL® is a registered trademark and the OpenGL ES™ and OpenGL SC™ logos are trademarks of Hewlett Packard Enterprise used under license by Khronos. ASTC is a trademark of ARM Holdings PLC. All other product names, trademarks, and/or company names are used solely for identification and belong to their respective owners.
This document, referred to as the “glTF Interactivity Extension Specification” or just the “Specification” hereafter, describes the KHR_interactivity
glTF extension.
This extension aims to enhance glTF 2.0 by adding the ability to encode behavior and interactivity in 3D assets.
Note
|
Note
This specification is for single user experiences only and does not deal with any of the complexity involved in multi-user networked experiences. |
The glTF Interactivity Extension Specification is intended for use by both implementers of the asset exporters or converters (e.g., digital content creation tools) and application developers seeking to import or load interactive glTF assets, forming a basis for interoperability between these parties.
Specification text can address either party; typically, the intended audience can be inferred from context, though some sections are defined to address only one of these parties.
Any requirements, prohibitions, recommendations, or options defined by normative terminology are imposed only on the audience of that text.
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in BCP 14.
These key words are highlighted in the specification for clarity.
References to external documents are considered normative if the Specification uses any of the normative terms defined in this section to refer to them or their requirements, either as a whole or in part.
Some language in the specification is purely informative, intended to give background or suggestions to implementers or developers.
If an entire chapter or section contains only informative language, its title is suffixed with “(Informative)”. If not designated as informative, all chapters, sections, and appendices in this document are normative.
All Notes, Implementation notes, and Examples are purely informative.
The following documents are referenced by normative sections of the specification:
-
Bradner, S., Key words for use in RFCs to Indicate Requirement Levels, BCP 14, RFC 2119, March 1997. Leiba, B., Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words, BCP 14, RFC 8174, May 2017. https://www.rfc-editor.org/info/bcp14
-
ISO/IEC 60559 Floating-point arithmetic https://www.iso.org/standard/80985.html
-
ECMA-262 ECMAScript® Language Specification https://www.ecma-international.org/publications-and-standards/standards/ecma-262/
glTF 2.0 assets are widely used in various industries, including automotive, e-commerce, and gaming. There is a growing demand for adding logic and behavior to glTF assets, particularly in the metaverse. This extension aims to fulfill this demand by providing a portable, easily implementable, safe, and visually accessible solution for adding behavior to glTF assets. The extension is inspired by visual scripting features of leading game engines and aims to deliver a minimum meaningful and extensible feature set.
A behavior graph is a series of interconnected nodes that represent behaviors and interactions in a 3D asset. It can respond to events and cause changes in the asset’s appearance and behavior.
Behavior graphs offer a flexible and multi-functional approach to encoding behavior, making them useful for various applications. For instance, they can be used to create smart assets with behavior and interactions, AR experiences with user interactions, and immersive game levels with dynamic assets and objectives.
Behavior graphs are not designed to handle UI presentation or arbitrary scripting. Creating a 3D UI using behavior graphs would be complex, not portable, and not accessible. Similarly, arbitrary scripting is challenging to make safe, portable across platforms, and has a vast surface area.
Behavior graphs and trigger-action lists are the two common models for representing and executing behaviors in the digital world. Common 3D experience commerce tools use trigger-action lists, while behavior graphs are typically used by high-end game engines. In this section, we will explore the differences and similarities between these two models, and explain why glTF chose to adopt behavior graphs.
Behavior graphs and trigger-action lists share common features, such as being safe and sandboxed, offering limited execution models controlled by the viewer, and both supporting the “trigger” and “action” node categories. However, there are also significant differences between the two models. Trigger-action lists lack “Queries”, “Logic”, and “Control Flow” nodes, meaning that sophisticated behavior based on queries, logic, or control flow branches is not possible. This lack of functionality greatly affects the ability to create complex behavior and control structures and rules out the implementation of advanced control flow structures in the future.
On the other hand, behavior graphs are a superset of trigger-action lists, meaning that the former can support everything that trigger-action lists can, and more. Behavior graphs support “Queries”, “Logic” and “Control Flow” nodes, making them more expressive and capable of creating more sophisticated behaviors. This makes behavior graphs the preferred method of choice for high-end game engines, as it offers an identical safety model as trigger-action lists while being more expressive.
The execution model and node choices for this extension mean that it is Turing-complete. This means that an implementation of this can execute any computation and it is also hard to predict if it will run forever (e.g. halt or not.)
While this may present security implications, it is not a major hindrance and can be safely mitigated so that any implementation does not become susceptible to denial of services by badly behaving behavior graphs, whether intentional or not.
The main way to mitigate the risk of non-halting behavior graphs is to limit the amount of time given to them for execution, both in terms of individual time slice as well as overall execution time.
There will be limitations in engines and devices to such as:
-
Number of nodes in the graph
-
Number of variables
-
Number of custom events
-
Number of concurrent pending events/async nodes
-
Number of nodes executed per time slice
-
Speed of graph execution
These limitations are not defined in this specification.
A behavior graph is a JSON object containing nodes. It MAY also contain custom variables and custom events.
Behavior graphs are directed graphs with no directed cycles.
A node is a JSON object, which represents an executable item. Each node is defined by its type and a set of sockets. There are four kinds of sockets.
Output value sockets represent data initialized by the node or produced during its execution. For example, it could be results of math operations or parts of the node’s internal state. Accessing these sockets either triggers computing the return value on the fly by executing the node or returns a value based on the node’s internal state. Exact behavior depends on the node’s type.
Input value sockets represent data accessed during the node’s execution. For example, it could be arguments of math operations or execution parameters such as iteration count for loop nodes or duration for time-related nodes. These sockets MUST either be given a static value in the node object or connected to an output value socket of a different node. The node MAY access its input value sockets multiple times during the execution. The runtime MUST guarantee that all input value sockets have defined values when the node execution starts.
Output flow sockets represent “function pointers” that the node will call to advance the graph execution. For example, bodies and branches of flow control nodes are output flow sockets that drive further execution when certain condition are fulfilled. Output flow sockets MAY be unconnected; in such a case graph execution proceeds as if such sockets are no-ops.
Input flow sockets represent “methods” that could be called on the node. For example, flow control nodes (such as loops and conditions) usually have an in
input flow socket that starts node’s execution. Additional operations MAY also be defined such as reset
for nodes having an internal state.
Nodes MAY be configurable through static properties collectively called “node’s configuration” that MAY affect the node’s behavior and the number of its sockets, such as the number of cases for a switch-case control flow node.
Input and output value sockets have associated data types, e.g., floats, integers, booleans, etc.
Node’s sockets and configurations are defined by its type. Node types follow domain/operation
naming pattern.
A node is executed when its input flow socket is reached by or when one of its output value sockets is requested by another node. Usually, the node executes its dependencies (if any), its own logic, and any number (including zero) of outgoing flow sockets.
All value sockets and configurations are strictly typed.
Implementations of this extension MUST support the following type signatures.
The following types are supported for value sockets.
- bool
-
a boolean value
- float
-
a double precision IEEE-754 floating-point scalar value
- float2
-
a two-component vector of float values
- float3
-
a three-component vector of float values
- float4
-
a four-component vector of float values
- float4x4
-
a 4x4 matrix of float values
- int
-
a two’s complement 32-bit signed integer scalar value
A behavior graph MAY define custom events for interacting with external execution environments and/or creating asynchronous loops. Although semantics of custom events is application-specific, their declarations MUST include value socket type information to ensure graph’s type safety.
A behavior graph MAY define custom variables. A variable MAY be declared simultaneously with its initial value, otherwise the variable MUST be initialized to the type-specific default.
Custom variables MUST retain their values until the graph execution is terminated.
In this section, floatN
is a placeholder for any of float
, float2
, float3
, float4
, or float4x4
types. All value sockets of floatN
types have the same type within a node.
Type |
|
Ratio of a circle’s circumference to its diameter |
---|---|---|
Output value sockets |
|
3.141592653589793 |
These all operate component-wise. The description is per component.
If any input value is NaN, the output value is also NaN.
Type |
|
Absolute value operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\(\begin{cases} -a & \text{if } a \lt 0 \\ 0 & \text{if } a = 0 \\ a & \text{if } a \gt 0 \end{cases}\) |
Type |
|
Sign operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\(\begin{cases} -1 & \text{if } a \lt 0 \\ a & \text{if } a = \pm0 \\ +1 & \text{if } a \gt 0 \end{cases}\) |
Type |
|
Truncate operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
Integer value equal to the nearest integer to \$a\$ whose absolute value is not larger than the absolute value of \$a\$ |
If the argument is infinity, it is returned unchanged.
Type |
|
Floor operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\$floor(a)\$, value equal to the nearest integer that is less than or equal to \$a\$ |
If the argument is infinity, it is returned unchanged.
Type |
|
Ceil operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\$ceil(a)\$, value equal to the nearest integer that is greater than or equal to \$a\$ |
If the argument is infinity, it is returned unchanged.
Type |
|
Fractional operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\$a - floor(a)\$ |
Type |
|
Negation operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\$-a\$ |
Type |
|
Addition operation |
---|---|---|
Input value sockets |
|
First addend |
|
Second addend |
|
Output value sockets |
|
Sum, \$a + b\$ |
Type |
|
Subtraction operation |
---|---|---|
Input value sockets |
|
Minuend |
|
Subtrahend |
|
Output value sockets |
|
Difference, \$a - b\$ |
Type |
|
Multiplication operation |
---|---|---|
Input value sockets |
|
First factor |
|
Second factor |
|
Output value sockets |
|
Product, \$a * b\$ |
Note
|
Note
For |
Type |
|
Division operation |
---|---|---|
Input value sockets |
|
Dividend |
|
Divisor |
|
Output value sockets |
|
Quotient, \$a / b\$ |
Type |
|
Remainder operation |
---|---|---|
Input value sockets |
|
Dividend |
|
Divisor |
|
Output value sockets |
|
\(\begin{cases} \mathit{NaN} & \text{if } a = \pm \infty \text{ or } b = \pm 0 \\ a & \text{if } a \ne \pm \infty \text{ and } b = \pm \infty \\ a - (b \cdot trunc(\frac{a}{b})) & \text{otherwise} \end{cases}\) |
Type |
|
Minimum operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
Smallest of the arguments |
For the purposes of this node, negative zero is less than positive zero.
Note
|
Note
This is implementable in ECMAScript via the following expression: Math.min(a, b) |
Type |
|
Maximum operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
Largest of the arguments |
For the purposes of this node, negative zero is less than positive zero.
Note
|
Note
This is implementable in ECMAScript via the following expression: Math.max(a, b) |
Type |
|
Clamp operation |
---|---|---|
Input value sockets |
|
Value to clamp |
|
First boundary |
|
|
Second boundary |
|
Output value sockets |
|
\(min(max(a, min(b, c)), max(b, c))\) |
This node relies on math/min
and math/max
nodes defined above.
Note
|
Note
This operation correctly handles a case when \$b\$ is greater than \$c\$. |
Type |
|
Saturate operation |
---|---|---|
Input value sockets |
|
Value to saturate |
Output value sockets |
|
\(min(max(a, 0), 1)\) |
If any input value is NaN, the output value is false.
Type |
|
Equality operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
True if the input arguments are equal, per-component; false otherwise |
Type |
|
Less than operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
True if \$a < b\$; false otherwise |
Type |
|
Less than or equal to operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
True if \$a <= b\$; false otherwise |
Type |
|
Greater than operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
True if \$a > b\$; false otherwise |
Type |
|
Not a Number check operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
True if \$a\$ is NaN; false otherwise |
Type |
|
Infinity check operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
True if \$a\$ is positive or negative infinity; false otherwise |
Type |
|
Conditional selection operation |
---|---|---|
Input value sockets |
|
Value selecting the value returned |
|
Positive selection option |
|
|
Negative selection option |
|
Output value sockets |
|
\$a\$ if the the |
The type T
represents any type. It MUST be the same for the output value socket and the input value sockets \$a\$ and \$b\$, otherwise the node is invalid.
Node parameters specified as angle are assumed to be in units of radians.
These all operate component-wise. The description is per component.
If any input value is NaN, the output value is also NaN.
Type |
|
Converts degrees to radians |
---|---|---|
Input value sockets |
|
Value in degrees |
Output value sockets |
|
\$a * pi / 180\$ |
Type |
|
Converts radians to degrees |
---|---|---|
Input value sockets |
|
Value in radians |
Output value sockets |
|
\$a * 180 / pi\$ |
Type |
|
Sine function |
---|---|---|
Input value sockets |
|
Angle |
Output value sockets |
|
\(\begin{cases} sin(a) & \text{if } a \ne \pm\infty \\ \mathit{NaN} & \text{if } a = \pm\infty \end{cases}\) |
Type |
|
Cosine function |
---|---|---|
Input value sockets |
|
Angle |
Output value sockets |
|
\(\begin{cases} cos(a) & \text{if } a \ne \pm\infty \\ \mathit{NaN} & \text{if } a = \pm\infty \end{cases}\) |
Type |
|
Tangent function |
---|---|---|
Input value sockets |
|
Angle |
Output value sockets |
|
\(\begin{cases} tan(a) & \text{if } a \ne \pm\infty \\ \mathit{NaN} & \text{if } a = \pm\infty \end{cases}\) |
Note
|
Note
Since \$a\$ cannot exactly represent \(\pm\frac{\pi}{2}\), this function does not return infinity. The closest representable argument values would likely produce \(\pm16331239353195370\). |
Type |
|
Arcsine function |
---|---|---|
Input value sockets |
|
Sine value |
Output value sockets |
|
\(\begin{cases} arcsin(a) \in [-\frac{\pi}{2}; \frac{\pi}{2}] & \text{if } |a| \le 1 \\ \mathit{NaN} & \text{if } |a| \gt 1 \end{cases}\) |
Type |
|
Arccosine function |
---|---|---|
Input value sockets |
|
Cosine value |
Output value sockets |
|
\(\begin{cases} arccos(a) \in [0; \pi] & \text{if } |a| \le 1 \\ \mathit{NaN} & \text{if } |a| \gt 1 \end{cases}\) |
Type |
|
Arctangent function |
---|---|---|
Input value sockets |
|
Tangent value |
Output value sockets |
|
\(arctan(a) \in [-\frac{\pi}{2}; \frac{\pi}{2}]\) |
Type |
|
Arctangent 2 function |
---|---|---|
Input value sockets |
|
Y coordinate |
|
X coordinate |
|
Output value sockets |
|
Angle between the positive X-axis and the vector from the \$(0, 0)\$ origin to the \$(X, Y)\$ point on a 2D plane |
These all operate component-wise. The description is per component.
If any input value is NaN, the output value is also NaN.
Type |
|
Hyperbolic sine function |
---|---|---|
Input value sockets |
|
Hyperbolic angle value |
Output value sockets |
|
\(\dfrac{e^a-e^{-a}}{2}\) |
Type |
|
Hyperbolic cosine function |
---|---|---|
Input value sockets |
|
Hyperbolic angle value |
Output value sockets |
|
\(\dfrac{e^a+e^{-a}}{2}\) |
Type |
|
Hyperbolic tangent function |
---|---|---|
Input value sockets |
|
Hyperbolic angle value |
Output value sockets |
|
\(\dfrac{e^a-e^{-a}}{e^a+e^{-a}}\) |
Type |
|
Inverse hyperbolic sine function |
---|---|---|
Input value sockets |
|
Hyperbolic sine value |
Output value sockets |
|
\(ln(a+\sqrt{a^2+1})\) |
Type |
|
Inverse hyperbolic cosine function |
---|---|---|
Input value sockets |
|
Hyperbolic cosine value |
Output value sockets |
|
\(\begin{cases} ln(a+\sqrt{a^2-1}) & \text{if } a \ge 1 \\ \mathit{NaN} & \text{if } a \lt 1 \end{cases}\) |
Type |
|
Inverse hyperbolic tangent function |
---|---|---|
Input value sockets |
|
Hyperbolic tangent value |
Output value sockets |
|
\(\begin{cases} \dfrac{1}{2}ln\dfrac{1+a}{1-a} & \text{if } |a| \lt 1 \\ \pm\infty & \text{if } a = \pm1 \\ \mathit{NaN} & \text{if } |a| \gt 1 \end{cases}\) |
These all operate component-wise. The description is per component.
If any input value is NaN, the output value is also NaN.
Type |
|
Exponent function |
---|---|---|
Input value sockets |
|
Power value |
Output value sockets |
|
\$e^a\$ |
Type |
|
Natural logarithm function |
---|---|---|
Input value sockets |
|
Argument value |
Output value sockets |
|
\(\begin{cases} ln(a) & \text{if } a \gt 0 \\ -\infty & \text{if } a = 0 \\ \mathit{NaN} & \text{if } a \lt 0 \end{cases}\) |
Type |
|
Base-2 logarithm function |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\(\begin{cases} log_2(a) & \text{if } a \gt 0 \\ -\infty & \text{if } a = 0 \\ \mathit{NaN} & \text{if } a \lt 0 \end{cases}\) |
Type |
|
Base-10 logarithm function |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\(\begin{cases} log_{10}(a) & \text{if } a \gt 0 \\ -\infty & \text{if } a = 0 \\ \mathit{NaN} & \text{if } a \lt 0 \end{cases}\) |
Type |
|
Square root function |
---|---|---|
Input value sockets |
|
Radicand |
Output value sockets |
|
\(\begin{cases} \sqrt{a} & \text{if } a \ge 0 \\ \mathit{NaN} & \text{if } a \lt 0 \end{cases}\) |
Type |
|
Cube root function |
---|---|---|
Input value sockets |
|
Radicand |
Output value sockets |
|
\(\sqrt[3]{a}\) |
Type |
|
Power function |
---|---|---|
Input value sockets |
|
Base |
|
Exponent |
|
Output value sockets |
|
\$a^b\$ |
Zero and infinity argument values are handled according to the ECMA-262 standard.
If any input value is NaN, the output value is also NaN.
Type |
|
Vector length |
---|---|---|
Input value sockets |
|
Vector |
Output value sockets |
|
Length of \$a\$, e.g., \$sqrt(a_x^2 + a_y^2)\$ for |
Type |
|
Vector normalization |
---|---|---|
Input value sockets |
|
Vector |
Output value sockets |
|
Vector in the same direction as \$a\$ but with a unit length, e.g., \$a/sqrt(a_x^2 + a_y^2)\$ for |
Type |
|
Dot product |
---|---|---|
Input value sockets |
|
First vector |
|
Second vector of the same type as \$a\$ |
|
Output value sockets |
|
Sum of per-component products of \$a\$ and \$b\$, e.g., \$a_x * b_x + a_y * b_y\$ for |
Type |
|
Cross product |
---|---|---|
Input value sockets |
|
Vector |
|
Vector |
|
Output value sockets |
|
Cross product of \$a\$ and \$b\$, i.e., \$(a_y * b_z - a_z * b_y, a_z * b_x - a_x * b_z, a_x * b_y - a_y * b_x)\$ |
Type |
|
2D rotation |
---|---|---|
Input value sockets |
|
Vector to rotate |
|
Angle in radians |
|
Output value sockets |
|
Vector \$a\$ rotated counter-clockwise by \$b\$ |
Type |
|
3D rotation |
---|---|---|
Input value sockets |
|
Vector to rotate |
|
Vector representing an axis to rotate around |
|
|
Angle in radians |
|
Output value sockets |
|
Vector \$a\$ rotated around vector \$b\$ counter-clockwise by \$c\$ |
If the vector \$b\$ is not unit, rotation results may be undefined.
Type |
|
Vector transformation |
---|---|---|
Input value sockets |
|
Vector to transform |
|
Transformation matrix |
|
Output value sockets |
|
Transformed vector |
Type |
|
Combine two floats into a two-component vector |
---|---|---|
Input value sockets |
|
First component |
|
Second component |
|
Output value sockets |
|
Vector |
Type |
|
Combine three floats into a three-component vector |
---|---|---|
Input value sockets |
|
First component |
|
Second component |
|
|
Third component |
|
Output value sockets |
|
Vector |
Type |
|
Combine four floats into a four-component vector |
---|---|---|
Input value sockets |
|
First component |
|
Second component |
|
|
Third component |
|
|
Fourth component |
|
Output value sockets |
|
Vector |
Type |
|
Extract two floats from a two-component vector |
---|---|---|
Input value sockets |
|
Vector |
Output value sockets |
|
First component |
|
Second component |
Type |
|
Extract three floats from a three-component vector |
---|---|---|
Input value sockets |
|
Vector |
Output value sockets |
|
First component |
|
Second component |
|
|
Third component |
Type |
|
Extract four floats from a four-component vector |
---|---|---|
Input value sockets |
|
Vector |
Output value sockets |
|
First component |
|
Second component |
|
|
Third component |
|
|
Fourth component |
Type |
|
Transpose operation |
---|---|---|
Input value sockets |
|
Matrix to transpose |
Output value sockets |
|
Matrix that is the transpose of \$a\$ |
Type |
|
Dot product |
---|---|---|
Input value sockets |
|
Matrix |
Output value sockets |
|
Determinant of \$a\$ |
Type |
|
Inverse operation |
---|---|---|
Input value sockets |
|
Matrix to inverse |
Output value sockets |
|
Matrix that is the inverse of \$a\$ |
Type |
|
Matrix multiplication operation |
---|---|---|
Input value sockets |
|
First matrix |
|
Second matrix |
|
Output value sockets |
|
Matrix product |
Type |
|
Combine 16 floats into a 4x4 matrix |
---|---|---|
Input value sockets |
|
First row, first column element |
|
Second row, first column element |
|
|
Third row, first column element |
|
|
Fourth row, first column element |
|
|
First row, second column element |
|
|
Second row, second column element |
|
|
Third row, second column element |
|
|
Fourth row, second column element |
|
|
First row, third column element |
|
|
Second row, third column element |
|
|
Third row, third column element |
|
|
Fourth row, third column element |
|
|
First row, fourth column element |
|
|
Second row, fourth column element |
|
|
Third row, fourth column element |
|
|
Fourth row, fourth column element |
|
Output value sockets |
|
Matrix |
Type |
|
Extract 16 floats from a 4x4 matrix |
---|---|---|
Input value sockets |
|
Matrix |
Output value sockets |
|
First row, first column element |
|
Second row, first column element |
|
|
Third row, first column element |
|
|
Fourth row, first column element |
|
|
First row, second column element |
|
|
Second row, second column element |
|
|
Third row, second column element |
|
|
Fourth row, second column element |
|
|
First row, third column element |
|
|
Second row, third column element |
|
|
Third row, third column element |
|
|
Fourth row, third column element |
|
|
First row, fourth column element |
|
|
Second row, fourth column element |
|
|
Third row, fourth column element |
|
|
Fourth row, fourth column element |
All inputs to these nodes are two’s complement 32-bit signed integers.
Type |
|
Absolute value operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\(\begin{cases} -a & \text{if } a \lt 0 \\ a & \text{if } a \ge 0 \end{cases}\) |
As this node is defined in terms of the negation node (see below), the absolute value of -2147483648
is -2147483648
.
Note
|
Note
This is implementable in ECMAScript via the following expression: Math.abs(a)|0 |
Type |
|
Sign operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\(\begin{cases} -1 & \text{if } a \lt 0 \\ 0 & \text{if } a = 0 \\ +1 & \text{if } a \gt 0 \end{cases}\) |
Type |
|
Negation operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\$-a\$ |
Negating -2147483648
MUST return -2147483648
.
Note
|
Note
This is implementable in ECMAScript via the following expression: (-a)|0 |
Type |
|
Addition operation |
---|---|---|
Input value sockets |
|
First addend |
|
Second addend |
|
Output value sockets |
|
Sum, \$a + b\$ |
Arithmetic overflow MUST wrap around, for example:
2147483647 + 1 == -2147483648
Note
|
Note
This is implementable in ECMAScript via the following expression: (a + b)|0 |
Type |
|
Subtraction operation |
---|---|---|
Input value sockets |
|
Minuend |
|
Subtrahend |
|
Output value sockets |
|
Difference, \$a - b\$ |
Arithmetic overflow MUST wrap around, for example:
-2147483648 - 1 == 2147483647
Note
|
Note
This is implementable in ECMAScript via the following expression: (a - b)|0 |
Type |
|
Multiplication operation |
---|---|---|
Input value sockets |
|
First factor |
|
Second factor |
|
Output value sockets |
|
Product, \$a * b\$ |
Arithmetic overflow MUST wrap around, for example:
2147483647 * 2147483647 == 1
-2147483648 * (-1) == -2147483648
Note
|
Note
This is implementable in ECMAScript via the following expression: Math.imul(a, b) |
Type |
|
Division operation |
---|---|---|
Input value sockets |
|
Dividend |
|
Divisor |
|
Output value sockets |
|
\(\begin{cases} \frac{a}{b} & \text{if } b \ne 0 \\ 0 & \text{if } b = 0 \end{cases}\) |
The quotient MUST be truncated towards zero.
Arithmetic overflow is defined as follows:
-2147483648 / (-1) == -2147483648
Note
|
Note
This is implementable in ECMAScript via the following expression: (a / b)|0 |
Type |
|
Remainder operation |
---|---|---|
Input value sockets |
|
Dividend |
|
Divisor |
|
Output value sockets |
|
\(\begin{cases} a - (b \cdot trunc(\frac{a}{b})) & \text{if } b \ne 0 \\ 0 & \text{if } b = 0 \end{cases}\) |
Note
|
Note
This is implementable in ECMAScript via the following expression: (a % b)|0 |
Type |
|
Minimum operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
Smallest of the arguments |
Type |
|
Maximum operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
Largest of the arguments |
All inputs to these nodes are two’s complement 32-bit signed integers.
Type |
|
Equality operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
True if the input arguments are equal; false otherwise |
Type |
|
Less than operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
True if \$a < b\$; false otherwise |
Type |
|
Less than or equal to operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
True if \$a <= b\$; false otherwise |
Type |
|
Greater than operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
True if \$a > b\$; false otherwise |
All inputs to these nodes are two’s complement 32-bit signed integers.
Type |
|
Bitwise NOT operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
|
Type |
|
Bitwise AND operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
|
Type |
|
Bitwise OR operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
|
Type |
|
Bitwise XOR operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
|
Type |
|
Right Shift |
---|---|---|
Input value sockets |
|
Value to be shifted |
|
Number of bits to shift by |
|
Output value sockets |
|
|
Only the lowest 5 bits of \$b\$ are considered, i.e., its effective range is [0, 31]. The result MUST be truncated to 32 bits and interpreted as a two’s complement signed integer. The most significant bit of \$a\$ MUST be propagated.
Type |
|
Left Shift |
---|---|---|
Input value sockets |
|
Value to be shifted |
|
Number of bits to shift by |
|
Output value sockets |
|
|
Only the lowest 5 bits of \$b\$ are considered, i.e., its effective range is [0, 31]. The result MUST be truncated to 32 bits and interpreted as a two’s complement signed integer.
Type |
|
Count leading zeros operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
Number of leading zero bits in \$a\$ |
If \$a\$ is 0, the operation returns 32; if \$a\$ is negative, the operation returns 0.
Note
|
Note
This is implementable in ECMAScript via the following expression: Math.clz32(a) |
Type |
|
Count trailing zeros operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
Number of trailing zero bits in \$a\$ |
If \$a\$ is 0, the operation returns 32.
Note
|
Note
This is implementable in ECMAScript via the following expression: a ? (31 - Math.clz32(a & -a)) : 32; |
Type |
|
Equality operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
True if and only if both \$a\$ and \$b\$ have the same value; false otherwise |
Type |
|
Boolean NOT operation |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
True if \$a\$ is false; false if \$a\$ is true |
Type |
|
Boolean AND operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
True if and only if both \$a\$ and \$b\$ are true; false otherwise |
Type |
|
Boolean OR operation |
---|---|---|
Input value sockets |
|
First argument |
|
Second argument |
|
Output value sockets |
|
False if and only if both \$a\$ and \$b\$ are false; true otherwise |
Type |
|
Boolean to integer conversion |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
\$1\$ if \$a\$ is true; \$0\$ otherwise |
Note
|
Note
This is implementable in ECMAScript via the following expression: a|0 |
Type |
|
Integer to boolean conversion |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
True if \$a\$ is not equal to zero; false otherwise |
Note
|
Note
This is implementable in ECMAScript via the following expression: !!a |
Type |
|
Integer to float conversion |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
Floating-point value equal to \$a\$ |
Since floating-point values have double precision, this conversion MUST be lossless.
This operation MUST NOT produce negative zero.
Note
|
Note
This operation is no-op in ECMAScript. |
Type |
|
Float to boolean conversion |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
False if \$a\$ is NaN or equal to zero; true otherwise |
Note
|
Note
This is implementable in ECMAScript via the following expression: !!a |
Type |
|
Float to integer conversion |
---|---|---|
Input value sockets |
|
Argument |
Output value sockets |
|
Integer value produced as described below |
-
If the \$a\$ input value is zero, infinite, or NaN, return zero and skip the next steps.
-
Let \$t\$ be \$a\$ with its fractional part removed by rounding towards zero.
-
Let \$k\$ be a value of the same sign as \$t\$ such that its absolute value is less than \$2^32\$ and \$k\$ is equal to \$t - q * 2^32\$ for some integer \$q\$.
-
If \$k\$ is greater than or equal to \$2^31\$, return \$k - 2^32\$; otherwise return \$k\$.
Note
|
Note
This is implementable in ECMAScript via the following expression: a|0 |
Type |
|
Sequentially activate all connected output flows |
---|---|---|
Input flow sockets |
|
The entry flow into this node |
Output flow sockets |
|
One or more output flows; their names are purely informative |
This node has no internal state.
When the in
input flow is activated, all output flows are activated one by one in the order they are defined in JSON.
Type |
|
Branch the execution flow based on a condition |
---|---|---|
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
Value selecting the branch taken |
Output flow sockets |
|
The flow to be activated if the |
|
The flow to be activated if the |
This node has no internal state.
The condition
input value is evaluated each time the node is executed.
Type |
|
Conditionally route the execution flow to one of the outputs |
---|---|---|
Configuration |
|
The cases on which to perform the switch on; values MUST be unique 32-bit signed integers; at least one value MUST be present |
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
The value on which the switch operates |
Output flow sockets |
|
The output flow, |
|
The output flow used when the |
The node has one or more <case>
output flow sockets named as decimal integers equal to the elements of the cases
configuration array. Encoded as JSON strings, these output flow socket names MUST contain only decimal integers (ASCII characters 0x30 … 0x39
) and optionally a leading minus sign (ASCII character 0x2D
); other characters and leading zeros are not allowed.
For example, if the cases
configuration array is [-1, 0, 1]
, the output socket names are exactly "-1"
, "0"
, and "1"
.
This node has no internal state.
When the in
input flow is activated:
-
Evaluate the
selection
input value. -
If the
cases
configuration array does not contain theselection
input value:-
activate the
default
output flow if it is connected.
-
-
If the
cases
configuration array contains theselection
input value:-
activate the output flow named
<selection>
if it is connected.
-
Type |
|
Repeatedly activate the output flow based on a condition |
---|---|---|
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
Loop condition |
Output flow sockets |
|
The flow to be activated while the |
|
The flow to be activated once the |
This node has no internal state.
When the in
input flow is activated:
-
Evaluate the
condition
. Thecondition
MUST NOT statically evaluate to true, otherwise the node is invalid. -
If the
condition
is true,-
activate the
loopBody
output flow; -
after completion of the
loopBody
output flow, goto step 1.
-
-
If the
condition
is false,-
activate the
completed
output flow.
-
Type |
|
Repeatedly activate the output flow based on an incrementing index value |
---|---|---|
Configuration |
|
The index value before the loop starts |
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
The start index of the loop |
|
The end index of the loop |
|
Output flow sockets |
|
The flow to be activated if the |
|
The flow to be activated if the |
|
Output value sockets |
|
The current index value if the node has ever been activated, |
The internal state of this node consists of one 32-bit signed integer value index
initialized to initialIndex
.
When the in
input flow is activated:
-
Evaluate the
startIndex
input value. -
Set
index
tostartIndex
. -
Evaluate the
endIndex
input value. -
If
index
is less than theendIndex
input value,-
activate the
loopBody
output flow; -
after completion of the
loopBody
output flow, increment theindex
value by 1; -
goto step 3.
-
-
If the
index
value is greater than or equal to theendIndex
input value,-
activate the
completed
output flow.
-
Type |
|
Activate the output flow no more than N times |
---|---|---|
Input flow sockets |
|
The entry flow into this node |
|
When this flow is activated, the |
|
Input value sockets |
|
Maximum number of times the |
Output flow sockets |
|
The flow to be activated if the |
Output value sockets |
|
The current execution count |
The internal state of this node consists of one 32-bit signed integer value currentCount
initialized to 0.
When the reset
input flow is activated:
-
Reset
currentCount
to 0.
When the in
input flow is activated:
-
Evaluate the
n
input value. -
If
currentCount
is less thann
,-
increment
currentCount
by 1; -
activate the
out
output flow.
-
Type |
|
Route the execution flow to one of the outputs sequentially or randomly |
---|---|---|
Configuration |
|
If set to true, output flows are executed in random order, picking a random not used output flow each time until all are done |
|
If set to true, the outputs will repeat in a loop continuously after all are done |
|
Input flow sockets |
|
The entry flow into this node |
|
When this flow is activated, the |
|
Output flow sockets |
|
One or more output flows; their names are purely informative |
Output value sockets |
|
The index of the last used output; |
The internal state of this node consists of one 32-bit signed integer value lastIndex
initialized to -1 and an array of booleans with all values initialized to false representing used output flows. The size of the boolean array is equal to the number of output flows.
The output flows are ordered as they are defined in JSON.
When the reset
input flow is activated:
-
Reset the
lastIndex
value to -1. -
Mark all output flows as not used in the boolean array.
When the in
input flow is activated:
-
If the
isRandom
configuration value is false,-
let
i
be the smallest not used output flow index according to the boolean array or -1 if all output flows are marked as used.
-
-
If the
isRandom
configuration value is true,-
let
i
be a random not used output flow index according to the boolean array or -1 if all output flows are marked as used.
-
-
If
i
is greater than -1,-
mark the output flow with index
i
as used in the boolean array; -
set the
lastIndex
value toi
; -
activate the output flow with index
i
.
-
-
If
i
is equal to -1 and theisLoop
configuration value is true,-
mark all output flows as not used in the boolean array;
-
if the
isRandom
configuration value is false,-
set
i
to 0;
-
-
if the
isRandom
configuration value is true,-
set
i
to a random output flow index;
-
-
mark the output flow with index
i
as used in the boolean array; -
set the
lastIndex
value toi
; -
activate the output flow with index
i
.
-
When the isRandom
and isLoop
configuration values are true, the output flow activation order SHOULD be randomized on each loop iteration.
Type |
|
Activate the output flow when all input flows have been activated at least once. |
---|---|---|
Configuration |
|
The number of input flows, MUST be greater than 0 and less than or equal to 2147483647 |
Input flow sockets |
|
The |
|
When this flow is activated, all input flows are marked as unused |
|
Output flow sockets |
|
The flow to be activated after every input flow activation except the last missing input |
|
The flow to be activated when the last missing input flow is activated |
|
Output value sockets |
|
The number of not yet activated input flows |
The node has one or more input flow sockets named as sequential non-negative decimal integers depending on the inputFlows
configuration value. Encoded as JSON strings, these input flow socket names contain only decimal integers (ASCII characters 0x30 … 0x39
); other characters and leading zeros are not allowed.
For example, if inputFlows
is 3, the input socket names are "0"
, "1"
, and "2"
exactly.
The internal state of this node consists of one 32-bit signed integer value remainingInputs
initialized to the number of connected input flows not including the reset
input flow and a map of booleans with all values initialized to false representing used input flow sockets. The size of the boolean map is equal to the initial remainingInputs
value.
When the reset
input flow is activated:
-
Reset
remainingInputs
to the number of connected input flows not including thereset
input flow. -
Mark all connected input flows as not used in the boolean map.
When any of the <i>
input flows is activated:
-
If the
<i>
-th input flow is not marked as used in the boolean map:-
mark the
<i>
-th input flow as used in the boolean map. -
decrement the
remainingInputs
value by 1;
-
-
If the
remainingInputs
value is zero:-
activate the
completed
output flow.
-
-
If the
remainingInputs
value is not zero:-
activate the
out
output flow.
-
Type |
|
Activate the output flow unless it has been activated less than a certain time ago |
---|---|---|
Input flow sockets |
|
The entry flow into this node |
|
When this flow is activated, the output flow throttling state is reset |
|
Input value sockets |
|
The time, in seconds, to wait after an output flow activation before allowing subsequent output flow activations |
Output flow sockets |
|
The flow to be activated if the output flow is not currently throttled |
|
The flow to be activated if the |
|
Output value sockets |
|
The remaining throttling time, in seconds, at the moment of the last valid activation of the input flow or NaN if the input flow has never been activated with a valid |
The internal state of this node consists of an uninitialized timestamp value of an implementation-defined high-precision time type and a floating-point lastRemainingTime
value initialized to NaN.
When the reset
input flow is activated:
-
Reset the
lastRemainingTime
value to NaN.
When the in
input flow is activated:
-
Evaluate the
duration
input value. -
If the
duration
input value is NaN, infinite, negative, or not convertible into an implementation-specific time type used for the internal timestamp value,-
activate the
err
output flow and skip the next steps.
-
-
If the
lastRemainingTime
value is not NaN:-
Let
elapsed
be a non-negative difference, in seconds, between the timestamp and the current time. -
If the
duration
input value is less than or equal to theelapsed
value,-
set the timestamp value to the current time;
-
set the
lastRemainingTime
value to zero; -
activate the
out
output flow.
-
-
If the
duration
input value is greater than theelapsed
value,-
set the
lastRemainingTime
value to the positive difference, in seconds, between theduration
andelapsed
values.
-
-
-
If the
lastRemainingTime
value is NaN,-
set the timestamp value to the current time;
-
set the
lastRemainingTime
value to zero; -
activate the
out
output flow.
-
Type |
|
Schedule the output flow activation after a certain delay |
---|---|---|
Input flow sockets |
|
The entry flow into this node |
|
When this flow is activated, all delayed activations scheduled by this node are cancelled |
|
Input value sockets |
|
The duration, in seconds, to delay the |
Output value sockets |
|
The delay index assigned during the last successful node execution |
Output flow sockets |
|
The flow to be activated if the |
|
The flow to be activated if the |
|
|
The flow to be activated after the delay |
The internal state of this node consists of an integer lastDelayIndex
value initialized to -1 and a dynamic array of activation indices scheduled by the node. This array is initially empty and its maximum size is implementation-specific.
The internal state of an execution graph having one or more flow/setDelay
nodes includes a dynamic array of activation indices scheduled from all such nodes. This array is initially empty and its maximum size is implementation-specific.
Implementations MUST be aware of their effective limit on the maximum supported duration
input value to avoid any implicit behavior changes, e.g., due to numeric overflows; exceeding such value MUST lead to the err
output flow activation as described below.
When the in
input flow is activated:
-
Evaluate the
duration
input value. -
If the
duration
input value is NaN, infinite, negative, or not convertible into an implementation-specific time type,-
activate the
err
output flow and skip the next steps.
-
-
If scheduling a new activation exceeds any implementation-specific limit,
-
activate the
err
output flow and skip the next steps.
-
-
Let activationTime be an implementation-defined high-precision time value equal to the sum of the current time value and the
duration
input value converted to the same time type. -
If activationTime is not valid according to implementation-specific validation rules, e.g., it exceeds an internal threshold value,
-
activate the
err
output flow and skip the next steps.
-
-
Set
lastDelayIndex
to a positive value representing the delayed flow activation being scheduled. This value MUST be unique across all previous activations of allflow/setDelay
nodes of the graph. -
Push the value of
lastDelayIndex
to the graph and node arrays of activation indices. -
Schedule the following actions at the activationTime time:
-
Removal of the activation index value from both arrays of activation indices.
-
Activation of the
done
output flow.
-
-
Activate the
out
output flow.
When the cancel
input flow is activated:
-
Set the
lastDelayIndex
value to -1. -
For each activation index value in the node’s array of activation indices:
-
Remove this activation index value from the node’s and the graph’s arrays of activation indices.
-
Cancel the corresponding scheduled activation.
-
Type |
|
Cancel a previously scheduled output flow activation |
---|---|---|
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
The index value of the scheduled activation to be cancelled |
Output flow sockets |
|
The flow to be activated after executing this node |
This node has no internal state but its execution MAY affect internal states of other nodes and the graph.
When the in
input flow is activated:
-
Evaluate the
delayIndex
input value. -
Remove this activation index value from all arrays of activation indices if it exists.
-
Cancel the corresponding scheduled activation if it exists.
-
Activate the
out
output flow.
Non-positive or not existing delay index values MUST NOT cause any runtime errors.
Type |
|
Get a custom variable value |
---|---|---|
Configuration |
|
The custom variable index |
Output value sockets |
|
The custom variable value |
This node gets a custom variable value using the variable index provided by the variable
configuration value. The type T
is determined by the referenced variable. The variable index MUST be non-negative and less than the total number of custom variables, otherwise the node is invalid.
This node has no internal state.
Type |
|
Set a custom variable value |
---|---|---|
Configuration |
|
The custom variable index |
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
The new variable value |
Output flow sockets |
|
The flow to be activated after the value is set |
This node sets a custom variable value using the variable index provided by the variable
configuration value and the value
input value. The type T
is determined by the referenced variable. The variable index MUST be non-negative and less than the total number of custom variables, otherwise the node is invalid.
This node has no internal state.
When the in
input flow is activated:
-
Evaluate the
value
input value. -
Set the custom variable with the
variable
configuration value index to thevalue
input value. -
Activate the
out
output flow.
Type |
|
Get an object model property value |
---|---|---|
Configuration |
|
The JSON Pointer or JSON Pointer template |
Input value sockets |
|
Zero or more JSON Pointer template path substitutions to be evaluated at runtime; input value socket names correspond to the pointer’s path segments wrapped with curly braces ( |
Output value sockets |
|
The resolved property value |
|
True if the property value can be resolved, false otherwise |
This node gets a glTF Asset Object Model value using the provided JSON Pointer. The type T
is determined by the pointer string according to the glTF Asset Object Model Specification. If the pointer string has invalid syntax or if the type of the referenced property cannot be statically determined, the node is invalid. Pointers containing extras
properties are out of scope of this specification but MAY be supported by implementations.
Note
|
Examples
The The The |
The pointer string MAY be a template pointer string, i.e., it MAY contain path segments substituted at runtime by converting each <segment>
input value to a base-10 string representation. All input values MUST be of int
type. Path segments, if used, MUST substitute only array indices in the pointer templates as listed in the glTF Asset Object Model Specification.
Note
|
Example
If the |
This node has no internal state.
If any of the input values is negative, the value
output value is the default value for its type and the isValid
output value is false.
If the pointer or the pointer template with all its substitutions applied can be resolved, the value
output value is the resolved property value and the isValid
output value is true.
If the pointer or the pointer template with all its substitutions applied cannot be resolved, the value
output value is the default value for its type and the isValid
output value is false.
Note
|
Note
When the |
Type |
|
Set an object model property value |
---|---|---|
Configuration |
|
The JSON Pointer or JSON Pointer template |
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
Zero or more JSON Pointer template path substitutions to be evaluated at runtime; input value socket names correspond to the pointer’s path segments wrapped with curly braces ( |
|
The new property value |
|
Output flow sockets |
|
The flow to be activated if the JSON Pointer can be resolved |
|
The flow to be activated if the JSON Pointer cannot be resolved |
This node sets a glTF Asset Object Model value using the provided JSON Pointer. The type T
is determined by the pointer string according to the glTF Asset Object Model Specification. If the pointer string has invalid syntax, if the type of the referenced property cannot be statically determined, or if the referenced property is not mutable, the node is invalid. Pointers containing extras
properties are out of scope of this specification but MAY be supported by implementations.
The pointer string MAY be a template pointer string, i.e., it MAY contain path segments substituted at runtime by converting each <segment>
input value to a base-10 string representation. All input values used for path segment substitutions MUST be of int
type. Path segments, if used, MUST substitute only array indices in the pointer templates as listed in the glTF Asset Object Model Specification.
If the value
input value is not valid for the resolved property, the effective property value becomes implementation-defined and subsequent pointer/get
evaluations of the property MAY return any value of the corresponding type until the property is updated with a valid value.
This node has no internal state.
When the in
input flow is activated:
-
Evaluate all input values.
-
If any of the pointer segment input values is negative,
-
activate the
err
output flow and skip the next steps.
-
-
If the pointer or the pointer template with all its substitutions applied can be resolved,
-
if the pointer interpolation state dynamic array (defined below) contains an entry with the same resolved JSON Pointer value, remove it from the array;
-
set the resolved property to the
value
input value; -
activate the
out
output flow.
-
-
If the pointer or the pointer template with all its substitutions applied cannot be resolved,
-
activate the
err
output flow.
-
Type |
|
Interpolate an object model property value |
---|---|---|
Configuration |
|
The JSON Pointer or JSON Pointer template |
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
Zero or more JSON Pointer template path substitutions to be evaluated at runtime; input value socket names correspond to the pointer’s path segments wrapped with curly braces ( |
|
The target property value |
|
|
The time, in seconds, in which the property SHOULD reach the target value |
|
|
Control point P1 |
|
|
Control point P2 |
|
Output flow sockets |
|
The flow to be activated if the JSON Pointer can be resolved and the input values are valid |
|
The flow to be activated if the JSON Pointer cannot be resolved or the input values are invalid |
|
|
The flow to be activated when the property reaches the target value |
This node interpolates and updates the specified glTF Asset Object Model property multiple times over the specified duration using the provided JSON Pointer. The type T
is determined by the pointer string according to the glTF Asset Object Model Specification. If the pointer string has invalid syntax, if the type of the referenced property cannot be statically determined, if it is integer or boolean, or if the referenced property is not mutable, the node is invalid. Pointers containing extras
properties are out of scope of this specification but MAY be supported by implementations.
The pointer string MAY be a template pointer string, i.e., it MAY contain path segments substituted at runtime by converting each <segment>
input value to a base-10 string representation. All input values used for path segment substitutions MUST be of int
type. Path segments, if used, MUST substitute only array indices in the pointer templates as listed in the glTF Asset Object Model Specification.
If the value
input value or any intermediate interpolated value are not valid for the resolved property, the effective property value becomes implementation-defined and subsequent pointer/get
evaluations of the property MAY return any value of the corresponding type until the property is updated with a valid value.
This node has no internal state.
When a node of this type is used in the behavior graph, the global graph state includes an implementation-defined pointer interpolation state dynamic array each element of which contains the following data:
-
The resolved JSON Pointer to the Object Model property being interpolated
-
Implementation-defined high precision timestamp value representing the interpolation start time
-
Interpolation duration value converted to the implementation-defined high precision time type
-
Object Model property value at the time of the successful node activation
-
Information needed for cubic Bézier spline evaluation derived from the node’s input values
-
Target property value
-
Implementation-specific pointer to the
done
output flow of the node that has added this entry
This array is initially empty and its maximum size is implementation-specific.
When the in
input flow is activated:
-
Evaluate all input values.
-
If any of the pointer segment input values is negative,
-
activate the
err
output flow and skip the next steps.
-
-
If the pointer or the pointer template with all its substitutions applied cannot be resolved,
-
activate the
err
output flow and skip the next steps.
-
-
If the
duration
input value is NaN, infinite, negative, or not convertible into an implementation-specific time type used for the internal interpolation start time value,-
activate the
err
output flow and skip the next steps.
-
-
If any component of the
p1
orp2
input values is NaN or infinite or if any of the first components of these input values is negative or greater than 1,-
activate the
err
output flow and skip the next steps.
-
-
If starting a new pointer interpolation exceeds any implementation-specific limit,
-
activate the
err
output flow and skip the next steps.
-
-
If the pointer interpolation state dynamic array contains an entry with the same resolved JSON Pointer value,
-
remove it from the array.
-
-
Using the implicitly-defined end points \$P_0 (0, 0)\$ and \$P_3 (1, 1)\$ together with the control points \$P_1\$ and \$P_2\$ provided via the input values construct a cubic Bézier easing function for the \$[0, 1\$] input range.
-
Add a new entry to the pointer interpolation state dynamic array filling it with the required information based on the evaluated input values.
-
Activate the
out
output flow.
On each asset animation update, for each entry in the pointer interpolation state dynamic array:
-
Compute the current input progress position t as the time passed since the interpolation start divided by the interpolation’s duration.
-
If t is less than or equal to zero
-
skip the next steps.
-
-
If t is NaN or greater than or equal to 1,
-
set the Object Model property to the target value;
-
remove the current entry from the pointer interpolation state dynamic array;
-
activate the
done
output flow linked to the current entry -
skip the next steps.
-
-
Using the cubic Bézier spline information, compute the output progress position q based on the t value. This step implies that \(t \in [0; 1]\).
-
Set the linked Object Model property to the new value computed as a linear interpolation between the original and the target property values using the output progress position q as the interpolation coefficient.
If the Object Model property is a quaternion, spherical linear interpolation expression SHOULD be used.
Intermediate output progress values MAY be less than zero or greater than one.
Type |
|
Start playing an animation |
---|---|---|
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
Animation index |
|
Start time |
|
|
End time |
|
|
Speed multiplier |
|
Output flow sockets |
|
The flow to be activated if the input values are valid |
|
The flow to be activated if any of the input values is invalid |
|
|
The flow to be activated after the animation ends |
This node starts playing an animation using the specified input values.
For the purposes of the Animation Control Nodes the concept of glTF animations is extended to unambiguously map any requested input timestamp \$r\$ to the effective input timestamp \$t\$ present in the glTF animation data as follows.
-
Let \$T\$ be the maximum value of all animation sampler input accessors of the animation. Then, the stored animation data defines the animated property values for all effective input timestamps in the \$[0, T\$] range.
-
Let \$r\$ be a scalar value on a timeline infinite in both directions, from negative infinity to positive infinity.
-
If \$T\$ is not equal to zero, let \$s\$ be the current iteration number computed as follows: \(s=\begin{cases} \left\lceil \dfrac{r-T}{T} \right\rceil & \text{if } r \gt 0 \\ \left\lfloor \dfrac{r}{T} \right\rfloor & \text{if } r \le 0 \\ \end{cases}\)
-
Now for each requested input timestamp \$r\$, the corresponding effective input timestamp is \(t=\begin{cases} r - s * T & \text{if } T \ne 0 \\ 0 & \text{if } T=0 \\ \end{cases}\)
This node has no internal state.
When a node of this type is used in the behavior graph, the global graph state includes an implementation-defined animation state dynamic array each element of which contains the following data:
-
Animation index
-
Start time value
-
End time value
-
Stop time value (see
animation/stopAt
) -
Speed value
-
Implementation-specific creation timestamp value associated with the system time when this entry was added
-
Implementation-specific end completion pointer to the
done
output flow of the node that has added this entry -
Implementation-specific stop completion pointer to the
done
output flow of the node that has scheduled its stopping (seeanimation/stopAt
)
This array is initially empty; its maximum size is implementation-specific.
When the in
input flow is activated:
-
Evaluate all input values.
-
If the
animation
input value is negative or greater than or equal to the number of glTF animations in the asset,-
activate the
err
output flow and skip the next steps.
-
-
If the
startTime
orendTime
input values are NaN or if thestartTime
input value is infinite,-
activate the
err
output flow and skip the next steps.
-
-
If the
speed
input value is NaN, infinite, or less than or equal to zero,-
activate the
err
output flow and skip the next steps.
-
-
If starting a new animation exceeds any implementation-specific limit,
-
activate the
err
output flow and skip the next steps.
-
-
If the animation state dynamic array contains an entry with the same animation index,
-
remove it from the array; the previously set
done
flows MUST NOT be activated.
-
-
Add a new entry to the animation state dynamic array filling it with the required information based on the evaluated input values. The stop time value MUST be set to the end time value and the stop completion pointer MUST be set to null.
-
Activate the
out
output flow.
On each asset animation update, for each entry in the animation state dynamic array:
-
TBD
Type |
|
Immediately stop a playing animation |
---|---|---|
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
Animation index |
Output flow sockets |
|
The flow to be activated if the animation index is valid |
|
The flow to be activated if the animation index is invalid |
This node stops a playing animation.
This node has no internal state.
When the in
input flow is activated:
-
Evaluate all input values.
-
If the
animation
input value is negative or greater than or equal to the number of glTF animations in the asset,-
activate the
err
output flow and skip the next steps.
-
-
If the animation state dynamic array exists and contains an entry with the same animation index,
-
remove it from the array and stop the playing animation. The animated properties MUST keep their current values and the previously associated
done
flows MUST NOT be activated.
-
-
Activate the
out
output flow.
Type |
|
Schedule stopping a playing animation |
---|---|---|
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
Animation index |
|
Stop time |
|
Output flow sockets |
|
The flow to be activated if the input values are valid |
|
The flow to be activated if any of the input values is invalid |
|
|
The flow to be activated after the animation stops |
This node stops a playing animation.
This node has no internal state.
When the in
input flow is activated:
-
Evaluate all input values.
-
If the
animation
input value is negative or greater than or equal to the number of glTF animations in the asset,-
activate the
err
output flow and skip the next steps.
-
-
If the
stopTime
input value is NaN,-
activate the
err
output flow and skip the next steps.
-
-
If the animation state dynamic array exists and does contain an entry with the same animation index,
-
update the entry’s stop completion pointer to the
done
output flow of this node; -
update the entry’s stop time to the
stopTime
input value.
-
-
Activate the
out
output flow.
Type |
|
Start event |
---|---|---|
Output flow sockets |
|
The flow to be activated when the start event happens |
This node is activated when all glTF asset resources are loaded and ready for rendering and interactions.
This node has no internal state.
Type |
|
Tick event |
---|---|---|
Output value sockets |
|
Relative time in seconds since the graph execution start |
|
Relative time in seconds since the last tick occurred |
|
Output flow sockets |
|
The flow to be activated when the tick event happens |
This node is activated when a tick occurs. There will be at most one tick per rendered frame, which SHOULD align with frame time, but there are no guarantees of time elapsed between ticks.
The internal state of this node consists of two floating-point time values initialized to NaN. They MUST be set to their effective values before the out
output flow is activated.
Type |
|
Receive a custom event |
---|---|---|
Configuration |
|
The custom event index |
Output value sockets |
|
Output values defined by the custom event |
Output flow sockets |
|
The flow to be activated when the custom event happens |
This node is activated when a custom event specified by the event
configuration value occurs. The types, names, and semantics of the output value sockets are defined by the custom event index.
The event
configuration value MUST be non-negative and less than the total number of custom event definitions, otherwise the node is invalid.
The internal state of this node consists of all output value sockets initialized to type-default values, i.e., NaN for floating-point types, zero for integers, and false for bools.
The output value sockets MUST be updated before activating the out
output flow.
Type |
|
Send a custom event |
---|---|---|
Configuration |
|
The custom event index |
Input flow sockets |
|
The entry flow into this node |
Input value sockets |
|
Input values defined by the custom event |
Output flow sockets |
|
The flow to be activated after sending the event |
This node sends a custom event specified by the event
configuration value. The types and names of the input value sockets are defined by the custom event index.
Note
|
Note
If the graph needs to know whether the event has been received and/or processed by an external environment, the latter could send another event in response. |
The event
configuration value MUST be non-negative and less than the total number of custom event definitions, otherwise the node is invalid.
This node has no internal state.
When the in
input flow is activated:
-
Evaluate all input values.
-
Send the custom event.
-
Activate the
out
output flow.
This Specification defines additional glTF Object Model pointers for use with pointer/*
nodes.
In some viewers, such as, but not limited to, augmented reality viewers and virtual reality viewers, the viewer implementation gives the user direct control over a virtual camera. This virtual camera MAY be controlled by user head movements, by movements of the user’s phone with their hands, or by mouse, keyboard or touch input on a laptop, or by other means. It is useful for interactivity to be able to react to the position of this virtual camera.
This Specification defines the “active camera” as the camera transformation that ought to be reacted to by interactivity. When there is only one camera being displayed to the user the implementation SHOULD use this camera as the “active camera”. When there are multiple cameras being controlled by the user, the implementation MAY select one such camera or construct a synthetic camera to use as the “active camera” (for example the midpoint of two stereoscopic camera positions). When zero cameras are being controlled by the user but views from one or more cameras are being displayed to the user, the implementation SHOULD select one of the cameras that is being displayed as the “active camera”.
The position
read-only property represents the “active camera” position in the global space. The rotation
read-only property represents the “active camera” rotation quaternion; the identity quaternion corresponds to the camera orientation defined in the glTF 2.0 Specification.
An implementation MAY provide no “active camera” data, for example for privacy reasons or if no cameras are being displayed to the user. If the “active camera” position is unavailable, the position
property MUST be set to all NaNs; if the “active camera” rotation is unavailable, the rotation
property MUST be set to all NaNs.
The following pointers represent the read-only properties defined in this section.
Pointer | Type |
---|---|
|
|
|
|
A KHR_interactivity
extension object is added to the root-level extensions
property. It contains four arrays corresponding to four interactivity concepts: types
, events
, variables
, and nodes
. As with the core glTF spec, if a JSON array is empty, it MUST be omitted from the asset.
{
"asset": {
"version": "2.0"
},
"extensionsUsed": ["KHR_interactivity"],
"extensions": {
"KHR_interactivity": {
"types": [
//
],
"events": [
//
],
"variables": [
//
],
"nodes": [
//
]
}
}
}
The types
array defines mappings between graph-local type indices and the recognized type signatures.
The following example defines type 0
as float2, type 1
as int, and type 2
as float:
"types": [
{
"signature": "float2"
},
{
"signature": "int"
},
{
"signature": "float"
}
]
The signature value MUST be one of the value types defined in this extension specification or "custom"
. In the latter case, the type semantic MUST be provided by an additional extension.
Non-custom signature MUST NOT appear more than once.
The events
array defines external identifiers and value socket types for custom events.
The following example defines a custom “checkout” event with an external identifier and one value socket:
"events": [
{
"id": "checkout",
"values": [
{
"id": "variant",
"type": 1
}
]
}
]
The event ID value is an application-specific event identifier recognized by the execution environment. If the id
property is undefined, the event is considered internal to the graph.
The values
array defines IDs and type indices of the sockets associated with the event. If the array is undefined, the event has no associated value sockets.
The variables
array defines custom variables with their types and optional initialization values.
The following example defines a custom variable with its initial value:
"variables": [
{
"type": 0,
"value": [0.5, 0.5]
}
]
The type
value defines the index of the variable type.
The value
array, if present, defines the initial variable value. The following table defines array size and default values for all value types defined in this extension.
Type | Array size | Default value |
---|---|---|
|
1 |
Boolean false |
|
1 |
Floating-point NaN |
|
2 |
Two floating-point NaNs |
|
3 |
Three floating-point NaNs |
|
4 |
Four floating-point NaN |
|
16 |
Sixteen floating-point NaNs |
|
1 |
Integer zero |
If the variable type is custom, the value
property is defined by the extension defining the custom type.
The nodes
array defines the behavior graph.
Each element of the nodes
array represents a node instance, i.e., it specifies node’s type, configuration, sources of input value sockets, and pointers of the output flow sockets.
Input value sockets MAY have inline constant values; in this case, the value socket type MUST be explicitly defined.
Configuration values are always implicitly typed based on the node’s type.
Note
|
Rationale
Some nodes have configuration values of array and/or string types that cannot be expressed with the explicit types defined in this Specification. |
Inline values and configurations use JSON arrays similarly to the initial variable values.
The following example instantiates a math/add
node that has both its input value sockets filled with inline integer values.
"nodes": [
{
"type": "math/add",
"values": [
{
"id": "a",
"value": [1],
"type": 1
},
{
"id": "b",
"value": [2],
"type": 1
}
]
}
]
The following example instantiates three nodes. The math/sub
node has both its input value sockets connected to output value sockets of two other nodes: math/pi
and math/e
.
"nodes": [
{
"type": "math/pi"
},
{
"type": "math/e"
},
{
"type": "math/sub",
"values": [
{
"id": "a",
"node": 0,
"socket": "value"
},
{
"id": "b",
"node": 1,
"socket": "value"
}
]
}
]
The following example instantiates two nodes. The variable/set
node sets a custom variable with index 0
when the start event happens.
"variables": [
{
"type": 1
}
],
"nodes": [
{
"type": "variable/set",
"configuration": [
{
"id": "variable",
"value": [0]
}
],
"values": [
{
"id": "value",
"value": [1],
"type": 1
}
]
},
{
"type": "event/onStart",
"flows": [
{
"id": "out",
"node": 0,
"socket": "in"
}
]
}
]
The type
property is required; it defines semantics and validation of the configuration
, values
, and flows
arrays.
The same id
value MUST NOT be used more than once within each of the configuration
, values
, and flows
arrays.
If the node type has configuration, the configuration
array MUST provide all configuration parameters as inline values.
If the node type has input value sockets, the values
array MUST connect all input value sockets to other nodes or fill them with inline values. Additionally, for each element of the values
array:
-
value
andnode
properties MUST NOT be defined at the same time; -
if
value
is defined,type
MUST also be defined.