diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 43e23c6238..b681e43aae 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/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(), diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 6787906c42..af29c23392 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/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; diff --git a/panda/src/glstuff/glImmediateModeSender_src.I b/panda/src/glstuff/glImmediateModeSender_src.I index a01845244a..c852660459 100644 --- a/panda/src/glstuff/glImmediateModeSender_src.I +++ b/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) +{ +} diff --git a/panda/src/glstuff/glImmediateModeSender_src.cxx b/panda/src/glstuff/glImmediateModeSender_src.cxx index 3b4e676a9b..22c160e880 100644 --- a/panda/src/glstuff/glImmediateModeSender_src.cxx +++ b/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); +} diff --git a/panda/src/glstuff/glImmediateModeSender_src.h b/panda/src/glstuff/glImmediateModeSender_src.h index 8cd959369d..4e0b94279b 100644 --- a/panda/src/glstuff/glImmediateModeSender_src.h +++ b/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 ComponentSenders; ComponentSenders _senders;