15 #include "geomVertexFormat.h" 16 #include "geomVertexData.h" 17 #include "geomMunger.h" 18 #include "lightReMutexHolder.h" 20 #include "bamReader.h" 21 #include "bamWriter.h" 23 GeomVertexFormat::Registry *GeomVertexFormat::_registry = NULL;
33 _is_registered(false),
34 _post_animated_format(NULL)
44 GeomVertexFormat(
const GeomVertexArrayFormat *array_format) :
45 _is_registered(false),
46 _post_animated_format(NULL)
48 add_array(array_format);
57 GeomVertexFormat(
const GeomVertexFormat ©) :
58 _is_registered(false),
59 _animation(copy._animation),
60 _arrays(copy._arrays),
61 _post_animated_format(NULL)
70 void GeomVertexFormat::
71 operator = (
const GeomVertexFormat ©) {
72 nassertv(!is_registered());
74 _animation = copy._animation;
75 _arrays = copy._arrays;
86 nassertv(!is_registered());
96 bool GeomVertexFormat::
98 Registry *registry = get_registry();
105 if (is_registered()) {
106 registry->unregister_format((GeomVertexFormat *)
this);
124 CPT(GeomVertexFormat) GeomVertexFormat::
125 get_post_animated_format()
const {
126 nassertr(is_registered(), NULL);
128 if (_post_animated_format == (GeomVertexFormat *)NULL) {
129 PT(GeomVertexFormat) new_format =
new GeomVertexFormat(*
this);
130 new_format->remove_column(InternalName::get_transform_blend());
132 int num_morphs = get_num_morphs();
133 for (
int mi = 0; mi < num_morphs; mi++) {
134 CPT(InternalName) delta_name = get_morph_delta(mi);
135 new_format->remove_column(delta_name);
138 new_format->_animation.set_none();
140 CPT(GeomVertexFormat) registered =
141 GeomVertexFormat::register_format(new_format);
142 ((GeomVertexFormat *)
this)->_post_animated_format = registered;
143 if (_post_animated_format !=
this) {
146 _post_animated_format->ref();
150 _post_animated_format->test_ref_count_integrity();
152 return _post_animated_format;
169 CPT(GeomVertexFormat) GeomVertexFormat::
170 get_union_format(
const GeomVertexFormat *other)
const {
171 nassertr(is_registered() && other->is_registered(), NULL);
173 PT(GeomVertexFormat) new_format =
new GeomVertexFormat;
178 if (_animation.get_animation_type() != AT_none) {
179 new_format->set_animation(_animation);
181 new_format->set_animation(other->get_animation());
186 ColumnNames column_names;
201 size_t num_arrays = max(_arrays.size(), other->_arrays.size());
202 for (
size_t ai = 0; ai < num_arrays; ++ai) {
203 PT(GeomVertexArrayFormat) new_array =
new GeomVertexArrayFormat;
206 if (ai < _arrays.size()) {
207 GeomVertexArrayFormat *array_format = _arrays[ai];
208 int num_columns = array_format->get_num_columns();
209 for (
int i = 0; i < num_columns; ++i) {
211 bool inserted = column_names.insert(column_a->
get_name()).second;
217 new_array->add_column(column_b->
get_name(),
223 new_array->add_column(column_a->
get_name(),
233 if (ai < other->_arrays.size()) {
234 GeomVertexArrayFormat *array_format = other->_arrays[ai];
235 int num_columns = array_format->get_num_columns();
236 for (
int i = 0; i < num_columns; ++i) {
238 bool inserted = column_names.insert(column_a->
get_name()).second;
244 new_array->add_column(column_b->
get_name(),
250 new_array->add_column(column_a->
get_name(),
259 if (new_array->get_num_columns() != 0) {
260 new_format->add_array(new_array);
265 return GeomVertexFormat::register_format(new_format);
278 GeomVertexArrayFormat *GeomVertexFormat::
279 modify_array(
int array) {
280 nassertr(!is_registered(), NULL);
281 nassertr(array >= 0 && array < (
int)_arrays.size(), NULL);
283 if (_arrays[array]->is_registered() ||
284 _arrays[array]->get_ref_count() > 1) {
285 _arrays[array] =
new GeomVertexArrayFormat(*_arrays[array]);
288 return _arrays[array];
299 void GeomVertexFormat::
300 set_array(
int array,
const GeomVertexArrayFormat *format) {
301 nassertv(!is_registered());
302 nassertv(array >= 0 && array < (
int)_arrays.size());
303 _arrays[array] = (GeomVertexArrayFormat *)format;
314 void GeomVertexFormat::
315 remove_array(
int array) {
316 nassertv(!is_registered());
318 nassertv(array >= 0 && array < (
int)_arrays.size());
319 _arrays.erase(_arrays.begin() + array);
333 int GeomVertexFormat::
334 add_array(
const GeomVertexArrayFormat *array_format) {
335 nassertr(!is_registered(), -1);
337 int new_array = (int)_arrays.size();
338 _arrays.push_back((GeomVertexArrayFormat *)array_format);
353 void GeomVertexFormat::
354 insert_array(
int array,
const GeomVertexArrayFormat *array_format) {
355 nassertv(!is_registered());
356 nassertv(array >= 0 && array <= (
int)_arrays.size());
358 _arrays.insert(_arrays.begin() + array, (GeomVertexArrayFormat *)array_format);
370 void GeomVertexFormat::
372 nassertv(!is_registered());
385 void GeomVertexFormat::
386 remove_empty_arrays() {
387 nassertv(!is_registered());
390 orig_arrays.swap(_arrays);
391 Arrays::const_iterator ai;
392 for (ai = orig_arrays.begin(); ai != orig_arrays.end(); ++ai) {
393 GeomVertexArrayFormat *array_format = (*ai);
394 if (array_format->get_num_columns() != 0) {
395 _arrays.push_back(array_format);
406 int GeomVertexFormat::
407 get_num_columns()
const {
409 Arrays::const_iterator ai;
410 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
411 num_columns += (*ai)->get_num_columns();
423 get_column(
int i)
const {
424 Arrays::const_iterator ai;
425 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
426 if (i < (*ai)->get_num_columns()) {
427 return (*ai)->get_column(i);
429 i -= (*ai)->get_num_columns();
447 int GeomVertexFormat::
448 get_array_with(
int i)
const {
450 for (array_index = 0; array_index < (int)_arrays.size(); array_index++) {
451 if (i < _arrays[array_index]->get_num_columns()) {
454 i -= _arrays[array_index]->get_num_columns();
476 int GeomVertexFormat::
477 get_array_with(
const InternalName *name)
const {
478 nassertr(_is_registered, -1);
480 DataTypesByName::const_iterator ai;
481 ai = _columns_by_name.find(name);
482 if (ai != _columns_by_name.end()) {
483 return (*ai).second._array_index;
497 get_column(
const InternalName *name)
const {
498 if (!_is_registered) {
501 Arrays::const_iterator ai;
502 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
514 DataTypesByName::const_iterator ai;
515 ai = _columns_by_name.find(name);
516 if (ai != _columns_by_name.end()) {
517 int array_index = (*ai).second._array_index;
518 int column_index = (*ai).second._column_index;
520 nassertr(array_index >= 0 && array_index < (
int)_arrays.size(), NULL);
521 return _arrays[array_index]->get_column(column_index);
540 void GeomVertexFormat::
541 remove_column(
const InternalName *name,
bool keep_empty_array) {
542 nassertv(!_is_registered);
547 for (
int array = 0; array < (int)_arrays.size(); ++array) {
548 GeomVertexArrayFormat *array_format = _arrays[array];
552 if (array_format->is_registered() ||
553 array_format->get_ref_count() > 1) {
555 _arrays[array] =
new GeomVertexArrayFormat(*array_format);
556 array_format = _arrays[array];
559 array_format->remove_column(name);
562 if (!keep_empty_array && array_format->get_num_columns() == 0) {
579 void GeomVertexFormat::
581 nassertv(!_is_registered);
583 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
584 if ((*ai)->is_registered()) {
585 (*ai) =
new GeomVertexArrayFormat(*(*ai));
587 (*ai)->pack_columns();
601 void GeomVertexFormat::
602 align_columns_for_animation() {
603 nassertv(!_is_registered);
605 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
606 if ((*ai)->is_registered()) {
607 (*ai) =
new GeomVertexArrayFormat(*(*ai));
609 (*ai)->align_columns_for_animation();
620 void GeomVertexFormat::
621 maybe_align_columns_for_animation() {
622 if (_animation.get_animation_type() == AT_panda && vertex_animation_align_16) {
623 align_columns_for_animation();
632 void GeomVertexFormat::
633 output(ostream &out)
const {
634 if (_arrays.empty()) {
638 Arrays::const_iterator ai;
639 ai = _arrays.begin();
642 while (ai != _arrays.end()) {
643 out <<
", " << *(*ai);
648 if (_animation.get_animation_type() != AT_none) {
649 out <<
", anim " << _animation;
658 void GeomVertexFormat::
659 write(ostream &out,
int indent_level)
const {
660 for (
size_t i = 0; i < _arrays.size(); i++) {
661 indent(out, indent_level)
662 <<
"Array " << i <<
":\n";
663 _arrays[i]->write(out, indent_level + 2);
666 if (_animation.get_animation_type() != AT_none) {
667 indent(out, indent_level)
668 <<
"anim " << _animation <<
"\n";
677 void GeomVertexFormat::
678 write_with_data(ostream &out,
int indent_level,
680 indent(out, indent_level)
682 for (
size_t i = 0; i < _arrays.size(); i++) {
684 const unsigned char *array_data = handle->get_read_pointer(
true);
685 indent(out, indent_level)
686 <<
"Array " << i <<
" (" << (
void *)array_data <<
", " 687 << *_arrays[i] <<
"):\n";
688 _arrays[i]->write_with_data(out, indent_level + 2, data->get_array(i));
705 bool GeomVertexFormat::
706 get_array_info(
const InternalName *name,
int &array_index,
708 nassertr(_is_registered,
false);
710 DataTypesByName::const_iterator ai;
711 ai = _columns_by_name.find(name);
712 if (ai != _columns_by_name.end()) {
713 array_index = (*ai).second._array_index;
714 column = _arrays[array_index]->get_column((*ai).second._column_index);
729 int GeomVertexFormat::
730 compare_to(
const GeomVertexFormat &other)
const {
731 int compare = _animation.
compare_to(other._animation);
736 if (_arrays.size() != other._arrays.size()) {
737 return (
int)_arrays.size() - (int)other._arrays.size();
740 for (
size_t i = 0; i < _arrays.size(); i++) {
741 int compare = _arrays[i]->compare_to(*other._arrays[i]);
755 void GeomVertexFormat::
757 if (_registry == (Registry *)NULL) {
758 _registry =
new Registry;
759 _registry->make_standard_formats();
768 void GeomVertexFormat::
770 nassertv(!is_registered());
771 nassertv(_columns_by_name.empty());
774 orig_arrays.swap(_arrays);
775 Arrays::const_iterator ai;
776 for (ai = orig_arrays.begin(); ai != orig_arrays.end(); ++ai) {
777 CPT(GeomVertexArrayFormat) array_format = (*ai);
778 if (!array_format->is_registered()) {
779 array_format = GeomVertexArrayFormat::register_format(array_format);
786 if (array_format->get_stride() == 0) {
788 <<
"Dropping empty array from GeomVertexFormat.\n";
792 int array = (int)_arrays.size();
793 _arrays.push_back((GeomVertexArrayFormat *)array_format.p());
796 int num_columns = array_format->get_num_columns();
797 for (
int i = 0; i < num_columns; i++) {
799 pair<DataTypesByName::iterator, bool> result;
800 result = _columns_by_name.insert(DataTypesByName::value_type(column->
get_name(), DataTypeRecord()));
801 if (!result.second) {
803 <<
"Column " << *column->
get_name() <<
" repeated in format.\n";
805 DataTypeRecord &record = (*result.first).second;
806 record._array_index = array;
807 record._column_index = i;
814 DataTypesByName::iterator ni;
815 for (ni = _columns_by_name.begin();
816 ni != _columns_by_name.end();
818 const DataTypeRecord &record = (*ni).second;
819 const GeomVertexColumn *column = _arrays[record._array_index]->get_column(record._column_index);
824 _points.push_back(column->
get_name());
830 _vectors.push_back(column->
get_name());
835 _texcoords.push_back(column->
get_name());
845 int n = morph._delta->find_ancestor(
"morph");
848 <<
"vertex format defines " << *column->
get_name()
849 <<
", which is stored as a C_morph_delta, but its name does not include \"morph\".\n";
851 morph._slider = InternalName::make(morph._delta->get_net_basename(n - 1));
852 morph._base = morph._delta->get_ancestor(n + 1);
854 if (_columns_by_name.find(morph._base) == _columns_by_name.end()) {
856 <<
"vertex format defines " 857 << *column->
get_name() <<
" but does not define " 858 << *morph._base <<
"\n";
860 _morphs.push_back(morph);
873 _is_registered =
true;
875 get_array_info(InternalName::get_vertex(), _vertex_array_index,
877 get_array_info(InternalName::get_normal(), _normal_array_index,
879 get_array_info(InternalName::get_color(), _color_array_index,
888 void GeomVertexFormat::
890 nassertv(_is_registered);
891 _is_registered =
false;
893 _columns_by_name.clear();
899 if (_post_animated_format != (GeomVertexFormat *)NULL &&
900 _post_animated_format !=
this) {
901 unref_delete(_post_animated_format);
903 _post_animated_format = NULL;
912 void GeomVertexFormat::
913 register_with_read_factory() {
923 void GeomVertexFormat::
927 _animation.write_datagram(manager, dg);
930 Arrays::const_iterator ai;
931 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
943 int GeomVertexFormat::
948 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
949 (*ai) = DCAST(GeomVertexArrayFormat, p_list[pi++]);
966 GeomVertexFormat *
object =
new GeomVertexFormat;
970 parse_params(params, scan, manager);
971 object->fillin(scan, manager);
983 void GeomVertexFormat::
987 _animation.fillin(scan, manager);
990 _arrays.reserve(num_arrays);
991 for (
int i = 0; i < num_arrays; i++) {
993 _arrays.push_back(NULL);
1002 GeomVertexFormat::Registry::
1011 void GeomVertexFormat::Registry::
1012 make_standard_formats() {
1013 _v3 = register_format(
new GeomVertexArrayFormat
1014 (InternalName::get_vertex(), 3,
1015 NT_stdfloat, C_point));
1017 _v3n3 = register_format(
new GeomVertexArrayFormat
1018 (InternalName::get_vertex(), 3,
1019 NT_stdfloat, C_point,
1020 InternalName::get_normal(), 3,
1021 NT_stdfloat, C_normal));
1023 _v3t2 = register_format(
new GeomVertexArrayFormat
1024 (InternalName::get_vertex(), 3,
1025 NT_stdfloat, C_point,
1026 InternalName::get_texcoord(), 2,
1027 NT_stdfloat, C_texcoord));
1029 _v3n3t2 = register_format(
new GeomVertexArrayFormat
1030 (InternalName::get_vertex(), 3,
1031 NT_stdfloat, C_point,
1032 InternalName::get_normal(), 3,
1033 NT_stdfloat, C_normal,
1034 InternalName::get_texcoord(), 2,
1035 NT_stdfloat, C_texcoord));
1038 _v3cp = register_format(
new GeomVertexArrayFormat
1039 (InternalName::get_vertex(), 3,
1040 NT_stdfloat, C_point,
1041 InternalName::get_color(), 1,
1042 NT_packed_dabc, C_color));
1044 _v3n3cp = register_format(
new GeomVertexArrayFormat
1045 (InternalName::get_vertex(), 3,
1046 NT_stdfloat, C_point,
1047 InternalName::get_normal(), 3,
1048 NT_stdfloat, C_normal,
1049 InternalName::get_color(), 1,
1050 NT_packed_dabc, C_color));
1052 _v3cpt2 = register_format(
new GeomVertexArrayFormat
1053 (InternalName::get_vertex(), 3,
1054 NT_stdfloat, C_point,
1055 InternalName::get_color(), 1,
1056 NT_packed_dabc, C_color,
1057 InternalName::get_texcoord(), 2,
1058 NT_stdfloat, C_texcoord));
1060 _v3n3cpt2 = register_format(
new GeomVertexArrayFormat
1061 (InternalName::get_vertex(), 3,
1062 NT_stdfloat, C_point,
1063 InternalName::get_normal(), 3,
1064 NT_stdfloat, C_normal,
1065 InternalName::get_color(), 1,
1066 NT_packed_dabc, C_color,
1067 InternalName::get_texcoord(), 2,
1068 NT_stdfloat, C_texcoord));
1073 _v3c4 = register_format(
new GeomVertexArrayFormat
1074 (InternalName::get_vertex(), 3,
1075 NT_stdfloat, C_point,
1076 InternalName::get_color(), 4,
1077 NT_uint8, C_color));
1079 _v3n3c4 = register_format(
new GeomVertexArrayFormat
1080 (InternalName::get_vertex(), 3,
1081 NT_stdfloat, C_point,
1082 InternalName::get_normal(), 3,
1083 NT_stdfloat, C_normal,
1084 InternalName::get_color(), 4,
1085 NT_uint8, C_color));
1087 _v3c4t2 = register_format(
new GeomVertexArrayFormat
1088 (InternalName::get_vertex(), 3,
1089 NT_stdfloat, C_point,
1090 InternalName::get_color(), 4,
1092 InternalName::get_texcoord(), 2,
1093 NT_stdfloat, C_texcoord));
1095 _v3n3c4t2 = register_format(
new GeomVertexArrayFormat
1096 (InternalName::get_vertex(), 3,
1097 NT_stdfloat, C_point,
1098 InternalName::get_normal(), 3,
1099 NT_stdfloat, C_normal,
1100 InternalName::get_color(), 4,
1102 InternalName::get_texcoord(), 2,
1103 NT_stdfloat, C_texcoord));
1121 CPT(GeomVertexFormat) GeomVertexFormat::Registry::
1122 register_format(GeomVertexFormat *format) {
1123 if (format->is_registered()) {
1130 PT(GeomVertexFormat) pt_format = format;
1132 GeomVertexFormat *new_format;
1135 Formats::iterator fi = _formats.insert(format).first;
1137 if (!new_format->is_registered()) {
1138 new_format->do_register();
1139 if (new_format->get_num_arrays() == 0) {
1141 <<
"Empty GeomVertexFormat registered.\n";
1158 void GeomVertexFormat::Registry::
1159 unregister_format(GeomVertexFormat *format) {
1160 nassertv(format->is_registered());
1161 Formats::iterator fi = _formats.find(format);
1162 nassertv(fi != _formats.end());
1164 format->do_unregister();
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
Base class for objects that can be written to and read from Bam files.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
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.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
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()...
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
An instance of this class is passed to the Factory when requesting it to do its business and construc...
int get_num_rows() const
Returns the number of rows stored within all the arrays.
Similar to MutexHolder, but for a light reentrant mutex.
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
This is our own Panda specialization on the default STL set.
A class to retrieve the individual data elements previously stored in a Datagram. ...
const InternalName * get_name() const
Returns the name of this particular data field, e.g.
int get_total_bytes() const
Returns the number of bytes used by each element of the column: component_bytes * num_components...
TypeHandle is the identifier used to differentiate C++ class types.
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
virtual bool unref() const
Explicitly decrements the reference count.
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.
int compare_to(const GeomVertexColumn &other) const
This is used to unquify columns, and hence formats, for the GeomVertexFormat registry.