Unlike many other languages, LSL has native support for several operations that are common in 3D geometry. A type that is fundamental in that support is the vector type. A vector can be defined as a type that is able to hold three floats; but LSL also supports many operations that are designed for geometry handling.
A vector literal is written in LSL as three comma-separated float values within angle brackets (e.g. <1.5, 0.0, -7.3>
is a valid vector). As in many other instances, if an integer appears instead of a float, it is automatically cast to a float, therefore this is also a valid vector literal: <0, 3, -5>
which represents the same vector as <0.0, 3.0, -5.0>
.
The components of a vector can be referenced only when they are inside variables, and the syntax is the name of the variable followed by a dot and then the letters x, y or z. For example, if vector_var
is a variable of type vector, then vector_var.y
is the second (y) component of the vector.
Due to their ability to store three floats, vectors are sometimes "abused" to hold three values even if they don't make a vector in the geometric sense. For example, they are used to store the Euler angles of a rotation, or the RGB components of a colour. Sometimes even one of the values is discarded, such as in the case of a Path Cut specification, which is written in a vector whose x component is the path cut begin, the y component is the path cut end, and the z component is ignored.
Adding a minus sign in front of a vector has the effect of negating each component; e.g. if v is a vector then -v
gives the same result as <-v.x, -v.y, -v.z>
(and takes less code space and is faster).
Vectors can be added, resulting in a new vector whose components are the sum of the corresponding component of each vector. The symbol is the same as for addition of floats and integers, i.e. the plus sign +
. For example, if v and w are vector variables, then v + w
gives the same result as <v.x + w.x, v.y + w.y, v.z + w.z>
.
Subtraction works similarly using the -
symbol instead.
Vectors can be multiplied in several ways. The most basic one is multiplication by a float: that returns a vector where each of its components is that of the original vector multiplied by the given float. As usual, integers can be used in place of floats and will be automatically cast to float. For example, <1, 2, 3> * 5
and 5 * <1, 2, 3>
both give the same vector as <5, 10, 15>
.
Another type of multiplication is the so called dot product or scalar product. It takes two vectors, and the result is a float. The symbol is the same as for multiplication of floats and integers, i.e. the asterisk *
. The resulting operation is the sum of the products of the components; for example, if v and w are vector variables, then v * w
gives the same result as v.x * w.x + v.y * w.y + v.z * w.z
. It is useful in several geometric applications.
A third type of multiplication is called cross product or vector product. It takes two vectors, and the result is a vector. The symbol is the same as for integer modulo, i.e. the percent sign %
. The operation is a bit complex: if v and w are vector variables, then v % w
gives the same result as <v.y*w.z - v.z*w.y, v.z*w.x - v.x*w.z, v.x*w.y - v.y*w.x>
. This kind of multiplication returns a vector that is perpendicular to both input vectors, and has several uses in geometry applications too.
And finally, there is a fourth type of multiplication: a vector multiplied by a rotation returns the vector rotated by the given rotation. For example, if r is a rotation that turns 90° counter-clockwise over the positive Z axis, then <0, 3, 1> * r
will result in <-3, 0, 1>
, that is, the vector will be rotated over that axis by that angle.
Important Note: There is no operation that returns the product of the components one by one similarly to vector addition. This operation has no meaning in geometry, and is thus not implemented; however, if you need it, it's easy to write like this: say v and w are your vectors; then you can obtain that result using <v.x*w.x, v.y*w.y, v.z*w.z>
.
Nothing can be divided by a vector, but vectors can be divided by two types of elements: floats, and rotations. As with multiplication by a float, dividing a vector by a float results in another vector where each element is divided by that float, e.g. v/f
gives the same result as <v.x/f, v.y/f, v.z/f>
. Division of a vector by a rotation results in applying the rotation that cancels the given one (e.g. if the rotation turns counter-clockwise over a certain axis, the vector will instead be rotated clockwise over that axis if it's divided by it).
Type casting a vector from and to other types can be done for only a limited number of types:
(vector)vector_value
does nothing special to the value, as expected.(vector)string_value
is supported; see Type casting of strings for details.(string)vector_value
is supported too; see Type casting a float to string for details.(list)vector_value
results in a list with one single element of type vector.