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) {
419 get_column(
const InternalName *name)
const {
420 ColumnsByName::const_iterator ni;
421 ni = _columns_by_name.find(name);
422 if (ni != _columns_by_name.end()) {
436 get_column(
int start_byte,
int num_bytes)
const {
437 consider_sort_columns();
438 Columns::const_iterator ci;
439 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
459 bool GeomVertexArrayFormat::
460 is_data_subset_of(
const GeomVertexArrayFormat &other)
const {
461 if (_columns.size() > other._columns.size() ||
462 get_stride() != other.get_stride()) {
466 consider_sort_columns();
467 other.consider_sort_columns();
470 while (i < _columns.size() && j < other._columns.size()) {
471 if (*_columns[i] == *other._columns[j]) {
478 return (i == _columns.size());
487 int GeomVertexArrayFormat::
488 count_unused_space()
const {
489 consider_sort_columns();
491 int unused_space = 0;
494 Columns::const_iterator ci;
495 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
498 unused_space += (column->
get_start() - last_pos);
503 if (_stride > last_pos) {
504 unused_space += (_stride - last_pos);
515 void GeomVertexArrayFormat::
516 output(ostream &out)
const {
517 Columns::const_iterator ci;
520 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
523 out <<
" (..." << (column->
get_start() - last_pos) <<
"...)";
525 out <<
" " << *column;
526 last_pos = column->
get_start() + column->get_total_bytes();
529 if (_stride > last_pos) {
530 out <<
" ..." << (_stride - last_pos) <<
"...";
541 void GeomVertexArrayFormat::
542 write(ostream &out,
int indent_level)
const {
543 indent(out, indent_level)
544 <<
"Array format (stride = " << get_stride() <<
"):\n";
545 consider_sort_columns();
546 Columns::const_iterator ci;
547 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
549 indent(out, indent_level + 2)
553 <<
" start at " << column->
get_start() <<
"\n";
562 void GeomVertexArrayFormat::
563 write_with_data(ostream &out,
int indent_level,
565 consider_sort_columns();
570 for (
int i = 0; i < num_rows; i++) {
571 indent(out, indent_level)
572 <<
"row " << i <<
":\n";
573 reader.set_row_unsafe(i);
574 Columns::const_iterator ci;
575 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
578 reader.set_column(0, column);
581 indent(out, indent_level + 2)
583 for (
int v = 0; v < num_values; v++) {
600 string GeomVertexArrayFormat::
601 get_format_string(
bool pad)
const {
602 consider_sort_columns();
606 row_size = get_stride();
608 row_size = get_total_bytes();
612 char *fmt = (
char*) malloc(row_size + 1);
613 memset((
void*) fmt, 0, row_size + 1);
617 for (
int ci = 0; ci < get_num_columns(); ++ci) {
620 if (offset < column->get_start()) {
623 memset((
void*) (fmt + fi),
'x', pad);
657 if (offset < row_size) {
659 int pad = row_size - offset;
660 memset((
void*) (fmt + fi),
'x', pad);
663 string fmt_string (fmt);
673 int GeomVertexArrayFormat::
674 compare_to(
const GeomVertexArrayFormat &other)
const {
675 if (_stride != other._stride) {
676 return _stride - other._stride;
678 if (_total_bytes != other._total_bytes) {
679 return _total_bytes - other._total_bytes;
681 if (_pad_to != other._pad_to) {
682 return _pad_to - other._pad_to;
684 if (_divisor != other._divisor) {
685 return _divisor - other._divisor;
687 if (_columns.size() != other._columns.size()) {
688 return (
int)_columns.size() - (int)other._columns.size();
690 consider_sort_columns();
691 other.consider_sort_columns();
692 for (
size_t i = 0; i < _columns.size(); i++) {
693 int compare = _columns[i]->compare_to(*other._columns[i]);
709 void GeomVertexArrayFormat::
719 void GeomVertexArrayFormat::
721 if (_registry == (Registry *)NULL) {
722 _registry =
new Registry;
731 void GeomVertexArrayFormat::
733 nassertv(!_is_registered);
734 _is_registered =
true;
742 void GeomVertexArrayFormat::
744 nassertv(_is_registered);
745 _is_registered =
false;
754 void GeomVertexArrayFormat::
755 register_with_read_factory() {
765 void GeomVertexArrayFormat::
774 consider_sort_columns();
777 Columns::iterator ci;
778 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
791 int GeomVertexArrayFormat::
795 Columns::iterator ci;
796 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
811 void GeomVertexArrayFormat::
817 _columns_by_name.clear();
818 Columns::iterator ci;
819 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
821 _columns_by_name.insert(ColumnsByName::value_type(column->
get_name(), column));
836 GeomVertexArrayFormat *
object =
new GeomVertexArrayFormat;
840 parse_params(params, scan, manager);
841 object->fillin(scan, manager);
854 void GeomVertexArrayFormat::
857 nassertv(!_is_registered);
869 _columns.reserve(num_columns);
870 for (
int i = 0; i < num_columns; ++i) {
872 column->
fillin(scan, manager);
873 _columns.push_back(column);
875 _columns_unsorted =
false;
883 GeomVertexArrayFormat::Registry::
902 CPT(GeomVertexArrayFormat) GeomVertexArrayFormat::Registry::
903 register_format(GeomVertexArrayFormat *format) {
904 if (format->is_registered()) {
911 PT(GeomVertexArrayFormat) pt_format = format;
913 GeomVertexArrayFormat *new_format;
916 ArrayFormats::iterator fi = _formats.insert(format).first;
918 if (!new_format->is_registered()) {
919 new_format->do_register();
935 void GeomVertexArrayFormat::Registry::
936 unregister_format(GeomVertexArrayFormat *format) {
937 nassertv(format->is_registered());
938 ArrayFormats::iterator fi = _formats.find(format);
939 nassertv(fi != _formats.end());
941 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...
int get_num_rows() const
Returns the number of rows stored in the array, based on the number of bytes and the stride...
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...
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 ...
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_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
int get_column_alignment() const
Returns the alignment requirements for this column.
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.
int get_start() const
Returns the byte within the array record at which this column starts.
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()...
virtual bool unref() const
Explicitly decrements the reference count.
Similar to MutexHolder, but for a light mutex.
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.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
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.
This is the base class for all three-component vectors and points.
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 object provides a high-level interface for quickly reading a sequence of numeric values from a v...
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.
A class to retrieve the individual data elements previously stored in a Datagram. ...
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.
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()...
This is the data for one array of a GeomVertexData structure.