45 (
"allow-flatten-color",
false,
46 PRC_DESC(
"allows color to always be flattened to vertices"));
54 GeomNode(
const std::string &name) :
57 _preserved = preserve_geom_nodes;
60 set_into_collide_mask(get_default_collide_mask());
69 _preserved(copy._preserved),
103 if (pgraph_cat.is_debug()) {
105 <<
"Transforming geometry:\n";
106 attribs.write(pgraph_cat.debug(
false), attrib_types, 2);
109 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
110 if (!attribs._transform->is_identity()) {
116 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
117 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
118 PT(
GeomList) geoms = cdata->modify_geoms();
124 size_t num_geoms = geoms->size();
125 for (
size_t i = 0; i < num_geoms; ++i) {
127 PT(
Geom) new_geom = entry->_geom.get_read_pointer()->make_copy();
130 entry->_state = geom_attribs.
collect(entry->_state, attrib_types);
132 bool any_changed =
false;
134 if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
137 int override = geom_attribs._color_override;
138 entry->_state = entry->_state->add_attrib(ra,
override);
141 ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
143 if (ca->get_color_type() != ColorAttrib::T_vertex) {
144 if(allow_flatten_color) {
145 if(transformer.
set_color(new_geom, ca->get_color())) {
147 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
150 if (transformer.
remove_column(new_geom, InternalName::get_color())) {
156 if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
157 if (geom_attribs._color_scale !=
nullptr) {
159 if (csa->get_scale() != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)) {
164 CPT(
RenderAttrib) ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
166 if(allow_flatten_color) {
171 if (ca->get_color_type() == ColorAttrib::T_off) {
172 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
175 entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(csa->get_scale()));
177 }
else if (ca->get_color_type() == ColorAttrib::T_flat) {
180 const LColor &c1 = ca->get_color();
181 const LVecBase4 &c2 = csa->get_scale();
182 LColor color(c1[0] * c2[0], c1[1] * c2[1],
183 c1[2] * c2[2], c1[3] * c2[3]);
184 entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(color));
192 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
199 if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
200 if (geom_attribs._tex_matrix !=
nullptr) {
208 if (geom_attribs._texture !=
nullptr) {
211 for (
int si = 0; si < num_on_stages; si++) {
214 count_name(name_count, name);
223 int num_stages = tma->get_num_stages();
224 for (
int i = 0; i < num_stages; i++) {
227 if (get_name_count(name_count, name) > 1) {
230 new_tma = DCAST(
TexMatrixAttrib, new_tma->add_stage(stage, tma->get_transform(stage)));
241 if (!new_tma->is_empty()) {
242 entry->_state = entry->_state->add_attrib(new_tma);
247 if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
248 entry->_state = geom_attribs._other->compose(entry->_state);
255 if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
256 if (geom_attribs._cull_face !=
nullptr) {
260 case CullFaceAttrib::M_cull_none:
263 bool has_normals = (new_geom->get_vertex_data()->has_column(InternalName::get_normal()));
267 PT(
Geom) dup_geom = new_geom->reverse();
270 geoms->push_back(
GeomEntry(dup_geom, entry->_state));
274 entry = &(*geoms)[i];
279 new_geom->doubleside_in_place();
285 case CullFaceAttrib::M_cull_counter_clockwise:
287 new_geom->reverse_in_place();
299 entry->_geom = new_geom;
303 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
305 if ((attrib_types & SceneGraphReducer::TT_apply_texture_color) != 0) {
366 CDReader cdata(_cycler, current_thread);
367 GeomList::const_iterator gi;
368 CPT(
GeomList) geoms = cdata->get_geoms();
369 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
371 CPT(
RenderState) geom_state = node_state->compose(entry._state);
372 CPT(
Geom) geom = entry._geom.get_read_pointer();
375 PT(
GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
376 geom = transformer.premunge_geom(geom, munger);
379 CPT(
GeomVertexData) vdata = geom->get_animated_vertex_data(
false, current_thread);
381 int num_arrays = vdata_reader.get_num_arrays();
382 for (
int i = 0; i < num_arrays; ++i) {
388 int num_primitives = geom->get_num_primitives();
389 for (
int i = 0; i < num_primitives; ++i) {
394 if (munger->is_of_type(StateMunger::get_class_type())) {
396 geom_state = state_munger->munge_state(geom_state);
401 if (geom_state->get_attrib(ta)) {
403 for (
int i = 0; i < num_stages; ++i) {
406 if (texture !=
nullptr) {
414 if (geom_state->get_attrib(sa)) {
416 if (shader !=
nullptr) {
462 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
bool &found_any,
465 PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
468 const LMatrix4 &mat = next_transform->get_mat();
470 CDReader cdata(_cycler, current_thread);
471 GeomList::const_iterator gi;
472 CPT(GeomList) geoms = cdata->get_geoms();
473 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
474 CPT(
Geom) geom = (*gi)._geom.get_read_pointer();
475 geom->calc_tight_bounds(min_point, max_point, found_any,
476 geom->get_animated_vertex_data(
true, current_thread),
477 !next_transform->is_identity(), mat,
481 return next_transform;
502 trav->_geom_nodes_pcollector.add_level(1);
504 if (pgraph_cat.is_spam()) {
506 <<
"Found " << *
this <<
" in state " << *data._state
507 <<
" draw_mask = " << data._draw_mask <<
"\n";
512 int num_geoms = geoms.get_num_geoms();
513 trav->_geoms_pcollector.add_level(num_geoms);
514 CPT(
TransformState) internal_transform = data.get_internal_transform(trav);
516 for (
int i = 0; i < num_geoms; i++) {
517 CPT(
Geom) geom = geoms.get_geom(i);
518 if (geom->is_empty()) {
522 CPT(
RenderState) state = data._state->compose(geoms.get_geom_state(i));
523 if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
533 if (data._view_frustum !=
nullptr) {
539 int result = data._view_frustum->contains(geom_gbv);
540 if (result == BoundingVolume::IF_no_intersection) {
545 if (!data._cull_planes->is_empty()) {
551 data._cull_planes->do_cull(result, state, geom_gbv);
552 if (result == BoundingVolume::IF_no_intersection) {
560 new CullableObject(std::move(geom), std::move(state), internal_transform);
585 nassertv(geom !=
nullptr);
587 nassertv(state !=
nullptr);
590 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
591 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
593 cdata->modify_geoms()->push_back(
GeomEntry(geom, state));
595 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
597 mark_internal_bounds_stale();
607 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
608 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
609 CDStageReader cdata_other(other->_cycler, pipeline_stage, current_thread);
611 GeomList::const_iterator gi;
612 CPT(
GeomList) other_geoms = cdata_other->get_geoms();
613 PT(
GeomList) this_geoms = cdata->modify_geoms();
614 for (gi = other_geoms->begin(); gi != other_geoms->end(); ++gi) {
616 nassertv(entry._geom.get_read_pointer()->check_valid());
617 this_geoms->push_back(entry);
620 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
622 mark_internal_bounds_stale();
636 nassertv(geom !=
nullptr);
640 PT(
GeomList) geoms = cdata->modify_geoms();
641 nassertv(n >= 0 && n < (
int)geoms->size());
642 (*geoms)[n]._geom = geom;
644 mark_internal_bounds_stale();
655 for (
int i = 0; i < num_geoms; i++) {
656 const Geom *geom = get_geom(i);
678 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
679 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
681 GeomList::iterator gi;
682 PT(
GeomList) geoms = cdata->modify_geoms();
683 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
685 nassertv(entry._geom.test_ref_count_integrity());
686 PT(
Geom) geom = entry._geom.get_write_pointer();
687 geom->decompose_in_place();
690 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
712 unify(
int max_indices,
bool preserve_order) {
713 bool any_changed =
false;
716 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
717 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
724 GeomList::const_iterator gi;
725 CPT(
GeomList) old_geoms = cdata->get_geoms();
726 for (gi = old_geoms->begin(); gi != old_geoms->end(); ++gi) {
729 bool unified =
false;
732 GeomList::reverse_iterator gj;
733 for (gj = new_geoms->rbegin(); gj != new_geoms->rend() && !unified; ++gj) {
735 if (old_entry._state == new_entry._state) {
737 CPT(
Geom) old_geom = old_entry._geom.get_read_pointer();
738 PT(
Geom) new_geom = new_entry._geom.get_write_pointer();
739 if (new_geom->copy_primitives_from(old_geom)) {
746 if (preserve_order) {
756 new_geoms->push_back(old_entry);
761 cdata->set_geoms(new_geoms);
764 GeomList::iterator wgi;
765 for (wgi = new_geoms->begin(); wgi != new_geoms->end(); ++wgi) {
767 nassertv(entry._geom.test_ref_count_integrity());
768 PT(
Geom) geom = entry._geom.get_write_pointer();
769 geom->unify_in_place(max_indices, preserve_order);
772 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
775 mark_internal_bounds_stale();
785 write(out, indent_level);
786 GeomList::const_iterator gi;
787 CPT(
GeomList) geoms = cdata->get_geoms();
788 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
790 indent(out, indent_level + 2)
791 << *entry._geom.get_read_pointer() <<
" " << *entry._state <<
"\n";
801 write(out, indent_level);
802 GeomList::const_iterator gi;
803 CPT(
GeomList) geoms = cdata->get_geoms();
804 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
806 CPT(
Geom) geom = entry._geom.get_read_pointer();
807 indent(out, indent_level + 2)
808 << *geom <<
" " << *entry._state <<
"\n";
809 geom->write(out, indent_level + 4);
817 output(std::ostream &out)
const {
823 CDReader cdata(_cycler);
827 GeomList::const_iterator gi;
828 CPT(
RenderState) common = RenderState::make_empty();
830 CPT(GeomList) geoms = cdata->get_geoms();
831 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
832 const GeomEntry &entry = (*gi);
833 common = common->compose(entry._state);
836 PandaNode::output(out);
837 out <<
" (" << geoms->size() <<
" geoms";
839 if (!common->is_empty()) {
840 out <<
": " << *common;
869 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
870 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
872 GeomList::iterator gi;
873 PT(
GeomList) geoms = cdata->modify_geoms();
874 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
876 CPT(
RenderState) geom_state = node_state->compose(entry._state);
877 CPT(
Geom) geom = entry._geom.get_read_pointer();
878 PT(
GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
879 entry._geom = transformer.premunge_geom(geom, munger);
882 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
890 r_mark_geom_bounds_stale(
Thread *current_thread) {
891 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
892 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
894 GeomList::iterator gi;
895 PT(GeomList) geoms = cdata->modify_geoms();
896 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
897 GeomEntry &entry = (*gi);
898 entry._geom.get_read_pointer()->mark_bounds_stale();
901 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
902 mark_internal_bounds_stale();
904 PandaNode::r_mark_geom_bounds_stale(current_thread);
914 int &internal_vertices,
916 Thread *current_thread)
const {
917 int num_vertices = 0;
919 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
925 GeomList::const_iterator gi;
926 CPT(GeomList) geoms = cdata->get_geoms();
927 child_volumes.reserve(geoms->size());
928 child_volumes_ref.reserve(geoms->size());
930 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
931 const GeomEntry &entry = (*gi);
932 CPT(
Geom) geom = entry._geom.get_read_pointer();
935 if (!volume->is_empty()) {
936 child_volumes.push_back(volume);
937 child_volumes_ref.push_back(volume);
938 if (!volume->is_exact_type(BoundingBox::get_class_type())) {
942 num_vertices += geom->get_nested_vertices();
948 if (btype == BoundingVolume::BT_default) {
952 if (btype == BoundingVolume::BT_box ||
953 (btype != BoundingVolume::BT_sphere && all_box)) {
962 if (child_volumes.size() > 0) {
964 const BoundingVolume **child_end = child_begin + child_volumes.size();
968 internal_bounds = gbv;
969 internal_vertices = num_vertices;
1007 CPT(
RenderAttrib) vertex_color = ColorAttrib::make_vertex();
1010 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1011 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1013 GeomList::iterator gi;
1014 PT(
GeomList) geoms = cdata->modify_geoms();
1015 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1017 CPT(
Geom) geom = entry._geom.get_read_pointer();
1022 CPT(
GeomVertexData) vdata = geom->get_vertex_data(current_thread);
1024 for (
size_t i = 0; i < vformat->get_num_arrays(); ++i) {
1029 if (vdata->has_column(color) &&
1030 !entry._state->has_attrib(ColorAttrib::get_class_slot())) {
1034 aux_data->_hold_state = entry._state;
1037 entry._state = entry._state->add_attrib(vertex_color, -1);
1041 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1057 node->fillin(scan, manager);
1072 PandaNode::fillin(scan, manager);
1080 CData(
const GeomNode::CData ©) :
1090 return new CData(*
this);
1097 void GeomNode::CData::
1099 CPT(GeomList) geoms = _geoms.get_read_pointer();
1100 int num_geoms = geoms->size();
1101 nassertv(num_geoms == (
int)(uint16_t)num_geoms);
1104 GeomList::const_iterator gi;
1105 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1106 const GeomEntry &entry = (*gi);
1116 int GeomNode::CData::
1121 GeomList::iterator gi;
1122 PT(GeomList) geoms = _geoms.get_write_pointer();
1123 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1124 GeomEntry &entry = (*gi);
1125 entry._geom = DCAST(
Geom, p_list[pi++]);
1136 void GeomNode::CData::
1140 PT(GeomList) geoms =
new GeomList;
1141 geoms->reserve(num_geoms);
1142 for (
int i = 0; i < num_geoms; i++) {
1145 geoms->push_back(GeomEntry(
nullptr,
nullptr));