15 #include "geomVertexData.h"
17 #include "geomVertexReader.h"
18 #include "geomVertexWriter.h"
19 #include "geomVertexRewriter.h"
20 #include "pStatTimer.h"
21 #include "bamReader.h"
22 #include "bamWriter.h"
27 TypeHandle GeomVertexData::CDataCache::_type_handle;
28 TypeHandle GeomVertexData::CacheEntry::_type_handle;
29 TypeHandle GeomVertexData::CData::_type_handle;
30 TypeHandle GeomVertexDataPipelineReader::_type_handle;
31 TypeHandle GeomVertexDataPipelineWriter::_type_handle;
33 PStatCollector GeomVertexData::_convert_pcollector(
"*:Munge:Convert");
34 PStatCollector GeomVertexData::_scale_color_pcollector(
"*:Munge:Scale color");
35 PStatCollector GeomVertexData::_set_color_pcollector(
"*:Munge:Set color");
36 PStatCollector GeomVertexData::_animation_pcollector(
"*:Animation");
47 _char_pcollector(_animation_pcollector,
"unnamed"),
48 _skinning_pcollector(_char_pcollector,
"Skinning"),
49 _morphs_pcollector(_char_pcollector,
"Morphs"),
50 _blends_pcollector(_char_pcollector,
"Calc blends")
70 GeomVertexData(
const string &name,
71 const GeomVertexFormat *format,
72 GeomVertexData::UsageHint usage_hint) :
75 _skinning_pcollector(_char_pcollector,
"Skinning"),
76 _morphs_pcollector(_char_pcollector,
"Morphs"),
77 _blends_pcollector(_char_pcollector,
"Calc blends")
79 nassertv(format->is_registered());
83 OPEN_ITERATE_ALL_STAGES(_cycler) {
84 CDStageWriter cdata(_cycler, pipeline_stage);
85 cdata->_format = format;
86 cdata->_usage_hint = usage_hint;
87 int num_arrays = format->get_num_arrays();
88 for (
int i = 0; i < num_arrays; i++) {
91 cdata->_arrays.push_back(array.p());
94 CLOSE_ITERATE_ALL_STAGES(_cycler);
106 _cycler(copy._cycler),
107 _char_pcollector(copy._char_pcollector),
108 _skinning_pcollector(copy._skinning_pcollector),
109 _morphs_pcollector(copy._morphs_pcollector),
110 _blends_pcollector(copy._blends_pcollector)
112 OPEN_ITERATE_ALL_STAGES(_cycler) {
113 CDStageWriter cdata(_cycler, pipeline_stage);
115 cdata->_animated_vertices = NULL;
116 cdata->_animated_vertices_modified =
UpdateSeq();
118 CLOSE_ITERATE_ALL_STAGES(_cycler);
131 const GeomVertexFormat *format) :
134 _cycler(copy._cycler),
135 _char_pcollector(copy._char_pcollector),
136 _skinning_pcollector(copy._skinning_pcollector),
137 _morphs_pcollector(copy._morphs_pcollector),
138 _blends_pcollector(copy._blends_pcollector)
140 nassertv(format->is_registered());
143 OPEN_ITERATE_ALL_STAGES(_cycler) {
146 UsageHint usage_hint = cdata->_usage_hint;
147 cdata->_arrays.clear();
148 cdata->_format = format;
149 int num_arrays = format->get_num_arrays();
150 for (
int i = 0; i < num_arrays; i++) {
152 (format->get_array(i), usage_hint);
153 cdata->_arrays.push_back(array.p());
157 cdata->_animated_vertices = NULL;
158 cdata->_animated_vertices_modified =
UpdateSeq();
160 CLOSE_ITERATE_ALL_STAGES(_cycler);
173 CopyOnWriteObject::operator = (copy);
178 _cycler = copy._cycler;
179 _char_pcollector = copy._char_pcollector;
180 _skinning_pcollector = copy._skinning_pcollector;
181 _morphs_pcollector = copy._morphs_pcollector;
182 _blends_pcollector = copy._blends_pcollector;
184 OPEN_ITERATE_ALL_STAGES(_cycler) {
187 cdata->_animated_vertices = NULL;
188 cdata->_animated_vertices_modified =
UpdateSeq();
190 CLOSE_ITERATE_ALL_STAGES(_cycler);
212 CDReader other_cdata(other._cycler);
214 if (cdata->_usage_hint != other_cdata->_usage_hint) {
215 return (
int)cdata->_usage_hint - (int)other_cdata->_usage_hint;
217 if (cdata->_format != other_cdata->_format) {
218 return cdata->_format < other_cdata->_format ? -1 : 1;
220 if (cdata->_transform_table != other_cdata->_transform_table) {
221 return cdata->_transform_table < other_cdata->_transform_table ? -1 : 1;
223 if (cdata->_transform_blend_table != other_cdata->_transform_blend_table) {
224 return cdata->_transform_blend_table < other_cdata->_transform_blend_table ? -1 : 1;
226 if (cdata->_slider_table != other_cdata->_slider_table) {
227 return cdata->_slider_table < other_cdata->_slider_table ? -1 : 1;
229 if (cdata->_arrays.size() != other_cdata->_arrays.size()) {
230 return (
int)cdata->_arrays.size() - (int)other_cdata->_arrays.size();
232 for (
size_t i = 0; i < cdata->_arrays.size(); ++i) {
233 if (cdata->_arrays[i] != other_cdata->_arrays[i]) {
234 return cdata->_arrays[i] < other_cdata->_arrays[i] ? -1 : 1;
251 _skinning_pcollector =
PStatCollector(_char_pcollector,
"Skinning");
253 _blends_pcollector =
PStatCollector(_char_pcollector,
"Calc blends");
270 cdata->_usage_hint = usage_hint;
273 for (ai = cdata->_arrays.begin();
274 ai != cdata->_arrays.end();
277 array_obj->set_usage_hint(usage_hint);
281 cdata->_animated_vertices_modified =
UpdateSeq();
298 nassertv(format->is_registered());
302 if (format == cdata->_format) {
307 CDWriter cdataw(_cycler, cdata,
true);
314 cdataw->_format = format;
316 UsageHint usage_hint = cdataw->_usage_hint;
317 cdataw->_arrays.clear();
318 int num_arrays = cdataw->_format->get_num_arrays();
319 for (
int i = 0; i < num_arrays; i++) {
321 (cdataw->_format->get_array(i), usage_hint);
322 cdataw->_arrays.push_back(array.p());
327 copy_from(orig_data,
false, current_thread);
331 cdataw->_animated_vertices.clear();
350 nassertv(format->is_registered());
354 if (format == cdata->_format) {
360 nassertv(format->get_num_arrays() == cdata->_format->get_num_arrays());
361 for (
int ai = 0; ai < format->get_num_arrays(); ++ai) {
362 nassertv(format->get_array(ai)->get_stride() == cdata->_format->get_array(ai)->get_stride());
364 nassertv(cdata->_arrays.size() == cdata->_format->get_num_arrays());
367 CDWriter cdataw(_cycler, cdata,
true);
370 cdataw->_format = format;
372 for (
size_t ai = 0; ai < cdataw->_arrays.size(); ++ai) {
374 array_obj->_array_format = format->get_array(ai);
379 cdataw->_animated_vertices.clear();
396 CDWriter cdata(_cycler,
true, current_thread);
397 nassertv(cdata->_format->get_num_arrays() == (int)cdata->_arrays.size());
400 for (ai = cdata->_arrays.begin();
401 ai != cdata->_arrays.end();
404 array_obj->clear_rows();
408 cdata->_animated_vertices.clear();
429 CDWriter cdata(_cycler,
true, current_thread);
433 cdata->_animated_vertices_modified =
UpdateSeq();
449 modify_transform_blend_table() {
450 CDWriter cdata(_cycler,
true);
454 cdata->_animated_vertices_modified =
UpdateSeq();
456 return cdata->_transform_blend_table.get_write_pointer();
478 cdata->_animated_vertices_modified =
UpdateSeq();
504 cdata->_animated_vertices_modified =
UpdateSeq();
518 bool resident =
true;
520 Arrays::const_iterator ai;
521 for (ai = cdata->_arrays.begin();
522 ai != cdata->_arrays.end();
524 if (!(*ai).get_read_pointer()->request_resident()) {
555 const GeomVertexFormat *source_format = source->
get_format();
556 const GeomVertexFormat *dest_format =
get_format();
559 int num_arrays = source_format->get_num_arrays();
566 for (source_i = 0; source_i < num_arrays; ++source_i) {
567 const GeomVertexArrayFormat *source_array_format =
568 source_format->get_array(source_i);
570 bool array_done =
false;
572 int dest_num_arrays = dest_format->get_num_arrays();
574 dest_i < dest_num_arrays && !array_done;
576 const GeomVertexArrayFormat *dest_array_format =
577 dest_format->get_array(dest_i);
578 if (dest_array_format->is_data_subset_of(*source_array_format)) {
580 if (keep_data_objects) {
585 dest_data->modify_handle()->copy_data_from(source_data->get_handle());
588 if (
get_array(dest_i) != source->get_array(source_i)) {
589 set_array(dest_i, source->get_array(source_i));
594 done_arrays.insert(dest_i);
604 for (source_i = 0; source_i < num_arrays; ++source_i) {
607 const unsigned char *array_data = array_handle->get_read_pointer(
true);
608 const GeomVertexArrayFormat *source_array_format = source_format->get_array(source_i);
609 int num_columns = source_array_format->get_num_columns();
610 for (
int di = 0; di < num_columns; ++di) {
611 const GeomVertexColumn *source_column = source_array_format->get_column(di);
613 int dest_i = dest_format->get_array_with(source_column->
get_name());
614 if (dest_i >= 0 && done_arrays.count(dest_i) == 0) {
616 const GeomVertexArrayFormat *dest_array_format =
617 dest_format->get_array(dest_i);
619 dest_array_format->get_column(source_column->
get_name());
626 unsigned char *dest_array_data = dest_handle->get_write_pointer();
628 bytewise_copy(dest_array_data + dest_column->
get_start(),
629 dest_array_format->get_stride(),
630 array_data + source_column->
get_start(), source_array_format->get_stride(),
631 source_column, num_rows);
638 unsigned char *dest_array_data = dest_handle->get_write_pointer();
640 uint8_rgba_to_packed_argb
641 (dest_array_data + dest_column->
get_start(),
642 dest_array_format->get_stride(),
643 array_data + source_column->
get_start(), source_array_format->get_stride(),
652 unsigned char *dest_array_data = dest_handle->get_write_pointer();
654 packed_argb_to_uint8_rgba
655 (dest_array_data + dest_column->
get_start(),
656 dest_array_format->get_stride(),
657 array_data + source_column->
get_start(), source_array_format->get_stride(),
662 if (gobj_cat.is_debug()) {
664 <<
"generic copy " << *dest_column <<
" from "
665 << *source_column <<
"\n";
683 if (source_animation != dest_animation) {
707 indices[i] = add_transform(transform_table, blend.
get_transform(i),
726 int index = add_transform(transform_table, blend.
get_transform(i),
728 nassertv(index <= 4);
758 int source_row,
Thread *current_thread) {
759 const GeomVertexFormat *source_format = source->
get_format();
760 const GeomVertexFormat *dest_format =
get_format();
761 nassertv(source_format == dest_format);
762 nassertv(source_row >= 0 && source_row < source->
get_num_rows());
769 int num_arrays = source_format->get_num_arrays();
771 for (
int i = 0; i < num_arrays; ++i) {
774 unsigned char *dest_array_data = dest_handle->get_write_pointer();
778 const unsigned char *source_array_data = source_array_handle->get_read_pointer(
true);
780 const GeomVertexArrayFormat *array_format = source_format->get_array(i);
781 int stride = array_format->get_stride();
783 memcpy(dest_array_data + stride * dest_row,
784 source_array_data + stride * source_row,
797 convert_to(const GeomVertexFormat *new_format)
const {
800 if (new_format == get_format()) {
807 PT(CacheEntry) entry;
809 CacheKey key(new_format);
811 _cache_lock.acquire();
812 Cache::const_iterator ci = _cache.find(&key);
813 if (ci == _cache.end()) {
814 _cache_lock.release();
817 entry = (*ci).second;
818 _cache_lock.release();
819 nassertr(entry->_source ==
this, NULL);
824 entry->refresh(current_thread);
826 CDCacheReader cdata(entry->_cycler);
828 return cdata->_result;
838 if (gobj_cat.is_debug()) {
840 <<
"Converting " << get_num_rows() <<
" rows from " << *get_format()
841 <<
" to " << *new_format <<
"\n";
847 new_data->set_transform_blend_table(get_transform_blend_table());
848 new_data->set_slider_table(get_slider_table());
850 new_data->copy_from(this, false);
853 if (entry == (CacheEntry *)NULL) {
855 #ifdef USE_MOVE_SEMANTICS
863 bool inserted = ((
GeomVertexData *)
this)->_cache.insert(Cache::value_type(&entry->_key, entry)).second;
874 entry->record(current_thread);
878 CDCacheWriter cdata(entry->_cycler,
true, current_thread);
879 cdata->_result = new_data;
894 scale_color(const
LVecBase4 &color_scale)
const {
896 get_format()->get_column(InternalName::get_color());
905 data.set_data4(color[0] * color_scale[0],
906 color[1] * color_scale[1],
907 color[2] * color_scale[2],
908 color[3] * color_scale[3]);
925 scale_color(const
LVecBase4 &color_scale,
int num_components,
928 int old_color_array = get_format()->get_array_with(InternalName::get_color());
929 if (old_color_array == -1) {
931 return set_color(color_scale, num_components, numeric_type, contents);
934 int num_rows = get_num_rows();
936 if (gobj_cat.is_debug()) {
938 <<
"Scaling color for " << num_rows <<
" vertices by "
939 << color_scale <<
".\n";
944 (InternalName::get_color(), num_components, numeric_type, contents);
950 for (
int i = 0; i < num_rows; i++) {
951 LColor color = from.get_data4();
953 color[1] * color_scale[1],
954 color[2] * color_scale[2],
955 color[3] * color_scale[3]);
971 set_color(const
LColor &color)
const {
973 get_format()->get_column(InternalName::get_color());
980 while (!to.is_at_end()) {
998 set_color(const
LColor &color,
int num_components,
1001 if (gobj_cat.is_debug()) {
1003 <<
"Setting color for " << get_num_rows() <<
" vertices to "
1009 (InternalName::get_color(), num_components, numeric_type, contents);
1013 while (!to.is_at_end()) {
1032 reverse_normals()
const {
1034 get_format()->get_column(InternalName::get_normal());
1041 while (!to.is_at_end()) {
1073 animate_vertices(
bool force,
Thread *current_thread)
const {
1074 #ifdef DO_PIPELINING
1079 CDReader cdata(_cycler, current_thread);
1080 if (cdata->_format->get_animation().get_animation_type() != AT_panda) {
1084 #endif // DO_PIPELINING
1091 CDLockedReader cdata(_cycler, current_thread);
1092 if (cdata->_format->get_animation().get_animation_type() != AT_panda) {
1099 if (!cdata->_transform_blend_table.is_null()) {
1100 if (cdata->_slider_table != (
SliderTable *)NULL) {
1102 max(cdata->_transform_blend_table.get_read_pointer()->get_modified(current_thread),
1103 cdata->_slider_table->get_modified(current_thread));
1105 modified = cdata->_transform_blend_table.get_read_pointer()->get_modified(current_thread);
1108 }
else if (cdata->_slider_table != (
SliderTable *)NULL) {
1109 modified = cdata->_slider_table->get_modified(current_thread);
1118 if (cdata->_animated_vertices_modified == modified &&
1121 return cdata->_animated_vertices;
1124 if (!force && !request_resident()) {
1128 return cdata->_animated_vertices;
1133 CDWriter cdataw(((
GeomVertexData *)
this)->_cycler, cdata,
false);
1134 cdataw->_animated_vertices_modified = modified;
1135 ((
GeomVertexData *)
this)->update_animated_vertices(cdataw, current_thread);
1137 return cdataw->_animated_vertices;
1152 cdata->_animated_vertices_modified.clear();
1153 cdata->_animated_vertices.clear();
1180 if (end_row <= begin_row) {
1185 const GeomVertexFormat *format =
get_format();
1188 for (ci = 0; ci < format->get_num_points(); ci++) {
1190 do_transform_point_column(format, data, mat, begin_row, end_row);
1193 for (ci = 0; ci < format->get_num_vectors(); ci++) {
1195 do_transform_vector_column(format, data, mat, begin_row, end_row);
1204 void GeomVertexData::
1205 bytewise_copy(
unsigned char *to,
int to_stride,
1206 const unsigned char *from,
int from_stride,
1209 if (gobj_cat.is_debug()) {
1211 <<
"bytewise_copy(" << (
void *)to <<
", " << to_stride
1212 <<
", " << (
const void *)from <<
", " << from_stride
1213 <<
", " << *from_type <<
", " << num_records <<
")\n";
1224 while (num_records > 0) {
1227 from += from_stride;
1248 replace_column(InternalName *name,
int num_components,
1251 CDReader cdata(_cycler);
1252 PT(GeomVertexFormat) new_format = new GeomVertexFormat(*cdata->_format);
1255 bool removed_type_array = false;
1256 int old_type_array = cdata->_format->get_array_with(name);
1257 if (old_type_array != -1) {
1258 GeomVertexArrayFormat *array_format = new_format->modify_array(old_type_array);
1259 if (array_format->get_num_columns() == 1) {
1262 new_format->remove_array(old_type_array);
1263 removed_type_array =
true;
1268 array_format->remove_column(name);
1273 int new_type_array = -1;
1274 if (num_components != 0) {
1275 PT(GeomVertexArrayFormat) type_array_format =
1276 new GeomVertexArrayFormat(name, num_components, numeric_type, contents);
1277 new_type_array = new_format->add_array(type_array_format);
1280 CPT(GeomVertexFormat) format =
1281 GeomVertexFormat::register_format(new_format);
1283 if (gobj_cat.is_debug()) {
1285 <<
"Replacing data type " << *name <<
"; converting "
1286 << get_num_rows() <<
" rows from "
1287 << *cdata->_format <<
" to " << *format <<
"\n";
1293 int num_arrays = get_num_arrays();
1294 for (
int i = 0; i < num_arrays; ++i) {
1295 if (i == old_type_array) {
1296 if (!removed_type_array) {
1310 if (new_type_array != -1) {
1311 nassertr(j == new_type_array, new_data);
1316 (format->
get_array(j), get_usage_hint());
1317 new_array->set_num_rows(get_num_rows());
1318 new_data->set_array(j, new_array);
1330 output(ostream &out)
const {
1331 if (!get_name().empty()) {
1332 out << get_name() <<
" ";
1334 out << get_num_rows() <<
" rows: " << *get_format();
1342 void GeomVertexData::
1343 write(ostream &out,
int indent_level)
const {
1345 indent(out, indent_level) <<
get_name() <<
"\n";
1347 get_format()->write_with_data(out, indent_level + 2,
this);
1350 indent(out, indent_level)
1351 <<
"Transform blend table:\n";
1352 table->write(out, indent_level + 2);
1366 out <<
"Vertex " << row <<
":\n";
1370 const GeomVertexFormat *format =
get_format();
1373 if (format->get_animation().get_animation_type() == AT_panda) {
1374 tb_table = get_transform_blend_table();
1377 int num_columns = format->get_num_columns();
1378 for (
int ci = 0; ci < num_columns; ++ci) {
1379 int ai = format->get_array_with(ci);
1387 for (
int v = 0; v < num_values; v++) {
1392 if (column->
get_name() == InternalName::get_transform_blend() &&
1398 if (bi >= 0 && bi < tb_table->get_num_blends()) {
1400 out <<
" " << blend <<
"\n";
1406 out <<
"\nraw data:\n";
1407 int num_arrays = format->get_num_arrays();
1408 for (
int ai = 0; ai < num_arrays; ++ai) {
1410 const GeomVertexArrayFormat *aformat = format->get_array(ai);
1411 nassertv(array != NULL && aformat != NULL);
1412 out <<
" " << *aformat <<
"\n";
1415 const unsigned char *data = handle->get_read_pointer(
true);
1416 nassertv(data != NULL);
1417 int stride = aformat->get_stride();
1418 int start = stride * row;
1440 for (Cache::iterator ci = _cache.begin();
1463 for (Cache::iterator ci = _cache.begin();
1468 cdata->_result = NULL;
1478 void GeomVertexData::
1479 packed_argb_to_uint8_rgba(
unsigned char *to,
int to_stride,
1480 const unsigned char *from,
int from_stride,
1482 if (gobj_cat.is_debug()) {
1484 <<
"packed_argb_to_uint8_rgba(" << (
void *)to <<
", " << to_stride
1485 <<
", " << (
const void *)from <<
", " << from_stride
1486 <<
", " << num_records <<
")\n";
1489 while (num_records > 0) {
1490 PN_uint32 dword = *(
const PN_uint32 *)from;
1497 from += from_stride;
1508 void GeomVertexData::
1509 uint8_rgba_to_packed_argb(
unsigned char *to,
int to_stride,
1510 const unsigned char *from,
int from_stride,
1512 if (gobj_cat.is_debug()) {
1514 <<
"uint8_rgba_to_packed_argb(" << (
void *)to <<
", " << to_stride
1515 <<
", " << (
const void *)from <<
", " << from_stride
1516 <<
", " << num_records <<
")\n";
1519 while (num_records > 0) {
1520 *(PN_uint32 *)to =
pack_abcd(from[3], from[0], from[1], from[2]);
1523 from += from_stride;
1535 void GeomVertexData::
1536 update_animated_vertices(GeomVertexData::CData *cdata,
Thread *current_thread) {
1537 PStatTimer timer(_char_pcollector, current_thread);
1541 if (gobj_cat.is_debug()) {
1543 <<
"Animating " << num_rows <<
" vertices for " <<
get_name()
1547 const GeomVertexFormat *orig_format = cdata->_format;
1548 CPT(GeomVertexFormat) new_format = orig_format;
1551 new_format = orig_format->get_post_animated_format();
1552 cdata->_animated_vertices =
1566 CPT(
SliderTable) slider_table = cdata->_slider_table;
1569 int num_morphs = orig_format->get_num_morphs();
1570 for (
int mi = 0; mi < num_morphs; mi++) {
1571 CPT(InternalName) slider_name = orig_format->get_morph_slider(mi);
1573 const
SparseArray &sliders = slider_table->find_sliders(slider_name);
1574 if (!sliders.is_zero()) {
1575 nassertv(!sliders.is_inverse());
1576 int num_slider_subranges = sliders.get_num_subranges();
1577 for (
int sni = 0; sni < num_slider_subranges; ++sni) {
1578 int slider_begin = sliders.get_subrange_begin(sni);
1579 int slider_end = sliders.get_subrange_end(sni);
1580 for (
int sn = slider_begin; sn < slider_end; ++sn) {
1581 const VertexSlider *slider = slider_table->get_slider(sn);
1582 const SparseArray &rows = slider_table->get_slider_rows(sn);
1585 PN_stdfloat slider_value = slider->get_slider();
1586 if (slider_value != 0.0f) {
1587 CPT(InternalName) base_name = orig_format->get_morph_base(mi);
1588 CPT(InternalName) delta_name = orig_format->get_morph_delta(mi);
1592 int num_subranges = rows.get_num_subranges();
1594 if (data.
get_column()->get_num_values() == 4) {
1595 if (data.get_column()->has_homogeneous_coord()) {
1597 for (
int i = 0; i < num_subranges; ++i) {
1600 data.set_row_unsafe(begin);
1601 delta.set_row_unsafe(begin);
1602 for (
int j = begin; j < end; ++j) {
1603 LPoint4 vertex = data.get_data4();
1604 LPoint3 d = delta.get_data3();
1605 d *= slider_value * vertex[3];
1606 data.set_data4(vertex[0] + d[0],
1614 for (
int i = 0; i < num_subranges; ++i) {
1617 data.set_row_unsafe(begin);
1618 delta.set_row_unsafe(begin);
1619 for (
int j = begin; j < end; ++j) {
1620 const LPoint4 &vertex = data.get_data4();
1621 LPoint4 d = delta.get_data4();
1622 data.set_data4(vertex + d * slider_value);
1629 for (
int i = 0; i < num_subranges; ++i) {
1632 data.set_row_unsafe(begin);
1633 delta.set_row_unsafe(begin);
1634 for (
int j = begin; j < end; ++j) {
1635 const LPoint3 &vertex = data.get_data3();
1636 LPoint3 d = delta.get_data3();
1637 data.set_data3(vertex + d * slider_value);
1655 int num_blends = tb_table->get_num_blends();
1656 for (
int bi = 0; bi < num_blends; bi++) {
1657 tb_table->get_blend(bi).update_blend(current_thread);
1667 int blend_array_index = orig_format->get_array_with(InternalName::get_transform_blend());
1668 if (blend_array_index < 0) {
1671 <<
" has a transform_blend_table, but no transform_blend data.\n";
1675 CPT(GeomVertexArrayFormat) blend_array_format = orig_format->
get_array(blend_array_index);
1678 blend_array_format->
get_column(0)->get_component_bytes() == 2) {
1681 CPT(
GeomVertexArrayDataHandle) blend_array_handle = cdata->_arrays[blend_array_index].get_read_pointer()->get_handle(current_thread);
1682 const
unsigned short *blendt = (const
unsigned short *)blend_array_handle->get_read_pointer(true);
1685 for (ci = 0; ci < new_format->get_num_points(); ci++) {
1688 for (
int i = 0; i < num_subranges; ++i) {
1691 nassertv(begin < end);
1693 int first_vertex = begin;
1694 int first_bi = blendt[first_vertex];
1696 while (first_vertex < end) {
1702 int next_vertex = first_vertex;
1703 int next_bi = first_bi;
1705 while (next_vertex < end) {
1706 next_bi = blendt[next_vertex];
1707 if (next_bi != first_bi) {
1716 tb_table->get_blend(first_bi).get_blend(mat, current_thread);
1717 new_data->do_transform_point_column(new_format, data, mat, first_vertex, next_vertex);
1719 first_vertex = next_vertex;
1725 for (ci = 0; ci < new_format->get_num_vectors(); ci++) {
1728 for (
int i = 0; i < num_subranges; ++i) {
1731 nassertv(begin < end);
1733 int first_vertex = begin;
1734 int first_bi = blendt[first_vertex];
1736 while (first_vertex < end) {
1742 int next_vertex = first_vertex;
1743 int next_bi = first_bi;
1745 while (next_vertex < end) {
1746 next_bi = blendt[next_vertex];
1747 if (next_bi != first_bi) {
1756 tb_table->get_blend(first_bi).get_blend(mat, current_thread);
1757 new_data->do_transform_vector_column(new_format, data, mat, first_vertex, next_vertex);
1759 first_vertex = next_vertex;
1769 nassertv(blendi.has_column());
1772 for (ci = 0; ci < new_format->get_num_points(); ci++) {
1775 for (
int i = 0; i < num_subranges; ++i) {
1778 nassertv(begin < end);
1779 blendi.set_row_unsafe(begin);
1781 int first_vertex = begin;
1782 int first_bi = blendi.get_data1i();
1784 while (first_vertex < end) {
1790 int next_vertex = first_vertex;
1791 int next_bi = first_bi;
1793 while (next_vertex < end) {
1794 next_bi = blendi.get_data1i();
1795 if (next_bi != first_bi) {
1804 tb_table->get_blend(first_bi).get_blend(mat, current_thread);
1805 new_data->do_transform_point_column(new_format, data, mat, first_vertex, next_vertex);
1807 first_vertex = next_vertex;
1813 for (ci = 0; ci < new_format->get_num_vectors(); ci++) {
1816 for (
int i = 0; i < num_subranges; ++i) {
1819 nassertv(begin != end);
1820 blendi.set_row_unsafe(begin);
1822 int first_vertex = begin;
1823 int first_bi = blendi.get_data1i();
1825 while (first_vertex < end) {
1831 int next_vertex = first_vertex;
1832 int next_bi = first_bi;
1834 while (next_vertex < end) {
1835 next_bi = blendi.get_data1i();
1836 if (next_bi != first_bi) {
1845 tb_table->get_blend(first_bi).get_blend(mat, current_thread);
1846 new_data->do_transform_vector_column(new_format, data, mat, first_vertex, next_vertex);
1848 first_vertex = next_vertex;
1864 void GeomVertexData::
1866 const LMatrix4 &mat,
int begin_row,
int end_row) {
1870 if ((num_values == 3 || num_values == 4) &&
1877 size_t num_rows = end_row - begin_row;
1879 datat += data_column->
get_start() + begin_row * stride;
1882 if (num_values == 3) {
1883 table_xform_point3f(datat, num_rows, stride, matf);
1885 table_xform_vecbase4f(datat, num_rows, stride, matf);
1888 }
else if (num_values == 4) {
1893 for (
int j = begin_row; j < end_row; ++j) {
1903 for (
int j = begin_row; j < end_row; ++j) {
1916 void GeomVertexData::
1918 const LMatrix4 &mat,
int begin_row,
int end_row) {
1923 bool normalize =
false;
1927 if (decompose_matrix(mat.
get_upper_3(), scale, shear, hpr) &&
1928 IS_NEARLY_EQUAL(scale[0], scale[1]) &&
1929 IS_NEARLY_EQUAL(scale[0], scale[2])) {
1930 if (scale[0] == 1) {
1942 xform.transpose_in_place();
1949 if ((num_values == 3 || num_values == 4) &&
1956 size_t num_rows = end_row - begin_row;
1958 datat += data_column->
get_start() + begin_row * stride;
1962 table_xform_normal3f(datat, num_rows, stride, matf);
1963 }
else if (num_values == 3) {
1964 table_xform_vector3f(datat, num_rows, stride, matf);
1966 table_xform_vecbase4f(datat, num_rows, stride, matf);
1974 for (
int j = begin_row; j < end_row; ++j) {
1981 for (
int j = begin_row; j < end_row; ++j) {
1995 void GeomVertexData::
1996 table_xform_point3f(
unsigned char *datat,
size_t num_rows,
size_t stride,
2000 for (
size_t i = 0; i < num_rows; ++i) {
2013 void GeomVertexData::
2014 table_xform_normal3f(
unsigned char *datat,
size_t num_rows,
size_t stride,
2018 for (
size_t i = 0; i < num_rows; ++i) {
2031 void GeomVertexData::
2032 table_xform_vector3f(
unsigned char *datat,
size_t num_rows,
size_t stride,
2036 for (
size_t i = 0; i < num_rows; ++i) {
2048 void GeomVertexData::
2049 table_xform_vecbase4f(
unsigned char *datat,
size_t num_rows,
size_t stride,
2051 #if defined(HAVE_EIGEN) && defined(LINMATH_ALIGN)
2054 if (((
size_t)datat & 0xf) != 0 || (stride & 0xf) != 0) {
2057 Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, 4, Eigen::RowMajor>, Eigen::Unaligned, Eigen::OuterStride<> > table((
float *)datat, num_rows, 4, Eigen::OuterStride<>(stride /
sizeof(
float)));
2058 for (
size_t i = 0; i < num_rows; ++i) {
2059 table.row(i) *= matf._m;
2063 #endif // HAVE_EIGEN
2068 for (
size_t i = 0; i < num_rows; ++i) {
2113 parse_params(params, scan, manager);
2114 object->fillin(scan, manager);
2173 for (
size_t i = 0; i < cdata->_arrays.size(); ++i) {
2174 CPT(GeomVertexFormat) new_format =
2175 GeomVertexFormat::register_format(cdata->_format);
2177 cdata->_format = new_format;
2179 CPT(GeomVertexArrayFormat) new_array_format = new_format->get_array(i);
2181 nassertv(new_array_format->is_data_subset_of(*array_obj->_array_format));
2183 manager->
change_pointer(array_obj->_array_format, new_array_format);
2184 array_obj->_array_format = new_array_format;
2189 TransformTable::register_table(cdata->_transform_table);
2190 manager->
change_pointer(cdata->_transform_table, new_transform_table);
2191 cdata->_transform_table = new_transform_table;
2194 if (cdata->_slider_table != (
SliderTable *)NULL) {
2196 SliderTable::register_table(cdata->_slider_table);
2198 cdata->_slider_table = new_slider_table;
2209 void GeomVertexData::
2224 return new CDataCache(*
this);
2236 Cache::iterator ci = _source->_cache.find(&_key);
2237 nassertv(ci != _source->_cache.end());
2238 nassertv((*ci).second ==
this);
2239 _source->_cache.erase(ci);
2247 void GeomVertexData::CacheEntry::
2248 output(ostream &out)
const {
2249 out <<
"vertex data " << (
void *)_source <<
" to "
2260 return new CData(*
this);
2269 void GeomVertexData::CData::
2275 Arrays::const_iterator ai;
2276 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
2281 manager->
write_pointer(dg, _transform_blend_table.get_read_pointer());
2292 int GeomVertexData::CData::
2296 _format = DCAST(GeomVertexFormat, p_list[pi++]);
2298 Arrays::iterator ai;
2299 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
2316 all_rows.set_range(0, adata->get_num_rows());
2319 int num_sliders = _slider_table->get_num_sliders();
2320 for (
int i = 0; i < num_sliders; ++i) {
2321 ((
SliderTable *)_slider_table.p())->set_slider_rows(i, all_rows);
2324 if (!_transform_blend_table.is_null()) {
2325 _transform_blend_table.get_unsafe_pointer()->set_rows(all_rows);
2339 void GeomVertexData::CData::
2342 _usage_hint = (UsageHint)scan.
get_uint8();
2345 _arrays.reserve(num_arrays);
2346 for (
size_t i = 0; i < num_arrays; ++i) {
2348 _arrays.push_back(NULL);
2361 int GeomVertexDataPipelineBase::
2362 get_num_bytes()
const {
2365 GeomVertexData::Arrays::const_iterator ai;
2366 for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
2367 num_bytes += (*ai).get_read_pointer()->get_data_size_bytes();
2378 int GeomVertexDataPipelineReader::
2379 get_num_rows()
const {
2380 nassertr(_cdata->_format->get_num_arrays() == (int)_cdata->_arrays.size(), 0);
2381 nassertr(_got_array_readers, 0);
2383 if (_cdata->_format->get_num_arrays() == 0) {
2389 int stride = _cdata->_format->get_array(0)->get_stride();
2390 return _array_readers[0]->get_data_size_bytes() / stride;
2398 bool GeomVertexDataPipelineReader::
2399 get_array_info(
const InternalName *name,
2402 GeomVertexDataPipelineReader::NumericType &numeric_type,
2403 int &start,
int &stride)
const {
2404 nassertr(_got_array_readers,
false);
2407 if (_cdata->_format->get_array_info(name, array_index, column)) {
2408 array_reader = _array_readers[array_index];
2412 stride = _cdata->_format->get_array(array_index)->get_stride();
2423 bool GeomVertexDataPipelineReader::
2424 get_array_info(
const InternalName *name,
2427 GeomVertexDataPipelineReader::NumericType &numeric_type,
2428 int &start,
int &stride,
int &divisor,
2429 int &num_elements,
int &element_stride)
const {
2430 nassertr(_got_array_readers,
false);
2433 if (_cdata->_format->get_array_info(name, array_index, column)) {
2434 array_reader = _array_readers[array_index];
2438 stride = _cdata->_format->get_array(array_index)->get_stride();
2439 divisor = _cdata->_format->get_array(array_index)->get_divisor();
2452 bool GeomVertexDataPipelineReader::
2455 GeomVertexDataPipelineReader::NumericType &numeric_type,
2456 int &start,
int &stride)
const {
2457 nassertr(_got_array_readers,
false);
2458 int array_index = _cdata->_format->get_vertex_array_index();
2459 if (array_index >= 0) {
2462 array_reader = _array_readers[array_index];
2466 stride = _cdata->_format->get_array(array_index)->get_stride();
2477 bool GeomVertexDataPipelineReader::
2479 GeomVertexDataPipelineReader::NumericType &numeric_type,
2480 int &start,
int &stride)
const {
2481 nassertr(_got_array_readers,
false);
2482 int array_index = _cdata->_format->get_normal_array_index();
2483 if (array_index >= 0) {
2486 array_reader = _array_readers[array_index];
2489 stride = _cdata->_format->get_array(array_index)->get_stride();
2500 bool GeomVertexDataPipelineReader::
2503 GeomVertexDataPipelineReader::NumericType &numeric_type,
2504 int &start,
int &stride)
const {
2505 nassertr(_got_array_readers,
false);
2506 int array_index = _cdata->_format->get_color_array_index();
2507 if (array_index >= 0) {
2510 array_reader = _array_readers[array_index];
2514 stride = _cdata->_format->get_array(array_index)->get_stride();
2525 void GeomVertexDataPipelineReader::
2526 make_array_readers() {
2527 nassertv(!_got_array_readers);
2529 _array_readers.reserve(_cdata->_arrays.size());
2530 GeomVertexData::Arrays::const_iterator ai;
2531 for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
2533 _array_readers.push_back(array_obj->get_handle(_current_thread));
2536 _got_array_readers = true;
2545 delete_array_readers() {
2546 nassertv(_got_array_readers);
2548 _array_readers.clear();
2549 _got_array_readers =
false;
2557 int GeomVertexDataPipelineWriter::
2558 get_num_rows()
const {
2559 nassertr(_cdata->_format->get_num_arrays() == (int)_cdata->_arrays.size(), 0);
2560 nassertr(_got_array_writers, 0);
2562 if (_cdata->_format->get_num_arrays() == 0) {
2568 int stride = _cdata->_format->get_array(0)->get_stride();
2569 return _array_writers[0]->get_data_size_bytes() / stride;
2577 bool GeomVertexDataPipelineWriter::
2578 set_num_rows(
int n) {
2579 nassertr(_got_array_writers,
false);
2580 nassertr(_cdata->_format->get_num_arrays() == (int)_cdata->_arrays.size(),
false);
2582 bool any_changed =
false;
2584 int color_array = -1;
2585 int orig_color_rows = -1;
2587 for (
size_t i = 0; i < _cdata->_arrays.size(); i++) {
2589 if (_array_writers[i]->get_object()->has_column(InternalName::get_color())) {
2591 orig_color_rows = _array_writers[i]->get_num_rows();
2593 _array_writers[i]->set_num_rows(n);
2598 if (color_array >= 0 && orig_color_rows < n) {
2602 const GeomVertexArrayFormat *array_format = array_writer->get_array_format();
2604 array_format->get_column(InternalName::get_color());
2605 int stride = array_format->get_stride();
2606 unsigned char *start =
2608 unsigned char *stop = start + array_writer->get_data_size_bytes();
2609 unsigned char *pointer = start + stride * orig_color_rows;
2613 case NT_packed_dcba:
2614 case NT_packed_dabc:
2618 while (pointer < stop) {
2625 while (pointer < stop) {
2626 PN_float32 *pi = (PN_float32 *)pointer;
2627 for (
int i = 0; i < num_values; i++) {
2635 while (pointer < stop) {
2636 PN_float64 *pi = (PN_float64 *)pointer;
2637 for (
int i = 0; i < num_values; i++) {
2646 nassertr(
false,
false);
2651 _object->clear_cache_stage();
2653 _cdata->_animated_vertices.clear();
2664 bool GeomVertexDataPipelineWriter::
2665 unclean_set_num_rows(
int n) {
2666 nassertr(_got_array_writers,
false);
2667 nassertr(_cdata->_format->get_num_arrays() == (int)_cdata->_arrays.size(),
false);
2669 bool any_changed =
false;
2671 for (
size_t i = 0; i < _cdata->_arrays.size(); i++) {
2680 _object->clear_cache_stage();
2682 _cdata->_animated_vertices.clear();
2693 bool GeomVertexDataPipelineWriter::
2694 reserve_num_rows(
int n) {
2695 nassertr(_got_array_writers,
false);
2696 nassertr(_cdata->_format->get_num_arrays() == (int)_cdata->_arrays.size(),
false);
2698 bool any_changed =
false;
2700 for (
size_t i = 0; i < _cdata->_arrays.size(); i++) {
2715 modify_array(
int i) {
2716 nassertr(i >= 0 && i < (
int)_cdata->_arrays.size(), NULL);
2719 if (_got_array_writers) {
2720 new_data = _array_writers[i]->get_object();
2722 new_data = _cdata->_arrays[i].get_write_pointer();
2725 _object->clear_cache_stage();
2727 _cdata->_animated_vertices_modified =
UpdateSeq();
2737 void GeomVertexDataPipelineWriter::
2739 nassertv(i >= 0 && i < (
int)_cdata->_arrays.size());
2741 _object->clear_cache_stage();
2743 _cdata->_animated_vertices_modified =
UpdateSeq();
2745 if (_got_array_writers) {
2746 _array_writers[i] = _cdata->_arrays[i].get_write_pointer()->modify_handle(_current_thread);
2755 void GeomVertexDataPipelineWriter::
2756 make_array_writers() {
2757 nassertv(!_got_array_writers);
2759 _array_writers.reserve(_cdata->_arrays.size());
2760 GeomVertexData::Arrays::iterator ai;
2761 for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
2763 _array_writers.push_back(array_obj->modify_handle(_current_thread));
2767 _cdata->_modified =
Geom::get_next_modified();
2768 _cdata->_animated_vertices_modified =
UpdateSeq();
2770 _got_array_writers = true;
2779 delete_array_writers() {
2780 nassertv(_got_array_writers);
2782 _array_writers.clear();
2783 _got_array_writers =
false;
LMatrix3f get_upper_3() const
Retrieves the upper 3x3 submatrix.
void copy_from(const GeomVertexData *source, bool keep_data_objects, Thread *current_thread=Thread::get_current_thread())
Copies all the data from the other array into the corresponding data types in this array...
This class records a set of integers, where each integer is either present or not present in the set...
int get_element_stride() const
This value is only relevant for matrix types.
bool is_uint8_rgba() const
Returns true if this column is the standard OpenGL representation of 4-component color: C_color...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
This is the base class for all three-component vectors and points.
void describe_vertex(ostream &out, int row) const
Writes a verbose, human-friendly description of the indicated vertex number.
This is our own Panda specialization on the default STL map.
bool is_packed_argb() const
Returns true if this column is the standard DirectX representation of 4-component color: C_color...
void clear_animated_vertices()
Removes the cache of animated vertices computed by a previous call to animate_vertices() within the s...
void transform_vertices(const LMatrix4 &mat)
Applies the indicated transform matrix to all of the vertices in the GeomVertexData.
void add_string(const string &str)
Adds a variable-length string to the datagram.
bool unclean_set_num_rows(int n)
This method behaves like set_num_rows(), except the new data is not initialized.
void set_format(const GeomVertexFormat *format)
Changes the format of the vertex data.
void unclean_set_format(const GeomVertexFormat *format)
Changes the format of the vertex data, without reformatting the data to match.
void set_transform_table(const TransformTable *table)
Replaces the TransformTable on this vertex data with the indicated table.
bool set_column(int column)
Sets up the reader to use the nth data type of the GeomVertexFormat, numbering from 0...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void set_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row. ...
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded...
static PN_uint32 pack_abcd(unsigned int a, unsigned int b, unsigned int c, unsigned int d)
Packs four values in a DirectX-style NT_packed_abcd value.
void set_data4i(int a, int b, int c, int d)
Sets the write row to a particular 4-component value, and advances the write row. ...
int get_total_bytes() const
Returns the number of bytes used by each element of the column: component_bytes * num_components...
bool request_resident() const
Returns true if the vertex data is currently resident in memory.
UsageHint get_usage_hint() const
Returns the usage hint that was passed to the constructor, and which will be passed to each array dat...
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
A single page of data maintained by a PipelineCycler.
int get_num_elements() const
Returns the number of times this column is repeated.
Base class for objects that can be written to and read from Bam files.
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
const InternalName * get_name() const
Returns the name of this particular data field, e.g.
void set_array(int i, const GeomVertexArrayData *array)
Replaces the indicated vertex data array with a completely new array.
const LVecBase4 & get_data4()
Returns the data associated with the read row, expressed as a 4-component value, and advances the rea...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
void set_usage_hint(UsageHint usage_hint)
Changes the UsageHint hint for this vertex data, and for all of the arrays that share this data...
This is an abstract base class that retains some slider value, which is a linear value that typically...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
void set_slider_table(const SliderTable *table)
Replaces the SliderTable on this vertex data with the indicated table.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
bool is_at_end() const
Returns true if the reader is currently at the end of the list of vertices, false otherwise...
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
static const LVecBase3f & zero()
Returns a zero-length vector.
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
bool is_registered() const
Returns true if this table has been registered.
This is the base class for all three-component vectors and points.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
string get_string()
Extracts a variable-length string.
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
This defines how a single column is interleaved within a vertex array stored within a Geom...
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
const string & get_name() const
Returns the name passed to the constructor, if any.
int get_start() const
Returns the byte within the array record at which this column starts.
size_t get_stride() const
Returns the per-row stride (bytes between consecutive rows) of the underlying vertex array...
int get_subrange_end(int n) const
Returns the last numeric element, plus one, in the nth subrange.
void set_transform_blend_table(const TransformBlendTable *table)
Replaces the TransformBlendTable on this vertex data with the indicated table.
AnimationType get_animation_type() const
Returns the type of animation represented by this spec.
A lightweight class that represents a single element that may be timed and/or counted via stats...
Stores the total set of VertexSliders that the vertices in a particular GeomVertexData object might d...
bool reserve_num_rows(int n)
This ensures that enough memory space for n rows is allocated, so that you may increase the number of...
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
void dump_hex(ostream &out, unsigned int indent=0) const
Writes a representation of the entire datagram contents, as a sequence of hex (and ASCII) values...
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
bool is_bytewise_equivalent(const GeomVertexColumn &other) const
Returns true if the data store of this column is exactly the same as that of the other, irrespective of name or start position within the record.
bool is_inverse() const
If this is true, the SparseArray is actually defined as a list of subranges of integers that are *not...
This is a 4-by-4 transform matrix.
static unsigned int unpack_abcd_c(PN_uint32 data)
Returns the third packed value from a DirectX-style NT_packed_abcd.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Similar to MutexHolder, but for a light mutex.
bool change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_pointer)
Indicates that an object recently read from the bam stream should be replaced with a new object...
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
A container for geometry primitives.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
bool invert_from(const LMatrix4f &other)
Computes the inverse of the other matrix, and stores the result in this matrix.
const LVecBase3 & get_data3()
Returns the data associated with the read row, expressed as a 3-component value, and advances the rea...
const GeomVertexFormat * get_format() const
Returns a pointer to the GeomVertexFormat structure that defines this data.
bool has_column() const
Returns true if a valid data type has been successfully set, or false if the data type does not exist...
void operator=(const GeomVertexData ©)
The copy assignment operator is not pipeline-safe.
void set_data4(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat w)
Sets the write row to a particular 4-component value, and advances the write row. ...
virtual void evict_callback()
Called when the entry is evicted from the cache, this should clean up the owning object appropriately...
bool set_num_rows(int n)
Sets the length of the array to n rows in all of the various arrays (presumably by adding rows)...
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
bool get_indexed_transforms() const
This is only meaningful for animation_type AT_hardware.
virtual bool require_fully_complete() const
Some objects require all of their nested pointers to have been completed before the objects themselve...
const GeomVertexColumn * get_column() const
Returns the description of the data type that the rewriter is working on.
unsigned char * get_write_pointer()
Returns a writable pointer to the beginning of the actual data stream.
int get_data1i()
Returns the data associated with the read row, expressed as a 1-component value, and advances the rea...
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
const GeomVertexColumn * get_column() const
Returns the description of the data type that the writer is working on.
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
This is the base class for all three-component vectors and points.
void copy_row_from(int dest_row, const GeomVertexData *source, int source_row, Thread *current_thread)
Copies a single row of the data from the other array into the indicated row of this array...
size_t get_stride() const
Returns the per-row stride (bytes between consecutive rows) of the underlying vertex array...
int get_num_subranges() const
Returns the number of separate subranges stored in the SparseArray.
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
GeomVertexArrayDataHandle * get_array_handle() const
Returns the write handle to the array object that the rewriter is currently processing.
int get_num_values() const
Returns the number of numeric values of the column: the number of distinct numeric values that go int...
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
This is a four-component point in space.
A thread; that is, a lightweight process.
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
static unsigned int unpack_abcd_d(PN_uint32 data)
Returns the fourth packed value from a DirectX-style NT_packed_abcd.
void clear_rows()
Removes all of the rows from the arrays; functionally equivalent to set_num_rows(0) (but faster)...
static UpdateSeq get_next_modified()
Returns a monotonically increasing sequence.
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
int compare_to(const GeomVertexData &other) const
Returns 0 if the two objects are equivalent, even if they are not the same pointer.
void clear_cache()
Removes all of the previously-cached results of convert_to().
bool set_column(int column)
Sets up the writer to use the nth data type of the GeomVertexFormat, numbering from 0...
static unsigned int unpack_abcd_b(PN_uint32 data)
Returns the second packed value from a DirectX-style NT_packed_abcd.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
int get_subrange_begin(int n) const
Returns the first numeric element in the nth subrange.
A class to retrieve the individual data elements previously stored in a Datagram. ...
int get_array() const
Returns the array index containing the data type that the writer is working on.
static unsigned int unpack_abcd_a(PN_uint32 data)
Returns the first packed value from a DirectX-style NT_packed_abcd.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
TypeHandle is the identifier used to differentiate C++ class types.
This is a sequence number that increments monotonically.
void clear_transform_blend_table()
Sets the TransformBlendTable pointer to NULL, removing the table from the vertex data.
bool normalize()
Normalizes the vector in place.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
void set_name(const string &name)
Changes the name of the vertex data.
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter, combined together into one convenient package.
This is the data for one array of a GeomVertexData structure.
static const LVecBase4f & zero()
Returns a zero-length vector.
void clear_cache_stage()
Removes all of the previously-cached results of convert_to(), at the current pipeline stage and upstr...
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
bool is_at_end() const
Returns true if the writer is currently at the end of the list of vertices, false otherwise...
static void register_with_read_factory()
Tells the BamReader how to create objects of type GeomVertexData.
int get_num_rows() const
Returns the number of rows stored within all the arrays.