Va Ve

A vector is 3 float values used together as a single item–usually representing a direction or magnitude. In LSL and OSSL, vector literals are formatted as <x,y,z>. A vector can be used to represent a 3-dimensional position, direction, velocity, force, impulse, scale, color, or rotation (in Euler format). Each component can be accessed via ‘.x’, ‘.y’, and ‘.z’ (see below).

The value for a NULL vector is <0.00000, 0.00000, 0.00000> (or just <0.0, 0.0, 0.0> to keep it simple).

LSL/OSSL does do some implicit typecasting but the compiler does not actually convert types or simplify code; it just makes implicit typecasts explicit. So while <0, 0, 0> is valid, it will use more byte code and be slower then <0.0, 0.0, 0.0>. For this reason please be sure to use a decimal point. 0. is enough you don’t need an extra zero.

Example vector literal: <.9,1,.25>

vector a = <1,2,3>;
llOwnerSay((string)a); //<1.00000, 2.00000, 3.00000>



Vector Arithmetic Operators


+ Add two vectors together <1,2,3> + <2,0,3> = <1+2, 2+0, 3+3> = <3,2,6>
Subract one vector from another <1,2,3> – <2,0,3> = <1-2, 2-0, 3-3> = <-1,2,0>
* Vector dot product <1,2,3> * <4,5,6> = (1 * 4) + (2 * 5) + (3 * 6) = 32
% Vector cross product <1,2,3> % <4,5,6> = <2*6 – 3*5, 3*4 – 1*6, 1*5 – 2*4> = <-3, 6, -3>

Note: if a vector and a float are multipled together with the * operator, this will scale the vector by the float. <1, 2, 3> * 5 yields the resulting vector <5,10,15>.

A vector can be rotated by using the * operator and a rotation:

vector v;
vector result;
rotation r;

result = v * r; // rotate vector v by rotation r

 To change a single float component of a vector, declare a variable, then address it by referring to the x, y, or z components in the form “vector_name.x”, “vector_name.y” and “vector_name.z”. These components will be treated as if they were ordinary floats.


vector foo = llGetScale();
foo.z = 1.5


Will change foo.z to 1.5


vector foo = llGetPos();
foo.z += 1; 
// or:
foo += <0,0,1>;
// or


Any of the above methods will cause 1 to be added to the .z component of foo, although the last way is the fastest.


Function Purpose
llVecDist Gets the Euclidean distance between 2 vectors
llVecMag Identical to llVecDist with the second vector being <0,0,0>
llVecNorm Returns a normalized vector of the same direction as the input
llLookAt Rotates the object to look at the specified vector position


Verifying a vector in a string

This function determines if a string is a vector. It uses another function to verify if a string is a decimal.

// Returns TRUE if the string is a vector
integer strIsVector(string str) //SL 1.17.2
    str = llStringTrim(str, STRING_TRIM);//remove whitespace
    if(llGetSubString(str, 0, 0) != "<" || llGetSubString(str, -1, -1) != ">")
        return FALSE;//make sure angle brackets exist at first and last index
    integer commaIndex = llSubStringIndex(str, ",");//position of the first comma
    if(commaIndex == -1 || commaIndex == 1)
        return FALSE;//if there is no first comma OR if the first comma is right after the first '<' (i.e.: "<,3,3>")
    if( !strIsDecimal(llGetSubString(str, 1, commaIndex - 1)) || llGetSubString(str, commaIndex - 1, commaIndex - 1) == " " )
        return FALSE;//if the substring inbetween the first '<' and the first comma (exclusive) isn't a decimal OR
                     //the last character of the substring inbetween the first '<' and the first comma (exclusive) is a space
                     //note 1: having a space after the substring that corresponds to one of the x, y or z attributes
                     //causes the (vector) typecast operator to return a zero vector. i.e.: (vector)"<3.0 ,5,9>" == ZERO_VECTOR is TRUE
                     //on the other hand, (vector)"< 3.0,5,9>" == ZERO_VECTOR would be FALSE. weird, huh? =]
                     //note 2: the (vector) typecast operator only accepts decimal values and not hexidecimal value.
                     //for example, (vector)"<0xFE8,4.0,3>" == ZERO_VECTOR is true.
    str = llDeleteSubString(str, 1, commaIndex);//get rid of the substring containing the x attribute and the following delimiter (the first comma)

    commaIndex = llSubStringIndex(str, ",");//position of the second comma
    if(commaIndex == -1 || commaIndex == 1 || commaIndex == llStringLength(str) - 2 ||
     //no second comma found OR the second comma is too close to the first comma (i.e.: "<3,,3>") OR the second comma is too close to the '>' OR...
       !strIsDecimal(llGetSubString(str, 1, commaIndex - 1)) || llGetSubString(str, commaIndex - 1, commaIndex - 1) == " " ||
    //... the substring containing the y attribute isn't a decimal OR the substring containing the y attribute ends in a space OR...
       !strIsDecimal(llGetSubString(str, commaIndex + 1, -2)) ||  llGetSubString(str, -2, -2) == " ")
    //... the substring containing the z attribute isn't a decimal OR the subtring containing the z attribute ends in a space
    //testing if the substring that should hold the z attribute is a decimal covers having "too many" attributes
    //i.e.: "<1,2,3,4>" would be parsed by this function as having "3,4" for the z attribute, which obviously is not a decimal
    //and causes the above conditional to evaluate TRUE
        return FALSE;
    return TRUE;

//returns TRUE if the string is a decimal
integer strIsDecimal(string str)
    str = llStringTrim(str, STRING_TRIM);
    integer strLen = llStringLength(str);
    if(!strLen){return FALSE;}//added by ruthven willenov 7/30/09 so it would return false when fed an empty string
    integer i;
    if(llGetSubString(str,0,0) == "-" && strLen > 1)
        i = 1;//no need to test for "-": following code will take care of that
        i = 0;

    integer decimalPointFlag = FALSE;
    for(; i < strLen; i++)
        string currentChar = llGetSubString(str, i, i);
        if(currentChar == ".")
                return FALSE;
                decimalPointFlag = TRUE;
        else if(currentChar != "3" && currentChar != "6" && currentChar != "9" &&
                currentChar != "2" && currentChar != "5" && currentChar != "8" && // the order dosen't matter
                currentChar != "1" && currentChar != "4" && currentChar != "7" && currentChar != "0")
            return FALSE;
    return TRUE;


More Information

For more on vectors, see this general vector tutorial. This is not an LSL/OSSL-specific tutorial; rather, it’s an in-depth explanation of the mathematics involved. It’s good, but is not required reading for working with vectors in LSL.

Q: When dealing with individual components of vectors, is it possible to do it without assigning a value to a variable?
Say, something like, “float foo = llGetPos().z“?
No, you must assign a variable first, then refer to that:
vector foo = llGetPos();
float bar = foo.z;

A: Yes, however it may be a bit messy as it may turn a single line into a very large line. The dot product is the soloution. The dot product of the unit vector of the axis you intend to isolate the component from and the original vector is a float of the magnitude of that component:

float bar_x = llGetPos()*<1.0,0.0,0.0>;
float bar_y = llGetPos()*<0.0,1.0,0.0>;
float bar_z = llGetPos()*<0.0,0.0,1.0>;


Q: Is there a non-lossy way to convert a vector to a string and then back to a vector again so that the resulting vector has the same value as the original vector?
See: Serialization


Credit to: Lslwiki.net (not working) with changes made for brevity and clarity.