Difference between revisions of "Talk:Send vector as on rez parameter"

From Second Life Wiki
Jump to navigation Jump to search
(Further example. For position vectors with 0.5 metre resolution)
m (Updated <lsl> tags to <source lang="lsl2">)
 
Line 5: Line 5:
Here is a simple method with similar effect to yours for decimal vectors (each component 0 thru 999)
Here is a simple method with similar effect to yours for decimal vectors (each component 0 thru 999)


<lsl>
<source lang="lsl2">
integer Vector2IntDec(vector v)
integer Vector2IntDec(vector v)
{
{
Line 18: Line 18:
     return <v.x, v.y, i % 1000>;
     return <v.x, v.y, i % 1000>;
}
}
</lsl>
</source>


However, it's nicer to do the conversions using bit shifts. As an integer (in LSL) consists of 31 bits plus sign bit, we can comfortably allocate 10 bits to each vector component, allowing each component to hold a value in the range 0 to 1023.
However, it's nicer to do the conversions using bit shifts. As an integer (in LSL) consists of 31 bits plus sign bit, we can comfortably allocate 10 bits to each vector component, allowing each component to hold a value in the range 0 to 1023.


<lsl>
<source lang="lsl2">
integer Vector2Int(vector v)
integer Vector2Int(vector v)
{
{
Line 37: Line 37:
     return <v.x, v.y,  (n & 0x3FF) >;
     return <v.x, v.y,  (n & 0x3FF) >;
}
}
</lsl>
</source>


(These examples have been compiled and tested using lslEditor and Mono)
(These examples have been compiled and tested using lslEditor and Mono)
Line 46: Line 46:
I was recently asked about sending a position vector to the nearest 0.5 metres as an integer.
I was recently asked about sending a position vector to the nearest 0.5 metres as an integer.


<lsl>
<source lang="lsl2">
// Code to compress an intra-region position vector to an integer and back again
// Code to compress an intra-region position vector to an integer and back again
// Omei Qunhua 12-March-2014
// Omei Qunhua 12-March-2014
Line 94: Line 94:
     }
     }
}
}
</lsl>
</source>

Latest revision as of 12:43, 3 February 2015

Conversion of a vector to an integer and back can be done far more simply.

Firstly, you need to realise that the 3 components of a vector v can be accessed as v.x, v.y and v.z, so your process of casting a vector to a string and then parsing to a list is ... (words fail me)

Here is a simple method with similar effect to yours for decimal vectors (each component 0 thru 999)

integer Vector2IntDec(vector v)
{
    return ( 1000000 * (integer) v.x + 1000 * (integer) v.y + (integer) v.z);
}

vector Int2VectorDec(integer i)
{
    vector v;
    v.x = i / 1000000;
    v.y = (i % 1000000) / 1000 ;
    return <v.x, v.y, i % 1000>;
}

However, it's nicer to do the conversions using bit shifts. As an integer (in LSL) consists of 31 bits plus sign bit, we can comfortably allocate 10 bits to each vector component, allowing each component to hold a value in the range 0 to 1023.

integer Vector2Int(vector v)
{
    integer n = (integer) v.x << 20;
    n = n | ( (integer) v.y) << 10;
    return  n | ( integer) v.z;
}

vector Int2Vector(integer n)
{
    vector v;
    v.x = n >> 20;
    v.y = (n >> 10) & 0x3FF;
    return <v.x, v.y,  (n & 0x3FF) >;
}

(These examples have been compiled and tested using lslEditor and Mono)

Omei Qunhua 01:51, 27 December 2012 (PST)

Compressing a position vector to an integer

I was recently asked about sending a position vector to the nearest 0.5 metres as an integer.

// Code to compress an intra-region position vector to an integer and back again
// Omei Qunhua 12-March-2014
// Components of the vector are rounded down to the nearest 0.5 metres
// Correctly handles vectors where .x and .y are in the range 0.0 to 255.999 and .z is in the range 0.0 to 4095.999

integer Vector2Int(vector v)
{
    // Compress the input vector to an integer, using 9 bits each for .x and .y and 13 bits for .z
    
    integer j = ( (integer) (v.z * 2) << 18) + ( (integer) (v.y * 2)  << 9) |  (integer) (v.x * 2) ;
    // We could have used llRound() instead of (integer) but that would restrict a component to a maximum value of 255.499 (.x and .y) or 4095.499 (.z)

    // If any of the vector components is negative, or is too big, the resultant integer will convert back to quite a different vector
    // such that the distance between the input and result vectors will be significant.
    // We use this as a method of validating the input.
    if (llVecDist(v, Int2Vector(j) ) > 5.0)
        return -1;
    return j;
}

vector Int2Vector(integer j)
{
    vector pos;
    pos.x = j & 511;        // 511 decimal is  111,111,111 in binary 
    j = j >> 9;
    pos.y = j & 511;
    pos.z = j >> 9;
    return (pos / 2);
}

default
{
    state_entry()
    {
        vector pos = <128.8, 255.999, 4095.999>;

        integer j = Vector2Int(pos);
        if (j < 0)
            llSay(0, (string) pos + " is not valid for compression");
        else
        {
            llSay(0, (string) pos  +  " was compressed OK");
            vector pos2 = Int2Vector(j);
            llSay(0, "pos2=" + (string) pos2);
        }
    }
}