16 #include "geomPoints.h" 17 #include "geomVertexReader.h" 18 #include "geomVertexRewriter.h" 19 #include "graphicsStateGuardianBase.h" 20 #include "preparedGraphicsObjects.h" 21 #include "pStatTimer.h" 22 #include "bamReader.h" 23 #include "bamWriter.h" 24 #include "boundingSphere.h" 25 #include "boundingBox.h" 26 #include "lightMutexHolder.h" 27 #include "config_mathutil.h" 30 PStatCollector Geom::_draw_primitive_setup_pcollector(
"Draw:Primitive:Setup");
56 OPEN_ITERATE_ALL_STAGES(_cycler) {
57 CDStageWriter cdata(_cycler, pipeline_stage);
60 CLOSE_ITERATE_ALL_STAGES(_cycler);
69 Geom(
const Geom ©) :
85 CopyOnWriteObject::operator = (copy);
89 _cycler = copy._cycler;
91 OPEN_ITERATE_ALL_STAGES(_cycler) {
93 mark_internal_bounds_stale(cdata);
95 CLOSE_ITERATE_ALL_STAGES(_cycler);
119 return new Geom(*
this);
136 CDWriter cdata(_cycler,
true, current_thread);
137 cdata->_usage_hint = usage_hint;
139 Primitives::iterator pi;
140 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
142 prim->set_usage_hint(usage_hint);
145 clear_cache_stage(current_thread);
161 modify_vertex_data() {
166 CDWriter cdata(_cycler,
true, current_thread);
167 clear_cache_stage(current_thread);
168 mark_internal_bounds_stale(cdata);
169 return cdata->_data.get_write_pointer();
185 nassertv(check_will_be_valid(data));
186 CDWriter cdata(_cycler,
true, current_thread);
188 clear_cache_stage(current_thread);
189 mark_internal_bounds_stale(cdata);
190 reset_geom_rendering(cdata);
211 CDWriter cdata(_cycler,
true, current_thread);
215 bool all_is_valid =
true;
217 Primitives::iterator pi;
218 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
220 prim->offset_vertices(offset);
223 if (!prim->check_valid(data)) {
225 << *prim <<
" is invalid for " << *data <<
":\n";
226 prim->write(gobj_cat.warning(
false), 4);
228 all_is_valid =
false;
234 clear_cache_stage(current_thread);
235 nassertv(all_is_valid);
256 CDWriter cdata(_cycler,
true, current_thread);
259 new_data->clear_rows();
262 bool all_is_valid =
true;
264 Primitives::iterator pi;
266 new_prims.reserve(cdata->_primitives.size());
267 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
268 PT(
GeomPrimitive) primitive = (*pi).get_read_pointer()->make_copy();
269 new_prims.push_back(primitive.p());
275 if (primitive->is_indexed() &&
276 (primitive->is_composite() ||
277 primitive->is_exact_type(GeomPoints::get_class_type()) ||
279 primitive->make_nonindexed(new_data, orig_data);
284 primitive->pack_vertices(new_data, orig_data);
288 if (!primitive->check_valid(new_data)) {
289 all_is_valid =
false;
294 nassertr(all_is_valid, 0);
296 if (num_changed != 0) {
300 cdata->_data = new_data;
301 cdata->_primitives.swap(new_prims);
303 clear_cache_stage(current_thread);
322 CDWriter cdata(_cycler,
true, current_thread);
323 nassertv(i >= 0 && i < (
int)cdata->_primitives.size());
324 nassertv(primitive->
check_valid(cdata->_data.get_read_pointer()));
328 nassertv(cdata->_primitive_type == PT_none ||
329 cdata->_primitive_type == primitive->get_primitive_type());
332 CPT(
GeomPrimitive) compat = primitive->match_shade_model(cdata->_shade_model);
336 PrimitiveType new_primitive_type = compat->get_primitive_type();
337 if (new_primitive_type != cdata->_primitive_type) {
338 cdata->_primitive_type = new_primitive_type;
340 ShadeModel new_shade_model = compat->get_shade_model();
341 if (new_shade_model != cdata->_shade_model &&
342 new_shade_model != SM_uniform) {
343 cdata->_shade_model = new_shade_model;
346 reset_geom_rendering(cdata);
347 cdata->_got_usage_hint =
false;
349 clear_cache_stage(current_thread);
350 mark_internal_bounds_stale(cdata);
368 CDWriter cdata(_cycler,
true, current_thread);
370 nassertv(primitive->
check_valid(cdata->_data.get_read_pointer()));
374 nassertv(cdata->_primitive_type == PT_none ||
375 cdata->_primitive_type == primitive->get_primitive_type());
378 CPT(
GeomPrimitive) compat = primitive->match_shade_model(cdata->_shade_model);
382 PrimitiveType new_primitive_type = compat->get_primitive_type();
383 if (new_primitive_type != cdata->_primitive_type) {
384 cdata->_primitive_type = new_primitive_type;
386 ShadeModel new_shade_model = compat->get_shade_model();
387 if (new_shade_model != cdata->_shade_model &&
388 new_shade_model != SM_uniform) {
389 cdata->_shade_model = new_shade_model;
392 reset_geom_rendering(cdata);
393 cdata->_got_usage_hint =
false;
395 clear_cache_stage(current_thread);
396 mark_internal_bounds_stale(cdata);
411 CDWriter cdata(_cycler,
true, current_thread);
412 nassertv(i >= 0 && i < (
int)cdata->_primitives.size());
413 cdata->_primitives.erase(cdata->_primitives.begin() + i);
414 if (cdata->_primitives.empty()) {
415 cdata->_primitive_type = PT_none;
416 cdata->_shade_model = SM_uniform;
418 reset_geom_rendering(cdata);
419 cdata->_got_usage_hint =
false;
421 clear_cache_stage(current_thread);
422 mark_internal_bounds_stale(cdata);
440 CDWriter cdata(_cycler,
true, current_thread);
441 cdata->_primitives.clear();
442 cdata->_primitive_type = PT_none;
443 cdata->_shade_model = SM_uniform;
444 reset_geom_rendering(cdata);
445 clear_cache_stage(current_thread);
446 mark_internal_bounds_stale(cdata);
463 CDWriter cdata(_cycler,
true, current_thread);
466 bool all_is_valid =
true;
468 Primitives::iterator pi;
469 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
470 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer()->decompose();
474 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
475 all_is_valid =
false;
481 reset_geom_rendering(cdata);
482 clear_cache_stage(current_thread);
484 nassertv(all_is_valid);
501 CDWriter cdata(_cycler,
true, current_thread);
504 bool all_is_valid =
true;
506 Primitives::iterator pi;
507 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
508 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer()->doubleside();
512 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
513 all_is_valid =
false;
519 reset_geom_rendering(cdata);
520 clear_cache_stage(current_thread);
522 nassertv(all_is_valid);
539 CDWriter cdata(_cycler,
true, current_thread);
542 bool all_is_valid =
true;
544 Primitives::iterator pi;
545 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
546 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer()->reverse();
550 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
551 all_is_valid =
false;
557 reset_geom_rendering(cdata);
558 clear_cache_stage(current_thread);
560 nassertv(all_is_valid);
577 CDWriter cdata(_cycler,
true, current_thread);
580 bool all_is_valid =
true;
582 Primitives::iterator pi;
583 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
584 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer()->rotate();
588 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
589 all_is_valid =
false;
594 switch (cdata->_shade_model) {
595 case SM_flat_first_vertex:
596 cdata->_shade_model = SM_flat_last_vertex;
599 case SM_flat_last_vertex:
600 cdata->_shade_model = SM_flat_first_vertex;
608 clear_cache_stage(current_thread);
610 nassertv(all_is_valid);
635 if (gobj_cat.is_debug()) {
637 <<
"unify_in_place(" << max_indices <<
", " << preserve_order
638 <<
"): " << *
this <<
"\n";
642 if (get_num_primitives() <= 1) {
648 CDWriter cdata(_cycler,
true, current_thread);
654 bool keep_different_types = preserve_triangle_strips && !preserve_order;
656 Primitives::const_iterator pi;
657 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
659 NewPrims::iterator npi = new_prims.find(primitive->get_type());
660 if (npi == new_prims.end()) {
662 if (!keep_different_types && !new_prims.empty()) {
669 primitive = primitive->decompose();
670 npi = new_prims.find(primitive->get_type());
671 if (npi == new_prims.end()) {
674 nassertv(new_prims.size() == 1);
675 npi = new_prims.begin();
678 new_prims.insert(NewPrims::value_type(np->get_type(), np->make_copy()));
679 npi = new_prims.find(primitive->get_type());
684 if (npi == new_prims.end()) {
686 new_prims.insert(NewPrims::value_type(primitive->get_type(), primitive->make_copy()));
691 combine_primitives((*npi).second, primitive, current_thread);
697 if (!keep_different_types && new_prims.size() > 1) {
707 cdata->_primitives.clear();
708 NewPrims::iterator npi;
709 for (npi = new_prims.begin(); npi != new_prims.end(); ++npi) {
712 nassertv(prim->
check_valid(cdata->_data.get_read_pointer()));
724 while (i < prim->get_num_primitives()) {
727 while (i < prim->get_num_primitives() &&
731 for (
int n = start; n < end; ++n) {
734 smaller->close_primitive();
739 cdata->_primitives.push_back(smaller.p());
744 cdata->_primitives.push_back(prim);
749 clear_cache_stage(current_thread);
750 reset_geom_rendering(cdata);
767 CDWriter cdata(_cycler,
true, current_thread);
770 bool all_is_valid =
true;
772 Primitives::iterator pi;
773 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
774 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_lines();
778 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
779 all_is_valid =
false;
785 reset_geom_rendering(cdata);
786 clear_cache_stage(current_thread);
788 nassertv(all_is_valid);
805 CDWriter cdata(_cycler,
true, current_thread);
808 bool all_is_valid =
true;
810 Primitives::iterator pi;
811 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
812 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_points();
816 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
817 all_is_valid =
false;
823 reset_geom_rendering(cdata);
824 clear_cache_stage(current_thread);
826 nassertv(all_is_valid);
843 CDWriter cdata(_cycler,
true, current_thread);
846 bool all_is_valid =
true;
848 Primitives::iterator pi;
849 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
850 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_patches();
854 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
855 all_is_valid =
false;
861 reset_geom_rendering(cdata);
862 clear_cache_stage(current_thread);
864 nassertv(all_is_valid);
883 if (get_primitive_type() != PT_none &&
887 if (get_vertex_data() != other->get_vertex_data()) {
890 if (get_type() != other->get_type()) {
894 ShadeModel this_shade_model = get_shade_model();
896 if (this_shade_model != SM_uniform && other_shade_model != SM_uniform &&
897 this_shade_model != other_shade_model) {
898 if ((this_shade_model == SM_flat_first_vertex && other_shade_model == SM_flat_last_vertex) ||
899 (this_shade_model == SM_flat_last_vertex && other_shade_model == SM_flat_first_vertex)) {
908 int num_primitives = other->get_num_primitives();
909 for (
int i = 0; i < num_primitives; i++) {
910 add_primitive(other->get_primitive(i));
926 int num_bytes =
sizeof(
Geom);
927 Primitives::const_iterator pi;
928 for (pi = cdata->_primitives.begin();
929 pi != cdata->_primitives.end();
931 num_bytes += (*pi).get_read_pointer()->get_num_bytes();
952 bool resident =
true;
954 Primitives::const_iterator pi;
955 for (pi = cdata->_primitives.begin();
956 pi != cdata->_primitives.end();
958 if (!(*pi).get_read_pointer()->request_resident()) {
982 CPT(GeomVertexFormat) format = new_data->get_format();
985 for (ci = 0; ci < format->get_num_points(); ci++) {
988 while (!data.is_at_end()) {
989 const LPoint3 &point = data.get_data3();
990 data.set_data3(point * mat);
993 for (ci = 0; ci < format->get_num_vectors(); ci++) {
996 while (!data.is_at_end()) {
997 const LVector3 &vector = data.get_data3();
998 data.set_data3(normalize(vector * mat));
1016 data_reader.check_array_readers();
1017 return geom_reader.check_valid(&data_reader);
1033 data_reader.check_array_readers();
1034 return geom_reader.check_valid(&data_reader);
1043 get_bounds(
Thread *current_thread)
const {
1046 return cdata->_user_bounds;
1049 if (cdata->_internal_bounds_stale) {
1050 CDWriter cdataw(((
Geom *)
this)->_cycler, cdata,
false);
1051 compute_internal_bounds(cdataw, current_thread);
1052 return cdataw->_internal_bounds;
1054 return cdata->_internal_bounds;
1064 get_nested_vertices(
Thread *current_thread)
const {
1066 if (cdata->_internal_bounds_stale) {
1067 CDWriter cdataw(((
Geom *)
this)->_cycler, cdata,
false);
1068 compute_internal_bounds(cdataw, current_thread);
1069 return cdataw->_nested_vertices;
1071 return cdata->_nested_vertices;
1080 output(ostream &out)
const {
1086 Primitives::const_iterator pi;
1087 for (pi = cdata->_primitives.begin();
1088 pi != cdata->_primitives.end();
1091 num_faces += prim->get_num_faces();
1092 types.insert(prim->get_type());
1095 out << get_type() <<
" [";
1097 for (ti = types.begin(); ti != types.end(); ++ti) {
1098 out <<
" " << (*ti);
1100 out <<
" ], " << num_faces <<
" faces";
1109 write(ostream &out,
int indent_level)
const {
1113 Primitives::const_iterator pi;
1114 for (pi = cdata->_primitives.begin();
1115 pi != cdata->_primitives.end();
1117 (*pi).get_read_pointer()->write(out, indent_level);
1135 for (Cache::iterator ci = _cache.begin();
1158 for (Cache::iterator ci = _cache.begin();
1163 cdata->set_result(NULL, NULL);
1193 Contexts::const_iterator ci;
1194 ci = _contexts.find(prepared_objects);
1195 if (ci != _contexts.end()) {
1210 Contexts::iterator ci;
1211 ci = _contexts.find(prepared_objects);
1212 if (ci != _contexts.end()) {
1236 int num_freed = (int)_contexts.size();
1238 Contexts::const_iterator ci;
1239 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1247 nassertr(_contexts.empty(), num_freed);
1271 Contexts::const_iterator ci;
1272 ci = _contexts.find(prepared_objects);
1273 if (ci != _contexts.end()) {
1274 return (*ci).second;
1279 _contexts[prepared_objects] = gc;
1300 Thread *current_thread)
const {
1305 data_reader.check_array_readers();
1307 return geom_reader.
draw(gsg, munger, &data_reader, force);
1326 return _next_modified;
1336 compute_internal_bounds(Geom::CData *cdata,
Thread *current_thread)
const {
1337 int num_vertices = 0;
1340 CPT(
GeomVertexData) vertex_data = cdata->_data.get_read_pointer();
1341 vertex_data = vertex_data->animate_vertices(
true, current_thread);
1346 PN_stdfloat sq_center_dist;
1347 bool found_any =
false;
1348 do_calc_tight_bounds(pmin, pmax, sq_center_dist, found_any,
1350 InternalName::get_vertex(),
1351 cdata, current_thread);
1353 BoundingVolume::BoundsType btype = cdata->_bounds_type;
1354 if (btype == BoundingVolume::BT_default) {
1355 btype = bounds_type;
1360 PN_stdfloat avg_box_area;
1362 case BoundingVolume::BT_best:
1363 case BoundingVolume::BT_fastest:
1364 case BoundingVolume::BT_default:
1369 PN_stdfloat min_extent = min(pmax[0] - pmin[0],
1370 min(pmax[1] - pmin[1],
1371 pmax[2] - pmin[2]));
1372 PN_stdfloat max_extent = max(pmax[0] - pmin[0],
1373 max(pmax[1] - pmin[1],
1374 pmax[2] - pmin[2]));
1375 avg_box_area = ((min_extent * min_extent) + (max_extent * max_extent)) / 2;
1378 case BoundingVolume::BT_sphere:
1381 LPoint3 aabb_center = (pmin + pmax) * 0.5f;
1382 PN_stdfloat best_sq_radius = (pmax - aabb_center).length_squared();
1384 if (btype != BoundingVolume::BT_fastest &&
1385 aabb_center.
length_squared() / best_sq_radius >= (0.2f * 0.2f)) {
1389 PN_stdfloat better_sq_radius;
1390 bool found_any =
false;
1391 do_calc_sphere_radius(aabb_center, better_sq_radius, found_any,
1392 vertex_data, cdata, current_thread);
1394 if (found_any && better_sq_radius <= best_sq_radius) {
1396 if (btype == BoundingVolume::BT_best &&
1397 avg_box_area < better_sq_radius * MathNumbers::pi) {
1399 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1402 cdata->_internal_bounds =
1408 if (btype != BoundingVolume::BT_sphere &&
1409 avg_box_area < sq_center_dist * MathNumbers::pi) {
1411 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1414 }
else if (sq_center_dist <= best_sq_radius) {
1417 cdata->_internal_bounds =
1421 }
else if (btype == BoundingVolume::BT_sphere) {
1424 cdata->_internal_bounds =
1431 case BoundingVolume::BT_box:
1432 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1435 Primitives::const_iterator pi;
1436 for (pi = cdata->_primitives.begin();
1437 pi != cdata->_primitives.end();
1440 num_vertices += prim->get_num_vertices();
1445 if (btype == BoundingVolume::BT_sphere) {
1452 cdata->_nested_vertices = num_vertices;
1453 cdata->_internal_bounds_stale =
false;
1463 PN_stdfloat &sq_center_dist,
bool &found_any,
1466 const InternalName *column_name,
1467 const CData *cdata,
Thread *current_thread)
const {
1468 Primitives::const_iterator pi;
1469 for (pi = cdata->_primitives.begin();
1470 pi != cdata->_primitives.end();
1473 prim->calc_tight_bounds(min_point, max_point, sq_center_dist,
1474 found_any, vertex_data, got_mat, mat,
1475 column_name, current_thread);
1485 do_calc_sphere_radius(
const LPoint3 ¢er, PN_stdfloat &sq_radius,
1487 const CData *cdata,
Thread *current_thread)
const {
1488 Primitives::const_iterator pi;
1489 for (pi = cdata->_primitives.begin();
1490 pi != cdata->_primitives.end();
1493 prim->calc_sphere_radius(center, sq_radius, found_any,
1494 vertex_data, current_thread);
1509 Contexts::iterator ci;
1510 ci = _contexts.find(prepared_objects);
1511 if (ci != _contexts.end()) {
1512 _contexts.erase(ci);
1534 Primitives::const_iterator pi;
1535 for (pi = cdata->_primitives.begin();
1536 pi != cdata->_primitives.end();
1538 if (!(*pi).get_read_pointer()->check_valid(vertex_data)) {
1552 reset_usage_hint(Geom::CData *cdata) {
1553 cdata->_usage_hint = UH_unspecified;
1554 Primitives::const_iterator pi;
1555 for (pi = cdata->_primitives.begin();
1556 pi != cdata->_primitives.end();
1558 cdata->_usage_hint = min(cdata->_usage_hint,
1559 (*pi).get_read_pointer()->get_usage_hint());
1561 cdata->_got_usage_hint =
true;
1570 reset_geom_rendering(Geom::CData *cdata) {
1571 cdata->_geom_rendering = 0;
1572 Primitives::const_iterator pi;
1573 for (pi = cdata->_primitives.begin();
1574 pi != cdata->_primitives.end();
1576 cdata->_geom_rendering |= (*pi).get_read_pointer()->get_geom_rendering();
1579 if ((cdata->_geom_rendering & GR_point) != 0) {
1581 if (data->has_column(InternalName::get_size())) {
1582 cdata->_geom_rendering |= GR_per_point_size;
1584 if (data->has_column(InternalName::get_aspect_ratio())) {
1585 cdata->_geom_rendering |= GR_point_aspect_ratio;
1587 if (data->has_column(InternalName::get_rotate())) {
1588 cdata->_geom_rendering |= GR_point_rotate;
1592 switch (get_shade_model()) {
1593 case SM_flat_first_vertex:
1594 cdata->_geom_rendering |= GR_flat_first_vertex;
1597 case SM_flat_last_vertex:
1598 cdata->_geom_rendering |= GR_flat_last_vertex;
1615 Thread *current_thread) {
1616 nassertv(a_prim != b_prim);
1617 nassertv(a_prim->get_type() == b_prim->get_type());
1622 GeomPrimitive::NumericType index_type = max(a_prim->
get_index_type(), b_prim2->get_index_type());
1624 if (b_prim2->get_index_type() != index_type) {
1626 b_prim_copy->set_index_type(index_type);
1627 b_prim2 = b_prim_copy;
1631 if (!b_prim2->is_indexed()) {
1633 b_prim_copy->make_indexed();
1634 b_prim2 = b_prim_copy;
1640 if (a_prim->requires_unused_vertices()) {
1643 a_prim->append_unused_vertices(a_vertices, b_vertex);
1649 size_t orig_a_vertices = a_handle->get_num_rows();
1651 a_handle->copy_subdata_from(a_handle->get_data_size_bytes(), 0,
1652 b_handle, 0, b_handle->get_data_size_bytes());
1657 CPTA_int b_ends = b_prim2->get_ends();
1658 for (
size_t i = 0; i < b_ends.size(); ++i) {
1659 a_ends.push_back(b_ends[i] + orig_a_vertices);
1702 parse_params(params, scan, manager);
1703 object->fillin(scan, manager);
1723 if (!cdata->_data.is_null()) {
1726 cdata->_data.get_unsafe_pointer()->finalize(manager);
1729 reset_geom_rendering(cdata);
1753 set_result(NULL, NULL);
1763 return new CDataCache(*
this);
1775 Cache::iterator ci = _source->_cache.find(&_key);
1776 nassertv(ci != _source->_cache.end());
1777 nassertv((*ci).second ==
this);
1778 _source->_cache.erase(ci);
1786 void Geom::CacheEntry::
1787 output(ostream &out)
const {
1788 out <<
"geom " << (
void *)_source <<
", " 1789 << (
const void *)_key._modifier;
1800 return new CData(*
this);
1814 Primitives::const_iterator pi;
1815 for (pi = _primitives.begin(); pi != _primitives.end(); ++pi) {
1842 Primitives::iterator pri;
1843 for (pri = _primitives.begin(); pri != _primitives.end(); ++pri) {
1862 _primitives.reserve(num_primitives);
1863 for (
int i = 0; i < num_primitives; ++i) {
1865 _primitives.push_back(NULL);
1868 _primitive_type = (PrimitiveType)scan.
get_uint8();
1869 _shade_model = (ShadeModel)scan.
get_uint8();
1875 _got_usage_hint =
false;
1878 _bounds_type = BoundingVolume::BT_default;
1880 _bounds_type = (BoundingVolume::BoundsType)scan.
get_uint8();
1892 if (!_cdata->_got_usage_hint) {
1897 #ifdef DO_PIPELINING 1901 false, _current_thread);
1903 #ifdef DO_PIPELINING 1906 if (!fresh_cdata->_got_usage_hint) {
1909 ((
Geom *)_object.p())->reset_usage_hint(fresh_cdata);
1910 nassertv(fresh_cdata->_got_usage_hint);
1919 nassertv(_cdata->_got_usage_hint);
1927 bool GeomPipelineReader::
1929 Geom::Primitives::const_iterator pi;
1930 for (pi = _cdata->_primitives.begin();
1931 pi != _cdata->_primitives.end();
1936 if (!reader.check_valid(data_reader)) {
1952 PStatTimer timer(Geom::_draw_primitive_setup_pcollector);
1953 bool all_ok = gsg->begin_draw_primitives(
this, munger, data_reader, force);
1955 Geom::Primitives::const_iterator pi;
1956 for (pi = _cdata->_primitives.begin();
1957 pi != _cdata->_primitives.end();
1961 if (reader.get_num_vertices() != 0) {
1963 nassertr(reader.check_valid(data_reader),
false);
1964 if (!primitive->draw(gsg, &reader, force)) {
1969 gsg->end_draw_primitives();
float length_squared() const
Returns the square of the vector's length, cheap and easy.
static const LMatrix4f & ident_mat()
Returns an identity matrix.
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
bool is_composite() const
Returns true if the primitive is a composite primitive such as a tristrip or trifan, or false if it is a fundamental primitive such as a collection of triangles.
This is a special class object that holds all the information returned by a particular GSG to indicat...
This is our own Panda specialization on the default STL map.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
void release_geom(GeomContext *gc)
Indicates that a geom context, created by a previous call to prepare_geom(), is no longer needed...
GeomContext * prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg)
Immediately creates a new GeomContext for the indicated geom and returns it.
void transform_vertices(const LMatrix4 &mat)
Applies the indicated transform to all of the vertices in the Geom.
int get_primitive_num_vertices(int n) const
Returns the number of vertices used by the nth primitive.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
void check_usage_hint() const
Ensures that the Geom's usage_hint cache has been computed.
This defines a bounding sphere, consisting of a center and a radius.
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
void clear_primitives()
Removes all the primitives from the Geom object (but keeps the same table of vertices).
void set_index_type(NumericType index_type)
Changes the numeric type of the index column.
A single page of data maintained by a PipelineCycler.
PTA_int modify_ends()
Returns a modifiable pointer to the primitive ends array, so application code can directly fiddle wit...
Base class for objects that can be written to and read from Bam files.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
void reverse_in_place()
Reverses all of the primitives within this Geom, leaving the results in place.
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
int get_num_vertices() const
Returns the number of indices used by all the primitives in this object.
void remove_primitive(int i)
Removes the ith primitive from the list.
PrimitiveType get_primitive_type() const
Returns the fundamental primitive type that is common to all GeomPrimitives added within the Geom...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
void add_primitive(const GeomPrimitive *primitive)
Adds a new GeomPrimitive structure to the Geom object.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
void make_lines_in_place()
Replaces the GeomPrimitives within this Geom with corresponding GeomLines, representing a wireframe o...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
int get_num_bytes() const
Returns the number of bytes consumed by the geom and its primitives (but not including its vertex tab...
void set_primitive(int i, const GeomPrimitive *primitive)
Replaces the ith GeomPrimitive object stored within the Geom with the new object. ...
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
static const LPoint3f & origin(CoordinateSystem cs=CS_default)
Returns the origin of the indicated coordinate system.
A table of objects that are saved within the graphics context for reference by handle later...
void rotate_in_place()
Rotates all of the primitives within this Geom, leaving the results in place.
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...
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
void offset_vertices(const GeomVertexData *data, int offset)
Replaces a Geom's vertex table with a new table, and simultaneously adds the indicated offset to all ...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
virtual void evict_callback()
Called when the entry is evicted from the cache, this should clean up the owning object appropriately...
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
A lightweight class that represents a single element that may be timed and/or counted via stats...
bool draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger, const GeomVertexDataPipelineReader *data_reader, bool force) const
The implementation of Geom::draw().
void unify_in_place(int max_indices, bool preserve_order)
Unifies all of the primitives contained within this Geom into a single (or as few as possible...
bool is_geom_queued(const Geom *geom) const
Returns true if the geom has been queued on this GSG, false otherwise.
void clear_cache_stage(Thread *current_thread)
Removes all of the previously-cached results of munge_geom(), at the current pipeline stage and upstr...
int get_primitive_start(int n) const
Returns the element within the _vertices list at which the nth primitive starts.
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
This is a 4-by-4 transform matrix.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
Similar to MutexHolder, but for a light mutex.
void clear_vertices()
Removes all of the vertices and primitives from the object, so they can be re-added.
void clear_minmax()
Undoes a previous call to set_minmax(), and allows the minimum and maximum values to be recomputed no...
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
A container for geometry primitives.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
GeomContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the geom on the particular GSG, if it does not already exist.
void set_shade_model(ShadeModel shade_model)
Changes the ShadeModel hint for this primitive.
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()...
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
void doubleside_in_place()
Doublesides all of the primitives within this Geom, leaving the results in place. ...
int get_data1i()
Returns the data associated with the read row, expressed as a 1-component value, and advances the rea...
bool check_valid(const GeomVertexData *vertex_data) const
Verifies that the primitive only references vertices that actually exist within the indicated GeomVer...
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.
bool check_valid() const
Verifies that the all of the primitives within the geom reference vertices that actually exist within...
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
void make_patches_in_place()
Replaces the GeomPrimitives within this Geom with corresponding GeomPatches.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
void set_vertex_data(const GeomVertexData *data)
Replaces the Geom's underlying vertex data table with a completely new table.
bool draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger, const GeomVertexData *vertex_data, bool force, Thread *current_thread) const
Actually draws the Geom with the indicated GSG, using the indicated vertex data (which might have bee...
ShadeModel get_shade_model() const
Returns the shade model common to all of the individual GeomPrimitives that have been added to the ge...
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the geom context only on the indicated object, if it exists there.
int get_vertex(int i) const
Returns the ith vertex index in the table.
A thread; that is, a lightweight process.
void prepare(PreparedGraphicsObjects *prepared_objects)
Indicates that the geom should be enqueued to be prepared in the indicated prepared_objects at the be...
int release_all()
Frees the context allocated on all objects for which the geom has been declared.
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
virtual bool copy_primitives_from(const Geom *other)
Copies the primitives from the indicated Geom into this one.
static UpdateSeq get_next_modified()
Returns a monotonically increasing sequence.
void decompose_in_place()
Decomposes all of the primitives within this Geom, leaving the results in place.
void enqueue_geom(Geom *geom)
Indicates that a geom would like to be put on the list to be prepared when the GSG is next ready to d...
void make_points_in_place()
Replaces the GeomPrimitives within this Geom with corresponding GeomPoints.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This is our own Panda specialization on the default STL set.
int make_nonindexed(bool composite_only)
Converts the geom from indexed to nonindexed by duplicating vertices as necessary.
A class to retrieve the individual data elements previously stored in a Datagram. ...
void operator=(const Geom ©)
The copy assignment operator is not pipeline-safe.
static void register_with_read_factory()
Tells the BamReader how to create objects of type Geom.
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the geom has already been prepared or enqueued for preparation on the indicated GSG...
TypeHandle is the identifier used to differentiate C++ class types.
This is a sequence number that increments monotonically.
void set_usage_hint(UsageHint usage_hint)
Changes the UsageHint hint for all of the primitives on this Geom to the same value.
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
void check_minmax() const
Ensures that the primitive's minmax cache has been computed.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
int get_primitive_end(int n) const
Returns the element within the _vertices list at which the nth primitive ends.
bool request_resident() const
Returns true if all the primitive arrays are currently resident in memory.
NumericType get_index_type() const
Returns the numeric type of the index column.
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter, combined together into one convenient package.
bool dequeue_geom(Geom *geom)
Removes a geom from the queued list of geoms to be prepared.
Similar to PointerToArray, except that its contents may not be modified.
This is the data for one array of a GeomVertexData structure.
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.