Browse Source

gobj: Support integer texture formats in TexturePeeker

rdb 4 years ago
parent
commit
a5a0809949
2 changed files with 173 additions and 23 deletions
  1. 109 23
      panda/src/gobj/texturePeeker.cxx
  2. 64 0
      tests/gobj/test_texture_peek.py

+ 109 - 23
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) {

+ 64 - 0
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)