hardware animation
This commit is contained in:
parent
bbe0a62001
commit
f77ea5156a
|
|
@ -27,3 +27,18 @@ INLINE const CharacterJoint *JointVertexTransform::
|
|||
get_joint() const {
|
||||
return _joint;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: JointVertexTransform::check_matrix
|
||||
// Access: Private
|
||||
// Description: Recomputes _matrix if it needs it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void JointVertexTransform::
|
||||
check_matrix() const {
|
||||
if (_matrix_stale) {
|
||||
((JointVertexTransform *)this)->_matrix =
|
||||
_joint->_initial_net_transform_inverse *
|
||||
_joint->_net_transform;
|
||||
((JointVertexTransform *)this)->_matrix_stale = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,16 +70,59 @@ JointVertexTransform::
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void JointVertexTransform::
|
||||
get_matrix(LMatrix4f &matrix) const {
|
||||
if (_matrix_stale) {
|
||||
((JointVertexTransform *)this)->_matrix =
|
||||
_joint->_initial_net_transform_inverse *
|
||||
_joint->_net_transform;
|
||||
((JointVertexTransform *)this)->_matrix_stale = false;
|
||||
}
|
||||
|
||||
check_matrix();
|
||||
matrix = _matrix;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: JointVertexTransform::mult_matrix
|
||||
// Access: Published, Virtual
|
||||
// Description: Premultiplies this transform's matrix with the
|
||||
// indicated previous matrix, so that the result is the
|
||||
// net composition of the given transform with this
|
||||
// transform. The result is stored in the parameter
|
||||
// "result", which should not be the same matrix as
|
||||
// previous.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void JointVertexTransform::
|
||||
mult_matrix(LMatrix4f &result, const LMatrix4f &previous) const {
|
||||
check_matrix();
|
||||
result.multiply(_matrix, previous);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: JointVertexTransform::accumulate_matrix
|
||||
// Access: Published, Virtual
|
||||
// Description: Adds the value of this transform's matrix, modified
|
||||
// by the indicated weight, into the indicated
|
||||
// accumulation matrix. This is used to compute the
|
||||
// result of several blended transforms.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void JointVertexTransform::
|
||||
accumulate_matrix(LMatrix4f &accum, float weight) const {
|
||||
check_matrix();
|
||||
|
||||
accum._m.m._00 += _matrix._m.m._00 * weight;
|
||||
accum._m.m._01 += _matrix._m.m._01 * weight;
|
||||
accum._m.m._02 += _matrix._m.m._02 * weight;
|
||||
accum._m.m._03 += _matrix._m.m._03 * weight;
|
||||
|
||||
accum._m.m._10 += _matrix._m.m._10 * weight;
|
||||
accum._m.m._11 += _matrix._m.m._11 * weight;
|
||||
accum._m.m._12 += _matrix._m.m._12 * weight;
|
||||
accum._m.m._13 += _matrix._m.m._13 * weight;
|
||||
|
||||
accum._m.m._20 += _matrix._m.m._20 * weight;
|
||||
accum._m.m._21 += _matrix._m.m._21 * weight;
|
||||
accum._m.m._22 += _matrix._m.m._22 * weight;
|
||||
accum._m.m._23 += _matrix._m.m._23 * weight;
|
||||
|
||||
accum._m.m._30 += _matrix._m.m._30 * weight;
|
||||
accum._m.m._31 += _matrix._m.m._31 * weight;
|
||||
accum._m.m._32 += _matrix._m.m._32 * weight;
|
||||
accum._m.m._33 += _matrix._m.m._33 * weight;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: JointVertexTransform::output
|
||||
// Access: Published, Virtual
|
||||
|
|
|
|||
|
|
@ -51,10 +51,14 @@ PUBLISHED:
|
|||
INLINE const CharacterJoint *get_joint() const;
|
||||
|
||||
virtual void get_matrix(LMatrix4f &matrix) const;
|
||||
virtual void mult_matrix(LMatrix4f &result, const LMatrix4f &previous) const;
|
||||
virtual void accumulate_matrix(LMatrix4f &accum, float weight) const;
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
INLINE void check_matrix() const;
|
||||
|
||||
PT(CharacterJoint) _joint;
|
||||
|
||||
LMatrix4f _matrix;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
||||
|
||||
#define SOURCES \
|
||||
colorMunger.I colorMunger.h \
|
||||
standardMunger.I standardMunger.h \
|
||||
config_display.h \
|
||||
drawableRegion.I drawableRegion.h \
|
||||
displayRegion.I displayRegion.h \
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
lensStack.I lensStack.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
colorMunger.cxx \
|
||||
standardMunger.cxx \
|
||||
config_display.cxx \
|
||||
drawableRegion.cxx \
|
||||
displayRegion.cxx \
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
windowProperties.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
colorMunger.I colorMunger.h \
|
||||
standardMunger.I standardMunger.h \
|
||||
config_display.h \
|
||||
drawableRegion.I drawableRegion.h \
|
||||
displayRegion.I displayRegion.h displayRegionStack.I \
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
|
||||
#include "config_display.h"
|
||||
#include "colorMunger.h"
|
||||
#include "standardMunger.h"
|
||||
#include "graphicsStateGuardian.h"
|
||||
#include "graphicsPipe.h"
|
||||
#include "graphicsOutput.h"
|
||||
|
|
@ -248,7 +248,7 @@ init_libdisplay() {
|
|||
}
|
||||
initialized = true;
|
||||
|
||||
ColorMunger::init_type();
|
||||
StandardMunger::init_type();
|
||||
GraphicsStateGuardian::init_type();
|
||||
GraphicsPipe::init_type();
|
||||
GraphicsOutput::init_type();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "colorMunger.cxx"
|
||||
#include "standardMunger.cxx"
|
||||
#include "drawableRegion.cxx"
|
||||
#include "displayRegion.cxx"
|
||||
#include "graphicsEngine.cxx"
|
||||
|
|
|
|||
|
|
@ -201,6 +201,44 @@ get_max_cube_map_dimension() const {
|
|||
return _max_cube_map_dimension;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_max_vertex_transforms
|
||||
// Access: Published
|
||||
// Description: Returns the maximum number of transform matrices that
|
||||
// may be simultaneously used to transform any one
|
||||
// vertex by the graphics hardware. If this number is
|
||||
// 0, then the hardware (or the graphics backend)
|
||||
// doesn't support soft-skinned vertices (in which case
|
||||
// Panda will animate the vertices in software).
|
||||
//
|
||||
// The value returned may not be meaningful until after
|
||||
// the graphics context has been fully created (e.g. the
|
||||
// window has been opened).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int GraphicsStateGuardian::
|
||||
get_max_vertex_transforms() const {
|
||||
return _max_vertex_transforms;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_max_vertex_transform_indices
|
||||
// Access: Published
|
||||
// Description: Returns the maximum number of transforms there may be
|
||||
// in a single TransformPalette for this graphics
|
||||
// hardware. If this number is 0 (but
|
||||
// get_max_transforms() is nonzero), then the graphics
|
||||
// hardware (or API) doesn't support indexed transforms,
|
||||
// but can support direct transform references.
|
||||
//
|
||||
// The value returned may not be meaningful until after
|
||||
// the graphics context has been fully created (e.g. the
|
||||
// window has been opened).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int GraphicsStateGuardian::
|
||||
get_max_vertex_transform_indices() const {
|
||||
return _max_vertex_transform_indices;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_copy_texture_inverted
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -104,6 +104,10 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
|
|||
_max_3d_texture_dimension = 0;
|
||||
_max_cube_map_dimension = 0;
|
||||
|
||||
// Assume no vertex blending capability.
|
||||
_max_vertex_transforms = 0;
|
||||
_max_vertex_transform_indices = 0;
|
||||
|
||||
// Initially, we set this to false; a GSG that knows it has this
|
||||
// property should set it to true.
|
||||
_copy_texture_inverted = false;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,9 @@ PUBLISHED:
|
|||
INLINE int get_max_3d_texture_dimension() const;
|
||||
INLINE int get_max_cube_map_dimension() const;
|
||||
|
||||
INLINE int get_max_vertex_transforms() const;
|
||||
INLINE int get_max_vertex_transform_indices() const;
|
||||
|
||||
INLINE bool get_copy_texture_inverted() const;
|
||||
virtual bool get_supports_multisample() const;
|
||||
INLINE bool get_supports_generate_mipmap() const;
|
||||
|
|
@ -314,6 +317,9 @@ protected:
|
|||
int _max_3d_texture_dimension;
|
||||
int _max_cube_map_dimension;
|
||||
|
||||
int _max_vertex_transforms;
|
||||
int _max_vertex_transform_indices;
|
||||
|
||||
bool _copy_texture_inverted;
|
||||
bool _supports_multisample;
|
||||
bool _supports_generate_mipmap;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Filename: colorMunger.I
|
||||
// Filename: standardMunger.I
|
||||
// Created by: drose (21Mar05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Filename: colorMunger.cxx
|
||||
// Filename: standardMunger.cxx
|
||||
// Created by: drose (21Mar05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -16,47 +16,53 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "colorMunger.h"
|
||||
#include "standardMunger.h"
|
||||
#include "renderState.h"
|
||||
#include "graphicsStateGuardian.h"
|
||||
#include "dcast.h"
|
||||
#include "config_gobj.h"
|
||||
|
||||
TypeHandle ColorMunger::_type_handle;
|
||||
TypeHandle StandardMunger::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ColorMunger::Constructor
|
||||
// Function: StandardMunger::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: The StandardMunger constructor accepts additional
|
||||
// parameters that specify the GSG's preferred color
|
||||
// format (since we might be munging the color anyway,
|
||||
// we might as well convert it as we munge).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ColorMunger::
|
||||
ColorMunger(const GraphicsStateGuardianBase *gsg, const RenderState *state,
|
||||
int num_components,
|
||||
qpGeomVertexDataType::NumericType numeric_type,
|
||||
qpGeomVertexDataType::Contents contents) :
|
||||
StandardMunger::
|
||||
StandardMunger(const GraphicsStateGuardianBase *gsg, const RenderState *state,
|
||||
int num_components,
|
||||
qpGeomVertexDataType::NumericType numeric_type,
|
||||
qpGeomVertexDataType::Contents contents) :
|
||||
qpGeomMunger(gsg, state),
|
||||
_num_components(num_components),
|
||||
_numeric_type(numeric_type),
|
||||
_contents(contents)
|
||||
{
|
||||
_gsg = DCAST(GraphicsStateGuardian, gsg);
|
||||
_color = state->get_color();
|
||||
_color_scale = state->get_color_scale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ColorMunger::Destructor
|
||||
// Function: StandardMunger::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ColorMunger::
|
||||
~ColorMunger() {
|
||||
StandardMunger::
|
||||
~StandardMunger() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ColorMunger::munge_data_impl
|
||||
// Function: StandardMunger::munge_data_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Given a source GeomVertexData, converts it as
|
||||
// necessary for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(qpGeomVertexData) ColorMunger::
|
||||
CPT(qpGeomVertexData) StandardMunger::
|
||||
munge_data_impl(const qpGeomVertexData *data) {
|
||||
CPT(qpGeomVertexData) new_data = data;
|
||||
|
||||
|
|
@ -81,20 +87,62 @@ munge_data_impl(const qpGeomVertexData *data) {
|
|||
_contents);
|
||||
}
|
||||
|
||||
return qpGeomMunger::munge_data_impl(new_data);
|
||||
qpGeomVertexAnimationSpec animation = data->get_format()->get_animation();
|
||||
if (hardware_animated_vertices &&
|
||||
animation.get_animation_type() == qpGeomVertexAnimationSpec::AT_panda &&
|
||||
data->get_slider_table() == (SliderTable *)NULL) {
|
||||
// Maybe we can animate the vertices with hardware.
|
||||
const TransformBlendPalette *palette = data->get_transform_blend_palette();
|
||||
if (palette != (TransformBlendPalette *)NULL &&
|
||||
palette->get_max_simultaneous_transforms() <=
|
||||
_gsg->get_max_vertex_transforms()) {
|
||||
if (palette->get_num_transforms() <=
|
||||
_gsg->get_max_vertex_transform_indices()) {
|
||||
|
||||
if (palette->get_num_transforms() == palette->get_max_simultaneous_transforms()) {
|
||||
// We can support an indexed palette, but since that won't
|
||||
// save us any per-vertex blends, go ahead and do a plain
|
||||
// old nonindexed palette instead.
|
||||
animation.set_hardware(palette->get_num_transforms(), false);
|
||||
|
||||
} else {
|
||||
// We can support an indexed palette, and that means we can
|
||||
// reduce the number of blends we have to specify for each
|
||||
// vertex.
|
||||
animation.set_hardware(palette->get_max_simultaneous_transforms(), true);
|
||||
}
|
||||
|
||||
} else if (palette->get_num_transforms() <=
|
||||
_gsg->get_max_vertex_transforms()) {
|
||||
// We can't support an indexed palette, but we have few enough
|
||||
// transforms that we can do a nonindexed palette.
|
||||
animation.set_hardware(palette->get_num_transforms(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CPT(qpGeomVertexFormat) orig_format = data->get_format();
|
||||
CPT(qpGeomVertexFormat) new_format = munge_format(orig_format, animation);
|
||||
|
||||
if (new_format == orig_format) {
|
||||
// Trivial case.
|
||||
return data;
|
||||
}
|
||||
|
||||
return data->convert_to(new_format);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ColorMunger::compare_to_impl
|
||||
// Function: StandardMunger::compare_to_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Called to compare two GeomMungers who are known to be
|
||||
// of the same type, for an apples-to-apples comparison.
|
||||
// This will never be called on two pointers of a
|
||||
// different type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int ColorMunger::
|
||||
int StandardMunger::
|
||||
compare_to_impl(const qpGeomMunger *other) const {
|
||||
const ColorMunger *om = DCAST(ColorMunger, other);
|
||||
const StandardMunger *om = DCAST(StandardMunger, other);
|
||||
if (_color != om->_color) {
|
||||
return _color < om->_color ? -1 : 1;
|
||||
}
|
||||
|
|
@ -106,16 +154,16 @@ compare_to_impl(const qpGeomMunger *other) const {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ColorMunger::geom_compare_to_impl
|
||||
// Function: StandardMunger::geom_compare_to_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Called to compare two GeomMungers who are known to be
|
||||
// of the same type, for an apples-to-apples comparison.
|
||||
// This will never be called on two pointers of a
|
||||
// different type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int ColorMunger::
|
||||
int StandardMunger::
|
||||
geom_compare_to_impl(const qpGeomMunger *other) const {
|
||||
const ColorMunger *om = DCAST(ColorMunger, other);
|
||||
const StandardMunger *om = DCAST(StandardMunger, other);
|
||||
if (_color != om->_color) {
|
||||
return _color < om->_color ? -1 : 1;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Filename: colorMunger.h
|
||||
// Filename: standardMunger.h
|
||||
// Created by: drose (21Mar05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -16,29 +16,32 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef COLORMUNGER_H
|
||||
#define COLORMUNGER_H
|
||||
#ifndef STANDARDMUNGER_H
|
||||
#define STANDARDMUNGER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "qpgeomMunger.h"
|
||||
#include "graphicsStateGuardian.h"
|
||||
#include "colorAttrib.h"
|
||||
#include "colorScaleAttrib.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ColorMunger
|
||||
// Description : Applies ColorAttrib and ColorScaleAttrib by munging
|
||||
// the vertex data.
|
||||
// Class : StandardMunger
|
||||
// Description : Performs some generic munging that is appropriate for
|
||||
// all GSG types; for instance, applies ColorAttrib and
|
||||
// ColorScaleAttrib to the vertices, and checks for
|
||||
// hardware-accelerated animation capabilities.
|
||||
//
|
||||
// This is part of the experimental Geom rewrite.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ColorMunger : public qpGeomMunger {
|
||||
class EXPCL_PANDA StandardMunger : public qpGeomMunger {
|
||||
public:
|
||||
ColorMunger(const GraphicsStateGuardianBase *gsg, const RenderState *state,
|
||||
int num_components,
|
||||
qpGeomVertexDataType::NumericType numeric_type,
|
||||
qpGeomVertexDataType::Contents contents);
|
||||
virtual ~ColorMunger();
|
||||
StandardMunger(const GraphicsStateGuardianBase *gsg, const RenderState *state,
|
||||
int num_components,
|
||||
qpGeomVertexDataType::NumericType numeric_type,
|
||||
qpGeomVertexDataType::Contents contents);
|
||||
virtual ~StandardMunger();
|
||||
|
||||
protected:
|
||||
virtual CPT(qpGeomVertexData) munge_data_impl(const qpGeomVertexData *data);
|
||||
|
|
@ -49,6 +52,7 @@ private:
|
|||
int _num_components;
|
||||
qpGeomVertexDataType::NumericType _numeric_type;
|
||||
qpGeomVertexDataType::Contents _contents;
|
||||
CPT(GraphicsStateGuardian) _gsg;
|
||||
CPT(ColorAttrib) _color;
|
||||
CPT(ColorScaleAttrib) _color_scale;
|
||||
|
||||
|
|
@ -58,7 +62,7 @@ public:
|
|||
}
|
||||
static void init_type() {
|
||||
qpGeomMunger::init_type();
|
||||
register_type(_type_handle, "ColorMunger",
|
||||
register_type(_type_handle, "StandardMunger",
|
||||
qpGeomMunger::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
|
|
@ -70,7 +74,7 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "colorMunger.I"
|
||||
#include "standardMunger.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE DXGeomMunger8::
|
||||
DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state) :
|
||||
ColorMunger(gsg, state, 1, qpGeomVertexDataType::NT_packed_8888,
|
||||
StandardMunger(gsg, state, 1, qpGeomVertexDataType::NT_packed_8888,
|
||||
qpGeomVertexDataType::C_argb)
|
||||
{
|
||||
}
|
||||
|
|
@ -38,5 +38,5 @@ DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state) :
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *DXGeomMunger8::
|
||||
operator new(size_t size) {
|
||||
return do_operator_new(size, _deleted_chain);
|
||||
return do_operator_new(size, &_deleted_chain);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dxGeomMunger8.h"
|
||||
#include "qpgeomVertexReader.h"
|
||||
#include "qpgeomVertexWriter.h"
|
||||
#include "config_dxgsg8.h"
|
||||
|
||||
qpGeomMunger *DXGeomMunger8::_deleted_chain = NULL;
|
||||
TypeHandle DXGeomMunger8::_type_handle;
|
||||
|
|
@ -28,11 +31,19 @@ TypeHandle DXGeomMunger8::_type_handle;
|
|||
// necessary to the appropriate format for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(qpGeomVertexFormat) DXGeomMunger8::
|
||||
munge_format_impl(const qpGeomVertexFormat *orig) {
|
||||
munge_format_impl(const qpGeomVertexFormat *orig,
|
||||
const qpGeomVertexAnimationSpec &animation) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
if (animation.get_animation_type() != qpGeomVertexAnimationSpec::AT_none) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "preparing animation type " << animation << "\n";
|
||||
}
|
||||
}
|
||||
// We have to build a completely new format that includes only the
|
||||
// appropriate components, in the appropriate order, in just one
|
||||
// array.
|
||||
PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*orig);
|
||||
new_format->set_animation(animation);
|
||||
PT(qpGeomVertexArrayFormat) new_array_format = new qpGeomVertexArrayFormat;
|
||||
|
||||
const qpGeomVertexDataType *vertex_type =
|
||||
|
|
@ -54,6 +65,23 @@ munge_format_impl(const qpGeomVertexFormat *orig) {
|
|||
return orig;
|
||||
}
|
||||
|
||||
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.
|
||||
new_array_format->add_data_type
|
||||
(InternalName::get_transform_weight(), animation.get_num_transforms() - 1,
|
||||
qpGeomVertexDataType::NT_float32, qpGeomVertexDataType::C_other);
|
||||
|
||||
if (animation.get_indexed_transforms()) {
|
||||
// Also, if we'll be indexing into the transfom palette, reserve
|
||||
// space for the index.
|
||||
new_array_format->add_data_type
|
||||
(InternalName::get_transform_index(), 1,
|
||||
qpGeomVertexDataType::NT_packed_8888, qpGeomVertexDataType::C_index);
|
||||
}
|
||||
}
|
||||
|
||||
if (normal_type != (const qpGeomVertexDataType *)NULL) {
|
||||
new_array_format->add_data_type
|
||||
(InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32,
|
||||
|
|
@ -89,27 +117,3 @@ munge_format_impl(const qpGeomVertexFormat *orig) {
|
|||
new_format->insert_array(0, new_array_format);
|
||||
return qpGeomVertexFormat::register_format(new_format);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXGeomMunger8::munge_geom_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Converts a Geom and/or its data as necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXGeomMunger8::
|
||||
munge_geom_impl(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &data) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXGeomMunger8::compare_to_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Called to compare two GeomMungers who are known to be
|
||||
// of the same type, for an apples-to-apples comparison.
|
||||
// This will never be called on two pointers of a
|
||||
// different type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int DXGeomMunger8::
|
||||
compare_to_impl(const qpGeomMunger *other) const {
|
||||
// const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other);
|
||||
|
||||
return ColorMunger::compare_to_impl(other);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#define DXGEOMMUNGER8_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "colorMunger.h"
|
||||
#include "standardMunger.h"
|
||||
#include "graphicsStateGuardian.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -31,14 +31,13 @@
|
|||
// and that all relevant components are packed into a
|
||||
// single array, in the correct order.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDADX DXGeomMunger8 : public ColorMunger {
|
||||
class EXPCL_PANDADX DXGeomMunger8 : public StandardMunger {
|
||||
public:
|
||||
INLINE DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state);
|
||||
|
||||
protected:
|
||||
virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig);
|
||||
virtual void munge_geom_impl(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &data);
|
||||
virtual int compare_to_impl(const qpGeomMunger *other) const;
|
||||
virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig,
|
||||
const qpGeomVertexAnimationSpec &animation);
|
||||
|
||||
public:
|
||||
INLINE void *operator new(size_t size);
|
||||
|
|
@ -51,9 +50,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ColorMunger::init_type();
|
||||
StandardMunger::init_type();
|
||||
register_type(_type_handle, "DXGeomMunger8",
|
||||
ColorMunger::get_class_type());
|
||||
StandardMunger::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ DXGraphicsStateGuardian8(const FrameBufferProperties &properties) :
|
|||
_pD3DDevice = NULL;
|
||||
|
||||
_bDXisReady = false;
|
||||
_transform_stale = false;
|
||||
_overlay_windows_supported = false;
|
||||
|
||||
_pFvfBufBasePtr = NULL;
|
||||
|
|
@ -287,10 +288,16 @@ free_d3d_device(void) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void DXGraphicsStateGuardian8::
|
||||
free_nondx_resources() {
|
||||
// this must not release any objects associated with D3D/DX!
|
||||
// those should be released in free_dxgsg_objects instead
|
||||
// this must not release any objects associated with D3D/DX!
|
||||
// those should be released in free_dxgsg_objects instead
|
||||
if (_index_buf != NULL) {
|
||||
SAFE_DELETE_ARRAY(_index_buf);
|
||||
_index_buf = NULL;
|
||||
}
|
||||
if (_pFvfBufBasePtr != NULL) {
|
||||
SAFE_DELETE_ARRAY(_pFvfBufBasePtr);
|
||||
_pFvfBufBasePtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -310,6 +317,34 @@ dx_init(void) {
|
|||
assert(_pScrn->pD3D8!=NULL);
|
||||
assert(_pD3DDevice!=NULL);
|
||||
|
||||
D3DCAPS8 d3dCaps;
|
||||
_pD3DDevice->GetDeviceCaps(&d3dCaps);
|
||||
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "\nHwTransformAndLight = " << ((d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0)
|
||||
<< "\nMaxTextureWidth = " << d3dCaps.MaxTextureWidth
|
||||
<< "\nMaxTextureHeight = " << d3dCaps.MaxTextureHeight
|
||||
<< "\nMaxVolumeExtent = " << d3dCaps.MaxVolumeExtent
|
||||
<< "\nMaxTextureAspectRatio = " << d3dCaps.MaxTextureAspectRatio
|
||||
<< "\nTexCoordCount = " << (d3dCaps.FVFCaps & D3DFVFCAPS_TEXCOORDCOUNTMASK)
|
||||
<< "\nMaxTextureBlendStages = " << d3dCaps.MaxTextureBlendStages
|
||||
<< "\nMaxSimultaneousTextures = " << d3dCaps.MaxSimultaneousTextures
|
||||
<< "\nMaxActiveLights = " << d3dCaps.MaxActiveLights
|
||||
<< "\nMaxUserClipPlanes = " << d3dCaps.MaxUserClipPlanes
|
||||
<< "\nMaxVertexBlendMatrices = " << d3dCaps.MaxVertexBlendMatrices
|
||||
<< "\nMaxVertexBlendMatrixIndex = " << d3dCaps.MaxVertexBlendMatrixIndex
|
||||
<< "\nMaxPointSize = " << d3dCaps.MaxPointSize
|
||||
<< "\nMaxPrimitiveCount = " << d3dCaps.MaxPrimitiveCount
|
||||
<< "\nMaxVertexIndex = " << d3dCaps.MaxVertexIndex
|
||||
<< "\nMaxStreams = " << d3dCaps.MaxStreams
|
||||
<< "\nMaxStreamStride = " << d3dCaps.MaxStreamStride
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
_max_vertex_transforms = d3dCaps.MaxVertexBlendMatrices;
|
||||
_max_vertex_transform_indices = d3dCaps.MaxVertexBlendMatrixIndex;
|
||||
|
||||
ZeroMemory(&_lmodel_ambient,sizeof(Colorf));
|
||||
_pD3DDevice->SetRenderState(D3DRS_AMBIENT, 0x0);
|
||||
|
||||
|
|
@ -2616,14 +2651,64 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
|
|||
|
||||
const qpGeomVertexFormat *format = _vertex_data->get_format();
|
||||
|
||||
// The munger should have put the "vertex" data at the beginning of
|
||||
// the first array.
|
||||
// The munger should have put the FVF data in the first array.
|
||||
const qpGeomVertexArrayData *data = _vertex_data->get_array(0);
|
||||
|
||||
VertexBufferContext *vbc = ((qpGeomVertexArrayData *)data)->prepare_now(get_prepared_objects(), this);
|
||||
nassertr(vbc != (VertexBufferContext *)NULL, false);
|
||||
apply_vertex_buffer(vbc);
|
||||
|
||||
const qpGeomVertexAnimationSpec &animation =
|
||||
vertex_data->get_format()->get_animation();
|
||||
if (animation.get_animation_type() == qpGeomVertexAnimationSpec::AT_hardware) {
|
||||
// Set up vertex blending.
|
||||
switch (animation.get_num_transforms()) {
|
||||
case 1:
|
||||
_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS);
|
||||
break;
|
||||
case 2:
|
||||
_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_1WEIGHTS);
|
||||
break;
|
||||
case 3:
|
||||
_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_2WEIGHTS);
|
||||
break;
|
||||
case 4:
|
||||
_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_3WEIGHTS);
|
||||
break;
|
||||
}
|
||||
|
||||
if (animation.get_indexed_transforms()) {
|
||||
// Set up indexed vertex blending.
|
||||
_pD3DDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);
|
||||
} else {
|
||||
_pD3DDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
|
||||
}
|
||||
|
||||
const TransformPalette *palette = vertex_data->get_transform_palette();
|
||||
if (palette != (TransformPalette *)NULL) {
|
||||
for (int i = 0; i < palette->get_num_transforms(); i++) {
|
||||
LMatrix4f mat;
|
||||
palette->get_transform(i)->mult_matrix(mat, _transform->get_mat());
|
||||
const D3DMATRIX *d3d_mat = (const D3DMATRIX *)mat.get_data();
|
||||
_pD3DDevice->SetTransform(D3DTS_WORLDMATRIX(i), d3d_mat);
|
||||
}
|
||||
|
||||
// Setting the palette transforms steps on the world matrix, so
|
||||
// we have to set a flag to reload the world matrix later.
|
||||
_transform_stale = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
// We're not using vertex blending.
|
||||
_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
|
||||
|
||||
if (_transform_stale) {
|
||||
const D3DMATRIX *d3d_mat = (const D3DMATRIX *)_transform->get_mat().get_data();
|
||||
_pD3DDevice->SetTransform(D3DTS_WORLD, d3d_mat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2938,16 +3023,18 @@ release_texture(TextureContext *tc) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
VertexBufferContext *DXGraphicsStateGuardian8::
|
||||
prepare_vertex_buffer(qpGeomVertexArrayData *data) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "prepare_vertex_buffer(" << (void *)data << ")\n";
|
||||
}
|
||||
|
||||
DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(data);
|
||||
|
||||
if (vertex_buffers) {
|
||||
dvbc->create_vbuffer(*_pScrn);
|
||||
dvbc->mark_loaded();
|
||||
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "creating vertex buffer " << dvbc->_vbuffer << ": "
|
||||
<< data->get_num_vertices() << " vertices "
|
||||
<< *data->get_array_format() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return dvbc;
|
||||
|
|
@ -2967,10 +3054,6 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
|
|||
add_to_vertex_buffer_record(dvbc);
|
||||
|
||||
if (dvbc->was_modified()) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "apply_vertex_buffer(" << (void *)vbc->get_data() << ")\n";
|
||||
}
|
||||
if (dvbc->changed_size()) {
|
||||
// Here we have to destroy the old vertex buffer and create a
|
||||
// new one.
|
||||
|
|
@ -3005,11 +3088,6 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void DXGraphicsStateGuardian8::
|
||||
release_vertex_buffer(VertexBufferContext *vbc) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "release_vertex_buffer(" << (void *)vbc->get_data() << ")\n";
|
||||
}
|
||||
|
||||
DXVertexBufferContext8 *dvbc = DCAST(DXVertexBufferContext8, vbc);
|
||||
delete dvbc;
|
||||
}
|
||||
|
|
@ -3029,16 +3107,16 @@ release_vertex_buffer(VertexBufferContext *vbc) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
IndexBufferContext *DXGraphicsStateGuardian8::
|
||||
prepare_index_buffer(qpGeomPrimitive *data) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "prepare_index_buffer(" << (void *)data << ")\n";
|
||||
}
|
||||
|
||||
DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(data);
|
||||
|
||||
dibc->create_ibuffer(*_pScrn);
|
||||
dibc->mark_loaded();
|
||||
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "creating index buffer " << dibc->_ibuffer << "\n";
|
||||
}
|
||||
|
||||
return dibc;
|
||||
}
|
||||
|
||||
|
|
@ -3056,10 +3134,6 @@ apply_index_buffer(IndexBufferContext *ibc) {
|
|||
add_to_index_buffer_record(dibc);
|
||||
|
||||
if (dibc->was_modified()) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "apply_index_buffer(" << (void *)ibc->get_data() << ")\n";
|
||||
}
|
||||
if (dibc->changed_size()) {
|
||||
// Here we have to destroy the old index buffer and create a
|
||||
// new one.
|
||||
|
|
@ -3092,11 +3166,6 @@ apply_index_buffer(IndexBufferContext *ibc) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void DXGraphicsStateGuardian8::
|
||||
release_index_buffer(IndexBufferContext *ibc) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "release_index_buffer(" << (void *)ibc->get_data() << ")\n";
|
||||
}
|
||||
|
||||
DXIndexBufferContext8 *dibc = DCAST(DXIndexBufferContext8, ibc);
|
||||
delete dibc;
|
||||
}
|
||||
|
|
@ -3419,9 +3488,9 @@ void DXGraphicsStateGuardian8::
|
|||
issue_transform(const TransformState *transform) {
|
||||
DO_PSTATS_STUFF(_transform_state_pcollector.add_level(1));
|
||||
|
||||
// if we're using ONLY vertex shaders, could get avoid calling SetTrans
|
||||
D3DMATRIX *pMat = (D3DMATRIX*)transform->get_mat().get_data();
|
||||
_pD3DDevice->SetTransform(D3DTS_WORLD,pMat);
|
||||
const D3DMATRIX *d3d_mat = (const D3DMATRIX *)transform->get_mat().get_data();
|
||||
_pD3DDevice->SetTransform(D3DTS_WORLD, d3d_mat);
|
||||
_transform_stale = false;
|
||||
|
||||
_transform = transform;
|
||||
if (_auto_rescale_normal) {
|
||||
|
|
|
|||
|
|
@ -185,8 +185,7 @@ protected:
|
|||
HRESULT _last_testcooplevel_result;
|
||||
DXTextureContext8 *_pCurTexContext;
|
||||
|
||||
bool _bTransformIssued; // decaling needs to tell when a transform has been issued
|
||||
D3DMATRIX _SavedTransform;
|
||||
bool _transform_stale;
|
||||
|
||||
RenderBuffer::Type _cur_read_pixel_buffer; // source for copy_pixel_buffer operation
|
||||
bool _auto_rescale_normal;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ DXIndexBufferContext8(qpGeomPrimitive *data) :
|
|||
DXIndexBufferContext8::
|
||||
~DXIndexBufferContext8() {
|
||||
if (_ibuffer != NULL) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "deleting index buffer " << _ibuffer << "\n";
|
||||
}
|
||||
|
||||
RELEASE(_ibuffer, dxgsg8, "index buffer", RELEASE_ONCE);
|
||||
_ibuffer = NULL;
|
||||
}
|
||||
|
|
@ -84,6 +89,12 @@ upload_data() {
|
|||
nassertv(_ibuffer != NULL);
|
||||
|
||||
int data_size = get_data()->get_data_size_bytes();
|
||||
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "copying " << data_size
|
||||
<< " bytes into index buffer " << _ibuffer << "\n";
|
||||
}
|
||||
|
||||
BYTE *local_pointer;
|
||||
HRESULT hr = _ibuffer->Lock(0, data_size, &local_pointer, 0);
|
||||
|
|
|
|||
|
|
@ -47,9 +47,52 @@ DXVertexBufferContext8(qpGeomVertexArrayData *data) :
|
|||
|
||||
if (n < num_data_types &&
|
||||
array_format->get_data_type(n)->get_name() == InternalName::get_vertex()) {
|
||||
_fvf |= D3DFVF_XYZ;
|
||||
++n;
|
||||
|
||||
int num_blend_values = 0;
|
||||
|
||||
if (n < num_data_types &&
|
||||
array_format->get_data_type(n)->get_name() == InternalName::get_transform_weight()) {
|
||||
// We have hardware vertex animation.
|
||||
num_blend_values = array_format->get_data_type(n)->get_num_values();
|
||||
++n;
|
||||
|
||||
if (n < num_data_types &&
|
||||
array_format->get_data_type(n)->get_name() == InternalName::get_transform_index()) {
|
||||
// Furthermore, it's indexed vertex animation.
|
||||
_fvf |= D3DFVF_LASTBETA_UBYTE4;
|
||||
++num_blend_values;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
switch (num_blend_values) {
|
||||
case 0:
|
||||
_fvf |= D3DFVF_XYZ;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
_fvf |= D3DFVF_XYZB1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
_fvf |= D3DFVF_XYZB2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
_fvf |= D3DFVF_XYZB3;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
_fvf |= D3DFVF_XYZB4;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
_fvf |= D3DFVF_XYZB5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (n < num_data_types &&
|
||||
array_format->get_data_type(n)->get_name() == InternalName::get_normal()) {
|
||||
_fvf |= D3DFVF_NORMAL;
|
||||
|
|
@ -95,6 +138,11 @@ DXVertexBufferContext8(qpGeomVertexArrayData *data) :
|
|||
DXVertexBufferContext8::
|
||||
~DXVertexBufferContext8() {
|
||||
if (_vbuffer != NULL) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "deleting vertex buffer " << _vbuffer << "\n";
|
||||
}
|
||||
|
||||
RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE);
|
||||
_vbuffer = NULL;
|
||||
}
|
||||
|
|
@ -136,6 +184,12 @@ upload_data() {
|
|||
nassertv(_vbuffer != NULL);
|
||||
|
||||
int data_size = get_data()->get_data_size_bytes();
|
||||
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "copying " << data_size
|
||||
<< " bytes into vertex buffer " << _vbuffer << "\n";
|
||||
}
|
||||
|
||||
BYTE *local_pointer;
|
||||
HRESULT hr = _vbuffer->Lock(0, data_size, &local_pointer, 0);
|
||||
|
|
|
|||
|
|
@ -1960,6 +1960,13 @@ make_vertex_data(const EggRenderState *render_state,
|
|||
// maybe a SliderTable, and additional columns in the vertex data:
|
||||
// one that indexes into the blend palette per vertex, and also
|
||||
// one for each different type of morph delta.
|
||||
|
||||
// Tell the format that we're setting it up for Panda-based
|
||||
// animation.
|
||||
qpGeomVertexAnimationSpec animation;
|
||||
animation.set_panda();
|
||||
temp_format->set_animation(animation);
|
||||
|
||||
blend_palette = new TransformBlendPalette;
|
||||
|
||||
PT(qpGeomVertexArrayFormat) anim_array_format = new qpGeomVertexArrayFormat;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(GeomMunger)::
|
||||
CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) :
|
||||
ColorMunger(gsg, state, 4, qpGeomVertexDataType::NT_uint8,
|
||||
StandardMunger(gsg, state, 4, qpGeomVertexDataType::NT_uint8,
|
||||
qpGeomVertexDataType::C_rgba),
|
||||
_gsg(gsg),
|
||||
_texture(state->get_texture()),
|
||||
|
|
@ -52,5 +52,5 @@ get_gsg() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *CLP(GeomMunger)::
|
||||
operator new(size_t size) {
|
||||
return do_operator_new(size, _deleted_chain);
|
||||
return do_operator_new(size, &_deleted_chain);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,33 +44,33 @@ CLP(GeomMunger)::
|
|||
// necessary to the appropriate format for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(qpGeomVertexFormat) CLP(GeomMunger)::
|
||||
munge_format_impl(const qpGeomVertexFormat *orig) {
|
||||
CPT(qpGeomVertexFormat) format = orig;
|
||||
munge_format_impl(const qpGeomVertexFormat *orig,
|
||||
const qpGeomVertexAnimationSpec &animation) {
|
||||
PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*orig);
|
||||
new_format->set_animation(animation);
|
||||
|
||||
const qpGeomVertexDataType *color_type =
|
||||
format->get_data_type(InternalName::get_color());
|
||||
orig->get_data_type(InternalName::get_color());
|
||||
if (color_type != (qpGeomVertexDataType *)NULL &&
|
||||
(color_type->get_numeric_type() == qpGeomVertexDataType::NT_packed_8888 ||
|
||||
color_type->get_contents() != qpGeomVertexDataType::C_rgba)) {
|
||||
// We need to convert the color format; OpenGL doesn't support the
|
||||
// byte order of DirectX's packed ARGB format.
|
||||
int color_array = format->get_array_with(InternalName::get_color());
|
||||
int color_array = orig->get_array_with(InternalName::get_color());
|
||||
|
||||
PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*format);
|
||||
PT(qpGeomVertexArrayFormat) new_array_format = new_format->modify_array(color_array);
|
||||
|
||||
// Replace the existing color format with the new format.
|
||||
new_array_format->add_data_type
|
||||
(InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8,
|
||||
qpGeomVertexDataType::C_rgba, color_type->get_start());
|
||||
|
||||
format = qpGeomVertexFormat::register_format(new_format);
|
||||
}
|
||||
|
||||
/*
|
||||
if (true) {
|
||||
// Split out the interleaved array into n parallel arrays.
|
||||
PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat;
|
||||
CPT(qpGeomVertexFormat) format = new_format;
|
||||
new_format = new qpGeomVertexFormat;
|
||||
for (int i = 0; i < format->get_num_data_types(); i++) {
|
||||
const qpGeomVertexDataType *data_type = format->get_data_type(i);
|
||||
PT(qpGeomVertexArrayFormat) new_array_format = new qpGeomVertexArrayFormat;
|
||||
|
|
@ -78,11 +78,10 @@ munge_format_impl(const qpGeomVertexFormat *orig) {
|
|||
data_type->get_numeric_type());
|
||||
new_format->add_array(new_array_format);
|
||||
}
|
||||
format = qpGeomVertexFormat::register_format(new_format);
|
||||
}
|
||||
*/
|
||||
|
||||
return format;
|
||||
return qpGeomVertexFormat::register_format(new_format);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -103,7 +102,7 @@ compare_to_impl(const qpGeomMunger *other) const {
|
|||
return _tex_gen < om->_tex_gen ? -1 : 1;
|
||||
}
|
||||
|
||||
return ColorMunger::compare_to_impl(other);
|
||||
return StandardMunger::compare_to_impl(other);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -119,5 +118,5 @@ geom_compare_to_impl(const qpGeomMunger *other) const {
|
|||
// We don't consider _texture and _tex_gen for this purpose; they
|
||||
// affect only whether the GL display list should be regenerated or
|
||||
// not, and don't require reconverting the vertices.
|
||||
return ColorMunger::geom_compare_to_impl(other);
|
||||
return StandardMunger::geom_compare_to_impl(other);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "colorMunger.h"
|
||||
#include "standardMunger.h"
|
||||
#include "graphicsStateGuardian.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "texGenAttrib.h"
|
||||
|
|
@ -31,7 +31,7 @@ class CLP(GeomContext);
|
|||
// for OpenGL rendering. In particular, it makes sure
|
||||
// colors aren't stored in DirectX's packed_argb format.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_GL CLP(GeomMunger) : public ColorMunger {
|
||||
class EXPCL_GL CLP(GeomMunger) : public StandardMunger {
|
||||
public:
|
||||
INLINE CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state);
|
||||
virtual ~CLP(GeomMunger)();
|
||||
|
|
@ -39,7 +39,8 @@ public:
|
|||
INLINE GraphicsStateGuardian *get_gsg() const;
|
||||
|
||||
protected:
|
||||
virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig);
|
||||
virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig,
|
||||
const qpGeomVertexAnimationSpec &animation);
|
||||
virtual int compare_to_impl(const qpGeomMunger *other) const;
|
||||
virtual int geom_compare_to_impl(const qpGeomMunger *other) const;
|
||||
|
||||
|
|
@ -61,9 +62,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ColorMunger::init_type();
|
||||
StandardMunger::init_type();
|
||||
register_type(_type_handle, CLASSPREFIX_QUOTED "GeomMunger",
|
||||
ColorMunger::get_class_type());
|
||||
StandardMunger::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
qpgeomVertexArrayFormat.h qpgeomVertexArrayFormat.I \
|
||||
qpgeomCacheEntry.h qpgeomCacheEntry.I \
|
||||
qpgeomCacheManager.h qpgeomCacheManager.I \
|
||||
qpgeomVertexAnimationSpec.h qpgeomVertexAnimationSpec.I \
|
||||
qpgeomVertexData.h qpgeomVertexData.I \
|
||||
qpgeomVertexDataType.h qpgeomVertexDataType.I \
|
||||
qpgeomVertexFormat.h qpgeomVertexFormat.I \
|
||||
|
|
@ -82,6 +83,7 @@
|
|||
qpgeomVertexArrayFormat.cxx \
|
||||
qpgeomCacheEntry.cxx \
|
||||
qpgeomCacheManager.cxx \
|
||||
qpgeomVertexAnimationSpec.cxx \
|
||||
qpgeomVertexData.cxx \
|
||||
qpgeomVertexDataType.cxx \
|
||||
qpgeomVertexFormat.cxx \
|
||||
|
|
@ -131,6 +133,7 @@
|
|||
qpgeomVertexArrayFormat.h qpgeomVertexArrayFormat.I \
|
||||
qpgeomCacheEntry.h qpgeomCacheEntry.I \
|
||||
qpgeomCacheManager.h qpgeomCacheManager.I \
|
||||
qpgeomVertexAnimationSpec.h qpgeomVertexAnimationSpec.I \
|
||||
qpgeomVertexData.h qpgeomVertexData.I \
|
||||
qpgeomVertexDataType.h qpgeomVertexDataType.I \
|
||||
qpgeomVertexFormat.h qpgeomVertexFormat.I \
|
||||
|
|
|
|||
|
|
@ -113,9 +113,21 @@ ConfigVariableBool display_lists
|
|||
"rendering static geometry. On some systems, this can result "
|
||||
"in a performance improvement over vertex buffers alone; on "
|
||||
"other systems (particularly low-end systems) it makes little to "
|
||||
"no difference. This has no effect on DirectX rendering. If "
|
||||
"vertex-buffers is also enabled, then OpenGL buffer objects "
|
||||
"will also be created for dynamic geometry."));
|
||||
"no difference. On some systems, using display lists can actually "
|
||||
"reduce performance. This has no effect on DirectX rendering or "
|
||||
"on dynamic geometry (e.g. soft-skinned animation)."));
|
||||
|
||||
ConfigVariableBool hardware_animated_vertices
|
||||
("hardware-animated-vertices", false,
|
||||
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. "
|
||||
"If you have a card that supports this, and your scene does "
|
||||
"not contain too many vertices already, this can provide a "
|
||||
"performance boost by offloading some work from your CPU onto "
|
||||
"your graphics card. It may also help by reducing the bandwidth "
|
||||
"necessary on your computer's bus. However, in some cases it "
|
||||
"may actually reduce performance."));
|
||||
|
||||
ConfigVariableBool use_qpgeom
|
||||
("use-qpgeom", false,
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ extern EXPCL_PANDA ConfigVariableBool keep_geom_ram;
|
|||
extern EXPCL_PANDA ConfigVariableBool retained_mode;
|
||||
extern EXPCL_PANDA ConfigVariableBool vertex_buffers;
|
||||
extern EXPCL_PANDA ConfigVariableBool display_lists;
|
||||
extern EXPCL_PANDA ConfigVariableBool hardware_animated_vertices;
|
||||
|
||||
extern EXPCL_PANDA ConfigVariableBool use_qpgeom;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "qpgeomVertexArrayFormat.cxx"
|
||||
#include "qpgeomCacheEntry.cxx"
|
||||
#include "qpgeomCacheManager.cxx"
|
||||
#include "qpgeomVertexAnimationSpec.cxx"
|
||||
#include "qpgeomVertexData.cxx"
|
||||
#include "qpgeomVertexDataType.cxx"
|
||||
#include "qpgeomVertexFormat.cxx"
|
||||
|
|
|
|||
|
|
@ -191,6 +191,32 @@ get_transform_blend() {
|
|||
return _transform_blend;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: InternalName::get_transform_weight
|
||||
// Access: Published, Static
|
||||
// Description: Returns the standard InternalName "transform_weight".
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PT(InternalName) InternalName::
|
||||
get_transform_weight() {
|
||||
if (_transform_weight == (InternalName *)NULL) {
|
||||
_transform_weight = InternalName::make("transform_weight");
|
||||
}
|
||||
return _transform_weight;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: InternalName::get_transform_index
|
||||
// Access: Published, Static
|
||||
// Description: Returns the standard InternalName "transform_index".
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PT(InternalName) InternalName::
|
||||
get_transform_index() {
|
||||
if (_transform_index == (InternalName *)NULL) {
|
||||
_transform_index = InternalName::make("transform_index");
|
||||
}
|
||||
return _transform_index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: InternalName::get_morph
|
||||
// Access: Published, Static
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ PT(InternalName) InternalName::_binormal;
|
|||
PT(InternalName) InternalName::_texcoord;
|
||||
PT(InternalName) InternalName::_color;
|
||||
PT(InternalName) InternalName::_transform_blend;
|
||||
PT(InternalName) InternalName::_transform_weight;
|
||||
PT(InternalName) InternalName::_transform_index;
|
||||
|
||||
TypeHandle InternalName::_type_handle;
|
||||
TypeHandle InternalName::_texcoord_type_handle;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ PUBLISHED:
|
|||
INLINE static PT(InternalName) get_texcoord_name(const string &name);
|
||||
INLINE static PT(InternalName) get_color();
|
||||
INLINE static PT(InternalName) get_transform_blend();
|
||||
INLINE static PT(InternalName) get_transform_weight();
|
||||
INLINE static PT(InternalName) get_transform_index();
|
||||
INLINE static PT(InternalName) get_morph(InternalName *data_type, const string &slider);
|
||||
|
||||
private:
|
||||
|
|
@ -91,6 +93,8 @@ private:
|
|||
static PT(InternalName) _texcoord;
|
||||
static PT(InternalName) _color;
|
||||
static PT(InternalName) _transform_blend;
|
||||
static PT(InternalName) _transform_weight;
|
||||
static PT(InternalName) _transform_index;
|
||||
|
||||
public:
|
||||
// Datagram stuff
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomMunger::is_registered
|
||||
// Access: Published
|
||||
// Access: Public
|
||||
// Description: Returns true if this munger has been registered,
|
||||
// false if it has not. It may not be used for a Geom
|
||||
// until it has been registered, but once registered, it
|
||||
|
|
@ -32,7 +32,7 @@ is_registered() const {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomMunger::register_munger
|
||||
// Access: Published, Static
|
||||
// Access: Public, Static
|
||||
// Description: Adds the indicated munger to the registry, if there
|
||||
// is not an equivalent munger already there; in either
|
||||
// case, returns the pointer to the equivalent munger
|
||||
|
|
@ -100,13 +100,19 @@ geom_compare_to(const qpGeomMunger &other) const {
|
|||
// Access: Public
|
||||
// Description: Given a source GeomVertexFormat, converts it if
|
||||
// necessary to the appropriate format for rendering.
|
||||
//
|
||||
// If the GeomVertexAnimationSpec so indicates, then the
|
||||
// format will be chosen to convert CPU-based animation
|
||||
// tables to HW-based animation tables, reserving space
|
||||
// for the specified number of transforms per vertex.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CPT(qpGeomVertexFormat) qpGeomMunger::
|
||||
munge_format(const qpGeomVertexFormat *format) const {
|
||||
munge_format(const qpGeomVertexFormat *format,
|
||||
const qpGeomVertexAnimationSpec &animation) const {
|
||||
// We cast away the const pointer, because do_munge_format() needs
|
||||
// to update caches and stuff, but we trust it not to change any
|
||||
// user-definable parameters.
|
||||
return ((qpGeomMunger *)this)->do_munge_format(format);
|
||||
return ((qpGeomMunger *)this)->do_munge_format(format, animation);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -123,6 +129,22 @@ munge_data(const qpGeomVertexData *data) const {
|
|||
return ((qpGeomMunger *)this)->munge_data_impl(data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomMunger::operator new
|
||||
// Access: Public
|
||||
// Description: This implementation of operator new isn't really
|
||||
// supposed to be called, but it's provided in case
|
||||
// someone screws up and doesn't define a more
|
||||
// appropriate operator new (that passes up a valid
|
||||
// _deleted_chain) for a derived class. Having this
|
||||
// operator new that passes NULL for _deleted_chain will
|
||||
// at least allow us to detect the error.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *qpGeomMunger::
|
||||
operator new(size_t size) {
|
||||
return do_operator_new(size, NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomMunger::operator delete
|
||||
// Access: Public
|
||||
|
|
@ -133,7 +155,14 @@ munge_data(const qpGeomVertexData *data) const {
|
|||
INLINE void qpGeomMunger::
|
||||
operator delete(void *ptr) {
|
||||
qpGeomMunger *obj = (qpGeomMunger *)ptr;
|
||||
nassertv(obj->_deleted_chain != (qpGeomMunger **)NULL);
|
||||
|
||||
#ifndef NDEBUG
|
||||
nassertd(obj->_deleted_chain != (qpGeomMunger **)NULL) {
|
||||
delete obj;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
nassertv(obj->_next == (qpGeomMunger *)NULL);
|
||||
obj->_next = (*obj->_deleted_chain);
|
||||
(*obj->_deleted_chain) = obj;
|
||||
|
|
@ -153,15 +182,24 @@ operator delete(void *ptr) {
|
|||
// there when it is deleted.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *qpGeomMunger::
|
||||
do_operator_new(size_t size, qpGeomMunger *&deleted_chain) {
|
||||
do_operator_new(size_t size, qpGeomMunger **deleted_chain) {
|
||||
qpGeomMunger *obj;
|
||||
if (deleted_chain != (qpGeomMunger *)NULL) {
|
||||
obj = deleted_chain;
|
||||
deleted_chain = deleted_chain->_next;
|
||||
|
||||
#ifndef NDEBUG
|
||||
nassertd(deleted_chain != (qpGeomMunger **)NULL) {
|
||||
obj = (qpGeomMunger *)::operator new(size);
|
||||
obj->_deleted_chain = NULL;
|
||||
return obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((*deleted_chain) != (qpGeomMunger *)NULL) {
|
||||
obj = (*deleted_chain);
|
||||
(*deleted_chain) = (*deleted_chain)->_next;
|
||||
} else {
|
||||
obj = (qpGeomMunger *)::operator new(size);
|
||||
}
|
||||
obj->_deleted_chain = &deleted_chain;
|
||||
obj->_deleted_chain = deleted_chain;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,36 +76,7 @@ qpGeomMunger::
|
|||
if (is_registered()) {
|
||||
get_registry()->unregister_munger(this);
|
||||
}
|
||||
nassertv(_formats.empty());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomMunger::remove_format
|
||||
// Access: Public
|
||||
// Description: Removes a prepared GeomVertexFormat from the cache.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomMunger::
|
||||
remove_format(const qpGeomVertexFormat *format) {
|
||||
// If this assertion is triggered, maybe we accidentally deleted a
|
||||
// GeomVertexFormat while we were in the process of unregistering,
|
||||
// causing a recursive re-entry.
|
||||
nassertv(_is_registered);
|
||||
|
||||
Formats::iterator fi;
|
||||
fi = _formats.find(format);
|
||||
nassertv(fi != _formats.end());
|
||||
|
||||
// We can't save this in a CPT, because it might be the same pointer
|
||||
// as format, which might be in the middle of its destructor.
|
||||
// Putting it in a CPT would bump up its reference count again, and
|
||||
// end up calling the destructor twice.
|
||||
const qpGeomVertexFormat *derived_format = (*fi).second;
|
||||
_formats.erase(fi);
|
||||
|
||||
// We need to unref the derived format, if we reffed it earlier.
|
||||
if (derived_format != format) {
|
||||
unref_delete(derived_format);
|
||||
}
|
||||
nassertv(_formats_by_animation.empty());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -128,43 +99,29 @@ remove_data(const qpGeomVertexData *data) {
|
|||
// exists just to cast away the const pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(qpGeomVertexFormat) qpGeomMunger::
|
||||
do_munge_format(const qpGeomVertexFormat *format) {
|
||||
do_munge_format(const qpGeomVertexFormat *format,
|
||||
const qpGeomVertexAnimationSpec &animation) {
|
||||
nassertr(_is_registered, NULL);
|
||||
nassertr(format->is_registered(), NULL);
|
||||
|
||||
Formats &formats = _formats_by_animation[animation];
|
||||
|
||||
Formats::iterator fi;
|
||||
fi = _formats.find(format);
|
||||
if (fi != _formats.end()) {
|
||||
fi = formats.find(format);
|
||||
if (fi != formats.end()) {
|
||||
// This format was previously munged, so the answer will be the
|
||||
// same.
|
||||
return (*fi).second;
|
||||
}
|
||||
|
||||
// We have to munge this format for the first time.
|
||||
CPT(qpGeomVertexFormat) derived_format = munge_format_impl(format);
|
||||
CPT(qpGeomVertexFormat) derived_format = munge_format_impl(format, animation);
|
||||
nassertr(derived_format->is_registered(), NULL);
|
||||
|
||||
// Store the answer in the map, so we can quickly get it next time.
|
||||
bool inserted = _formats.insert(Formats::value_type(format, derived_format)).second;
|
||||
bool inserted = formats.insert(Formats::value_type(format, derived_format)).second;
|
||||
nassertr(inserted, NULL);
|
||||
|
||||
// Tell the source format that we have its pointer.
|
||||
{
|
||||
qpGeomVertexFormat *f = (qpGeomVertexFormat *)format;
|
||||
MutexHolder holder(f->_cache_lock);
|
||||
nassertr(f->is_registered(), NULL);
|
||||
inserted = f->_mungers.insert(this).second;
|
||||
nassertr(inserted, NULL);
|
||||
}
|
||||
|
||||
// We also want to keep a reference count on the derived format, but
|
||||
// only if it is actually a different pointer from the original
|
||||
// format--otherwise it would cause a self-referential reference
|
||||
// count.
|
||||
if (derived_format != format) {
|
||||
derived_format->ref();
|
||||
}
|
||||
|
||||
return derived_format;
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +132,7 @@ do_munge_format(const qpGeomVertexFormat *format) {
|
|||
// necessary to the appropriate format for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(qpGeomVertexFormat) qpGeomMunger::
|
||||
munge_format_impl(const qpGeomVertexFormat *orig) {
|
||||
munge_format_impl(const qpGeomVertexFormat *orig, const qpGeomVertexAnimationSpec &) {
|
||||
return orig;
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +147,8 @@ munge_data_impl(const qpGeomVertexData *data) {
|
|||
nassertr(_is_registered, NULL);
|
||||
|
||||
CPT(qpGeomVertexFormat) orig_format = data->get_format();
|
||||
CPT(qpGeomVertexFormat) new_format = munge_format(orig_format);
|
||||
CPT(qpGeomVertexFormat) new_format =
|
||||
munge_format(orig_format, orig_format->get_animation());
|
||||
|
||||
if (new_format == orig_format) {
|
||||
// Trivial case.
|
||||
|
|
@ -208,7 +166,7 @@ munge_data_impl(const qpGeomVertexData *data) {
|
|||
void qpGeomMunger::
|
||||
munge_geom_impl(CPT(qpGeom) &, CPT(qpGeomVertexData) &) {
|
||||
// The default implementation does nothing (the work has already
|
||||
// been done in munge_format_impl).
|
||||
// been done in munge_format_impl() and munge_data_impl()).
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -261,7 +219,7 @@ do_register() {
|
|||
<< "GeomMunger::do_register(): " << (void *)this << "\n";
|
||||
}
|
||||
nassertv(!_is_registered);
|
||||
nassertv(_formats.empty());
|
||||
nassertv(_formats_by_animation.empty());
|
||||
|
||||
// Tell the cache manager to hang on to this new GeomMunger, so we
|
||||
// don't waste our time re-registering the same GeomMunger over and
|
||||
|
|
@ -288,22 +246,7 @@ do_unregister() {
|
|||
_is_registered = false;
|
||||
|
||||
// Unregistering means we should blow away the cache.
|
||||
Formats::iterator fi;
|
||||
for (fi = _formats.begin(); fi != _formats.end(); ++fi) {
|
||||
qpGeomVertexFormat *format = (qpGeomVertexFormat *)(*fi).first;
|
||||
CPT(qpGeomVertexFormat) derived_format = (*fi).second;
|
||||
|
||||
{
|
||||
MutexHolder holder(format->_cache_lock);
|
||||
size_t num_erased = format->_mungers.erase(this);
|
||||
nassertv(num_erased == 1);
|
||||
}
|
||||
|
||||
if (derived_format != format) {
|
||||
derived_format->unref();
|
||||
}
|
||||
}
|
||||
_formats.clear();
|
||||
_formats_by_animation.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "qpgeomVertexAnimationSpec.h"
|
||||
#include "qpgeomVertexFormat.h"
|
||||
#include "qpgeomVertexData.h"
|
||||
#include "qpgeomCacheEntry.h"
|
||||
|
|
@ -67,8 +68,8 @@ public:
|
|||
INLINE bool is_registered() const;
|
||||
INLINE static CPT(qpGeomMunger) register_munger(qpGeomMunger *munger);
|
||||
|
||||
INLINE CPT(qpGeomVertexFormat) munge_format(const qpGeomVertexFormat *format) const;
|
||||
void remove_format(const qpGeomVertexFormat *format);
|
||||
INLINE CPT(qpGeomVertexFormat) munge_format(const qpGeomVertexFormat *format,
|
||||
const qpGeomVertexAnimationSpec &animation) const;
|
||||
|
||||
INLINE CPT(qpGeomVertexData) munge_data(const qpGeomVertexData *data) const;
|
||||
void remove_data(const qpGeomVertexData *data);
|
||||
|
|
@ -80,9 +81,11 @@ public:
|
|||
INLINE int geom_compare_to(const qpGeomMunger &other) const;
|
||||
|
||||
protected:
|
||||
CPT(qpGeomVertexFormat) do_munge_format(const qpGeomVertexFormat *format);
|
||||
CPT(qpGeomVertexFormat) do_munge_format(const qpGeomVertexFormat *format,
|
||||
const qpGeomVertexAnimationSpec &animation);
|
||||
|
||||
virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig);
|
||||
virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig,
|
||||
const qpGeomVertexAnimationSpec &animation);
|
||||
virtual CPT(qpGeomVertexData) munge_data_impl(const qpGeomVertexData *data);
|
||||
virtual void munge_geom_impl(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &data);
|
||||
virtual int compare_to_impl(const qpGeomMunger *other) const;
|
||||
|
|
@ -93,10 +96,11 @@ public:
|
|||
// and delete using their own deleted_chain. This is the base class
|
||||
// implementation, which requires a pointer to deleted_chain be
|
||||
// stored on each instance.
|
||||
INLINE void *operator new(size_t size);
|
||||
INLINE void operator delete(void *ptr);
|
||||
|
||||
protected:
|
||||
INLINE static void *do_operator_new(size_t size, qpGeomMunger *&_deleted_chain);
|
||||
INLINE static void *do_operator_new(size_t size, qpGeomMunger **_deleted_chain);
|
||||
|
||||
private:
|
||||
qpGeomMunger **_deleted_chain;
|
||||
|
|
@ -120,8 +124,9 @@ private:
|
|||
PT(qpGeomMunger) _munger;
|
||||
};
|
||||
|
||||
typedef pmap<const qpGeomVertexFormat *, const qpGeomVertexFormat *> Formats;
|
||||
Formats _formats;
|
||||
typedef pmap<CPT(qpGeomVertexFormat), CPT(qpGeomVertexFormat) > Formats;
|
||||
typedef pmap<qpGeomVertexAnimationSpec, Formats> FormatsByAnimation;
|
||||
FormatsByAnimation _formats_by_animation;
|
||||
|
||||
bool _is_registered;
|
||||
typedef pset<qpGeomMunger *, IndirectCompareTo<qpGeomMunger> > Mungers;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,198 @@
|
|||
// Filename: qpgeomVertexAnimationSpec.I
|
||||
// Created by: drose (29Mar05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpGeomVertexAnimationSpec::
|
||||
qpGeomVertexAnimationSpec() :
|
||||
_animation_type(AT_none),
|
||||
_num_transforms(0),
|
||||
_indexed_transforms(0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::Copy Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpGeomVertexAnimationSpec::
|
||||
qpGeomVertexAnimationSpec(const qpGeomVertexAnimationSpec &other) :
|
||||
_animation_type(other._animation_type),
|
||||
_num_transforms(other._num_transforms),
|
||||
_indexed_transforms(other._indexed_transforms)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::Copy Assignment Operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexAnimationSpec::
|
||||
operator = (const qpGeomVertexAnimationSpec &other) {
|
||||
_animation_type = other._animation_type;
|
||||
_num_transforms = other._num_transforms;
|
||||
_indexed_transforms = other._indexed_transforms;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::get_animation_type
|
||||
// Access: Published
|
||||
// Description: Returns the type of animation represented by this
|
||||
// spec.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpGeomVertexAnimationSpec::AnimationType qpGeomVertexAnimationSpec::
|
||||
get_animation_type() const {
|
||||
return _animation_type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::get_num_transforms
|
||||
// Access: Published
|
||||
// Description: This is only meaningful for animation_type
|
||||
// AT_hardware. It specifies the maximum number of
|
||||
// transforms that might be simultaneously applied to
|
||||
// any one vertex by the data in this format.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int qpGeomVertexAnimationSpec::
|
||||
get_num_transforms() const {
|
||||
return _num_transforms;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::get_indexed_transforms
|
||||
// Access: Published
|
||||
// Description: This is only meaningful for animation_type
|
||||
// AT_hardware. If true, it indicates that the format
|
||||
// uses indexed animation palettes. It is false if each
|
||||
// vertex will reference the first _num_transforms
|
||||
// palette entries only.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpGeomVertexAnimationSpec::
|
||||
get_indexed_transforms() const {
|
||||
return _indexed_transforms;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::set_none
|
||||
// Access: Published
|
||||
// Description: Specifies that no vertex animation is represented by
|
||||
// this spec.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexAnimationSpec::
|
||||
set_none() {
|
||||
_animation_type = AT_none;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::set_panda
|
||||
// Access: Published
|
||||
// Description: Specifies that vertex animation is to be performed by
|
||||
// Panda. This is the most general setting and can
|
||||
// handle any kind of vertex animation represented.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexAnimationSpec::
|
||||
set_panda() {
|
||||
_animation_type = AT_panda;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::set_hardware
|
||||
// Access: Published
|
||||
// Description: Specifies that vertex animation is to be performed by
|
||||
// the graphics hardware (or at least by the graphics
|
||||
// backend API, which is actually still free to animate
|
||||
// the vertices on the CPU).
|
||||
//
|
||||
// This is only legal if the graphics hardware can
|
||||
// support the specified limits on number of transforms
|
||||
// and/or indexed transforms. Also, no current graphics
|
||||
// API's support morphing.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexAnimationSpec::
|
||||
set_hardware(int num_transforms, bool indexed_transforms) {
|
||||
_animation_type = AT_hardware;
|
||||
_num_transforms = num_transforms;
|
||||
_indexed_transforms = indexed_transforms;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::operator <
|
||||
// Access: Public
|
||||
// Description: Provides an arbitrary ordering between different
|
||||
// animation specs.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpGeomVertexAnimationSpec::
|
||||
operator < (const qpGeomVertexAnimationSpec &other) const {
|
||||
return (compare_to(other) < 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::operator ==
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpGeomVertexAnimationSpec::
|
||||
operator == (const qpGeomVertexAnimationSpec &other) const {
|
||||
return (compare_to(other) == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::operator !=
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpGeomVertexAnimationSpec::
|
||||
operator != (const qpGeomVertexAnimationSpec &other) const {
|
||||
return (compare_to(other) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::compare_to
|
||||
// Access: Public
|
||||
// Description: Provides an arbitrary ordering between different
|
||||
// animation specs.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int qpGeomVertexAnimationSpec::
|
||||
compare_to(const qpGeomVertexAnimationSpec &other) const {
|
||||
if (_animation_type != other._animation_type) {
|
||||
return (int)_animation_type - (int)other._animation_type;
|
||||
}
|
||||
|
||||
if (_animation_type == AT_hardware) {
|
||||
if (_num_transforms != other._num_transforms) {
|
||||
return _num_transforms - other._num_transforms;
|
||||
}
|
||||
if (_indexed_transforms != other._indexed_transforms) {
|
||||
return (int)_indexed_transforms - (int)other._indexed_transforms;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const qpGeomVertexAnimationSpec &animation) {
|
||||
animation.output(out);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Filename: qpgeomVertexAnimationSpec.cxx
|
||||
// Created by: drose (29Mar05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "qpgeomVertexAnimationSpec.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexAnimationSpec::output
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexAnimationSpec::
|
||||
output(ostream &out) const {
|
||||
switch (_animation_type) {
|
||||
case AT_none:
|
||||
out << "none";
|
||||
break;
|
||||
|
||||
case AT_panda:
|
||||
out << "panda";
|
||||
break;
|
||||
|
||||
case AT_hardware:
|
||||
out << "hardware(" << _num_transforms << ", "
|
||||
<< _indexed_transforms << ")";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// Filename: qpgeomVertexAnimationSpec.h
|
||||
// Created by: drose (29Mar05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef qpGEOMVERTEXANIMATIONSPEC_H
|
||||
#define qpGEOMVERTEXANIMATIONSPEC_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : qpGeomVertexAnimationSpec
|
||||
// Description : This object describes how the vertex animation, if
|
||||
// any, represented in a GeomVertexData is encoded.
|
||||
//
|
||||
// Vertex animation includes soft-skinned skeleton
|
||||
// animation and morphs (blend shapes), and might be
|
||||
// performed on the CPU by Panda, or passed down to the
|
||||
// graphics backed to be performed on the hardware
|
||||
// (depending on the hardware's advertised
|
||||
// capabilities).
|
||||
//
|
||||
// Changing this setting doesn't by itself change the
|
||||
// way the animation is actually performed; this just
|
||||
// specifies how the vertices are set up to be animated.
|
||||
//
|
||||
// This is part of the experimental Geom rewrite.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA qpGeomVertexAnimationSpec {
|
||||
PUBLISHED:
|
||||
INLINE qpGeomVertexAnimationSpec();
|
||||
INLINE qpGeomVertexAnimationSpec(const qpGeomVertexAnimationSpec &other);
|
||||
INLINE void operator = (const qpGeomVertexAnimationSpec &other);
|
||||
|
||||
enum AnimationType {
|
||||
AT_none, // No vertex animation.
|
||||
AT_panda, // Vertex animation calculated on the CPU by Panda.
|
||||
AT_hardware, // Hardware-accelerated animation on the graphics card.
|
||||
};
|
||||
|
||||
INLINE AnimationType get_animation_type() const;
|
||||
|
||||
INLINE int get_num_transforms() const;
|
||||
INLINE bool get_indexed_transforms() const;
|
||||
|
||||
INLINE void set_none();
|
||||
INLINE void set_panda();
|
||||
INLINE void set_hardware(int num_transforms, bool indexed_transforms);
|
||||
|
||||
void output(ostream &out) const;
|
||||
|
||||
public:
|
||||
INLINE bool operator < (const qpGeomVertexAnimationSpec &other) const;
|
||||
INLINE bool operator == (const qpGeomVertexAnimationSpec &other) const;
|
||||
INLINE bool operator != (const qpGeomVertexAnimationSpec &other) const;
|
||||
INLINE int compare_to(const qpGeomVertexAnimationSpec &other) const;
|
||||
|
||||
private:
|
||||
AnimationType _animation_type;
|
||||
|
||||
int _num_transforms;
|
||||
bool _indexed_transforms;
|
||||
};
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const qpGeomVertexAnimationSpec &animation);
|
||||
|
||||
#include "qpgeomVertexAnimationSpec.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -118,6 +118,40 @@ get_array(int i) const {
|
|||
return cdata->_arrays[i];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::get_transform_palette
|
||||
// Access: Published
|
||||
// Description: Returns a const pointer to the TransformPalette
|
||||
// assigned to this data. Vertices within the table
|
||||
// will index into this palette to indicate their
|
||||
// dynamic skinning information; this table is used when
|
||||
// the vertex animation is to be performed by the
|
||||
// graphics hardware (but also see
|
||||
// get_transform_blend_palette()).
|
||||
//
|
||||
// This will return NULL if the vertex data does not
|
||||
// have a TransformPalette assigned (which implies the
|
||||
// vertices will not be animated by the graphics
|
||||
// hardware).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const TransformPalette *qpGeomVertexData::
|
||||
get_transform_palette() const {
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_transform_palette;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::clear_transform_palette
|
||||
// Access: Published
|
||||
// Description: Sets the TransformPalette pointer to NULL,
|
||||
// removing the palette from the vertex data. This
|
||||
// disables hardware-driven vertex animation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexData::
|
||||
clear_transform_palette() {
|
||||
set_transform_palette(NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::get_transform_blend_palette
|
||||
// Access: Published
|
||||
|
|
@ -288,6 +322,24 @@ unpack_8888_d(PN_uint32 data) {
|
|||
return data & 0xff;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::add_transform
|
||||
// Access: Private, Static
|
||||
// Description: Adds the indicated transform to the palette, if it is
|
||||
// not already there, and returns its index number.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int qpGeomVertexData::
|
||||
add_transform(TransformPalette *palette, const VertexTransform *transform,
|
||||
TransformMap &already_added) {
|
||||
pair<TransformMap::iterator, bool> result = already_added.insert(TransformMap::value_type(transform, palette->get_num_transforms()));
|
||||
|
||||
if (result.second) {
|
||||
palette->add_transform(transform);
|
||||
}
|
||||
|
||||
return (*(result.first)).second;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::CData::Constructor
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -201,6 +201,47 @@ set_array(int i, const qpGeomVertexArrayData *array) {
|
|||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::modify_transform_palette
|
||||
// Access: Published
|
||||
// Description: Returns a modifiable pointer to the current
|
||||
// TransformPalette on this vertex data, if any, or
|
||||
// NULL if there is not a TransformPalette. See
|
||||
// get_transform_palette().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TransformPalette *qpGeomVertexData::
|
||||
modify_transform_palette() {
|
||||
// Perform copy-on-write: if the reference count on the palette is
|
||||
// greater than 1, assume some other GeomVertexData has the same
|
||||
// pointer, so make a copy of it first.
|
||||
CDWriter cdata(_cycler);
|
||||
|
||||
if (cdata->_transform_palette->get_ref_count() > 1) {
|
||||
cdata->_transform_palette = new TransformPalette(*cdata->_transform_palette);
|
||||
}
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
|
||||
return cdata->_transform_palette;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::set_transform_palette
|
||||
// Access: Published
|
||||
// Description: Replaces the TransformPalette on this vertex
|
||||
// data with the indicated palette. The length of this
|
||||
// palette should be consistent with the maximum palette
|
||||
// index assigned to the vertices under the
|
||||
// "transform_index" name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexData::
|
||||
set_transform_palette(const TransformPalette *palette) {
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_transform_palette = (TransformPalette *)palette;
|
||||
cdata->_modified = qpGeom::get_next_modified();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexData::modify_transform_blend_palette
|
||||
// Access: Published
|
||||
|
|
@ -442,6 +483,65 @@ copy_from(const qpGeomVertexData &source, bool keep_data_objects) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also convert the animation tables as necessary.
|
||||
const qpGeomVertexAnimationSpec &source_animation = source_format->get_animation();
|
||||
const qpGeomVertexAnimationSpec &dest_animation = dest_format->get_animation();
|
||||
if (source_animation != dest_animation) {
|
||||
if (dest_animation.get_animation_type() == qpGeomVertexAnimationSpec::AT_hardware) {
|
||||
// Convert Panda-style animation tables to hardware-style
|
||||
// animation tables.
|
||||
CPT(TransformBlendPalette) blend_palette = source.get_transform_blend_palette();
|
||||
if (blend_palette != (TransformBlendPalette *)NULL) {
|
||||
PT(TransformPalette) transform_palette = new TransformPalette;
|
||||
TransformMap already_added;
|
||||
|
||||
if (dest_animation.get_indexed_transforms()) {
|
||||
// Build an indexed transform array. This is easier; this
|
||||
// means we can put the blends in any order.
|
||||
qpGeomVertexWriter weight(this, InternalName::get_transform_weight());
|
||||
qpGeomVertexWriter index(this, InternalName::get_transform_index());
|
||||
qpGeomVertexReader from(&source, InternalName::get_transform_blend());
|
||||
|
||||
while (!from.is_at_end()) {
|
||||
const TransformBlend &blend = blend_palette->get_blend(from.get_data1i());
|
||||
LVecBase4f weights = LVecBase4f::zero();
|
||||
int indices[4] = {0, 0, 0, 0};
|
||||
nassertv(blend.get_num_transforms() <= 4);
|
||||
|
||||
for (int i = 0; i < blend.get_num_transforms(); i++) {
|
||||
weights[i] = blend.get_weight(i);
|
||||
indices[i] = add_transform(transform_palette, blend.get_transform(i),
|
||||
already_added);
|
||||
}
|
||||
weight.set_data4f(weights);
|
||||
index.set_data4i(indices[3], indices[2], indices[1], indices[0]);
|
||||
}
|
||||
} else {
|
||||
// Build a nonindexed transform array. This means we have to
|
||||
// use the same n transforms, in the same order, for each vertex.
|
||||
qpGeomVertexWriter weight(this, InternalName::get_transform_weight());
|
||||
qpGeomVertexReader from(&source, InternalName::get_transform_blend());
|
||||
|
||||
while (!from.is_at_end()) {
|
||||
const TransformBlend &blend = blend_palette->get_blend(from.get_data1i());
|
||||
LVecBase4f weights = LVecBase4f::zero();
|
||||
|
||||
for (int i = 0; i < blend.get_num_transforms(); i++) {
|
||||
int index = add_transform(transform_palette, blend.get_transform(i),
|
||||
already_added);
|
||||
nassertv(index <= 4);
|
||||
weights[index] = blend.get_weight(i);
|
||||
}
|
||||
weight.set_data4f(weights);
|
||||
}
|
||||
}
|
||||
|
||||
clear_transform_blend_palette();
|
||||
set_transform_palette(transform_palette);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -725,6 +825,11 @@ CPT(qpGeomVertexData) qpGeomVertexData::
|
|||
do_animate_vertices(bool from_app) const {
|
||||
CDReader cdata(_cycler);
|
||||
|
||||
if (_format->get_animation().get_animation_type() !=
|
||||
qpGeomVertexAnimationSpec::AT_panda) {
|
||||
return this;
|
||||
}
|
||||
|
||||
UpdateSeq modified;
|
||||
if (cdata->_transform_blend_palette != (TransformBlendPalette *)NULL) {
|
||||
if (cdata->_slider_table != (SliderTable *)NULL) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "qpgeomVertexDataType.h"
|
||||
#include "qpgeomVertexArrayData.h"
|
||||
#include "qpgeomUsageHint.h"
|
||||
#include "transformPalette.h"
|
||||
#include "transformBlendPalette.h"
|
||||
#include "sliderTable.h"
|
||||
#include "internalName.h"
|
||||
|
|
@ -87,6 +88,11 @@ PUBLISHED:
|
|||
qpGeomVertexArrayData *modify_array(int i);
|
||||
void set_array(int i, const qpGeomVertexArrayData *array);
|
||||
|
||||
INLINE const TransformPalette *get_transform_palette() const;
|
||||
TransformPalette *modify_transform_palette();
|
||||
void set_transform_palette(const TransformPalette *palette);
|
||||
INLINE void clear_transform_palette();
|
||||
|
||||
INLINE const TransformBlendPalette *get_transform_blend_palette() const;
|
||||
TransformBlendPalette *modify_transform_blend_palette();
|
||||
void set_transform_blend_palette(const TransformBlendPalette *palette);
|
||||
|
|
@ -154,6 +160,11 @@ private:
|
|||
uint8_rgba_to_packed_argb(unsigned char *to, int to_stride,
|
||||
const unsigned char *from, int from_stride,
|
||||
int num_records);
|
||||
|
||||
typedef pmap<const VertexTransform *, int> TransformMap;
|
||||
INLINE static int
|
||||
add_transform(TransformPalette *palette, const VertexTransform *transform,
|
||||
TransformMap &already_added);
|
||||
|
||||
private:
|
||||
string _name;
|
||||
|
|
@ -173,6 +184,7 @@ private:
|
|||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
Arrays _arrays;
|
||||
PT(TransformPalette) _transform_palette;
|
||||
PT(TransformBlendPalette) _transform_blend_palette;
|
||||
PT(SliderTable) _slider_table;
|
||||
PT(qpGeomVertexData) _animated_vertices;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,34 @@ register_format(qpGeomVertexArrayFormat *format) {
|
|||
return get_registry()->register_format(format);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexFormat::get_animation
|
||||
// Access: Published
|
||||
// Description: Returns the GeomVertexAnimationSpec that indicates
|
||||
// how this format's vertices are set up for animation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const qpGeomVertexAnimationSpec &qpGeomVertexFormat::
|
||||
get_animation() const {
|
||||
return _animation;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexFormat::set_animation
|
||||
// Access: Published
|
||||
// Description: Resets the GeomVertexAnimationSpec that indicates
|
||||
// how this format's vertices are set up for animation.
|
||||
// You should also, of course, change the columns in the
|
||||
// tables accordingly.
|
||||
//
|
||||
// This may not be called once the format has been
|
||||
// registered.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexFormat::
|
||||
set_animation(const qpGeomVertexAnimationSpec &animation) {
|
||||
nassertv(!_is_registered);
|
||||
_animation = animation;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexFormat::get_num_arrays
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ qpGeomVertexFormat(qpGeomVertexArrayFormat *array_format) :
|
|||
qpGeomVertexFormat::
|
||||
qpGeomVertexFormat(const qpGeomVertexFormat ©) :
|
||||
_is_registered(false),
|
||||
_animation(copy._animation),
|
||||
_arrays(copy._arrays)
|
||||
{
|
||||
}
|
||||
|
|
@ -71,6 +72,7 @@ void qpGeomVertexFormat::
|
|||
operator = (const qpGeomVertexFormat ©) {
|
||||
nassertv(!_is_registered);
|
||||
|
||||
_animation = copy._animation;
|
||||
_arrays = copy._arrays;
|
||||
}
|
||||
|
||||
|
|
@ -84,8 +86,6 @@ qpGeomVertexFormat::
|
|||
if (is_registered()) {
|
||||
get_registry()->unregister_format(this);
|
||||
}
|
||||
|
||||
nassertv(_mungers.empty());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -379,6 +379,10 @@ output(ostream &out) const {
|
|||
++ai;
|
||||
}
|
||||
}
|
||||
|
||||
if (_animation.get_animation_type() != qpGeomVertexAnimationSpec::AT_none) {
|
||||
out << ", anim " << _animation;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -446,6 +450,11 @@ get_array_info(const InternalName *name, int &array_index,
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int qpGeomVertexFormat::
|
||||
compare_to(const qpGeomVertexFormat &other) const {
|
||||
int compare = _animation.compare_to(other._animation);
|
||||
if (compare != 0) {
|
||||
return compare;
|
||||
}
|
||||
|
||||
if (_arrays.size() != other._arrays.size()) {
|
||||
return (int)_arrays.size() - (int)other._arrays.size();
|
||||
}
|
||||
|
|
@ -481,7 +490,6 @@ void qpGeomVertexFormat::
|
|||
do_register() {
|
||||
nassertv(!_is_registered);
|
||||
nassertv(_data_types_by_name.empty());
|
||||
nassertv(_mungers.empty());
|
||||
|
||||
for (int array = 0; array < (int)_arrays.size(); ++array) {
|
||||
const qpGeomVertexArrayFormat *array_format = _arrays[array];
|
||||
|
|
@ -556,13 +564,6 @@ do_unregister() {
|
|||
_is_registered = false;
|
||||
|
||||
_data_types_by_name.clear();
|
||||
|
||||
MutexHolder holder(_cache_lock);
|
||||
Mungers::iterator mi;
|
||||
for (mi = _mungers.begin(); mi != _mungers.end(); ++mi) {
|
||||
(*mi)->remove_format(this);
|
||||
}
|
||||
_mungers.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "qpgeomVertexAnimationSpec.h"
|
||||
#include "qpgeomVertexArrayFormat.h"
|
||||
#include "internalName.h"
|
||||
#include "luse.h"
|
||||
|
|
@ -66,6 +67,9 @@ PUBLISHED:
|
|||
INLINE static CPT(qpGeomVertexFormat) register_format(qpGeomVertexFormat *format);
|
||||
INLINE static CPT(qpGeomVertexFormat) register_format(qpGeomVertexArrayFormat *format);
|
||||
|
||||
INLINE const qpGeomVertexAnimationSpec &get_animation() const;
|
||||
INLINE void set_animation(const qpGeomVertexAnimationSpec &animation);
|
||||
|
||||
INLINE int get_num_arrays() const;
|
||||
INLINE const qpGeomVertexArrayFormat *get_array(int array) const;
|
||||
qpGeomVertexArrayFormat *modify_array(int array);
|
||||
|
|
@ -140,6 +144,8 @@ private:
|
|||
|
||||
bool _is_registered;
|
||||
|
||||
qpGeomVertexAnimationSpec _animation;
|
||||
|
||||
typedef pvector< PT(qpGeomVertexArrayFormat) > Arrays;
|
||||
Arrays _arrays;
|
||||
|
||||
|
|
@ -161,12 +167,6 @@ private:
|
|||
typedef pvector<MorphRecord> Morphs;
|
||||
Morphs _morphs;
|
||||
|
||||
// This set keeps track of things that need to be told when we
|
||||
// destruct, and it is protected by the mutex.
|
||||
Mutex _cache_lock;
|
||||
typedef pset<qpGeomMunger *> Mungers;
|
||||
Mungers _mungers;
|
||||
|
||||
// This is the global registry of all currently-in-use formats.
|
||||
typedef pset<qpGeomVertexFormat *, IndirectCompareTo<qpGeomVertexFormat> > Formats;
|
||||
class EXPCL_PANDA Registry {
|
||||
|
|
|
|||
|
|
@ -320,6 +320,45 @@ get_data1i() {
|
|||
return _reader->get_data1i(inc_pointer());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexReader::get_data2i
|
||||
// Access: Published
|
||||
// Description: Returns the data associated with the read vertex,
|
||||
// expressed as a 2-component value, and advances the
|
||||
// read vertex.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const int *qpGeomVertexReader::
|
||||
get_data2i() {
|
||||
nassertr(_data_type != (qpGeomVertexDataType *)NULL, 0);
|
||||
return _reader->get_data2i(inc_pointer());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexReader::get_data3i
|
||||
// Access: Published
|
||||
// Description: Returns the data associated with the read vertex,
|
||||
// expressed as a 3-component value, and advances the
|
||||
// read vertex.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const int *qpGeomVertexReader::
|
||||
get_data3i() {
|
||||
nassertr(_data_type != (qpGeomVertexDataType *)NULL, 0);
|
||||
return _reader->get_data3i(inc_pointer());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexReader::get_data4i
|
||||
// Access: Published
|
||||
// Description: Returns the data associated with the read vertex,
|
||||
// expressed as a 4-component value, and advances the
|
||||
// read vertex.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const int *qpGeomVertexReader::
|
||||
get_data4i() {
|
||||
nassertr(_data_type != (qpGeomVertexDataType *)NULL, 0);
|
||||
return _reader->get_data4i(inc_pointer());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexReader::set_pointer
|
||||
// Access: Private
|
||||
|
|
|
|||
|
|
@ -423,6 +423,215 @@ get_data1i(const unsigned char *pointer) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexReader::Reader::get_data2i
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const int *qpGeomVertexReader::Reader::
|
||||
get_data2i(const unsigned char *pointer) {
|
||||
switch (_data_type->get_num_values()) {
|
||||
case 1:
|
||||
_i[0] = get_data1i(pointer);
|
||||
_i[1] = 0;
|
||||
return _i;
|
||||
|
||||
default:
|
||||
switch (_data_type->get_numeric_type()) {
|
||||
case qpGeomVertexDataType::NT_uint8:
|
||||
_i[0] = pointer[0];
|
||||
_i[1] = pointer[1];
|
||||
return _i;
|
||||
|
||||
case qpGeomVertexDataType::NT_uint16:
|
||||
{
|
||||
const PN_uint16 *pi = (const PN_uint16 *)pointer;
|
||||
_i[0] = pi[0];
|
||||
_i[1] = pi[1];
|
||||
}
|
||||
return _i;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
{
|
||||
PN_uint32 dword = *(const PN_uint32 *)pointer;
|
||||
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
|
||||
_i[0] = qpGeomVertexData::unpack_8888_b(dword);
|
||||
_i[1] = qpGeomVertexData::unpack_8888_c(dword);
|
||||
} else {
|
||||
_i[0] = qpGeomVertexData::unpack_8888_a(dword);
|
||||
_i[1] = qpGeomVertexData::unpack_8888_b(dword);
|
||||
}
|
||||
}
|
||||
return _i;
|
||||
|
||||
case qpGeomVertexDataType::NT_float32:
|
||||
{
|
||||
const PN_float32 *pi = (const PN_float32 *)pointer;
|
||||
_i[0] = (int)pi[0];
|
||||
_i[1] = (int)pi[1];
|
||||
}
|
||||
return _i;
|
||||
}
|
||||
}
|
||||
|
||||
return _i;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexReader::Reader::get_data3i
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const int *qpGeomVertexReader::Reader::
|
||||
get_data3i(const unsigned char *pointer) {
|
||||
switch (_data_type->get_num_values()) {
|
||||
case 1:
|
||||
_i[0] = get_data1i(pointer);
|
||||
_i[1] = 0;
|
||||
_i[2] = 0;
|
||||
return _i;
|
||||
|
||||
case 2:
|
||||
{
|
||||
const int *i = get_data2i(pointer);
|
||||
_i[0] = i[0];
|
||||
_i[1] = i[1];
|
||||
_i[2] = 0;
|
||||
}
|
||||
return _i;
|
||||
|
||||
default:
|
||||
switch (_data_type->get_numeric_type()) {
|
||||
case qpGeomVertexDataType::NT_uint8:
|
||||
_i[0] = pointer[0];
|
||||
_i[1] = pointer[1];
|
||||
_i[2] = pointer[2];
|
||||
return _i;
|
||||
|
||||
case qpGeomVertexDataType::NT_uint16:
|
||||
{
|
||||
const PN_uint16 *pi = (const PN_uint16 *)pointer;
|
||||
_i[0] = pi[0];
|
||||
_i[1] = pi[1];
|
||||
_i[2] = pi[2];
|
||||
}
|
||||
return _i;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
{
|
||||
PN_uint32 dword = *(const PN_uint32 *)pointer;
|
||||
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
|
||||
_i[0] = qpGeomVertexData::unpack_8888_b(dword);
|
||||
_i[1] = qpGeomVertexData::unpack_8888_c(dword);
|
||||
_i[2] = qpGeomVertexData::unpack_8888_d(dword);
|
||||
} else {
|
||||
_i[0] = qpGeomVertexData::unpack_8888_a(dword);
|
||||
_i[1] = qpGeomVertexData::unpack_8888_b(dword);
|
||||
_i[2] = qpGeomVertexData::unpack_8888_c(dword);
|
||||
}
|
||||
}
|
||||
return _i;
|
||||
|
||||
case qpGeomVertexDataType::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];
|
||||
}
|
||||
return _i;
|
||||
}
|
||||
}
|
||||
|
||||
return _i;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexReader::Reader::get_data4i
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const int *qpGeomVertexReader::Reader::
|
||||
get_data4i(const unsigned char *pointer) {
|
||||
switch (_data_type->get_num_values()) {
|
||||
case 1:
|
||||
_i[0] = get_data1i(pointer);
|
||||
_i[1] = 0;
|
||||
_i[2] = 0;
|
||||
_i[3] = 0;
|
||||
return _i;
|
||||
|
||||
case 2:
|
||||
{
|
||||
const int *i = get_data2i(pointer);
|
||||
_i[0] = i[0];
|
||||
_i[1] = i[1];
|
||||
_i[2] = 0;
|
||||
_i[3] = 0;
|
||||
}
|
||||
return _i;
|
||||
|
||||
case 3:
|
||||
{
|
||||
const int *i = get_data3i(pointer);
|
||||
_i[0] = i[0];
|
||||
_i[1] = i[1];
|
||||
_i[2] = i[2];
|
||||
_i[3] = 0;
|
||||
}
|
||||
return _i;
|
||||
|
||||
default:
|
||||
switch (_data_type->get_numeric_type()) {
|
||||
case qpGeomVertexDataType::NT_uint8:
|
||||
_i[0] = pointer[0];
|
||||
_i[1] = pointer[1];
|
||||
_i[2] = pointer[2];
|
||||
_i[3] = pointer[3];
|
||||
return _i;
|
||||
|
||||
case qpGeomVertexDataType::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];
|
||||
}
|
||||
return _i;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
{
|
||||
PN_uint32 dword = *(const PN_uint32 *)pointer;
|
||||
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
|
||||
_i[0] = qpGeomVertexData::unpack_8888_b(dword);
|
||||
_i[1] = qpGeomVertexData::unpack_8888_c(dword);
|
||||
_i[2] = qpGeomVertexData::unpack_8888_d(dword);
|
||||
_i[3] = qpGeomVertexData::unpack_8888_a(dword);
|
||||
} else {
|
||||
_i[0] = qpGeomVertexData::unpack_8888_a(dword);
|
||||
_i[1] = qpGeomVertexData::unpack_8888_b(dword);
|
||||
_i[2] = qpGeomVertexData::unpack_8888_c(dword);
|
||||
_i[3] = qpGeomVertexData::unpack_8888_d(dword);
|
||||
}
|
||||
}
|
||||
return _i;
|
||||
|
||||
case qpGeomVertexDataType::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];
|
||||
}
|
||||
return _i;
|
||||
}
|
||||
}
|
||||
|
||||
return _i;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexReader::Reader_point::get_data1f
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -91,6 +91,9 @@ PUBLISHED:
|
|||
INLINE const LVecBase4f &get_data4f();
|
||||
|
||||
INLINE int get_data1i();
|
||||
INLINE const int *get_data2i();
|
||||
INLINE const int *get_data3i();
|
||||
INLINE const int *get_data4i();
|
||||
|
||||
private:
|
||||
class Reader;
|
||||
|
|
@ -124,6 +127,9 @@ private:
|
|||
virtual const LVecBase3f &get_data3f(const unsigned char *pointer);
|
||||
virtual const LVecBase4f &get_data4f(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);
|
||||
|
||||
INLINE float maybe_scale_color(unsigned int value);
|
||||
INLINE void maybe_scale_color(unsigned int a, unsigned int b);
|
||||
|
|
@ -136,6 +142,7 @@ private:
|
|||
LVecBase2f _v2;
|
||||
LVecBase3f _v3;
|
||||
LVecBase4f _v4;
|
||||
int _i[4];
|
||||
};
|
||||
|
||||
// This is a specialization on the generic Reader that handles
|
||||
|
|
|
|||
|
|
@ -372,6 +372,93 @@ set_data1i(int data) {
|
|||
_writer->set_data1i(inc_pointer(), data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::set_data2i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 2-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// It is an error for the write vertex to advance past
|
||||
// the end of data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
set_data2i(int a, int b) {
|
||||
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
|
||||
_writer->set_data2i(inc_pointer(), a, b);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::set_data2i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 2-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// It is an error for the write vertex to advance past
|
||||
// the end of data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
set_data2i(const int data[2]) {
|
||||
set_data2i(data[0], data[1]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::set_data3i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 3-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// It is an error for the write vertex to advance past
|
||||
// the end of data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
set_data3i(int a, int b, int c) {
|
||||
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
|
||||
_writer->set_data3i(inc_pointer(), a, b, c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::set_data3i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 3-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// It is an error for the write vertex to advance past
|
||||
// the end of data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
set_data3i(const int data[3]) {
|
||||
set_data3i(data[0], data[1], data[2]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::set_data4i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 4-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// It is an error for the write vertex to advance past
|
||||
// the end of data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
set_data4i(int a, int b, int c, int d) {
|
||||
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
|
||||
_writer->set_data4i(inc_pointer(), a, b, c, d);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::set_data4i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 4-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// It is an error for the write vertex to advance past
|
||||
// the end of data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
set_data4i(const int data[4]) {
|
||||
set_data4i(data[0], data[1], data[2], data[3]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::add_data1f
|
||||
// Access: Published
|
||||
|
|
@ -489,6 +576,93 @@ add_data1i(int data) {
|
|||
_writer->set_data1i(inc_add_pointer(), data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::add_data2i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 2-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// If the write vertex advances past the end of data,
|
||||
// implicitly adds a new vertex to the data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
add_data2i(int a, int b) {
|
||||
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
|
||||
_writer->set_data2i(inc_add_pointer(), a, b);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::add_data2i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 2-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// If the write vertex advances past the end of data,
|
||||
// implicitly adds a new vertex to the data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
add_data2i(const int data[2]) {
|
||||
add_data2i(data[0], data[1]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::add_data3i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 3-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// If the write vertex advances past the end of data,
|
||||
// implicitly adds a new vertex to the data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
add_data3i(int a, int b, int c) {
|
||||
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
|
||||
_writer->set_data3i(inc_add_pointer(), a, b, c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::add_data3i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 3-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// If the write vertex advances past the end of data,
|
||||
// implicitly adds a new vertex to the data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
add_data3i(const int data[3]) {
|
||||
add_data3i(data[0], data[1], data[2]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::add_data4i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 4-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// If the write vertex advances past the end of data,
|
||||
// implicitly adds a new vertex to the data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
add_data4i(int a, int b, int c, int d) {
|
||||
nassertv(_data_type != (qpGeomVertexDataType *)NULL);
|
||||
_writer->set_data4i(inc_add_pointer(), a, b, c, d);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::add_data4i
|
||||
// Access: Published
|
||||
// Description: Sets the write vertex to a particular 4-component
|
||||
// value, and advances the write vertex.
|
||||
//
|
||||
// If the write vertex advances past the end of data,
|
||||
// implicitly adds a new vertex to the data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpGeomVertexWriter::
|
||||
add_data4i(const int data[4]) {
|
||||
add_data4i(data[0], data[1], data[2], data[3]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::set_pointer
|
||||
// Access: Private
|
||||
|
|
|
|||
|
|
@ -185,14 +185,7 @@ set_data1f(unsigned char *pointer, float data) {
|
|||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
{
|
||||
maybe_scale_color(data);
|
||||
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
|
||||
*(PN_uint32 *)pointer = qpGeomVertexData::pack_8888(0, _a, 0, 0);
|
||||
} else {
|
||||
*(PN_uint32 *)pointer = qpGeomVertexData::pack_8888(_a, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
nassertv(false);
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_float32:
|
||||
|
|
@ -243,14 +236,7 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) {
|
|||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
{
|
||||
maybe_scale_color(data);
|
||||
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
|
||||
*(PN_uint32 *)pointer = qpGeomVertexData::pack_8888(0, _a, _b, 0);
|
||||
} else {
|
||||
*(PN_uint32 *)pointer = qpGeomVertexData::pack_8888(_a, _b, 0, 0);
|
||||
}
|
||||
}
|
||||
nassertv(false);
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_float32:
|
||||
|
|
@ -308,14 +294,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) {
|
|||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
{
|
||||
maybe_scale_color(data);
|
||||
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
|
||||
*(PN_uint32 *)pointer = qpGeomVertexData::pack_8888(0, _a, _b, _c);
|
||||
} else {
|
||||
*(PN_uint32 *)pointer = qpGeomVertexData::pack_8888(_a, _b, _c, 0);
|
||||
}
|
||||
}
|
||||
nassertv(false);
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_float32:
|
||||
|
|
@ -406,28 +385,206 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) {
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexWriter::Writer::
|
||||
set_data1i(unsigned char *pointer, int data) {
|
||||
switch (_data_type->get_numeric_type()) {
|
||||
case qpGeomVertexDataType::NT_uint8:
|
||||
*pointer = data;
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_uint16:
|
||||
*(PN_uint16 *)pointer = data;
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
{
|
||||
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
|
||||
*(PN_uint32 *)pointer = qpGeomVertexData::pack_8888(0, data, 0, 0);
|
||||
} else {
|
||||
*(PN_uint32 *)pointer = qpGeomVertexData::pack_8888(_a, data, 0, 0);
|
||||
}
|
||||
set_data1i(unsigned char *pointer, int a) {
|
||||
switch (_data_type->get_num_values()) {
|
||||
case 1:
|
||||
switch (_data_type->get_numeric_type()) {
|
||||
case qpGeomVertexDataType::NT_uint8:
|
||||
*pointer = a;
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_uint16:
|
||||
*(PN_uint16 *)pointer = a;
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
nassertv(false);
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_float32:
|
||||
*(PN_float32 *)pointer = (float)a;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_float32:
|
||||
*(PN_float32 *)pointer = (float)data;
|
||||
case 2:
|
||||
set_data2i(pointer, a, 0);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
set_data3i(pointer, a, 0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
set_data4i(pointer, a, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::Writer::set_data2i
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexWriter::Writer::
|
||||
set_data2i(unsigned char *pointer, int a, int b) {
|
||||
switch (_data_type->get_num_values()) {
|
||||
case 1:
|
||||
set_data1i(pointer, a);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
switch (_data_type->get_numeric_type()) {
|
||||
case qpGeomVertexDataType::NT_uint8:
|
||||
pointer[0] = a;
|
||||
pointer[1] = b;
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_uint16:
|
||||
{
|
||||
PN_uint16 *pi = (PN_uint16 *)pointer;
|
||||
pi[0] = a;
|
||||
pi[1] = b;
|
||||
}
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
nassertv(false);
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_float32:
|
||||
{
|
||||
PN_float32 *pi = (PN_float32 *)pointer;
|
||||
pi[0] = a;
|
||||
pi[1] = b;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
set_data3i(pointer, a, b, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
set_data4i(pointer, a, b, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::Writer::set_data3i
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexWriter::Writer::
|
||||
set_data3i(unsigned char *pointer, int a, int b, int c) {
|
||||
switch (_data_type->get_num_values()) {
|
||||
case 1:
|
||||
set_data1i(pointer, a);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
set_data2i(pointer, a, b);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
switch (_data_type->get_numeric_type()) {
|
||||
case qpGeomVertexDataType::NT_uint8:
|
||||
pointer[0] = a;
|
||||
pointer[1] = b;
|
||||
pointer[2] = c;
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_uint16:
|
||||
{
|
||||
PN_uint16 *pi = (PN_uint16 *)pointer;
|
||||
pi[0] = a;
|
||||
pi[1] = b;
|
||||
pi[2] = c;
|
||||
}
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
nassertv(false);
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_float32:
|
||||
{
|
||||
PN_float32 *pi = (PN_float32 *)pointer;
|
||||
pi[0] = a;
|
||||
pi[1] = b;
|
||||
pi[2] = c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
set_data4i(pointer, a, b, c, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpGeomVertexWriter::Writer::set_data4i
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpGeomVertexWriter::Writer::
|
||||
set_data4i(unsigned char *pointer, int a, int b, int c, int d) {
|
||||
switch (_data_type->get_num_values()) {
|
||||
case 1:
|
||||
set_data1i(pointer, a);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
set_data2i(pointer, a, b);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
set_data3i(pointer, a, b, c);
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (_data_type->get_numeric_type()) {
|
||||
case qpGeomVertexDataType::NT_uint8:
|
||||
pointer[0] = a;
|
||||
pointer[1] = b;
|
||||
pointer[2] = c;
|
||||
pointer[3] = d;
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_uint16:
|
||||
{
|
||||
PN_uint16 *pi = (PN_uint16 *)pointer;
|
||||
pi[0] = a;
|
||||
pi[1] = b;
|
||||
pi[2] = c;
|
||||
pi[3] = d;
|
||||
}
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_packed_8888:
|
||||
{
|
||||
if (_data_type->get_contents() == qpGeomVertexDataType::C_argb) {
|
||||
*(PN_uint32 *)pointer = qpGeomVertexData::pack_8888(d, a, b, c);
|
||||
} else {
|
||||
*(PN_uint32 *)pointer = qpGeomVertexData::pack_8888(a, b, c, d);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case qpGeomVertexDataType::NT_float32:
|
||||
{
|
||||
PN_float32 *pi = (PN_float32 *)pointer;
|
||||
pi[0] = a;
|
||||
pi[1] = b;
|
||||
pi[2] = c;
|
||||
pi[3] = d;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,12 @@ PUBLISHED:
|
|||
INLINE void set_data4f(const LVecBase4f &data);
|
||||
|
||||
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_data3i(int a, int b, int c);
|
||||
INLINE void set_data3i(const int data[3]);
|
||||
INLINE void set_data4i(int a, int b, int c, int d);
|
||||
INLINE void set_data4i(const int data[4]);
|
||||
|
||||
INLINE void add_data1f(float data);
|
||||
INLINE void add_data2f(float x, float y);
|
||||
|
|
@ -116,6 +122,12 @@ PUBLISHED:
|
|||
INLINE void add_data4f(const LVecBase4f &data);
|
||||
|
||||
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_data3i(int a, int b, int c);
|
||||
INLINE void add_data3i(const int data[3]);
|
||||
INLINE void add_data4i(int a, int b, int c, int d);
|
||||
INLINE void add_data4i(const int data[4]);
|
||||
|
||||
private:
|
||||
class Writer;
|
||||
|
|
@ -150,7 +162,10 @@ private:
|
|||
virtual void set_data3f(unsigned char *pointer, const LVecBase3f &data);
|
||||
virtual void set_data4f(unsigned char *pointer, const LVecBase4f &data);
|
||||
|
||||
virtual void set_data1i(unsigned char *pointer, int 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);
|
||||
|
||||
INLINE unsigned int maybe_scale_color(float data);
|
||||
INLINE void maybe_scale_color(const LVecBase2f &data);
|
||||
|
|
|
|||
|
|
@ -58,6 +58,49 @@ get_modified() const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformBlendPalette::get_num_transforms
|
||||
// Access: Published
|
||||
// Description: Returns the number of unique VertexTransform objects
|
||||
// represented in the palette. This will correspond to
|
||||
// the size of the TransformPalette object that would
|
||||
// represent the same table. This is also the same
|
||||
// limit reflected by
|
||||
// GraphicsStateGuardian::get_max_vertex_transform_indices().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int TransformBlendPalette::
|
||||
get_num_transforms() const {
|
||||
consider_rebuild_index();
|
||||
return _num_transforms;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformBlendPalette::get_max_simultaneous_transforms
|
||||
// Access: Published
|
||||
// Description: Returns the maximum number of unique VertexTransform
|
||||
// objects that are applied to any one vertex
|
||||
// simultaneously. This is the same limit reflected by
|
||||
// GraphicsStateGuardian::get_max_vertex_transforms().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int TransformBlendPalette::
|
||||
get_max_simultaneous_transforms() const {
|
||||
consider_rebuild_index();
|
||||
return _max_simultaneous_transforms;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformBlendPalette::consider_rebuild_index
|
||||
// Access: Private
|
||||
// Description: Calls rebuild_index() if the index needs to be
|
||||
// rebuilt.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TransformBlendPalette::
|
||||
consider_rebuild_index() const {
|
||||
if (_blend_index.empty()) {
|
||||
((TransformBlendPalette *)this)->rebuild_index();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformBlendPalette::CData::Constructor
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -95,9 +95,7 @@ remove_blend(int n) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int TransformBlendPalette::
|
||||
add_blend(const TransformBlend &blend) {
|
||||
if (_blend_index.empty()) {
|
||||
rebuild_index();
|
||||
}
|
||||
consider_rebuild_index();
|
||||
|
||||
BlendIndex::iterator bi;
|
||||
bi = _blend_index.find(&blend);
|
||||
|
|
@ -148,9 +146,25 @@ void TransformBlendPalette::
|
|||
rebuild_index() {
|
||||
_blend_index.clear();
|
||||
|
||||
for (int i = 0; i < (int)_blends.size(); i++) {
|
||||
_blend_index[&_blends[i]] = i;
|
||||
// We'll also count up these two statistics while we rebuild the
|
||||
// index.
|
||||
_num_transforms = 0;
|
||||
_max_simultaneous_transforms = 0;
|
||||
|
||||
pset<const VertexTransform *> transforms;
|
||||
|
||||
for (int i = 0; i < (int)_blends.size(); ++i) {
|
||||
const TransformBlend &blend = _blends[i];
|
||||
_blend_index[&blend] = i;
|
||||
|
||||
for (int ti = 0; ti < blend.get_num_transforms(); ++ti) {
|
||||
transforms.insert(blend.get_transform(ti));
|
||||
}
|
||||
_max_simultaneous_transforms = max(_max_simultaneous_transforms,
|
||||
blend.get_num_transforms());
|
||||
}
|
||||
|
||||
_num_transforms = transforms.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -64,10 +64,14 @@ PUBLISHED:
|
|||
void remove_blend(int n);
|
||||
int add_blend(const TransformBlend &blend);
|
||||
|
||||
INLINE int get_num_transforms() const;
|
||||
INLINE int get_max_simultaneous_transforms() const;
|
||||
|
||||
void write(ostream &out, int indent_level) const;
|
||||
|
||||
private:
|
||||
void clear_index();
|
||||
INLINE void consider_rebuild_index() const;
|
||||
void rebuild_index();
|
||||
|
||||
private:
|
||||
|
|
@ -84,6 +88,8 @@ private:
|
|||
// invalidating all the pointers into it).
|
||||
typedef pmap<const TransformBlend *, int, IndirectLess<TransformBlend> > BlendIndex;
|
||||
BlendIndex _blend_index;
|
||||
int _num_transforms;
|
||||
int _max_simultaneous_transforms;
|
||||
|
||||
// Even though we don't store the actual blend palette data in a
|
||||
// CycleData structure, we do need to keep a local cache of the
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ TransformPalette::
|
|||
// unregistered palettes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TransformPalette::
|
||||
set_transform(int n, VertexTransform *transform) {
|
||||
set_transform(int n, const VertexTransform *transform) {
|
||||
nassertv(!_is_registered);
|
||||
nassertv(n >= 0 && n < (int)_transforms.size());
|
||||
_transforms[n] = transform;
|
||||
|
|
@ -102,7 +102,7 @@ remove_transform(int n) {
|
|||
// unregistered palettes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int TransformPalette::
|
||||
add_transform(VertexTransform *transform) {
|
||||
add_transform(const VertexTransform *transform) {
|
||||
nassertr(!_is_registered, -1);
|
||||
int new_index = (int)_transforms.size();
|
||||
_transforms.push_back(transform);
|
||||
|
|
@ -132,7 +132,8 @@ do_register() {
|
|||
|
||||
Transforms::iterator ti;
|
||||
for (ti = _transforms.begin(); ti != _transforms.end(); ++ti) {
|
||||
bool inserted = (*ti)->_palettes.insert(this).second;
|
||||
VertexTransform *transform = (VertexTransform *)(*ti).p();
|
||||
bool inserted = transform->_palettes.insert(this).second;
|
||||
nassertv(inserted);
|
||||
}
|
||||
_is_registered = true;
|
||||
|
|
@ -150,7 +151,8 @@ do_unregister() {
|
|||
|
||||
Transforms::iterator ti;
|
||||
for (ti = _transforms.begin(); ti != _transforms.end(); ++ti) {
|
||||
(*ti)->_palettes.erase(this);
|
||||
VertexTransform *transform = (VertexTransform *)(*ti).p();
|
||||
transform->_palettes.erase(this);
|
||||
}
|
||||
_is_registered = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ PUBLISHED:
|
|||
INLINE const VertexTransform *get_transform(int n) const;
|
||||
INLINE UpdateSeq get_modified() const;
|
||||
|
||||
void set_transform(int n, VertexTransform *transform);
|
||||
void set_transform(int n, const VertexTransform *transform);
|
||||
void remove_transform(int n);
|
||||
int add_transform(VertexTransform *transform);
|
||||
int add_transform(const VertexTransform *transform);
|
||||
|
||||
void write(ostream &out) const;
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ private:
|
|||
private:
|
||||
bool _is_registered;
|
||||
|
||||
typedef pvector< PT(VertexTransform) > Transforms;
|
||||
typedef pvector< CPT(VertexTransform) > Transforms;
|
||||
Transforms _transforms;
|
||||
|
||||
// This is the data that must be cycled between pipeline stages.
|
||||
|
|
|
|||
|
|
@ -47,6 +47,24 @@ VertexTransform::
|
|||
nassertv(_palettes.empty());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VertexTransform::mult_matrix
|
||||
// Access: Published, Virtual
|
||||
// Description: Premultiplies this transform's matrix with the
|
||||
// indicated previous matrix, so that the result is the
|
||||
// net composition of the given transform with this
|
||||
// transform. The result is stored in the parameter
|
||||
// "result", which should not be the same matrix as
|
||||
// previous.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void VertexTransform::
|
||||
mult_matrix(LMatrix4f &result, const LMatrix4f &previous) const {
|
||||
nassertv(&result != &previous);
|
||||
LMatrix4f me;
|
||||
get_matrix(me);
|
||||
result.multiply(me, previous);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VertexTransform::accumulate_matrix
|
||||
// Access: Published, Virtual
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ PUBLISHED:
|
|||
virtual ~VertexTransform();
|
||||
|
||||
virtual void get_matrix(LMatrix4f &matrix) const=0;
|
||||
virtual void mult_matrix(LMatrix4f &result, const LMatrix4f &previous) const;
|
||||
virtual void accumulate_matrix(LMatrix4f &accum, float weight) const;
|
||||
|
||||
INLINE UpdateSeq get_modified() const;
|
||||
|
|
|
|||
Loading…
Reference in New Issue