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());
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() {
157 CDWriter cdata(_cycler,
true, current_thread);
159 mark_internal_bounds_stale(cdata);
160 return cdata->_data.get_write_pointer();
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);
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);
238 CDWriter cdata(_cycler,
true, current_thread);
239 CPT(
GeomVertexData) orig_data = cdata->_data.get_read_pointer(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);
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);
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);
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);
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);
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";
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) {
637 CPT(
GeomPrimitive) primitive = (*pi).get_read_pointer(current_thread);
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);
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;
808 if (cdata->_primitive_type == PT_polygons ||
809 cdata->_primitive_type == PT_patches) {
810 cdata->_primitive_type = PT_lines;
814 reset_geom_rendering(cdata);
817 nassertv(all_is_valid);
830 CDWriter cdata(_cycler,
true, current_thread);
834 data_reader.check_array_readers();
836 bool all_is_valid =
true;
838 Primitives::iterator pi;
839 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
840 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_points();
844 if (!new_prim->check_valid(&data_reader)) {
845 all_is_valid =
false;
850 if (cdata->_primitive_type != PT_none) {
851 cdata->_primitive_type = PT_points;
855 reset_geom_rendering(cdata);
858 nassertv(all_is_valid);
871 CDWriter cdata(_cycler,
true, current_thread);
875 data_reader.check_array_readers();
877 bool all_is_valid =
true;
879 Primitives::iterator pi;
880 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
881 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_patches();
885 if (!new_prim->check_valid(&data_reader)) {
886 all_is_valid =
false;
891 if (cdata->_primitive_type != PT_none) {
892 cdata->_primitive_type = PT_patches;
896 reset_geom_rendering(cdata);
899 nassertv(all_is_valid);
914 CDWriter cdata(_cycler,
true, current_thread);
918 data_reader.check_array_readers();
920 bool all_is_valid =
true;
922 Primitives::iterator pi;
923 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
924 CPT(
GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_adjacency();
925 if (new_prim !=
nullptr) {
929 if (!new_prim->check_valid(&data_reader)) {
930 all_is_valid =
false;
937 reset_geom_rendering(cdata);
940 nassertv(all_is_valid);
959 if (get_vertex_data() != other->get_vertex_data()) {
962 if (get_type() != other->get_type()) {
968 if (this_shade_model != SM_uniform && other_shade_model != SM_uniform &&
969 this_shade_model != other_shade_model) {
970 if ((this_shade_model == SM_flat_first_vertex && other_shade_model == SM_flat_last_vertex) ||
971 (this_shade_model == SM_flat_last_vertex && other_shade_model == SM_flat_first_vertex)) {
980 int num_primitives = other->get_num_primitives();
981 for (
int i = 0; i < num_primitives; i++) {
994 CDReader cdata(_cycler);
996 int num_bytes =
sizeof(
Geom);
997 Primitives::const_iterator pi;
998 for (pi = cdata->_primitives.begin();
999 pi != cdata->_primitives.end();
1001 num_bytes += (*pi).get_read_pointer()->get_num_bytes();
1019 CDReader cdata(_cycler, current_thread);
1021 bool resident =
true;
1023 Primitives::const_iterator pi;
1024 for (pi = cdata->_primitives.begin();
1025 pi != cdata->_primitives.end();
1027 if (!(*pi).get_read_pointer(current_thread)->request_resident()) {
1050 for (ci = 0; ci < format->get_num_points(); ci++) {
1053 while (!data.is_at_end()) {
1054 const LPoint3 &point = data.get_data3();
1055 data.set_data3(point * mat);
1058 for (ci = 0; ci < format->get_num_vectors(); ci++) {
1061 while (!data.is_at_end()) {
1062 const LVector3 &vector = data.get_data3();
1063 data.set_data3(normalize(vector * mat));
1079 data_reader.check_array_readers();
1080 return geom_reader.check_valid(&data_reader);
1093 data_reader.check_array_readers();
1094 return geom_reader.check_valid(&data_reader);
1101 get_bounds(
Thread *current_thread)
const {
1102 CDLockedReader cdata(_cycler, current_thread);
1103 if (cdata->_user_bounds !=
nullptr) {
1104 return cdata->_user_bounds;
1107 if (cdata->_internal_bounds_stale) {
1108 CDWriter cdataw(((
Geom *)
this)->_cycler, cdata,
false);
1109 compute_internal_bounds(cdataw, current_thread);
1110 return cdataw->_internal_bounds;
1112 return cdata->_internal_bounds;
1119 get_nested_vertices(
Thread *current_thread)
const {
1120 CDLockedReader cdata(_cycler, current_thread);
1121 if (cdata->_internal_bounds_stale) {
1122 CDWriter cdataw(((
Geom *)
this)->_cycler, cdata,
false);
1123 compute_internal_bounds(cdataw, current_thread);
1124 return cdataw->_nested_vertices;
1126 return cdata->_nested_vertices;
1133 output(std::ostream &out)
const {
1134 CDReader cdata(_cycler);
1139 Primitives::const_iterator pi;
1140 for (pi = cdata->_primitives.begin();
1141 pi != cdata->_primitives.end();
1144 num_faces += prim->get_num_faces();
1145 types.insert(prim->get_type());
1148 out << get_type() <<
" [";
1150 for (ti = types.begin(); ti != types.end(); ++ti) {
1151 out <<
" " << (*ti);
1153 out <<
" ], " << num_faces <<
" faces";
1160 write(std::ostream &out,
int indent_level)
const {
1161 CDReader cdata(_cycler);
1164 Primitives::const_iterator pi;
1165 for (pi = cdata->_primitives.begin();
1166 pi != cdata->_primitives.end();
1168 (*pi).get_read_pointer()->write(out, indent_level);
1182 for (Cache::iterator ci = _cache.begin();
1185 CacheEntry *entry = (*ci).second;
1201 for (Cache::iterator ci = _cache.begin();
1206 cdata->set_result(
nullptr,
nullptr);
1230 Contexts::const_iterator ci;
1231 ci = _contexts.find(prepared_objects);
1232 if (ci != _contexts.end()) {
1244 Contexts::iterator ci;
1245 ci = _contexts.find(prepared_objects);
1246 if (ci != _contexts.end()) {
1267 int num_freed = (int)_contexts.size();
1269 Contexts::const_iterator ci;
1270 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1278 nassertr(_contexts.empty(), num_freed);
1297 Contexts::const_iterator ci;
1298 ci = _contexts.find(prepared_objects);
1299 if (ci != _contexts.end()) {
1300 return (*ci).second;
1304 if (gc !=
nullptr) {
1305 _contexts[prepared_objects] = gc;
1320 bool force,
Thread *current_thread)
const {
1323 data_reader.check_array_readers();
1325 return geom_reader.
draw(gsg, &data_reader, force);
1339 return _next_modified;
1347 compute_internal_bounds(Geom::CData *cdata,
Thread *current_thread)
const {
1348 int num_vertices = 0;
1351 CPT(
GeomVertexData) vertex_data = get_animated_vertex_data(
true, current_thread);
1356 PN_stdfloat sq_center_dist = 0.0f;
1357 bool found_any =
false;
1358 do_calc_tight_bounds(pmin, pmax, sq_center_dist, found_any,
1359 vertex_data,
false, LMatrix4::ident_mat(),
1360 InternalName::get_vertex(),
1361 cdata, current_thread);
1363 BoundingVolume::BoundsType btype = cdata->_bounds_type;
1364 if (btype == BoundingVolume::BT_default) {
1365 btype = bounds_type;
1369 nassertv(!pmin.is_nan());
1370 nassertv(!pmax.is_nan());
1373 PN_stdfloat avg_box_area;
1375 case BoundingVolume::BT_best:
1376 case BoundingVolume::BT_fastest:
1377 case BoundingVolume::BT_default:
1382 PN_stdfloat min_extent = min(pmax[0] - pmin[0],
1383 min(pmax[1] - pmin[1],
1384 pmax[2] - pmin[2]));
1385 PN_stdfloat max_extent = max(pmax[0] - pmin[0],
1386 max(pmax[1] - pmin[1],
1387 pmax[2] - pmin[2]));
1388 avg_box_area = ((min_extent * min_extent) + (max_extent * max_extent)) / 2;
1391 case BoundingVolume::BT_sphere:
1394 LPoint3 aabb_center = (pmin + pmax) * 0.5f;
1395 PN_stdfloat best_sq_radius = (pmax - aabb_center).length_squared();
1397 if (btype != BoundingVolume::BT_fastest && best_sq_radius > 0.0f &&
1398 aabb_center.length_squared() / best_sq_radius >= (0.2f * 0.2f)) {
1402 PN_stdfloat better_sq_radius;
1403 bool found_any =
false;
1404 do_calc_sphere_radius(aabb_center, better_sq_radius, found_any,
1405 vertex_data, cdata, current_thread);
1407 if (found_any && better_sq_radius > 0.0f &&
1408 better_sq_radius <= best_sq_radius) {
1410 if (btype == BoundingVolume::BT_best &&
1411 avg_box_area < better_sq_radius * MathNumbers::pi) {
1413 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1416 cdata->_internal_bounds =
1422 if (btype != BoundingVolume::BT_sphere &&
1423 avg_box_area < sq_center_dist * MathNumbers::pi) {
1425 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1428 }
else if (sq_center_dist >= 0.0f && sq_center_dist <= best_sq_radius) {
1431 cdata->_internal_bounds =
1435 }
else if (btype == BoundingVolume::BT_sphere) {
1438 cdata->_internal_bounds =
1440 (best_sq_radius > 0.0f) ? csqrt(best_sq_radius) : 0.0f);
1446 case BoundingVolume::BT_box:
1447 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1450 Primitives::const_iterator pi;
1451 for (pi = cdata->_primitives.begin();
1452 pi != cdata->_primitives.end();
1454 CPT(
GeomPrimitive) prim = (*pi).get_read_pointer(current_thread);
1455 num_vertices += prim->get_num_vertices();
1460 if (btype == BoundingVolume::BT_sphere) {
1467 cdata->_nested_vertices = num_vertices;
1468 cdata->_internal_bounds_stale =
false;
1475 do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
1476 PN_stdfloat &sq_center_dist,
bool &found_any,
1478 bool got_mat,
const LMatrix4 &mat,
1480 const CData *cdata,
Thread *current_thread)
const {
1481 Primitives::const_iterator pi;
1482 for (pi = cdata->_primitives.begin();
1483 pi != cdata->_primitives.end();
1485 CPT(
GeomPrimitive) prim = (*pi).get_read_pointer(current_thread);
1486 prim->calc_tight_bounds(min_point, max_point, sq_center_dist,
1487 found_any, vertex_data, got_mat, mat,
1488 column_name, current_thread);
1496 do_calc_sphere_radius(
const LPoint3 ¢er, PN_stdfloat &sq_radius,
1498 const CData *cdata,
Thread *current_thread)
const {
1499 Primitives::const_iterator pi;
1500 for (pi = cdata->_primitives.begin();
1501 pi != cdata->_primitives.end();
1503 CPT(
GeomPrimitive) prim = (*pi).get_read_pointer(current_thread);
1504 prim->calc_sphere_radius(center, sq_radius, found_any,
1505 vertex_data, current_thread);
1517 Contexts::iterator ci;
1518 ci = _contexts.find(prepared_objects);
1519 if (ci != _contexts.end()) {
1520 _contexts.erase(ci);
1524 nassert_raise(
"unknown PreparedGraphicsObjects");
1538 CDReader cdata(_cycler, current_thread);
1541 data_reader.check_array_readers();
1543 Primitives::const_iterator pi;
1544 for (pi = cdata->_primitives.begin();
1545 pi != cdata->_primitives.end();
1548 reader.check_minmax();
1549 if (!reader.check_valid(&data_reader)) {
1561 reset_geom_rendering(Geom::CData *cdata) {
1562 cdata->_geom_rendering = 0;
1563 Primitives::const_iterator pi;
1564 for (pi = cdata->_primitives.begin();
1565 pi != cdata->_primitives.end();
1567 cdata->_geom_rendering |= (*pi).get_read_pointer()->get_geom_rendering();
1570 if ((cdata->_geom_rendering & GR_point) != 0) {
1572 if (data->has_column(InternalName::get_size())) {
1573 cdata->_geom_rendering |= GR_per_point_size;
1575 if (data->has_column(InternalName::get_aspect_ratio())) {
1576 cdata->_geom_rendering |= GR_point_aspect_ratio;
1578 if (data->has_column(InternalName::get_rotate())) {
1579 cdata->_geom_rendering |= GR_point_rotate;
1584 case SM_flat_first_vertex:
1585 cdata->_geom_rendering |= GR_flat_first_vertex;
1588 case SM_flat_last_vertex:
1589 cdata->_geom_rendering |= GR_flat_last_vertex;
1603 Thread *current_thread) {
1604 nassertv(a_prim != b_prim);
1605 nassertv(a_prim->get_type() == b_prim->get_type());
1613 b_prim = b_prim_copy;
1620 b_prim = b_prim_copy;
1626 if (a_prim->requires_unused_vertices()) {
1628 int b_vertex = index.get_data1i();
1629 a_prim->append_unused_vertices(a_vertices, b_vertex);
1637 size_t orig_a_vertices = a_handle->get_num_rows();
1639 a_handle->copy_subdata_from(a_handle->get_data_size_bytes(), 0,
1640 b_handle, 0, b_handle->get_data_size_bytes());
1646 for (
size_t i = 0; i < b_ends.size(); ++i) {
1647 a_ends.push_back(b_ends[i] + orig_a_vertices);
1683 object->fillin(scan, manager);
1700 if (!cdata->_data.is_null()) {
1703 cdata->_data.get_unsafe_pointer()->finalize(manager);
1706 reset_geom_rendering(cdata);
1725 set_result(
nullptr,
nullptr);
1733 return new CDataCache(*
this);
1743 Cache::iterator ci = _source->_cache.find(&_key);
1744 nassertv(ci != _source->_cache.end());
1745 nassertv((*ci).second ==
this);
1746 _source->_cache.erase(ci);
1752 void Geom::CacheEntry::
1753 output(std::ostream &out)
const {
1754 out <<
"geom " << (
void *)_source <<
", "
1755 << (
const void *)_key._modifier;
1764 return new CData(*
this);
1776 Primitives::const_iterator pi;
1777 for (pi = _primitives.begin(); pi != _primitives.end(); ++pi) {
1801 Primitives::iterator pri;
1802 for (pri = _primitives.begin(); pri != _primitives.end(); ++pri) {
1818 _primitives.reserve(num_primitives);
1819 for (
int i = 0; i < num_primitives; ++i) {
1821 _primitives.push_back(
nullptr);
1824 _primitive_type = (PrimitiveType)scan.
get_uint8();
1825 _shade_model = (ShadeModel)scan.
get_uint8();
1833 _bounds_type = BoundingVolume::BT_default;
1835 _bounds_type = (BoundingVolume::BoundsType)scan.
get_uint8();
1842 bool GeomPipelineReader::
1844 Geom::Primitives::const_iterator pi;
1845 for (pi = _cdata->_primitives.begin();
1846 pi != _cdata->_primitives.end();
1849 reader.check_minmax();
1850 if (!reader.check_valid(data_reader)) {
1866 PStatTimer timer(Geom::_draw_primitive_setup_pcollector);
1867 all_ok = gsg->begin_draw_primitives(
this, data_reader, force);
1870 Geom::Primitives::const_iterator pi;
1871 for (pi = _cdata->_primitives.begin();
1872 pi != _cdata->_primitives.end();
1875 if (reader.get_num_vertices() != 0) {
1877 nassertr(reader.check_valid(data_reader),
false);
1878 if (!reader.draw(gsg, force)) {
1883 gsg->end_draw_primitives();
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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 register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
This defines a bounding sphere, consisting of a center and a radius.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
Similar to PointerToArray, except that its contents may not be modified.
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
A single page of data maintained by a PipelineCycler.
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().
A class to retrieve the individual data elements previously stored in a Datagram.
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
This is a special class object that holds all the information returned by a particular GSG to indicat...
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
bool draw(GraphicsStateGuardianBase *gsg, const GeomVertexDataPipelineReader *data_reader, bool force) const
The implementation of Geom::draw().
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.
int get_vertex(int i) const
Returns the ith vertex index in the table.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
void clear_vertices()
Removes all of the vertices and primitives from the object, so they can be re-added.
CPTA_int get_ends() const
Returns a const pointer to the primitive ends array so application code can read it directly.
void make_indexed()
Converts the primitive from nonindexed form to indexed form.
get_num_vertices
Returns the number of indices used by all the primitives in this object.
bool check_valid(const GeomVertexData *vertex_data) const
Verifies that the primitive only references vertices that actually exist within the indicated GeomVer...
bool is_composite() const
Returns true if the primitive is a composite primitive such as a tristrip or trifan,...
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.
get_num_unused_vertices_per_primitive
Returns the number of vertices that are added between primitives that aren't, strictly speaking,...
void set_index_type(NumericType index_type)
Changes the numeric type of the index column.
get_num_vertices_per_primitive
If the primitive type is a simple type in which all primitives have the same number of vertices,...
PTA_int modify_ends()
Returns a modifiable pointer to the primitive ends array, so application code can directly fiddle wit...
void clear_minmax()
Undoes a previous call to set_minmax(), and allows the minimum and maximum values to be recomputed no...
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
unsigned char * get_write_pointer()
Returns a writable pointer to the beginning of the actual data stream.
This is the data for one array of a GeomVertexData structure.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter,...
virtual void evict_callback()
Called when the entry is evicted from the cache, this should clean up the owning object appropriately...
A container for geometry primitives.
void decompose_in_place()
Decomposes all of the primitives within this Geom, leaving the results in place.
bool request_resident() const
Returns true if all the primitive arrays are currently resident in memory.
void prepare(PreparedGraphicsObjects *prepared_objects)
Indicates that the geom should be enqueued to be prepared in the indicated prepared_objects at the be...
insert_primitive
Inserts a new GeomPrimitive structure to the Geom object.
int release_all()
Frees the context allocated on all objects for which the geom has been declared.
void reverse_in_place()
Reverses all of the primitives within this Geom, leaving the results in place.
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 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 ...
void make_patches_in_place()
Replaces the GeomPrimitives within this Geom with corresponding GeomPatches.
virtual bool copy_primitives_from(const Geom *other)
Copies the primitives from the indicated Geom into this one.
void clear_primitives()
Removes all the primitives from the Geom object (but keeps the same table of vertices).
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the geom context only on the indicated object, if it exists there.
int make_nonindexed(bool composite_only)
Converts the geom from indexed to nonindexed by duplicating vertices as necessary.
void doubleside_in_place()
Doublesides all of the primitives within this Geom, leaving the results in place.
bool check_valid() const
Verifies that the all of the primitives within the geom reference vertices that actually exist within...
remove_primitive
Removes the ith primitive from the list.
void add_primitive(const GeomPrimitive *primitive)
Inserts a new GeomPrimitive structure to the Geom object.
void clear_cache_stage(Thread *current_thread)
Removes all of the previously-cached results of munge_geom(), at the current pipeline stage and upstr...
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 operator=(const Geom ©)
The copy assignment operator is not pipeline-safe.
void make_points_in_place()
Replaces the GeomPrimitives within this Geom with corresponding GeomPoints.
void rotate_in_place()
Rotates all of the primitives within this Geom, leaving the results in place.
void make_lines_in_place()
Replaces the GeomPrimitives within this Geom with corresponding GeomLines, representing a wireframe o...
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,...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
get_shade_model
Returns the shade model common to all of the individual GeomPrimitives that have been added to the ge...
static void register_with_read_factory()
Tells the BamReader how to create objects of type Geom.
static UpdateSeq get_next_modified()
Returns a monotonically increasing sequence.
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the geom has already been prepared or enqueued for preparation on the indicated GSG,...
void make_adjacency_in_place()
Replaces the GeomPrimitives within this Geom with corresponding versions with adjacency information.
get_num_bytes
Returns the number of bytes consumed by the geom and its primitives (but not including its vertex tab...
void transform_vertices(const LMatrix4 &mat)
Applies the indicated transform to all of the vertices in the Geom.
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
void set_vertex_data(const GeomVertexData *data)
Replaces the Geom's underlying vertex data table with a completely new table.
void set_usage_hint(UsageHint usage_hint)
Changes the UsageHint hint for all of the primitives on this Geom to the same value.
get_primitive_type
Returns the fundamental primitive type that is common to all GeomPrimitives added within the Geom.
UsageHint get_usage_hint() const
Returns the minimum (i.e.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
Encodes a string name in a hash table, mapping it to a pointer.
Similar to MutexHolder, but for a light mutex.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
A table of objects that are saved within the graphics context for reference by handle later.
void release_geom(GeomContext *gc)
Indicates that a geom context, created by a previous call to prepare_geom(), is no longer needed.
bool is_geom_queued(const Geom *geom) const
Returns true if the geom has been queued on this GSG, false otherwise.
GeomContext * prepare_geom_now(Geom *geom, GraphicsStateGuardianBase *gsg)
Immediately creates a new GeomContext for the indicated geom and returns it.
bool dequeue_geom(Geom *geom)
Removes a geom from the queued list of geoms to be prepared.
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...
A thread; that is, a lightweight process.
get_current_thread
Returns a pointer to the currently-executing Thread object.
TypeHandle is the identifier used to differentiate C++ class types.
Base class for objects that can be written to and read from Bam files.
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...
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 is a sequence number that increments monotonically.
This is our own Panda specialization on the default STL map.
This is our own Panda specialization on the default STL set.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT(GeomVertexData) Geom
Returns a GeomVertexData that represents the results of computing the vertex animation on the CPU for...
PT(CopyOnWriteObject) Geom
Required to implement CopyOnWriteObject.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.