32 PStatCollector Geom::_draw_primitive_setup_pcollector(
"Draw:Primitive:Setup");
59 Geom(
const Geom ©) :
72 CopyOnWriteObject::operator = (copy);
76 _cycler = copy._cycler;
78 OPEN_ITERATE_ALL_STAGES(_cycler) {
80 mark_internal_bounds_stale(cdata);
82 CLOSE_ITERATE_ALL_STAGES(_cycler);
101 return new Geom(*
this);
112 GeomEnums::UsageHint hint = UH_unspecified;
113 Primitives::const_iterator pi;
114 for (pi = cdata->_primitives.begin();
115 pi != cdata->_primitives.end();
117 hint = min(hint, (*pi).get_read_pointer()->get_usage_hint());
131 Thread *current_thread = Thread::get_current_thread();
132 CDWriter cdata(_cycler,
true, current_thread);
134 Primitives::iterator pi;
135 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
137 prim->set_usage_hint(usage_hint);
152 modify_vertex_data() {
153 Thread *current_thread = Thread::get_current_thread();
157 CDWriter cdata(_cycler,
true, current_thread);
159 mark_internal_bounds_stale(cdata);
160 return cdata->_data.get_write_pointer();
172 Thread *current_thread = Thread::get_current_thread();
173 nassertv(check_will_be_valid(data));
174 CDWriter cdata(_cycler,
true, current_thread);
177 mark_internal_bounds_stale(cdata);
178 reset_geom_rendering(cdata);
193 Thread *current_thread = Thread::get_current_thread();
194 CDWriter cdata(_cycler,
true, current_thread);
199 data_reader.check_array_readers();
201 bool all_is_valid =
true;
203 Primitives::iterator pi;
204 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
206 prim->offset_vertices(offset);
209 if (!prim->check_valid(&data_reader)) {
211 << *prim <<
" is invalid for " << *data <<
":\n";
212 prim->write(gobj_cat.warning(
false), 4);
214 all_is_valid =
false;
221 nassertv(all_is_valid);
235 Thread *current_thread = Thread::get_current_thread();
238 CDWriter cdata(_cycler,
true, current_thread);
241 new_data->clear_rows();
244 bool all_is_valid =
true;
246 Primitives::iterator pi;
248 new_prims.reserve(cdata->_primitives.size());
249 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
250 PT(
GeomPrimitive) primitive = (*pi).get_read_pointer(current_thread)->make_copy();
251 new_prims.push_back(primitive.p());
256 if (primitive->is_indexed() &&
257 (primitive->is_composite() ||
258 primitive->is_exact_type(GeomPoints::get_class_type()) ||
260 primitive->make_nonindexed(new_data, orig_data);
265 primitive->pack_vertices(new_data, orig_data);
269 if (!primitive->check_valid(new_data)) {
270 all_is_valid =
false;
275 nassertr(all_is_valid, 0);
277 if (num_changed != 0) {
280 cdata->_data = new_data;
281 cdata->_primitives.swap(new_prims);
307 get_animated_vertex_data(
bool force,
Thread *current_thread)
const {
308 return get_vertex_data()->animate_vertices(force, current_thread);
321 CDWriter cdata(_cycler,
true, current_thread);
322 nassertv(i < cdata->_primitives.size());
323 nassertv(primitive->
check_valid(cdata->_data.get_read_pointer(current_thread)));
327 nassertv(cdata->_primitive_type == PT_none ||
328 cdata->_primitive_type == primitive->get_primitive_type());
331 CPT(
GeomPrimitive) compat = primitive->match_shade_model(cdata->_shade_model);
332 nassertv_always(compat !=
nullptr);
335 PrimitiveType new_primitive_type = compat->get_primitive_type();
336 if (new_primitive_type != cdata->_primitive_type) {
337 cdata->_primitive_type = new_primitive_type;
339 ShadeModel new_shade_model = compat->get_shade_model();
340 if (new_shade_model != cdata->_shade_model &&
341 new_shade_model != SM_uniform) {
342 cdata->_shade_model = new_shade_model;
345 reset_geom_rendering(cdata);
348 mark_internal_bounds_stale(cdata);
362 CDWriter cdata(_cycler,
true, current_thread);
364 nassertv(primitive->
check_valid(cdata->_data.get_read_pointer(current_thread)));
368 nassertv(cdata->_primitive_type == PT_none ||
369 cdata->_primitive_type == primitive->get_primitive_type());
372 CPT(
GeomPrimitive) compat = primitive->match_shade_model(cdata->_shade_model);
373 nassertv_always(compat !=
nullptr);
375 if (i >= cdata->_primitives.size()) {
378 cdata->_primitives.insert(cdata->_primitives.begin() + i, (
GeomPrimitive *)compat.p());
380 PrimitiveType new_primitive_type = compat->get_primitive_type();
381 if (new_primitive_type != cdata->_primitive_type) {
382 cdata->_primitive_type = new_primitive_type;
384 ShadeModel new_shade_model = compat->get_shade_model();
385 if (new_shade_model != cdata->_shade_model &&
386 new_shade_model != SM_uniform) {
387 cdata->_shade_model = new_shade_model;
390 reset_geom_rendering(cdata);
393 mark_internal_bounds_stale(cdata);
405 CDWriter cdata(_cycler,
true, current_thread);
406 nassertv(i < cdata->_primitives.size());
407 cdata->_primitives.erase(cdata->_primitives.begin() + i);
408 if (cdata->_primitives.empty()) {
409 cdata->_primitive_type = PT_none;
410 cdata->_shade_model = SM_uniform;
412 reset_geom_rendering(cdata);
415 mark_internal_bounds_stale(cdata);
428 Thread *current_thread = Thread::get_current_thread();
429 CDWriter cdata(_cycler,
true, current_thread);
430 cdata->_primitives.clear();
431 cdata->_primitive_type = PT_none;
432 cdata->_shade_model = SM_uniform;
433 reset_geom_rendering(cdata);
435 mark_internal_bounds_stale(cdata);
447 Thread *current_thread = Thread::get_current_thread();
448 CDWriter cdata(_cycler,
true, current_thread);
452 data_reader.check_array_readers();
454 bool all_is_valid =
true;
456 Primitives::iterator pi;
457 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
458 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->decompose();
462 if (!new_prim->check_valid(&data_reader)) {
463 all_is_valid =
false;
469 reset_geom_rendering(cdata);
472 nassertv(all_is_valid);
484 Thread *current_thread = Thread::get_current_thread();
485 CDWriter cdata(_cycler,
true, current_thread);
489 data_reader.check_array_readers();
491 bool all_is_valid =
true;
493 Primitives::iterator pi;
494 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
495 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->doubleside();
499 if (!new_prim->check_valid(&data_reader)) {
500 all_is_valid =
false;
506 reset_geom_rendering(cdata);
509 nassertv(all_is_valid);
521 Thread *current_thread = Thread::get_current_thread();
522 CDWriter cdata(_cycler,
true, current_thread);
526 data_reader.check_array_readers();
528 bool all_is_valid =
true;
530 Primitives::iterator pi;
531 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
532 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->reverse();
536 if (!new_prim->check_valid(&data_reader)) {
537 all_is_valid =
false;
543 reset_geom_rendering(cdata);
546 nassertv(all_is_valid);
558 Thread *current_thread = Thread::get_current_thread();
559 CDWriter cdata(_cycler,
true, current_thread);
563 data_reader.check_array_readers();
565 bool all_is_valid =
true;
567 Primitives::iterator pi;
568 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
569 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->rotate();
573 if (!new_prim->check_valid(&data_reader)) {
574 all_is_valid =
false;
579 switch (cdata->_shade_model) {
580 case SM_flat_first_vertex:
581 cdata->_shade_model = SM_flat_last_vertex;
584 case SM_flat_last_vertex:
585 cdata->_shade_model = SM_flat_first_vertex;
595 nassertv(all_is_valid);
614 if (gobj_cat.is_debug()) {
616 <<
"unify_in_place(" << max_indices <<
", " << preserve_order
617 <<
"): " << *
this <<
"\n";
620 Thread *current_thread = Thread::get_current_thread();
621 if (get_num_primitives() <= 1) {
627 CDWriter cdata(_cycler,
true, current_thread);
633 bool keep_different_types = preserve_triangle_strips && !preserve_order;
635 Primitives::const_iterator pi;
636 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
638 NewPrims::iterator npi = new_prims.find(primitive->get_type());
639 if (npi == new_prims.end()) {
641 if (!keep_different_types && !new_prims.empty()) {
647 primitive = primitive->decompose();
648 npi = new_prims.find(primitive->get_type());
649 if (npi == new_prims.end()) {
651 nassertv(new_prims.size() == 1);
652 npi = new_prims.begin();
655 new_prims.insert(NewPrims::value_type(np->get_type(), np->make_copy()));
656 npi = new_prims.find(primitive->get_type());
661 if (npi == new_prims.end()) {
663 new_prims.insert(NewPrims::value_type(primitive->get_type(), primitive->make_copy()));
668 combine_primitives((*npi).second, std::move(primitive), current_thread);
674 if (!keep_different_types && new_prims.size() > 1) {
682 data_reader.check_array_readers();
687 cdata->_primitives.clear();
688 NewPrims::iterator npi;
689 for (npi = new_prims.begin(); npi != new_prims.end(); ++npi) {
706 int num_primitives = reader.get_num_primitives();
709 if (num_vertices_per_primitive != 0) {
712 int total_vertices_per_primitive = num_vertices_per_primitive + num_unused_vertices_per_primitive;
713 int max_primitives = max_indices / total_vertices_per_primitive;
714 const unsigned char *ptr = reader.get_read_pointer(
true);
715 size_t stride = reader.get_index_stride();
717 while (i < num_primitives) {
723 int copy_primitives = min((num_primitives - i), max_primitives);
724 int num_vertices = copy_primitives * total_vertices_per_primitive;
725 nassertv(num_vertices > 0);
727 smaller->set_index_type(reader.get_index_type());
729 writer.unclean_set_num_rows(num_vertices);
730 memcpy(writer.get_write_pointer(), ptr, stride * (size_t)(num_vertices - num_unused_vertices_per_primitive));
733 cdata->_primitives.push_back(smaller.p());
735 ptr += stride * (size_t)num_vertices;
736 i += copy_primitives;
744 while (i < num_primitives) {
748 while (smaller->get_num_vertices() + (end - start) < max_indices) {
749 for (
int n = start; n < end; ++n) {
752 smaller->close_primitive();
755 if (i >= num_primitives) {
759 start = end + num_unused_vertices_per_primitive;
763 cdata->_primitives.push_back(smaller.p());
768 cdata->_primitives.push_back(prim);
774 reset_geom_rendering(cdata);
787 Thread *current_thread = Thread::get_current_thread();
788 CDWriter cdata(_cycler,
true, current_thread);
792 data_reader.check_array_readers();
794 bool all_is_valid =
true;
796 Primitives::iterator pi;
797 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
798 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_lines();
802 if (!new_prim->check_valid(&data_reader)) {
803 all_is_valid =
false;
809 reset_geom_rendering(cdata);
812 nassertv(all_is_valid);
824 Thread *current_thread = Thread::get_current_thread();
825 CDWriter cdata(_cycler,
true, current_thread);
829 data_reader.check_array_readers();
831 bool all_is_valid =
true;
833 Primitives::iterator pi;
834 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
835 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_points();
839 if (!new_prim->check_valid(&data_reader)) {
840 all_is_valid =
false;
846 reset_geom_rendering(cdata);
849 nassertv(all_is_valid);
861 Thread *current_thread = Thread::get_current_thread();
862 CDWriter cdata(_cycler,
true, current_thread);
866 data_reader.check_array_readers();
868 bool all_is_valid =
true;
870 Primitives::iterator pi;
871 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
872 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_patches();
876 if (!new_prim->check_valid(&data_reader)) {
877 all_is_valid =
false;
883 reset_geom_rendering(cdata);
886 nassertv(all_is_valid);
898 Thread *current_thread = Thread::get_current_thread();
899 CDWriter cdata(_cycler,
true, current_thread);
903 data_reader.check_array_readers();
905 bool all_is_valid =
true;
907 Primitives::iterator pi;
908 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
909 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_adjacency();
910 if (new_prim !=
nullptr) {
914 if (!new_prim->check_valid(&data_reader)) {
915 all_is_valid =
false;
922 reset_geom_rendering(cdata);
925 nassertv(all_is_valid);
944 if (get_vertex_data() != other->get_vertex_data()) {
947 if (get_type() != other->get_type()) {
953 if (this_shade_model != SM_uniform && other_shade_model != SM_uniform &&
954 this_shade_model != other_shade_model) {
955 if ((this_shade_model == SM_flat_first_vertex && other_shade_model == SM_flat_last_vertex) ||
956 (this_shade_model == SM_flat_last_vertex && other_shade_model == SM_flat_first_vertex)) {
965 int num_primitives = other->get_num_primitives();
966 for (
int i = 0; i < num_primitives; i++) {
978 get_num_bytes()
const {
979 CDReader cdata(_cycler);
981 int num_bytes =
sizeof(
Geom);
982 Primitives::const_iterator pi;
983 for (pi = cdata->_primitives.begin();
984 pi != cdata->_primitives.end();
986 num_bytes += (*pi).get_read_pointer()->get_num_bytes();
1002 Thread *current_thread = Thread::get_current_thread();
1004 CDReader cdata(_cycler, current_thread);
1006 bool resident =
true;
1008 Primitives::const_iterator pi;
1009 for (pi = cdata->_primitives.begin();
1010 pi != cdata->_primitives.end();
1012 if (!(*pi).get_read_pointer(current_thread)->request_resident()) {
1035 for (ci = 0; ci < format->get_num_points(); ci++) {
1038 while (!data.is_at_end()) {
1039 const LPoint3 &point = data.get_data3();
1040 data.set_data3(point * mat);
1043 for (ci = 0; ci < format->get_num_vectors(); ci++) {
1046 while (!data.is_at_end()) {
1047 const LVector3 &vector = data.get_data3();
1048 data.set_data3(normalize(vector * mat));
1060 Thread *current_thread = Thread::get_current_thread();
1064 data_reader.check_array_readers();
1065 return geom_reader.check_valid(&data_reader);
1075 Thread *current_thread = Thread::get_current_thread();
1078 data_reader.check_array_readers();
1079 return geom_reader.check_valid(&data_reader);
1086 get_bounds(
Thread *current_thread)
const {
1087 CDLockedReader cdata(_cycler, current_thread);
1088 if (cdata->_user_bounds !=
nullptr) {
1089 return cdata->_user_bounds;
1092 if (cdata->_internal_bounds_stale) {
1093 CDWriter cdataw(((
Geom *)
this)->_cycler, cdata,
false);
1094 compute_internal_bounds(cdataw, current_thread);
1095 return cdataw->_internal_bounds;
1097 return cdata->_internal_bounds;
1104 get_nested_vertices(
Thread *current_thread)
const {
1105 CDLockedReader cdata(_cycler, current_thread);
1106 if (cdata->_internal_bounds_stale) {
1107 CDWriter cdataw(((
Geom *)
this)->_cycler, cdata,
false);
1108 compute_internal_bounds(cdataw, current_thread);
1109 return cdataw->_nested_vertices;
1111 return cdata->_nested_vertices;
1118 output(std::ostream &out)
const {
1119 CDReader cdata(_cycler);
1124 Primitives::const_iterator pi;
1125 for (pi = cdata->_primitives.begin();
1126 pi != cdata->_primitives.end();
1129 num_faces += prim->get_num_faces();
1130 types.insert(prim->get_type());
1133 out << get_type() <<
" [";
1135 for (ti = types.begin(); ti != types.end(); ++ti) {
1136 out <<
" " << (*ti);
1138 out <<
" ], " << num_faces <<
" faces";
1145 write(std::ostream &out,
int indent_level)
const {
1146 CDReader cdata(_cycler);
1149 Primitives::const_iterator pi;
1150 for (pi = cdata->_primitives.begin();
1151 pi != cdata->_primitives.end();
1153 (*pi).get_read_pointer()->write(out, indent_level);
1167 for (Cache::iterator ci = _cache.begin();
1170 CacheEntry *entry = (*ci).second;
1186 for (Cache::iterator ci = _cache.begin();
1191 cdata->set_result(
nullptr,
nullptr);
1215 Contexts::const_iterator ci;
1216 ci = _contexts.find(prepared_objects);
1217 if (ci != _contexts.end()) {
1229 Contexts::iterator ci;
1230 ci = _contexts.find(prepared_objects);
1231 if (ci != _contexts.end()) {
1252 int num_freed = (int)_contexts.size();
1254 Contexts::const_iterator ci;
1255 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1263 nassertr(_contexts.empty(), num_freed);
1282 Contexts::const_iterator ci;
1283 ci = _contexts.find(prepared_objects);
1284 if (ci != _contexts.end()) {
1285 return (*ci).second;
1289 if (gc !=
nullptr) {
1290 _contexts[prepared_objects] = gc;
1305 bool force,
Thread *current_thread)
const {
1308 data_reader.check_array_readers();
1310 return geom_reader.
draw(gsg, &data_reader, force);
1324 return _next_modified;
1332 compute_internal_bounds(Geom::CData *cdata,
Thread *current_thread)
const {
1333 int num_vertices = 0;
1336 CPT(
GeomVertexData) vertex_data = get_animated_vertex_data(
true, current_thread);
1341 PN_stdfloat sq_center_dist = 0.0f;
1342 bool found_any =
false;
1343 do_calc_tight_bounds(pmin, pmax, sq_center_dist, found_any,
1344 vertex_data,
false, LMatrix4::ident_mat(),
1345 InternalName::get_vertex(),
1346 cdata, current_thread);
1348 BoundingVolume::BoundsType btype = cdata->_bounds_type;
1349 if (btype == BoundingVolume::BT_default) {
1350 btype = bounds_type;
1354 nassertv(!pmin.is_nan());
1355 nassertv(!pmax.is_nan());
1358 PN_stdfloat avg_box_area;
1360 case BoundingVolume::BT_best:
1361 case BoundingVolume::BT_fastest:
1362 case BoundingVolume::BT_default:
1367 PN_stdfloat min_extent = min(pmax[0] - pmin[0],
1368 min(pmax[1] - pmin[1],
1369 pmax[2] - pmin[2]));
1370 PN_stdfloat max_extent = max(pmax[0] - pmin[0],
1371 max(pmax[1] - pmin[1],
1372 pmax[2] - pmin[2]));
1373 avg_box_area = ((min_extent * min_extent) + (max_extent * max_extent)) / 2;
1376 case BoundingVolume::BT_sphere:
1379 LPoint3 aabb_center = (pmin + pmax) * 0.5f;
1380 PN_stdfloat best_sq_radius = (pmax - aabb_center).length_squared();
1382 if (btype != BoundingVolume::BT_fastest && best_sq_radius > 0.0f &&
1383 aabb_center.length_squared() / best_sq_radius >= (0.2f * 0.2f)) {
1387 PN_stdfloat better_sq_radius;
1388 bool found_any =
false;
1389 do_calc_sphere_radius(aabb_center, better_sq_radius, found_any,
1390 vertex_data, cdata, current_thread);
1392 if (found_any && better_sq_radius > 0.0f &&
1393 better_sq_radius <= best_sq_radius) {
1395 if (btype == BoundingVolume::BT_best &&
1396 avg_box_area < better_sq_radius * MathNumbers::pi) {
1398 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1401 cdata->_internal_bounds =
1407 if (btype != BoundingVolume::BT_sphere &&
1408 avg_box_area < sq_center_dist * MathNumbers::pi) {
1410 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1413 }
else if (sq_center_dist >= 0.0f && sq_center_dist <= best_sq_radius) {
1416 cdata->_internal_bounds =
1420 }
else if (btype == BoundingVolume::BT_sphere) {
1423 cdata->_internal_bounds =
1425 (best_sq_radius > 0.0f) ? csqrt(best_sq_radius) : 0.0f);
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;
1460 do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
1461 PN_stdfloat &sq_center_dist,
bool &found_any,
1463 bool got_mat,
const LMatrix4 &mat,
1465 const CData *cdata,
Thread *current_thread)
const {
1466 Primitives::const_iterator pi;
1467 for (pi = cdata->_primitives.begin();
1468 pi != cdata->_primitives.end();
1471 prim->calc_tight_bounds(min_point, max_point, sq_center_dist,
1472 found_any, vertex_data, got_mat, mat,
1473 column_name, current_thread);
1481 do_calc_sphere_radius(
const LPoint3 ¢er, PN_stdfloat &sq_radius,
1483 const CData *cdata,
Thread *current_thread)
const {
1484 Primitives::const_iterator pi;
1485 for (pi = cdata->_primitives.begin();
1486 pi != cdata->_primitives.end();
1489 prim->calc_sphere_radius(center, sq_radius, found_any,
1490 vertex_data, current_thread);
1502 Contexts::iterator ci;
1503 ci = _contexts.find(prepared_objects);
1504 if (ci != _contexts.end()) {
1505 _contexts.erase(ci);
1509 nassert_raise(
"unknown PreparedGraphicsObjects");
1523 CDReader cdata(_cycler, current_thread);
1526 data_reader.check_array_readers();
1528 Primitives::const_iterator pi;
1529 for (pi = cdata->_primitives.begin();
1530 pi != cdata->_primitives.end();
1533 reader.check_minmax();
1534 if (!reader.check_valid(&data_reader)) {
1546 reset_geom_rendering(Geom::CData *cdata) {
1547 cdata->_geom_rendering = 0;
1548 Primitives::const_iterator pi;
1549 for (pi = cdata->_primitives.begin();
1550 pi != cdata->_primitives.end();
1552 cdata->_geom_rendering |= (*pi).get_read_pointer()->get_geom_rendering();
1555 if ((cdata->_geom_rendering & GR_point) != 0) {
1557 if (data->has_column(InternalName::get_size())) {
1558 cdata->_geom_rendering |= GR_per_point_size;
1560 if (data->has_column(InternalName::get_aspect_ratio())) {
1561 cdata->_geom_rendering |= GR_point_aspect_ratio;
1563 if (data->has_column(InternalName::get_rotate())) {
1564 cdata->_geom_rendering |= GR_point_rotate;
1569 case SM_flat_first_vertex:
1570 cdata->_geom_rendering |= GR_flat_first_vertex;
1573 case SM_flat_last_vertex:
1574 cdata->_geom_rendering |= GR_flat_last_vertex;
1588 Thread *current_thread) {
1589 nassertv(a_prim != b_prim);
1590 nassertv(a_prim->get_type() == b_prim->get_type());
1598 b_prim = b_prim_copy;
1605 b_prim = b_prim_copy;
1611 if (a_prim->requires_unused_vertices()) {
1613 int b_vertex = index.get_data1i();
1614 a_prim->append_unused_vertices(a_vertices, b_vertex);
1622 size_t orig_a_vertices = a_handle->get_num_rows();
1624 a_handle->copy_subdata_from(a_handle->get_data_size_bytes(), 0,
1625 b_handle, 0, b_handle->get_data_size_bytes());
1631 for (
size_t i = 0; i < b_ends.size(); ++i) {
1632 a_ends.push_back(b_ends[i] + orig_a_vertices);
1668 object->fillin(scan, manager);
1685 if (!cdata->_data.is_null()) {
1688 cdata->_data.get_unsafe_pointer()->finalize(manager);
1691 reset_geom_rendering(cdata);
1710 set_result(
nullptr,
nullptr);
1718 return new CDataCache(*
this);
1728 Cache::iterator ci = _source->_cache.find(&_key);
1729 nassertv(ci != _source->_cache.end());
1730 nassertv((*ci).second ==
this);
1731 _source->_cache.erase(ci);
1737 void Geom::CacheEntry::
1738 output(std::ostream &out)
const {
1739 out <<
"geom " << (
void *)_source <<
", " 1740 << (
const void *)_key._modifier;
1749 return new CData(*
this);
1761 Primitives::const_iterator pi;
1762 for (pi = _primitives.begin(); pi != _primitives.end(); ++pi) {
1786 Primitives::iterator pri;
1787 for (pri = _primitives.begin(); pri != _primitives.end(); ++pri) {
1803 _primitives.reserve(num_primitives);
1804 for (
int i = 0; i < num_primitives; ++i) {
1806 _primitives.push_back(
nullptr);
1809 _primitive_type = (PrimitiveType)scan.
get_uint8();
1810 _shade_model = (ShadeModel)scan.
get_uint8();
1818 _bounds_type = BoundingVolume::BT_default;
1820 _bounds_type = (BoundingVolume::BoundsType)scan.
get_uint8();
1827 bool GeomPipelineReader::
1829 Geom::Primitives::const_iterator pi;
1830 for (pi = _cdata->_primitives.begin();
1831 pi != _cdata->_primitives.end();
1834 reader.check_minmax();
1835 if (!reader.check_valid(data_reader)) {
1851 PStatTimer timer(Geom::_draw_primitive_setup_pcollector);
1852 all_ok = gsg->begin_draw_primitives(
this, data_reader, force);
1855 Geom::Primitives::const_iterator pi;
1856 for (pi = _cdata->_primitives.begin();
1857 pi != _cdata->_primitives.end();
1860 if (reader.get_num_vertices() != 0) {
1861 reader.check_minmax();
1862 nassertr(reader.check_valid(data_reader),
false);
1863 if (!reader.draw(gsg, force)) {
1868 gsg->end_draw_primitives();
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
void transform_vertices(const LMatrix4 &mat)
Applies the indicated transform to all of the vertices in the Geom.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
UsageHint get_usage_hint() const
Returns the minimum (i.e.
This defines a bounding sphere, consisting of a center and a radius.
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.
PT(CopyOnWriteObject) Geom
Required to implement CopyOnWriteObject.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
insert_primitive
Inserts a new GeomPrimitive structure to the Geom object.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_num_vertices
Returns the number of indices used by all the primitives in this object.
bool draw(GraphicsStateGuardianBase *gsg, 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...
void add_primitive(const GeomPrimitive *primitive)
Inserts 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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void make_lines_in_place()
Replaces the GeomPrimitives within this Geom with corresponding GeomLines, representing a wireframe o...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
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 ...
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...
bool draw(GraphicsStateGuardianBase *gsg, const GeomVertexDataPipelineReader *data_reader, bool force) const
The implementation of Geom::draw().
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
void make_adjacency_in_place()
Replaces the GeomPrimitives within this Geom with corresponding versions with adjacency information...
A lightweight class that represents a single element that may be timed and/or counted via stats...
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function...
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
get_current_thread
Returns a pointer to the currently-executing Thread object.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear_cache_stage(Thread *current_thread)
Removes all of the previously-cached results of munge_geom(), at the current pipeline stage and upstr...
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
CPT(GeomVertexData) Geom
Returns a GeomVertexData that represents the results of computing the vertex animation on the CPU for...
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...
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.
get_index_type
Returns the numeric type of the index column.
CPTA_int get_ends() const
Returns a const pointer to the primitive ends array so application code can read it directly...
get_shade_model
Returns the shade model common to all of the individual GeomPrimitives that have been added to the ge...
int get_vertex(int i) const
Returns the ith vertex index in the table.
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
remove_primitive
Removes the ith primitive from the list.
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void doubleside_in_place()
Doublesides all of the primitives within this Geom, leaving the results in place. ...
bool check_valid(const GeomVertexData *vertex_data) const
Verifies that the primitive only references vertices that actually exist within the indicated GeomVer...
Encodes a string name in a hash table, mapping it to a pointer.
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 ...
get_primitive_type
Returns the fundamental primitive type that is common to all GeomPrimitives added within the Geom...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
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 release(PreparedGraphicsObjects *prepared_objects)
Frees the geom context only on the indicated object, if it exists there.
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.
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
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 add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void make_indexed()
Converts the primitive from nonindexed form to indexed form.
get_num_unused_vertices_per_primitive
Returns the number of vertices that are added between primitives that aren't, strictly speaking...
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
bool request_resident() const
Returns true if all the primitive arrays are currently resident in memory.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_num_vertices_per_primitive
If the primitive type is a simple type in which all primitives have the same number of vertices...
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.