Browse Source

Add packed unsigned 11/10/10-bit floating point vertex format

rdb 10 years ago
parent
commit
fdc8918946

+ 50 - 20
panda/src/glstuff/glGeomMunger_src.cxx

@@ -92,7 +92,8 @@ munge_format_impl(const GeomVertexFormat *orig,
   // and texture coordinates.
   const GeomVertexColumn *vertex_type = orig->get_vertex_column();
   if (vertex_type != (GeomVertexColumn *)NULL &&
-      vertex_type->get_numeric_type() == NT_int8) {
+      (vertex_type->get_numeric_type() == NT_int8 ||
+       vertex_type->get_numeric_type() == NT_uint8)) {
     int vertex_array = orig->get_array_with(InternalName::get_vertex());
 
     PT(GeomVertexArrayFormat) new_array_format = new_format->modify_array(vertex_array);
@@ -102,7 +103,29 @@ munge_format_impl(const GeomVertexFormat *orig,
       (InternalName::get_vertex(), 3, NT_int16,
        C_point, vertex_type->get_start(), vertex_type->get_column_alignment());
   }
-#endif
+
+  // Convert packed formats that OpenGL may not understand.
+  for (int i = 0; i < orig->get_num_columns(); ++i) {
+    const GeomVertexColumn *column = orig->get_column(i);
+    int array = orig->get_array_with(column->get_name());
+
+    if (column->get_numeric_type() == NT_packed_dabc &&
+        !glgsg->_supports_packed_dabc) {
+      // Unpack the packed ARGB color into its four byte components.
+      PT(GeomVertexArrayFormat) array_format = new_format->modify_array(array);
+      array_format->add_column(column->get_name(), 4, NT_uint8, C_color,
+                               column->get_start(), column->get_column_alignment());
+
+    } else if (column->get_numeric_type() == NT_packed_ufloat &&
+               !glgsg->_supports_packed_ufloat) {
+      // Unpack to three 32-bit floats.  (In future, should try 16-bit float)
+      PT(GeomVertexArrayFormat) array_format = new_format->modify_array(array);
+      array_format->add_column(column->get_name(), 3, NT_float32,
+                               column->get_contents(), column->get_start(),
+                               column->get_column_alignment());
+    }
+  }
+#endif  // !OPENGLES
 
   const GeomVertexColumn *color_type = orig->get_color_column();
   if (color_type != (GeomVertexColumn *)NULL &&
@@ -116,8 +139,8 @@ munge_format_impl(const GeomVertexFormat *orig,
 
     // Replace the existing color format with the new format.
     new_array_format->add_column
-      (InternalName::get_color(), 4, NT_uint8,
-       C_color, color_type->get_start(), color_type->get_column_alignment());
+      (InternalName::get_color(), 4, NT_uint8, C_color,
+       color_type->get_start(), color_type->get_column_alignment());
   }
 
   if (animation.get_animation_type() == AT_hardware) {
@@ -259,7 +282,8 @@ premunge_format_impl(const GeomVertexFormat *orig) {
   // and texture coordinates.
   const GeomVertexColumn *vertex_type = orig->get_vertex_column();
   if (vertex_type != (GeomVertexColumn *)NULL &&
-      vertex_type->get_numeric_type() == NT_int8) {
+      (vertex_type->get_numeric_type() == NT_int8 ||
+       vertex_type->get_numeric_type() == NT_uint8)) {
     int vertex_array = orig->get_array_with(InternalName::get_vertex());
 
     PT(GeomVertexArrayFormat) new_array_format = new_format->modify_array(vertex_array);
@@ -269,23 +293,29 @@ premunge_format_impl(const GeomVertexFormat *orig) {
       (InternalName::get_vertex(), 3, NT_int16,
        C_point, vertex_type->get_start(), vertex_type->get_column_alignment());
   }
-#endif
-
-  const GeomVertexColumn *color_type = orig->get_color_column();
-  if (color_type != (GeomVertexColumn *)NULL &&
-      color_type->get_numeric_type() == NT_packed_dabc &&
-      !glgsg->_supports_packed_dabc) {
-    // We need to convert the color format; OpenGL doesn't support the
-    // byte order of DirectX's packed ARGB format.
-    int color_array = orig->get_array_with(InternalName::get_color());
 
-    PT(GeomVertexArrayFormat) new_array_format = new_format->modify_array(color_array);
-
-    // Replace the existing color format with the new format.
-    new_array_format->add_column
-      (InternalName::get_color(), 4, NT_uint8,
-       C_color, color_type->get_start(), color_type->get_column_alignment());
+  // Convert packed formats that OpenGL may not understand.
+  for (int i = 0; i < orig->get_num_columns(); ++i) {
+    const GeomVertexColumn *column = orig->get_column(i);
+    int array = orig->get_array_with(column->get_name());
+
+    if (column->get_numeric_type() == NT_packed_dabc &&
+        !glgsg->_supports_packed_dabc) {
+      // Unpack the packed ARGB color into its four byte components.
+      PT(GeomVertexArrayFormat) array_format = new_format->modify_array(array);
+      array_format->add_column(column->get_name(), 4, NT_uint8, C_color,
+                               column->get_start(), column->get_column_alignment());
+
+    } else if (column->get_numeric_type() == NT_packed_ufloat &&
+               !glgsg->_supports_packed_ufloat) {
+      // Unpack to three 32-bit floats.  (In future, should try 16-bit float)
+      PT(GeomVertexArrayFormat) array_format = new_format->modify_array(array);
+      array_format->add_column(column->get_name(), 3, NT_float32,
+                               column->get_contents(), column->get_start(),
+                               column->get_column_alignment());
+    }
   }
+#endif  // !OPENGLES
 
   CPT(GeomVertexFormat) format = GeomVertexFormat::register_format(new_format);
 

+ 11 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1012,10 +1012,13 @@ reset() {
 
 #ifdef OPENGLES
   _supports_packed_dabc = false;
+  _supports_packed_ufloat = false;
 #else
   _supports_packed_dabc = is_at_least_gl_version(3, 2) ||
                           has_extension("GL_ARB_vertex_array_bgra") ||
                           has_extension("GL_EXT_vertex_array_bgra");
+  _supports_packed_ufloat = is_at_least_gl_version(4, 4) ||
+                            has_extension("GL_ARB_vertex_type_10f_11f_11f_rev");
 #endif
 
   _supports_multisample =
@@ -3707,7 +3710,7 @@ update_standard_vertex_arrays(bool force) {
         return false;
       }
       glVertexPointer(num_values, get_numeric_type(numeric_type),
-                         stride, client_pointer + start);
+                      stride, client_pointer + start);
       glEnableClientState(GL_VERTEX_ARRAY);
     }
   }
@@ -7380,6 +7383,13 @@ get_numeric_type(Geom::NumericType numeric_type) {
 
   case Geom::NT_int32:
     return GL_INT;
+
+  case Geom::NT_packed_ufloat:
+#ifndef OPENGLES
+    return GL_UNSIGNED_INT_10F_11F_11F_REV;
+#else
+    break;
+#endif
   }
 
   GLCAT.error()

+ 1 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -713,6 +713,7 @@ public:
   bool _supports_bgr;
   bool _supports_rescale_normal;
   bool _supports_packed_dabc;
+  bool _supports_packed_ufloat;
 
   PFNGLACTIVETEXTUREPROC _glActiveTexture;
 #ifndef OPENGLES_2

+ 2 - 2
panda/src/glstuff/glShaderContext_src.cxx

@@ -2002,8 +2002,8 @@ glsl_compile_and_link() {
   //  glsl_report_shader_errors(*it);
   //}
 
-  // Under core OpenGL, we have to make sure that we bind something to
-  // attribute 0.  Make sure that this is the position array.
+  // Under OpenGL's compatibility profile, we have to make sure that we bind
+  // something to attribute 0.  Make sure that this is the position array.
   _glgsg->_glBindAttribLocation(_glsl_program, 0, "p3d_Vertex");
   _glgsg->_glBindAttribLocation(_glsl_program, 0, "vertex");
 

+ 3 - 0
panda/src/gobj/geomEnums.cxx

@@ -110,6 +110,9 @@ operator << (ostream &out, GeomEnums::NumericType numeric_type) {
 
   case GeomEnums::NT_int32:
     return out << "int32";
+
+  case GeomEnums::NT_packed_ufloat:
+    return out << "packed_ufloat";
   }
 
   return out << "**invalid numeric type (" << (int)numeric_type << ")**";

+ 1 - 0
panda/src/gobj/geomEnums.h

@@ -186,6 +186,7 @@ PUBLISHED:
     NT_int8,         // An integer -128..127
     NT_int16,        // An integer -32768..32767
     NT_int32,        // An integer -2147483648..2147483647
+    NT_packed_ufloat,// Three 10/11-bit float components packed in a uint32
   };
 
   // The contents determine the semantic meaning of a numeric value

+ 179 - 3
panda/src/gobj/geomVertexColumn.cxx

@@ -153,6 +153,7 @@ output(ostream &out) const {
     break;
 
   case NT_stdfloat:
+  case NT_packed_ufloat:
     out << "?";
     break;
   }
@@ -214,6 +215,11 @@ setup() {
   case NT_stdfloat:
     nassertv(false);
     break;
+
+  case NT_packed_ufloat:
+    _component_bytes = 4;  // sizeof(PN_uint32)
+    _num_values *= 3;
+    break;
   }
 
   if (_contents == C_matrix) {
@@ -483,6 +489,12 @@ get_data1f(const unsigned char *pointer) {
   case NT_int32:
     return *(const PN_int32 *)pointer;
 
+  case NT_packed_ufloat:
+    {
+      PN_uint32 dword = *(const PN_uint32 *)pointer;
+      return GeomVertexData::unpack_ufloat_a(dword);
+    }
+
   default:
     nassertr(false, 0.0f);
   }
@@ -578,6 +590,10 @@ get_data2f(const unsigned char *pointer) {
         _v2.set(pi[0], pi[1]);
       }
       return _v2;
+
+    case NT_packed_ufloat:
+      nassertr(false, _v2);
+      return _v2;
     }
   }
 
@@ -682,6 +698,15 @@ get_data3f(const unsigned char *pointer) {
         _v3.set(pi[0], pi[1], pi[2]);
       }
       return _v3;
+
+    case NT_packed_ufloat:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _v3.set(GeomVertexData::unpack_ufloat_a(dword),
+                GeomVertexData::unpack_ufloat_b(dword),
+                GeomVertexData::unpack_ufloat_c(dword));
+      }
+      return _v3;
     }
   }
 
@@ -795,6 +820,10 @@ get_data4f(const unsigned char *pointer) {
         _v4.set(pi[0], pi[1], pi[2], pi[3]);
       }
       return _v4;
+
+    case NT_packed_ufloat:
+      nassertr(false, _v4);
+      break;
     }
   }
 
@@ -837,8 +866,8 @@ get_data1d(const unsigned char *pointer) {
     return *(const PN_float64 *)pointer;
 
   case NT_stdfloat:
-    nassertr(false, 0.0f);
-    return 0.0f;
+    nassertr(false, 0.0);
+    return 0.0;
 
   case NT_int8:
     return *(const PN_int8 *)pointer;
@@ -848,9 +877,15 @@ get_data1d(const unsigned char *pointer) {
 
   case NT_int32:
     return *(const PN_int32 *)pointer;
+
+  case NT_packed_ufloat:
+    {
+      PN_uint32 dword = *(const PN_uint32 *)pointer;
+      return GeomVertexData::unpack_ufloat_a(dword);
+    }
   }
 
-  return 0.0f;
+  return 0.0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -941,6 +976,10 @@ get_data2d(const unsigned char *pointer) {
         _v2d.set(pi[0], pi[1]);
       }
       return _v2d;
+
+    case NT_packed_ufloat:
+      nassertr(false, _v2d);
+      break;
     }
   }
 
@@ -1045,6 +1084,15 @@ get_data3d(const unsigned char *pointer) {
         _v3d.set(pi[0], pi[1], pi[2]);
       }
       return _v3d;
+
+    case NT_packed_ufloat:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _v3d.set(GeomVertexData::unpack_ufloat_a(dword),
+                 GeomVertexData::unpack_ufloat_b(dword),
+                 GeomVertexData::unpack_ufloat_c(dword));
+      }
+      return _v3d;
     }
   }
 
@@ -1158,6 +1206,10 @@ get_data4d(const unsigned char *pointer) {
         _v4d.set(pi[0], pi[1], pi[2], pi[3]);
       }
       return _v4d;
+
+    case NT_packed_ufloat:
+      nassertr(false, _v4d);
+      break;
     }
   }
 
@@ -1211,6 +1263,12 @@ get_data1i(const unsigned char *pointer) {
 
   case NT_int32:
     return *(const PN_int32 *)pointer;
+
+  case NT_packed_ufloat:
+    {
+      PN_uint32 dword = *(const PN_uint32 *)pointer;
+      return (int)GeomVertexData::unpack_ufloat_a(dword);
+    }
   }
 
   return 0;
@@ -1302,6 +1360,10 @@ get_data2i(const unsigned char *pointer) {
         _v2i.set(pi[0], pi[1]);
       }
       return _v2i;
+
+    case NT_packed_ufloat:
+      nassertr(false, _v2i);
+      break;
     }
   }
 
@@ -1403,6 +1465,15 @@ get_data3i(const unsigned char *pointer) {
         _v3i.set(pi[0], pi[1], pi[2]);
       }
       return _v3i;
+
+    case NT_packed_ufloat:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _v3i.set((int)GeomVertexData::unpack_ufloat_a(dword),
+                 (int)GeomVertexData::unpack_ufloat_b(dword),
+                 (int)GeomVertexData::unpack_ufloat_c(dword));
+      }
+      return _v3i;
     }
   }
 
@@ -1513,6 +1584,10 @@ get_data4i(const unsigned char *pointer) {
         _v4i.set(pi[0], pi[1], pi[2], pi[3]);
       }
       return _v4i;
+
+    case NT_packed_ufloat:
+      nassertr(false, _v4i);
+      break;
     }
   }
 
@@ -1569,6 +1644,10 @@ set_data1f(unsigned char *pointer, float data) {
     case NT_int32:
       *(PN_int32 *)pointer = (int)data;
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
 
@@ -1596,6 +1675,7 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) {
   switch (_column->get_num_values()) {
   case 1:
     set_data1f(pointer, data[0]);
+    break;
 
   case 2:
     switch (_column->get_numeric_type()) {
@@ -1671,6 +1751,10 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) {
         pi[1] = (int)data[1];
       }
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
 
@@ -1782,6 +1866,10 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) {
         pi[2] = (int)data[2];
       }
       break;
+
+    case NT_packed_ufloat:
+      *(PN_uint32 *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]);
+      break;
     }
     break;
 
@@ -1904,6 +1992,10 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) {
         pi[3] = (int)data[3];
       }
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
   }
@@ -1959,6 +2051,10 @@ set_data1d(unsigned char *pointer, double data) {
     case NT_int32:
       *(PN_int32 *)pointer = (int)data;
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
 
@@ -2061,6 +2157,10 @@ set_data2d(unsigned char *pointer, const LVecBase2d &data) {
         pi[1] = (int)data[1];
       }
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
 
@@ -2172,6 +2272,10 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) {
         pi[2] = (int)data[2];
       }
       break;
+
+    case NT_packed_ufloat:
+      *(PN_uint32 *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]);
+      break;
     }
     break;
 
@@ -2294,6 +2398,10 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) {
         pi[3] = (int)data[3];
       }
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
   }
@@ -2353,6 +2461,10 @@ set_data1i(unsigned char *pointer, int data) {
     case NT_int32:
       *(PN_int32 *)pointer = data;
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
 
@@ -2453,6 +2565,10 @@ set_data2i(unsigned char *pointer, const LVecBase2i &data) {
         pi[1] = data[1];
       }
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
 
@@ -2561,6 +2677,10 @@ set_data3i(unsigned char *pointer, const LVecBase3i &data) {
         pi[2] = data[2];
       }
       break;
+
+    case NT_packed_ufloat:
+      *(PN_uint32 *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]);
+      break;
     }
     break;
 
@@ -2680,6 +2800,10 @@ set_data4i(unsigned char *pointer, const LVecBase4i &data) {
         pi[3] = data[3];
       }
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
   }
@@ -2839,6 +2963,10 @@ get_data4f(const unsigned char *pointer) {
         _v4.set(pi[0], pi[1], pi[2], pi[3]);
       }
       return _v4;
+
+    case NT_packed_ufloat:
+      nassertr(false, _v4);
+      break;
     }
   }
 
@@ -2999,6 +3127,10 @@ get_data4d(const unsigned char *pointer) {
         _v4d.set(pi[0], pi[1], pi[2], pi[3]);
       }
       return _v4d;
+
+    case NT_packed_ufloat:
+      nassertr(false, _v4d);
+      break;
     }
   }
 
@@ -3160,6 +3292,10 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) {
         pi[3] = (int)data[3];
       }
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
   }
@@ -3320,6 +3456,10 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) {
         pi[3] = (int)data[3];
       }
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
     break;
   }
@@ -3443,6 +3583,15 @@ get_data3f(const unsigned char *pointer) {
     case NT_int32:
       nassertr(false, _v3);
       return _v3;
+
+    case NT_packed_ufloat:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _v3.set(GeomVertexData::unpack_ufloat_a(dword),
+                GeomVertexData::unpack_ufloat_b(dword),
+                GeomVertexData::unpack_ufloat_c(dword));
+      }
+      return _v3;
     }
   } else {
     const LVecBase4f &v4 = get_data4f(pointer);
@@ -3528,6 +3677,7 @@ get_data4f(const unsigned char *pointer) {
     case NT_int8:
     case NT_int16:
     case NT_int32:
+    case NT_packed_ufloat:
       nassertr(false, _v4);
       return _v4;
     }
@@ -3652,6 +3802,15 @@ get_data3d(const unsigned char *pointer) {
     case NT_int32:
       nassertr(false, _v3d);
       return _v3d;
+
+    case NT_packed_ufloat:
+      {
+        PN_uint32 dword = *(const PN_uint32 *)pointer;
+        _v3d.set(GeomVertexData::unpack_ufloat_a(dword),
+                 GeomVertexData::unpack_ufloat_b(dword),
+                 GeomVertexData::unpack_ufloat_c(dword));
+      }
+      return _v3d;
     }
   } else {
     const LVecBase4d &v4 = get_data4d(pointer);
@@ -3737,6 +3896,7 @@ get_data4d(const unsigned char *pointer) {
     case NT_int8:
     case NT_int16:
     case NT_int32:
+    case NT_packed_ufloat:
       nassertr(false, _v4d);
       return _v4d;
     }
@@ -3850,6 +4010,10 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) {
     case NT_int32:
       nassertv(false);
       break;
+
+    case NT_packed_ufloat:
+      *(PN_uint32 *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]);
+      break;
     }
   } else {
     set_data4f(pointer, LVecBase4f(data[0], data[1], data[2], 1.0f));
@@ -3942,6 +4106,10 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) {
     case NT_int32:
       nassertv(false);
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
   }
 }
@@ -4053,6 +4221,10 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) {
     case NT_int32:
       nassertv(false);
       break;
+
+    case NT_packed_ufloat:
+      *(PN_uint32 *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]);
+      break;
     }
   } else {
     set_data4d(pointer, LVecBase4d(data[0], data[1], data[2], 1.0f));
@@ -4145,6 +4317,10 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) {
     case NT_int32:
       nassertv(false);
       break;
+
+    case NT_packed_ufloat:
+      nassertv(false);
+      break;
     }
   }
 }

+ 144 - 0
panda/src/gobj/geomVertexData.I

@@ -403,6 +403,150 @@ unpack_abcd_d(PN_uint32 data) {
   return data & 0xff;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexData::pack_ufloat
+//       Access: Public, Static
+//  Description: Packs three float values in an unsigned 32-bit int.
+////////////////////////////////////////////////////////////////////
+INLINE PN_uint32 GeomVertexData::
+pack_ufloat(float a, float b, float c) {
+  // Since we have to clamp both low exponents and negative numbers to 0,
+  // it's easier to see a float as having a 9-bit signed exponent.
+  union {
+    PN_int32 _packed;
+    float _float;
+  } f0, f1, f2;
+
+  f0._float = a;
+  f1._float = b;
+  f2._float = c;
+
+  // There are several cases here:
+  // 1. exponent 0xff: NaN or infinity (negative infinity excluded)
+  // 2. exponent too large: clamped to maximum value
+  // 3. normalized float
+  // 4. exponent 0: denormal float
+  // 5. zero or anything negative, clamped to 0
+
+  PN_uint32 packed = 0;
+
+  if ((f0._packed & 0x7f800000) == 0x7f800000 && (unsigned)f0._packed != 0xff800000u) {
+    packed |= (f0._packed >> 17) & 0x7ffu;
+  } else if (f0._packed >= 0x47800000) {
+    packed |= 0x7bf;
+  } else if (f0._packed >= 0x38800000) {
+    packed |= (f0._packed >> 17) - 0x1c00;
+  } else if (f0._packed >= 0x35000000) {
+    packed |= ((f0._packed & 0x7c0000u) | 0x800000u) >> (130 - (f0._packed >> 23));
+  }
+
+  if ((f1._packed & 0x7f800000) == 0x7f800000 && (unsigned)f1._packed != 0xff800000u) {
+    packed |= (f1._packed >> 6) & 0x3ff800u;
+  } else if (f1._packed >= 0x47800000) {
+    packed |= 0x3df800;
+  } else if (f1._packed >= 0x38800000) {
+    packed |= ((f1._packed >> 6) - 0xe00000) & 0x3ff800;
+  } else if (f1._packed >= 0x35000000) {
+    packed |= (((f1._packed & 0x7c0000u) | 0x800000u) >> (119 - (f1._packed >> 23))) & 0x1f800u;
+  }
+
+  if ((f2._packed & 0x7f800000) == 0x7f800000 && (unsigned)f2._packed != 0xff800000u) {
+    packed |= (f2._packed & 0x0ffe0000u) << 4;
+  } else if (f2._packed >= 0x47800000) {
+    packed |= 0xf7c00000;
+  } else if (f2._packed >= 0x38800000) {
+    packed |= ((f2._packed - 0x38000000) << 4) & 0xffc00000;
+  } else if (f2._packed >= 0x35000000) {
+    packed |= ((((f2._packed << 3) & 0x03c00000u) | 0x04000000u) >> (112 - (f2._packed >> 23))) & 0x07c00000u;
+  }
+
+  return packed;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexData::unpack_ufloat_a
+//       Access: Public, Static
+//  Description: Unpacks an unsigned float11 value from an uint32.
+////////////////////////////////////////////////////////////////////
+INLINE float GeomVertexData::
+unpack_ufloat_a(PN_uint32 data) {
+  if ((data & 0x7c0) == 0) {
+    // Denormal float (includes zero).
+    return ldexpf((data & 63) / 64.0f, -14);
+  }
+
+  union {
+    PN_uint32 _packed;
+    float _float;
+  } value;
+  value._packed = ((data & 0x7ff) << 17);
+
+  if ((data & 0x7c0) == 0x7c0) {
+    // Infinity / NaN
+    value._packed |= 0x7f800000;
+  } else {
+    value._packed += 0x38000000;
+  }
+
+  return value._float;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexData::unpack_ufloat_b
+//       Access: Public, Static
+//  Description: Unpacks an unsigned float11 value from an uint32.
+////////////////////////////////////////////////////////////////////
+INLINE float GeomVertexData::
+unpack_ufloat_b(PN_uint32 data) {
+  if ((data & 0x3e0000) == 0) {
+    // Denormal float (includes zero).
+    return ldexpf(((data >> 11) & 63) / 64.0f, -14);
+  }
+
+  union {
+    PN_uint32 _packed;
+    float _float;
+  } value;
+  value._packed = ((data & 0x3ff800) << 6);
+
+  if ((data & 0x3e0000) == 0x3e0000) {
+    // Infinity / NaN
+    value._packed |= 0x7f800000;
+  } else {
+    value._packed += 0x38000000;
+  }
+
+  return value._float;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexData::unpack_ufloat_c
+//       Access: Public, Static
+//  Description: Unpacks an unsigned float10 value from an uint32.
+////////////////////////////////////////////////////////////////////
+INLINE float GeomVertexData::
+unpack_ufloat_c(PN_uint32 data) {
+  if ((data & 0xf8000000u) == 0) {
+    // Denormal float (includes zero).
+    return ldexpf(((data >> 22) & 31) / 32.0f, -14);
+  }
+
+  union {
+    PN_uint32 _packed;
+    float _float;
+  } value;
+  value._packed = ((data & 0xffc00000u) >> 4);
+
+  if ((data & 0xf8000000u) == 0xf8000000u) {
+    // Infinity / NaN
+    value._packed |= 0x7f800000;
+  } else {
+    value._packed += 0x38000000;
+  }
+
+  return value._float;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexData::add_transform
 //       Access: Private, Static

+ 9 - 1
panda/src/gobj/geomVertexData.cxx

@@ -2579,7 +2579,7 @@ set_num_rows(int n) {
       while (pointer < stop) {
         PN_float64 *pi = (PN_float64 *)pointer;
         for (int i = 0; i < num_values; i++) {
-          pi[i] = 1.0f;
+          pi[i] = 1.0;
         }
         pointer += stride;
       }
@@ -2591,6 +2591,14 @@ set_num_rows(int n) {
     case NT_int32:
       // Shouldn't have this type in the format.
       nassertr(false, false);
+      break;
+
+    case NT_packed_ufloat:
+      while (pointer < stop) {
+        *(PN_int32 *)pointer = 0x781e03c0;
+        pointer += stride;
+      }
+      break;
     }
   }
 

+ 5 - 0
panda/src/gobj/geomVertexData.h

@@ -176,6 +176,11 @@ public:
   static INLINE unsigned int unpack_abcd_c(PN_uint32 data);
   static INLINE unsigned int unpack_abcd_d(PN_uint32 data);
 
+  static INLINE PN_uint32 pack_ufloat(float a, float b, float c);
+  static INLINE float unpack_ufloat_a(PN_uint32 data);
+  static INLINE float unpack_ufloat_b(PN_uint32 data);
+  static INLINE float unpack_ufloat_c(PN_uint32 data);
+
 private:
   static void bytewise_copy(unsigned char *to, int to_stride,
                             const unsigned char *from, int from_stride,