Created
August 5, 2016 16:51
-
-
Save meepen/2a39868232d4118fc00ac28b87e3f4d7 to your computer and use it in GitHub Desktop.
WriteCoordBitMP/ReadCoordBitMP in Garry's Mod Lua (for prediction fixing!!!)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local function encodefloat(f, bIntegral, bLowPrecision) | |
local signbit = (f <= -( bLowPrecision and COORD_RESOLUTION_LOWPRECISION or COORD_RESOLUTION )); | |
local intval = math.floor(math.abs(f)); | |
local fractval = bLowPrecision and | |
( bit.band(math.floor(math.abs(f*COORD_DENOMINATOR_LOWPRECISION)), (COORD_DENOMINATOR_LOWPRECISION-1))) or | |
( bit.band(math.floor(math.abs(f*COORD_DENOMINATOR)), (COORD_DENOMINATOR-1) )); | |
local bInBounds = intval < (2 ^ COORD_INTEGER_BITS_MP ); | |
--[[ unsigned ]] local intvalret, fractvalret | |
local INBOUNDS, INTVAL, SIGN | |
if ( bIntegral ) then | |
-- Integer encoding: in-bounds bit, nonzero bit, optional sign bit + integer value bits | |
if (0 ~= intval) then | |
-- Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] | |
intvalret = intval - 1; | |
SIGN = signbit | |
INBOUNDS = bInBounds | |
INTVAL = true | |
else | |
INBOUNDS = bInBounds | |
end | |
else | |
-- Float encoding: in-bounds bit, integer bit, sign bit, fraction value bits, optional integer value bits | |
if (intval ~= 0) then | |
-- Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] | |
intvalret = intval - 1; | |
SIGN = signbit | |
INBOUNDS = bInBounds | |
INTVAL = true | |
fractvalret = fractval | |
else | |
SIGN = signbit | |
INBOUNDS = bInBounds | |
INTVAL = false | |
fractvalret = fractval | |
end | |
end | |
return INBOUNDS, INTVAL, SIGN, intvalret, fractvalret; | |
end | |
local mul_table = | |
{ | |
1/(2^COORD_FRACTIONAL_BITS), | |
-1/(2^COORD_FRACTIONAL_BITS), | |
1/(2^COORD_FRACTIONAL_BITS_MP_LOWPRECISION), | |
-1/(2^COORD_FRACTIONAL_BITS_MP_LOWPRECISION) | |
}; | |
local function decodefloat(bIntegral, bLowPrecision, INBOUNDS, INTVAL, SIGN, intvalret, fractvalret) | |
-- BitCoordMP float encoding: inbounds bit, integer bit, sign bit, optional int bits, float bits | |
-- BitCoordMP integer encoding: inbounds bit, integer bit, optional sign bit, optional int bits. | |
-- int bits are always encoded as (value - 1) since zero is handled by the integer bit | |
-- With integer-only encoding, the presence of the third bit depends on the second | |
if ( bIntegral ) then | |
if ( INTVAL ) then | |
-- Read the third bit and the integer portion together at once | |
-- Remap from [0,N] to [1,N+1] | |
intval = math.floor(intvalret * 2^-1) + 1; | |
return (intvalret % 2 == 1) and -intval or intval; | |
end | |
return 0; | |
end | |
local bits = fractvalret | |
-- equivalent to: float multiply = mul_table[ ((flags & SIGN) ? 1 : 0) + bLowPrecision*2 ]; | |
--float multiply = *(float*)((uintptr_t)&mul_table[0] + (flags & 4) + bLowPrecision*8); | |
local multiply = mul_table[(SIGN and 1 or 0) + (bLowPrecision and 1 or 0)*2 + 1] | |
if ( INTVAL ) then | |
-- Shuffle the bits to remap the integer portion from [0,N] to [1,N+1] | |
-- and then paste in front of the fractional parts so we only need one | |
-- int-to-float conversion. | |
local fracbits = fractvalret | |
local intpart = intvalret | |
local intbitsLow = intpart * 2 ^ COORD_FRACTIONAL_BITS_MP_LOWPRECISION; | |
local intbits = intpart * 2 ^ COORD_FRACTIONAL_BITS; | |
local selectNotLow = (bLowPrecision and 1 or 0) - 1; | |
intbits = intbits - intbitsLow; | |
intbits = bit.band(intbits, selectNotLow); | |
intbits = intbits + intbitsLow; | |
bits = bit.bor(fracbits, intbits); | |
end | |
return math.floor(bits) * multiply; | |
end | |
local function networkedfloatencode(f) | |
return decodefloat(false, false, encodefloat(f, false, false)) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment