Add StreamBuffer functions for "ranges"

This reads / writes a float in the range of 0.0 to 1.0, but
with a uniform distribution instead of whatever it's called
that floating point values do.

This allows us to more efficiently store euler angles, which
can only have values between 0.0 and TAU. No more wasted bits!
main
copygirl 2 weeks ago
parent 0984148ee5
commit 9052c473ef
  1. 19
      stream_buffer.gd

@ -83,6 +83,10 @@ func write_vector32(value: Vector3) -> void: write_float32(value.x); write_float
func write_transform16(value: Transform3D) -> void: write_vector16(value.basis.x); write_vector16(value.basis.y); write_vector16(value.basis.z); write_vector16(value.origin)
func write_transform32(value: Transform3D) -> void: write_vector32(value.basis.x); write_vector32(value.basis.y); write_vector32(value.basis.z); write_vector32(value.origin)
func write_range8(value: float) -> void: write_uint8(roundi(value * 255))
func write_range16(value: float) -> void: write_uint16(roundi(value * 65535))
func write_range32(value: float) -> void: write_uint32(roundi(value * 4294967295))
func read_int8() -> int: assert(remaining_bytes() >= 1); var result := buffer.decode_s8(cursor); cursor += 1; bit = 0; return result
func read_int16() -> int: assert(remaining_bytes() >= 2); var result := buffer.decode_s16(cursor); cursor += 2; bit = 0; return result
@ -105,6 +109,10 @@ func read_vector32() -> Vector3: return Vector3(read_float32(), read_float32(),
func read_transform16() -> Transform3D: return Transform3D(Basis(read_vector16(), read_vector16(), read_vector16()), read_vector16())
func read_transform32() -> Transform3D: return Transform3D(Basis(read_vector32(), read_vector32(), read_vector32()), read_vector32())
func read_range8() -> float: return float(read_uint8()) / 255
func read_range16() -> float: return float(read_uint16()) / 65535
func read_range32() -> float: return float(read_uint32()) / 4294967295
func write_bit(value: bool) -> void:
if bit == 0: ensure_capacity(1); buffer[size] = 0; size += 1
@ -155,14 +163,9 @@ func write_bone_pose(value: Transform3D) -> void:
var has_rot := !rot.is_zero_approx()
var has_scale := !scale.is_equal_approx(Vector3.ONE)
var has_scale3 := !is_equal_approx(scale.x, scale.y) or !is_equal_approx(scale.x, scale.y)
write_bit(has_pos)
write_bit(has_rot)
write_bit(has_scale)
write_bit(has_scale3)
write_bit(has_pos); write_bit(has_rot); write_bit(has_scale); write_bit(has_scale3)
if has_pos: write_vector16(pos)
# TODO: Could optimize this by using 16-bit fixed-point values.
# Since these values can only be in the range 0 to 1.
if has_rot: write_vector16(rot)
if has_rot: write_range16(rot.x / TAU); write_range16(rot.y / TAU); write_range16(rot.z / TAU)
if has_scale3: write_vector16(scale)
elif has_scale: write_float16((scale.x + scale.y + scale.z) / 3)
@ -175,7 +178,7 @@ func read_bone_pose() -> Transform3D:
var has_scale := read_bit()
var has_scale3 := read_bit()
if has_pos: pos = read_vector16()
if has_rot: rot = read_vector16()
if has_rot: rot = Vector3(read_range16() * TAU, read_range16() * TAU, read_range16() * TAU)
if has_scale3: scale = read_vector16()
elif has_scale: var s := read_float16(); scale = Vector3(s, s, s)
var basis := Basis.from_scale(scale) * Basis.from_euler(rot)

Loading…
Cancel
Save