gl vertex animation

This commit is contained in:
David Rose 2005-03-31 21:43:38 +00:00
parent c6bcbe88f5
commit b31d8eadd7
7 changed files with 281 additions and 20 deletions

View File

@ -90,8 +90,8 @@ upload_data() {
int data_size = get_data()->get_data_size_bytes(); int data_size = get_data()->get_data_size_bytes();
if (dxgsg8_cat.is_debug()) { if (dxgsg8_cat.is_spam()) {
dxgsg8_cat.debug() dxgsg8_cat.spam()
<< "copying " << data_size << "copying " << data_size
<< " bytes into index buffer " << _ibuffer << "\n"; << " bytes into index buffer " << _ibuffer << "\n";
} }

View File

@ -185,8 +185,8 @@ upload_data() {
int data_size = get_data()->get_data_size_bytes(); int data_size = get_data()->get_data_size_bytes();
if (dxgsg8_cat.is_debug()) { if (dxgsg8_cat.is_spam()) {
dxgsg8_cat.debug() dxgsg8_cat.spam()
<< "copying " << data_size << "copying " << data_size
<< " bytes into vertex buffer " << _vbuffer << "\n"; << " bytes into vertex buffer " << _vbuffer << "\n";
} }

View File

@ -65,6 +65,39 @@ munge_format_impl(const qpGeomVertexFormat *orig,
qpGeomVertexColumn::C_color, color_type->get_start()); qpGeomVertexColumn::C_color, color_type->get_start());
} }
if (animation.get_animation_type() == qpGeomVertexAnimationSpec::AT_hardware &&
animation.get_num_transforms() > 0) {
// If we want hardware animation, we need to reserve space for the
// blend weights.
PT(qpGeomVertexArrayFormat) new_array_format = new qpGeomVertexArrayFormat;
new_array_format->add_column
(InternalName::get_transform_weight(), animation.get_num_transforms() - 1,
qpGeomVertexColumn::NT_float32, qpGeomVertexColumn::C_other);
if (animation.get_indexed_transforms()) {
// Also, if we'll be indexing into the transform palette, reserve
// space for the index.
// TODO: We should examine the maximum palette index so we can
// decide whether we need 16-bit indices. That implies saving
// the maximum palette index, presumably in the AnimationSpec.
new_array_format->add_column
(InternalName::get_transform_index(), animation.get_num_transforms(),
qpGeomVertexColumn::NT_uint8, qpGeomVertexColumn::C_index);
}
// Make sure the old weights and indices are removed, just in
// case.
new_format->remove_column(InternalName::get_transform_weight());
new_format->remove_column(InternalName::get_transform_index());
// And we don't need the transform_blend table any more.
new_format->remove_column(InternalName::get_transform_blend());
new_format->add_array(new_array_format);
}
/* /*
if (true) { if (true) {
// Split out the interleaved array into n parallel arrays. // Split out the interleaved array into n parallel arrays.

View File

@ -364,12 +364,78 @@ reset() {
get_extra_extensions(); get_extra_extensions();
report_extensions(); report_extensions();
_supports_vertex_blend = has_extension("GL_ARB_vertex_blend");
if (_supports_vertex_blend) {
_glWeightPointerARB = (PFNGLWEIGHTPOINTERARBPROC)
get_extension_func(GLPREFIX_QUOTED, "WeightPointerARB");
_glVertexBlendARB = (PFNGLVERTEXBLENDARBPROC)
get_extension_func(GLPREFIX_QUOTED, "VertexBlendARB");
if (_glWeightPointerARB == NULL || _glVertexBlendARB == NULL) {
GLCAT.warning()
<< "Vertex blending advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n";
_supports_vertex_blend = false;
}
}
if (_supports_vertex_blend) {
GLP(Enable)(GL_WEIGHT_SUM_UNITY_ARB);
GLint max_vertex_units;
GLP(GetIntegerv)(GL_MAX_VERTEX_UNITS_ARB, &max_vertex_units);
_max_vertex_transforms = max_vertex_units;
GLCAT.debug()
<< "max vertex transforms = " << _max_vertex_transforms << "\n";
}
_supports_matrix_palette = has_extension("GL_ARB_matrix_palette");
if (_supports_matrix_palette) {
_glCurrentPaletteMatrixARB = (PFNGLCURRENTPALETTEMATRIXARBPROC)
get_extension_func(GLPREFIX_QUOTED, "CurrentPaletteMatrixARB");
_glMatrixIndexPointerARB = (PFNGLMATRIXINDEXPOINTERARBPROC)
get_extension_func(GLPREFIX_QUOTED, "MatrixIndexPointerARB");
if (_glCurrentPaletteMatrixARB == NULL || _glMatrixIndexPointerARB == NULL) {
GLCAT.warning()
<< "Matrix palette advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n";
_supports_matrix_palette = false;
}
}
/*
The matrix_palette support in this module is completely untested
(because I don't happen to have a card handy whose driver supports
this extension), so I have this ConfigVariable set to
unconditionally set this flag off for now, to protect the unwary.
When we have shown that the code works, we should remove this bit.
In the meantime, you must put both "matrix-palette 1" and
"gl-matrix-palette 1" in your Config.prc to exercise the new
code. */
if (!ConfigVariableBool("gl-matrix-palette", false, PRC_DESC("Temporary hack variable protecting untested code. See glGraphicsStateGuardian_src.cxx."))) {
if (_supports_matrix_palette) {
GLCAT.debug() << "Forcing off matrix palette support.\n";
}
_supports_matrix_palette = false;
}
if (_supports_matrix_palette) {
GLint max_palette_matrices;
GLP(GetIntegerv)(GL_MAX_PALETTE_MATRICES_ARB, &max_palette_matrices);
_max_vertex_transform_indices = max_palette_matrices;
GLCAT.debug()
<< "max vertex transform indices = " << _max_vertex_transform_indices << "\n";
}
_supports_draw_range_elements = false;
if (is_at_least_version(1, 2)) { if (is_at_least_version(1, 2)) {
_supports_draw_range_elements = true; _supports_draw_range_elements = true;
_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) _glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)
get_extension_func(GLPREFIX_QUOTED, "DrawRangeElements"); get_extension_func(GLPREFIX_QUOTED, "DrawRangeElements");
} else if (has_extension("EXT_draw_range_elements")) { } else if (has_extension("GL_EXT_draw_range_elements")) {
_supports_draw_range_elements = true; _supports_draw_range_elements = true;
_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) _glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)
get_extension_func(GLPREFIX_QUOTED, "DrawRangeElementsEXT"); get_extension_func(GLPREFIX_QUOTED, "DrawRangeElementsEXT");
@ -721,6 +787,9 @@ reset() {
_auto_antialias_mode = false; _auto_antialias_mode = false;
_render_mode = RenderModeAttrib::M_filled; _render_mode = RenderModeAttrib::M_filled;
_transform_stale = false;
_vertex_blending_enabled = false;
report_my_gl_errors(); report_my_gl_errors();
// Make sure the GL state matches all of our initial attribute // Make sure the GL state matches all of our initial attribute
@ -2084,9 +2153,93 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
} }
} }
const qpGeomVertexAnimationSpec &animation =
vertex_data->get_format()->get_animation();
bool hardware_animation = (animation.get_animation_type() == qpGeomVertexAnimationSpec::AT_hardware);
if (hardware_animation) {
// Set up the transform matrices for vertex blending.
GLP(Enable)(GL_VERTEX_BLEND_ARB);
_glVertexBlendARB(animation.get_num_transforms() - 1);
const TransformPalette *palette = vertex_data->get_transform_palette();
if (palette != (TransformPalette *)NULL) {
if (animation.get_indexed_transforms()) {
// We are loading the indexed matrix palette. The ARB decided
// to change this interface from that for the list of
// nonindexed matrices, to make it easier to load an arbitrary
// number of matrices.
GLP(Enable)(GL_MATRIX_PALETTE_ARB);
GLP(MatrixMode)(GL_MATRIX_PALETTE_ARB);
for (int i = 0; i < palette->get_num_transforms(); ++i) {
LMatrix4f mat;
palette->get_transform(i)->mult_matrix(mat, _transform->get_mat());
_glCurrentPaletteMatrixARB(i);
GLP(LoadMatrixf)(mat.get_data());
}
// Presumably loading the matrix palette does not step on the
// GL_MODELVIEW matrix?
} else {
// We are loading the list of nonindexed matrices. This is a
// little clumsier.
if (_supports_matrix_palette) {
GLP(Disable)(GL_MATRIX_PALETTE_ARB);
}
// GL_MODELVIEW0 and 1 are different than the rest.
int i = 0;
if (i < palette->get_num_transforms()) {
LMatrix4f mat;
palette->get_transform(i)->mult_matrix(mat, _transform->get_mat());
GLP(MatrixMode)(GL_MODELVIEW0_ARB);
GLP(LoadMatrixf)(mat.get_data());
++i;
}
if (i < palette->get_num_transforms()) {
LMatrix4f mat;
palette->get_transform(i)->mult_matrix(mat, _transform->get_mat());
GLP(MatrixMode)(GL_MODELVIEW1_ARB);
GLP(LoadMatrixf)(mat.get_data());
++i;
}
while (i < palette->get_num_transforms()) {
LMatrix4f mat;
palette->get_transform(i)->mult_matrix(mat, _transform->get_mat());
GLP(MatrixMode)(GL_MODELVIEW2_ARB + i - 2);
GLP(LoadMatrixf)(mat.get_data());
++i;
}
// Setting the GL_MODELVIEW0 matrix steps on the world matrix,
// so we have to set a flag to reload the world matrix later.
_transform_stale = true;
}
}
_vertex_blending_enabled = true;
} else {
// We're not using vertex blending.
if (_vertex_blending_enabled) {
GLP(Disable)(GL_VERTEX_BLEND_ARB);
if (_supports_matrix_palette) {
GLP(Disable)(GL_MATRIX_PALETTE_ARB);
}
_vertex_blending_enabled = false;
}
if (_transform_stale) {
GLP(MatrixMode)(GL_MODELVIEW);
GLP(LoadMatrixf)(_transform->get_mat().get_data());
}
}
if (geom->get_usage_hint() == qpGeomUsageHint::UH_static && if (geom->get_usage_hint() == qpGeomUsageHint::UH_static &&
_vertex_data->get_usage_hint() == qpGeomUsageHint::UH_static && _vertex_data->get_usage_hint() == qpGeomUsageHint::UH_static &&
display_lists) { display_lists && (!hardware_animation || display_list_animation)) {
// If the geom claims to be totally static, try to build it into // If the geom claims to be totally static, try to build it into
// a display list. // a display list.
GeomContext *gc = ((qpGeom *)geom)->prepare_now(get_prepared_objects(), this); GeomContext *gc = ((qpGeom *)geom)->prepare_now(get_prepared_objects(), this);
@ -2107,6 +2260,8 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
#endif #endif
// And now we don't need to do anything else for this geom. // And now we don't need to do anything else for this geom.
_geom_display_list = 0;
end_draw_primitives();
return false; return false;
} }
@ -2218,6 +2373,42 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
} }
_last_max_stage_index = max_stage_index; _last_max_stage_index = max_stage_index;
if (_supports_vertex_blend) {
if (hardware_animation) {
// Issue the weights and/or transform indices for vertex blending.
if (_vertex_data->get_array_info(InternalName::get_transform_weight(),
array_data, num_values, numeric_type,
start, stride)) {
const unsigned char *client_pointer = setup_array_data(array_data);
_glWeightPointerARB(num_values, get_numeric_type(numeric_type),
stride, client_pointer + start);
GLP(EnableClientState)(GL_WEIGHT_ARRAY_ARB);
} else {
GLP(DisableClientState)(GL_WEIGHT_ARRAY_ARB);
}
if (animation.get_indexed_transforms()) {
// Issue the matrix palette indices.
if (_vertex_data->get_array_info(InternalName::get_transform_index(),
array_data, num_values, numeric_type,
start, stride)) {
const unsigned char *client_pointer = setup_array_data(array_data);
_glMatrixIndexPointerARB(num_values, get_numeric_type(numeric_type),
stride, client_pointer + start);
GLP(EnableClientState)(GL_MATRIX_INDEX_ARRAY_ARB);
} else {
GLP(DisableClientState)(GL_MATRIX_INDEX_ARRAY_ARB);
}
}
} else {
GLP(DisableClientState)(GL_WEIGHT_ARRAY_ARB);
if (_supports_matrix_palette) {
GLP(DisableClientState)(GL_MATRIX_INDEX_ARRAY_ARB);
}
}
}
return true; return true;
} }
@ -2336,6 +2527,20 @@ end_draw_primitives() {
} }
_geom_display_list = 0; _geom_display_list = 0;
// Clean up the vertex blending state.
if (_vertex_blending_enabled) {
GLP(Disable)(GL_VERTEX_BLEND_ARB);
if (_supports_matrix_palette) {
GLP(Disable)(GL_MATRIX_PALETTE_ARB);
}
_vertex_blending_enabled = false;
}
if (_transform_stale) {
GLP(MatrixMode)(GL_MODELVIEW);
GLP(LoadMatrixf)(_transform->get_mat().get_data());
}
GraphicsStateGuardian::end_draw_primitives(); GraphicsStateGuardian::end_draw_primitives();
} }
@ -2585,8 +2790,8 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
add_to_vertex_buffer_record(gvbc); add_to_vertex_buffer_record(gvbc);
if (gvbc->was_modified()) { if (gvbc->was_modified()) {
if (GLCAT.is_debug()) { if (GLCAT.is_spam()) {
GLCAT.debug() GLCAT.spam()
<< "copying " << gvbc->get_data()->get_data_size_bytes() << "copying " << gvbc->get_data()->get_data_size_bytes()
<< " bytes into vertex buffer " << gvbc->_index << "\n"; << " bytes into vertex buffer " << gvbc->_index << "\n";
} }
@ -2716,8 +2921,8 @@ apply_index_buffer(IndexBufferContext *ibc) {
add_to_index_buffer_record(gibc); add_to_index_buffer_record(gibc);
if (gibc->was_modified()) { if (gibc->was_modified()) {
if (GLCAT.is_debug()) { if (GLCAT.is_spam()) {
GLCAT.debug() GLCAT.spam()
<< "copying " << gibc->get_data()->get_data_size_bytes() << "copying " << gibc->get_data()->get_data_size_bytes()
<< " bytes into index buffer " << gibc->_index << "\n"; << " bytes into index buffer " << gibc->_index << "\n";
} }
@ -3081,6 +3286,7 @@ issue_transform(const TransformState *transform) {
DO_PSTATS_STUFF(_transform_state_pcollector.add_level(1)); DO_PSTATS_STUFF(_transform_state_pcollector.add_level(1));
GLP(MatrixMode)(GL_MODELVIEW); GLP(MatrixMode)(GL_MODELVIEW);
GLP(LoadMatrixf)(transform->get_mat().get_data()); GLP(LoadMatrixf)(transform->get_mat().get_data());
_transform_stale = false;
_transform = transform; _transform = transform;
if (_auto_rescale_normal) { if (_auto_rescale_normal) {

View File

@ -314,6 +314,9 @@ protected:
bool _auto_antialias_mode; bool _auto_antialias_mode;
RenderModeAttrib::Mode _render_mode; RenderModeAttrib::Mode _render_mode;
bool _transform_stale;
bool _vertex_blending_enabled;
CPT(DisplayRegion) _actual_display_region; CPT(DisplayRegion) _actual_display_region;
#ifdef HAVE_CGGL #ifdef HAVE_CGGL
PT(CgShader) _cg_shader; // The current CgShader object PT(CgShader) _cg_shader; // The current CgShader object
@ -332,6 +335,14 @@ protected:
pset<string> _extensions; pset<string> _extensions;
public: public:
bool _supports_vertex_blend;
PFNGLWEIGHTPOINTERARBPROC _glWeightPointerARB;
PFNGLVERTEXBLENDARBPROC _glVertexBlendARB;
bool _supports_matrix_palette;
PFNGLCURRENTPALETTEMATRIXARBPROC _glCurrentPaletteMatrixARB;
PFNGLMATRIXINDEXPOINTERARBPROC _glMatrixIndexPointerARB;
bool _supports_draw_range_elements; bool _supports_draw_range_elements;
PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements; PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements;

View File

@ -99,16 +99,17 @@ ConfigVariableBool retained_mode
"in the experimental Geom rewrite.")); "in the experimental Geom rewrite."));
ConfigVariableBool vertex_buffers ConfigVariableBool vertex_buffers
("vertex-buffers", false, ("vertex-buffers", true,
PRC_DESC("Set this true to allow the use of vertex buffers (or buffer " PRC_DESC("Set this true to allow the use of vertex buffers (or buffer "
"objects, as OpenGL dubs them) for rendering vertex data. This " "objects, as OpenGL dubs them) for rendering vertex data. This "
"can greatly improve rendering performance, especially on " "can greatly improve rendering performance on "
"higher-end graphics cards, at the cost of some additional " "higher-end graphics cards, at the cost of some additional "
"graphics memory (which might otherwise be used for textures " "graphics memory (which might otherwise be used for textures "
"or offscreen buffers).")); "or offscreen buffers). On lower-end graphics cards this will "
"make little or no difference."));
ConfigVariableBool display_lists ConfigVariableBool display_lists
("display-lists", false, ("display-lists", true,
PRC_DESC("Set this true to allow the use of OpenGL display lists for " PRC_DESC("Set this true to allow the use of OpenGL display lists for "
"rendering static geometry. On some systems, this can result " "rendering static geometry. On some systems, this can result "
"in a performance improvement over vertex buffers alone; on " "in a performance improvement over vertex buffers alone; on "
@ -118,7 +119,7 @@ ConfigVariableBool display_lists
"on dynamic geometry (e.g. soft-skinned animation).")); "on dynamic geometry (e.g. soft-skinned animation)."));
ConfigVariableBool hardware_animated_vertices ConfigVariableBool hardware_animated_vertices
("hardware-animated-vertices", false, ("hardware-animated-vertices", true,
PRC_DESC("Set this true to allow the transforming of soft-skinned " PRC_DESC("Set this true to allow the transforming of soft-skinned "
"animated vertices via hardware, if supported, or false always " "animated vertices via hardware, if supported, or false always "
"to perform the vertex animation via software within Panda. " "to perform the vertex animation via software within Panda. "
@ -132,16 +133,25 @@ ConfigVariableBool hardware_animated_vertices
ConfigVariableBool matrix_palette ConfigVariableBool matrix_palette
("matrix-palette", false, ("matrix-palette", false,
PRC_DESC("Set this true to allow the use of the matrix palette when " PRC_DESC("Set this true to allow the use of the matrix palette when "
"animating vertices in hardware (if hardware-animated-vertices " "animating vertices in hardware. The matrix palette is "
"is also true). The matrix palette is not supported by all " "not supported by all devices, but if it is, using "
"devices, but if it is, using it can allow animation of more " "it can allow animation of more sophisticated meshes "
"sophisticated meshes in hardware, and it can also improve the " "in hardware, and it can also improve the "
"performance of animating some simpler meshes. Without " "performance of animating some simpler meshes. Without "
"this option, certain meshes will have to be animated in " "this option, certain meshes will have to be animated in "
"software. However, this option is not enabled by default, " "software. However, this option is not enabled by default, "
"because its support seems to be buggy in certain drivers " "because its support seems to be buggy in certain drivers "
"(ATI FireGL T2 8.103 in particular.)")); "(ATI FireGL T2 8.103 in particular.)"));
ConfigVariableBool display_list_animation
("display-list-animation", false,
PRC_DESC("Set this true to allow the use of OpenGL display lists for "
"rendering animated geometry (when the geometry is animated "
"by the hardware). This is not on by default because there "
"appear to be some driver issues with this on my FireGL T2, "
"but it should be perfectly doable in principle, and might get "
"you a small performance boost."));
ConfigVariableBool connect_triangle_strips ConfigVariableBool connect_triangle_strips
("connect-triangle-strips", true, ("connect-triangle-strips", true,
PRC_DESC("Set this true to set a batch of triangle strips to the graphics " PRC_DESC("Set this true to set a batch of triangle strips to the graphics "

View File

@ -55,6 +55,7 @@ extern EXPCL_PANDA ConfigVariableBool vertex_buffers;
extern EXPCL_PANDA ConfigVariableBool display_lists; extern EXPCL_PANDA ConfigVariableBool display_lists;
extern EXPCL_PANDA ConfigVariableBool hardware_animated_vertices; extern EXPCL_PANDA ConfigVariableBool hardware_animated_vertices;
extern EXPCL_PANDA ConfigVariableBool matrix_palette; extern EXPCL_PANDA ConfigVariableBool matrix_palette;
extern EXPCL_PANDA ConfigVariableBool display_list_animation;
extern EXPCL_PANDA ConfigVariableBool connect_triangle_strips; extern EXPCL_PANDA ConfigVariableBool connect_triangle_strips;
extern EXPCL_PANDA ConfigVariableBool use_qpgeom; extern EXPCL_PANDA ConfigVariableBool use_qpgeom;