فهرست منبع

Add integer vectors. Also add __pow__ operator to vectors.

rdb 11 سال پیش
والد
کامیت
5dae464394
91فایلهای تغییر یافته به همراه1440 افزوده شده و 622 حذف شده
  1. 22 0
      dtool/src/dtoolbase/cmath.I
  2. 2 0
      dtool/src/dtoolbase/cmath.h
  3. 8 1
      dtool/src/dtoolbase/nearly_zero.h
  4. 2 0
      dtool/src/pystub/pystub.cxx
  5. 60 12
      panda/src/display/windowProperties.I
  6. 8 14
      panda/src/display/windowProperties.cxx
  7. 11 7
      panda/src/display/windowProperties.h
  8. 6 6
      panda/src/glstuff/glImmediateModeSender_src.cxx
  9. 154 198
      panda/src/gobj/geomVertexColumn.cxx
  10. 10 8
      panda/src/gobj/geomVertexColumn.h
  11. 1 1
      panda/src/gobj/geomVertexData.cxx
  12. 6 6
      panda/src/gobj/geomVertexReader.I
  13. 3 3
      panda/src/gobj/geomVertexReader.h
  14. 63 21
      panda/src/gobj/geomVertexWriter.I
  15. 6 3
      panda/src/gobj/geomVertexWriter.h
  16. 2 2
      panda/src/linmath/Sources.pp
  17. 11 0
      panda/src/linmath/config_linmath.cxx
  18. 1 1
      panda/src/linmath/dblnames.h
  19. 1 0
      panda/src/linmath/fltnames.h
  20. 46 0
      panda/src/linmath/intnames.h
  21. 2 0
      panda/src/linmath/lpoint2.cxx
  22. 2 0
      panda/src/linmath/lpoint2.h
  23. 3 0
      panda/src/linmath/lpoint2_ext.h
  24. 13 1
      panda/src/linmath/lpoint2_ext_src.I
  25. 2 0
      panda/src/linmath/lpoint2_src.I
  26. 3 0
      panda/src/linmath/lpoint2_src.h
  27. 2 0
      panda/src/linmath/lpoint3.cxx
  28. 2 0
      panda/src/linmath/lpoint3.h
  29. 3 0
      panda/src/linmath/lpoint3_ext.h
  30. 13 1
      panda/src/linmath/lpoint3_ext_src.I
  31. 15 2
      panda/src/linmath/lpoint3_src.I
  32. 6 1
      panda/src/linmath/lpoint3_src.h
  33. 2 0
      panda/src/linmath/lpoint4.cxx
  34. 3 0
      panda/src/linmath/lpoint4.h
  35. 3 0
      panda/src/linmath/lpoint4_ext.h
  36. 14 2
      panda/src/linmath/lpoint4_ext_src.I
  37. 13 1
      panda/src/linmath/lpoint4_src.I
  38. 4 0
      panda/src/linmath/lpoint4_src.h
  39. 18 9
      panda/src/linmath/luse.N
  40. 3 0
      panda/src/linmath/lvec2_ops.h
  41. 2 1
      panda/src/linmath/lvec2_ops_src.I
  42. 2 1
      panda/src/linmath/lvec2_ops_src.h
  43. 2 0
      panda/src/linmath/lvec3_ops.h
  44. 2 2
      panda/src/linmath/lvec3_ops_src.I
  45. 2 1
      panda/src/linmath/lvec3_ops_src.h
  46. 2 0
      panda/src/linmath/lvec4_ops.h
  47. 2 1
      panda/src/linmath/lvec4_ops_src.I
  48. 2 2
      panda/src/linmath/lvec4_ops_src.h
  49. 2 0
      panda/src/linmath/lvecBase2.cxx
  50. 4 0
      panda/src/linmath/lvecBase2.h
  51. 3 0
      panda/src/linmath/lvecBase2_ext.h
  52. 67 5
      panda/src/linmath/lvecBase2_ext_src.I
  53. 3 0
      panda/src/linmath/lvecBase2_ext_src.h
  54. 125 69
      panda/src/linmath/lvecBase2_src.I
  55. 3 3
      panda/src/linmath/lvecBase2_src.cxx
  56. 16 9
      panda/src/linmath/lvecBase2_src.h
  57. 2 0
      panda/src/linmath/lvecBase3.cxx
  58. 4 0
      panda/src/linmath/lvecBase3.h
  59. 3 0
      panda/src/linmath/lvecBase3_ext.h
  60. 68 5
      panda/src/linmath/lvecBase3_ext_src.I
  61. 3 0
      panda/src/linmath/lvecBase3_ext_src.h
  62. 155 78
      panda/src/linmath/lvecBase3_src.I
  63. 4 4
      panda/src/linmath/lvecBase3_src.cxx
  64. 18 9
      panda/src/linmath/lvecBase3_src.h
  65. 2 0
      panda/src/linmath/lvecBase4.cxx
  66. 5 0
      panda/src/linmath/lvecBase4.h
  67. 3 0
      panda/src/linmath/lvecBase4_ext.h
  68. 73 6
      panda/src/linmath/lvecBase4_ext_src.I
  69. 3 0
      panda/src/linmath/lvecBase4_ext_src.h
  70. 164 76
      panda/src/linmath/lvecBase4_src.I
  71. 5 5
      panda/src/linmath/lvecBase4_src.cxx
  72. 17 9
      panda/src/linmath/lvecBase4_src.h
  73. 2 0
      panda/src/linmath/lvector2.cxx
  74. 3 0
      panda/src/linmath/lvector2.h
  75. 3 0
      panda/src/linmath/lvector2_ext.h
  76. 13 1
      panda/src/linmath/lvector2_ext_src.I
  77. 3 3
      panda/src/linmath/lvector2_src.I
  78. 2 0
      panda/src/linmath/lvector2_src.h
  79. 2 0
      panda/src/linmath/lvector3.cxx
  80. 3 0
      panda/src/linmath/lvector3.h
  81. 3 0
      panda/src/linmath/lvector3_ext.h
  82. 13 1
      panda/src/linmath/lvector3_ext_src.I
  83. 28 19
      panda/src/linmath/lvector3_src.I
  84. 4 1
      panda/src/linmath/lvector3_src.h
  85. 2 0
      panda/src/linmath/lvector4.cxx
  86. 3 0
      panda/src/linmath/lvector4.h
  87. 3 0
      panda/src/linmath/lvector4_ext.h
  88. 14 2
      panda/src/linmath/lvector4_ext_src.I
  89. 14 3
      panda/src/linmath/lvector4_src.I
  90. 3 0
      panda/src/linmath/lvector4_src.h
  91. 5 6
      panda/src/pgraph/geomTransformer.cxx

+ 22 - 0
dtool/src/dtoolbase/cmath.I

@@ -336,6 +336,28 @@ cpow(double x, double y) {
   return pow(x, y);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: cpow
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE int
+cpow(int x, int y) {
+  int result = 1;
+
+  if (y >= 0) {
+    for(; y > 0; --y) {
+      result *= x;
+    }
+    return result;
+
+  } else {
+    for(; y < 0; ++y) {
+      result *= x;
+    }
+    return 1 / result;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: cnan
 //  Description: 

+ 2 - 0
dtool/src/dtoolbase/cmath.h

@@ -62,6 +62,8 @@ INLINE double cacos(double v);
 INLINE double cmod(double x, double y);
 INLINE double cpow(double x, double y);
 
+INLINE int cpow(int x, int y);
+
 // Returns true if the number is NaN, false if it's a genuine number
 // or infinity.
 INLINE bool cnan(double v);

+ 8 - 1
dtool/src/dtoolbase/nearly_zero.h

@@ -35,6 +35,13 @@ get_nearly_zero_value(float) {
   return 1.0e-6f;
 }
 
+INLINE int
+get_nearly_zero_value(int) {
+  // This is a bit silly, but we should nevertheless define it in
+  // case it is called for an integer type.
+  return 0;
+}
+
 
 // IS_THRESHOLD_ZERO(value, threshold) returns true if the value is
 // within threshold of zero.
@@ -73,7 +80,7 @@ get_nearly_zero_value(float) {
 // MAYBE_ZERO(value) returns 0 if the value is nearly zero, and the
 // value itself otherwise.
 #define MAYBE_ZERO(value) \
-  (IS_NEARLY_ZERO(value) ? 0.0 : (value))
+  (IS_NEARLY_ZERO(value) ? 0 : (value))
 
 
 #endif

+ 2 - 0
dtool/src/pystub/pystub.cxx

@@ -85,6 +85,7 @@ extern "C" {
   EXPCL_PYSTUB int PyModule_AddStringConstant(...);
   EXPCL_PYSTUB int PyModule_Create2(...);
   EXPCL_PYSTUB int PyNumber_Float(...);
+  EXPCL_PYSTUB int PyNumber_Int(...);
   EXPCL_PYSTUB int PyNumber_Long(...);
   EXPCL_PYSTUB int PyObject_ASCII(...);
   EXPCL_PYSTUB int PyObject_Call(...);
@@ -249,6 +250,7 @@ int PyModule_AddObject(...) { return 0; };
 int PyModule_AddStringConstant(...) { return 0; };
 int PyModule_Create2(...) { return 0; };
 int PyNumber_Float(...) { return 0; }
+int PyNumber_Int(...) { return 0; }
 int PyNumber_Long(...) { return 0; }
 int PyObject_ASCII(...) { return 0; }
 int PyObject_Call(...) { return 0; }

+ 60 - 12
panda/src/display/windowProperties.I

@@ -53,6 +53,21 @@ is_any_specified() const {
   return (_specified != 0);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::set_origin
+//       Access: Published
+//  Description: Specifies the origin on the screen (in pixels,
+//               relative to the top-left corner) at which the window
+//               should appear.  This is the origin of the top-left
+//               corner of the useful part of the window, not
+//               including decorations.
+////////////////////////////////////////////////////////////////////
+INLINE void WindowProperties::
+set_origin(const LPoint2i &origin) {
+  _origin = origin;
+  _specified |= S_origin;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: WindowProperties::set_origin
 //       Access: Published
@@ -64,11 +79,22 @@ is_any_specified() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void WindowProperties::
 set_origin(int x_origin, int y_origin) {
-  _x_origin = x_origin;
-  _y_origin = y_origin;
+  _origin.set(x_origin, y_origin);
   _specified |= S_origin;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::get_origin
+//       Access: Published
+//  Description: Returns the coordinates of the window's top-left
+//               corner, not including decorations.
+////////////////////////////////////////////////////////////////////
+INLINE const LPoint2i &WindowProperties::
+get_origin() const {
+  nassertr(has_origin(), LPoint2i::zero());
+  return _origin;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: WindowProperties::get_x_origin
 //       Access: Published
@@ -78,7 +104,7 @@ set_origin(int x_origin, int y_origin) {
 INLINE int WindowProperties::
 get_x_origin() const {
   nassertr(has_origin(), 0);
-  return _x_origin;
+  return _origin.get_x();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -90,7 +116,7 @@ get_x_origin() const {
 INLINE int WindowProperties::
 get_y_origin() const {
   nassertr(has_origin(), 0);
-  return _y_origin;
+  return _origin.get_y();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -112,8 +138,20 @@ has_origin() const {
 INLINE void WindowProperties::
 clear_origin() {
   _specified &= ~S_origin;
-  _x_origin = 0;
-  _y_origin = 0;
+  _origin = LPoint2i::zero();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::set_size
+//       Access: Published
+//  Description: Specifies the requested size of the window, in
+//               pixels.  This is the size of the useful part of the
+//               window, not including decorations.
+////////////////////////////////////////////////////////////////////
+INLINE void WindowProperties::
+set_size(const LVector2i &size) {
+  _size = size;
+  _specified |= S_size;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -125,11 +163,22 @@ clear_origin() {
 ////////////////////////////////////////////////////////////////////
 INLINE void WindowProperties::
 set_size(int x_size, int y_size) {
-  _x_size = x_size;
-  _y_size = y_size;
+  _size.set(x_size, y_size);
   _specified |= S_size;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::get_origin
+//       Access: Published
+//  Description: Returns size in pixels of the useful part of the
+//               window, not including decorations.
+////////////////////////////////////////////////////////////////////
+INLINE const LVector2i &WindowProperties::
+get_size() const {
+  nassertr(has_size(), LVector2i::zero());
+  return _size;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: WindowProperties::get_x_size
 //       Access: Published
@@ -140,7 +189,7 @@ set_size(int x_size, int y_size) {
 INLINE int WindowProperties::
 get_x_size() const {
   nassertr(has_size(), 0);
-  return _x_size;
+  return _size.get_x();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -153,7 +202,7 @@ get_x_size() const {
 INLINE int WindowProperties::
 get_y_size() const {
   nassertr(has_size(), 0);
-  return _y_size;
+  return _size.get_y();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -175,8 +224,7 @@ has_size() const {
 INLINE void WindowProperties::
 clear_size() {
   _specified &= ~S_size;
-  _x_size = 0;
-  _y_size = 0;
+  _size = LVector2i::zero();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 8 - 14
panda/src/display/windowProperties.cxx

@@ -36,10 +36,8 @@ WindowProperties() {
 void WindowProperties::
 operator = (const WindowProperties &copy) {
   _specified = copy._specified;
-  _x_origin = copy._x_origin;
-  _y_origin = copy._y_origin;
-  _x_size = copy._x_size;
-  _y_size = copy._y_size;
+  _origin = copy._origin;
+  _size = copy._size;
   _title = copy._title;
   _icon_filename = copy._icon_filename;
   _cursor_filename = copy._cursor_filename;
@@ -169,10 +167,8 @@ bool WindowProperties::
 operator == (const WindowProperties &other) const {
   return (_specified == other._specified &&
           _flags == other._flags &&
-          _x_origin == other._x_origin &&
-          _y_origin == other._y_origin &&
-          _x_size == other._x_size &&
-          _y_size == other._y_size &&
+          _origin == other._origin &&
+          _size == other._size &&
           _z_order == other._z_order &&
           _title == other._title &&
           _icon_filename == other._icon_filename &&
@@ -191,10 +187,8 @@ operator == (const WindowProperties &other) const {
 void WindowProperties::
 clear() {
   _specified = 0;
-  _x_origin = 0;
-  _y_origin = 0;
-  _x_size = 0;
-  _y_size = 0;
+  _origin = LPoint2i::zero();
+  _size = LVector2i::zero();
   _title = string();
   _icon_filename = Filename();
   _cursor_filename = Filename();
@@ -244,10 +238,10 @@ set_parent_window(size_t parent) {
 void WindowProperties::
 add_properties(const WindowProperties &other) {
   if (other.has_origin()) {
-    set_origin(other.get_x_origin(), other.get_y_origin());
+    set_origin(other.get_origin());
   }
   if (other.has_size()) {
-    set_size(other.get_x_size(), other.get_y_size());
+    set_size(other.get_size());
   }
   if (other.has_title()) {
     set_title(other.get_title());

+ 11 - 7
panda/src/display/windowProperties.h

@@ -19,7 +19,9 @@
 #include "filename.h"
 #include "pnotify.h"
 #include "windowHandle.h"
-   
+#include "lpoint2.h"
+#include "lvector2.h"
+
 ////////////////////////////////////////////////////////////////////
 //       Class : WindowProperties
 // Description : A container for the various kinds of properties we
@@ -57,14 +59,18 @@ PUBLISHED:
 
   void clear();
   INLINE bool is_any_specified() const;
-  
+
+  INLINE void set_origin(const LPoint2i &origin);
   INLINE void set_origin(int x_origin, int y_origin);
+  INLINE const LPoint2i &get_origin() const;
   INLINE int get_x_origin() const;
   INLINE int get_y_origin() const;
   INLINE bool has_origin() const;
   INLINE void clear_origin();
 
+  INLINE void set_size(const LVector2i &size);
   INLINE void set_size(int x_size, int y_size);
+  INLINE const LVector2i &get_size() const;
   INLINE int get_x_size() const;
   INLINE int get_y_size() const;
   INLINE bool has_size() const;
@@ -73,7 +79,7 @@ PUBLISHED:
   INLINE bool has_mouse_mode() const;
   INLINE void set_mouse_mode(MouseMode mode);
   INLINE MouseMode get_mouse_mode() const;
-  INLINE void clear_mouse_mode();  
+  INLINE void clear_mouse_mode();
 
   INLINE void set_title(const string &title);
   INLINE const string &get_title() const;
@@ -183,10 +189,8 @@ private:
   };
 
   int _specified;
-  int _x_origin;
-  int _y_origin;
-  int _x_size;
-  int _y_size;
+  LPoint2i _origin;
+  LVector2i _size;
   MouseMode _mouse_mode;
   string _title;
   Filename _cursor_filename;

+ 6 - 6
panda/src/glstuff/glImmediateModeSender_src.cxx

@@ -564,7 +564,7 @@ issue_vertex() {
 ////////////////////////////////////////////////////////////////////
 void CLP(ImmediateModeSender)::VectorSender2fui::
 issue_vertex() {
-  const int *d = _reader->get_data2i();
+  const LVecBase2i &d = _reader->get_data2i();
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
     GLCAT.spam()
@@ -573,7 +573,7 @@ issue_vertex() {
   }
 #endif  // NDEBUG
 
-  (*_func)(2, (const GLuint *)d);
+  (*_func)(2, (const GLuint *)d.get_data());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -583,7 +583,7 @@ issue_vertex() {
 ////////////////////////////////////////////////////////////////////
 void CLP(ImmediateModeSender)::VectorSender3fui::
 issue_vertex() {
-  const int *d = _reader->get_data3i();
+  const LVecBase3i &d = _reader->get_data3i();
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
     GLCAT.spam()
@@ -592,7 +592,7 @@ issue_vertex() {
   }
 #endif  // NDEBUG
 
-  (*_func)(3, (const GLuint *)d);
+  (*_func)(3, (const GLuint *)d.get_data());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -602,7 +602,7 @@ issue_vertex() {
 ////////////////////////////////////////////////////////////////////
 void CLP(ImmediateModeSender)::VectorSender4fui::
 issue_vertex() {
-  const int *d = _reader->get_data4i();
+  const LVecBase4i &d = _reader->get_data4i();
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
     GLCAT.spam()
@@ -611,7 +611,7 @@ issue_vertex() {
   }
 #endif  // NDEBUG
 
-  (*_func)(4, (const GLuint *)d);
+  (*_func)(4, (const GLuint *)d.get_data());
 }
 
 #endif  // SUPPORT_IMMEDIATE_MODE

+ 154 - 198
panda/src/gobj/geomVertexColumn.cxx

@@ -1043,75 +1043,69 @@ get_data1i(const unsigned char *pointer) {
 //       Access: Public, Virtual
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-const int *GeomVertexColumn::Packer::
+const LVecBase2i &GeomVertexColumn::Packer::
 get_data2i(const unsigned char *pointer) {
   switch (_column->get_num_values()) {
   case 1:
-    _i[0] = get_data1i(pointer);
-    _i[1] = 0;
-    return _i;
+    _v2i.set(get_data1i(pointer), 0);
+    return _v2i;
 
   default:
     switch (_column->get_numeric_type()) {
     case NT_uint8:
-      _i[0] = pointer[0];
-      _i[1] = pointer[1];
-      return _i;
+      _v2i.set(pointer[0], pointer[1]);
+      return _v2i;
       
     case NT_uint16:
       {
         const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
+        _v2i.set(pi[0], pi[1]);
       }
-      return _i;
+      return _v2i;
       
     case NT_uint32:
       {
         const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
+        _v2i.set(pi[0], pi[1]);
       }
-      return _i;
+      return _v2i;
       
     case NT_packed_dcba:
       {
         PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = GeomVertexData::unpack_abcd_d(dword);
-        _i[1] = GeomVertexData::unpack_abcd_c(dword);
+        _v2i.set(GeomVertexData::unpack_abcd_d(dword),
+                 GeomVertexData::unpack_abcd_c(dword));
       }
-      return _i;
+      return _v2i;
       
     case NT_packed_dabc:
       {
         PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = GeomVertexData::unpack_abcd_b(dword);
-        _i[1] = GeomVertexData::unpack_abcd_c(dword);
+        _v2i.set(GeomVertexData::unpack_abcd_b(dword),
+                 GeomVertexData::unpack_abcd_c(dword));
       }
-      return _i;
+      return _v2i;
       
     case NT_float32:
       {
         const PN_float32 *pi = (const PN_float32 *)pointer;
-        _i[0] = (int)pi[0];
-        _i[1] = (int)pi[1];
+        _v2i.set((int)pi[0], (int)pi[1]);
       }
-      return _i;
+      return _v2i;
       
     case NT_float64:
       {
         const PN_float64 *pi = (const PN_float64 *)pointer;
-        _i[0] = (int)pi[0];
-        _i[1] = (int)pi[1];
+        _v2i.set((int)pi[0], (int)pi[1]);
       }
-      return _i;
+      return _v2i;
 
     case NT_stdfloat:
-      nassertr(false, _i);
+      nassertr(false, _v2i);
     }
   }
 
-  return _i;
+  return _v2i;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1119,92 +1113,78 @@ get_data2i(const unsigned char *pointer) {
 //       Access: Public, Virtual
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-const int *GeomVertexColumn::Packer::
+const LVecBase3i &GeomVertexColumn::Packer::
 get_data3i(const unsigned char *pointer) {
   switch (_column->get_num_values()) {
   case 1:
-    _i[0] = get_data1i(pointer);
-    _i[1] = 0;
-    _i[2] = 0;
-    return _i;
+    _v3i.set(get_data1i(pointer), 0, 0);
+    return _v3i;
 
   case 2:
     {
-      const int *i = get_data2i(pointer);
-      _i[0] = i[0];
-      _i[1] = i[1];
-      _i[2] = 0;
+      const LVecBase2i &v2 = get_data2i(pointer);
+      _v3i.set(v2[0], v2[1], 0);
     }
-    return _i;
+    return _v3i;
 
   default:
     switch (_column->get_numeric_type()) {
     case NT_uint8:
-      _i[0] = pointer[0];
-      _i[1] = pointer[1];
-      _i[2] = pointer[2];
-      return _i;
-      
+      _v3i.set(pointer[0], pointer[1], 0);
+      return _v3i;
+
     case NT_uint16:
       {
         const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
-        _i[2] = pi[2];
+        _v3i.set(pi[0], pi[1], pi[2]);
       }
-      return _i;
-      
+      return _v3i;
+
     case NT_uint32:
       {
         const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
-        _i[2] = pi[2];
+        _v3i.set(pi[0], pi[1], pi[2]);
       }
-      return _i;
-      
+      return _v3i;
+
     case NT_packed_dcba:
       {
         PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = GeomVertexData::unpack_abcd_d(dword);
-        _i[1] = GeomVertexData::unpack_abcd_c(dword);
-        _i[2] = GeomVertexData::unpack_abcd_b(dword);
+        _v3i.set(GeomVertexData::unpack_abcd_d(dword),
+                 GeomVertexData::unpack_abcd_c(dword),
+                 GeomVertexData::unpack_abcd_b(dword));
       }
-      return _i;
-      
+      return _v3i;
+
     case NT_packed_dabc:
       {
         PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = GeomVertexData::unpack_abcd_b(dword);
-        _i[1] = GeomVertexData::unpack_abcd_c(dword);
-        _i[2] = GeomVertexData::unpack_abcd_d(dword);
+        _v3i.set(GeomVertexData::unpack_abcd_b(dword),
+                 GeomVertexData::unpack_abcd_c(dword),
+                 GeomVertexData::unpack_abcd_d(dword));
       }
-      return _i;
-      
+      return _v3i;
+
     case NT_float32:
       {
         const PN_float32 *pi = (const PN_float32 *)pointer;
-        _i[0] = (int)pi[0];
-        _i[1] = (int)pi[1];
-        _i[2] = (int)pi[2];
+        _v3i.set((int)pi[0], (int)pi[1], (int)pi[2]);
       }
-      return _i;
-      
+      return _v3i;
+
     case NT_float64:
       {
         const PN_float64 *pi = (const PN_float64 *)pointer;
-        _i[0] = (int)pi[0];
-        _i[1] = (int)pi[1];
-        _i[2] = (int)pi[2];
+        _v3i.set((int)pi[0], (int)pi[1], (int)pi[2]);
       }
-      return _i;
+      return _v3i;
 
     case NT_stdfloat:
-      nassertr(false, _i);
+      nassertr(false, _v3i);
     }
   }
 
-  return _i;
+  return _v3i;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1212,111 +1192,87 @@ get_data3i(const unsigned char *pointer) {
 //       Access: Public, Virtual
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-const int *GeomVertexColumn::Packer::
+const LVecBase4i &GeomVertexColumn::Packer::
 get_data4i(const unsigned char *pointer) {
   switch (_column->get_num_values()) {
   case 1:
-    _i[0] = get_data1i(pointer);
-    _i[1] = 0;
-    _i[2] = 0;
-    _i[3] = 0;
-    return _i;
+    _v4i.set(get_data1i(pointer), 0, 0, 0);
+    return _v4i;
 
   case 2:
     {
-      const int *i = get_data2i(pointer);
-      _i[0] = i[0];
-      _i[1] = i[1];
-      _i[2] = 0;
-      _i[3] = 0;
+      const LVecBase2i &v2 = get_data2i(pointer);
+      _v4i.set(v2[0], v2[1], 0, 0);
     }
-    return _i;
+    return _v4i;
 
   case 3:
     {
-      const int *i = get_data3i(pointer);
-      _i[0] = i[0];
-      _i[1] = i[1];
-      _i[2] = i[2];
-      _i[3] = 0;
+      const LVecBase3i &v3 = get_data3i(pointer);
+      _v4i.set(v3[0], v3[1], v3[2], 0);
     }
-    return _i;
+    return _v4i;
 
   default:
     switch (_column->get_numeric_type()) {
     case NT_uint8:
-      _i[0] = pointer[0];
-      _i[1] = pointer[1];
-      _i[2] = pointer[2];
-      _i[3] = pointer[3];
-      return _i;
+      _v4i.set(pointer[0], pointer[1], pointer[2], pointer[3]);
+      return _v4i;
       
     case NT_uint16:
       {
         const PN_uint16 *pi = (const PN_uint16 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
-        _i[2] = pi[2];
-        _i[3] = pi[3];
+        _v4i.set(pi[0], pi[1], pi[2], pi[3]);
       }
-      return _i;
+      return _v4i;
       
     case NT_uint32:
       {
         const PN_uint32 *pi = (const PN_uint32 *)pointer;
-        _i[0] = pi[0];
-        _i[1] = pi[1];
-        _i[2] = pi[2];
-        _i[3] = pi[3];
+        _v4i.set(pi[0], pi[1], pi[2], pi[3]);
       }
-      return _i;
+      return _v4i;
       
     case NT_packed_dcba:
       {
         PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = GeomVertexData::unpack_abcd_d(dword);
-        _i[1] = GeomVertexData::unpack_abcd_c(dword);
-        _i[2] = GeomVertexData::unpack_abcd_b(dword);
-        _i[3] = GeomVertexData::unpack_abcd_a(dword);
+        _v4i.set(GeomVertexData::unpack_abcd_d(dword),
+                 GeomVertexData::unpack_abcd_c(dword),
+                 GeomVertexData::unpack_abcd_b(dword),
+                 GeomVertexData::unpack_abcd_a(dword));
       }
-      return _i;
+      return _v4i;
       
     case NT_packed_dabc:
       {
         PN_uint32 dword = *(const PN_uint32 *)pointer;
-        _i[0] = GeomVertexData::unpack_abcd_b(dword);
-        _i[1] = GeomVertexData::unpack_abcd_c(dword);
-        _i[2] = GeomVertexData::unpack_abcd_d(dword);
-        _i[3] = GeomVertexData::unpack_abcd_a(dword);
+        _v4i.set(GeomVertexData::unpack_abcd_b(dword),
+                 GeomVertexData::unpack_abcd_c(dword),
+                 GeomVertexData::unpack_abcd_d(dword),
+                 GeomVertexData::unpack_abcd_a(dword));
       }
-      return _i;
+      return _v4i;
       
     case NT_float32:
       {
         const PN_float32 *pi = (const PN_float32 *)pointer;
-        _i[0] = (int)pi[0];
-        _i[1] = (int)pi[1];
-        _i[2] = (int)pi[2];
-        _i[3] = (int)pi[3];
+        _v4i.set((int)pi[0], (int)pi[1], (int)pi[2], (int)pi[3]);
       }
-      return _i;
+      return _v4i;
       
     case NT_float64:
       {
         const PN_float64 *pi = (const PN_float64 *)pointer;
-        _i[0] = (int)pi[0];
-        _i[1] = (int)pi[1];
-        _i[2] = (int)pi[2];
-        _i[3] = (int)pi[3];
+        _v4i.set((int)pi[0], (int)pi[1], (int)pi[2], (int)pi[3]);
       }
-      return _i;
+      return _v4i;
 
     case NT_stdfloat:
-      nassertr(false, _i);
+      nassertr(false, _v4i);
     }
   }
 
-  return _i;
+  return _v4i;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1903,22 +1859,22 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void GeomVertexColumn::Packer::
-set_data1i(unsigned char *pointer, int a) {
+set_data1i(unsigned char *pointer, int data) {
   switch (_column->get_num_values()) {
   case 1:
     switch (_column->get_numeric_type()) {
     case NT_uint8:
-      *pointer = a;
-      nassertv((*pointer) == a);
+      *pointer = data;
+      nassertv((*pointer) == data);
       break;
       
     case NT_uint16:
-      *(PN_uint16 *)pointer = a;
-      nassertv(*(PN_uint16 *)pointer == a);
+      *(PN_uint16 *)pointer = data;
+      nassertv(*(PN_uint16 *)pointer == data);
       break;
       
     case NT_uint32:
-      *(PN_uint32 *)pointer = a;
+      *(PN_uint32 *)pointer = data;
       break;
       
     case NT_packed_dcba:
@@ -1927,11 +1883,11 @@ set_data1i(unsigned char *pointer, int a) {
       break;
       
     case NT_float32:
-      *(PN_float32 *)pointer = (float)a;
+      *(PN_float32 *)pointer = (float)data;
       break;
       
     case NT_float64:
-      *(PN_float64 *)pointer = (double)a;
+      *(PN_float64 *)pointer = (double)data;
       break;
 
     case NT_stdfloat:
@@ -1940,15 +1896,15 @@ set_data1i(unsigned char *pointer, int a) {
     break;
 
   case 2:
-    set_data2i(pointer, a, 0);
+    set_data2i(pointer, LVecBase2i(data, 0));
     break;
 
   case 3:
-    set_data3i(pointer, a, 0, 0);
+    set_data3i(pointer, LVecBase3i(data, 0, 0));
     break;
 
   default:
-    set_data4i(pointer, a, 0, 0, 0);
+    set_data4i(pointer, LVecBase4i(data, 0, 0, 0));
     break;
   }
 }
@@ -1959,32 +1915,32 @@ set_data1i(unsigned char *pointer, int a) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void GeomVertexColumn::Packer::
-set_data2i(unsigned char *pointer, int a, int b) {
+set_data2i(unsigned char *pointer, const LVecBase2i &data) {
   switch (_column->get_num_values()) {
   case 1:
-    set_data1i(pointer, a);
+    set_data1i(pointer, data[0]);
     break;
 
   case 2:
     switch (_column->get_numeric_type()) {
     case NT_uint8:
-      pointer[0] = a;
-      pointer[1] = b;
+      pointer[0] = data[0];
+      pointer[1] = data[1];
       break;
 
     case NT_uint16:
       {
         PN_uint16 *pi = (PN_uint16 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
+        pi[0] = data[0];
+        pi[1] = data[1];
       }
       break;
 
     case NT_uint32:
       {
         PN_uint32 *pi = (PN_uint32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
+        pi[0] = data[0];
+        pi[1] = data[1];
       }
       break;
       
@@ -1996,16 +1952,16 @@ set_data2i(unsigned char *pointer, int a, int b) {
     case NT_float32:
       {
         PN_float32 *pi = (PN_float32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
+        pi[0] = data[0];
+        pi[1] = data[1];
       }
       break;
       
     case NT_float64:
       {
         PN_float64 *pi = (PN_float64 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
+        pi[0] = data[0];
+        pi[1] = data[1];
       }
       break;
 
@@ -2015,11 +1971,11 @@ set_data2i(unsigned char *pointer, int a, int b) {
     break;
 
   case 3:
-    set_data3i(pointer, a, b, 0);
+    set_data3i(pointer, LVecBase3i(data[0], data[1], 0));
     break;
 
   default:
-    set_data4i(pointer, a, b, 0, 0);
+    set_data4i(pointer, LVecBase4i(data[0], data[1], 0, 0));
     break;
   }
 }
@@ -2030,39 +1986,39 @@ set_data2i(unsigned char *pointer, int a, int b) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void GeomVertexColumn::Packer::
-set_data3i(unsigned char *pointer, int a, int b, int c) {
+set_data3i(unsigned char *pointer, const LVecBase3i &data) {
   switch (_column->get_num_values()) {
   case 1:
-    set_data1i(pointer, a);
+    set_data1i(pointer, data[0]);
     break;
 
   case 2:
-    set_data2i(pointer, a, b);
+    set_data2i(pointer, LVecBase2i(data[0], data[1]));
     break;
 
   case 3:
     switch (_column->get_numeric_type()) {
     case NT_uint8:
-      pointer[0] = a;
-      pointer[1] = b;
-      pointer[2] = c;
+      pointer[0] = data[0];
+      pointer[1] = data[1];
+      pointer[2] = data[2];
       break;
 
     case NT_uint16:
       {
         PN_uint16 *pi = (PN_uint16 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
       }
       break;
 
     case NT_uint32:
       {
         PN_uint32 *pi = (PN_uint32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
       }
       break;
       
@@ -2074,18 +2030,18 @@ set_data3i(unsigned char *pointer, int a, int b, int c) {
     case NT_float32:
       {
         PN_float32 *pi = (PN_float32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
       }
       break;
       
     case NT_float64:
       {
         PN_float64 *pi = (PN_float64 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
       }
       break;
 
@@ -2095,7 +2051,7 @@ set_data3i(unsigned char *pointer, int a, int b, int c) {
     break;
 
   default:
-    set_data4i(pointer, a, b, c, 0);
+    set_data4i(pointer, LVecBase4i(data[0], data[1], data[2], 0));
     break;
   }
 }
@@ -2106,74 +2062,74 @@ set_data3i(unsigned char *pointer, int a, int b, int c) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void GeomVertexColumn::Packer::
-set_data4i(unsigned char *pointer, int a, int b, int c, int d) {
+set_data4i(unsigned char *pointer, const LVecBase4i &data) {
   switch (_column->get_num_values()) {
   case 1:
-    set_data1i(pointer, a);
+    set_data1i(pointer, data[0]);
     break;
 
   case 2:
-    set_data2i(pointer, a, b);
+    set_data2i(pointer, LVecBase2i(data[0], data[1]));
     break;
 
   case 3:
-    set_data3i(pointer, a, b, c);
+    set_data3i(pointer, LVecBase3i(data[0], data[1], data[2]));
     break;
 
   default:
     switch (_column->get_numeric_type()) {
     case NT_uint8:
-      pointer[0] = a;
-      pointer[1] = b;
-      pointer[2] = c;
-      pointer[3] = d;
+      pointer[0] = data[0];
+      pointer[1] = data[1];
+      pointer[2] = data[2];
+      pointer[3] = data[3];
       break;
 
     case NT_uint16:
       {
         PN_uint16 *pi = (PN_uint16 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
-        pi[3] = d;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
+        pi[3] = data[3];
       }
       break;
 
     case NT_uint32:
       {
         PN_uint32 *pi = (PN_uint32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
-        pi[3] = d;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
+        pi[3] = data[3];
       }
       break;
       
     case NT_packed_dcba:
-      *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(d, c, b, a);
+      *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]);
       break;
       
     case NT_packed_dabc:
-      *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(d, a, b, c);
+      *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]);
       break;
       
     case NT_float32:
       {
         PN_float32 *pi = (PN_float32 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
-        pi[3] = d;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
+        pi[3] = data[3];
       }
       break;
       
     case NT_float64:
       {
         PN_float64 *pi = (PN_float64 *)pointer;
-        pi[0] = a;
-        pi[1] = b;
-        pi[2] = c;
-        pi[3] = d;
+        pi[0] = data[0];
+        pi[1] = data[1];
+        pi[2] = data[2];
+        pi[3] = data[3];
       }
       break;
 

+ 10 - 8
panda/src/gobj/geomVertexColumn.h

@@ -124,9 +124,9 @@ private:
     virtual const LVecBase4d &get_data4d(const unsigned char *pointer);
 
     virtual int get_data1i(const unsigned char *pointer);
-    virtual const int *get_data2i(const unsigned char *pointer);
-    virtual const int *get_data3i(const unsigned char *pointer);
-    virtual const int *get_data4i(const unsigned char *pointer);
+    virtual const LVecBase2i &get_data2i(const unsigned char *pointer);
+    virtual const LVecBase3i &get_data3i(const unsigned char *pointer);
+    virtual const LVecBase4i &get_data4i(const unsigned char *pointer);
 
     virtual void set_data1f(unsigned char *pointer, float data);
     virtual void set_data2f(unsigned char *pointer, const LVecBase2f &data);
@@ -138,10 +138,10 @@ private:
     virtual void set_data3d(unsigned char *pointer, const LVecBase3d &data);
     virtual void set_data4d(unsigned char *pointer, const LVecBase4d &data);
     
-    virtual void set_data1i(unsigned char *pointer, int a);
-    virtual void set_data2i(unsigned char *pointer, int a, int b);
-    virtual void set_data3i(unsigned char *pointer, int a, int b, int c);
-    virtual void set_data4i(unsigned char *pointer, int a, int b, int c, int d);
+    virtual void set_data1i(unsigned char *pointer, int data);
+    virtual void set_data2i(unsigned char *pointer, const LVecBase2i &data);
+    virtual void set_data3i(unsigned char *pointer, const LVecBase3i &data);
+    virtual void set_data4i(unsigned char *pointer, const LVecBase4i &data);
 
     virtual const char *get_name() const {
       return "Packer";
@@ -178,7 +178,9 @@ private:
     LVecBase2d _v2d;
     LVecBase3d _v3d;
     LVecBase4d _v4d;
-    int _i[4];
+    LVecBase2i _v2i;
+    LVecBase3i _v3i;
+    LVecBase4i _v4i;
     unsigned int _a, _b, _c, _d;
   };
 

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

@@ -699,7 +699,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
           while (!from.is_at_end()) {
             const TransformBlend &blend = blend_table->get_blend(from.get_data1i());
             LVecBase4 weights = LVecBase4::zero();
-            int indices[4] = {0, 0, 0, 0};
+            LVecBase4i indices(0, 0, 0, 0);
             nassertv(blend.get_num_transforms() <= 4);
             
             for (int i = 0; i < blend.get_num_transforms(); i++) {

+ 6 - 6
panda/src/gobj/geomVertexReader.I

@@ -660,9 +660,9 @@ get_data1i() {
 //               expressed as a 2-component value, and advances the
 //               read row.
 ////////////////////////////////////////////////////////////////////
-INLINE const int *GeomVertexReader::
+INLINE const LVecBase2i &GeomVertexReader::
 get_data2i() {
-  nassertr(has_column(), 0);
+  nassertr(has_column(), LVecBase2i::zero());
   return _packer->get_data2i(inc_pointer());
 }
 
@@ -673,9 +673,9 @@ get_data2i() {
 //               expressed as a 3-component value, and advances the
 //               read row.
 ////////////////////////////////////////////////////////////////////
-INLINE const int *GeomVertexReader::
+INLINE const LVecBase3i &GeomVertexReader::
 get_data3i() {
-  nassertr(has_column(), 0);
+  nassertr(has_column(), LVecBase3i::zero());
   return _packer->get_data3i(inc_pointer());
 }
 
@@ -686,9 +686,9 @@ get_data3i() {
 //               expressed as a 4-component value, and advances the
 //               read row.
 ////////////////////////////////////////////////////////////////////
-INLINE const int *GeomVertexReader::
+INLINE const LVecBase4i &GeomVertexReader::
 get_data4i() {
-  nassertr(has_column(), 0);
+  nassertr(has_column(), LVecBase4i::zero());
   return _packer->get_data4i(inc_pointer());
 }
 

+ 3 - 3
panda/src/gobj/geomVertexReader.h

@@ -122,9 +122,9 @@ PUBLISHED:
   INLINE const LVecBase4 &get_data4();
 
   INLINE int get_data1i();
-  INLINE const int *get_data2i();
-  INLINE const int *get_data3i();
-  INLINE const int *get_data4i();
+  INLINE const LVecBase2i &get_data2i();
+  INLINE const LVecBase3i &get_data3i();
+  INLINE const LVecBase4i &get_data4i();
 
   void output(ostream &out) const;
 

+ 63 - 21
panda/src/gobj/geomVertexWriter.I

@@ -792,8 +792,7 @@ set_data1i(int data) {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
 set_data2i(int a, int b) {
-  nassertv(has_column());
-  _packer->set_data2i(inc_pointer(), a, b);
+  set_data2i(LVecBase2i(a, b));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -806,8 +805,9 @@ set_data2i(int a, int b) {
 //               the end of data.
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
-set_data2i(const int data[2]) {
-  set_data2i(data[0], data[1]);
+set_data2i(const LVecBase2i &data) {
+  nassertv(has_column());
+  _packer->set_data2i(inc_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -821,8 +821,7 @@ set_data2i(const int data[2]) {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
 set_data3i(int a, int b, int c) {
-  nassertv(has_column());
-  _packer->set_data3i(inc_pointer(), a, b, c);
+  set_data3i(LVecBase3i(a, b, c));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -835,8 +834,9 @@ set_data3i(int a, int b, int c) {
 //               the end of data.
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
-set_data3i(const int data[3]) {
-  set_data3i(data[0], data[1], data[2]);
+set_data3i(const LVecBase3i &data) {
+  nassertv(has_column());
+  _packer->set_data3i(inc_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -850,8 +850,7 @@ set_data3i(const int data[3]) {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
 set_data4i(int a, int b, int c, int d) {
-  nassertv(has_column());
-  _packer->set_data4i(inc_pointer(), a, b, c, d);
+  set_data4i(LVecBase4i(a, b, c, d));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -864,8 +863,9 @@ set_data4i(int a, int b, int c, int d) {
 //               the end of data.
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
-set_data4i(const int data[4]) {
-  set_data4i(data[0], data[1], data[2], data[3]);
+set_data4i(const LVecBase4i &data) {
+  nassertv(has_column());
+  _packer->set_data4i(inc_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1224,8 +1224,7 @@ add_data1i(int data) {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
 add_data2i(int a, int b) {
-  nassertv(has_column());
-  _packer->set_data2i(inc_add_pointer(), a, b);
+  add_data2i(LVecBase2i(a, b));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1239,7 +1238,22 @@ add_data2i(int a, int b) {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
 add_data2i(const int data[2]) {
-  add_data2i(data[0], data[1]);
+  add_data2i(LVecBase2i(data[0], data[1]));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexWriter::add_data2i
+//       Access: Published
+//  Description: Sets the write row to a particular 2-component
+//               value, and advances the write row.
+//
+//               If the write row advances past the end of data,
+//               implicitly adds a new row to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void GeomVertexWriter::
+add_data2i(const LVecBase2i &data) {
+  nassertv(has_column());
+  _packer->set_data2i(inc_add_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1253,8 +1267,7 @@ add_data2i(const int data[2]) {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
 add_data3i(int a, int b, int c) {
-  nassertv(has_column());
-  _packer->set_data3i(inc_add_pointer(), a, b, c);
+  add_data3i(LVecBase3i(a, b, c));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1268,7 +1281,22 @@ add_data3i(int a, int b, int c) {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
 add_data3i(const int data[3]) {
-  add_data3i(data[0], data[1], data[2]);
+  add_data3i(LVecBase3i(data[0], data[1], data[2]));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexWriter::add_data3i
+//       Access: Published
+//  Description: Sets the write row to a particular 3-component
+//               value, and advances the write row.
+//
+//               If the write row advances past the end of data,
+//               implicitly adds a new row to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void GeomVertexWriter::
+add_data3i(const LVecBase3i &data) {
+  nassertv(has_column());
+  _packer->set_data3i(inc_add_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1282,8 +1310,7 @@ add_data3i(const int data[3]) {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
 add_data4i(int a, int b, int c, int d) {
-  nassertv(has_column());
-  _packer->set_data4i(inc_add_pointer(), a, b, c, d);
+  add_data4i(LVecBase4i(a, b, c, d));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1297,7 +1324,22 @@ add_data4i(int a, int b, int c, int d) {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
 add_data4i(const int data[4]) {
-  add_data4i(data[0], data[1], data[2], data[3]);
+  add_data4i(LVecBase4i(data[0], data[1], data[2], data[3]));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexWriter::add_data4i
+//       Access: Published
+//  Description: Sets the write row to a particular 4-component
+//               value, and advances the write row.
+//
+//               If the write row advances past the end of data,
+//               implicitly adds a new row to the data.
+////////////////////////////////////////////////////////////////////
+INLINE void GeomVertexWriter::
+add_data4i(const LVecBase4i &data) {
+  nassertv(has_column());
+  _packer->set_data4i(inc_add_pointer(), data);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 6 - 3
panda/src/gobj/geomVertexWriter.h

@@ -142,11 +142,11 @@ PUBLISHED:
 
   INLINE void set_data1i(int data);
   INLINE void set_data2i(int a, int b);
-  INLINE void set_data2i(const int data[2]);
+  INLINE void set_data2i(const LVecBase2i &data);
   INLINE void set_data3i(int a, int b, int c);
-  INLINE void set_data3i(const int data[3]);
+  INLINE void set_data3i(const LVecBase3i &data);
   INLINE void set_data4i(int a, int b, int c, int d);
-  INLINE void set_data4i(const int data[4]);
+  INLINE void set_data4i(const LVecBase4i &data);
 
   INLINE void add_data1f(float data);
   INLINE void add_data2f(float x, float y);
@@ -175,10 +175,13 @@ PUBLISHED:
   INLINE void add_data1i(int data);
   INLINE void add_data2i(int a, int b);
   INLINE void add_data2i(const int data[2]);
+  INLINE void add_data2i(const LVecBase2i &data);
   INLINE void add_data3i(int a, int b, int c);
   INLINE void add_data3i(const int data[3]);
+  INLINE void add_data3i(const LVecBase3i &data);
   INLINE void add_data4i(int a, int b, int c, int d);
   INLINE void add_data4i(const int data[4]);
+  INLINE void add_data4i(const LVecBase4i &data);
 
   void output(ostream &out) const;
 

+ 2 - 2
panda/src/linmath/Sources.pp

@@ -14,7 +14,7 @@
      compose_matrix_src.cxx compose_matrix_src.h config_linmath.h  \
      coordinateSystem.h dbl2fltnames.h dblnames.h \
      deg_2_rad.h deg_2_rad.I \
-     flt2dblnames.h fltnames.h lcast_to.h lcast_to_src.h  \
+     flt2dblnames.h fltnames.h intnames.h lcast_to.h lcast_to_src.h  \
      lcast_to_src.I lmatrix.h lmatrix_ext.h lmatrix3_src.I  \
      lmatrix3_src.cxx lmatrix3_src.h lmatrix4_src.I  \
      lmatrix4_src.cxx lmatrix4_src.h lorientation.h  \
@@ -56,7 +56,7 @@
     compose_matrix_src.h config_linmath.h coordinateSystem.h \
     dbl2fltnames.h dblnames.h \
     deg_2_rad.h deg_2_rad.I \
-    flt2dblnames.h fltnames.h lcast_to.h lcast_to_src.I lcast_to_src.h \
+    flt2dblnames.h fltnames.h intnames.h lcast_to.h lcast_to_src.I lcast_to_src.h \
     lmat_ops.h lmat_ops_src.I lmat_ops_src.h lmatrix.h \
     lmatrix3_src.I lmatrix3_src.h lmatrix4_src.I \
     lmatrix4_src.h lorientation.h lorientation_src.I \

+ 11 - 0
panda/src/linmath/config_linmath.cxx

@@ -88,6 +88,17 @@ init_liblinmath() {
   UnalignedLVecBase4d::init_type();
   UnalignedLMatrix4d::init_type();
 
+  LVecBase2i::init_type();
+  LVecBase3i::init_type();
+  LVecBase4i::init_type();
+  LVector2i::init_type();
+  LVector3i::init_type();
+  LVector4i::init_type();
+  LPoint2i::init_type();
+  LPoint3i::init_type();
+  LPoint4i::init_type();
+  UnalignedLVecBase4i::init_type();
+
   LQuaternionf::init_type();
   LRotationf::init_type();
   LOrientationf::init_type();

+ 1 - 1
panda/src/linmath/dblnames.h

@@ -37,9 +37,9 @@
 #undef FLOATNAME
 #undef FLOATTOKEN
 #undef FLOATCONST
+#undef FLOATTYPE_IS_INT
 
 #define FLOATTYPE double
 #define FLOATNAME(ARG) ARG##d
 #define FLOATTOKEN 'd'
 #define FLOATCONST(ARG) ARG
-

+ 1 - 0
panda/src/linmath/fltnames.h

@@ -37,6 +37,7 @@
 #undef FLOATNAME
 #undef FLOATTOKEN
 #undef FLOATCONST
+#undef FLOATTYPE_IS_INT
 
 #define FLOATTYPE float
 #define FLOATNAME(ARG) ARG##f

+ 46 - 0
panda/src/linmath/intnames.h

@@ -0,0 +1,46 @@
+// Filename: intnames.h
+// Created by:  rdb (07Jun14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//
+// This file is used throughout this directory, in conjunction with
+// dblnames.h, to implement a poor man's template of the linmath
+// objects on numeric type.  The idea is to #include either fltnames.h
+// or dblnames.h (or, in theory, intnames.h or any other numeric type
+// we wanted to implement) and then to include the various *_src.h
+// and/or *_src.cxx files that actually define the linmath objects.
+//
+// We do this instead of using actual templates to avoid some of the
+// inherent problems with templates: compiler complexity and
+// distributed code bloat, for instance; plus it allows us to
+// implement #if-based specialization on numeric type for compilers
+// (like VC++) that don't completely support template specialization.
+// That and the fact that VC++ seems to have a particularly bad time
+// with templates in general.
+//
+////////////////////////////////////////////////////////////////////
+
+
+#undef FLOATTYPE
+#undef FLOATNAME
+#undef FLOATTOKEN
+#undef FLOATCONST
+#undef FLOATTYPE_IS_INT
+
+#define FLOATTYPE int
+#define FLOATNAME(ARG) ARG##i
+#define FLOATTOKEN 'i'
+#define FLOATCONST(ARG) ARG
+#define FLOATTYPE_IS_INT

+ 2 - 0
panda/src/linmath/lpoint2.cxx

@@ -20,3 +20,5 @@
 #include "dblnames.h"
 #include "lpoint2_src.cxx"
 
+#include "intnames.h"
+#include "lpoint2_src.cxx"

+ 2 - 0
panda/src/linmath/lpoint2.h

@@ -26,5 +26,7 @@
 #include "dblnames.h"
 #include "lpoint2_src.h"
 
+#include "intnames.h"
+#include "lpoint2_src.h"
 
 #endif

+ 3 - 0
panda/src/linmath/lpoint2_ext.h

@@ -26,4 +26,7 @@
 #include "dblnames.h"
 #include "lpoint2_ext_src.h"
 
+#include "intnames.h"
+#include "lpoint2_ext_src.h"
+
 #endif

+ 13 - 1
panda/src/linmath/lpoint2_ext_src.I

@@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint3);
 IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint4);
 #endif
 
+#ifdef FLOATTYPE_IS_INT
+#if PY_MAJOR_VERSION >= 3
+#define PY_FROM_FLOATTYPE PyLong_FromLong
+#else
+#define PY_FROM_FLOATTYPE PyInt_FromLong
+#endif
+#else
+#define PY_FROM_FLOATTYPE PyFloat_FromDouble
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LPoint2::python_repr
 //       Access: Published
@@ -46,7 +56,7 @@ __getattr__(const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x'));
+      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2);
@@ -84,3 +94,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase2.
   return invoke_extension<FLOATNAME(LVecBase2)>(_this).__setattr__(self, attr_name, assign);
 }
+
+#undef PY_FROM_FLOATTYPE

+ 2 - 0
panda/src/linmath/lpoint2_src.I

@@ -185,6 +185,7 @@ operator / (FLOATTYPE scalar) const {
   return FLOATNAME(LPoint2)(FLOATNAME(LVecBase2)::operator / (scalar));
 }
 
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: LPoint2::project
 //       Access: Published
@@ -196,3 +197,4 @@ INLINE_LINMATH FLOATNAME(LPoint2) FLOATNAME(LPoint2)::
 project(const FLOATNAME(LVecBase2) &onto) const {
   return FLOATNAME(LVecBase2)::project(onto);
 }
+#endif  // FLOATTYPE_IS_INT

+ 3 - 0
panda/src/linmath/lpoint2_src.h

@@ -49,7 +49,10 @@ PUBLISHED:
 
   INLINE_LINMATH FLOATNAME(LPoint2) operator * (FLOATTYPE scalar) const;
   INLINE_LINMATH FLOATNAME(LPoint2) operator / (FLOATTYPE scalar) const;
+
+#ifndef FLOATTYPE_IS_INT
   INLINE_LINMATH FLOATNAME(LPoint2) project(const FLOATNAME(LVecBase2) &onto) const;
+#endif
 
   EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const);
 

+ 2 - 0
panda/src/linmath/lpoint3.cxx

@@ -20,3 +20,5 @@
 #include "dblnames.h"
 #include "lpoint3_src.cxx"
 
+#include "intnames.h"
+#include "lpoint3_src.cxx"

+ 2 - 0
panda/src/linmath/lpoint3.h

@@ -28,5 +28,7 @@
 #include "dblnames.h"
 #include "lpoint3_src.h"
 
+#include "intnames.h"
+#include "lpoint3_src.h"
 
 #endif

+ 3 - 0
panda/src/linmath/lpoint3_ext.h

@@ -26,4 +26,7 @@
 #include "dblnames.h"
 #include "lpoint3_ext_src.h"
 
+#include "intnames.h"
+#include "lpoint3_ext_src.h"
+
 #endif

+ 13 - 1
panda/src/linmath/lpoint3_ext_src.I

@@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint3);
 IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint4);
 #endif
 
+#ifdef FLOATTYPE_IS_INT
+#if PY_MAJOR_VERSION >= 3
+#define PY_FROM_FLOATTYPE PyLong_FromLong
+#else
+#define PY_FROM_FLOATTYPE PyInt_FromLong
+#endif
+#else
+#define PY_FROM_FLOATTYPE PyFloat_FromDouble
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LPoint3::python_repr
 //       Access: Published
@@ -47,7 +57,7 @@ __getattr__(const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x'));
+      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2);
@@ -85,3 +95,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase2.
   return invoke_extension<FLOATNAME(LVecBase3)>(_this).__setattr__(self, attr_name, assign);
 }
+
+#undef PY_FROM_FLOATTYPE

+ 15 - 2
panda/src/linmath/lpoint3_src.I

@@ -75,6 +75,17 @@ FLOATNAME(LPoint3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint3::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LPoint3)::
+FLOATNAME(LPoint3)(const FLOATNAME(LVecBase2) &copy, FLOATTYPE z) :
+  FLOATNAME(LVecBase3)(copy, z)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LPoint3::zero Named Constructor
 //       Access: Public
@@ -218,6 +229,7 @@ cross(const FLOATNAME(LVecBase3) &other) const {
   return FLOATNAME(LVecBase3)::cross(other);
 }
 
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: LPoint3::project
 //       Access: Published
@@ -229,6 +241,7 @@ INLINE_LINMATH FLOATNAME(LPoint3) FLOATNAME(LPoint3)::
 project(const FLOATNAME(LVecBase3) &onto) const {
   return FLOATNAME(LVecBase3)::project(onto);
 }
+#endif  // FLOATTYPE_IS_INT
 
 ////////////////////////////////////////////////////////////////////
 //     Function: LPoint3::operator * scalar
@@ -258,9 +271,9 @@ operator / (FLOATTYPE scalar) const {
 //               existing coordinate systems; it's hard to imagine it
 //               ever being different.
 ////////////////////////////////////////////////////////////////////
-INLINE_LINMATH FLOATNAME(LPoint3) FLOATNAME(LPoint3)::
+INLINE_LINMATH const FLOATNAME(LPoint3) &FLOATNAME(LPoint3)::
 origin(CoordinateSystem) {
-  return FLOATNAME(LPoint3)(0.0f, 0.0f, 0.0f);
+  return FLOATNAME(LPoint3)::zero();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 6 - 1
panda/src/linmath/lpoint3_src.h

@@ -30,6 +30,7 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LPoint3) &operator = (FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LPoint3)(FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LPoint3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z);
+  INLINE_LINMATH FLOATNAME(LPoint3)(const FLOATNAME(LVecBase2) &copy, FLOATTYPE z);
 
   EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const);
   EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign));
@@ -58,13 +59,17 @@ PUBLISHED:
   operator - (const FLOATNAME(LVector3) &other) const;
 
   INLINE_LINMATH FLOATNAME(LPoint3) cross(const FLOATNAME(LVecBase3) &other) const;
+
+#ifndef FLOATTYPE_IS_INT
   INLINE_LINMATH FLOATNAME(LPoint3) project(const FLOATNAME(LVecBase3) &onto) const;
+#endif
+
   INLINE_LINMATH FLOATNAME(LPoint3) operator * (FLOATTYPE scalar) const;
   INLINE_LINMATH FLOATNAME(LPoint3) operator / (FLOATTYPE scalar) const;
 
   // Some special named constructors for LPoint3.
 
-  INLINE_LINMATH static FLOATNAME(LPoint3) origin(CoordinateSystem cs = CS_default);
+  INLINE_LINMATH static const FLOATNAME(LPoint3) &origin(CoordinateSystem cs = CS_default);
   INLINE_LINMATH static FLOATNAME(LPoint3) rfu(FLOATTYPE right,
                                        FLOATTYPE fwd,
                                        FLOATTYPE up,

+ 2 - 0
panda/src/linmath/lpoint4.cxx

@@ -20,3 +20,5 @@
 #include "dblnames.h"
 #include "lpoint4_src.cxx"
 
+#include "intnames.h"
+#include "lpoint4_src.cxx"

+ 3 - 0
panda/src/linmath/lpoint4.h

@@ -26,4 +26,7 @@
 #include "dblnames.h"
 #include "lpoint4_src.h"
 
+#include "intnames.h"
+#include "lpoint4_src.h"
+
 #endif

+ 3 - 0
panda/src/linmath/lpoint4_ext.h

@@ -26,4 +26,7 @@
 #include "dblnames.h"
 #include "lpoint4_ext_src.h"
 
+#include "intnames.h"
+#include "lpoint4_ext_src.h"
+
 #endif

+ 14 - 2
panda/src/linmath/lpoint4_ext_src.I

@@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint3);
 IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint4);
 #endif
 
+#ifdef FLOATTYPE_IS_INT
+#if PY_MAJOR_VERSION >= 3
+#define PY_FROM_FLOATTYPE PyLong_FromLong
+#else
+#define PY_FROM_FLOATTYPE PyInt_FromLong
+#endif
+#else
+#define PY_FROM_FLOATTYPE PyFloat_FromDouble
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LPoint4::python_repr
 //       Access: Published
@@ -49,9 +59,9 @@ __getattr__(const string &attr_name) const {
   switch (attr_name.size()) {
     case 1:
       if (attr_name[0] == 'w') {
-        return PyFloat_FromDouble(_this->_v(3));
+        return PY_FROM_FLOATTYPE(_this->_v(3));
       } else {
-        return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x'));
+        return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
       }
 
     case 2: {
@@ -90,3 +100,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase4.
   return invoke_extension<FLOATNAME(LVecBase4)>(_this).__setattr__(self, attr_name, assign);
 }
+
+#undef PY_FROM_FLOATTYPE

+ 13 - 1
panda/src/linmath/lpoint4_src.I

@@ -75,6 +75,17 @@ FLOATNAME(LPoint4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LPoint4::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LPoint4)::
+FLOATNAME(LPoint4)(const FLOATNAME(LVecBase3) &copy, FLOATTYPE w) :
+  FLOATNAME(LVecBase4)(copy, w)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LPoint4::zero Named Constructor
 //       Access: Public
@@ -205,6 +216,7 @@ operator / (FLOATTYPE scalar) const {
   return FLOATNAME(LPoint4)(FLOATNAME(LVecBase4)::operator / (scalar));
 }
 
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: LPoint4::project
 //       Access: Published
@@ -216,4 +228,4 @@ INLINE_LINMATH FLOATNAME(LPoint4) FLOATNAME(LPoint4)::
 project(const FLOATNAME(LVecBase4) &onto) const {
   return FLOATNAME(LVecBase4)::project(onto);
 }
-
+#endif  // FLOATTYPE_IS_INT

+ 4 - 0
panda/src/linmath/lpoint4_src.h

@@ -24,6 +24,7 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LPoint4) &operator = (FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LPoint4)(FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LPoint4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w);
+  INLINE_LINMATH FLOATNAME(LPoint4)(const FLOATNAME(LVecBase3) &copy, FLOATTYPE w);
 
   EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const);
   EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign));
@@ -50,7 +51,10 @@ PUBLISHED:
 
   INLINE_LINMATH FLOATNAME(LPoint4) operator * (FLOATTYPE scalar) const;
   INLINE_LINMATH FLOATNAME(LPoint4) operator / (FLOATTYPE scalar) const;
+
+#ifndef FLOATTYPE_IS_INT
   INLINE_LINMATH FLOATNAME(LPoint4) project(const FLOATNAME(LVecBase4) &onto) const;
+#endif
 
   EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const);
 

+ 18 - 9
panda/src/linmath/luse.N

@@ -2,23 +2,32 @@
 defconstruct LPoint2f new LPoint2f(0.0f)
 defconstruct LPoint3f new LPoint3f(0.0f)
 defconstruct LPoint4f new LPoint4f(0.0f)
-defconstruct LPoint2d new LPoint2d(0.0f)
-defconstruct LPoint3d new LPoint3d(0.0f)
-defconstruct LPoint4d new LPoint4d(0.0f)
+defconstruct LPoint2d new LPoint2d(0.0)
+defconstruct LPoint3d new LPoint3d(0.0)
+defconstruct LPoint4d new LPoint4d(0.0)
+defconstruct LPoint2i new LPoint2i(0)
+defconstruct LPoint3i new LPoint3i(0)
+defconstruct LPoint4i new LPoint4i(0)
 
 defconstruct LVecBase2f new LVecBase2f(0.0f)
 defconstruct LVecBase3f new LVecBase3f(0.0f)
 defconstruct LVecBase4f new LVecBase4f(0.0f)
-defconstruct LVecBase2d new LVecBase2d(0.0f)
-defconstruct LVecBase3d new LVecBase3d(0.0f)
-defconstruct LVecBase4d new LVecBase4d(0.0f)
+defconstruct LVecBase2d new LVecBase2d(0.0)
+defconstruct LVecBase3d new LVecBase3d(0.0)
+defconstruct LVecBase4d new LVecBase4d(0.0)
+defconstruct LVecBase2i new LVecBase2i(0)
+defconstruct LVecBase3i new LVecBase3i(0)
+defconstruct LVecBase4i new LVecBase4i(0)
 
 defconstruct LVector2f new LVector2f(0.0f)
 defconstruct LVector3f new LVector3f(0.0f)
 defconstruct LVector4f new LVector4f(0.0f)
-defconstruct LVector2d new LVector2d(0.0f)
-defconstruct LVector3d new LVector3d(0.0f)
-defconstruct LVector4d new LVector4d(0.0f)
+defconstruct LVector2d new LVector2d(0.0)
+defconstruct LVector3d new LVector3d(0.0)
+defconstruct LVector4d new LVector4d(0.0)
+defconstruct LVector2i new LVector2i(0)
+defconstruct LVector3i new LVector3i(0)
+defconstruct LVector4i new LVector4i(0)
 
 defconstruct LMatrix3f new LMatrix3f(LMatrix3f::ident_mat())
 defconstruct LMatrix4f new LMatrix4f(LMatrix4f::ident_mat())

+ 3 - 0
panda/src/linmath/lvec2_ops.h

@@ -27,4 +27,7 @@
 #include "dblnames.h"
 #include "lvec2_ops_src.h"
 
+#include "intnames.h"
+#include "lvec2_ops_src.h"
+
 #endif

+ 2 - 1
panda/src/linmath/lvec2_ops_src.I

@@ -48,6 +48,7 @@ dot(const FLOATNAME(LVecBase2) &a, const FLOATNAME(LVecBase2) &b) {
   return a.dot(b);
 }
 
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: length of a vector
 //  Description:
@@ -67,7 +68,7 @@ normalize(const FLOATNAME(LVector2) &v) {
   v1.normalize();
   return v1;
 }
-
+#endif  // FLOATTYPE_IS_INT
 
 ////////////////////////////////////////////////////////////////////
 //     Function: generic_write_datagram

+ 2 - 1
panda/src/linmath/lvec2_ops_src.h

@@ -33,14 +33,15 @@ operator * (FLOATTYPE scalar, const FLOATNAME(LVector2) &a);
 INLINE_LINMATH FLOATTYPE
 dot(const FLOATNAME(LVecBase2) &a, const FLOATNAME(LVecBase2) &b);
 
+#ifndef FLOATTYPE_IS_INT
 // Length of a vector.
 INLINE_LINMATH FLOATTYPE
 length(const FLOATNAME(LVector2) &a);
 
-
 // A normalized vector.
 INLINE_LINMATH FLOATNAME(LVector2)
 normalize(const FLOATNAME(LVector2) &v);
+#endif  // FLOATTYPE_IS_INT
 
 INLINE_LINMATH void
 generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase2) &value);

+ 2 - 0
panda/src/linmath/lvec3_ops.h

@@ -27,5 +27,7 @@
 #include "dblnames.h"
 #include "lvec3_ops_src.h"
 
+#include "intnames.h"
+#include "lvec3_ops_src.h"
 
 #endif

+ 2 - 2
panda/src/linmath/lvec3_ops_src.I

@@ -70,7 +70,7 @@ cross(const FLOATNAME(LVector3) &a, const FLOATNAME(LVector3) &b) {
   return FLOATNAME(LVector3)(a.cross(b));
 }
 
-
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: length of a vector
 //  Description:
@@ -81,7 +81,6 @@ length(const FLOATNAME(LVecBase3) &a) {
   return a.length();
 }
 
-
 ////////////////////////////////////////////////////////////////////
 //     Function: normalize
 //  Description: Returns a normalized vector from the given vector.
@@ -93,6 +92,7 @@ normalize(const FLOATNAME(LVecBase3) &v) {
   v1.normalize();
   return v1;
 }
+#endif  // FLOATTYPE_IS_INT
 
 ////////////////////////////////////////////////////////////////////
 //     Function: generic_write_datagram

+ 2 - 1
panda/src/linmath/lvec3_ops_src.h

@@ -41,7 +41,7 @@ cross(const FLOATNAME(LVecBase3) &a, const FLOATNAME(LVecBase3) &b);
 INLINE_LINMATH FLOATNAME(LVector3)
 cross(const FLOATNAME(LVector3) &a, const FLOATNAME(LVector3) &b);
 
-
+#ifndef FLOATTYPE_IS_INT
 // Length of a vector.
 INLINE_LINMATH FLOATTYPE
 length(const FLOATNAME(LVecBase3) &a);
@@ -49,6 +49,7 @@ length(const FLOATNAME(LVecBase3) &a);
 // A normalized vector.
 INLINE_LINMATH FLOATNAME(LVector3)
 normalize(const FLOATNAME(LVecBase3) &v);
+#endif  // FLOATTYPE_IS_INT
 
 INLINE_LINMATH void
 generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase3) &value);

+ 2 - 0
panda/src/linmath/lvec4_ops.h

@@ -27,5 +27,7 @@
 #include "dblnames.h"
 #include "lvec4_ops_src.h"
 
+#include "intnames.h"
+#include "lvec4_ops_src.h"
 
 #endif

+ 2 - 1
panda/src/linmath/lvec4_ops_src.I

@@ -49,6 +49,7 @@ dot(const FLOATNAME(LVecBase4) &a, const FLOATNAME(LVecBase4) &b) {
   return a.dot(b);
 }
 
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: length of a vector
 //  Description:
@@ -59,7 +60,6 @@ length(const FLOATNAME(LVector4) &a) {
   return a.length();
 }
 
-
 ////////////////////////////////////////////////////////////////////
 //     Function: normalize
 //  Description: Returns a normalized vector from the given vector.
@@ -71,6 +71,7 @@ normalize(const FLOATNAME(LVector4) &v) {
   v1.normalize();
   return v1;
 }
+#endif  // FLOATTYPE_IS_INT
 
 ////////////////////////////////////////////////////////////////////
 //     Function: generic_write_datagram

+ 2 - 2
panda/src/linmath/lvec4_ops_src.h

@@ -33,15 +33,15 @@ operator * (FLOATTYPE scalar, const FLOATNAME(LVector4) &a);
 INLINE_LINMATH FLOATTYPE
 dot(const FLOATNAME(LVecBase4) &a, const FLOATNAME(LVecBase4) &b);
 
-
+#ifndef FLOATTYPE_IS_INT
 // Length of a vector.
 INLINE_LINMATH FLOATTYPE
 length(const FLOATNAME(LVector4) &a);
 
-
 // A normalized vector.
 INLINE_LINMATH FLOATNAME(LVector4)
 normalize(const FLOATNAME(LVector4) &v);
+#endif  // FLOATTYPE_IS_INT
 
 INLINE_LINMATH void
 generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase4) &value);

+ 2 - 0
panda/src/linmath/lvecBase2.cxx

@@ -20,3 +20,5 @@
 #include "dblnames.h"
 #include "lvecBase2_src.cxx"
 
+#include "intnames.h"
+#include "lvecBase2_src.cxx"

+ 4 - 0
panda/src/linmath/lvecBase2.h

@@ -16,6 +16,7 @@
 #define LVECBASE2_H
 
 #include "pandabase.h"
+#include "config_linmath.h"
 #include "typedObject.h"
 #include "pnotify.h"
 #include "datagram.h"
@@ -36,4 +37,7 @@ class DatagramIterator;
 #include "dblnames.h"
 #include "lvecBase2_src.h"
 
+#include "intnames.h"
+#include "lvecBase2_src.h"
+
 #endif

+ 3 - 0
panda/src/linmath/lvecBase2_ext.h

@@ -24,4 +24,7 @@
 #include "dblnames.h"
 #include "lvecBase2_ext_src.h"
 
+#include "intnames.h"
+#include "lvecBase2_ext_src.h"
+
 #endif

+ 67 - 5
panda/src/linmath/lvecBase2_ext_src.I

@@ -19,6 +19,22 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3);
 IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4);
 #endif
 
+#ifdef FLOATTYPE_IS_INT
+#if PY_MAJOR_VERSION >= 3
+#define PYNUMBER_FLOATTYPE PyNumber_Long
+#define PY_FROM_FLOATTYPE PyLong_FromLong
+#define PY_AS_FLOATTYPE PyLong_AS_LONG
+#else
+#define PYNUMBER_FLOATTYPE PyNumber_Int
+#define PY_FROM_FLOATTYPE PyInt_FromLong
+#define PY_AS_FLOATTYPE PyInt_AS_LONG
+#endif
+#else
+#define PYNUMBER_FLOATTYPE PyNumber_Float
+#define PY_FROM_FLOATTYPE PyFloat_FromDouble
+#define PY_AS_FLOATTYPE PyFloat_AsDouble
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::__setitem__
 //       Access: Public
@@ -59,8 +75,17 @@ __reduce__(PyObject *self) const {
     return NULL;
   }
 
+#if FLOATTOKEN == 'i'
+  PyObject *result = Py_BuildValue("(O(ii))", this_class,
+                                   (*_this)[0], (*_this)[1]);
+#elif FLOATTOKEN == 'f'
   PyObject *result = Py_BuildValue("(O(ff))", this_class,
                                    (*_this)[0], (*_this)[1]);
+#else
+  PyObject *result = Py_BuildValue("(O(dd))", this_class,
+                                   (*_this)[0], (*_this)[1]);
+#endif
+
   Py_DECREF(this_class);
   return result;
 }
@@ -81,7 +106,7 @@ __getattr__(const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x'));
+      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2);
@@ -148,14 +173,18 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
     PyObject** items = PySequence_Fast_ITEMS(fast);
     for (size_t i = 0; i < attr_name.size(); ++i) {
 
-      PyObject* fl = PyNumber_Float(items[i]);
+      PyObject* fl = PYNUMBER_FLOATTYPE(items[i]);
       if (fl == NULL) {
         // Oh darn.  Not when we've come this far.
+#ifdef FLOATTYPE_IS_INT
+        PyErr_SetString(PyExc_ValueError, "a sequence of integers is required");
+#else
         PyErr_SetString(PyExc_ValueError, "a sequence of floats is required");
+#endif
         Py_DECREF(fast);
         return -1;
       }
-      double value = PyFloat_AS_DOUBLE(fl);
+      FLOATTYPE value = PY_AS_FLOATTYPE(fl);
       Py_DECREF(fl);
 
       _this->_v(attr_name[i] - 'x') = value;
@@ -165,19 +194,23 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
 
   } else {
     // Maybe it's a single floating-point value.
-    PyObject* fl = PyNumber_Float(assign);
+    PyObject* fl = PYNUMBER_FLOATTYPE(assign);
     if (fl == NULL) {
       // It's not a floating-point value either?
       // Sheesh, I don't know what to do with it then.
       if (attr_name.size() == 1) {
+#ifdef FLOATTYPE_IS_INT
+        PyErr_SetString(PyExc_ValueError, "an integer is required");
+#else
         PyErr_SetString(PyExc_ValueError, "a float is required");
+#endif
       } else {
         PyErr_Format(PyExc_ValueError, "'%.200s' object is not iterable",
           assign->ob_type->tp_name);
       }
       return -1;
     }
-    double value = PyFloat_AS_DOUBLE(fl);
+    FLOATTYPE value = PY_AS_FLOATTYPE(fl);
     Py_DECREF(fl);
 
     // Loop through the components in the attribute name,
@@ -189,3 +222,32 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
 
   return 0;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::__pow__
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LVecBase2) Extension<FLOATNAME(LVecBase2)>::
+__pow__(FLOATTYPE exponent) const {
+  return FLOATNAME(LVecBase2)(
+    cpow(_this->_v(0), exponent),
+    cpow(_this->_v(1), exponent));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::__ipow__
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase2)>::
+__ipow__(PyObject *self, FLOATTYPE exponent) {
+  _this->_v(0) = cpow(_this->_v(0), exponent);
+  _this->_v(1) = cpow(_this->_v(1), exponent);
+  Py_INCREF(self);
+  return self;
+}
+
+#undef PYNUMBER_FLOATTYPE
+#undef PY_FROM_FLOATTYPE
+#undef PY_AS_FLOATTYPE

+ 3 - 0
panda/src/linmath/lvecBase2_ext_src.h

@@ -27,6 +27,9 @@ public:
   INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign);
   INLINE_LINMATH void __setitem__(int i, FLOATTYPE v);
   INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const;
+
+  INLINE_LINMATH FLOATNAME(LVecBase2) __pow__(FLOATTYPE exponent) const;
+  INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent);
 };
 
 #include "lvecBase2_ext_src.I"

+ 125 - 69
panda/src/linmath/lvecBase2_src.I

@@ -123,7 +123,7 @@ INLINE_LINMATH FLOATNAME(LVecBase2)::
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase2)::
 operator [](int i) const {
-  nassertr(i >= 0 && i < 2, 0.0);
+  nassertr(i >= 0 && i < 2, 0);
   return _v(i);
 }
 
@@ -156,8 +156,12 @@ size() {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH bool FLOATNAME(LVecBase2)::
 is_nan() const {
+#ifdef FLOATTYPE_IS_INT
+  return false;
+#else
   TAU_PROFILE("bool LVecBase2::is_nan()", " ", TAU_USER);
   return cnan(_v(0)) || cnan(_v(1));
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -167,7 +171,7 @@ is_nan() const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase2)::
 get_cell(int i) const {
-  nassertr(i >= 0 && i < 2, 0.0);
+  nassertr(i >= 0 && i < 2, 0);
   return _v(i);
 }
 
@@ -346,18 +350,17 @@ set(FLOATTYPE x, FLOATTYPE y) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: LVecBase2::length
+//     Function: LVecBase2::dot
 //       Access: Published
-//  Description: Returns the length of the vector, by the Pythagorean
-//               theorem.
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase2)::
-length() const {
-  TAU_PROFILE("FLOATTYPE LVecBase2::length()", " ", TAU_USER);
+dot(const FLOATNAME(LVecBase2) &other) const {
+  TAU_PROFILE("FLOATTYPE LVecBase2::dot()", " ", TAU_USER);
 #ifdef HAVE_EIGEN
-  return _v.norm();
+  return _v.dot(other._v);
 #else
-  return csqrt((*this).dot(*this));
+  return _v(0) * other._v(0) + _v(1) * other._v(1);
 #endif  // HAVE_EIGEN
 }
 
@@ -377,6 +380,23 @@ length_squared() const {
 #endif  // HAVE_EIGEN
 }
 
+#ifndef FLOATTYPE_IS_INT
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::length
+//       Access: Published
+//  Description: Returns the length of the vector, by the Pythagorean
+//               theorem.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase2)::
+length() const {
+  TAU_PROFILE("FLOATTYPE LVecBase2::length()", " ", TAU_USER);
+#ifdef HAVE_EIGEN
+  return _v.norm();
+#else
+  return csqrt((*this).dot(*this));
+#endif  // HAVE_EIGEN
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::normalize
 //       Access: Published
@@ -398,21 +418,6 @@ normalize() {
   return true;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase2::dot
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase2)::
-dot(const FLOATNAME(LVecBase2) &other) const {
-  TAU_PROFILE("FLOATTYPE LVecBase2::dot()", " ", TAU_USER);
-#ifdef HAVE_EIGEN
-  return _v.dot(other._v);
-#else
-  return _v(0) * other._v(0) + _v(1) * other._v(1);
-#endif  // HAVE_EIGEN
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::project
 //       Access: Published
@@ -424,6 +429,7 @@ INLINE_LINMATH FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::
 project(const FLOATNAME(LVecBase2) &onto) const {
   return onto * (dot(onto) / onto.length_squared());
 }
+#endif  // FLOATTYPE_IS_INT
 
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::operator <
@@ -475,9 +481,64 @@ operator != (const FLOATNAME(LVecBase2) &other) const {
 INLINE_LINMATH int FLOATNAME(LVecBase2)::
 compare_to(const FLOATNAME(LVecBase2) &other) const {
   TAU_PROFILE("int LVecBase2::compare_to(const LVecBase2 &)", " ", TAU_USER);
+#ifdef FLOATTYPE_IS_INT
+  if (_v(0) != other._v(0)) {
+    return (_v(0) < other._v(0)) ? -1 : 1;
+  }
+  if (_v(1) != other._v(1)) {
+    return (_v(1) < other._v(1)) ? -1 : 1;
+  }
+  return 0;
+#else
   return compare_to(other, NEARLY_ZERO(FLOATTYPE));
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::get_hash
+//       Access: Published
+//  Description: Returns a suitable hash for phash_map.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH size_t FLOATNAME(LVecBase2)::
+get_hash() const {
+  TAU_PROFILE("size_t LVecBase2::get_hash()", " ", TAU_USER);
+  return add_hash(0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::add_hash
+//       Access: Published
+//  Description: Adds the vector into the running hash.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH size_t FLOATNAME(LVecBase2)::
+add_hash(size_t hash) const {
+  TAU_PROFILE("size_t LVecBase2::add_hash(size_t)", " ", TAU_USER);
+#ifdef FLOATTYPE_IS_INT
+  int_hash ihasher;
+  hash = ihasher.add_hash(hash, _v(0));
+  hash = ihasher.add_hash(hash, _v(1));
+  return hash;
+#else
+  return add_hash(hash, NEARLY_ZERO(FLOATTYPE));
+#endif
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::generate_hash
+//       Access: Published
+//  Description: Adds the vector to the indicated hash generator.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH void FLOATNAME(LVecBase2)::
+generate_hash(ChecksumHashGenerator &hashgen) const {
+#ifdef FLOATTYPE_IS_INT
+  hashgen.add_int(_v(0));
+  hashgen.add_int(_v(1));
+#else
+  generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE));
+#endif
+}
+
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::compare_to
 //       Access: Published
@@ -499,17 +560,6 @@ compare_to(const FLOATNAME(LVecBase2) &other, FLOATTYPE threshold) const {
   return 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase2::get_hash
-//       Access: Published
-//  Description: Returns a suitable hash for phash_map.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH size_t FLOATNAME(LVecBase2)::
-get_hash() const {
-  TAU_PROFILE("size_t LVecBase2::get_hash()", " ", TAU_USER);
-  return add_hash(0);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::get_hash
 //       Access: Published
@@ -521,17 +571,6 @@ get_hash(FLOATTYPE threshold) const {
   return add_hash(0, threshold);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase2::add_hash
-//       Access: Published
-//  Description: Adds the vector into the running hash.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH size_t FLOATNAME(LVecBase2)::
-add_hash(size_t hash) const {
-  TAU_PROFILE("size_t LVecBase2::add_hash(size_t)", " ", TAU_USER);
-  return add_hash(hash, NEARLY_ZERO(FLOATTYPE));
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::add_hash
 //       Access: Published
@@ -546,6 +585,18 @@ add_hash(size_t hash, FLOATTYPE threshold) const {
   return hash;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase2::generate_hash
+//       Access: Published
+//  Description: Adds the vector to the indicated hash generator.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH void FLOATNAME(LVecBase2)::
+generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const {
+  hashgen.add_fp(_v(0), threshold);
+  hashgen.add_fp(_v(1), threshold);
+}
+#endif  // FLOATTYPE_IS_INT
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::unary -
 //       Access: Published
@@ -612,8 +663,13 @@ operator * (FLOATTYPE scalar) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::
 operator / (FLOATTYPE scalar) const {
+#ifdef FLOATTYPE_IS_INT
+  return FLOATNAME(LVecBase2)(_v(0) / scalar,
+                              _v(1) / scalar);
+#else
   FLOATTYPE recip_scalar = 1.0f/scalar;
   return operator * (recip_scalar);
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -668,8 +724,13 @@ operator *= (FLOATTYPE scalar) {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase2)::
 operator /= (FLOATTYPE scalar) {
+#ifdef FLOATTYPE_IS_INT
+  _v(0) /= scalar;
+  _v(1) /= scalar;
+#else
   FLOATTYPE recip_scalar = 1.0f/scalar;
   operator *= (recip_scalar);
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -732,27 +793,6 @@ output(ostream &out) const {
       << MAYBE_ZERO(_v(1));
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase2::generate_hash
-//       Access: Published
-//  Description: Adds the vector to the indicated hash generator.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH void FLOATNAME(LVecBase2)::
-generate_hash(ChecksumHashGenerator &hashgen) const {
-  generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase2::generate_hash
-//       Access: Published
-//  Description: Adds the vector to the indicated hash generator.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH void FLOATNAME(LVecBase2)::
-generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const {
-  hashgen.add_fp(_v(0), threshold);
-  hashgen.add_fp(_v(1), threshold);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::write_datagram_fixed
 //       Access: Published
@@ -766,7 +806,10 @@ generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase2)::
 write_datagram_fixed(Datagram &destination) const {
-#if FLOATTOKEN == 'f'
+#if FLOATTOKEN == 'i'
+  destination.add_int32(_v(0));
+  destination.add_int32(_v(1));
+#elif FLOATTOKEN == 'f'
   destination.add_float32(_v(0));
   destination.add_float32(_v(1));
 #else
@@ -783,7 +826,10 @@ write_datagram_fixed(Datagram &destination) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase2)::
 read_datagram_fixed(DatagramIterator &source) {
-#if FLOATTOKEN == 'f'
+#if FLOATTOKEN == 'i'
+  _v(0) = source.get_int32();
+  _v(1) = source.get_int32();
+#elif FLOATTOKEN == 'f'
   _v(0) = source.get_float32();
   _v(1) = source.get_float32();
 #else
@@ -802,8 +848,13 @@ read_datagram_fixed(DatagramIterator &source) {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase2)::
 write_datagram(Datagram &destination) const {
+#if FLOATTOKEN == 'i'
+  destination.add_int32(_v(0));
+  destination.add_int32(_v(1));
+#else
   destination.add_stdfloat(_v(0));
   destination.add_stdfloat(_v(1));
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -813,6 +864,11 @@ write_datagram(Datagram &destination) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase2)::
 read_datagram(DatagramIterator &source) {
+#if FLOATTOKEN == 'i'
+  _v(0) = source.get_int32();
+  _v(1) = source.get_int32();
+#else
   _v(0) = source.get_stdfloat();
   _v(1) = source.get_stdfloat();
+#endif
 }

+ 3 - 3
panda/src/linmath/lvecBase2_src.cxx

@@ -15,11 +15,11 @@
 TypeHandle FLOATNAME(LVecBase2)::_type_handle;
 
 const FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::_zero =
-  FLOATNAME(LVecBase2)(0.0f, 0.0f);
+  FLOATNAME(LVecBase2)(0, 0);
 const FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::_unit_x =
-  FLOATNAME(LVecBase2)(1.0f, 0.0f);
+  FLOATNAME(LVecBase2)(1, 0);
 const FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::_unit_y =
-  FLOATNAME(LVecBase2)(0.0f, 1.0f);
+  FLOATNAME(LVecBase2)(0, 1);
 
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::init_type

+ 16 - 9
panda/src/linmath/lvecBase2_src.h

@@ -78,24 +78,32 @@ PUBLISHED:
   INLINE_LINMATH void fill(FLOATTYPE fill_value);
   INLINE_LINMATH void set(FLOATTYPE x, FLOATTYPE y);
 
-  INLINE_LINMATH FLOATTYPE length() const;
+  INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase2) &other) const;
   INLINE_LINMATH FLOATTYPE length_squared() const;
-  INLINE_LINMATH bool normalize();
 
-  INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase2) &other) const;
+#ifndef FLOATTYPE_IS_INT
+  INLINE_LINMATH FLOATTYPE length() const;
+  INLINE_LINMATH bool normalize();
   INLINE_LINMATH FLOATNAME(LVecBase2) project(const FLOATNAME(LVecBase2) &onto) const;
+#endif
 
   INLINE_LINMATH bool operator < (const FLOATNAME(LVecBase2) &other) const;
   INLINE_LINMATH bool operator == (const FLOATNAME(LVecBase2) &other) const;
   INLINE_LINMATH bool operator != (const FLOATNAME(LVecBase2) &other) const;
 
   INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase2) &other) const;
+  INLINE_LINMATH size_t get_hash() const;
+  INLINE_LINMATH size_t add_hash(size_t hash) const;
+  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const;
+
+#ifndef FLOATTYPE_IS_INT
   INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase2) &other,
                                 FLOATTYPE threshold) const;
-  INLINE_LINMATH size_t get_hash() const;
   INLINE_LINMATH size_t get_hash(FLOATTYPE threshold) const;
-  INLINE_LINMATH size_t add_hash(size_t hash) const;
   INLINE_LINMATH size_t add_hash(size_t hash, FLOATTYPE threshold) const;
+  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen,
+                                    FLOATTYPE threshold) const;
+#endif
 
   INLINE_LINMATH FLOATNAME(LVecBase2) operator - () const;
 
@@ -113,6 +121,9 @@ PUBLISHED:
   INLINE_LINMATH void operator *= (FLOATTYPE scalar);
   INLINE_LINMATH void operator /= (FLOATTYPE scalar);
 
+  EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase2) __pow__(FLOATTYPE exponent) const);
+  EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent));
+
   INLINE_LINMATH FLOATNAME(LVecBase2) fmax(const FLOATNAME(LVecBase2) &other);
   INLINE_LINMATH FLOATNAME(LVecBase2) fmin(const FLOATNAME(LVecBase2) &other);
 
@@ -123,10 +134,6 @@ PUBLISHED:
   INLINE_LINMATH void output(ostream &out) const;
   EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const);
 
-  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const;
-  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen,
-                                    FLOATTYPE threshold) const;
-
   INLINE_LINMATH void write_datagram_fixed(Datagram &destination) const;
   INLINE_LINMATH void read_datagram_fixed(DatagramIterator &source);
   INLINE_LINMATH void write_datagram(Datagram &destination) const;

+ 2 - 0
panda/src/linmath/lvecBase3.cxx

@@ -20,3 +20,5 @@
 #include "dblnames.h"
 #include "lvecBase3_src.cxx"
 
+#include "intnames.h"
+#include "lvecBase3_src.cxx"

+ 4 - 0
panda/src/linmath/lvecBase3.h

@@ -16,6 +16,7 @@
 #define LVECBASE3_H
 
 #include "pandabase.h"
+#include "config_linmath.h"
 #include "typedObject.h"
 #include "pnotify.h"
 #include "datagram.h"
@@ -37,4 +38,7 @@ class DatagramIterator;
 #include "dblnames.h"
 #include "lvecBase3_src.h"
 
+#include "intnames.h"
+#include "lvecBase3_src.h"
+
 #endif

+ 3 - 0
panda/src/linmath/lvecBase3_ext.h

@@ -24,4 +24,7 @@
 #include "dblnames.h"
 #include "lvecBase3_ext_src.h"
 
+#include "intnames.h"
+#include "lvecBase3_ext_src.h"
+
 #endif

+ 68 - 5
panda/src/linmath/lvecBase3_ext_src.I

@@ -19,6 +19,22 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3);
 IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4);
 #endif
 
+#ifdef FLOATTYPE_IS_INT
+#if PY_MAJOR_VERSION >= 3
+#define PYNUMBER_FLOATTYPE PyNumber_Long
+#define PY_FROM_FLOATTYPE PyLong_FromLong
+#define PY_AS_FLOATTYPE PyLong_AS_LONG
+#else
+#define PYNUMBER_FLOATTYPE PyNumber_Int
+#define PY_FROM_FLOATTYPE PyInt_FromLong
+#define PY_AS_FLOATTYPE PyInt_AS_LONG
+#endif
+#else
+#define PYNUMBER_FLOATTYPE PyNumber_Float
+#define PY_FROM_FLOATTYPE PyFloat_FromDouble
+#define PY_AS_FLOATTYPE PyFloat_AsDouble
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::__setitem__
 //       Access: Public
@@ -60,8 +76,17 @@ __reduce__(PyObject *self) const {
     return NULL;
   }
 
+#if FLOATTOKEN == 'i'
+  PyObject *result = Py_BuildValue("(O(iii))", this_class,
+                                   (*_this)[0], (*_this)[1], (*_this)[2]);
+#elif FLOATTOKEN == 'f'
   PyObject *result = Py_BuildValue("(O(fff))", this_class,
                                    (*_this)[0], (*_this)[1], (*_this)[2]);
+#else
+  PyObject *result = Py_BuildValue("(O(ddd))", this_class,
+                                   (*_this)[0], (*_this)[1], (*_this)[2]);
+#endif
+
   Py_DECREF(this_class);
   return result;
 }
@@ -82,7 +107,7 @@ __getattr__(const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x'));
+      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2);
@@ -149,14 +174,18 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
     PyObject** items = PySequence_Fast_ITEMS(fast);
     for (size_t i = 0; i < attr_name.size(); ++i) {
 
-      PyObject* fl = PyNumber_Float(items[i]);
+      PyObject* fl = PYNUMBER_FLOATTYPE(items[i]);
       if (fl == NULL) {
         // Oh darn.  Not when we've come this far.
+#ifdef FLOATTYPE_IS_INT
+        PyErr_SetString(PyExc_ValueError, "a sequence of integers is required");
+#else
         PyErr_SetString(PyExc_ValueError, "a sequence of floats is required");
+#endif
         Py_DECREF(fast);
         return -1;
       }
-      double value = PyFloat_AS_DOUBLE(fl);
+      FLOATTYPE value = PY_AS_FLOATTYPE(fl);
       Py_DECREF(fl);
 
       _this->_v(attr_name[i] - 'x') = value;
@@ -166,19 +195,23 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
 
   } else {
     // Maybe it's a single floating-point value.
-    PyObject* fl = PyNumber_Float(assign);
+    PyObject* fl = PYNUMBER_FLOATTYPE(assign);
     if (fl == NULL) {
       // It's not a floating-point value either?
       // Sheesh, I don't know what to do with it then.
       if (attr_name.size() == 1) {
+#ifdef FLOATTYPE_IS_INT
+        PyErr_SetString(PyExc_ValueError, "an integer is required");
+#else
         PyErr_SetString(PyExc_ValueError, "a float is required");
+#endif
       } else {
         PyErr_Format(PyExc_ValueError, "'%.200s' object is not iterable",
           assign->ob_type->tp_name);
       }
       return -1;
     }
-    double value = PyFloat_AS_DOUBLE(fl);
+    FLOATTYPE value = PY_AS_FLOATTYPE(fl);
     Py_DECREF(fl);
 
     // Loop through the components in the attribute name,
@@ -191,3 +224,33 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   return 0;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::__pow__
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LVecBase3) Extension<FLOATNAME(LVecBase3)>::
+__pow__(FLOATTYPE exponent) const {
+  return FLOATNAME(LVecBase3)(
+    cpow(_this->_v(0), exponent),
+    cpow(_this->_v(1), exponent),
+    cpow(_this->_v(2), exponent));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::__ipow__
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase3)>::
+__ipow__(PyObject *self, FLOATTYPE exponent) {
+  _this->_v(0) = cpow(_this->_v(0), exponent);
+  _this->_v(1) = cpow(_this->_v(1), exponent);
+  _this->_v(2) = cpow(_this->_v(2), exponent);
+  Py_INCREF(self);
+  return self;
+}
+
+#undef PYNUMBER_FLOATTYPE
+#undef PY_FROM_FLOATTYPE
+#undef PY_AS_FLOATTYPE

+ 3 - 0
panda/src/linmath/lvecBase3_ext_src.h

@@ -27,6 +27,9 @@ public:
   INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign);
   INLINE_LINMATH void __setitem__(int i, FLOATTYPE v);
   INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const;
+
+  INLINE_LINMATH FLOATNAME(LVecBase3) __pow__(FLOATTYPE exponent) const;
+  INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent);
 };
 
 #include "lvecBase3_ext_src.I"

+ 155 - 78
panda/src/linmath/lvecBase3_src.I

@@ -77,6 +77,16 @@ FLOATNAME(LVecBase3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) {
 //  set(x, y, z);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LVecBase3)::
+FLOATNAME(LVecBase3)(const FLOATNAME(LVecBase2) &copy, FLOATTYPE z) {
+  set(copy[0], copy[1], z);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::zero Named Constructor
 //       Access: Public
@@ -133,7 +143,7 @@ INLINE_LINMATH FLOATNAME(LVecBase3)::
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase3)::
 operator [](int i) const {
-  nassertr(i >= 0 && i < 3, 0.0);
+  nassertr(i >= 0 && i < 3, 0);
   return _v(i);
 }
 
@@ -166,8 +176,12 @@ size() {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH bool FLOATNAME(LVecBase3)::
 is_nan() const {
+#ifdef FLOATTYPE_IS_INT
+  return false;
+#else
   TAU_PROFILE("bool LVecBase3::is_nan()", " ", TAU_USER);
   return cnan(_v(0)) || cnan(_v(1)) || cnan(_v(2));
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -425,18 +439,17 @@ set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: LVecBase3::length
+//     Function: LVecBase3::dot
 //       Access: Published
-//  Description: Returns the length of the vector, by the Pythagorean
-//               theorem.
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase3)::
-length() const {
-  TAU_PROFILE("FLOATTYPE LVecBase3::length()", " ", TAU_USER);
+dot(const FLOATNAME(LVecBase3) &other) const {
+  TAU_PROFILE("FLOATTYPE LVecBase3::dot()", " ", TAU_USER);
 #ifdef HAVE_EIGEN
-  return _v.norm();
+  return _v.dot(other._v);
 #else
-  return csqrt((*this).dot(*this));
+  return _v(0) * other._v(0) + _v(1) * other._v(1) + _v(2) * other._v(2);
 #endif  // HAVE_EIGEN
 }
 
@@ -456,6 +469,23 @@ length_squared() const {
 #endif  // HAVE_EIGEN
 }
 
+#ifndef FLOATTYPE_IS_INT
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::length
+//       Access: Published
+//  Description: Returns the length of the vector, by the Pythagorean
+//               theorem.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase3)::
+length() const {
+  TAU_PROFILE("FLOATTYPE LVecBase3::length()", " ", TAU_USER);
+#ifdef HAVE_EIGEN
+  return _v.norm();
+#else
+  return csqrt((*this).dot(*this));
+#endif  // HAVE_EIGEN
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::normalize
 //       Access: Published
@@ -479,19 +509,17 @@ normalize() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: LVecBase3::dot
+//     Function: LVecBase3::project
 //       Access: Published
-//  Description:
+//  Description: Returns a new vector representing the projection of
+//               this vector onto another one.  The resulting vector
+//               will be a scalar multiple of onto.
 ////////////////////////////////////////////////////////////////////
-INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase3)::
-dot(const FLOATNAME(LVecBase3) &other) const {
-  TAU_PROFILE("FLOATTYPE LVecBase3::dot()", " ", TAU_USER);
-#ifdef HAVE_EIGEN
-  return _v.dot(other._v);
-#else
-  return _v(0) * other._v(0) + _v(1) * other._v(1) + _v(2) * other._v(2);
-#endif  // HAVE_EIGEN
+INLINE_LINMATH FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::
+project(const FLOATNAME(LVecBase3) &onto) const {
+  return onto * (dot(onto) / onto.length_squared());
 }
+#endif  // FLOATTYPE_IS_INT
 
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::cross
@@ -510,18 +538,6 @@ cross(const FLOATNAME(LVecBase3) &other) const {
 #endif  // HAVE_EIGEN
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase3::project
-//       Access: Published
-//  Description: Returns a new vector representing the projection of
-//               this vector onto another one.  The resulting vector
-//               will be a scalar multiple of onto.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::
-project(const FLOATNAME(LVecBase3) &onto) const {
-  return onto * (dot(onto) / onto.length_squared());
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::operator <
 //       Access: Published
@@ -621,9 +637,70 @@ get_standardized_hpr() const {
 INLINE_LINMATH int FLOATNAME(LVecBase3)::
 compare_to(const FLOATNAME(LVecBase3) &other) const {
   TAU_PROFILE("int LVecBase3::compare_to(const LVecBase3 &)", " ", TAU_USER);
+#ifdef FLOATTYPE_IS_INT
+  if (_v(0) != other._v(0)) {
+    return (_v(0) < other._v(0)) ? -1 : 1;
+  }
+  if (_v(1) != other._v(1)) {
+    return (_v(1) < other._v(1)) ? -1 : 1;
+  }
+  if (_v(2) != other._v(2)) {
+    return (_v(2) < other._v(2)) ? -1 : 1;
+  }
+  return 0;
+#else
   return compare_to(other, NEARLY_ZERO(FLOATTYPE));
+#endif
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::get_hash
+//       Access: Published
+//  Description: Returns a suitable hash for phash_map.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH size_t FLOATNAME(LVecBase3)::
+get_hash() const {
+  TAU_PROFILE("size_t LVecBase3::get_hash()", " ", TAU_USER);
+  return add_hash(0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::add_hash
+//       Access: Published
+//  Description: Adds the vector into the running hash.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH size_t FLOATNAME(LVecBase3)::
+add_hash(size_t hash) const {
+  TAU_PROFILE("size_t LVecBase3::add_hash(size_t)", " ", TAU_USER);
+#ifdef FLOATTYPE_IS_INT
+  int_hash ihasher;
+  hash = ihasher.add_hash(hash, _v(0));
+  hash = ihasher.add_hash(hash, _v(1));
+  hash = ihasher.add_hash(hash, _v(2));
+  return hash;
+#else
+  return add_hash(hash, NEARLY_ZERO(FLOATTYPE));
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::generate_hash
+//       Access: Published
+//  Description: Adds the vector to the indicated hash generator.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH void FLOATNAME(LVecBase3)::
+generate_hash(ChecksumHashGenerator &hashgen) const {
+  TAU_PROFILE("LVecBase3::generate_hash(ChecksumHashGenerator &)", " ", TAU_USER);
+#ifdef FLOATTYPE_IS_INT
+  hashgen.add_int(_v(0));
+  hashgen.add_int(_v(1));
+  hashgen.add_int(_v(2));
+#else
+  generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE));
+#endif
+}
+
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::compare_to
 //       Access: Published
@@ -648,17 +725,6 @@ compare_to(const FLOATNAME(LVecBase3) &other, FLOATTYPE threshold) const {
   return 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase3::get_hash
-//       Access: Published
-//  Description: Returns a suitable hash for phash_map.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH size_t FLOATNAME(LVecBase3)::
-get_hash() const {
-  TAU_PROFILE("size_t LVecBase3::get_hash()", " ", TAU_USER);
-  return add_hash(0);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::get_hash
 //       Access: Published
@@ -670,17 +736,6 @@ get_hash(FLOATTYPE threshold) const {
   return add_hash(0, threshold);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase3::add_hash
-//       Access: Published
-//  Description: Adds the vector into the running hash.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH size_t FLOATNAME(LVecBase3)::
-add_hash(size_t hash) const {
-  TAU_PROFILE("size_t LVecBase3::add_hash(size_t)", " ", TAU_USER);
-  return add_hash(hash, NEARLY_ZERO(FLOATTYPE));
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::add_hash
 //       Access: Published
@@ -696,6 +751,20 @@ add_hash(size_t hash, FLOATTYPE threshold) const {
   return hash;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase3::generate_hash
+//       Access: Published
+//  Description: Adds the vector to the indicated hash generator.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH void FLOATNAME(LVecBase3)::
+generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const {
+  TAU_PROFILE("LVecBase3::generate_hash(ChecksumHashGenerator &, FLOATTYPE)", " ", TAU_USER);
+  hashgen.add_fp(_v(0), threshold);
+  hashgen.add_fp(_v(1), threshold);
+  hashgen.add_fp(_v(2), threshold);
+}
+#endif  // FLOATTYPE_IS_INT
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::unary -
 //       Access: Published
@@ -765,8 +834,14 @@ operator * (FLOATTYPE scalar) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::
 operator / (FLOATTYPE scalar) const {
+#ifdef FLOATTYPE_IS_INT
+  return FLOATNAME(LVecBase3)(_v(0) / scalar,
+                              _v(1) / scalar,
+                              _v(2) / scalar);
+#else
   FLOATTYPE recip_scalar = 1.0f/scalar;
   return operator * (recip_scalar);
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -824,8 +899,14 @@ operator *= (FLOATTYPE scalar) {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase3)::
 operator /= (FLOATTYPE scalar) {
+#ifdef FLOATTYPE_IS_INT
+  _v(0) /= scalar;
+  _v(1) /= scalar;
+  _v(2) /= scalar;
+#else
   FLOATTYPE recip_scalar = 1.0f/scalar;
   operator *= (recip_scalar);
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -902,30 +983,6 @@ output(ostream &out) const {
       << MAYBE_ZERO(_v(2));
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase3::generate_hash
-//       Access: Published
-//  Description: Adds the vector to the indicated hash generator.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH void FLOATNAME(LVecBase3)::
-generate_hash(ChecksumHashGenerator &hashgen) const {
-  TAU_PROFILE("LVecBase3::generate_hash(ChecksumHashGenerator &)", " ", TAU_USER);
-  generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase3::generate_hash
-//       Access: Published
-//  Description: Adds the vector to the indicated hash generator.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH void FLOATNAME(LVecBase3)::
-generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const {
-  TAU_PROFILE("LVecBase3::generate_hash(ChecksumHashGenerator &, FLOATTYPE)", " ", TAU_USER);
-  hashgen.add_fp(_v(0), threshold);
-  hashgen.add_fp(_v(1), threshold);
-  hashgen.add_fp(_v(2), threshold);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::write_datagram_fixed
 //       Access: Published
@@ -939,7 +996,11 @@ generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase3)::
 write_datagram_fixed(Datagram &destination) const {
-#if FLOATTOKEN == 'f'
+#if FLOATTOKEN == 'i'
+  destination.add_int32(_v(0));
+  destination.add_int32(_v(1));
+  destination.add_int32(_v(2));
+#elif FLOATTOKEN == 'f'
   destination.add_float32(_v(0));
   destination.add_float32(_v(1));
   destination.add_float32(_v(2));
@@ -958,7 +1019,11 @@ write_datagram_fixed(Datagram &destination) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase3)::
 read_datagram_fixed(DatagramIterator &source) {
-#if FLOATTOKEN == 'f'
+#if FLOATTOKEN == 'i'
+  _v(0) = source.get_int32();
+  _v(1) = source.get_int32();
+  _v(2) = source.get_int32();
+#elif FLOATTOKEN == 'f'
   _v(0) = source.get_float32();
   _v(1) = source.get_float32();
   _v(2) = source.get_float32();
@@ -979,9 +1044,15 @@ read_datagram_fixed(DatagramIterator &source) {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase3)::
 write_datagram(Datagram &destination) const {
+#if FLOATTOKEN == 'i'
+  destination.add_int32(_v(0));
+  destination.add_int32(_v(1));
+  destination.add_int32(_v(2));
+#else
   destination.add_stdfloat(_v(0));
   destination.add_stdfloat(_v(1));
   destination.add_stdfloat(_v(2));
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -991,7 +1062,13 @@ write_datagram(Datagram &destination) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase3)::
 read_datagram(DatagramIterator &source) {
+#if FLOATTOKEN == 'i'
+  _v(0) = source.get_int32();
+  _v(1) = source.get_int32();
+  _v(2) = source.get_int32();
+#else
   _v(0) = source.get_stdfloat();
   _v(1) = source.get_stdfloat();
   _v(2) = source.get_stdfloat();
+#endif
 }

+ 4 - 4
panda/src/linmath/lvecBase3_src.cxx

@@ -16,13 +16,13 @@
 TypeHandle FLOATNAME(LVecBase3)::_type_handle;
 
 const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_zero =
-  FLOATNAME(LVecBase3)(0.0f, 0.0f, 0.0f);
+  FLOATNAME(LVecBase3)(0, 0, 0);
 const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_unit_x =
-  FLOATNAME(LVecBase3)(1.0f, 0.0f, 0.0f);
+  FLOATNAME(LVecBase3)(1, 0, 0);
 const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_unit_y =
-  FLOATNAME(LVecBase3)(0.0f, 1.0f, 0.0f);
+  FLOATNAME(LVecBase3)(0, 1, 0);
 const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_unit_z =
-  FLOATNAME(LVecBase3)(0.0f, 0.0f, 1.0f);
+  FLOATNAME(LVecBase3)(0, 0, 1);
 
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase3::init_type

+ 18 - 9
panda/src/linmath/lvecBase3_src.h

@@ -29,6 +29,7 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LVecBase3) &operator = (FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LVecBase3)(FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LVecBase3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z);
+  INLINE_LINMATH FLOATNAME(LVecBase3)(const FLOATNAME(LVecBase2) &copy, FLOATTYPE z);
   ALLOC_DELETED_CHAIN(FLOATNAME(LVecBase3));
 
   INLINE_LINMATH static const FLOATNAME(LVecBase3) &zero();
@@ -86,13 +87,16 @@ PUBLISHED:
   INLINE_LINMATH void fill(FLOATTYPE fill_value);
   INLINE_LINMATH void set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z);
 
-  INLINE_LINMATH FLOATTYPE length() const;
+  INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase3) &other) const;
   INLINE_LINMATH FLOATTYPE length_squared() const;
+
+#ifndef FLOATTYPE_IS_INT
+  INLINE_LINMATH FLOATTYPE length() const;
   INLINE_LINMATH bool normalize();
+  INLINE_LINMATH FLOATNAME(LVecBase3) project(const FLOATNAME(LVecBase3) &onto) const;
+#endif
 
-  INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase3) &other) const;
   INLINE_LINMATH FLOATNAME(LVecBase3) cross(const FLOATNAME(LVecBase3) &other) const;
-  INLINE_LINMATH FLOATNAME(LVecBase3) project(const FLOATNAME(LVecBase3) &onto) const;
 
   INLINE_LINMATH bool operator < (const FLOATNAME(LVecBase3) &other) const;
   INLINE_LINMATH bool operator == (const FLOATNAME(LVecBase3) &other) const;
@@ -101,12 +105,18 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LVecBase3) get_standardized_hpr() const;
 
   INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase3) &other) const;
+  INLINE_LINMATH size_t get_hash() const;
+  INLINE_LINMATH size_t add_hash(size_t hash) const;
+  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const;
+
+#ifndef FLOATTYPE_IS_INT
   INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase3) &other,
                                 FLOATTYPE threshold) const;
-  INLINE_LINMATH size_t get_hash() const;
   INLINE_LINMATH size_t get_hash(FLOATTYPE threshold) const;
-  INLINE_LINMATH size_t add_hash(size_t hash) const;
   INLINE_LINMATH size_t add_hash(size_t hash, FLOATTYPE threshold) const;
+  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen,
+                                    FLOATTYPE threshold) const;
+#endif
 
   INLINE_LINMATH FLOATNAME(LVecBase3) operator - () const;
 
@@ -124,6 +134,9 @@ PUBLISHED:
   INLINE_LINMATH void operator *= (FLOATTYPE scalar);
   INLINE_LINMATH void operator /= (FLOATTYPE scalar);
 
+  EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase3) __pow__(FLOATTYPE exponent) const);
+  EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent));
+
   INLINE_LINMATH FLOATNAME(LVecBase3) fmax(const FLOATNAME(LVecBase3) &other);
   INLINE_LINMATH FLOATNAME(LVecBase3) fmin(const FLOATNAME(LVecBase3) &other);
 
@@ -136,10 +149,6 @@ PUBLISHED:
   INLINE_LINMATH void output(ostream &out) const;
   EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const);
 
-  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const;
-  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen,
-                                    FLOATTYPE threshold) const;
-
   INLINE_LINMATH void write_datagram_fixed(Datagram &destination) const;
   INLINE_LINMATH void read_datagram_fixed(DatagramIterator &source);
   INLINE_LINMATH void write_datagram(Datagram &destination) const;

+ 2 - 0
panda/src/linmath/lvecBase4.cxx

@@ -20,3 +20,5 @@
 #include "dblnames.h"
 #include "lvecBase4_src.cxx"
 
+#include "intnames.h"
+#include "lvecBase4_src.cxx"

+ 5 - 0
panda/src/linmath/lvecBase4.h

@@ -16,11 +16,14 @@
 #define LVECBASE4_H
 
 #include "pandabase.h"
+#include "config_linmath.h"
 #include "typedObject.h"
 #include "pnotify.h"
 #include "datagram.h"
 #include "datagramIterator.h"
 #include "checksumHashGenerator.h"
+#include "lvecBase2.h"
+#include "lvecBase3.h"
 
 #include "cmath.h"
 #include "nearly_zero.h"
@@ -34,5 +37,7 @@ class DatagramIterator;
 #include "dblnames.h"
 #include "lvecBase4_src.h"
 
+#include "intnames.h"
+#include "lvecBase4_src.h"
 
 #endif

+ 3 - 0
panda/src/linmath/lvecBase4_ext.h

@@ -24,4 +24,7 @@
 #include "dblnames.h"
 #include "lvecBase4_ext_src.h"
 
+#include "intnames.h"
+#include "lvecBase4_ext_src.h"
+
 #endif

+ 73 - 6
panda/src/linmath/lvecBase4_ext_src.I

@@ -19,6 +19,22 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3);
 IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4);
 #endif
 
+#ifdef FLOATTYPE_IS_INT
+#if PY_MAJOR_VERSION >= 3
+#define PYNUMBER_FLOATTYPE PyNumber_Long
+#define PY_FROM_FLOATTYPE PyLong_FromLong
+#define PY_AS_FLOATTYPE PyLong_AS_LONG
+#else
+#define PYNUMBER_FLOATTYPE PyNumber_Int
+#define PY_FROM_FLOATTYPE PyInt_FromLong
+#define PY_AS_FLOATTYPE PyInt_AS_LONG
+#endif
+#else
+#define PYNUMBER_FLOATTYPE PyNumber_Float
+#define PY_FROM_FLOATTYPE PyFloat_FromDouble
+#define PY_AS_FLOATTYPE PyFloat_AsDouble
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::__setitem__
 //       Access: Public
@@ -61,8 +77,17 @@ __reduce__(PyObject *self) const {
     return NULL;
   }
 
+#if FLOATTOKEN == 'i'
+  PyObject *result = Py_BuildValue("(O(iiii))", this_class,
+                                   (*_this)[0], (*_this)[1], (*_this)[2], (*_this)[3]);
+#elif FLOATTOKEN == 'f'
   PyObject *result = Py_BuildValue("(O(ffff))", this_class,
                                    (*_this)[0], (*_this)[1], (*_this)[2], (*_this)[3]);
+#else
+  PyObject *result = Py_BuildValue("(O(dddd))", this_class,
+                                   (*_this)[0], (*_this)[1], (*_this)[2], (*_this)[3]);
+#endif
+
   Py_DECREF(this_class);
   return result;
 }
@@ -84,9 +109,9 @@ __getattr__(const string &attr_name) const {
   switch (attr_name.size()) {
     case 1:
       if (attr_name[0] == 'w') {
-        return PyFloat_FromDouble(_this->_v(3));
+        return PY_FROM_FLOATTYPE(_this->_v(3));
       } else {
-        return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x'));
+        return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
       }
 
     case 2: {
@@ -154,14 +179,18 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
     PyObject** items = PySequence_Fast_ITEMS(fast);
     for (size_t i = 0; i < attr_name.size(); ++i) {
 
-      PyObject* fl = PyNumber_Float(items[i]);
+      PyObject* fl = PYNUMBER_FLOATTYPE(items[i]);
       if (fl == NULL) {
         // Oh darn.  Not when we've come this far.
+#ifdef FLOATTYPE_IS_INT
+        PyErr_SetString(PyExc_ValueError, "a sequence of integers is required");
+#else
         PyErr_SetString(PyExc_ValueError, "a sequence of floats is required");
+#endif
         Py_DECREF(fast);
         return -1;
       }
-      double value = PyFloat_AS_DOUBLE(fl);
+      FLOATTYPE value = PY_AS_FLOATTYPE(fl);
       Py_DECREF(fl);
 
       _this->_v((attr_name[i] == 'w') ? 3 : attr_name[i] - 'x') = value;
@@ -171,19 +200,24 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
 
   } else {
     // Maybe it's a single floating-point value.
-    PyObject* fl = PyNumber_Float(assign);
+    PyObject* fl = PYNUMBER_FLOATTYPE(assign);
+
     if (fl == NULL) {
       // It's not a floating-point value either?
       // Sheesh, I don't know what to do with it then.
       if (attr_name.size() == 1) {
+#ifdef FLOATTYPE_IS_INT
+        PyErr_SetString(PyExc_ValueError, "an integer is required");
+#else
         PyErr_SetString(PyExc_ValueError, "a float is required");
+#endif
       } else {
         PyErr_Format(PyExc_ValueError, "'%.200s' object is not iterable",
           assign->ob_type->tp_name);
       }
       return -1;
     }
-    double value = PyFloat_AS_DOUBLE(fl);
+    FLOATTYPE value = PY_AS_FLOATTYPE(fl);
     Py_DECREF(fl);
 
     // Loop through the components in the attribute name,
@@ -196,6 +230,35 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   return 0;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::__pow__
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LVecBase4) Extension<FLOATNAME(LVecBase4)>::
+__pow__(FLOATTYPE exponent) const {
+  return FLOATNAME(LVecBase4)(
+    cpow(_this->_v(0), exponent),
+    cpow(_this->_v(1), exponent),
+    cpow(_this->_v(2), exponent),
+    cpow(_this->_v(3), exponent));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::__ipow__
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase4)>::
+__ipow__(PyObject *self, FLOATTYPE exponent) {
+  _this->_v(0) = cpow(_this->_v(0), exponent);
+  _this->_v(1) = cpow(_this->_v(1), exponent);
+  _this->_v(2) = cpow(_this->_v(2), exponent);
+  _this->_v(3) = cpow(_this->_v(3), exponent);
+  Py_INCREF(self);
+  return self;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: UnalignedLVecBase4::__setitem__
 //       Access: Public
@@ -206,3 +269,7 @@ __setitem__(int i, FLOATTYPE v) {
   nassertv(i >= 0 && i < 4);
   _this->_v(i) = v;
 }
+
+#undef PYNUMBER_FLOATTYPE
+#undef PY_FROM_FLOATTYPE
+#undef PY_AS_FLOATTYPE

+ 3 - 0
panda/src/linmath/lvecBase4_ext_src.h

@@ -27,6 +27,9 @@ public:
   INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign);
   INLINE_LINMATH void __setitem__(int i, FLOATTYPE v);
   INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const;
+
+  INLINE_LINMATH FLOATNAME(LVecBase4) __pow__(FLOATTYPE exponent) const;
+  INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent);
 };
 
 ////////////////////////////////////////////////////////////////////

+ 164 - 76
panda/src/linmath/lvecBase4_src.I

@@ -96,6 +96,16 @@ FLOATNAME(LVecBase4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) {
   set(x, y, z, w);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LVecBase4)::
+FLOATNAME(LVecBase4)(const FLOATNAME(LVecBase3) &copy, FLOATTYPE w) {
+  set(copy[0], copy[1], copy[2], w);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::Destructor
 //       Access: Published
@@ -162,7 +172,7 @@ unit_w() {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase4)::
 operator [](int i) const {
-  nassertr(i >= 0 && i < 4, 0.0);
+  nassertr(i >= 0 && i < 4, 0);
   return _v(i);
 }
 
@@ -195,8 +205,12 @@ size() {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH bool FLOATNAME(LVecBase4)::
 is_nan() const {
+#ifdef FLOATTYPE_IS_INT
+  return false;
+#else
   TAU_PROFILE("bool LVecBase4::is_nan()", " ", TAU_USER);
   return cnan(_v(0)) || cnan(_v(1)) || cnan(_v(2)) || cnan(_v(3));
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -206,7 +220,7 @@ is_nan() const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase4)::
 get_cell(int i) const {
-  nassertr(i >= 0 && i < 4, 0.0);
+  nassertr(i >= 0 && i < 4, 0);
   return _v(i);
 }
 
@@ -453,18 +467,19 @@ set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: LVecBase4::length
+//     Function: LVecBase4::dot
 //       Access: Published
-//  Description: Returns the length of the vector, by the Pythagorean
-//               theorem.
+//  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase4)::
-length() const {
-  TAU_PROFILE("FLOATTYPE LVecBase4::length()", " ", TAU_USER);
+dot(const FLOATNAME(LVecBase4) &other) const {
+  TAU_PROFILE("FLOATTYPE LVecBase4::dot()", " ", TAU_USER);
 #ifdef HAVE_EIGEN
-  return _v.norm();
+  return _v.dot(other._v);
 #else
-  return csqrt((*this).dot(*this));
+  return
+    _v(0) * other._v(0) + _v(1) * other._v(1) +
+    _v(2) * other._v(2) + _v(3) * other._v(3);
 #endif  // HAVE_EIGEN
 }
 
@@ -484,6 +499,23 @@ length_squared() const {
 #endif  // HAVE_EIGEN
 }
 
+#ifndef FLOATTYPE_IS_INT
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::length
+//       Access: Published
+//  Description: Returns the length of the vector, by the Pythagorean
+//               theorem.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase4)::
+length() const {
+  TAU_PROFILE("FLOATTYPE LVecBase4::length()", " ", TAU_USER);
+#ifdef HAVE_EIGEN
+  return _v.norm();
+#else
+  return csqrt((*this).dot(*this));
+#endif  // HAVE_EIGEN
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::normalize
 //       Access: Published
@@ -505,23 +537,6 @@ normalize() {
   return true;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase4::dot
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase4)::
-dot(const FLOATNAME(LVecBase4) &other) const {
-  TAU_PROFILE("FLOATTYPE LVecBase4::dot()", " ", TAU_USER);
-#ifdef HAVE_EIGEN
-  return _v.dot(other._v);
-#else
-  return
-    _v(0) * other._v(0) + _v(1) * other._v(1) +
-    _v(2) * other._v(2) + _v(3) * other._v(3);
-#endif  // HAVE_EIGEN
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::project
 //       Access: Published
@@ -533,6 +548,7 @@ INLINE_LINMATH FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::
 project(const FLOATNAME(LVecBase4) &onto) const {
   return onto * (dot(onto) / onto.length_squared());
 }
+#endif  // FLOATTYPE_IS_INT
 
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::operator <
@@ -586,9 +602,75 @@ operator != (const FLOATNAME(LVecBase4) &other) const {
 INLINE_LINMATH int FLOATNAME(LVecBase4)::
 compare_to(const FLOATNAME(LVecBase4) &other) const {
   TAU_PROFILE("int LVecBase4::compare_to(const LVecBase4 &)", " ", TAU_USER);
+#ifdef FLOATTYPE_IS_INT
+  if (_v(0) != other._v(0)) {
+    return (_v(0) < other._v(0)) ? -1 : 1;
+  }
+  if (_v(1) != other._v(1)) {
+    return (_v(1) < other._v(1)) ? -1 : 1;
+  }
+  if (_v(2) != other._v(2)) {
+    return (_v(2) < other._v(2)) ? -1 : 1;
+  }
+  if (_v(3) != other._v(3)) {
+    return (_v(3) < other._v(3)) ? -1 : 1;
+  }
+  return 0;
+#else
   return compare_to(other, NEARLY_ZERO(FLOATTYPE));
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::get_hash
+//       Access: Published
+//  Description: Returns a suitable hash for phash_map.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH size_t FLOATNAME(LVecBase4)::
+get_hash() const {
+  TAU_PROFILE("size_t LVecBase4::get_hash()", " ", TAU_USER);
+  return add_hash(0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::add_hash
+//       Access: Published
+//  Description: Adds the vector into the running hash.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH size_t FLOATNAME(LVecBase4)::
+add_hash(size_t hash) const {
+  TAU_PROFILE("size_t LVecBase4::add_hash(size_t)", " ", TAU_USER);
+#ifdef FLOATTYPE_IS_INT
+  int_hash ihasher;
+  hash = ihasher.add_hash(hash, _v(0));
+  hash = ihasher.add_hash(hash, _v(1));
+  hash = ihasher.add_hash(hash, _v(2));
+  hash = ihasher.add_hash(hash, _v(3));
+  return hash;
+#else
+  return add_hash(hash, NEARLY_ZERO(FLOATTYPE));
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::generate_hash
+//       Access: Published
+//  Description: Adds the vector to the indicated hash generator.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH void FLOATNAME(LVecBase4)::
+generate_hash(ChecksumHashGenerator &hashgen) const {
+  TAU_PROFILE("LVecBase4::generate_hash(ChecksumHashGenerator &)", " ", TAU_USER);
+#ifdef FLOATTYPE_IS_INT
+  hashgen.add_int(_v(0));
+  hashgen.add_int(_v(1));
+  hashgen.add_int(_v(2));
+  hashgen.add_int(_v(3));
+#else
+  generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE));
+#endif
 }
 
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::compare_to
 //       Access: Published
@@ -616,17 +698,6 @@ compare_to(const FLOATNAME(LVecBase4) &other, FLOATTYPE threshold) const {
   return 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase4::get_hash
-//       Access: Published
-//  Description: Returns a suitable hash for phash_map.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH size_t FLOATNAME(LVecBase4)::
-get_hash() const {
-  TAU_PROFILE("size_t LVecBase4::get_hash()", " ", TAU_USER);
-  return add_hash(0);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::get_hash
 //       Access: Published
@@ -638,17 +709,6 @@ get_hash(FLOATTYPE threshold) const {
   return add_hash(0, threshold);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase4::add_hash
-//       Access: Published
-//  Description: Adds the vector into the running hash.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH size_t FLOATNAME(LVecBase4)::
-add_hash(size_t hash) const {
-  TAU_PROFILE("size_t LVecBase4::add_hash(size_t)", " ", TAU_USER);
-  return add_hash(hash, NEARLY_ZERO(FLOATTYPE));
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::add_hash
 //       Access: Published
@@ -665,6 +725,21 @@ add_hash(size_t hash, FLOATTYPE threshold) const {
   return hash;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::generate_hash
+//       Access: Published
+//  Description: Adds the vector to the indicated hash generator.
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH void FLOATNAME(LVecBase4)::
+generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const {
+  TAU_PROFILE("LVecBase4::generate_hash(ChecksumHashGenerator &, FLOATTYPE)", " ", TAU_USER);
+  hashgen.add_fp(_v(0), threshold);
+  hashgen.add_fp(_v(1), threshold);
+  hashgen.add_fp(_v(2), threshold);
+  hashgen.add_fp(_v(3), threshold);
+}
+#endif  // FLOATTYPE_IS_INT
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::unary -
 //       Access: Published
@@ -737,8 +812,15 @@ operator * (FLOATTYPE scalar) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::
 operator / (FLOATTYPE scalar) const {
+#ifdef FLOATTYPE_IS_INT
+  return FLOATNAME(LVecBase4)(_v(0) / scalar,
+                              _v(1) / scalar,
+                              _v(2) / scalar,
+                              _v(3) / scalar);
+#else
   FLOATTYPE recip_scalar = 1.0f/scalar;
   return operator * (recip_scalar);
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -799,8 +881,15 @@ operator *= (FLOATTYPE scalar) {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase4)::
 operator /= (FLOATTYPE scalar) {
+#ifdef FLOATTYPE_IS_INT
+  _v(0) /= scalar;
+  _v(1) /= scalar;
+  _v(2) /= scalar;
+  _v(3) /= scalar;
+#else
   FLOATTYPE recip_scalar = 1.0f/scalar;
   operator *= (recip_scalar);
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -871,31 +960,6 @@ output(ostream &out) const {
       << MAYBE_ZERO(_v(3));
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase4::generate_hash
-//       Access: Published
-//  Description: Adds the vector to the indicated hash generator.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH void FLOATNAME(LVecBase4)::
-generate_hash(ChecksumHashGenerator &hashgen) const {
-  TAU_PROFILE("LVecBase4::generate_hash(ChecksumHashGenerator &)", " ", TAU_USER);
-  generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase4::generate_hash
-//       Access: Published
-//  Description: Adds the vector to the indicated hash generator.
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH void FLOATNAME(LVecBase4)::
-generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const {
-  TAU_PROFILE("LVecBase4::generate_hash(ChecksumHashGenerator &, FLOATTYPE)", " ", TAU_USER);
-  hashgen.add_fp(_v(0), threshold);
-  hashgen.add_fp(_v(1), threshold);
-  hashgen.add_fp(_v(2), threshold);
-  hashgen.add_fp(_v(3), threshold);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::write_datagram_fixed
 //       Access: Published
@@ -909,7 +973,12 @@ generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase4)::
 write_datagram_fixed(Datagram &destination) const {
-#if FLOATTOKEN == 'f'
+#if FLOATTOKEN == 'i'
+  destination.add_int32(_v(0));
+  destination.add_int32(_v(1));
+  destination.add_int32(_v(2));
+  destination.add_int32(_v(3));
+#elif FLOATTOKEN == 'f'
   destination.add_float32(_v(0));
   destination.add_float32(_v(1));
   destination.add_float32(_v(2));
@@ -930,7 +999,12 @@ write_datagram_fixed(Datagram &destination) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase4)::
 read_datagram_fixed(DatagramIterator &source) {
-#if FLOATTOKEN == 'f'
+#if FLOATTOKEN == 'i'
+  _v(0) = source.get_int32();
+  _v(1) = source.get_int32();
+  _v(2) = source.get_int32();
+  _v(3) = source.get_int32();
+#elif FLOATTOKEN == 'f'
   _v(0) = source.get_float32();
   _v(1) = source.get_float32();
   _v(2) = source.get_float32();
@@ -953,10 +1027,17 @@ read_datagram_fixed(DatagramIterator &source) {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase4)::
 write_datagram(Datagram &destination) const {
+#if FLOATTOKEN == 'i'
+  destination.add_int32(_v(0));
+  destination.add_int32(_v(1));
+  destination.add_int32(_v(2));
+  destination.add_int32(_v(3));
+#else
   destination.add_stdfloat(_v(0));
   destination.add_stdfloat(_v(1));
   destination.add_stdfloat(_v(2));
   destination.add_stdfloat(_v(3));
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -966,10 +1047,17 @@ write_datagram(Datagram &destination) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH void FLOATNAME(LVecBase4)::
 read_datagram(DatagramIterator &source) {
+#if FLOATTOKEN == 'i'
+  _v(0) = source.get_int32();
+  _v(1) = source.get_int32();
+  _v(2) = source.get_int32();
+  _v(3) = source.get_int32();
+#else
   _v(0) = source.get_stdfloat();
   _v(1) = source.get_stdfloat();
   _v(2) = source.get_stdfloat();
   _v(3) = source.get_stdfloat();
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1055,7 +1143,7 @@ set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATTYPE FLOATNAME(UnalignedLVecBase4)::
 operator [](int i) const {
-  nassertr(i >= 0 && i < 4, 0.0);
+  nassertr(i >= 0 && i < 4, 0);
   return _v(i);
 }
 

+ 5 - 5
panda/src/linmath/lvecBase4_src.cxx

@@ -16,15 +16,15 @@ TypeHandle FLOATNAME(LVecBase4)::_type_handle;
 TypeHandle FLOATNAME(UnalignedLVecBase4)::_type_handle;
 
 const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_zero =
-  FLOATNAME(LVecBase4)(0.0f, 0.0f, 0.0f, 0.0f);
+  FLOATNAME(LVecBase4)(0, 0, 0, 0);
 const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_x =
-  FLOATNAME(LVecBase4)(1.0f, 0.0f, 0.0f, 0.0f);
+  FLOATNAME(LVecBase4)(1, 0, 0, 0);
 const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_y =
-  FLOATNAME(LVecBase4)(0.0f, 1.0f, 0.0f, 0.0f);
+  FLOATNAME(LVecBase4)(0, 1, 0, 0);
 const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_z =
-  FLOATNAME(LVecBase4)(0.0f, 0.0f, 1.0f, 0.0f);
+  FLOATNAME(LVecBase4)(0, 0, 1, 0);
 const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_w =
-  FLOATNAME(LVecBase4)(0.0f, 0.0f, 0.0f, 1.0f);
+  FLOATNAME(LVecBase4)(0, 0, 0, 1);
 
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::init_type

+ 17 - 9
panda/src/linmath/lvecBase4_src.h

@@ -34,6 +34,7 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LVecBase4) &operator = (FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LVecBase4)(FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LVecBase4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w);
+  INLINE_LINMATH FLOATNAME(LVecBase4)(const FLOATNAME(LVecBase3) &copy, FLOATTYPE w);
   ALLOC_DELETED_CHAIN(FLOATNAME(LVecBase4));
 
   INLINE_LINMATH static const FLOATNAME(LVecBase4) &zero();
@@ -91,24 +92,32 @@ PUBLISHED:
   INLINE_LINMATH void fill(FLOATTYPE fill_value);
   INLINE_LINMATH void set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w);
 
-  INLINE_LINMATH FLOATTYPE length() const;
+  INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase4) &other) const;
   INLINE_LINMATH FLOATTYPE length_squared() const;
-  INLINE_LINMATH bool normalize();
 
-  INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase4) &other) const;
+#ifndef FLOATTYPE_IS_INT
+  INLINE_LINMATH FLOATTYPE length() const;
+  INLINE_LINMATH bool normalize();
   INLINE_LINMATH FLOATNAME(LVecBase4) project(const FLOATNAME(LVecBase4) &onto) const;
+#endif
 
   INLINE_LINMATH bool operator < (const FLOATNAME(LVecBase4) &other) const;
   INLINE_LINMATH bool operator == (const FLOATNAME(LVecBase4) &other) const;
   INLINE_LINMATH bool operator != (const FLOATNAME(LVecBase4) &other) const;
 
   INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase4) &other) const;
+  INLINE_LINMATH size_t get_hash() const;
+  INLINE_LINMATH size_t add_hash(size_t hash) const;
+  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const;
+
+#ifndef FLOATTYPE_IS_INT
   INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase4) &other,
                                 FLOATTYPE threshold) const;
-  INLINE_LINMATH size_t get_hash() const;
   INLINE_LINMATH size_t get_hash(FLOATTYPE threshold) const;
-  INLINE_LINMATH size_t add_hash(size_t hash) const;
   INLINE_LINMATH size_t add_hash(size_t hash, FLOATTYPE threshold) const;
+  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen,
+                                    FLOATTYPE threshold) const;
+#endif
 
   INLINE_LINMATH FLOATNAME(LVecBase4) operator - () const;
 
@@ -126,6 +135,9 @@ PUBLISHED:
   INLINE_LINMATH void operator *= (FLOATTYPE scalar);
   INLINE_LINMATH void operator /= (FLOATTYPE scalar);
 
+  EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase4) __pow__(FLOATTYPE exponent) const);
+  EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent));
+
   INLINE_LINMATH FLOATNAME(LVecBase4) fmax(const FLOATNAME(LVecBase4) &other);
   INLINE_LINMATH FLOATNAME(LVecBase4) fmin(const FLOATNAME(LVecBase4) &other);
 
@@ -136,10 +148,6 @@ PUBLISHED:
   INLINE_LINMATH void output(ostream &out) const;
   EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const);
 
-  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const;
-  INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen,
-                                    FLOATTYPE threshold) const;
-
   INLINE_LINMATH void write_datagram_fixed(Datagram &destination) const;
   INLINE_LINMATH void read_datagram_fixed(DatagramIterator &source);
   INLINE_LINMATH void write_datagram(Datagram &destination) const;

+ 2 - 0
panda/src/linmath/lvector2.cxx

@@ -20,3 +20,5 @@
 #include "dblnames.h"
 #include "lvector2_src.cxx"
 
+#include "intnames.h"
+#include "lvector2_src.cxx"

+ 3 - 0
panda/src/linmath/lvector2.h

@@ -26,4 +26,7 @@
 #include "dblnames.h"
 #include "lvector2_src.h"
 
+#include "intnames.h"
+#include "lvector2_src.h"
+
 #endif

+ 3 - 0
panda/src/linmath/lvector2_ext.h

@@ -26,4 +26,7 @@
 #include "dblnames.h"
 #include "lvector2_ext_src.h"
 
+#include "intnames.h"
+#include "lvector2_ext_src.h"
+
 #endif

+ 13 - 1
panda/src/linmath/lvector2_ext_src.I

@@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector3);
 IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector4);
 #endif
 
+#ifdef FLOATTYPE_IS_INT
+#if PY_MAJOR_VERSION >= 3
+#define PY_FROM_FLOATTYPE PyLong_FromLong
+#else
+#define PY_FROM_FLOATTYPE PyInt_FromLong
+#endif
+#else
+#define PY_FROM_FLOATTYPE PyFloat_FromDouble
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVector2::python_repr
 //       Access: Published
@@ -46,7 +56,7 @@ __getattr__(const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x'));
+      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2);
@@ -84,3 +94,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase2.
   return invoke_extension<FLOATNAME(LVecBase2)>(_this).__setattr__(self, attr_name, assign);
 }
+
+#undef PY_FROM_FLOATTYPE

+ 3 - 3
panda/src/linmath/lvector2_src.I

@@ -171,10 +171,10 @@ operator * (FLOATTYPE scalar) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LVector2) FLOATNAME(LVector2)::
 operator / (FLOATTYPE scalar) const {
-  FLOATTYPE recip_scalar = 1.0f/scalar;
-  return FLOATNAME(LVector2)(FLOATNAME(LVecBase2)::operator * (recip_scalar));
+  return FLOATNAME(LVector2)(FLOATNAME(LVecBase2)::operator / (scalar));
 }
 
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: LVector2::project
 //       Access: Published
@@ -208,4 +208,4 @@ INLINE_LINMATH FLOATTYPE FLOATNAME(LVector2)::
 signed_angle_deg(const FLOATNAME(LVector2) &other) const {
   return rad_2_deg(signed_angle_rad(other));
 }
-
+#endif  // FLOATTYPE_IS_INT

+ 2 - 0
panda/src/linmath/lvector2_src.h

@@ -43,9 +43,11 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LVector2) operator * (FLOATTYPE scalar) const;
   INLINE_LINMATH FLOATNAME(LVector2) operator / (FLOATTYPE scalar) const;
 
+#ifndef FLOATTYPE_IS_INT
   INLINE_LINMATH FLOATNAME(LVector2) project(const FLOATNAME(LVecBase2) &onto) const;
   INLINE_LINMATH FLOATTYPE signed_angle_rad(const FLOATNAME(LVector2) &other) const;
   INLINE_LINMATH FLOATTYPE signed_angle_deg(const FLOATNAME(LVector2) &other) const;
+#endif
 
   EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const);
 

+ 2 - 0
panda/src/linmath/lvector3.cxx

@@ -20,3 +20,5 @@
 #include "dblnames.h"
 #include "lvector3_src.cxx"
 
+#include "intnames.h"
+#include "lvector3_src.cxx"

+ 3 - 0
panda/src/linmath/lvector3.h

@@ -29,4 +29,7 @@
 #include "dblnames.h"
 #include "lvector3_src.h"
 
+#include "intnames.h"
+#include "lvector3_src.h"
+
 #endif

+ 3 - 0
panda/src/linmath/lvector3_ext.h

@@ -26,4 +26,7 @@
 #include "dblnames.h"
 #include "lvector3_ext_src.h"
 
+#include "intnames.h"
+#include "lvector3_ext_src.h"
+
 #endif

+ 13 - 1
panda/src/linmath/lvector3_ext_src.I

@@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector3);
 IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector4);
 #endif
 
+#ifdef FLOATTYPE_IS_INT
+#if PY_MAJOR_VERSION >= 3
+#define PY_FROM_FLOATTYPE PyLong_FromLong
+#else
+#define PY_FROM_FLOATTYPE PyInt_FromLong
+#endif
+#else
+#define PY_FROM_FLOATTYPE PyFloat_FromDouble
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVector3::python_repr
 //       Access: Published
@@ -47,7 +57,7 @@ __getattr__(const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x'));
+      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2);
@@ -85,3 +95,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase3.
   return invoke_extension<FLOATNAME(LVecBase3)>(_this).__setattr__(self, attr_name, assign);
 }
+
+#undef PY_FROM_FLOATTYPE

+ 28 - 19
panda/src/linmath/lvector3_src.I

@@ -75,6 +75,17 @@ FLOATNAME(LVector3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVector3::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LVector3)::
+FLOATNAME(LVector3)(const FLOATNAME(LVecBase2) &copy, FLOATTYPE z) :
+  FLOATNAME(LVecBase3)(copy, z)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVector3::zero Named Constructor
 //       Access: Published
@@ -208,6 +219,7 @@ cross(const FLOATNAME(LVecBase3) &other) const {
   return FLOATNAME(LVecBase3)::cross(other);
 }
 
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: LVector3::project
 //       Access: Published
@@ -309,6 +321,7 @@ INLINE_LINMATH FLOATTYPE FLOATNAME(LVector3)::
 relative_angle_deg(const FLOATNAME(LVector3) &other) const {
   return relative_angle_rad(other)*180/3.1415926535;
 }
+#endif  // FLOATTYPE_IS_INT
 
 ////////////////////////////////////////////////////////////////////
 //     Function: LVector3::operator * scalar
@@ -327,8 +340,7 @@ operator * (FLOATTYPE scalar) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LVector3) FLOATNAME(LVector3)::
 operator / (FLOATTYPE scalar) const {
-  FLOATTYPE recip_scalar = 1.0f/scalar;
-  return FLOATNAME(LVector3)(FLOATNAME(LVecBase3)::operator * (recip_scalar));
+  return FLOATNAME(LVector3)(FLOATNAME(LVecBase3)::operator / (scalar));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -345,16 +357,16 @@ up(CoordinateSystem cs) {
   switch (cs) {
   case CS_zup_right:
   case CS_zup_left:
-    return FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f);
+    return FLOATNAME(LVector3)(0, 0, 1);
 
   case CS_yup_right:
   case CS_yup_left:
-    return FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f);
+    return FLOATNAME(LVector3)(0, 1, 0);
 
   default:
     linmath_cat.error()
       << "Invalid coordinate system!\n";
-    return FLOATNAME(LVector3)(0.0f, 0.0f, 0.0f);
+    return FLOATNAME(LVector3)(0, 0, 0);
   }
 }
 
@@ -366,7 +378,7 @@ up(CoordinateSystem cs) {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LVector3) FLOATNAME(LVector3)::
 right(CoordinateSystem) {
-  return FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f);
+  return FLOATNAME(LVector3)(1, 0, 0);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -382,21 +394,21 @@ forward(CoordinateSystem cs) {
   }
   switch (cs) {
   case CS_zup_right:
-    return FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f);
+    return FLOATNAME(LVector3)(0, 1, 0);
 
   case CS_zup_left:
-    return FLOATNAME(LVector3)(0.0f, -1.0f, 0.0f);
+    return FLOATNAME(LVector3)(0, -1, 0);
 
   case CS_yup_right:
-    return FLOATNAME(LVector3)(0.0f, 0.0f, -1.0f);
+    return FLOATNAME(LVector3)(0, 0, -1);
 
   case CS_yup_left:
-    return FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f);
+    return FLOATNAME(LVector3)(0, 0, 1);
 
   default:
     linmath_cat.error()
       << "Invalid coordinate system!\n";
-    return FLOATNAME(LVector3)(0.0f, 0.0f, 0.0f);
+    return FLOATNAME(LVector3)(0, 0, 0);
   }
 }
 
@@ -440,8 +452,7 @@ back(CoordinateSystem cs) {
 //               forward, and up components, in whatever way the
 //               coordinate system represents that vector.
 ////////////////////////////////////////////////////////////////////
-
-//INLINE_LINMATH FLOATNAME(LVector3) & FLOATNAME(LVector3)::
+//INLINE_LINMATH FLOATNAME(LVector3) &FLOATNAME(LVector3)::
 INLINE_LINMATH FLOATNAME(LVector3) FLOATNAME(LVector3)::
 rfu(FLOATTYPE right_v, FLOATTYPE fwd_v, FLOATTYPE up_v,
     CoordinateSystem cs) {
@@ -449,12 +460,11 @@ rfu(FLOATTYPE right_v, FLOATTYPE fwd_v, FLOATTYPE up_v,
   /*  return forward(cs) * fwd_v + up(cs) * up_v + right(cs) * right_v; */
 
   // fast implementation of above for axis-aligned coordinate systems
-
-
   if (cs == CS_default) {
     cs = get_default_coordinate_system();
   }
-  FLOATTYPE vy,vz;
+
+  FLOATTYPE vy, vz;
   switch(cs) {
   case CS_yup_right:
     vz = -fwd_v;
@@ -479,9 +489,8 @@ rfu(FLOATTYPE right_v, FLOATTYPE fwd_v, FLOATTYPE up_v,
   default:
     linmath_cat.error()
       << "Invalid coordinate system!\n";
-    return FLOATNAME(LVector3)(0.0f, 0.0f, 0.0f);
+    return FLOATNAME(LVector3)(0);
   }
 
- return FLOATNAME(LVector3)(right_v,vy,vz);
+  return FLOATNAME(LVector3)(right_v, vy, vz);
 }
-

+ 4 - 1
panda/src/linmath/lvector3_src.h

@@ -30,6 +30,7 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LVector3) &operator = (FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LVector3)(FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LVector3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z);
+  INLINE_LINMATH FLOATNAME(LVector3)(const FLOATNAME(LVecBase2) &copy, FLOATTYPE z);
 
   EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const);
   EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign));
@@ -52,6 +53,8 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LVector3) operator - (const FLOATNAME(LVector3) &other) const;
 
   INLINE_LINMATH FLOATNAME(LVector3) cross(const FLOATNAME(LVecBase3) &other) const;
+
+#ifndef FLOATTYPE_IS_INT
   INLINE_LINMATH FLOATNAME(LVector3) project(const FLOATNAME(LVecBase3) &onto) const;
   INLINE_LINMATH FLOATTYPE angle_rad(const FLOATNAME(LVector3) &other) const;
   INLINE_LINMATH FLOATTYPE angle_deg(const FLOATNAME(LVector3) &other) const;
@@ -63,7 +66,7 @@ PUBLISHED:
 
   INLINE_LINMATH FLOATTYPE relative_angle_rad(const FLOATNAME(LVector3) &other) const;
   INLINE_LINMATH FLOATTYPE relative_angle_deg(const FLOATNAME(LVector3) &other) const;
-
+#endif
 
   INLINE_LINMATH FLOATNAME(LVector3) operator * (FLOATTYPE scalar) const;
   INLINE_LINMATH FLOATNAME(LVector3) operator / (FLOATTYPE scalar) const;

+ 2 - 0
panda/src/linmath/lvector4.cxx

@@ -20,3 +20,5 @@
 #include "dblnames.h"
 #include "lvector4_src.cxx"
 
+#include "intnames.h"
+#include "lvector4_src.cxx"

+ 3 - 0
panda/src/linmath/lvector4.h

@@ -26,4 +26,7 @@
 #include "dblnames.h"
 #include "lvector4_src.h"
 
+#include "intnames.h"
+#include "lvector4_src.h"
+
 #endif

+ 3 - 0
panda/src/linmath/lvector4_ext.h

@@ -26,4 +26,7 @@
 #include "dblnames.h"
 #include "lvector4_ext_src.h"
 
+#include "intnames.h"
+#include "lvector4_ext_src.h"
+
 #endif

+ 14 - 2
panda/src/linmath/lvector4_ext_src.I

@@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector3);
 IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector4);
 #endif
 
+#ifdef FLOATTYPE_IS_INT
+#if PY_MAJOR_VERSION >= 3
+#define PY_FROM_FLOATTYPE PyLong_FromLong
+#else
+#define PY_FROM_FLOATTYPE PyInt_FromLong
+#endif
+#else
+#define PY_FROM_FLOATTYPE PyFloat_FromDouble
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVector4::python_repr
 //       Access: Published
@@ -49,9 +59,9 @@ __getattr__(const string &attr_name) const {
   switch (attr_name.size()) {
     case 1:
       if (attr_name[0] == 'w') {
-        return PyFloat_FromDouble(_this->_v(3));
+        return PY_FROM_FLOATTYPE(_this->_v(3));
       } else {
-        return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x'));
+        return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
       }
 
     case 2: {
@@ -90,3 +100,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase4.
   return invoke_extension<FLOATNAME(LVecBase4)>(_this).__setattr__(self, attr_name, assign);
 }
+
+#undef PY_FROM_FLOATTYPE

+ 14 - 3
panda/src/linmath/lvector4_src.I

@@ -75,6 +75,17 @@ FLOATNAME(LVector4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVector4::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LVector4)::
+FLOATNAME(LVector4)(const FLOATNAME(LVecBase3) &copy, FLOATTYPE w) :
+  FLOATNAME(LVecBase4)(copy, w)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: LVector4::zero Named Constructor
 //       Access: Public
@@ -192,10 +203,10 @@ operator * (FLOATTYPE scalar) const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LVector4) FLOATNAME(LVector4)::
 operator / (FLOATTYPE scalar) const {
-  FLOATTYPE recip_scalar = 1.0f/scalar;
-  return FLOATNAME(LVector4)(FLOATNAME(LVecBase4)::operator * (recip_scalar));
+  return FLOATNAME(LVector4)(FLOATNAME(LVecBase4)::operator / (scalar));
 }
 
+#ifndef FLOATTYPE_IS_INT
 ////////////////////////////////////////////////////////////////////
 //     Function: LVector4::project
 //       Access: Published
@@ -207,4 +218,4 @@ INLINE_LINMATH FLOATNAME(LVector4) FLOATNAME(LVector4)::
 project(const FLOATNAME(LVecBase4) &onto) const {
   return FLOATNAME(LVecBase4)::project(onto);
 }
-
+#endif  // FLOATTYPE_IS_INT

+ 3 - 0
panda/src/linmath/lvector4_src.h

@@ -24,6 +24,7 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LVector4) &operator = (FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LVector4)(FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LVector4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w);
+  INLINE_LINMATH FLOATNAME(LVector4)(const FLOATNAME(LVecBase3) &copy, FLOATTYPE w);
 
   EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const);
   EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign));
@@ -45,7 +46,9 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LVector4) operator * (FLOATTYPE scalar) const;
   INLINE_LINMATH FLOATNAME(LVector4) operator / (FLOATTYPE scalar) const;
 
+#ifndef FLOATTYPE_IS_INT
   INLINE_LINMATH FLOATNAME(LVector4) project(const FLOATNAME(LVecBase4) &onto) const;
+#endif
 
   EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const);
 

+ 5 - 6
panda/src/pgraph/geomTransformer.cxx

@@ -1437,16 +1437,15 @@ append_vdata(const GeomVertexData *vdata, int vertex_offset) {
     if (index.has_column()) {
       int num_values = index.get_column()->get_num_values();
       int num_rows = vdata->get_num_rows();
-      int new_index[4];
-      
+
       index.set_row_unsafe(vertex_offset);
       for (int ci = 0; ci < num_rows; ++ci) {
-        const int *orig_index = index.get_data4i();
+        LVecBase4i indices = index.get_data4i();
         for (int i = 0; i < num_values; i++) {
-          nassertv(orig_index[i] >= 0 && orig_index[i] < (int)transform_map.size());
-          new_index[i] = transform_map[orig_index[i]];
+          nassertv(indices[i] >= 0 && indices[i] < (int)transform_map.size());
+          indices[i] = transform_map[indices[i]];
         }
-        index.set_data4i(new_index);
+        index.set_data4i(indices);
       }
     }
   }