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);
900 Thread *current_thread = Thread::get_current_thread();
901 CDWriter cdata(_cycler,
true, current_thread);
905 data_reader.check_array_readers();
907 bool all_is_valid =
true;
909 Primitives::iterator pi;
910 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
911 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_adjacency();
912 if (new_prim !=
nullptr) {
916 if (!new_prim->check_valid(&data_reader)) {
917 all_is_valid =
false;
924 reset_geom_rendering(cdata);
927 nassertv(all_is_valid);
946 if (get_vertex_data() != other->get_vertex_data()) {
949 if (get_type() != other->get_type()) {
955 if (this_shade_model != SM_uniform && other_shade_model != SM_uniform &&
956 this_shade_model != other_shade_model) {
957 if ((this_shade_model == SM_flat_first_vertex && other_shade_model == SM_flat_last_vertex) ||
958 (this_shade_model == SM_flat_last_vertex && other_shade_model == SM_flat_first_vertex)) {
967 int num_primitives = other->get_num_primitives();
968 for (
int i = 0; i < num_primitives; i++) {
980 get_num_bytes()
const {
981 CDReader cdata(_cycler);
983 int num_bytes =
sizeof(
Geom);
984 Primitives::const_iterator pi;
985 for (pi = cdata->_primitives.begin();
986 pi != cdata->_primitives.end();
988 num_bytes += (*pi).get_read_pointer()->get_num_bytes();
1004 Thread *current_thread = Thread::get_current_thread();
1006 CDReader cdata(_cycler, current_thread);
1008 bool resident =
true;
1010 Primitives::const_iterator pi;
1011 for (pi = cdata->_primitives.begin();
1012 pi != cdata->_primitives.end();
1014 if (!(*pi).get_read_pointer(current_thread)->request_resident()) {
1037 for (ci = 0; ci < format->get_num_points(); ci++) {
1040 while (!data.is_at_end()) {
1041 const LPoint3 &point = data.get_data3();
1042 data.set_data3(point * mat);
1045 for (ci = 0; ci < format->get_num_vectors(); ci++) {
1048 while (!data.is_at_end()) {
1049 const LVector3 &vector = data.get_data3();
1050 data.set_data3(normalize(vector * mat));
1062 Thread *current_thread = Thread::get_current_thread();
1066 data_reader.check_array_readers();
1067 return geom_reader.check_valid(&data_reader);
1077 Thread *current_thread = Thread::get_current_thread();
1080 data_reader.check_array_readers();
1081 return geom_reader.check_valid(&data_reader);
1088 get_bounds(
Thread *current_thread)
const {
1089 CDLockedReader cdata(_cycler, current_thread);
1090 if (cdata->_user_bounds !=
nullptr) {
1091 return cdata->_user_bounds;
1094 if (cdata->_internal_bounds_stale) {
1095 CDWriter cdataw(((
Geom *)
this)->_cycler, cdata,
false);
1096 compute_internal_bounds(cdataw, current_thread);
1097 return cdataw->_internal_bounds;
1099 return cdata->_internal_bounds;
1106 get_nested_vertices(
Thread *current_thread)
const {
1107 CDLockedReader cdata(_cycler, current_thread);
1108 if (cdata->_internal_bounds_stale) {
1109 CDWriter cdataw(((
Geom *)
this)->_cycler, cdata,
false);
1110 compute_internal_bounds(cdataw, current_thread);
1111 return cdataw->_nested_vertices;
1113 return cdata->_nested_vertices;
1120 output(std::ostream &out)
const {
1121 CDReader cdata(_cycler);
1126 Primitives::const_iterator pi;
1127 for (pi = cdata->_primitives.begin();
1128 pi != cdata->_primitives.end();
1131 num_faces += prim->get_num_faces();
1132 types.insert(prim->get_type());
1135 out << get_type() <<
" [";
1137 for (ti = types.begin(); ti != types.end(); ++ti) {
1138 out <<
" " << (*ti);
1140 out <<
" ], " << num_faces <<
" faces";
1147 write(std::ostream &out,
int indent_level)
const {
1148 CDReader cdata(_cycler);
1151 Primitives::const_iterator pi;
1152 for (pi = cdata->_primitives.begin();
1153 pi != cdata->_primitives.end();
1155 (*pi).get_read_pointer()->write(out, indent_level);
1169 for (Cache::iterator ci = _cache.begin();
1172 CacheEntry *entry = (*ci).second;
1188 for (Cache::iterator ci = _cache.begin();
1193 cdata->set_result(
nullptr,
nullptr);
1217 Contexts::const_iterator ci;
1218 ci = _contexts.find(prepared_objects);
1219 if (ci != _contexts.end()) {
1231 Contexts::iterator ci;
1232 ci = _contexts.find(prepared_objects);
1233 if (ci != _contexts.end()) {
1254 int num_freed = (int)_contexts.size();
1256 Contexts::const_iterator ci;
1257 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1265 nassertr(_contexts.empty(), num_freed);
1284 Contexts::const_iterator ci;
1285 ci = _contexts.find(prepared_objects);
1286 if (ci != _contexts.end()) {
1287 return (*ci).second;
1291 if (gc !=
nullptr) {
1292 _contexts[prepared_objects] = gc;
1307 bool force,
Thread *current_thread)
const {
1310 data_reader.check_array_readers();
1312 return geom_reader.
draw(gsg, &data_reader, force);
1326 return _next_modified;
1334 compute_internal_bounds(Geom::CData *cdata,
Thread *current_thread)
const {
1335 int num_vertices = 0;
1338 CPT(
GeomVertexData) vertex_data = get_animated_vertex_data(
true, current_thread);
1343 PN_stdfloat sq_center_dist = 0.0f;
1344 bool found_any =
false;
1345 do_calc_tight_bounds(pmin, pmax, sq_center_dist, found_any,
1346 vertex_data,
false, LMatrix4::ident_mat(),
1347 InternalName::get_vertex(),
1348 cdata, current_thread);
1350 BoundingVolume::BoundsType btype = cdata->_bounds_type;
1351 if (btype == BoundingVolume::BT_default) {
1352 btype = bounds_type;
1356 nassertv(!pmin.is_nan());
1357 nassertv(!pmax.is_nan());
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 && best_sq_radius > 0.0f &&
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 > 0.0f &&
1395 better_sq_radius <= best_sq_radius) {
1397 if (btype == BoundingVolume::BT_best &&
1398 avg_box_area < better_sq_radius * MathNumbers::pi) {
1400 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1403 cdata->_internal_bounds =
1409 if (btype != BoundingVolume::BT_sphere &&
1410 avg_box_area < sq_center_dist * MathNumbers::pi) {
1412 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1415 }
else if (sq_center_dist >= 0.0f && sq_center_dist <= best_sq_radius) {
1418 cdata->_internal_bounds =
1422 }
else if (btype == BoundingVolume::BT_sphere) {
1425 cdata->_internal_bounds =
1427 (best_sq_radius > 0.0f) ? csqrt(best_sq_radius) : 0.0f);
1433 case BoundingVolume::BT_box:
1434 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1437 Primitives::const_iterator pi;
1438 for (pi = cdata->_primitives.begin();
1439 pi != cdata->_primitives.end();
1442 num_vertices += prim->get_num_vertices();
1447 if (btype == BoundingVolume::BT_sphere) {
1454 cdata->_nested_vertices = num_vertices;
1455 cdata->_internal_bounds_stale =
false;
1462 do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
1463 PN_stdfloat &sq_center_dist,
bool &found_any,
1465 bool got_mat,
const LMatrix4 &mat,
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);
1483 do_calc_sphere_radius(
const LPoint3 ¢er, PN_stdfloat &sq_radius,
1485 const CData *cdata,
Thread *current_thread)
const {
1486 Primitives::const_iterator pi;
1487 for (pi = cdata->_primitives.begin();
1488 pi != cdata->_primitives.end();
1491 prim->calc_sphere_radius(center, sq_radius, found_any,
1492 vertex_data, current_thread);
1504 Contexts::iterator ci;
1505 ci = _contexts.find(prepared_objects);
1506 if (ci != _contexts.end()) {
1507 _contexts.erase(ci);
1511 nassert_raise(
"unknown PreparedGraphicsObjects");
1525 CDReader cdata(_cycler, current_thread);
1528 data_reader.check_array_readers();
1530 Primitives::const_iterator pi;
1531 for (pi = cdata->_primitives.begin();
1532 pi != cdata->_primitives.end();
1535 reader.check_minmax();
1536 if (!reader.check_valid(&data_reader)) {
1548 reset_geom_rendering(Geom::CData *cdata) {
1549 cdata->_geom_rendering = 0;
1550 Primitives::const_iterator pi;
1551 for (pi = cdata->_primitives.begin();
1552 pi != cdata->_primitives.end();
1554 cdata->_geom_rendering |= (*pi).get_read_pointer()->get_geom_rendering();
1557 if ((cdata->_geom_rendering & GR_point) != 0) {
1559 if (data->has_column(InternalName::get_size())) {
1560 cdata->_geom_rendering |= GR_per_point_size;
1562 if (data->has_column(InternalName::get_aspect_ratio())) {
1563 cdata->_geom_rendering |= GR_point_aspect_ratio;
1565 if (data->has_column(InternalName::get_rotate())) {
1566 cdata->_geom_rendering |= GR_point_rotate;
1571 case SM_flat_first_vertex:
1572 cdata->_geom_rendering |= GR_flat_first_vertex;
1575 case SM_flat_last_vertex:
1576 cdata->_geom_rendering |= GR_flat_last_vertex;
1590 Thread *current_thread) {
1591 nassertv(a_prim != b_prim);
1592 nassertv(a_prim->get_type() == b_prim->get_type());
1600 b_prim = b_prim_copy;
1607 b_prim = b_prim_copy;
1613 if (a_prim->requires_unused_vertices()) {
1615 int b_vertex = index.get_data1i();
1616 a_prim->append_unused_vertices(a_vertices, b_vertex);
1624 size_t orig_a_vertices = a_handle->get_num_rows();
1626 a_handle->copy_subdata_from(a_handle->get_data_size_bytes(), 0,
1627 b_handle, 0, b_handle->get_data_size_bytes());
1633 for (
size_t i = 0; i < b_ends.size(); ++i) {
1634 a_ends.push_back(b_ends[i] + orig_a_vertices);
1670 object->fillin(scan, manager);
1687 if (!cdata->_data.is_null()) {
1690 cdata->_data.get_unsafe_pointer()->finalize(manager);
1693 reset_geom_rendering(cdata);
1712 set_result(
nullptr,
nullptr);
1720 return new CDataCache(*
this);
1730 Cache::iterator ci = _source->_cache.find(&_key);
1731 nassertv(ci != _source->_cache.end());
1732 nassertv((*ci).second ==
this);
1733 _source->_cache.erase(ci);
1739 void Geom::CacheEntry::
1740 output(std::ostream &out)
const {
1741 out <<
"geom " << (
void *)_source <<
", " 1742 << (
const void *)_key._modifier;
1751 return new CData(*
this);
1763 Primitives::const_iterator pi;
1764 for (pi = _primitives.begin(); pi != _primitives.end(); ++pi) {
1788 Primitives::iterator pri;
1789 for (pri = _primitives.begin(); pri != _primitives.end(); ++pri) {
1805 _primitives.reserve(num_primitives);
1806 for (
int i = 0; i < num_primitives; ++i) {
1808 _primitives.push_back(
nullptr);
1811 _primitive_type = (PrimitiveType)scan.
get_uint8();
1812 _shade_model = (ShadeModel)scan.
get_uint8();
1820 _bounds_type = BoundingVolume::BT_default;
1822 _bounds_type = (BoundingVolume::BoundsType)scan.
get_uint8();
1829 bool GeomPipelineReader::
1831 Geom::Primitives::const_iterator pi;
1832 for (pi = _cdata->_primitives.begin();
1833 pi != _cdata->_primitives.end();
1836 reader.check_minmax();
1837 if (!reader.check_valid(data_reader)) {
1853 PStatTimer timer(Geom::_draw_primitive_setup_pcollector);
1854 all_ok = gsg->begin_draw_primitives(
this, data_reader, force);
1857 Geom::Primitives::const_iterator pi;
1858 for (pi = _cdata->_primitives.begin();
1859 pi != _cdata->_primitives.end();
1862 if (reader.get_num_vertices() != 0) {
1863 reader.check_minmax();
1864 nassertr(reader.check_valid(data_reader),
false);
1865 if (!reader.draw(gsg, force)) {
1870 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,...
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,...
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.