animation optimization

This commit is contained in:
David Rose 2008-09-03 20:00:21 +00:00
parent 1959cc2fb9
commit b515eea911

View File

@ -1339,9 +1339,10 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
PStatTimer timer(_char_pcollector, current_thread); PStatTimer timer(_char_pcollector, current_thread);
const GeomVertexFormat *orig_format = cdata->_format; const GeomVertexFormat *orig_format = cdata->_format;
CPT(GeomVertexFormat) new_format = orig_format;
if (cdata->_animated_vertices == (GeomVertexData *)NULL) { if (cdata->_animated_vertices == (GeomVertexData *)NULL) {
CPT(GeomVertexFormat) new_format = orig_format->get_post_animated_format(); new_format = orig_format->get_post_animated_format();
cdata->_animated_vertices = cdata->_animated_vertices =
new GeomVertexData(get_name(), new_format, new GeomVertexData(get_name(), new_format,
min(get_usage_hint(), UH_dynamic)); min(get_usage_hint(), UH_dynamic));
@ -1452,61 +1453,179 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
} }
// Now go through and apply the transforms. // Now go through and apply the transforms.
GeomVertexReader blendi(this, InternalName::get_transform_blend());
if (!blendi.has_column()) { const SparseArray &rows = tb_table->get_rows();
int num_subranges = rows.get_num_subranges();
int blend_array_index = orig_format->get_array_with(InternalName::get_transform_blend());
if (blend_array_index < 0) {
gobj_cat.warning() gobj_cat.warning()
<< "Vertex data " << get_name() << "Vertex data " << get_name()
<< " has a transform_blend_table, but no transform_blend data.\n"; << " has a transform_blend_table, but no transform_blend data.\n";
return; return;
} }
const SparseArray &rows = tb_table->get_rows(); CPT(GeomVertexArrayFormat) blend_array_format = orig_format->get_array(blend_array_index);
int num_subranges = rows.get_num_subranges();
int ci; if (blend_array_format->get_num_columns() == 1 &&
for (ci = 0; ci < orig_format->get_num_points(); ci++) { blend_array_format->get_stride() == 2 &&
GeomVertexRewriter data(new_data, orig_format->get_point(ci)); blend_array_format->get_column(0)->get_component_bytes() == 2) {
// The blend indices are a table of ushorts. Optimize this
if (data.get_column()->get_num_values() == 4) { // common case.
for (int i = 0; i < num_subranges; ++i) { CPT(GeomVertexArrayDataHandle) blend_array_handle = cdata->_arrays[blend_array_index].get_read_pointer()->get_handle(current_thread);
int begin = rows.get_subrange_begin(i); const unsigned short *blendt = (const unsigned short *)blend_array_handle->get_read_pointer(true);
int end = rows.get_subrange_end(i);
data.set_row(begin); int ci;
blendi.set_row(begin); for (ci = 0; ci < new_format->get_num_points(); ci++) {
for (int j = begin; j < end; ++j) { GeomVertexRewriter data(new_data, new_format->get_point(ci));
LPoint4f vertex = data.get_data4f(); const GeomVertexColumn *data_column = data.get_column();
int bi = blendi.get_data1i(); if (data_column->get_num_values() == 3 &&
tb_table->get_blend(bi).transform_point(vertex, current_thread); data_column->get_numeric_type() == NT_float32) {
data.set_data4f(vertex); // 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) {
int begin = rows.get_subrange_begin(i);
int end = rows.get_subrange_end(i);
for (int j = begin; j < end; ++j) {
LPoint3f &vertex = *(LPoint3f *)(&datat[j * stride]);
int bi = blendt[j];
tb_table->get_blend(bi).transform_point(vertex, current_thread);
}
} }
}
} else { } else if (data_column->get_num_values() == 4) {
for (int i = 0; i < num_subranges; ++i) { // Use the GeomVertexRewriter to adjust the 4-component
int begin = rows.get_subrange_begin(i); // points.
int end = rows.get_subrange_end(i); for (int i = 0; i < num_subranges; ++i) {
data.set_row(begin); int begin = rows.get_subrange_begin(i);
blendi.set_row(begin); int end = rows.get_subrange_end(i);
for (int j = begin; j < end; ++j) { data.set_row(begin);
LPoint3f vertex = data.get_data3f(); for (int j = begin; j < end; ++j) {
int bi = blendi.get_data1i(); LPoint4f vertex = data.get_data4f();
tb_table->get_blend(bi).transform_point(vertex, current_thread); int bi = blendt[j];
data.set_data3f(vertex); tb_table->get_blend(bi).transform_point(vertex, current_thread);
data.set_data4f(vertex);
}
}
} else {
// Use the GeomVertexRewriter to adjust the 3-component
// 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(begin);
for (int j = begin; j < end; ++j) {
LPoint3f vertex = data.get_data3f();
int bi = blendt[j];
tb_table->get_blend(bi).transform_point(vertex, current_thread);
data.set_data3f(vertex);
}
} }
} }
} }
}
for (ci = 0; ci < orig_format->get_num_vectors(); ci++) { // Also process vectors: normals, etc.
GeomVertexRewriter data(new_data, orig_format->get_vector(ci)); for (ci = 0; ci < new_format->get_num_vectors(); ci++) {
for (int i = 0; i < num_subranges; ++i) { GeomVertexRewriter data(new_data, new_format->get_vector(ci));
int begin = rows.get_subrange_begin(i); const GeomVertexColumn *data_column = data.get_column();
int end = rows.get_subrange_end(i); if (data_column->get_num_values() == 3 &&
data.set_row(begin); data_column->get_numeric_type() == NT_float32) {
blendi.set_row(begin); // Table of vectors is a table of LVector3f's. Optimize this
for (int j = begin; j < end; ++j) { // common case.
LVector3f vertex = data.get_data3f(); int data_index = new_format->get_array_with(new_format->get_point(ci));
int bi = blendi.get_data1i(); PT(GeomVertexArrayData) data_array = new_data->modify_array(data_index);
tb_table->get_blend(bi).transform_vector(vertex, current_thread); PT(GeomVertexArrayDataHandle) data_handle = data_array->modify_handle();
data.set_data3f(vertex); 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) {
int begin = rows.get_subrange_begin(i);
int end = rows.get_subrange_end(i);
for (int j = begin; j < end; ++j) {
LVector3f &vertex = *(LVector3f *)(&datat[j * stride]);
int bi = blendt[j];
tb_table->get_blend(bi).transform_vector(vertex, current_thread);
}
}
} else {
// Use the GeomVertexRewriter to adjust the vectors.
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(begin);
for (int j = begin; j < end; ++j) {
LVector3f vertex = data.get_data3f();
int bi = blendt[j];
tb_table->get_blend(bi).transform_vector(vertex, current_thread);
data.set_data3f(vertex);
}
}
}
}
} else {
// The blend indices are anything else. Use the
// GeomVertexReader to iterate through them.
GeomVertexReader blendi(this, InternalName::get_transform_blend());
nassertv(blendi.has_column());
int ci;
for (ci = 0; ci < new_format->get_num_points(); 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(begin);
blendi.set_row(begin);
for (int j = begin; j < end; ++j) {
LPoint4f vertex = data.get_data4f();
int bi = blendi.get_data1i();
tb_table->get_blend(bi).transform_point(vertex, current_thread);
data.set_data4f(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(begin);
blendi.set_row(begin);
for (int j = begin; j < end; ++j) {
LPoint3f vertex = data.get_data3f();
int bi = blendi.get_data1i();
tb_table->get_blend(bi).transform_point(vertex, current_thread);
data.set_data3f(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) {
int begin = rows.get_subrange_begin(i);
int end = rows.get_subrange_end(i);
data.set_row(begin);
blendi.set_row(begin);
for (int j = begin; j < end; ++j) {
LVector3f vertex = data.get_data3f();
int bi = blendi.get_data1i();
tb_table->get_blend(bi).transform_vector(vertex, current_thread);
data.set_data3f(vertex);
}
} }
} }
} }