geomVertexArrayFormat.cxx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file geomVertexArrayFormat.cxx
  10. * @author drose
  11. * @date 2005-03-06
  12. */
  13. #include "geomVertexFormat.h"
  14. #include "geomVertexColumn.h"
  15. #include "geomVertexData.h"
  16. #include "geomVertexReader.h"
  17. #include "indent.h"
  18. #include "bamReader.h"
  19. #include "bamWriter.h"
  20. #include "indirectLess.h"
  21. #include "lightMutexHolder.h"
  22. using std::max;
  23. using std::min;
  24. GeomVertexArrayFormat::Registry *GeomVertexArrayFormat::_registry = nullptr;
  25. TypeHandle GeomVertexArrayFormat::_type_handle;
  26. /**
  27. *
  28. */
  29. GeomVertexArrayFormat::
  30. GeomVertexArrayFormat() :
  31. _is_registered(false),
  32. _stride(0),
  33. _total_bytes(0),
  34. _pad_to(1),
  35. _divisor(0),
  36. _columns_unsorted(false)
  37. {
  38. }
  39. /**
  40. *
  41. */
  42. GeomVertexArrayFormat::
  43. GeomVertexArrayFormat(CPT_InternalName name0, int num_components0,
  44. GeomVertexArrayFormat::NumericType numeric_type0,
  45. GeomVertexArrayFormat::Contents contents0) :
  46. _is_registered(false),
  47. _stride(0),
  48. _total_bytes(0),
  49. _pad_to(1),
  50. _divisor(0),
  51. _columns_unsorted(false)
  52. {
  53. add_column(std::move(name0), num_components0, numeric_type0, contents0);
  54. }
  55. /**
  56. *
  57. */
  58. GeomVertexArrayFormat::
  59. GeomVertexArrayFormat(CPT_InternalName name0, int num_components0,
  60. GeomVertexArrayFormat::NumericType numeric_type0,
  61. GeomVertexArrayFormat::Contents contents0,
  62. CPT_InternalName name1, int num_components1,
  63. GeomVertexArrayFormat::NumericType numeric_type1,
  64. GeomVertexArrayFormat::Contents contents1) :
  65. _is_registered(false),
  66. _stride(0),
  67. _total_bytes(0),
  68. _pad_to(1),
  69. _divisor(0),
  70. _columns_unsorted(false)
  71. {
  72. add_column(std::move(name0), num_components0, numeric_type0, contents0);
  73. add_column(std::move(name1), num_components1, numeric_type1, contents1);
  74. }
  75. /**
  76. *
  77. */
  78. GeomVertexArrayFormat::
  79. GeomVertexArrayFormat(CPT_InternalName name0, int num_components0,
  80. GeomVertexArrayFormat::NumericType numeric_type0,
  81. GeomVertexArrayFormat::Contents contents0,
  82. CPT_InternalName name1, int num_components1,
  83. GeomVertexArrayFormat::NumericType numeric_type1,
  84. GeomVertexArrayFormat::Contents contents1,
  85. CPT_InternalName name2, int num_components2,
  86. GeomVertexArrayFormat::NumericType numeric_type2,
  87. GeomVertexArrayFormat::Contents contents2) :
  88. _is_registered(false),
  89. _stride(0),
  90. _total_bytes(0),
  91. _pad_to(1),
  92. _divisor(0),
  93. _columns_unsorted(false)
  94. {
  95. add_column(std::move(name0), num_components0, numeric_type0, contents0);
  96. add_column(std::move(name1), num_components1, numeric_type1, contents1);
  97. add_column(std::move(name2), num_components2, numeric_type2, contents2);
  98. }
  99. /**
  100. *
  101. */
  102. GeomVertexArrayFormat::
  103. GeomVertexArrayFormat(CPT_InternalName name0, int num_components0,
  104. GeomVertexArrayFormat::NumericType numeric_type0,
  105. GeomVertexArrayFormat::Contents contents0,
  106. CPT_InternalName name1, int num_components1,
  107. GeomVertexArrayFormat::NumericType numeric_type1,
  108. GeomVertexArrayFormat::Contents contents1,
  109. CPT_InternalName name2, int num_components2,
  110. GeomVertexArrayFormat::NumericType numeric_type2,
  111. GeomVertexArrayFormat::Contents contents2,
  112. CPT_InternalName name3, int num_components3,
  113. GeomVertexArrayFormat::NumericType numeric_type3,
  114. GeomVertexArrayFormat::Contents contents3) :
  115. _is_registered(false),
  116. _stride(0),
  117. _total_bytes(0),
  118. _pad_to(1),
  119. _divisor(0),
  120. _columns_unsorted(false)
  121. {
  122. add_column(std::move(name0), num_components0, numeric_type0, contents0);
  123. add_column(std::move(name1), num_components1, numeric_type1, contents1);
  124. add_column(std::move(name2), num_components2, numeric_type2, contents2);
  125. add_column(std::move(name3), num_components3, numeric_type3, contents3);
  126. }
  127. /**
  128. *
  129. */
  130. GeomVertexArrayFormat::
  131. GeomVertexArrayFormat(const GeomVertexArrayFormat &copy) :
  132. _is_registered(false),
  133. _stride(copy._stride),
  134. _total_bytes(copy._total_bytes),
  135. _pad_to(copy._pad_to),
  136. _divisor(copy._divisor),
  137. _columns_unsorted(copy._columns_unsorted)
  138. {
  139. Columns::const_iterator dti;
  140. for (dti = copy._columns.begin(); dti != copy._columns.end(); ++dti) {
  141. add_column(*(*dti));
  142. }
  143. }
  144. /**
  145. *
  146. */
  147. void GeomVertexArrayFormat::
  148. operator = (const GeomVertexArrayFormat &copy) {
  149. nassertv(!_is_registered);
  150. _stride = copy._stride;
  151. _total_bytes = copy._total_bytes;
  152. _pad_to = copy._pad_to;
  153. _divisor = copy._divisor;
  154. _columns.clear();
  155. _columns_by_name.clear();
  156. _columns_unsorted = false;
  157. Columns::const_iterator dti;
  158. for (dti = copy._columns.begin(); dti != copy._columns.end(); ++dti) {
  159. add_column(*(*dti));
  160. }
  161. }
  162. /**
  163. *
  164. */
  165. GeomVertexArrayFormat::
  166. ~GeomVertexArrayFormat() {
  167. // unref() should have unregistered us.
  168. nassertv(!is_registered());
  169. Columns::iterator ci;
  170. for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
  171. delete (*ci);
  172. }
  173. }
  174. /**
  175. * This method overrides ReferenceCount::unref() to unregister the object when
  176. * its reference count goes to zero.
  177. */
  178. bool GeomVertexArrayFormat::
  179. unref() const {
  180. Registry *registry = get_registry();
  181. LightMutexHolder holder(registry->_lock);
  182. if (ReferenceCount::unref()) {
  183. return true;
  184. }
  185. if (is_registered()) {
  186. registry->unregister_format((GeomVertexArrayFormat *)this);
  187. }
  188. return false;
  189. }
  190. /**
  191. * Adds a new column to the specification. This is a table of per-vertex
  192. * floating-point numbers such as "vertex" or "normal"; you must specify where
  193. * in each record the table starts, and how many components (dimensions) exist
  194. * per vertex.
  195. *
  196. * The return value is the index number of the new data type.
  197. */
  198. int GeomVertexArrayFormat::
  199. add_column(CPT_InternalName name, int num_components,
  200. GeomVertexArrayFormat::NumericType numeric_type,
  201. GeomVertexArrayFormat::Contents contents, int start,
  202. int column_alignment) {
  203. if (start < 0) {
  204. start = _total_bytes;
  205. }
  206. return add_column(GeomVertexColumn(std::move(name), num_components, numeric_type, contents,
  207. start, column_alignment));
  208. }
  209. /**
  210. * Adds a new column to the specification. This is a table of per-vertex
  211. * floating-point numbers such as "vertex" or "normal"; you must specify where
  212. * in each record the table starts, and how many components (dimensions) exist
  213. * per vertex.
  214. *
  215. * Adding a column with the same name as a previous type, or that overlaps
  216. * with one or more previous types, quietly removes the previous type(s).
  217. *
  218. * The return value is the index number of the new data type.
  219. */
  220. int GeomVertexArrayFormat::
  221. add_column(const GeomVertexColumn &column) {
  222. nassertr(!_is_registered, -1);
  223. // Make sure there isn't already a column with this name.
  224. remove_column(column.get_name());
  225. // Also make sure there aren't any columns that overlap with this one.
  226. const GeomVertexColumn *orig_column = get_column(column.get_start(), column.get_total_bytes());
  227. while (orig_column != nullptr) {
  228. remove_column(orig_column->get_name());
  229. orig_column = get_column(column.get_start(), column.get_total_bytes());
  230. }
  231. _total_bytes = max(_total_bytes, column.get_start() + column.get_total_bytes());
  232. _pad_to = max(_pad_to, column.get_column_alignment());
  233. _stride = max(_stride, _total_bytes);
  234. if (_pad_to > 1) {
  235. _stride = ((_stride + _pad_to - 1) / _pad_to) * _pad_to;
  236. }
  237. GeomVertexColumn *new_column = new GeomVertexColumn(column);
  238. if (!_columns.empty() && *new_column < *_columns.back()) {
  239. _columns_unsorted = true;
  240. }
  241. int new_index = (int)_columns.size();
  242. _columns.push_back(new_column);
  243. _columns_by_name.insert(ColumnsByName::value_type(new_column->get_name(), new_column));
  244. return new_index;
  245. }
  246. /**
  247. * Removes the column with the indicated name, if any. This leaves a gap in
  248. * the byte structure.
  249. */
  250. void GeomVertexArrayFormat::
  251. remove_column(const InternalName *name) {
  252. nassertv(!_is_registered);
  253. ColumnsByName::iterator ni;
  254. ni = _columns_by_name.find(name);
  255. if (ni != _columns_by_name.end()) {
  256. GeomVertexColumn *column = (*ni).second;
  257. _columns_by_name.erase(ni);
  258. Columns::iterator ci;
  259. ci = find(_columns.begin(), _columns.end(), column);
  260. nassertv(ci != _columns.end());
  261. _columns.erase(ci);
  262. delete column;
  263. // Maybe we just removed the tail column. If that's so, we should
  264. // recompute _total_bytes to reflect the new tail.
  265. if (_columns.empty()) {
  266. _total_bytes = 0;
  267. } else {
  268. consider_sort_columns();
  269. GeomVertexColumn *last = _columns.back();
  270. _total_bytes = last->get_start() + last->get_total_bytes();
  271. }
  272. }
  273. }
  274. /**
  275. * Removes all columns previously added, sets the stride to zero, and prepares
  276. * to start over.
  277. */
  278. void GeomVertexArrayFormat::
  279. clear_columns() {
  280. nassertv(!_is_registered);
  281. _columns.clear();
  282. _columns_by_name.clear();
  283. _columns_unsorted = false;
  284. _stride = 0;
  285. _total_bytes = 0;
  286. _pad_to = 1;
  287. }
  288. /**
  289. * Removes wasted space between columns.
  290. */
  291. void GeomVertexArrayFormat::
  292. pack_columns() {
  293. nassertv(!_is_registered);
  294. Columns orig_columns;
  295. orig_columns.swap(_columns);
  296. clear_columns();
  297. Columns::const_iterator ci;
  298. for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
  299. GeomVertexColumn *column = (*ci);
  300. add_column(column->get_name(), column->get_num_components(),
  301. column->get_numeric_type(), column->get_contents());
  302. }
  303. }
  304. /**
  305. * Reprocesses the columns in the format to align the C_point and C_vector
  306. * columns to 16-byte boundaries to allow for the more efficient SSE2
  307. * operations (assuming SSE2 is enabled in the build).
  308. *
  309. * The caller is responsible for testing vertex_animation_align_16 to decide
  310. * whether to call this method.
  311. */
  312. void GeomVertexArrayFormat::
  313. align_columns_for_animation() {
  314. nassertv(!_is_registered);
  315. Columns orig_columns;
  316. orig_columns.swap(_columns);
  317. clear_columns();
  318. Columns::const_iterator ci;
  319. for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
  320. GeomVertexColumn *column = (*ci);
  321. if ((column->get_contents() == C_point ||
  322. column->get_contents() == C_vector ||
  323. column->get_contents() == C_normal) &&
  324. (column->get_numeric_type() == NT_float32 ||
  325. column->get_numeric_type() == NT_float64) &&
  326. column->get_num_components() >= 3) {
  327. add_column(column->get_name(), 4, column->get_numeric_type(), column->get_contents(), -1, 16);
  328. } else {
  329. add_column(column->get_name(), column->get_num_components(),
  330. column->get_numeric_type(), column->get_contents(),
  331. -1, column->get_column_alignment());
  332. }
  333. }
  334. }
  335. /**
  336. * Returns the specification with the indicated name, or NULL if the name is
  337. * not used.
  338. */
  339. const GeomVertexColumn *GeomVertexArrayFormat::
  340. get_column(const InternalName *name) const {
  341. ColumnsByName::const_iterator ni;
  342. ni = _columns_by_name.find(name);
  343. if (ni != _columns_by_name.end()) {
  344. return (*ni).second;
  345. }
  346. return nullptr;
  347. }
  348. /**
  349. * Returns the first specification that overlaps with any of the indicated
  350. * bytes in the range, or NULL if none do.
  351. */
  352. const GeomVertexColumn *GeomVertexArrayFormat::
  353. get_column(int start_byte, int num_bytes) const {
  354. consider_sort_columns();
  355. Columns::const_iterator ci;
  356. for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
  357. const GeomVertexColumn *column = (*ci);
  358. if (column->overlaps_with(start_byte, num_bytes)) {
  359. return column;
  360. }
  361. }
  362. return nullptr;
  363. }
  364. /**
  365. * Returns true if all of the fields in this array format are also present and
  366. * equivalent in the other array format, and in the same byte positions, and
  367. * the stride is the same. That is, true if this format can share the same
  368. * data pointer as the other format (with possibly some unused gaps).
  369. */
  370. bool GeomVertexArrayFormat::
  371. is_data_subset_of(const GeomVertexArrayFormat &other) const {
  372. if (_columns.size() > other._columns.size() ||
  373. get_stride() != other.get_stride()) {
  374. return false;
  375. }
  376. consider_sort_columns();
  377. other.consider_sort_columns();
  378. size_t i = 0;
  379. size_t j = 0;
  380. while (i < _columns.size() && j < other._columns.size()) {
  381. if (*_columns[i] == *other._columns[j]) {
  382. ++i;
  383. }
  384. ++j;
  385. }
  386. // If we reached the end of our list, all fields matched.
  387. return (i == _columns.size());
  388. }
  389. /**
  390. * Returns the number of bytes per row that are not assigned to any column.
  391. */
  392. int GeomVertexArrayFormat::
  393. count_unused_space() const {
  394. consider_sort_columns();
  395. int unused_space = 0;
  396. int last_pos = 0;
  397. Columns::const_iterator ci;
  398. for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
  399. const GeomVertexColumn *column = (*ci);
  400. if (column->get_start() > last_pos) {
  401. unused_space += (column->get_start() - last_pos);
  402. }
  403. last_pos = column->get_start() + column->get_total_bytes();
  404. }
  405. if (_stride > last_pos) {
  406. unused_space += (_stride - last_pos);
  407. }
  408. return unused_space;
  409. }
  410. /**
  411. *
  412. */
  413. void GeomVertexArrayFormat::
  414. output(std::ostream &out) const {
  415. Columns::const_iterator ci;
  416. int last_pos = 0;
  417. out << "[";
  418. for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
  419. const GeomVertexColumn *column = (*ci);
  420. if (column->get_start() > last_pos) {
  421. out << " (..." << (column->get_start() - last_pos) << "...)";
  422. }
  423. out << " " << *column;
  424. last_pos = column->get_start() + column->get_total_bytes();
  425. }
  426. if (_stride > last_pos) {
  427. out << " ..." << (_stride - last_pos) << "...";
  428. }
  429. out << " ]";
  430. }
  431. /**
  432. *
  433. */
  434. void GeomVertexArrayFormat::
  435. write(std::ostream &out, int indent_level) const {
  436. indent(out, indent_level)
  437. << "Array format (stride = " << get_stride() << "):\n";
  438. consider_sort_columns();
  439. Columns::const_iterator ci;
  440. for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
  441. const GeomVertexColumn *column = (*ci);
  442. indent(out, indent_level + 2)
  443. << *column
  444. << " " << column->get_numeric_type()
  445. << " " << column->get_contents()
  446. << " start at " << column->get_start() << "\n";
  447. }
  448. }
  449. /**
  450. *
  451. */
  452. void GeomVertexArrayFormat::
  453. write_with_data(std::ostream &out, int indent_level,
  454. const GeomVertexArrayData *array_data) const {
  455. consider_sort_columns();
  456. int num_rows = array_data->get_num_rows();
  457. GeomVertexReader reader(array_data);
  458. for (int i = 0; i < num_rows; i++) {
  459. indent(out, indent_level)
  460. << "row " << i << ":\n";
  461. reader.set_row_unsafe(i);
  462. Columns::const_iterator ci;
  463. for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
  464. const GeomVertexColumn *column = (*ci);
  465. int num_values = min(column->get_num_values(), 4);
  466. reader.set_column(0, column);
  467. const LVecBase4f &d = reader.get_data4f();
  468. indent(out, indent_level + 2)
  469. << *column->get_name();
  470. for (int v = 0; v < num_values; v++) {
  471. out << " " << d[v];
  472. }
  473. out << "\n";
  474. }
  475. }
  476. }
  477. /**
  478. * Returns a string with format codes representing the exact memory layout of
  479. * the columns in memory, as understood by Python's struct module. If pad is
  480. * true, extra padding bytes are added to the end as 'x' characters as needed.
  481. */
  482. std::string GeomVertexArrayFormat::
  483. get_format_string(bool pad) const {
  484. consider_sort_columns();
  485. int row_size;
  486. if (pad) {
  487. row_size = get_stride();
  488. } else {
  489. row_size = get_total_bytes();
  490. }
  491. // Synthesize the format string.
  492. char *fmt = (char *)alloca(row_size + 1);
  493. memset((void *)fmt, 0, row_size + 1);
  494. int fi = 0;
  495. int offset = 0;
  496. for (const GeomVertexColumn *column : _columns) {
  497. if (offset < column->get_start()) {
  498. // Add padding bytes to fill the gap.
  499. int pad = column->get_start() - offset;
  500. memset((void*) (fmt + fi), 'x', pad);
  501. fi += pad;
  502. offset += pad;
  503. }
  504. char fmt_code = 'x';
  505. int num_components = column->get_num_components();
  506. switch (column->get_numeric_type()) {
  507. case NT_uint8:
  508. fmt_code = 'B';
  509. break;
  510. case NT_uint16:
  511. fmt_code = 'H';
  512. break;
  513. case NT_uint32:
  514. case NT_packed_dcba:
  515. case NT_packed_dabc:
  516. case NT_packed_ufloat:
  517. fmt_code = 'I';
  518. break;
  519. case NT_float32:
  520. fmt_code = 'f';
  521. break;
  522. case NT_float64:
  523. fmt_code = 'd';
  524. break;
  525. case NT_int8:
  526. fmt_code = 'b';
  527. break;
  528. case NT_int16:
  529. fmt_code = 'h';
  530. break;
  531. case NT_int32:
  532. fmt_code = 'i';
  533. break;
  534. default:
  535. gobj_cat.error()
  536. << "Unknown numeric type " << column->get_numeric_type() << "!\n";
  537. num_components *= column->get_component_bytes();
  538. }
  539. memset((void*) (fmt + fi), fmt_code, num_components);
  540. offset += column->get_total_bytes();
  541. fi += num_components;
  542. }
  543. if (offset < row_size) {
  544. // Add padding bytes.
  545. int pad = row_size - offset;
  546. memset((void *)(fmt + fi), 'x', pad);
  547. ++fi;
  548. }
  549. return std::string(fmt, (size_t)fi);
  550. }
  551. /**
  552. *
  553. */
  554. int GeomVertexArrayFormat::
  555. compare_to(const GeomVertexArrayFormat &other) const {
  556. if (_stride != other._stride) {
  557. return _stride - other._stride;
  558. }
  559. if (_total_bytes != other._total_bytes) {
  560. return _total_bytes - other._total_bytes;
  561. }
  562. if (_pad_to != other._pad_to) {
  563. return _pad_to - other._pad_to;
  564. }
  565. if (_divisor != other._divisor) {
  566. return _divisor - other._divisor;
  567. }
  568. if (_columns.size() != other._columns.size()) {
  569. return (int)_columns.size() - (int)other._columns.size();
  570. }
  571. consider_sort_columns();
  572. other.consider_sort_columns();
  573. for (size_t i = 0; i < _columns.size(); i++) {
  574. int compare = _columns[i]->compare_to(*other._columns[i]);
  575. if (compare != 0) {
  576. return compare;
  577. }
  578. }
  579. return 0;
  580. }
  581. /**
  582. * Returns a suitable format for sending an array of instances to the graphics
  583. * backend.
  584. *
  585. * This may only be called after the format has been registered. The return
  586. * value will have been already registered.
  587. */
  588. const GeomVertexArrayFormat *GeomVertexArrayFormat::
  589. get_instance_array_format() {
  590. static CPT(GeomVertexArrayFormat) inst_array_format;
  591. if (inst_array_format == nullptr) {
  592. GeomVertexArrayFormat *new_array_format = new GeomVertexArrayFormat("instance_matrix", 4, NT_stdfloat, C_matrix);
  593. new_array_format->set_divisor(1);
  594. inst_array_format = GeomVertexArrayFormat::register_format(new_array_format);
  595. }
  596. nassertr(inst_array_format != nullptr, nullptr);
  597. return inst_array_format.p();
  598. }
  599. /**
  600. * Resorts the _columns vector so that the columns are listed in the same
  601. * order they appear in the record.
  602. */
  603. void GeomVertexArrayFormat::
  604. sort_columns() {
  605. sort(_columns.begin(), _columns.end(), IndirectLess<GeomVertexColumn>());
  606. }
  607. /**
  608. * Returns the global registry object.
  609. */
  610. void GeomVertexArrayFormat::
  611. make_registry() {
  612. if (_registry == nullptr) {
  613. _registry = new Registry;
  614. }
  615. }
  616. /**
  617. * Called internally when the format is registered.
  618. */
  619. void GeomVertexArrayFormat::
  620. do_register() {
  621. nassertv(!_is_registered);
  622. _is_registered = true;
  623. }
  624. /**
  625. * Called internally when the format is unregistered.
  626. */
  627. void GeomVertexArrayFormat::
  628. do_unregister() {
  629. nassertv(_is_registered);
  630. _is_registered = false;
  631. }
  632. /**
  633. * Tells the BamReader how to create objects of type GeomVertexArrayFormat.
  634. */
  635. void GeomVertexArrayFormat::
  636. register_with_read_factory() {
  637. BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
  638. }
  639. /**
  640. * Writes the contents of this object to the datagram for shipping out to a
  641. * Bam file.
  642. */
  643. void GeomVertexArrayFormat::
  644. write_datagram(BamWriter *manager, Datagram &dg) {
  645. TypedWritableReferenceCount::write_datagram(manager, dg);
  646. dg.add_uint16(_stride);
  647. dg.add_uint16(_total_bytes);
  648. dg.add_uint8(_pad_to);
  649. if (manager->get_file_minor_ver() > 36) {
  650. dg.add_uint16(_divisor);
  651. }
  652. consider_sort_columns();
  653. dg.add_uint16(_columns.size());
  654. Columns::iterator ci;
  655. for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
  656. GeomVertexColumn *column = (*ci);
  657. column->write_datagram(manager, dg);
  658. }
  659. }
  660. /**
  661. * Receives an array of pointers, one for each time manager->read_pointer()
  662. * was called in fillin(). Returns the number of pointers processed.
  663. */
  664. int GeomVertexArrayFormat::
  665. complete_pointers(TypedWritable **p_list, BamReader *manager) {
  666. int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
  667. Columns::iterator ci;
  668. for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
  669. GeomVertexColumn *column = (*ci);
  670. pi += column->complete_pointers(p_list + pi, manager);
  671. }
  672. return pi;
  673. }
  674. /**
  675. * Called by the BamReader to perform any final actions needed for setting up
  676. * the object after all objects have been read and all pointers have been
  677. * completed.
  678. */
  679. void GeomVertexArrayFormat::
  680. finalize(BamReader *manager) {
  681. // Now we can build up the _columns_by_name index. We have to wait until
  682. // finalize(), since the index is based on the nested name pointer within
  683. // each column, which might not be available at the time complete_pointers()
  684. // is called.
  685. _columns_by_name.clear();
  686. Columns::iterator ci;
  687. for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
  688. GeomVertexColumn *column = (*ci);
  689. _columns_by_name.insert(ColumnsByName::value_type(column->get_name(), column));
  690. }
  691. }
  692. /**
  693. * This function is called by the BamReader's factory when a new object of
  694. * type GeomVertexArrayFormat is encountered in the Bam file. It should
  695. * create the GeomVertexArrayFormat and extract its information from the file.
  696. */
  697. TypedWritable *GeomVertexArrayFormat::
  698. make_from_bam(const FactoryParams &params) {
  699. GeomVertexArrayFormat *object = new GeomVertexArrayFormat;
  700. DatagramIterator scan;
  701. BamReader *manager;
  702. parse_params(params, scan, manager);
  703. object->fillin(scan, manager);
  704. manager->register_finalize(object);
  705. return object;
  706. }
  707. /**
  708. * This internal function is called by make_from_bam to read in all of the
  709. * relevant data from the BamFile for the new GeomVertexArrayFormat.
  710. */
  711. void GeomVertexArrayFormat::
  712. fillin(DatagramIterator &scan, BamReader *manager) {
  713. TypedWritableReferenceCount::fillin(scan, manager);
  714. nassertv(!_is_registered);
  715. _stride = scan.get_uint16();
  716. _total_bytes = scan.get_uint16();
  717. _pad_to = scan.get_uint8();
  718. if (manager->get_file_minor_ver() > 36) {
  719. _divisor = scan.get_uint16();
  720. } else {
  721. _divisor = 0;
  722. }
  723. int num_columns = scan.get_uint16();
  724. _columns.reserve(num_columns);
  725. for (int i = 0; i < num_columns; ++i) {
  726. GeomVertexColumn *column = new GeomVertexColumn;
  727. column->fillin(scan, manager);
  728. _columns.push_back(column);
  729. }
  730. _columns_unsorted = false;
  731. }
  732. /**
  733. *
  734. */
  735. GeomVertexArrayFormat::Registry::
  736. Registry() {
  737. }
  738. /**
  739. * Adds the indicated format to the registry, if there is not an equivalent
  740. * format already there; in either case, returns the pointer to the equivalent
  741. * format now in the registry.
  742. *
  743. * This must be called before a format may be used in a Geom. After this
  744. * call, you should discard the original pointer you passed in (which may or
  745. * may not now be invalid) and let its reference count decrement normally; you
  746. * should use only the returned value from this point on.
  747. */
  748. CPT(GeomVertexArrayFormat) GeomVertexArrayFormat::Registry::
  749. register_format(GeomVertexArrayFormat *format) {
  750. if (format->is_registered()) {
  751. return format;
  752. }
  753. // Save the incoming pointer in a local PointerTo, so that if it has a zero
  754. // reference count and is not added into the map below, it will be
  755. // automatically deleted when this function returns.
  756. PT(GeomVertexArrayFormat) pt_format = format;
  757. GeomVertexArrayFormat *new_format;
  758. {
  759. LightMutexHolder holder(_lock);
  760. ArrayFormats::iterator fi = _formats.insert(format).first;
  761. new_format = (*fi);
  762. if (!new_format->is_registered()) {
  763. new_format->do_register();
  764. }
  765. }
  766. return new_format;
  767. }
  768. /**
  769. * Removes the indicated format from the registry. Normally this should not
  770. * be done until the format is destructing.
  771. *
  772. * The lock should be held prior to calling this method.
  773. */
  774. void GeomVertexArrayFormat::Registry::
  775. unregister_format(GeomVertexArrayFormat *format) {
  776. nassertv(format->is_registered());
  777. ArrayFormats::iterator fi = _formats.find(format);
  778. nassertv(fi != _formats.end());
  779. _formats.erase(fi);
  780. format->do_unregister();
  781. }