3.2. Data Types

The purpose of the network protocol is to allow data to be serialized and transmitted over a network in a way that is independent of the machine type of the transmitting end. This requires well-defined ways to represent various kinds of values, and how this is done is specified in this section.

These are the types defined below, collected for easy reference:

Integers

int8, int16, int32, uint8, uint16, uint32

Reals

real32, real64

Integer Aliases

boolean, VNodeID, VLayerID, VNMFragmentID, VBufferID

Strings

string16, string500

Enumerations

VNodeType, VNodeOwner, VNOParamType, VNTagType, VNOTagConstants, VNRealFormat, VNOMethodConstants, VNGLayerType, VNMLightType, VNMNoiseType, VNMRampType, VNMRampChannel, VNMBlendType, VNMFragmentType, VNBLayerType, VNABlockType, VNAConstants, VNTConstants

Structures and Unions

VNQuat32, VNQuat64, VNOParam, VNOPackedParams, VNTag, VNMRampPoint, VMatFrag, VNBTile, VNABlock

3.2.1. Integers

Integers are the most fundamental data types used in Verse. This section presents the various specific integer types in use. They all have explicit bit counts, since it is important to know the exact number of bits needed to represent a value when working in a network context.

Bits in integers are numbered from zero, which is the least significant bit (the bit with the value one) and up. The notation X:Y is occasionally used to refer to a subfield in an integer, consisting of the (X-Y)+1 bits with the indicated bits being the most and least significant, respectively. For example, 15:12 is the top half-byte of a uint16.

int8

A signed 8-bit integer quantity. Can represent values between -128 and 127, inclusive.

int16

A signed 16-bit integer quantity. Can represent values between -32768 and 32767, inclusive.

int32

A signed 32-bit integer quantity. Can represent values between -2147483648 and 2147483647, inclusive.

uint8

An unsigned 8-bit integer quantity. Can represent values between 0 and 255, inclusive.

uint16

An unsigned 16-bit integer quantity. Can represent values between 0 and 65535, inclusive.

uint32

An unsigned 32-bit integer quantity. Can represent values between 0 and 4294967295, inclusive.

3.2.2. Reals

Real numbers are highly useful when dealing with 3D geometry data and related applications, so Verse defines two types for handling such numbers, below. They are called reals although they are of course not true real numbers in the mathematical sense, but approximated using floating-point numbers. The same holds true for integers however, and that name is natural so by analogy we have reals.

real32

An IEEE 754 floating-point number using exactly 32 bits in its representation.

real64

An IEEE 754 floating-point number using exactly 64 bits in its representation.

3.2.3. Integer Aliases

For clarity and convenience, there are many integer types defined that are simply aliases for one of the types defined above.

Having these aliases makes many descriptions easier to read, and in some situations (such as API function prototypes) makes them a lot more information-dense, descriptive, and generally useful. Note that these are not enumerations; there are no named values associated with these types.

Table 3-1. Integer Aliases

NameAlias ForDescription
boolean uint8

Used to represent boolean values, i.e. values that are either true or false. The values 0 (for false) and 1 (for true) are used.

VNodeID uint32

Used to identify nodes.

VLayerID uint16

Used to identify layers in nodes that have them.

VNMFragmentID uint16

Used to identify fragments in material nodes.

VBufferID uint16

Used to identify buffers in audio and text nodes.

3.2.4. Strings

These are variable-length character strings, which are mainly used to assign and reference names to various pieces of data.

Strings have explicit (maximum) sizes, in 8-bit bytes. In the encoding actually used, a character is not a byte, but since the strings need to be used in a network context, this is the simplest way to put a known limit on their sizes. Of course, being of variable length, a string does not have to occupy its maximum size, but can vary its encoded size depending on the content.

string16

A string type. Maximum size for strings of this type is 16 bytes.

string500

A string type. Maximum size for strings of this type is 500 bytes.

3.2.5. Enumerations

These are integer types with a set of pre-defined values. For fields having an enumerated type, only values described in the enumeration are legal to use.

Unless otherwise noted, all enumerations are represented as the given integer value using an uint8.

3.2.5.1. VNodeType

Defines a set of integers that are used to identify the various node types in Verse.

SymbolValue
V_NT_OBJECT 0
V_NT_GEOMETRY 1
V_NT_MATERIAL 2
V_NT_BITMAP 3
V_NT_TEXT 4
V_NT_CURVE 5
V_NT_AUDIO 6
V_NT_NUM_TYPES 7

3.2.5.2. VNodeOwner

Used to indicate whether a receiving client is actually the owner of a node or not.

SymbolValue
VN_OWNER_OTHER 0
VN_OWNER_MINE 1

3.2.5.3. VNOParamType

Identifies the type of an object node method parameter.

SymbolValue
VN_O_METHOD_PTYPE_INT8 0
VN_O_METHOD_PTYPE_INT16 1
VN_O_METHOD_PTYPE_INT32 2
VN_O_METHOD_PTYPE_UINT8 3
VN_O_METHOD_PTYPE_UINT16 4
VN_O_METHOD_PTYPE_UINT32 5
VN_O_METHOD_PTYPE_REAL32 6
VN_O_METHOD_PTYPE_REAL64 7
VN_O_METHOD_PTYPE_STRING 8
VN_O_METHOD_PTYPE_NODE 9
VN_O_METHOD_PTYPE_LAYER 10
VN_O_METHOD_PTYPE_REAL32_VEC2 11
VN_O_METHOD_PTYPE_REAL32_VEC3 12
VN_O_METHOD_PTYPE_REAL32_VEC4 13
VN_O_METHOD_PTYPE_REAL64_VEC2 14
VN_O_METHOD_PTYPE_REAL64_VEC3 15
VN_O_METHOD_PTYPE_REAL64_VEC4 16
VN_O_METHOD_PTYPE_REAL32_MAT4 17
VN_O_METHOD_PTYPE_REAL32_MAT9 18
VN_O_METHOD_PTYPE_REAL32_MAT16 19
VN_O_METHOD_PTYPE_REAL64_MAT4 20
VN_O_METHOD_PTYPE_REAL64_MAT9 21
VN_O_METHOD_PTYPE_REAL64_MAT16 22

3.2.5.4. VNTagType

Identifies the type of a node tag value.

SymbolValue
VN_TAG_BOOLEAN 0
VN_TAG_UINT32 1
VN_TAG_REAL64 2
VN_TAG_STRING 3
VN_TAG_REAL64_VEC3 4
VN_TAG_LINK 5
VN_TAG_ANIMATION 6
VN_TAG_BLOB 7

3.2.5.5. VNOTagConstants

These are constants used when working with node tags. The name is misleading.

SymbolValue
VN_O_TAG_GROUP_SIZE 16
VN_O_TAG_NAME_SIZE 16
VN_O_TAG_FULL_NAME_SIZE 64
VN_O_TAG_STRING_SIZE 128

3.2.5.6. VNRealFormat

Constants used when subscribing to transformations, to select the desired precision.

SymbolValue
VN_FORMAT_REAL32 0
VN_FORMAT_REAL64 1

3.2.5.7. VNOMethodConstants

These are some constants used with the object node's method system.

SymbolValue
VN_O_METHOD_GROUP_NAME_SIZE 16
VN_O_METHOD_NAME_SIZE 16
VN_O_METHOD_SIG_SIZE 256

3.2.5.8. VNGLayerType

Identifies the various types of layer supported by the geometry node.

SymbolValue
VN_G_LAYER_VERTEX_XYZ 0
VN_G_LAYER_VERTEX_UINT32 1
VN_G_LAYER_VERTEX_REAL 2
VN_G_LAYER_POLYGON_CORNER_UINT32 128
VN_G_LAYER_POLYGON_CORNER_REAL 129
VN_G_LAYER_POLYGON_FACE_UINT8 130
VN_G_LAYER_POLYGON_FACE_UINT32 131
VN_G_LAYER_POLYGON_FACE_REAL 132

3.2.5.9. VNMLightType

Identifies the types of light that a material node light fragment can receive.

SymbolValue
VN_M_LIGHT_DIRECT 0
VN_M_LIGHT_AMBIENT 1
VN_M_LIGHT_DIRECT_AND_AMBIENT 2
VN_M_LIGHT_BACK_DIRECT 3
VN_M_LIGHT_BACK_AMBIENT 4
VN_M_LIGHT_BACK_DIRECT_AND_AMBIENT 5

3.2.5.10. VNMNoiseType

Identifies the types of noise generated by a material node noise fragment. Has plenty of room for expansion.

SymbolValue
VN_M_NOISE_PERLIN_ZERO_TO_ONE 0
VN_M_NOISE_PERLIN_MINUS_ONE_TO_ONE 1
VN_M_NOISE_POINT_ZERO_TO_ONE 2
VN_M_NOISE_POINT_MINUS_ONE_TO_ONE 3

3.2.5.11. VNMRampType

Identifies which kind of interpolation is done by a material node ramp fragment.

SymbolValue
VN_M_RAMP_SQUARE 0
VN_M_RAMP_LINEAR 1
VN_M_RAMP_SMOOTH 2

3.2.5.12. VNMRampChannel

Identifies which color channel is to be affected by a material node ramp fragment.

SymbolValue
VN_M_RAMP_RED 0
VN_M_RAMP_GREEN 1
VN_M_RAMP_BLUE 2

3.2.5.13. VNMBlendType

Identifies which type of blending operation a material node blend fragment does.

SymbolValue
VN_M_BLEND_FADE 0
VN_M_BLEND_ADD 1
VN_M_BLEND_SUBTRACT 2
VN_M_BLEND_MULTIPLY 3
VN_M_BLEND_DIVIDE 4

3.2.5.14. VNMFragmentType

Identifies the type of a material node fragment.

SymbolValue
VN_M_FT_COLOR 0
VN_M_FT_LIGHT 1
VN_M_FT_REFLECTION 2
VN_M_FT_TRANSPARENCY 3
VN_M_FT_VOLUME 4
VN_M_FT_VIEW 5
VN_M_FT_GEOMETRY 6
VN_M_FT_TEXTURE 7
VN_M_FT_NOISE 8
VN_M_FT_BLENDER 9
VN_M_FT_CLAMP 10
VN_M_FT_MATRIX 11
VN_M_FT_RAMP 12
VN_M_FT_ANIMATION 13
VN_M_FT_ALTERNATIVE 14
VN_M_FT_OUTPUT 15

3.2.5.15. VNBLayerType

Identifies the type of a bitmap node layer, i.e. what type of value is stored in each of the pixels.

SymbolValue
VN_B_LAYER_UINT1 0
VN_B_LAYER_UINT8 1
VN_B_LAYER_UINT16 2
VN_B_LAYER_REAL32 3
VN_B_LAYER_REAL64 4

3.2.5.16. VNABlockType

Identifies the data representation used for blocks of audio samples. Note that 24-bit integers are supported.

24-bit samples are represented at the application level as uint32s, with the 24-bit sample left-adjusted, thus occupying the topmost 24 bits. The bottom eight bits contain a copy of the topmost eight. This means that 24-bit and 32-bit samples can be used interchangably, and if you really need the true 24-bit data, just shift the value Verse gave you right by eight bits. In network transmissions, these duplicate bits are not transmitted, which is why the block size (see below) for 24-bit integer data is larger than for 32-bit.

As an example, consider a sample value of 0.7. As an 8-bit integer, this would be 0.7 * 27-1 = 0.7 * 127 = 88. As a 24-integer, taking the above rules into account, we get: 0.7 * 223-1 = 0.7 * 8388607 = 5872024. If we convert this decimal number to hexadecimal, to see the individual bytes, we get 0x00599998. Now, we shift this to the left 8 bits, which gives 0x59999800. Finally, copying the top byte into the least significant place gives us the final result, which is 0x59999859. As a reference, the same sample value as a 32-bit integer is: 0.7 * 231-1 = 0.7 * 2147483647 = 1503238552. This value converted to hexadecimal is 0x59999998. The difference between the 24- and 32-bit representations here is on the order of 0.00002%.

SymbolValue
VN_A_BLOCK_INTEGER8 0
VN_A_BLOCK_INTEGER16 1
VN_A_BLOCK_INTEGER24 2
VN_A_BLOCK_INTEGER32 3
VN_A_BLOCK_REAL32 4
VN_A_BLOCK_REAL64 5

3.2.5.17. VNAConstants

Values needed to work with the audio node. The VN_A_BLOCK_ symbols specify the number of individual samples in a block of the indicated type.

It is important to note that these are not maximums; they are the only valid block sizes used in Verse. There is no such thing as a shorter block, the full block size according to the table is always used. Set any un-used samples to 0.

SymbolValue
VN_A_BLOCK_SIZE_INT8 1024
VN_A_BLOCK_SIZE_INT16 512
VN_A_BLOCK_SIZE_INT24 384
VN_A_BLOCK_SIZE_INT32 256
VN_A_BLOCK_SIZE_REAL32 256
VN_A_BLOCK_SIZE_REAL64 128

3.2.5.18. VNTConstants

Constants used with the text node.

SymbolValue
VN_T_BUFFER_NAME_SIZE 16
VN_T_CONTENT_LANGUAGE_SIZE 32
VN_T_CONTENT_INFO_SIZE 256
VN_T_MAX_TEXT_CMD_SIZE 1450

3.2.6. Arrays

All datatypes can be formed into arrays, which are simply linear sequences of values of one type.

The notation for an array is type[length] (where type is a type name and length an integer literal) for an array of known length, type[min..max] (where min and max are integer literals) for an array whose length can vary, type[SYMBOL] (where SYMBOL is a symbolic constant defined elsewhere) and type[] for an array whose length is not known. Extraneous information is needed to resolve how long a variable-length array is in each case; no length information is ever stored in the array itself.

Sometimes, an array length needs to be dynamic and not known in advance. In such cases, there is always some related (adjacent in a structure, for instance) field that gives the length, and the notation type[fieldname] is used to indicate this condition. Such a fieldname is in lower-case characters, to make it distinct from the case of a symbolic (upper-case) constant.

When a union type (see below) is made into an array, it is not defined if each element in the array has the same type, or if the type can vary between slots. This needs to be specified for each such use, and taken into account when encoding (or decoding) the data. The ability to vary the type of an array of unions per-slot gives a lot of flexibility.

3.2.7. Structures and Unions

These are types that collect several values into single entity. Each value is called a field of the structure.

Union types can only contain one of their member fields at any given time, and do not by themselves "know" which of the members is the one in use.

3.2.7.1. VNQuat32

This type describes a quaternion, a way to represent an arbitrary rotation. It uses 32-bit precision for all its floating point members.

The first three fields, x y and z, is the vector part of the quaternion, while the final field w represents the cosine of half the angle of rotation.

A good description of quaternions and operations on them is the Matrix and Quaternion FAQ (external link).

TypeName
real32 x
real32 y
real32 z
real32 w

3.2.7.2. VNQuat64

This type describes a quaternion, a way to represent an arbitrary rotation. See the description of VNQuat32 above, the only difference is that this type is used when 64-bit precision is desired.

TypeName
real64 x
real64 y
real64 z
real64 w

3.2.7.3. VNOParam

A union type that can hold a single value for a method parameter.

The vector and matrix members (vreal32_vec, vreal32_mat, vreal64_vec and vreal64_mat) are used for vectors of lengths 2, 3 and 4 inclusive and matrices of ranks 2x2, 3x3, and 4x4 inclusive.

Additional information, about which member is actually present, is needed to correctly interpret a value of this union type.

TypeName
int8 vint8
int16 vint16
int32 vint32
uint8 vuint8
uint16 vuint16
uint32 vuint32
real32 vreal32
real64 vreal64
string500 vstring
VNodeID vnode
VLayerID vlayer
real32[2..4] vreal32_vec
real32[4..16] vreal32_mat
real64[2..4] vreal64_vec
real64[4..16] vreal64_mat

3.2.7.4. VNOPackedParams

This structure is used to hold a "packed" version of a method call's parameters. The initial size field is the size, in bytes, of the structure as a whole, including the size field itself.

The array of VNOParam unions does not have uniform type over its length; each array member can have its own type. This means that additional data about the number of parameters and the type of each parameter is needed to properly create (pack) and interpret (unpack) these structures.

If the method call in question has no parameters, size will simply be two and no array will be present.

TypeName
uint16 size
VNOParam[0..255] param

3.2.7.5. VNTag

A union type that can hold the value of a node tag. Requires additional information to know which member is actually in use.

TypeName
boolean vboolean
uint32 vuint32
real64 vreal64
string500 vstring
real64[3] vreal64_vec3
VNodeID curve
uint32 start
uint32 end
vanimation
uint16 size
uint8[1..500] blob
vblob

3.2.7.6. VNMRampPoint

Represents the value of a single point in a material node ramp fragment.

TypeName
real64 pos
real64 red
real64 green
real64 blue

3.2.7.7. VMatFrag

A union that can hold a description of a single material node fragment. Its members are structures, since each fragment requires multiple values to define it.

TypeName
real64 red
real64 green
real64 blue
color
uint8 type
real64 normal_falloff
VNodeID brdf
string16 brdf_r
string16 brdf_g
string16 brdf_b
light
real64 normal_falloff
reflection
real64 normal_fallof
real64 refraction_index
transparency
real64 diffusion
real64 col_r
real64 col_g
real64 col_b
volume
string16 layer_r
string16 layer_g
string16 layer_b
geometry
VNodeID bitmap
string16 layer_r
string16 layer_g
string16 layer_b
boolean filtered
VNMFragmentID mapping
texture
uint8 type
VNMFragmentID mapping
noise
uint8 type
VNMFragmentID data_a
VNMFragmentID data_b
VNMFragmentID control
blender
boolean min
real64 red
real64 green
real64 blue
VNMFragmentID data
clamp
real64[16] matrix
VNMFragmentID data
matrix
uint8 type
uint8 channel
VNMFragmentID mapping
uint8 point_count
VNMRampPoint[1..48] ramp
ramp
string16 label
animation
VNMFragmentID alt_a
VNMFragmentID alt_b
alternative
string16 label
VNMFragmentID front
VNMFragmentID back
output

3.2.7.8. VNBTile

A union that holds the pixels of a single tile from a bitmap node.

Note how the vuint1 member is actually an array of vuint8, which holds the complete data for a tile in a 1-bit per pixel layer. All pixels are packed in a left-to-right, bottom-to-top manner, with the most significant bits considered to the left of the less significant ones. The array has length 8, which gives it a total capacity of 8 * 8 = 64 bits, which is precisely what is needed for one tile. The first uint8 holds the first scanline of the tile, and bit 7 of that uint8 holds the topmost leftmost pixel of the tile.

Pixels in tiles can be indexed by a coordinate pair (x,y), with x and y both in the range [0,7] inclusive. Then, (0,0) is the topmost leftmost pixel, and (7,7) is the pixel at the bottom right corner of the tile. For multi-bit pixel types, a pixel is referenced as simply a[y * 8 + x], where a is the union member (one of vuint8, vuint16, vreal32 and vreal64). For one-bit tiles, the pixel is tested by the C expression (vuint1[y] & (128 >> x)).

TypeName
uint8[8] vuint1
uint8[64] vuint8
uint16[64] vuint16
real32[64] vreal32
real64[64] vuint8

3.2.7.9. VNABlock

A union that holds a the samples for a block of audio. The number of samples held depends on the sample type; knowledge of the union's intended type is always needed in order to correctly interpret it.

TypeName
int8[VN_A_BLOCK_SIZE_INT8] vint8
int16[VN_A_BLOCK_SIZE_INT16] vint16
int32[VN_A_BLOCK_SIZE_INT24] vint24
int32[VN_A_BLOCK_SIZE_INT32] vint32
real32[VN_A_BLOCK_SIZE_REAL32] vreal32
real64[VN_A_BLOCK_SIZE_REAL64] vreal64