mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
some animation optimizations
This commit is contained in:
parent
5e5d8f7e17
commit
7e8737dd3d
@ -800,6 +800,53 @@ transform(const LMatrix4d &mat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A function object for sort_by_external_index(), below.
|
||||||
|
class SortByExternalIndex {
|
||||||
|
public:
|
||||||
|
bool operator () (EggVertex *a, EggVertex *b) const {
|
||||||
|
int ai = a->get_external_index();
|
||||||
|
int bi = b->get_external_index();
|
||||||
|
if (ai != bi) {
|
||||||
|
return ai < bi;
|
||||||
|
}
|
||||||
|
return a->get_index() < b->get_index();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: EggVertexPool::sort_by_external_index
|
||||||
|
// Access: Published
|
||||||
|
// Description: Re-orders (and re-numbers) the vertices in this
|
||||||
|
// vertex pool so that they appear in increasing order
|
||||||
|
// by the optional external_index that has been assigned
|
||||||
|
// to each vertex.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void EggVertexPool::
|
||||||
|
sort_by_external_index() {
|
||||||
|
// Copy the vertices into a vector for sorting.
|
||||||
|
typedef pvector<EggVertex *> SortedVertices;
|
||||||
|
SortedVertices sorted_vertices;
|
||||||
|
sorted_vertices.reserve(size());
|
||||||
|
iterator i;
|
||||||
|
for (i = begin(); i != end(); ++i) {
|
||||||
|
sorted_vertices.push_back(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
::sort(sorted_vertices.begin(), sorted_vertices.end(), SortByExternalIndex());
|
||||||
|
|
||||||
|
// Now reassign the indices, and copy them into a new index map.
|
||||||
|
IndexVertices new_index_vertices;
|
||||||
|
int vi;
|
||||||
|
for (vi = 0; vi < (int)sorted_vertices.size(); ++vi) {
|
||||||
|
EggVertex *vertex = sorted_vertices[vi];
|
||||||
|
vertex->_index = vi;
|
||||||
|
new_index_vertices[vi] = vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, assign the new index map.
|
||||||
|
_index_vertices.swap(new_index_vertices);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: EggVertexPool::write
|
// Function: EggVertexPool::write
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -133,6 +133,7 @@ PUBLISHED:
|
|||||||
void add_unused_vertices_to_prim(EggPrimitive *prim);
|
void add_unused_vertices_to_prim(EggPrimitive *prim);
|
||||||
|
|
||||||
void transform(const LMatrix4d &mat);
|
void transform(const LMatrix4d &mat);
|
||||||
|
void sort_by_external_index();
|
||||||
|
|
||||||
void write(ostream &out, int indent_level) const;
|
void write(ostream &out, int indent_level) const;
|
||||||
|
|
||||||
|
@ -170,13 +170,20 @@ ConfigVariableBool egg_preload_simple_textures
|
|||||||
"either this or preload-simple-textures is true."));
|
"either this or preload-simple-textures is true."));
|
||||||
|
|
||||||
ConfigVariableDouble egg_vertex_membership_quantize
|
ConfigVariableDouble egg_vertex_membership_quantize
|
||||||
("egg-vertex-membership-quantize", 0.01,
|
("egg-vertex-membership-quantize", 0.1,
|
||||||
PRC_DESC("Specifies the nearest amount to round each vertex joint "
|
PRC_DESC("Specifies the nearest amount to round each vertex joint "
|
||||||
"membership value when loading an egg file. This affects animated "
|
"membership value when loading an egg file. This affects animated "
|
||||||
"egg files only. There is a substantial runtime "
|
"egg files only. There is a substantial runtime "
|
||||||
"performance advantage for reducing trivial differences in joint "
|
"performance advantage for reducing trivial differences in joint "
|
||||||
"membership. Set this to 0 to leave joint membership as it is."));
|
"membership. Set this to 0 to leave joint membership as it is."));
|
||||||
|
|
||||||
|
ConfigVariableInt egg_vertex_max_num_joints
|
||||||
|
("egg-vertex-max-num-joints", 4,
|
||||||
|
PRC_DESC("Specifies the maximum number of distinct joints that are allowed "
|
||||||
|
"to control any one vertex. If a vertex requests assignment to "
|
||||||
|
"more than this number of joints, the joints with the lesser membership "
|
||||||
|
"value are ignored. Set this to -1 to allow any number of joints."));
|
||||||
|
|
||||||
ConfigureFn(config_egg2pg) {
|
ConfigureFn(config_egg2pg) {
|
||||||
init_libegg2pg();
|
init_libegg2pg();
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ extern EXPCL_PANDAEGG ConfigVariableInt egg_max_indices;
|
|||||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_emulate_bface;
|
extern EXPCL_PANDAEGG ConfigVariableBool egg_emulate_bface;
|
||||||
extern EXPCL_PANDAEGG ConfigVariableBool egg_preload_simple_textures;
|
extern EXPCL_PANDAEGG ConfigVariableBool egg_preload_simple_textures;
|
||||||
extern EXPCL_PANDAEGG ConfigVariableDouble egg_vertex_membership_quantize;
|
extern EXPCL_PANDAEGG ConfigVariableDouble egg_vertex_membership_quantize;
|
||||||
|
extern EXPCL_PANDAEGG ConfigVariableInt egg_vertex_max_num_joints;
|
||||||
|
|
||||||
extern EXPCL_PANDAEGG void init_libegg2pg();
|
extern EXPCL_PANDAEGG void init_libegg2pg();
|
||||||
|
|
||||||
|
@ -379,6 +379,20 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
|
|||||||
// pools as if they contain a combination of multiple colors.
|
// pools as if they contain a combination of multiple colors.
|
||||||
has_overall_color = false;
|
has_overall_color = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PT(TransformBlendTable) blend_table;
|
||||||
|
if (is_dynamic) {
|
||||||
|
// Dynamic vertex pools will require a TransformBlendTable to
|
||||||
|
// indicate how the vertices are to be animated.
|
||||||
|
blend_table = make_blend_table(vertex_pool, egg_bin, character_maker);
|
||||||
|
|
||||||
|
// Now that we've created the blend table, we can re-order the
|
||||||
|
// vertices in the pool to efficiently group vertices together
|
||||||
|
// that will share the same transform matrix. (We have to
|
||||||
|
// re-order them before we create primitives, below, because
|
||||||
|
// this will change the vertex index numbers.)
|
||||||
|
vertex_pool->sort_by_external_index();
|
||||||
|
}
|
||||||
|
|
||||||
// Create a handful of GeomPrimitives corresponding to the various
|
// Create a handful of GeomPrimitives corresponding to the various
|
||||||
// types of primitives that reference this vertex pool.
|
// types of primitives that reference this vertex pool.
|
||||||
@ -400,10 +414,10 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
|
|||||||
} else {
|
} else {
|
||||||
mat = egg_bin->get_vertex_to_node();
|
mat = egg_bin->get_vertex_to_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now convert this vertex pool to a GeomVertexData.
|
// Now convert this vertex pool to a GeomVertexData.
|
||||||
PT(GeomVertexData) vertex_data =
|
PT(GeomVertexData) vertex_data =
|
||||||
make_vertex_data(render_state, vertex_pool, egg_bin, mat,
|
make_vertex_data(render_state, vertex_pool, egg_bin, mat, blend_table,
|
||||||
is_dynamic, character_maker, has_overall_color);
|
is_dynamic, character_maker, has_overall_color);
|
||||||
nassertv(vertex_data != (GeomVertexData *)NULL);
|
nassertv(vertex_data != (GeomVertexData *)NULL);
|
||||||
|
|
||||||
@ -2185,7 +2199,7 @@ check_for_polysets(EggGroup *egg_group, bool &all_polysets, bool &any_hidden) {
|
|||||||
PT(GeomVertexData) EggLoader::
|
PT(GeomVertexData) EggLoader::
|
||||||
make_vertex_data(const EggRenderState *render_state,
|
make_vertex_data(const EggRenderState *render_state,
|
||||||
EggVertexPool *vertex_pool, EggNode *primitive_home,
|
EggVertexPool *vertex_pool, EggNode *primitive_home,
|
||||||
const LMatrix4d &transform,
|
const LMatrix4d &transform, TransformBlendTable *blend_table,
|
||||||
bool is_dynamic, CharacterMaker *character_maker,
|
bool is_dynamic, CharacterMaker *character_maker,
|
||||||
bool ignore_color) {
|
bool ignore_color) {
|
||||||
VertexPoolTransform vpt;
|
VertexPoolTransform vpt;
|
||||||
@ -2255,7 +2269,6 @@ make_vertex_data(const EggRenderState *render_state,
|
|||||||
|
|
||||||
PT(GeomVertexFormat) temp_format = new GeomVertexFormat(array_format);
|
PT(GeomVertexFormat) temp_format = new GeomVertexFormat(array_format);
|
||||||
|
|
||||||
PT(TransformBlendTable) blend_table;
|
|
||||||
PT(SliderTable) slider_table;
|
PT(SliderTable) slider_table;
|
||||||
string name = _data->get_egg_filename().get_basename_wo_extension();
|
string name = _data->get_egg_filename().get_basename_wo_extension();
|
||||||
|
|
||||||
@ -2271,9 +2284,6 @@ make_vertex_data(const EggRenderState *render_state,
|
|||||||
animation.set_panda();
|
animation.set_panda();
|
||||||
temp_format->set_animation(animation);
|
temp_format->set_animation(animation);
|
||||||
|
|
||||||
blend_table = new TransformBlendTable;
|
|
||||||
blend_table->set_rows(SparseArray::lower_on(vertex_pool->size()));
|
|
||||||
|
|
||||||
PT(GeomVertexArrayFormat) anim_array_format = new GeomVertexArrayFormat;
|
PT(GeomVertexArrayFormat) anim_array_format = new GeomVertexArrayFormat;
|
||||||
anim_array_format->add_column
|
anim_array_format->add_column
|
||||||
(InternalName::get_transform_blend(), 1,
|
(InternalName::get_transform_blend(), 1,
|
||||||
@ -2477,34 +2487,7 @@ make_vertex_data(const EggRenderState *render_state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_dynamic) {
|
if (is_dynamic) {
|
||||||
// Figure out the transforms affecting this particular vertex.
|
int table_index = vertex->get_external_index();
|
||||||
TransformBlend blend;
|
|
||||||
if (vertex->gref_size() == 0) {
|
|
||||||
// If the vertex has no explicit membership, it belongs right
|
|
||||||
// where it is.
|
|
||||||
PT(VertexTransform) vt = character_maker->egg_to_transform(primitive_home);
|
|
||||||
nassertr(vt != (VertexTransform *)NULL, vertex_data);
|
|
||||||
blend.add_transform(vt, 1.0f);
|
|
||||||
} else {
|
|
||||||
// If the vertex does have an explicit membership, ignore its
|
|
||||||
// parentage and assign it where it wants to be.
|
|
||||||
double quantize = egg_vertex_membership_quantize;
|
|
||||||
EggVertex::GroupRef::const_iterator gri;
|
|
||||||
for (gri = vertex->gref_begin(); gri != vertex->gref_end(); ++gri) {
|
|
||||||
EggGroup *egg_joint = (*gri);
|
|
||||||
double membership = egg_joint->get_vertex_membership(vertex);
|
|
||||||
if (quantize != 0.0) {
|
|
||||||
membership = cfloor(membership / quantize + 0.5) * quantize;
|
|
||||||
}
|
|
||||||
|
|
||||||
PT(VertexTransform) vt = character_maker->egg_to_transform(egg_joint);
|
|
||||||
nassertr(vt != (VertexTransform *)NULL, vertex_data);
|
|
||||||
blend.add_transform(vt, membership);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
blend.normalize_weights();
|
|
||||||
|
|
||||||
int table_index = blend_table->add_blend(blend);
|
|
||||||
gvw.set_column(InternalName::get_transform_blend());
|
gvw.set_column(InternalName::get_transform_blend());
|
||||||
gvw.set_data1i(table_index);
|
gvw.set_data1i(table_index);
|
||||||
}
|
}
|
||||||
@ -2518,6 +2501,62 @@ make_vertex_data(const EggRenderState *render_state,
|
|||||||
return vertex_data;
|
return vertex_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: EggLoader::make_blend_table
|
||||||
|
// Access: Private
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PT(TransformBlendTable) EggLoader::
|
||||||
|
make_blend_table(EggVertexPool *vertex_pool, EggNode *primitive_home,
|
||||||
|
CharacterMaker *character_maker) {
|
||||||
|
PT(TransformBlendTable) blend_table;
|
||||||
|
blend_table = new TransformBlendTable;
|
||||||
|
blend_table->set_rows(SparseArray::lower_on(vertex_pool->size()));
|
||||||
|
|
||||||
|
EggVertexPool::const_iterator vi;
|
||||||
|
for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
|
||||||
|
EggVertex *vertex = (*vi);
|
||||||
|
|
||||||
|
// Figure out the transforms affecting this particular vertex.
|
||||||
|
TransformBlend blend;
|
||||||
|
if (vertex->gref_size() == 0) {
|
||||||
|
// If the vertex has no explicit membership, it belongs right
|
||||||
|
// where it is.
|
||||||
|
PT(VertexTransform) vt = character_maker->egg_to_transform(primitive_home);
|
||||||
|
nassertr(vt != (VertexTransform *)NULL, NULL);
|
||||||
|
blend.add_transform(vt, 1.0f);
|
||||||
|
} else {
|
||||||
|
// If the vertex does have an explicit membership, ignore its
|
||||||
|
// parentage and assign it where it wants to be.
|
||||||
|
double quantize = egg_vertex_membership_quantize;
|
||||||
|
EggVertex::GroupRef::const_iterator gri;
|
||||||
|
for (gri = vertex->gref_begin(); gri != vertex->gref_end(); ++gri) {
|
||||||
|
EggGroup *egg_joint = (*gri);
|
||||||
|
double membership = egg_joint->get_vertex_membership(vertex);
|
||||||
|
if (quantize != 0.0) {
|
||||||
|
membership = cfloor(membership / quantize + 0.5) * quantize;
|
||||||
|
}
|
||||||
|
|
||||||
|
PT(VertexTransform) vt = character_maker->egg_to_transform(egg_joint);
|
||||||
|
nassertr(vt != (VertexTransform *)NULL, NULL);
|
||||||
|
blend.add_transform(vt, membership);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (egg_vertex_max_num_joints >= 0) {
|
||||||
|
blend.limit_transforms(egg_vertex_max_num_joints);
|
||||||
|
}
|
||||||
|
blend.normalize_weights();
|
||||||
|
|
||||||
|
int table_index = blend_table->add_blend(blend);
|
||||||
|
|
||||||
|
// We take advantage of the "external index" field of the
|
||||||
|
// EggVertex to temporarily store the transform blend index.
|
||||||
|
vertex->set_external_index(table_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return blend_table;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: EggLoader::record_morph
|
// Function: EggLoader::record_morph
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
@ -143,8 +143,11 @@ private:
|
|||||||
bool &any_hidden);
|
bool &any_hidden);
|
||||||
PT(GeomVertexData) make_vertex_data
|
PT(GeomVertexData) make_vertex_data
|
||||||
(const EggRenderState *render_state, EggVertexPool *vertex_pool,
|
(const EggRenderState *render_state, EggVertexPool *vertex_pool,
|
||||||
EggNode *primitive_home, const LMatrix4d &transform, bool is_dynamic,
|
EggNode *primitive_home, const LMatrix4d &transform, TransformBlendTable *blend_table,
|
||||||
CharacterMaker *character_maker, bool ignore_color);
|
bool is_dynamic, CharacterMaker *character_maker, bool ignore_color);
|
||||||
|
PT(TransformBlendTable) make_blend_table
|
||||||
|
(EggVertexPool *vertex_bool, EggNode *primitive_home,
|
||||||
|
CharacterMaker *character_maker);
|
||||||
void record_morph
|
void record_morph
|
||||||
(GeomVertexArrayFormat *array_format,
|
(GeomVertexArrayFormat *array_format,
|
||||||
CharacterMaker *character_maker, const string &morph_name,
|
CharacterMaker *character_maker, const string &morph_name,
|
||||||
|
@ -35,6 +35,7 @@ PStatCollector GeomVertexData::_scale_color_pcollector("*:Munge:Scale color");
|
|||||||
PStatCollector GeomVertexData::_set_color_pcollector("*:Munge:Set color");
|
PStatCollector GeomVertexData::_set_color_pcollector("*:Munge:Set color");
|
||||||
PStatCollector GeomVertexData::_animation_pcollector("*:Animation");
|
PStatCollector GeomVertexData::_animation_pcollector("*:Animation");
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexData::Default Constructor
|
// Function: GeomVertexData::Default Constructor
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -1100,6 +1101,49 @@ clear_animated_vertices() {
|
|||||||
cdata->_animated_vertices.clear();
|
cdata->_animated_vertices.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexData::transform_vertices
|
||||||
|
// Access: Published
|
||||||
|
// Description: Applies the indicated transform matrix to all of the
|
||||||
|
// vertices in the GeomVertexData. The transform is
|
||||||
|
// applied to all "point" and "vector" type columns
|
||||||
|
// described in the format.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void GeomVertexData::
|
||||||
|
transform_vertices(const LMatrix4 &mat) {
|
||||||
|
transform_vertices(mat, 0, get_num_rows());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexData::transform_vertices
|
||||||
|
// Access: Published
|
||||||
|
// Description: Applies the indicated transform matrix to all of the
|
||||||
|
// vertices from begin_row up to but not including
|
||||||
|
// end_row. The transform is applied to all "point" and
|
||||||
|
// "vector" type columns described in the format.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void GeomVertexData::
|
||||||
|
transform_vertices(const LMatrix4 &mat, int begin_row, int end_row) {
|
||||||
|
if (end_row <= begin_row) {
|
||||||
|
// Trivial no-op.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GeomVertexFormat *format = get_format();
|
||||||
|
|
||||||
|
int ci;
|
||||||
|
for (ci = 0; ci < format->get_num_points(); ci++) {
|
||||||
|
GeomVertexRewriter data(this, format->get_point(ci));
|
||||||
|
do_transform_point_column(format, data, mat, begin_row, end_row);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ci = 0; ci < format->get_num_vectors(); ci++) {
|
||||||
|
GeomVertexRewriter data(this, format->get_vector(ci));
|
||||||
|
do_transform_vector_column(format, data, mat, begin_row, end_row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexData::bytewise_copy
|
// Function: GeomVertexData::bytewise_copy
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
@ -1552,17 +1596,18 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
|
|||||||
// Then apply the transforms.
|
// Then apply the transforms.
|
||||||
CPT(TransformBlendTable) tb_table = cdata->_transform_blend_table.get_read_pointer();
|
CPT(TransformBlendTable) tb_table = cdata->_transform_blend_table.get_read_pointer();
|
||||||
if (tb_table != (TransformBlendTable *)NULL) {
|
if (tb_table != (TransformBlendTable *)NULL) {
|
||||||
PStatTimer timer3(_skinning_pcollector);
|
|
||||||
|
|
||||||
// Recompute all the blends up front, so we don't have to test
|
// Recompute all the blends up front, so we don't have to test
|
||||||
// each one for staleness at each vertex.
|
// each one for staleness at each vertex.
|
||||||
int num_blends = tb_table->get_num_blends();
|
{
|
||||||
int bi;
|
PStatTimer timer4(_blends_pcollector);
|
||||||
for (bi = 0; bi < num_blends; bi++) {
|
int num_blends = tb_table->get_num_blends();
|
||||||
tb_table->get_blend(bi).update_blend(current_thread);
|
for (int bi = 0; bi < num_blends; bi++) {
|
||||||
|
tb_table->get_blend(bi).update_blend(current_thread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now go through and apply the transforms.
|
// Now go through and apply the transforms.
|
||||||
|
PStatTimer timer3(_skinning_pcollector);
|
||||||
|
|
||||||
const SparseArray &rows = tb_table->get_rows();
|
const SparseArray &rows = tb_table->get_rows();
|
||||||
int num_subranges = rows.get_num_subranges();
|
int num_subranges = rows.get_num_subranges();
|
||||||
@ -1577,8 +1622,7 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
|
|||||||
|
|
||||||
CPT(GeomVertexArrayFormat) blend_array_format = orig_format->get_array(blend_array_index);
|
CPT(GeomVertexArrayFormat) blend_array_format = orig_format->get_array(blend_array_index);
|
||||||
|
|
||||||
if (blend_array_format->get_num_columns() == 1 &&
|
if (blend_array_format->get_stride() == 2 &&
|
||||||
blend_array_format->get_stride() == 2 &&
|
|
||||||
blend_array_format->get_column(0)->get_component_bytes() == 2) {
|
blend_array_format->get_column(0)->get_component_bytes() == 2) {
|
||||||
// The blend indices are a table of ushorts. Optimize this
|
// The blend indices are a table of ushorts. Optimize this
|
||||||
// common case.
|
// common case.
|
||||||
@ -1588,98 +1632,80 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
|
|||||||
int ci;
|
int ci;
|
||||||
for (ci = 0; ci < new_format->get_num_points(); ci++) {
|
for (ci = 0; ci < new_format->get_num_points(); ci++) {
|
||||||
GeomVertexRewriter data(new_data, new_format->get_point(ci));
|
GeomVertexRewriter data(new_data, new_format->get_point(ci));
|
||||||
const GeomVertexColumn *data_column = data.get_column();
|
|
||||||
if (data_column->get_num_values() == 3 &&
|
|
||||||
data_column->get_numeric_type() == NT_float32) {
|
|
||||||
// Table of points is a table of LPoint3f's. Optimize this
|
|
||||||
// common case.
|
|
||||||
int data_index = new_format->get_array_with(new_format->get_point(ci));
|
|
||||||
PT(GeomVertexArrayData) data_array = new_data->modify_array(data_index);
|
|
||||||
PT(GeomVertexArrayDataHandle) data_handle = data_array->modify_handle();
|
|
||||||
unsigned char *datat = data_handle->get_write_pointer();
|
|
||||||
datat += data_column->get_start();
|
|
||||||
size_t stride = data_array->get_array_format()->get_stride();
|
|
||||||
|
|
||||||
for (int i = 0; i < num_subranges; ++i) {
|
for (int i = 0; i < num_subranges; ++i) {
|
||||||
int begin = rows.get_subrange_begin(i);
|
int begin = rows.get_subrange_begin(i);
|
||||||
int end = rows.get_subrange_end(i);
|
int end = rows.get_subrange_end(i);
|
||||||
for (int j = begin; j < end; ++j) {
|
nassertv(begin < end);
|
||||||
LPoint3f &vertex = *(LPoint3f *)(&datat[j * stride]);
|
|
||||||
int bi = blendt[j];
|
|
||||||
tb_table->get_blend(bi).transform_point(vertex, current_thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (data_column->get_num_values() == 4) {
|
int first_vertex = begin;
|
||||||
// Use the GeomVertexRewriter to adjust the 4-component
|
int first_bi = blendt[first_vertex];
|
||||||
// points.
|
|
||||||
for (int i = 0; i < num_subranges; ++i) {
|
|
||||||
int begin = rows.get_subrange_begin(i);
|
|
||||||
int end = rows.get_subrange_end(i);
|
|
||||||
data.set_row_unsafe(begin);
|
|
||||||
for (int j = begin; j < end; ++j) {
|
|
||||||
LPoint4 vertex = data.get_data4();
|
|
||||||
int bi = blendt[j];
|
|
||||||
tb_table->get_blend(bi).transform_point(vertex, current_thread);
|
|
||||||
data.set_data4(vertex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
while (first_vertex < end) {
|
||||||
// Use the GeomVertexRewriter to adjust the 3-component
|
// At this point, first_vertex is the first of a series of
|
||||||
// points.
|
// vertices that shares the blend index first_bi.
|
||||||
for (int i = 0; i < num_subranges; ++i) {
|
|
||||||
int begin = rows.get_subrange_begin(i);
|
// Scan for the end of this series of vertices--we're
|
||||||
int end = rows.get_subrange_end(i);
|
// looking for the next vertex with a different blend index.
|
||||||
data.set_row_unsafe(begin);
|
int next_vertex = first_vertex;
|
||||||
for (int j = begin; j < end; ++j) {
|
int next_bi = first_bi;
|
||||||
LPoint3 vertex = data.get_data3();
|
++next_vertex;
|
||||||
int bi = blendt[j];
|
while (next_vertex < end) {
|
||||||
tb_table->get_blend(bi).transform_point(vertex, current_thread);
|
next_bi = blendt[next_vertex];
|
||||||
data.set_data3(vertex);
|
if (next_bi != first_bi) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++next_vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We've just reached the end of the vertices with a matching
|
||||||
|
// blend index. Transform all those vertices as a block.
|
||||||
|
LMatrix4 mat;
|
||||||
|
tb_table->get_blend(first_bi).get_blend(mat, current_thread);
|
||||||
|
new_data->do_transform_point_column(new_format, data, mat, first_vertex, next_vertex);
|
||||||
|
|
||||||
|
first_vertex = next_vertex;
|
||||||
|
first_bi = next_bi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also process vectors: normals, etc.
|
|
||||||
for (ci = 0; ci < new_format->get_num_vectors(); ci++) {
|
for (ci = 0; ci < new_format->get_num_vectors(); ci++) {
|
||||||
GeomVertexRewriter data(new_data, new_format->get_vector(ci));
|
GeomVertexRewriter data(new_data, new_format->get_vector(ci));
|
||||||
const GeomVertexColumn *data_column = data.get_column();
|
|
||||||
if (data_column->get_num_values() == 3 &&
|
|
||||||
data_column->get_numeric_type() == NT_float32) {
|
|
||||||
// Table of vectors is a table of LVector3f's. Optimize this
|
|
||||||
// common case.
|
|
||||||
int data_index = new_format->get_array_with(new_format->get_vector(ci));
|
|
||||||
PT(GeomVertexArrayData) data_array = new_data->modify_array(data_index);
|
|
||||||
PT(GeomVertexArrayDataHandle) data_handle = data_array->modify_handle();
|
|
||||||
unsigned char *datat = data_handle->get_write_pointer();
|
|
||||||
datat += data_column->get_start();
|
|
||||||
size_t stride = data_array->get_array_format()->get_stride();
|
|
||||||
|
|
||||||
for (int i = 0; i < num_subranges; ++i) {
|
for (int i = 0; i < num_subranges; ++i) {
|
||||||
int begin = rows.get_subrange_begin(i);
|
int begin = rows.get_subrange_begin(i);
|
||||||
int end = rows.get_subrange_end(i);
|
int end = rows.get_subrange_end(i);
|
||||||
for (int j = begin; j < end; ++j) {
|
nassertv(begin < end);
|
||||||
LVector3f &vertex = *(LVector3f *)(&datat[j * stride]);
|
|
||||||
int bi = blendt[j];
|
int first_vertex = begin;
|
||||||
tb_table->get_blend(bi).transform_vector(vertex, current_thread);
|
int first_bi = blendt[first_vertex];
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
while (first_vertex < end) {
|
||||||
// Use the GeomVertexRewriter to adjust the vectors.
|
// At this point, first_vertex is the first of a series of
|
||||||
|
// vertices that shares the blend index first_bi.
|
||||||
for (int i = 0; i < num_subranges; ++i) {
|
|
||||||
int begin = rows.get_subrange_begin(i);
|
// Scan for the end of this series of vertices--we're
|
||||||
int end = rows.get_subrange_end(i);
|
// looking for the next vertex with a different blend index.
|
||||||
data.set_row_unsafe(begin);
|
int next_vertex = first_vertex;
|
||||||
for (int j = begin; j < end; ++j) {
|
int next_bi = first_bi;
|
||||||
LVector3 vertex = data.get_data3();
|
++next_vertex;
|
||||||
int bi = blendt[j];
|
while (next_vertex < end) {
|
||||||
tb_table->get_blend(bi).transform_vector(vertex, current_thread);
|
next_bi = blendt[next_vertex];
|
||||||
data.set_data3(vertex);
|
if (next_bi != first_bi) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++next_vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We've just reached the end of the vertices with a matching
|
||||||
|
// blend index. Transform all those vertices as a block.
|
||||||
|
LMatrix4 mat;
|
||||||
|
tb_table->get_blend(first_bi).get_blend(mat, current_thread);
|
||||||
|
new_data->do_transform_vector_column(new_format, data, mat, first_vertex, next_vertex);
|
||||||
|
|
||||||
|
first_vertex = next_vertex;
|
||||||
|
first_bi = next_bi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1693,51 +1719,174 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
|
|||||||
int ci;
|
int ci;
|
||||||
for (ci = 0; ci < new_format->get_num_points(); ci++) {
|
for (ci = 0; ci < new_format->get_num_points(); ci++) {
|
||||||
GeomVertexRewriter data(new_data, new_format->get_point(ci));
|
GeomVertexRewriter data(new_data, new_format->get_point(ci));
|
||||||
const GeomVertexColumn *data_column = data.get_column();
|
|
||||||
|
|
||||||
if (data_column->get_num_values() == 4) {
|
|
||||||
for (int i = 0; i < num_subranges; ++i) {
|
|
||||||
int begin = rows.get_subrange_begin(i);
|
|
||||||
int end = rows.get_subrange_end(i);
|
|
||||||
data.set_row_unsafe(begin);
|
|
||||||
blendi.set_row_unsafe(begin);
|
|
||||||
for (int j = begin; j < end; ++j) {
|
|
||||||
LPoint4 vertex = data.get_data4();
|
|
||||||
int bi = blendi.get_data1i();
|
|
||||||
tb_table->get_blend(bi).transform_point(vertex, current_thread);
|
|
||||||
data.set_data4(vertex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < num_subranges; ++i) {
|
|
||||||
int begin = rows.get_subrange_begin(i);
|
|
||||||
int end = rows.get_subrange_end(i);
|
|
||||||
data.set_row_unsafe(begin);
|
|
||||||
blendi.set_row_unsafe(begin);
|
|
||||||
for (int j = begin; j < end; ++j) {
|
|
||||||
LPoint3 vertex = data.get_data3();
|
|
||||||
int bi = blendi.get_data1i();
|
|
||||||
tb_table->get_blend(bi).transform_point(vertex, current_thread);
|
|
||||||
data.set_data3(vertex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ci = 0; ci < new_format->get_num_vectors(); ci++) {
|
|
||||||
GeomVertexRewriter data(new_data, new_format->get_vector(ci));
|
|
||||||
for (int i = 0; i < num_subranges; ++i) {
|
for (int i = 0; i < num_subranges; ++i) {
|
||||||
int begin = rows.get_subrange_begin(i);
|
int begin = rows.get_subrange_begin(i);
|
||||||
int end = rows.get_subrange_end(i);
|
int end = rows.get_subrange_end(i);
|
||||||
data.set_row_unsafe(begin);
|
nassertv(begin < end);
|
||||||
blendi.set_row_unsafe(begin);
|
blendi.set_row_unsafe(begin);
|
||||||
for (int j = begin; j < end; ++j) {
|
|
||||||
LVector3 vertex = data.get_data3();
|
int first_vertex = begin;
|
||||||
int bi = blendi.get_data1i();
|
int first_bi = blendi.get_data1i();
|
||||||
tb_table->get_blend(bi).transform_vector(vertex, current_thread);
|
|
||||||
data.set_data3(vertex);
|
while (first_vertex < end) {
|
||||||
|
// At this point, first_vertex is the first of a series of
|
||||||
|
// vertices that shares the blend index first_bi.
|
||||||
|
|
||||||
|
// Scan for the end of this series of vertices--we're
|
||||||
|
// looking for the next vertex with a different blend index.
|
||||||
|
int next_vertex = first_vertex;
|
||||||
|
int next_bi = first_bi;
|
||||||
|
++next_vertex;
|
||||||
|
while (next_vertex < end) {
|
||||||
|
next_bi = blendi.get_data1i();
|
||||||
|
if (next_bi != first_bi) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++next_vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We've just reached the end of the vertices with a matching
|
||||||
|
// blend index. Transform all those vertices as a block.
|
||||||
|
LMatrix4 mat;
|
||||||
|
tb_table->get_blend(first_bi).get_blend(mat, current_thread);
|
||||||
|
new_data->do_transform_point_column(new_format, data, mat, first_vertex, next_vertex);
|
||||||
|
|
||||||
|
first_vertex = next_vertex;
|
||||||
|
first_bi = next_bi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (ci = 0; ci < new_format->get_num_vectors(); ci++) {
|
||||||
|
GeomVertexRewriter data(new_data, new_format->get_vector(ci));
|
||||||
|
|
||||||
|
for (int i = 0; i < num_subranges; ++i) {
|
||||||
|
int begin = rows.get_subrange_begin(i);
|
||||||
|
int end = rows.get_subrange_end(i);
|
||||||
|
nassertv(begin != end);
|
||||||
|
blendi.set_row_unsafe(begin);
|
||||||
|
|
||||||
|
int first_vertex = begin;
|
||||||
|
int first_bi = blendi.get_data1i();
|
||||||
|
|
||||||
|
while (first_vertex < end) {
|
||||||
|
// At this point, first_vertex is the first of a series of
|
||||||
|
// vertices that shares the blend index first_bi.
|
||||||
|
|
||||||
|
// Scan for the end of this series of vertices--we're
|
||||||
|
// looking for the next vertex with a different blend index.
|
||||||
|
int next_vertex = first_vertex;
|
||||||
|
int next_bi = first_bi;
|
||||||
|
++next_vertex;
|
||||||
|
while (next_vertex < end) {
|
||||||
|
next_bi = blendi.get_data1i();
|
||||||
|
if (next_bi != first_bi) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++next_vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We've just reached the end of the vertices with a matching
|
||||||
|
// blend index. Transform all those vertices as a block.
|
||||||
|
LMatrix4 mat;
|
||||||
|
tb_table->get_blend(first_bi).get_blend(mat, current_thread);
|
||||||
|
new_data->do_transform_vector_column(new_format, data, mat, first_vertex, next_vertex);
|
||||||
|
|
||||||
|
first_vertex = next_vertex;
|
||||||
|
first_bi = next_bi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexData::do_transform_point_column
|
||||||
|
// Access: Private
|
||||||
|
// Description: Transforms a range of vertices for one particular
|
||||||
|
// column, as a point.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void GeomVertexData::
|
||||||
|
do_transform_point_column(const GeomVertexFormat *format, GeomVertexRewriter &data,
|
||||||
|
const LMatrix4 &mat, int begin_row, int end_row) {
|
||||||
|
const GeomVertexColumn *data_column = data.get_column();
|
||||||
|
|
||||||
|
if (data_column->get_num_values() == 3 &&
|
||||||
|
data_column->get_numeric_type() == NT_float32) {
|
||||||
|
// The table of points is a table of LPoint3f's. Optimize this
|
||||||
|
// common case.
|
||||||
|
PT(GeomVertexArrayDataHandle) data_handle = data.get_array_handle();
|
||||||
|
PT(GeomVertexArrayData) data_array = data_handle->get_object();
|
||||||
|
|
||||||
|
unsigned char *datat = data_handle->get_write_pointer();
|
||||||
|
datat += data_column->get_start();
|
||||||
|
size_t stride = data_array->get_array_format()->get_stride();
|
||||||
|
|
||||||
|
LMatrix4f matf = LCAST(float, mat);
|
||||||
|
for (int j = begin_row; j < end_row; ++j) {
|
||||||
|
LPoint3f &vertex = *(LPoint3f *)(&datat[j * stride]);
|
||||||
|
vertex = vertex * matf;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (data_column->get_num_values() == 4) {
|
||||||
|
// Use the GeomVertexRewriter to adjust the 4-component
|
||||||
|
// points.
|
||||||
|
|
||||||
|
data.set_row_unsafe(begin_row);
|
||||||
|
for (int j = begin_row; j < end_row; ++j) {
|
||||||
|
LPoint4 vertex = data.get_data4();
|
||||||
|
data.set_data4(vertex * mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Use the GeomVertexRewriter to adjust the 3-component
|
||||||
|
// points.
|
||||||
|
|
||||||
|
data.set_row_unsafe(begin_row);
|
||||||
|
for (int j = begin_row; j < end_row; ++j) {
|
||||||
|
LPoint3 vertex = data.get_data3();
|
||||||
|
data.set_data3(vertex * mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexData::do_transform_vector_column
|
||||||
|
// Access: Private
|
||||||
|
// Description: Transforms a range of vertices for one particular
|
||||||
|
// column, as a vector.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void GeomVertexData::
|
||||||
|
do_transform_vector_column(const GeomVertexFormat *format, GeomVertexRewriter &data,
|
||||||
|
const LMatrix4 &mat, int begin_row, int end_row) {
|
||||||
|
const GeomVertexColumn *data_column = data.get_column();
|
||||||
|
|
||||||
|
if (data_column->get_num_values() == 3 &&
|
||||||
|
data_column->get_numeric_type() == NT_float32) {
|
||||||
|
// The table of vectors is a table of LVector3f's. Optimize this
|
||||||
|
// common case.
|
||||||
|
PT(GeomVertexArrayDataHandle) data_handle = data.get_array_handle();
|
||||||
|
PT(GeomVertexArrayData) data_array = data_handle->get_object();
|
||||||
|
|
||||||
|
unsigned char *datat = data_handle->get_write_pointer();
|
||||||
|
datat += data_column->get_start();
|
||||||
|
size_t stride = data_array->get_array_format()->get_stride();
|
||||||
|
|
||||||
|
LMatrix4f matf = LCAST(float, mat);
|
||||||
|
for (int j = begin_row; j < end_row; ++j) {
|
||||||
|
LVector3f &vector = *(LVector3f *)(&datat[j * stride]);
|
||||||
|
vector = vector * matf;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Use the GeomVertexRewriter to transform the vectors.
|
||||||
|
|
||||||
|
data.set_row_unsafe(begin_row);
|
||||||
|
for (int j = begin_row; j < end_row; ++j) {
|
||||||
|
LVector3 vertex = data.get_data3();
|
||||||
|
data.set_data3(vertex * mat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
|
|
||||||
class FactoryParams;
|
class FactoryParams;
|
||||||
class GeomVertexColumn;
|
class GeomVertexColumn;
|
||||||
|
class GeomVertexRewriter;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : GeomVertexData
|
// Class : GeomVertexData
|
||||||
@ -152,6 +153,8 @@ PUBLISHED:
|
|||||||
|
|
||||||
CPT(GeomVertexData) animate_vertices(bool force, Thread *current_thread) const;
|
CPT(GeomVertexData) animate_vertices(bool force, Thread *current_thread) const;
|
||||||
void clear_animated_vertices();
|
void clear_animated_vertices();
|
||||||
|
void transform_vertices(const LMatrix4 &mat);
|
||||||
|
void transform_vertices(const LMatrix4 &mat, int begin_row, int end_row);
|
||||||
|
|
||||||
PT(GeomVertexData)
|
PT(GeomVertexData)
|
||||||
replace_column(InternalName *name, int num_components,
|
replace_column(InternalName *name, int num_components,
|
||||||
@ -315,6 +318,10 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void update_animated_vertices(CData *cdata, Thread *current_thread);
|
void update_animated_vertices(CData *cdata, Thread *current_thread);
|
||||||
|
void do_transform_point_column(const GeomVertexFormat *format, GeomVertexRewriter &data,
|
||||||
|
const LMatrix4 &mat, int begin_row, int end_row);
|
||||||
|
void do_transform_vector_column(const GeomVertexFormat *format, GeomVertexRewriter &data,
|
||||||
|
const LMatrix4 &mat, int begin_row, int end_row);
|
||||||
|
|
||||||
static PStatCollector _convert_pcollector;
|
static PStatCollector _convert_pcollector;
|
||||||
static PStatCollector _scale_color_pcollector;
|
static PStatCollector _scale_color_pcollector;
|
||||||
|
@ -206,6 +206,18 @@ get_array_data() const {
|
|||||||
return _array_data;
|
return _array_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexReader::get_array_handle
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the read handle to the array object that the
|
||||||
|
// read is currently processing. This low-level call
|
||||||
|
// should be used with caution.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE const GeomVertexArrayDataHandle *GeomVertexReader::
|
||||||
|
get_array_handle() const {
|
||||||
|
return _handle;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexReader::get_current_thread
|
// Function: GeomVertexReader::get_current_thread
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -82,6 +82,7 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE const GeomVertexData *get_vertex_data() const;
|
INLINE const GeomVertexData *get_vertex_data() const;
|
||||||
INLINE const GeomVertexArrayData *get_array_data() const;
|
INLINE const GeomVertexArrayData *get_array_data() const;
|
||||||
|
INLINE const GeomVertexArrayDataHandle *get_array_handle() const;
|
||||||
INLINE Thread *get_current_thread() const;
|
INLINE Thread *get_current_thread() const;
|
||||||
|
|
||||||
INLINE void set_force(bool force);
|
INLINE void set_force(bool force);
|
||||||
|
@ -159,6 +159,20 @@ get_array_data() const {
|
|||||||
return GeomVertexWriter::get_array_data();
|
return GeomVertexWriter::get_array_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexRewriter::get_array_handle
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the write handle to the array object that the
|
||||||
|
// rewriter is currently processing. This low-level call
|
||||||
|
// should be used with caution; be careful with
|
||||||
|
// modifying the data in the handle out from under the
|
||||||
|
// GeomVertexRewriter.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE GeomVertexArrayDataHandle *GeomVertexRewriter::
|
||||||
|
get_array_handle() const {
|
||||||
|
return GeomVertexWriter::get_array_handle();
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexRewriter::set_column
|
// Function: GeomVertexRewriter::set_column
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -53,6 +53,7 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE GeomVertexData *get_vertex_data() const;
|
INLINE GeomVertexData *get_vertex_data() const;
|
||||||
INLINE GeomVertexArrayData *get_array_data() const;
|
INLINE GeomVertexArrayData *get_array_data() const;
|
||||||
|
INLINE GeomVertexArrayDataHandle *get_array_handle() const;
|
||||||
|
|
||||||
INLINE bool set_column(int column);
|
INLINE bool set_column(int column);
|
||||||
INLINE bool set_column(const string &name);
|
INLINE bool set_column(const string &name);
|
||||||
|
@ -201,6 +201,20 @@ get_array_data() const {
|
|||||||
return _array_data;
|
return _array_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexWriter::get_array_handle
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the write handle to the array object that the
|
||||||
|
// writer is currently processing. This low-level call
|
||||||
|
// should be used with caution; be careful with
|
||||||
|
// modifying the data in the handle out from under the
|
||||||
|
// GeomVertexWriter.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE GeomVertexArrayDataHandle *GeomVertexWriter::
|
||||||
|
get_array_handle() const {
|
||||||
|
return _handle;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexWriter::get_current_thread
|
// Function: GeomVertexWriter::get_current_thread
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -94,6 +94,7 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE GeomVertexData *get_vertex_data() const;
|
INLINE GeomVertexData *get_vertex_data() const;
|
||||||
INLINE GeomVertexArrayData *get_array_data() const;
|
INLINE GeomVertexArrayData *get_array_data() const;
|
||||||
|
INLINE GeomVertexArrayDataHandle *get_array_handle() const;
|
||||||
INLINE Thread *get_current_thread() const;
|
INLINE Thread *get_current_thread() const;
|
||||||
|
|
||||||
INLINE bool set_column(int column);
|
INLINE bool set_column(int column);
|
||||||
|
@ -79,7 +79,7 @@ add_transform(const VertexTransform *transform, PN_stdfloat weight) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TransformBlend::remove_transform
|
// Function: TransformBlend::remove_transform
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Removes the indicated transform to the blend.
|
// Description: Removes the indicated transform from the blend.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void TransformBlend::
|
void TransformBlend::
|
||||||
remove_transform(const VertexTransform *transform) {
|
remove_transform(const VertexTransform *transform) {
|
||||||
@ -94,6 +94,38 @@ remove_transform(const VertexTransform *transform) {
|
|||||||
clear_result(current_thread);
|
clear_result(current_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TransformBlend::limit_transforms
|
||||||
|
// Access: Published
|
||||||
|
// Description: If the total number of transforms in the blend
|
||||||
|
// exceeds max_transforms, removes the n least-important
|
||||||
|
// transforms as needed to reduce the number of
|
||||||
|
// transforms to max_transforms.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TransformBlend::
|
||||||
|
limit_transforms(int max_transforms) {
|
||||||
|
if (max_transforms <= 0) {
|
||||||
|
_entries.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (_entries.size() > max_transforms) {
|
||||||
|
// Repeatedly find and remove the least-important transform.
|
||||||
|
nassertv(!_entries.empty());
|
||||||
|
Entries::iterator ei_least = _entries.begin();
|
||||||
|
Entries::iterator ei = ei_least;
|
||||||
|
++ei;
|
||||||
|
while (ei != _entries.end()) {
|
||||||
|
if ((*ei)._weight < (*ei_least)._weight) {
|
||||||
|
ei_least = ei;
|
||||||
|
}
|
||||||
|
++ei;
|
||||||
|
}
|
||||||
|
|
||||||
|
_entries.erase(ei_least);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TransformBlend::normalize_weights
|
// Function: TransformBlend::normalize_weights
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -57,6 +57,7 @@ PUBLISHED:
|
|||||||
|
|
||||||
void add_transform(const VertexTransform *transform, PN_stdfloat weight);
|
void add_transform(const VertexTransform *transform, PN_stdfloat weight);
|
||||||
void remove_transform(const VertexTransform *transform);
|
void remove_transform(const VertexTransform *transform);
|
||||||
|
void limit_transforms(int max_transforms);
|
||||||
void normalize_weights();
|
void normalize_weights();
|
||||||
bool has_transform(const VertexTransform *transform) const;
|
bool has_transform(const VertexTransform *transform) const;
|
||||||
PN_stdfloat get_weight(const VertexTransform *transform) const;
|
PN_stdfloat get_weight(const VertexTransform *transform) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user