mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
gl vertex animation
This commit is contained in:
parent
c6bcbe88f5
commit
b31d8eadd7
@ -90,8 +90,8 @@ upload_data() {
|
||||
|
||||
int data_size = get_data()->get_data_size_bytes();
|
||||
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
if (dxgsg8_cat.is_spam()) {
|
||||
dxgsg8_cat.spam()
|
||||
<< "copying " << data_size
|
||||
<< " bytes into index buffer " << _ibuffer << "\n";
|
||||
}
|
||||
|
@ -185,8 +185,8 @@ upload_data() {
|
||||
|
||||
int data_size = get_data()->get_data_size_bytes();
|
||||
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
if (dxgsg8_cat.is_spam()) {
|
||||
dxgsg8_cat.spam()
|
||||
<< "copying " << data_size
|
||||
<< " bytes into vertex buffer " << _vbuffer << "\n";
|
||||
}
|
||||
|
@ -65,6 +65,39 @@ munge_format_impl(const qpGeomVertexFormat *orig,
|
||||
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) {
|
||||
// Split out the interleaved array into n parallel arrays.
|
||||
|
@ -364,12 +364,78 @@ reset() {
|
||||
get_extra_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)) {
|
||||
_supports_draw_range_elements = true;
|
||||
_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)
|
||||
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;
|
||||
_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DrawRangeElementsEXT");
|
||||
@ -721,6 +787,9 @@ reset() {
|
||||
_auto_antialias_mode = false;
|
||||
_render_mode = RenderModeAttrib::M_filled;
|
||||
|
||||
_transform_stale = false;
|
||||
_vertex_blending_enabled = false;
|
||||
|
||||
report_my_gl_errors();
|
||||
|
||||
// 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 &&
|
||||
_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
|
||||
// a display list.
|
||||
GeomContext *gc = ((qpGeom *)geom)->prepare_now(get_prepared_objects(), this);
|
||||
@ -2107,6 +2260,8 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
|
||||
#endif
|
||||
|
||||
// And now we don't need to do anything else for this geom.
|
||||
_geom_display_list = 0;
|
||||
end_draw_primitives();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2218,6 +2373,42 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *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.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2336,6 +2527,20 @@ end_draw_primitives() {
|
||||
}
|
||||
_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();
|
||||
}
|
||||
|
||||
@ -2585,8 +2790,8 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
|
||||
|
||||
add_to_vertex_buffer_record(gvbc);
|
||||
if (gvbc->was_modified()) {
|
||||
if (GLCAT.is_debug()) {
|
||||
GLCAT.debug()
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< "copying " << gvbc->get_data()->get_data_size_bytes()
|
||||
<< " bytes into vertex buffer " << gvbc->_index << "\n";
|
||||
}
|
||||
@ -2716,8 +2921,8 @@ apply_index_buffer(IndexBufferContext *ibc) {
|
||||
|
||||
add_to_index_buffer_record(gibc);
|
||||
if (gibc->was_modified()) {
|
||||
if (GLCAT.is_debug()) {
|
||||
GLCAT.debug()
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam()
|
||||
<< "copying " << gibc->get_data()->get_data_size_bytes()
|
||||
<< " 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));
|
||||
GLP(MatrixMode)(GL_MODELVIEW);
|
||||
GLP(LoadMatrixf)(transform->get_mat().get_data());
|
||||
_transform_stale = false;
|
||||
|
||||
_transform = transform;
|
||||
if (_auto_rescale_normal) {
|
||||
|
@ -314,6 +314,9 @@ protected:
|
||||
bool _auto_antialias_mode;
|
||||
RenderModeAttrib::Mode _render_mode;
|
||||
|
||||
bool _transform_stale;
|
||||
bool _vertex_blending_enabled;
|
||||
|
||||
CPT(DisplayRegion) _actual_display_region;
|
||||
#ifdef HAVE_CGGL
|
||||
PT(CgShader) _cg_shader; // The current CgShader object
|
||||
@ -332,6 +335,14 @@ protected:
|
||||
pset<string> _extensions;
|
||||
|
||||
public:
|
||||
bool _supports_vertex_blend;
|
||||
PFNGLWEIGHTPOINTERARBPROC _glWeightPointerARB;
|
||||
PFNGLVERTEXBLENDARBPROC _glVertexBlendARB;
|
||||
|
||||
bool _supports_matrix_palette;
|
||||
PFNGLCURRENTPALETTEMATRIXARBPROC _glCurrentPaletteMatrixARB;
|
||||
PFNGLMATRIXINDEXPOINTERARBPROC _glMatrixIndexPointerARB;
|
||||
|
||||
bool _supports_draw_range_elements;
|
||||
PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements;
|
||||
|
||||
|
@ -99,16 +99,17 @@ ConfigVariableBool retained_mode
|
||||
"in the experimental Geom rewrite."));
|
||||
|
||||
ConfigVariableBool vertex_buffers
|
||||
("vertex-buffers", false,
|
||||
("vertex-buffers", true,
|
||||
PRC_DESC("Set this true to allow the use of vertex buffers (or buffer "
|
||||
"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 "
|
||||
"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
|
||||
("display-lists", false,
|
||||
("display-lists", true,
|
||||
PRC_DESC("Set this true to allow the use of OpenGL display lists for "
|
||||
"rendering static geometry. On some systems, this can result "
|
||||
"in a performance improvement over vertex buffers alone; on "
|
||||
@ -118,7 +119,7 @@ ConfigVariableBool display_lists
|
||||
"on dynamic geometry (e.g. soft-skinned animation)."));
|
||||
|
||||
ConfigVariableBool hardware_animated_vertices
|
||||
("hardware-animated-vertices", false,
|
||||
("hardware-animated-vertices", true,
|
||||
PRC_DESC("Set this true to allow the transforming of soft-skinned "
|
||||
"animated vertices via hardware, if supported, or false always "
|
||||
"to perform the vertex animation via software within Panda. "
|
||||
@ -132,16 +133,25 @@ ConfigVariableBool hardware_animated_vertices
|
||||
ConfigVariableBool matrix_palette
|
||||
("matrix-palette", false,
|
||||
PRC_DESC("Set this true to allow the use of the matrix palette when "
|
||||
"animating vertices in hardware (if hardware-animated-vertices "
|
||||
"is also true). The matrix palette is not supported by all "
|
||||
"devices, but if it is, using it can allow animation of more "
|
||||
"sophisticated meshes in hardware, and it can also improve the "
|
||||
"animating vertices in hardware. The matrix palette is "
|
||||
"not supported by all devices, but if it is, using "
|
||||
"it can allow animation of more sophisticated meshes "
|
||||
"in hardware, and it can also improve the "
|
||||
"performance of animating some simpler meshes. Without "
|
||||
"this option, certain meshes will have to be animated in "
|
||||
"software. However, this option is not enabled by default, "
|
||||
"because its support seems to be buggy in certain drivers "
|
||||
"(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
|
||||
("connect-triangle-strips", true,
|
||||
PRC_DESC("Set this true to set a batch of triangle strips to the graphics "
|
||||
|
@ -55,6 +55,7 @@ extern EXPCL_PANDA ConfigVariableBool vertex_buffers;
|
||||
extern EXPCL_PANDA ConfigVariableBool display_lists;
|
||||
extern EXPCL_PANDA ConfigVariableBool hardware_animated_vertices;
|
||||
extern EXPCL_PANDA ConfigVariableBool matrix_palette;
|
||||
extern EXPCL_PANDA ConfigVariableBool display_list_animation;
|
||||
extern EXPCL_PANDA ConfigVariableBool connect_triangle_strips;
|
||||
|
||||
extern EXPCL_PANDA ConfigVariableBool use_qpgeom;
|
||||
|
Loading…
x
Reference in New Issue
Block a user