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();
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
int get_total_bytes() const
Returns the number of bytes used by each element of the column: component_bytes * num_components...
Base class for objects that can be written to and read from Bam files.
const InternalName * get_name() const
Returns the name of this particular data field, e.g.
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().
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
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()...
virtual bool unref() const
Explicitly decrements the reference count.
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...
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.
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.
This is our own Panda specialization on the default STL set.
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
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 get_num_rows() const
Returns the number of rows stored within all the arrays.