A non-standard standardization attempt
This file is written to ease the developing of a project using XVR Studio 2.0, written in S3D language.
For the style guide, check this other document.
Note: This document is for the most part a direct copy of the content of the wiki documentation of XVR and S3D language, available inside VRMedia Wiki website.
Identifiers are names which are used to declare variables, functions and classes. The rules to follow to build a valid identifier are the same of the C language, i.e. they can be constituted by:
- alphanumeric characters
- underscore characters
'_'
The first character must not be a number; besides, it is not possible to use reserved names used by the compiler. The reserved name are the followings:
| aadd | case | for | modulus | static | vector |
| abs | char | function | null | str | void |
| acos | class | goto | range | switch | while |
| adel | continue | if | reset | tan | |
| array | cos | int | return | trace | |
| asc | default | left | right | true | |
| asin | do | len | set | upper | |
| asize | else | ln | sin | val | |
| atan | extern | log | space | valtype | |
| break | false | lower | sqrt | var |
The basic statements of the language are bolded.
Preprocessor directives, such as #define and #ifdef, are typically used to make source programs easy to change and easy to compile in different execution environments. Directives in the source file tell the preprocessor to perform specific actions. For example, the preprocessor can replace tokens in the text, insert the contents of other files into the source file, or suppress compilation of part of the file by removing sections of text. Preprocessor lines are recognized and carried out before macro expansion. Therefore, if a macro expands into something that looks like a preprocessor command, that command is not recognized by the preprocessor. The preprocessor recognizes the following directives:
| define | endif | ifdef | include | import |
| else | if | ifndef | pragma |
In order to facilitate the exchange of software modules and to preserve the IP of developers, XVR was added a new pre-processor directive, #import, allowing to import a pre-compiled XVR script under the shape of a .s3d.bin file and to enable using the functions defined and implemented in the external imported module. Functions must be explicitely declared as extern in order to be called by the host XVR application. This is a snippet showing how to use the #import directive:
#import <ExternLib.s3d.bin> // name of the precompiled bin file
extern function fibonacci; // name of the functions defined in
extern function factorial; // the imported .bin file
...
for(var i=0; i<20; i++)
{
outputLn("factorial(", i, ") = ", factorial(i) );
outputLn("fibonacci(", i, ") = ", fibonacci(i) );
}
...XVR variables have dynamic typing; the type of a variable can change through the variable's life.
NOTE: while this is true, it is not a good practice to change multiple times the purpose of a variable.
A variable is declared using the following syntax:
var <var1>[= <value1>] [,<var2>[ = <value2>]...] ;It is possible to declare more than one variable with a single instruction and to assign an initial value.
-
Local variables — Variables declared inside a function body are considered local, therefore their value is destroyed when exiting the function.
-
Global variables — Variables declared outside function bodies are considered global, therefore they are visible everywhere from there on and their value persists during the whole execution.
The static keyword specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless another value is specified.
static var <var1>[= <value1>] [,<var2>[ = <value2>]...] ;If the static variable is explicitely initialized when it is declared, it is possible in every moment to reset its value to the initialization value:
static var a = 10;
a = 7;
reset a; // a = 10A class is declared using the followin syntax
class <classname>[:<classbase1>][,<classbase2>][,...] // declaration of class name (and base classes)
{
// class declaration body
var <var1>[= <value1>] [,<var2>[ = <value2>]...] ; // declaration of member variables
...
<funcname> ( [<var1>] [,[<var2>] ... ] ); // declaration of methods
...
};Once the class is declared, its default constructor and destructor are automatically created. Optionally it is possible to declare a user-defined version of constructor and destructor, using this syntax:
function <classname>::<classname> ( [<c_var1>] [,[<c_var2>] ... ] )
{
[<constructor body>]
}
function <classname>::~<classname> ( [<d_var1>] [,[<d_var2>] ... ] )
{
[<destructor body>]
}Note: it is not necessary to declare the constructor and the destructor inside the class declaration body.
Methods are declared using the following syntax:
function <classname>::<funcname> ( [<m_var1>] [,[<m_var2>] ... ] )
{
[<method body>]
}Note: it is necessary to declare the method prototype inside the class declaration body, while its full declaration must be defined outside.
To instance an object of the class:
var <obj> = <classname> ( [<c_param1>] [,[<c_param2>] ... ] )To call a method of an instanced object:
<obj>.<funcname>( [<m_param1>] [,[<m_param2>] ... ] )A function is declared using the following syntax:
function <func> ( [<var1>] [,[<var2>] ... ] )
{
<Function Body>
}Inside the function body it is possible to declare new local variables, call other functions and methods (both user defined or predefined), use language instruction etc.
The return [<value>] instruction allows to specify the return value of the function. If the value is not specified, or return is not used, the function will return a null value. If a function is used before its declaration, it is necessary to declare a prototype of the function before its first usage:
function <func> ( [<var1>] [,[<var2>] ... ] );With this prototype declaration, the compiler is instructed about the function existance and about the number of parameters. In the real declaration it is possible to specify different names for the formal parameters, but the number has to be the same.
To use a function the following syntax is used:
<func> ( <param1>, <param2>, ...);
The number of actual parameters (APN) can be different from the number of formal parameters (FPN).
- If APN < FPN, the missing parameters will be passed with null values.
- If APN > FPN, the exceeding parameters will be ignored.
Variables can be passed to the function by reference or by value. If by reference, the actual parameters undergo the possible modifications operated by the function, otherwise they cannot be modified.
To pass a variable by reference, the & symbol must be put before the identifier in function declaration:
<func> ( &<param1>, <param2>, ...);Note: Since Arrays or Objects are reference variables, even if they are passed by value they are actually passed by reference, like in Java language.
Constants and variables assume values which may own to predefined data types, any predefined data type.
Therefore the following situation is legal:
var a;
a = true;
a = 2.1;
a = 182;IMPORTANT: Often it is not necessary to specify the type at declaration time, as it is automatically assumed at the first instancing.
Therefore, although the following data types exist, they are not specified with the corresponding keyword, except from vector and array (for instance, int is not a data type but a predefined function).
NOTE: In official documentation, references to the ANYTYPE data type may be found. ANYTYPE corresponds to any valid XVR data type, with the exception of objects.
- bool — value is either
trueorfalse. - float — floating point numbers, which can range between
±1e-45and±1e38. The'.'separator or the exponential one'e'are sufficient to define a floating point number. - int — regular integer valyes, between
±2147483647. - object — in addition to user-defined classes, the S3D language offers lots of predefined classes. It is possible to declare objects of these classes (except from classes which allow just one object automatically created) and to access methods and members with the operator
'.', as already shown. - string — they are sequences of character with no limits on length. As for the arrays, it is possible to access an element (a character) using an index and the operator
[ ]. - vector — they are array of floats. They can have any dimension. In the XVR reference, when not differently specified, vectors are assumed to be three-component.
- matrices — although not directly supported, often XVR functions return, or accept as input, 16-dim vectors representing matrices. In this case the matrix is stored in column-major order, like in OpenGL. Thus, the vector representation of a 4x4 matrix named
MATwill be:
MAT[0] MAT[4] MAT[8] MAT[12]
MAT[1] MAT[5] MAT[9] MAT[13]
MAT[2] MAT[6] MAT[10] MAT[14]
MAT[3] MAT[7] MAT[11] MAT[15]
- array — it is a set of elements which can be accessed through an index. The array size is not fixed, but it may be changed with particular functions. The S3D array is much more flexible than in other languages, as its elements may be of differeny type. To specify the index in order to access the desired element, the operator
[ ]is used. Arrays are zero-indexed.
An overview of the various data dypes is the following one:
v0 = false; // bool
v1 = 123.2; // float
v2 = -20.0; // float
v3 = 3e-2; // float
v4 = 123; // int
v5 = CVmLight(); // object
v5.setPosition(10, 10, 20);
v6 = "Hello!!!"; // string
v7 = v6[1]; // string with only one character "e"
v8 = [0.2, 2, 3.33, 4]; // 4-elements vector (of floats)
v9 = vector(16); // 16-elements vector (of floats)
v10 = v9[0]; // float
v11 = {1, true, {12, 3} }; // array made of different types
v12 = array(12); // array of 12 elements
v13 = v11[0]; // v13 = 1
v14 = v11[2][0]; // v14 = 12
v11[1] = false; // now v11[1] is falseOperators are basically the same as in C language, with the addition of some cross-operations between integers, strings or vectors, which are allowrd in S3D language. For a complete specification refer to this document.
They are a convenient and meaningful way to access single components of a vector using keywords such as xyzw and rgba. A shortcut to generate a new vector containing the selected components in a specific order, including repetition The swizzle operator syntax is similar to object members access:
<vector_name>.<swizzle>but the swizzle must not exceed 4 characters.
Allowed swizzle characters are:
x or r |
first component |
y or g |
second component |
z or b |
third component |
w or a |
fourth component |
_ or 0 |
ignore component |
Some examples follow:
v1 = [ 1, 100, -10, -100 ];
// v1.zwx corresponds to [-10, -100, 1]
// v1.xxxy corresponds to [1, 1, 1, 100]
// v1.x_z or v1.x0z correspond to [1, 0, -10]
col = [0.8, 0.4, 0.9, 1.0];
// col.rgb0 corresponds to [0.8, 0.4, 0.9, 0.0]
// col.r corresponds to 0.8Swizzles can be used also in assignments to overwrite selected components:
v2 = [-2, 20, 200, -20]
v2.x = 5; // one component change
// --> v2 = [ 5, 20, 200, -20]
v2.wy = [3, 4]; // multiple components change
// --> v2 = [ -2, 4, 200, 3 ]
v2.x_z = [3, 4, 5]; // multiple components change with
// no changes on some of them
// --> v2 = [ 3, 20, 5, -20 ]Statements are basically the same as in C language. For a complete specification refer to this document.
It is used to set the value of some system constants before the program actually starts. The allowed constants are:
SCENE_FOV— field of view of the camera.SCENE_NEAR— near clipping plane distance (everything farther than this plane is not drawn).SCENE_FAR— far clipping plane distance (everything closer than this plane is not drawn).AUDIO_MODE— 3D Audio Setup mode:0force software 3d capabilities;1force hardware 3d capabilities;2automatically get capabilities.
Example:
set SCENE_FOV = 50.0;It is out of the scope of this document to provide a documentation for most common basic functions. For a complete specification refer to this document.