15 #include "geomVertexFormat.h" 16 #include "geomVertexColumn.h" 17 #include "geomVertexData.h" 18 #include "geomVertexReader.h" 20 #include "bamReader.h" 21 #include "bamWriter.h" 22 #include "indirectLess.h" 23 #include "lightMutexHolder.h" 25 GeomVertexArrayFormat::Registry *GeomVertexArrayFormat::_registry = NULL;
26 TypeHandle GeomVertexArrayFormat::_type_handle;
33 GeomVertexArrayFormat::
34 GeomVertexArrayFormat() :
35 _is_registered(false),
40 _columns_unsorted(false)
49 GeomVertexArrayFormat::
51 GeomVertexArrayFormat::NumericType numeric_type0,
52 GeomVertexArrayFormat::Contents contents0) :
53 _is_registered(false),
58 _columns_unsorted(false)
60 add_column(MOVE(name0), num_components0, numeric_type0, contents0);
68 GeomVertexArrayFormat::
70 GeomVertexArrayFormat::NumericType numeric_type0,
71 GeomVertexArrayFormat::Contents contents0,
73 GeomVertexArrayFormat::NumericType numeric_type1,
74 GeomVertexArrayFormat::Contents contents1) :
75 _is_registered(false),
80 _columns_unsorted(false)
82 add_column(MOVE(name0), num_components0, numeric_type0, contents0);
83 add_column(MOVE(name1), num_components1, numeric_type1, contents1);
91 GeomVertexArrayFormat::
93 GeomVertexArrayFormat::NumericType numeric_type0,
94 GeomVertexArrayFormat::Contents contents0,
96 GeomVertexArrayFormat::NumericType numeric_type1,
97 GeomVertexArrayFormat::Contents contents1,
99 GeomVertexArrayFormat::NumericType numeric_type2,
100 GeomVertexArrayFormat::Contents contents2) :
101 _is_registered(false),
106 _columns_unsorted(false)
108 add_column(MOVE(name0), num_components0, numeric_type0, contents0);
109 add_column(MOVE(name1), num_components1, numeric_type1, contents1);
110 add_column(MOVE(name2), num_components2, numeric_type2, contents2);
118 GeomVertexArrayFormat::
120 GeomVertexArrayFormat::NumericType numeric_type0,
121 GeomVertexArrayFormat::Contents contents0,
123 GeomVertexArrayFormat::NumericType numeric_type1,
124 GeomVertexArrayFormat::Contents contents1,
126 GeomVertexArrayFormat::NumericType numeric_type2,
127 GeomVertexArrayFormat::Contents contents2,
129 GeomVertexArrayFormat::NumericType numeric_type3,
130 GeomVertexArrayFormat::Contents contents3) :
131 _is_registered(false),
136 _columns_unsorted(false)
138 add_column(MOVE(name0), num_components0, numeric_type0, contents0);
139 add_column(MOVE(name1), num_components1, numeric_type1, contents1);
140 add_column(MOVE(name2), num_components2, numeric_type2, contents2);
141 add_column(MOVE(name3), num_components3, numeric_type3, contents3);
149 GeomVertexArrayFormat::
150 GeomVertexArrayFormat(
const GeomVertexArrayFormat ©) :
151 _is_registered(false),
152 _stride(copy._stride),
153 _total_bytes(copy._total_bytes),
154 _pad_to(copy._pad_to),
155 _divisor(copy._divisor),
156 _columns_unsorted(copy._columns_unsorted)
158 Columns::const_iterator dti;
159 for (dti = copy._columns.begin(); dti != copy._columns.end(); ++dti) {
169 void GeomVertexArrayFormat::
170 operator = (
const GeomVertexArrayFormat ©) {
171 nassertv(!_is_registered);
172 _stride = copy._stride;
173 _total_bytes = copy._total_bytes;
174 _pad_to = copy._pad_to;
175 _divisor = copy._divisor;
178 _columns_by_name.clear();
179 _columns_unsorted =
false;
180 Columns::const_iterator dti;
181 for (dti = copy._columns.begin(); dti != copy._columns.end(); ++dti) {
191 GeomVertexArrayFormat::
192 ~GeomVertexArrayFormat() {
194 nassertv(!is_registered());
196 Columns::iterator ci;
197 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
209 bool GeomVertexArrayFormat::
211 Registry *registry = get_registry();
218 if (is_registered()) {
219 registry->unregister_format((GeomVertexArrayFormat *)
this);
237 int GeomVertexArrayFormat::
239 GeomVertexArrayFormat::NumericType numeric_type,
240 GeomVertexArrayFormat::Contents contents,
int start,
241 int column_alignment) {
243 start = _total_bytes;
246 return add_column(
GeomVertexColumn(MOVE(name), num_components, numeric_type, contents,
247 start, column_alignment));
266 int GeomVertexArrayFormat::
268 nassertr(!_is_registered, -1);
277 remove_column(orig_column->get_name());
283 _stride = max(_stride, _total_bytes);
285 _stride = ((_stride + _pad_to - 1) / _pad_to) * _pad_to;
290 if (!_columns.empty() && *new_column < *_columns.back()) {
291 _columns_unsorted =
true;
294 int new_index = (int)_columns.size();
295 _columns.push_back(new_column);
296 _columns_by_name.insert(ColumnsByName::value_type(new_column->
get_name(), new_column));
307 void GeomVertexArrayFormat::
308 remove_column(
const InternalName *name) {
309 nassertv(!_is_registered);
310 ColumnsByName::iterator ni;
311 ni = _columns_by_name.find(name);
312 if (ni != _columns_by_name.end()) {
314 _columns_by_name.erase(ni);
316 Columns::iterator ci;
317 ci = find(_columns.begin(), _columns.end(), column);
318 nassertv(ci != _columns.end());
325 if (_columns.empty()) {
328 consider_sort_columns();
341 void GeomVertexArrayFormat::
343 nassertv(!_is_registered);
346 _columns_by_name.clear();
347 _columns_unsorted =
false;
358 void GeomVertexArrayFormat::
360 nassertv(!_is_registered);
362 Columns orig_columns;
363 orig_columns.swap(_columns);
366 Columns::const_iterator ci;
367 for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
386 void GeomVertexArrayFormat::
387 align_columns_for_animation() {
388 nassertv(!_is_registered);
390 Columns orig_columns;
391 orig_columns.swap(_columns);
394 Columns::const_iterator ci;
395 for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
420 get_column(
const InternalName *name)
const {
421 ColumnsByName::const_iterator ni;
422 ni = _columns_by_name.find(name);
423 if (ni != _columns_by_name.end()) {
437 get_column(
int start_byte,
int num_bytes)
const {
438 consider_sort_columns();
439 Columns::const_iterator ci;
440 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
460 bool GeomVertexArrayFormat::
461 is_data_subset_of(
const GeomVertexArrayFormat &other)
const {
462 if (_columns.size() > other._columns.size() ||
463 get_stride() != other.get_stride()) {
467 consider_sort_columns();
468 other.consider_sort_columns();
471 while (i < _columns.size() && j < other._columns.size()) {
472 if (*_columns[i] == *other._columns[j]) {
479 return (i == _columns.size());
488 int GeomVertexArrayFormat::
489 count_unused_space()
const {
490 consider_sort_columns();
492 int unused_space = 0;
495 Columns::const_iterator ci;
496 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
499 unused_space += (column->
get_start() - last_pos);
504 if (_stride > last_pos) {
505 unused_space += (_stride - last_pos);
516 void GeomVertexArrayFormat::
517 output(ostream &out)
const {
518 Columns::const_iterator ci;
521 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
524 out <<
" (..." << (column->
get_start() - last_pos) <<
"...)";
526 out <<
" " << *column;
527 last_pos = column->
get_start() + column->get_total_bytes();
530 if (_stride > last_pos) {
531 out <<
" ..." << (_stride - last_pos) <<
"...";
542 void GeomVertexArrayFormat::
543 write(ostream &out,
int indent_level)
const {
544 indent(out, indent_level)
545 <<
"Array format (stride = " << get_stride() <<
"):\n";
546 consider_sort_columns();
547 Columns::const_iterator ci;
548 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
550 indent(out, indent_level + 2)
554 <<
" start at " << column->
get_start() <<
"\n";
563 void GeomVertexArrayFormat::
564 write_with_data(ostream &out,
int indent_level,
566 consider_sort_columns();
571 for (
int i = 0; i < num_rows; i++) {
572 indent(out, indent_level)
573 <<
"row " << i <<
":\n";
574 reader.set_row_unsafe(i);
575 Columns::const_iterator ci;
576 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
579 reader.set_column(0, column);
582 indent(out, indent_level + 2)
584 for (
int v = 0; v < num_values; v++) {
601 string GeomVertexArrayFormat::
602 get_format_string(
bool pad)
const {
603 consider_sort_columns();
607 row_size = get_stride();
609 row_size = get_total_bytes();
613 char *fmt = (
char*) malloc(row_size + 1);
614 memset((
void*) fmt, 0, row_size + 1);
618 for (
int ci = 0; ci < get_num_columns(); ++ci) {
621 if (offset < column->get_start()) {
624 memset((
void*) (fmt + fi),
'x', pad);
658 if (offset < row_size) {
660 int pad = row_size - offset;
661 memset((
void*) (fmt + fi),
'x', pad);
664 string fmt_string (fmt);
674 int GeomVertexArrayFormat::
675 compare_to(
const GeomVertexArrayFormat &other)
const {
676 if (_stride != other._stride) {
677 return _stride - other._stride;
679 if (_total_bytes != other._total_bytes) {
680 return _total_bytes - other._total_bytes;
682 if (_pad_to != other._pad_to) {
683 return _pad_to - other._pad_to;
685 if (_divisor != other._divisor) {
686 return _divisor - other._divisor;
688 if (_columns.size() != other._columns.size()) {
689 return (
int)_columns.size() - (int)other._columns.size();
691 consider_sort_columns();
692 other.consider_sort_columns();
693 for (
size_t i = 0; i < _columns.size(); i++) {
694 int compare = _columns[i]->compare_to(*other._columns[i]);
710 void GeomVertexArrayFormat::
720 void GeomVertexArrayFormat::
722 if (_registry == (Registry *)NULL) {
723 _registry =
new Registry;
732 void GeomVertexArrayFormat::
734 nassertv(!_is_registered);
735 _is_registered =
true;
743 void GeomVertexArrayFormat::
745 nassertv(_is_registered);
746 _is_registered =
false;
755 void GeomVertexArrayFormat::
756 register_with_read_factory() {
766 void GeomVertexArrayFormat::
775 consider_sort_columns();
778 Columns::iterator ci;
779 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
792 int GeomVertexArrayFormat::
796 Columns::iterator ci;
797 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
812 void GeomVertexArrayFormat::
818 _columns_by_name.clear();
819 Columns::iterator ci;
820 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
822 _columns_by_name.insert(ColumnsByName::value_type(column->
get_name(), column));
837 GeomVertexArrayFormat *
object =
new GeomVertexArrayFormat;
841 parse_params(params, scan, manager);
842 object->fillin(scan, manager);
855 void GeomVertexArrayFormat::
858 nassertv(!_is_registered);
870 _columns.reserve(num_columns);
871 for (
int i = 0; i < num_columns; ++i) {
873 column->
fillin(scan, manager);
874 _columns.push_back(column);
876 _columns_unsorted =
false;
884 GeomVertexArrayFormat::Registry::
903 CPT(GeomVertexArrayFormat) GeomVertexArrayFormat::Registry::
904 register_format(GeomVertexArrayFormat *format) {
905 if (format->is_registered()) {
912 PT(GeomVertexArrayFormat) pt_format = format;
914 GeomVertexArrayFormat *new_format;
917 ArrayFormats::iterator fi = _formats.insert(format).first;
919 if (!new_format->is_registered()) {
920 new_format->do_register();
936 void GeomVertexArrayFormat::Registry::
937 unregister_format(GeomVertexArrayFormat *format) {
938 nassertv(format->is_registered());
939 ArrayFormats::iterator fi = _formats.find(format);
940 nassertv(fi != _formats.end());
942 format->do_unregister();
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
This is a const pointer to an InternalName, and should be used in lieu of a CPT(InternalName) in func...
bool overlaps_with(int start_byte, int num_bytes) const
Returns true if this column overlaps with any of the bytes in the indicated range, false if it does not.
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is called by make_from_bam to read in all of the relevant data from the BamFil...
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 ...
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
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.
An STL function object class, this is intended to be used on any ordered collection of pointers to cl...
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()...
Similar to MutexHolder, but for a light mutex.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
int get_num_values() const
Returns the number of numeric values of the column: the number of distinct numeric values that go int...
int get_column_alignment() const
Returns the alignment requirements for this column.
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
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.
int get_start() const
Returns the byte within the array record at which this column starts.
This is the base class for all three-component vectors and points.
int get_num_rows() const
Returns the number of rows stored in the array, based on the number of bytes and the stride...
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
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 ...
int complete_pointers(TypedWritable **plist, 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 is the data for one array of a GeomVertexData structure.