32PStatCollector Geom::_draw_primitive_setup_pcollector(
"Draw:Primitive:Setup");
59Geom(
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);
152modify_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);
307get_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);
1101get_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;
1119get_nested_vertices(
Thread *current_thread)
const {
1120 CDLockedReader cdata(_cycler, current_thread);
1121 if (cdata->_internal_bounds_stale) {
1122 if (cdata->_user_bounds !=
nullptr) {
1124 if (cdata->_nested_vertices == 0) {
1125 CDWriter cdataw(((
Geom *)
this)->_cycler, cdata,
false);
1126 int num_vertices = 0;
1128 Primitives::const_iterator pi;
1129 for (pi = cdataw->_primitives.begin();
1130 pi != cdataw->_primitives.end();
1133 num_vertices += reader.get_num_vertices();
1136 cdataw->_nested_vertices = num_vertices;
1137 return num_vertices;
1140 CDWriter cdataw(((
Geom *)
this)->_cycler, cdata,
false);
1141 compute_internal_bounds(cdataw, current_thread);
1142 return cdataw->_nested_vertices;
1145 return cdata->_nested_vertices;
1152output(std::ostream &out)
const {
1153 CDReader cdata(_cycler);
1158 Primitives::const_iterator pi;
1159 for (pi = cdata->_primitives.begin();
1160 pi != cdata->_primitives.end();
1163 num_faces += prim->get_num_faces();
1164 types.insert(prim->get_type());
1167 out << get_type() <<
" [";
1169 for (ti = types.begin(); ti != types.end(); ++ti) {
1170 out <<
" " << (*ti);
1172 out <<
" ], " << num_faces <<
" faces";
1179write(std::ostream &out,
int indent_level)
const {
1180 CDReader cdata(_cycler);
1183 Primitives::const_iterator pi;
1184 for (pi = cdata->_primitives.begin();
1185 pi != cdata->_primitives.end();
1187 (*pi).get_read_pointer()->write(out, indent_level);
1201 for (Cache::iterator ci = _cache.begin();
1204 CacheEntry *entry = (*ci).second;
1220 for (Cache::iterator ci = _cache.begin();
1225 cdata->set_result(
nullptr,
nullptr);
1249 Contexts::const_iterator ci;
1250 ci = _contexts.find(prepared_objects);
1251 if (ci != _contexts.end()) {
1263 Contexts::iterator ci;
1264 ci = _contexts.find(prepared_objects);
1265 if (ci != _contexts.end()) {
1286 int num_freed = (int)_contexts.size();
1288 Contexts::const_iterator ci;
1289 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1297 nassertr(_contexts.empty(), num_freed);
1316 Contexts::const_iterator ci;
1317 ci = _contexts.find(prepared_objects);
1318 if (ci != _contexts.end()) {
1319 return (*ci).second;
1323 if (gc !=
nullptr) {
1324 _contexts[prepared_objects] = gc;
1339 bool force,
Thread *current_thread)
const {
1342 data_reader.check_array_readers();
1344 return geom_reader.
draw(gsg, &data_reader, force);
1358 return _next_modified;
1366compute_internal_bounds(Geom::CData *cdata,
Thread *current_thread)
const {
1367 int num_vertices = 0;
1370 CPT(
GeomVertexData) vertex_data = get_animated_vertex_data(
true, current_thread);
1375 PN_stdfloat sq_center_dist = 0.0f;
1376 bool found_any =
false;
1377 do_calc_tight_bounds(pmin, pmax, sq_center_dist, found_any,
1378 vertex_data,
false, LMatrix4::ident_mat(),
1379 InternalName::get_vertex(),
1380 cdata, current_thread);
1382 BoundingVolume::BoundsType btype = cdata->_bounds_type;
1383 if (btype == BoundingVolume::BT_default) {
1384 btype = bounds_type;
1388 nassertv(!pmin.is_nan());
1389 nassertv(!pmax.is_nan());
1392 PN_stdfloat avg_box_area;
1394 case BoundingVolume::BT_best:
1395 case BoundingVolume::BT_fastest:
1396 case BoundingVolume::BT_default:
1401 PN_stdfloat min_extent = min(pmax[0] - pmin[0],
1402 min(pmax[1] - pmin[1],
1403 pmax[2] - pmin[2]));
1404 PN_stdfloat max_extent = max(pmax[0] - pmin[0],
1405 max(pmax[1] - pmin[1],
1406 pmax[2] - pmin[2]));
1407 avg_box_area = ((min_extent * min_extent) + (max_extent * max_extent)) / 2;
1410 case BoundingVolume::BT_sphere:
1413 LPoint3 aabb_center = (pmin + pmax) * 0.5f;
1414 PN_stdfloat best_sq_radius = (pmax - aabb_center).length_squared();
1416 if (btype != BoundingVolume::BT_fastest && best_sq_radius > 0.0f &&
1417 aabb_center.length_squared() / best_sq_radius >= (0.2f * 0.2f)) {
1421 PN_stdfloat better_sq_radius;
1422 bool found_any =
false;
1423 do_calc_sphere_radius(aabb_center, better_sq_radius, found_any,
1424 vertex_data, cdata, current_thread);
1426 if (found_any && better_sq_radius > 0.0f &&
1427 better_sq_radius <= best_sq_radius) {
1429 if (btype == BoundingVolume::BT_best &&
1430 avg_box_area < better_sq_radius * MathNumbers::pi) {
1432 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1435 cdata->_internal_bounds =
1441 if (btype != BoundingVolume::BT_sphere &&
1442 avg_box_area < sq_center_dist * MathNumbers::pi) {
1444 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1447 }
else if (sq_center_dist >= 0.0f && sq_center_dist <= best_sq_radius) {
1450 cdata->_internal_bounds =
1454 }
else if (btype == BoundingVolume::BT_sphere) {
1457 cdata->_internal_bounds =
1459 (best_sq_radius > 0.0f) ? csqrt(best_sq_radius) : 0.0f);
1465 case BoundingVolume::BT_box:
1466 cdata->_internal_bounds =
new BoundingBox(pmin, pmax);
1469 Primitives::const_iterator pi;
1470 for (pi = cdata->_primitives.begin();
1471 pi != cdata->_primitives.end();
1473 CPT(
GeomPrimitive) prim = (*pi).get_read_pointer(current_thread);
1474 num_vertices += prim->get_num_vertices();
1479 if (btype == BoundingVolume::BT_sphere) {
1486 cdata->_nested_vertices = num_vertices;
1487 cdata->_internal_bounds_stale =
false;
1494do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
1495 PN_stdfloat &sq_center_dist,
bool &found_any,
1497 bool got_mat,
const LMatrix4 &mat,
1499 const CData *cdata,
Thread *current_thread)
const {
1500 Primitives::const_iterator pi;
1501 for (pi = cdata->_primitives.begin();
1502 pi != cdata->_primitives.end();
1504 CPT(
GeomPrimitive) prim = (*pi).get_read_pointer(current_thread);
1505 prim->calc_tight_bounds(min_point, max_point, sq_center_dist,
1506 found_any, vertex_data, got_mat, mat,
1507 column_name, current_thread);
1515do_calc_sphere_radius(
const LPoint3 ¢er, PN_stdfloat &sq_radius,
1517 const CData *cdata,
Thread *current_thread)
const {
1518 Primitives::const_iterator pi;
1519 for (pi = cdata->_primitives.begin();
1520 pi != cdata->_primitives.end();
1522 CPT(
GeomPrimitive) prim = (*pi).get_read_pointer(current_thread);
1523 prim->calc_sphere_radius(center, sq_radius, found_any,
1524 vertex_data, current_thread);
1536 Contexts::iterator ci;
1537 ci = _contexts.find(prepared_objects);
1538 if (ci != _contexts.end()) {
1539 _contexts.erase(ci);
1543 nassert_raise(
"unknown PreparedGraphicsObjects");
1557 CDReader cdata(_cycler, current_thread);
1560 data_reader.check_array_readers();
1562 Primitives::const_iterator pi;
1563 for (pi = cdata->_primitives.begin();
1564 pi != cdata->_primitives.end();
1567 reader.check_minmax();
1568 if (!reader.check_valid(&data_reader)) {
1580reset_geom_rendering(Geom::CData *cdata) {
1581 cdata->_geom_rendering = 0;
1582 Primitives::const_iterator pi;
1583 for (pi = cdata->_primitives.begin();
1584 pi != cdata->_primitives.end();
1586 cdata->_geom_rendering |= (*pi).get_read_pointer()->get_geom_rendering();
1589 if ((cdata->_geom_rendering & GR_point) != 0) {
1591 if (data->has_column(InternalName::get_size())) {
1592 cdata->_geom_rendering |= GR_per_point_size;
1594 if (data->has_column(InternalName::get_aspect_ratio())) {
1595 cdata->_geom_rendering |= GR_point_aspect_ratio;
1597 if (data->has_column(InternalName::get_rotate())) {
1598 cdata->_geom_rendering |= GR_point_rotate;
1603 case SM_flat_first_vertex:
1604 cdata->_geom_rendering |= GR_flat_first_vertex;
1607 case SM_flat_last_vertex:
1608 cdata->_geom_rendering |= GR_flat_last_vertex;
1622 Thread *current_thread) {
1623 nassertv(a_prim != b_prim);
1624 nassertv(a_prim->get_type() == b_prim->get_type());
1632 b_prim = b_prim_copy;
1639 b_prim = b_prim_copy;
1645 if (a_prim->requires_unused_vertices()) {
1647 int b_vertex = index.get_data1i();
1648 a_prim->append_unused_vertices(a_vertices, b_vertex);
1656 size_t orig_a_vertices = a_handle->get_num_rows();
1658 a_handle->copy_subdata_from(a_handle->get_data_size_bytes(), 0,
1659 b_handle, 0, b_handle->get_data_size_bytes());
1665 for (
size_t i = 0; i < b_ends.size(); ++i) {
1666 a_ends.push_back(b_ends[i] + orig_a_vertices);
1702 object->fillin(scan, manager);
1719 if (!cdata->_data.is_null()) {
1722 cdata->_data.get_unsafe_pointer()->finalize(manager);
1725 reset_geom_rendering(cdata);
1744 set_result(
nullptr,
nullptr);
1752 return new CDataCache(*
this);
1762 Cache::iterator ci = _source->_cache.find(&_key);
1763 nassertv(ci != _source->_cache.end());
1764 nassertv((*ci).second ==
this);
1765 _source->_cache.erase(ci);
1771void Geom::CacheEntry::
1772output(std::ostream &out)
const {
1773 out <<
"geom " << (
void *)_source <<
", "
1774 << (
const void *)_key._modifier;
1783 return new CData(*
this);
1795 Primitives::const_iterator pi;
1796 for (pi = _primitives.begin(); pi != _primitives.end(); ++pi) {
1820 Primitives::iterator pri;
1821 for (pri = _primitives.begin(); pri != _primitives.end(); ++pri) {
1837 _primitives.reserve(num_primitives);
1838 for (
int i = 0; i < num_primitives; ++i) {
1840 _primitives.push_back(
nullptr);
1843 _primitive_type = (PrimitiveType)scan.
get_uint8();
1844 _shade_model = (ShadeModel)scan.
get_uint8();
1852 _bounds_type = BoundingVolume::BT_default;
1854 _bounds_type = (BoundingVolume::BoundsType)scan.
get_uint8();
1861bool GeomPipelineReader::
1863 Geom::Primitives::const_iterator pi;
1864 for (pi = _cdata->_primitives.begin();
1865 pi != _cdata->_primitives.end();
1868 reader.check_minmax();
1869 if (!reader.check_valid(data_reader)) {
1885 PStatTimer timer(Geom::_draw_primitive_setup_pcollector);
1886 all_ok = gsg->begin_draw_primitives(
this, data_reader, force);
1889 Geom::Primitives::const_iterator pi;
1890 for (pi = _cdata->_primitives.begin();
1891 pi != _cdata->_primitives.end();
1894 if (reader.get_num_vertices() != 0) {
1896 nassertr(reader.check_valid(data_reader),
false);
1897 if (!reader.draw(gsg, force)) {
1902 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.
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.