LSL Wiki Mirror : vector

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings ::

Vector


A vector is 3 float values used together as a single item--usually representing a direction or magnitude. In LSL, 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 does do some implicit typecasting but the LSL compiler does not actualy convert types or simplify code; it just makes implicit typecasts explicit. So while <0, 0, 0> is valid, it will use more bytecode 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.

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

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


Functions

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);
    
    integer i;
    if(llGetSubString(str,0,0) == "-" && strLen > 1)
        i = 1;//no need to test for "-": following code will take care of that
    else
        i = 0;

    integer decimalPointFlag = FALSE;
    
    for(; i < strLen; i++)
    {
        string currentChar = llGetSubString(str, i, i);
        
        if(currentChar == ".")
            if(decimalPointFlag)
                return FALSE;
            else
                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-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"?
A:
No, you must assign a variable first, then refer to that:
vector foo = llGetPos();
float bar = foo.z;

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?
A:
See: Serialization

Types | Binary | Rotation | UserDefinedFunction
There is one comment on this page. [Display comments/form]