From a5a080994956e0a5059ab8f87819d938e57ca2b9 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 17 Jan 2021 15:27:19 +0100 Subject: [PATCH] gobj: Support integer texture formats in TexturePeeker --- panda/src/gobj/texturePeeker.cxx | 132 +++++++++++++++++++++++++------ tests/gobj/test_texture_peek.py | 64 +++++++++++++++ 2 files changed, 173 insertions(+), 23 deletions(-) diff --git a/panda/src/gobj/texturePeeker.cxx b/panda/src/gobj/texturePeeker.cxx index 03d9bff39d..ee82e4644b 100644 --- a/panda/src/gobj/texturePeeker.cxx +++ b/panda/src/gobj/texturePeeker.cxx @@ -14,6 +14,58 @@ #include "texturePeeker.h" +static double get_unsigned_byte_i(const unsigned char *&p) { + return *p++; +} + +static double get_signed_byte_i(const unsigned char *&p) { + return *(signed char *)p++; +} + +static double get_unsigned_short_i(const unsigned char *&p) { + union { + unsigned short us; + unsigned char uc[2]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + return (double)v.us; +} + +static double get_signed_short_i(const unsigned char *&p) { + union { + signed short ss; + unsigned char uc[2]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + return (double)v.ss; +} + +static double get_unsigned_int_i(const unsigned char *&p) { + union { + unsigned int ui; + unsigned char uc[4]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + v.uc[2] = (*p++); + v.uc[3] = (*p++); + return (double)v.ui; +} + +static double get_signed_int_i(const unsigned char *&p) { + union { + signed int si; + unsigned char uc[4]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + v.uc[2] = (*p++); + v.uc[3] = (*p++); + return (double)v.si; +} + /** * Use Texture::peek() to construct a TexturePeeker. * @@ -73,35 +125,69 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) { } _pixel_width = _component_width * _num_components; - switch (_component_type) { - case Texture::T_unsigned_byte: - _get_component = Texture::get_unsigned_byte; - break; + if (Texture::is_integer(_format)) { + switch (_component_type) { + case Texture::T_unsigned_byte: + _get_component = get_unsigned_byte_i; + break; - case Texture::T_unsigned_short: - _get_component = Texture::get_unsigned_short; - break; + case Texture::T_unsigned_short: + _get_component = get_unsigned_short_i; + break; - case Texture::T_unsigned_int: - _get_component = Texture::get_unsigned_int; - break; + case Texture::T_unsigned_int: + _get_component = get_unsigned_int_i; + break; - case Texture::T_float: - _get_component = Texture::get_float; - break; + case Texture::T_byte: + _get_component = get_signed_byte_i; + break; - case Texture::T_half_float: - _get_component = Texture::get_half_float; - break; + case Texture::T_short: + _get_component = get_signed_short_i; + break; - case Texture::T_unsigned_int_24_8: - _get_component = Texture::get_unsigned_int_24; - break; + case Texture::T_int: + _get_component = get_signed_int_i; + break; - default: - // Not supported. - _image.clear(); - return; + default: + // Not supported. + _image.clear(); + return; + } + } + else { + switch (_component_type) { + case Texture::T_unsigned_byte: + _get_component = Texture::get_unsigned_byte; + break; + + case Texture::T_unsigned_short: + _get_component = Texture::get_unsigned_short; + break; + + case Texture::T_unsigned_int: + _get_component = Texture::get_unsigned_int; + break; + + case Texture::T_float: + _get_component = Texture::get_float; + break; + + case Texture::T_half_float: + _get_component = Texture::get_half_float; + break; + + case Texture::T_unsigned_int_24_8: + _get_component = Texture::get_unsigned_int_24; + break; + + default: + // Not supported. + _image.clear(); + return; + } } switch (_format) { diff --git a/tests/gobj/test_texture_peek.py b/tests/gobj/test_texture_peek.py index accd1b02d0..b113312dbb 100644 --- a/tests/gobj/test_texture_peek.py +++ b/tests/gobj/test_texture_peek.py @@ -94,3 +94,67 @@ def test_texture_peek_srgba(): # We allow some imprecision. assert col.almost_equal((0.5, 0.5, 0.5, 188 / 255.0), 1 / 255.0) + + +def test_texture_peek_ubyte_i(): + maxval = 255 + data = array('B', (2, 1, 0, maxval)) + peeker = peeker_from_pixel(Texture.T_unsigned_byte, Texture.F_rgba8i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (0, 1, 2, maxval) + + +def test_texture_peek_byte_i(): + minval = -128 + maxval = 127 + data = array('b', (0, -1, minval, maxval)) + peeker = peeker_from_pixel(Texture.T_byte, Texture.F_rgba8i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (minval, -1, 0, maxval) + + +def test_texture_peek_ushort_i(): + maxval = 65535 + data = array('H', (2, 1, 0, maxval)) + peeker = peeker_from_pixel(Texture.T_unsigned_short, Texture.F_rgba16i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (0, 1, 2, maxval) + + +def test_texture_peek_short_i(): + minval = -32768 + maxval = 32767 + data = array('h', (0, -1, minval, maxval)) + peeker = peeker_from_pixel(Texture.T_short, Texture.F_rgba16i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (minval, -1, 0, maxval) + + +def test_texture_peek_uint_i(): + # Highest integer that fits inside float + maxval = 2147483648 + data = array('I', (2, 1, 0, maxval)) + peeker = peeker_from_pixel(Texture.T_unsigned_int, Texture.F_rgba32i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (0, 1, 2, maxval) + + +def test_texture_peek_int_i(): + minval = -2147483648 + maxval = 2147483647 + data = array('i', (0, -1, minval, maxval)) + peeker = peeker_from_pixel(Texture.T_int, Texture.F_rgba32i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (minval, -1, 0, maxval)