Browse Source

gl_vertex_blend with immediate-mode

David Rose 20 years ago
parent
commit
b390e64bc8

+ 23 - 2
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -360,8 +360,11 @@ reset() {
       get_extension_func(GLPREFIX_QUOTED, "WeightPointerARB");
     _glVertexBlendARB = (PFNGLVERTEXBLENDARBPROC)
       get_extension_func(GLPREFIX_QUOTED, "VertexBlendARB");
+    _glWeightfvARB = (PFNGLWEIGHTFVARBPROC)
+      get_extension_func(GLPREFIX_QUOTED, "WeightfvARB");
 
-    if (_glWeightPointerARB == NULL || _glVertexBlendARB == NULL) {
+    if (_glWeightPointerARB == NULL || _glVertexBlendARB == NULL ||
+        _glWeightfvARB == NULL) {
       GLCAT.warning()
         << "Vertex blending advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n";
       _supports_vertex_blend = false;
@@ -385,8 +388,12 @@ reset() {
       get_extension_func(GLPREFIX_QUOTED, "CurrentPaletteMatrixARB");
     _glMatrixIndexPointerARB = (PFNGLMATRIXINDEXPOINTERARBPROC)
       get_extension_func(GLPREFIX_QUOTED, "MatrixIndexPointerARB");
+    _glMatrixIndexuivARB = (PFNGLMATRIXINDEXUIVARBPROC)
+      get_extension_func(GLPREFIX_QUOTED, "MatrixIndexuivARB");
 
-    if (_glCurrentPaletteMatrixARB == NULL || _glMatrixIndexPointerARB == NULL) {
+    if (_glCurrentPaletteMatrixARB == NULL || 
+        _glMatrixIndexPointerARB == NULL ||
+        _glMatrixIndexuivARB == NULL) {
       GLCAT.warning()
         << "Matrix palette advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n";
       _supports_matrix_palette = false;
@@ -1345,6 +1352,20 @@ begin_draw_primitives(const Geom *geom, const GeomMunger *munger,
     }
     _last_max_stage_index = max_stage_index;
 
+    if (_supports_vertex_blend) {
+      if (hardware_animation) {
+        // Issue the weights and/or transform indices for vertex blending.
+        _sender.add_vector_column(_vertex_data, InternalName::get_transform_weight(),
+                                  _glWeightfvARB);
+        
+        if (animation.get_indexed_transforms()) {
+          // Issue the matrix palette indices.
+          _sender.add_vector_uint_column(_vertex_data, InternalName::get_transform_index(),
+                                        _glMatrixIndexuivARB);
+        }
+      }
+    }
+
     // We must add vertex last, because glVertex3f() is the key
     // function call that actually issues the vertex.
     _sender.add_column(_vertex_data, InternalName::get_vertex(),

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

@@ -337,10 +337,12 @@ public:
   bool _supports_vertex_blend;
   PFNGLWEIGHTPOINTERARBPROC _glWeightPointerARB;
   PFNGLVERTEXBLENDARBPROC _glVertexBlendARB;
+  PFNGLWEIGHTFVARBPROC _glWeightfvARB;
 
   bool _supports_matrix_palette;
   PFNGLCURRENTPALETTEMATRIXARBPROC _glCurrentPaletteMatrixARB;
   PFNGLMATRIXINDEXPOINTERARBPROC _glMatrixIndexPointerARB;
+  PFNGLMATRIXINDEXUIVARBPROC _glMatrixIndexuivARB;
 
   bool _supports_draw_range_elements;
   PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements;

+ 96 - 0
panda/src/glstuff/glImmediateModeSender_src.I

@@ -155,3 +155,99 @@ TexcoordSender4f(GeomVertexReader *reader, TexcoordFunc4f *func,
   _stage_index(stage_index)
 {
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender1f::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CLP(ImmediateModeSender)::VectorSender1f::
+VectorSender1f(GeomVertexReader *reader, VectorFunc *func) :
+  ComponentSender(reader),
+  _func(func)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender2f::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CLP(ImmediateModeSender)::VectorSender2f::
+VectorSender2f(GeomVertexReader *reader, VectorFunc *func) :
+  ComponentSender(reader),
+  _func(func)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender3f::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CLP(ImmediateModeSender)::VectorSender3f::
+VectorSender3f(GeomVertexReader *reader, VectorFunc *func) :
+  ComponentSender(reader),
+  _func(func)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender4f::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CLP(ImmediateModeSender)::VectorSender4f::
+VectorSender4f(GeomVertexReader *reader, VectorFunc *func) :
+  ComponentSender(reader),
+  _func(func)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender1ui::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CLP(ImmediateModeSender)::VectorSender1ui::
+VectorSender1ui(GeomVertexReader *reader, VectorUintFunc *func) :
+  ComponentSender(reader),
+  _func(func)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender2ui::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CLP(ImmediateModeSender)::VectorSender2ui::
+VectorSender2ui(GeomVertexReader *reader, VectorUintFunc *func) :
+  ComponentSender(reader),
+  _func(func)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender3ui::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CLP(ImmediateModeSender)::VectorSender3ui::
+VectorSender3ui(GeomVertexReader *reader, VectorUintFunc *func) :
+  ComponentSender(reader),
+  _func(func)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender4ui::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CLP(ImmediateModeSender)::VectorSender4ui::
+VectorSender4ui(GeomVertexReader *reader, VectorUintFunc *func) :
+  ComponentSender(reader),
+  _func(func)
+{
+}

+ 256 - 0
panda/src/glstuff/glImmediateModeSender_src.cxx

@@ -190,6 +190,115 @@ add_texcoord_column(const GeomVertexData *vertex_data,
   return false;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::add_vector_column
+//       Access: Public
+//  Description: Creates a new ComponentSender for the named data
+//               column, if it exists in the vertex data, and adds it
+//               to the list of senders for this object.
+//
+//               This works like add_column(), but it specifically
+//               handles a function that accepts as its first
+//               parameter the size (number of components) of the
+//               floating-point vector, followed by the address of the
+//               vector.
+//
+//               The return value is true if the column is added,
+//               false if it is not for some reason (for instance, the
+//               named column doesn't exist in the vertex data).
+////////////////////////////////////////////////////////////////////
+bool CLP(ImmediateModeSender)::
+add_vector_column(const GeomVertexData *vertex_data, const InternalName *name,
+                  VectorFunc *func) {
+  if (vertex_data->has_column(name)) {
+    GeomVertexReader *reader = new GeomVertexReader(vertex_data, name);
+    ComponentSender *sender = NULL;
+    const GeomVertexColumn *column = reader->get_column();
+    switch (column->get_num_components()) {
+    case 1:
+      sender = new VectorSender1f(reader, func);
+      break;
+
+    case 2:
+      sender = new VectorSender2f(reader, func);
+      break;
+
+    case 3:
+      sender = new VectorSender3f(reader, func);
+      break;
+
+    case 4:
+      sender = new VectorSender4f(reader, func);
+      break;
+    }
+
+    if (sender != (ComponentSender *)NULL) {
+      // Ok, we've got a valid sender; add it to the list.
+      _senders.push_back(sender);
+      return true;
+
+    } else {
+      // We didn't get a valid sender; clean up and return.
+      delete reader;
+    }
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::add_vector_uint_column
+//       Access: Public
+//  Description: Creates a new ComponentSender for the named data
+//               column, if it exists in the vertex data, and adds it
+//               to the list of senders for this object.
+//
+//               This works like add_vector_column(), but handles a
+//               function that receives a vector of unsigned ints.
+//
+//               The return value is true if the column is added,
+//               false if it is not for some reason (for instance, the
+//               named column doesn't exist in the vertex data).
+////////////////////////////////////////////////////////////////////
+bool CLP(ImmediateModeSender)::
+add_vector_uint_column(const GeomVertexData *vertex_data, 
+                       const InternalName *name, VectorUintFunc *func) {
+  if (vertex_data->has_column(name)) {
+    GeomVertexReader *reader = new GeomVertexReader(vertex_data, name);
+    ComponentSender *sender = NULL;
+    const GeomVertexColumn *column = reader->get_column();
+    switch (column->get_num_components()) {
+    case 1:
+      sender = new VectorSender1ui(reader, func);
+      break;
+
+    case 2:
+      sender = new VectorSender2ui(reader, func);
+      break;
+
+    case 3:
+      sender = new VectorSender3ui(reader, func);
+      break;
+
+    case 4:
+      sender = new VectorSender4ui(reader, func);
+      break;
+    }
+
+    if (sender != (ComponentSender *)NULL) {
+      // Ok, we've got a valid sender; add it to the list.
+      _senders.push_back(sender);
+      return true;
+
+    } else {
+      // We didn't get a valid sender; clean up and return.
+      delete reader;
+    }
+  }
+
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CLP(ImmediateModeSender)::add_sender
 //       Access: Public
@@ -360,3 +469,150 @@ issue_vertex() {
 
   (*_func)(GL_TEXTURE0 + _stage_index, d[0], d[1], d[2], d[3]);
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender1f::issue_vertex
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(ImmediateModeSender)::VectorSender1f::
+issue_vertex() {
+  float d = _reader->get_data1f();
+#ifndef NDEBUG
+  if (GLCAT.is_spam()) {
+    GLCAT.spam()
+      << *_reader->get_column()->get_name() << ": " << d << "\n";
+  }
+#endif  // NDEBUG
+
+  (*_func)(1, &d);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender2f::issue_vertex
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(ImmediateModeSender)::VectorSender2f::
+issue_vertex() {
+  const LVecBase2f &d = _reader->get_data2f();
+#ifndef NDEBUG
+  if (GLCAT.is_spam()) {
+    GLCAT.spam()
+      << *_reader->get_column()->get_name() << ": " << d << "\n";
+  }
+#endif  // NDEBUG
+
+  (*_func)(2, d.get_data());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender3f::issue_vertex
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(ImmediateModeSender)::VectorSender3f::
+issue_vertex() {
+  const LVecBase3f &d = _reader->get_data3f();
+#ifndef NDEBUG
+  if (GLCAT.is_spam()) {
+    GLCAT.spam()
+      << *_reader->get_column()->get_name() << ": " << d << "\n";
+  }
+#endif  // NDEBUG
+
+  (*_func)(3, d.get_data());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender4f::issue_vertex
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(ImmediateModeSender)::VectorSender4f::
+issue_vertex() {
+  const LVecBase4f &d = _reader->get_data4f();
+#ifndef NDEBUG
+  if (GLCAT.is_spam()) {
+    GLCAT.spam()
+      << *_reader->get_column()->get_name() << ": " << d << "\n";
+  }
+#endif  // NDEBUG
+
+  (*_func)(4, d.get_data());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender1ui::issue_vertex
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(ImmediateModeSender)::VectorSender1ui::
+issue_vertex() {
+  int d = _reader->get_data1i();
+#ifndef NDEBUG
+  if (GLCAT.is_spam()) {
+    GLCAT.spam()
+      << *_reader->get_column()->get_name() << ": " << d << "\n";
+  }
+#endif  // NDEBUG
+
+  (*_func)(1, (const unsigned int *)&d);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender2ui::issue_vertex
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(ImmediateModeSender)::VectorSender2ui::
+issue_vertex() {
+  const int *d = _reader->get_data2i();
+#ifndef NDEBUG
+  if (GLCAT.is_spam()) {
+    GLCAT.spam()
+      << *_reader->get_column()->get_name() << ": " << d[0] << " " 
+      << d[1] << "\n";
+  }
+#endif  // NDEBUG
+
+  (*_func)(2, (const unsigned int *)d);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender3ui::issue_vertex
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(ImmediateModeSender)::VectorSender3ui::
+issue_vertex() {
+  const int *d = _reader->get_data3i();
+#ifndef NDEBUG
+  if (GLCAT.is_spam()) {
+    GLCAT.spam()
+      << *_reader->get_column()->get_name() << ": " << d[0] << " " 
+      << d[1] << " " << d[2] << "\n";
+  }
+#endif  // NDEBUG
+
+  (*_func)(3, (const unsigned int *)d);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(ImmediateModeSender)::VectorSender4ui::issue_vertex
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CLP(ImmediateModeSender)::VectorSender4ui::
+issue_vertex() {
+  const int *d = _reader->get_data4i();
+#ifndef NDEBUG
+  if (GLCAT.is_spam()) {
+    GLCAT.spam()
+      << *_reader->get_column()->get_name() << ": " << d[0] << " " 
+      << d[1] << " " << d[2] << " " << d[3] << "\n";
+  }
+#endif  // NDEBUG
+
+  (*_func)(4, (const unsigned int *)d);
+}

+ 71 - 0
panda/src/glstuff/glImmediateModeSender_src.h

@@ -53,6 +53,8 @@ public:
   typedef void APIENTRY TexcoordFunc2f(GLenum texture, GLfloat a, GLfloat b);
   typedef void APIENTRY TexcoordFunc3f(GLenum texture, GLfloat a, GLfloat b, GLfloat c);
   typedef void APIENTRY TexcoordFunc4f(GLenum texture, GLfloat a, GLfloat b, GLfloat c, GLfloat d);
+  typedef void APIENTRY VectorFunc(GLint, const GLfloat *);
+  typedef void APIENTRY VectorUintFunc(GLint, const GLuint *);
 
   bool add_column(const GeomVertexData *vertex_data, const InternalName *name,
                   Func1f *func1f, Func2f *func2f, Func3f *func3f, Func4f *func4f);
@@ -61,6 +63,11 @@ public:
                            TexcoordFunc1f *func1f, TexcoordFunc2f *func2f, 
                            TexcoordFunc3f *func3f, TexcoordFunc4f *func4f);
 
+  bool add_vector_column(const GeomVertexData *vertex_data, const InternalName *name,
+                         VectorFunc *func);
+  bool add_vector_uint_column(const GeomVertexData *vertex_data, const InternalName *name,
+                              VectorUintFunc *func);
+
   void add_sender(ComponentSender *sender);
 
 public:
@@ -147,6 +154,70 @@ public:
     int _stage_index;
   };
 
+  class VectorSender1f : public ComponentSender {
+  public:
+    INLINE VectorSender1f(GeomVertexReader *reader, VectorFunc *func);
+    virtual void issue_vertex();
+  private:
+    VectorFunc *_func;
+  };
+
+  class VectorSender2f : public ComponentSender {
+  public:
+    INLINE VectorSender2f(GeomVertexReader *reader, VectorFunc *func);
+    virtual void issue_vertex();
+  private:
+    VectorFunc *_func;
+  };
+
+  class VectorSender3f : public ComponentSender {
+  public:
+    INLINE VectorSender3f(GeomVertexReader *reader, VectorFunc *func);
+    virtual void issue_vertex();
+  private:
+    VectorFunc *_func;
+  };
+
+  class VectorSender4f : public ComponentSender {
+  public:
+    INLINE VectorSender4f(GeomVertexReader *reader, VectorFunc *func);
+    virtual void issue_vertex();
+  private:
+    VectorFunc *_func;
+  };
+
+  class VectorSender1ui : public ComponentSender {
+  public:
+    INLINE VectorSender1ui(GeomVertexReader *reader, VectorUintFunc *func);
+    virtual void issue_vertex();
+  private:
+    VectorUintFunc *_func;
+  };
+
+  class VectorSender2ui : public ComponentSender {
+  public:
+    INLINE VectorSender2ui(GeomVertexReader *reader, VectorUintFunc *func);
+    virtual void issue_vertex();
+  private:
+    VectorUintFunc *_func;
+  };
+
+  class VectorSender3ui : public ComponentSender {
+  public:
+    INLINE VectorSender3ui(GeomVertexReader *reader, VectorUintFunc *func);
+    virtual void issue_vertex();
+  private:
+    VectorUintFunc *_func;
+  };
+
+  class VectorSender4ui : public ComponentSender {
+  public:
+    INLINE VectorSender4ui(GeomVertexReader *reader, VectorUintFunc *func);
+    virtual void issue_vertex();
+  private:
+    VectorUintFunc *_func;
+  };
+
 private:
   typedef pvector<ComponentSender *> ComponentSenders;
   ComponentSenders _senders;