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) {
321 xform(
const LMatrix4 &mat) {
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";
514 int num_geoms = geoms.get_num_geoms();
515 trav->_geoms_pcollector.add_level(num_geoms);
516 CPT(
TransformState) internal_transform = data.get_internal_transform(trav);
518 for (
int i = 0; i < num_geoms; i++) {
519 CPT(
Geom) geom = geoms.get_geom(i);
520 if (geom->is_empty()) {
524 CPT(
RenderState) state = data._state->compose(geoms.get_geom_state(i));
525 if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
535 if (data._view_frustum !=
nullptr) {
537 CPT(
BoundingVolume) geom_volume = geom->get_bounds(current_thread);
541 int result = data._view_frustum->contains(geom_gbv);
542 if (result == BoundingVolume::IF_no_intersection) {
547 if (!data._cull_planes->is_empty()) {
549 CPT(
BoundingVolume) geom_volume = geom->get_bounds(current_thread);
553 data._cull_planes->do_cull(result, state, geom_gbv);
554 if (result == BoundingVolume::IF_no_intersection) {
562 new CullableObject(std::move(geom), std::move(state), internal_transform);
587 nassertv(geom !=
nullptr);
589 nassertv(state !=
nullptr);
592 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
593 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
595 cdata->modify_geoms()->push_back(
GeomEntry(geom, state));
597 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
599 mark_internal_bounds_stale();
609 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
610 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
611 CDStageReader cdata_other(other->_cycler, pipeline_stage, current_thread);
613 GeomList::const_iterator gi;
614 CPT(
GeomList) other_geoms = cdata_other->get_geoms();
615 PT(
GeomList) this_geoms = cdata->modify_geoms();
616 for (gi = other_geoms->begin(); gi != other_geoms->end(); ++gi) {
618 nassertv(entry._geom.get_read_pointer()->check_valid());
619 this_geoms->push_back(entry);
622 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
624 mark_internal_bounds_stale();
638 nassertv(geom !=
nullptr);
642 PT(
GeomList) geoms = cdata->modify_geoms();
643 nassertv(n >= 0 && n < (
int)geoms->size());
644 (*geoms)[n]._geom = geom;
646 mark_internal_bounds_stale();
657 for (
int i = 0; i < num_geoms; i++) {
658 const Geom *geom = get_geom(i);
680 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
681 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
683 GeomList::iterator gi;
684 PT(
GeomList) geoms = cdata->modify_geoms();
685 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
687 nassertv(entry._geom.test_ref_count_integrity());
688 PT(
Geom) geom = entry._geom.get_write_pointer();
689 geom->decompose_in_place();
692 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
714 unify(
int max_indices,
bool preserve_order) {
715 bool any_changed =
false;
718 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
719 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
726 GeomList::const_iterator gi;
727 CPT(
GeomList) old_geoms = cdata->get_geoms();
728 for (gi = old_geoms->begin(); gi != old_geoms->end(); ++gi) {
731 bool unified =
false;
734 GeomList::reverse_iterator gj;
735 for (gj = new_geoms->rbegin(); gj != new_geoms->rend() && !unified; ++gj) {
737 if (old_entry._state == new_entry._state) {
739 CPT(
Geom) old_geom = old_entry._geom.get_read_pointer();
740 PT(
Geom) new_geom = new_entry._geom.get_write_pointer();
741 if (new_geom->copy_primitives_from(old_geom)) {
748 if (preserve_order) {
758 new_geoms->push_back(old_entry);
763 cdata->set_geoms(new_geoms);
766 GeomList::iterator wgi;
767 for (wgi = new_geoms->begin(); wgi != new_geoms->end(); ++wgi) {
769 nassertv(entry._geom.test_ref_count_integrity());
770 PT(
Geom) geom = entry._geom.get_write_pointer();
771 geom->unify_in_place(max_indices, preserve_order);
774 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
777 mark_internal_bounds_stale();
785 write_geoms(std::ostream &out,
int indent_level)
const {
787 write(out, indent_level);
788 GeomList::const_iterator gi;
789 CPT(
GeomList) geoms = cdata->get_geoms();
790 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
792 indent(out, indent_level + 2)
793 << *entry._geom.get_read_pointer() <<
" " << *entry._state <<
"\n";
803 write(out, indent_level);
804 GeomList::const_iterator gi;
805 CPT(
GeomList) geoms = cdata->get_geoms();
806 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
808 CPT(
Geom) geom = entry._geom.get_read_pointer();
809 indent(out, indent_level + 2)
810 << *geom <<
" " << *entry._state <<
"\n";
811 geom->write(out, indent_level + 4);
819 output(std::ostream &out)
const {
825 CDReader cdata(_cycler);
829 GeomList::const_iterator gi;
830 CPT(
RenderState) common = RenderState::make_empty();
832 CPT(GeomList) geoms = cdata->get_geoms();
833 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
834 const GeomEntry &entry = (*gi);
835 common = common->compose(entry._state);
838 PandaNode::output(out);
839 out <<
" (" << geoms->size() <<
" geoms";
841 if (!common->is_empty()) {
842 out <<
": " << *common;
871 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
872 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
874 GeomList::iterator gi;
875 PT(
GeomList) geoms = cdata->modify_geoms();
876 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
878 CPT(
RenderState) geom_state = node_state->compose(entry._state);
879 CPT(
Geom) geom = entry._geom.get_read_pointer();
880 PT(
GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
881 entry._geom = transformer.premunge_geom(geom, munger);
884 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
892 r_mark_geom_bounds_stale(
Thread *current_thread) {
893 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
894 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
896 GeomList::iterator gi;
897 PT(GeomList) geoms = cdata->modify_geoms();
898 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
899 GeomEntry &entry = (*gi);
900 entry._geom.get_read_pointer()->mark_bounds_stale();
903 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
904 mark_internal_bounds_stale();
906 PandaNode::r_mark_geom_bounds_stale(current_thread);
916 int &internal_vertices,
918 Thread *current_thread)
const {
919 int num_vertices = 0;
921 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
927 GeomList::const_iterator gi;
928 CPT(GeomList) geoms = cdata->get_geoms();
929 child_volumes.reserve(geoms->size());
930 child_volumes_ref.reserve(geoms->size());
932 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
933 const GeomEntry &entry = (*gi);
934 CPT(
Geom) geom = entry._geom.get_read_pointer();
937 if (!volume->is_empty()) {
938 child_volumes.push_back(volume);
939 child_volumes_ref.push_back(volume);
940 if (!volume->is_exact_type(BoundingBox::get_class_type())) {
944 num_vertices += geom->get_nested_vertices();
950 if (btype == BoundingVolume::BT_default) {
954 if (btype == BoundingVolume::BT_box ||
955 (btype != BoundingVolume::BT_sphere && all_box)) {
964 if (child_volumes.size() > 0) {
966 const BoundingVolume **child_end = child_begin + child_volumes.size();
970 internal_bounds = gbv;
971 internal_vertices = num_vertices;
1009 CPT(
RenderAttrib) vertex_color = ColorAttrib::make_vertex();
1012 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1013 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1015 GeomList::iterator gi;
1016 PT(
GeomList) geoms = cdata->modify_geoms();
1017 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1019 CPT(
Geom) geom = entry._geom.get_read_pointer();
1024 CPT(
GeomVertexData) vdata = geom->get_vertex_data(current_thread);
1026 for (
size_t i = 0; i < vformat->get_num_arrays(); ++i) {
1031 if (vdata->has_column(color) &&
1032 !entry._state->has_attrib(ColorAttrib::get_class_slot())) {
1036 aux_data->_hold_state = entry._state;
1039 entry._state = entry._state->add_attrib(vertex_color, -1);
1043 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1059 node->fillin(scan, manager);
1074 PandaNode::fillin(scan, manager);
1082 CData(
const GeomNode::CData ©) :
1092 return new CData(*
this);
1099 void GeomNode::CData::
1101 CPT(GeomList) geoms = _geoms.get_read_pointer();
1102 int num_geoms = geoms->size();
1103 nassertv(num_geoms == (
int)(uint16_t)num_geoms);
1106 GeomList::const_iterator gi;
1107 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1108 const GeomEntry &entry = (*gi);
1118 int GeomNode::CData::
1123 GeomList::iterator gi;
1124 PT(GeomList) geoms = _geoms.get_write_pointer();
1125 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1126 GeomEntry &entry = (*gi);
1127 entry._geom = DCAST(
Geom, p_list[pi++]);
1138 void GeomNode::CData::
1142 PT(GeomList) geoms =
new GeomList;
1143 geoms->reserve(num_geoms);
1144 for (
int i = 0; i < num_geoms; i++) {
1147 geoms->push_back(GeomEntry(
nullptr,
nullptr));