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
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