Offset Compression

From Second Life Wiki
Revision as of 06:36, 16 December 2015 by Haravikk Mistral (talk | contribs) (Created page with "{{LSL Header}} = Offset Compression = I have often found in scripts that move objects or involve a lot of possible animations, that I have to handle (and store) a large number...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Offset Compression

I have often found in scripts that move objects or involve a lot of possible animations, that I have to handle (and store) a large number of vector and rotation pairs describing offsets. Since each vector is three floats, and each rotation is four floats, and each float is 32-bits, that's 224 bits of data, plus overhead for lists. However, the rotation is normalised to ensure that its components never exceed a total of 1.0, meanwhile and offset vector rarely needs to be larger than 10 metres (the furthest a linked prim can be moved from its parent in most cases), as a result there is a lot of precision in that rotation that isn't really being used, since rotations don't generally need to be super-precise, and rarely so when used as part of an offset.

As a result I've designed the following functions to make it easy to store a vector plus a rotation in either a single vector or rotation value depending upon your requirements.

Offset as Rotation

This method works by adding the vector values into the integer part of the corresponding rotation value by multiplying it by 1000 and rounding; this restricts the vector's precision to three decimal places, but is nice and simple. Rotations must be normalised before being passed to this function otherwise it will not decompress properly; any rotation retrieved using a standard LSL function should be okay, but user provided values should be normalised first.

In tests, there is an error of up to 0.5 degrees for the rotation; this should be precise enough for most use cases, but may become more noticeable with larger objects.

Functions

rotation offsetAsRot(vector offsetPos, rotation offsetRot) {
    return <
        (float)((integer)(offsetPos.x * 1000.0) * 10) + ((float)(((offsetPos.x < 0) * -2) + 1) * (offsetRot.x + 1.0)), 
        (float)((integer)(offsetPos.y * 1000.0) * 10) + ((float)(((offsetPos.y < 0) * -2) + 1) * (offsetRot.y + 1.0)), 
        (float)((integer)(offsetPos.z * 1000.0) * 10) + ((float)(((offsetPos.z < 0) * -2) + 1) * (offsetRot.z + 1.0)), 
        offsetRot.s
    >;
}
vector offsetVectorFromRot(rotation offset) {
    return <
        (float)((integer)(offset.x / 10.0)) / 1000.0, 
        (float)((integer)(offset.y / 10.0)) / 1000.0, 
        (float)((integer)(offset.z / 10.0)) / 1000.0
    >;
}
rotation offsetRotFromRot(rotation offset) {
    offset = <
        (offset.x - ((integer)(offset.x / 10.0) * 10)) * (float)(((offset.x < 0) * -2) + 1) - 1.0,
        (offset.y - ((integer)(offset.y / 10.0) * 10)) * (float)(((offset.y < 0) * -2) + 1) - 1.0,
        (offset.z - ((integer)(offset.z / 10.0) * 10)) * (float)(((offset.z < 0) * -2) + 1) - 1.0,
        offset.s
    >;
    float mag = llSqrt((offset.x * offset.x) + (offset.y * offset.y) + (offset.z * offset.z) + (offset.s * offset.s));
    return <offset.x / mag, offset.y / mag, offset.z / mag, offset.s / mag>;
}