50 _allow_tex_mat =
false;
66 _geom_node_list.clear();
81 if (grutil_cat.is_debug()) {
83 <<
"scan(" << *node <<
", " << *state <<
", " << *transform <<
")\n";
86 CPT(
RenderState) next_state = state->compose(node->get_state());
87 CPT(
TransformState) next_transform = transform->compose(node->get_transform());
93 node->
set_state(node->get_state()->remove_attrib(TextureAttrib::get_class_slot()));
96 scan_geom_node(DCAST(
GeomNode, node), next_state, next_transform);
101 for (
int i = 0; i < num_children; i++) {
112 _target_stage = stage;
135 _use_geom = use_geom;
153 _allow_tex_mat = allow_tex_mat;
166 if (grutil_cat.is_debug()) {
168 <<
"Beginning flatten operation\n";
169 Stages::const_iterator mi;
170 for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
171 const StageList &stage_list = (*mi).first;
172 const GeomList &geom_list = (*mi).second;
173 grutil_cat.debug(
false)
174 <<
"stage_list for:";
175 for (GeomList::const_iterator gi = geom_list.begin();
176 gi != geom_list.end();
178 const GeomInfo &geom_info = (*gi);
179 grutil_cat.debug(
false)
180 <<
" (" << geom_info._geom_node->get_name() <<
" g"
181 << geom_info._index <<
")";
183 grutil_cat.debug(
false) <<
":\n";
185 StageList::const_iterator si;
186 for (si = stage_list.begin(); si != stage_list.end(); ++si) {
187 const StageInfo &stage_info = (*si);
188 grutil_cat.debug(
false)
189 <<
" " << *stage_info._stage <<
" " << *stage_info._tex
190 <<
" " << *stage_info._tex_mat <<
"\n";
194 Stages::const_iterator mi;
195 for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
196 const StageList &stage_list = (*mi).first;
197 const GeomList &geom_list = (*mi).second;
200 bool use_transparent_bg =
false;
201 if(stage_list.size() > 0) {
202 if(stage_list[0]._stage->get_mode() == TextureStage::M_decal)
203 use_transparent_bg =
true;
205 use_transparent_bg =
false;
207 grutil_cat.debug(
false) <<
"use transparent bg = " << use_transparent_bg <<
"\n";
215 const StageInfo &model_stage = stage_list[choose_model_stage(stage_list)];
217 Texture *model_tex = model_stage._tex;
219 SamplerState::FilterType minfilter = model_tex->
get_minfilter();
220 SamplerState::FilterType magfilter = model_tex->
get_magfilter();
223 LTexCoord min_uv, max_uv;
224 determine_uv_range(min_uv, max_uv, model_stage, geom_list);
230 get_uv_scale(uv_scale, uv_trans, min_uv, max_uv);
238 choose_texture_size(x_size, y_size, model_stage, uv_scale,
241 static int multitex_id = 1;
242 std::ostringstream multitex_name_strm;
243 multitex_name_strm <<
"multitex" << multitex_id;
247 (multitex_name_strm.str(), x_size, y_size,
nullptr,
false);
263 lens->set_film_size(1.0f, 1.0f);
264 lens->set_film_offset(0.5f, 0.5f);
265 lens->set_near_far(-1000.0f, 1000.0f);
266 lens->set_view_mat(LMatrix4(uv_scale[0], 0.0f, 0.0, 0.0f,
267 0.0f, 1.0f, 0.0, 0.0f,
268 0.0f, 0.0f, uv_scale[1], 0.0f,
269 uv_trans[0], 0.0f, uv_trans[1], 1.0f));
270 cam_node->set_lens(lens);
286 bool force_use_geom = _use_geom;
287 bool bake_in_color = _use_geom;
288 LColor geom_color(1.0f, 1.0f, 1.0f, 1.0f);
291 if(use_transparent_bg)
292 geom_color = LColor(0.0f,0.0f,0.0f,0.0f);
294 if (!force_use_geom) {
295 bool uses_decal = scan_decal(stage_list);
299 bake_in_color =
true;
313 if (!force_use_geom) {
318 cm.set_frame(min_uv[0], max_uv[0], min_uv[1], max_uv[1]);
320 cm.set_color(geom_color);
327 nassertv(bake_in_color);
329 transfer_geom(geom_node,
nullptr, geom_list,
true);
334 StageList::const_iterator si;
335 for (si = stage_list.begin(); si != stage_list.end(); ++si) {
336 const StageInfo &stage_info = (*si);
338 make_texture_layer(render, stage_info, geom_list,
339 min_uv, max_uv, force_use_geom, use_transparent_bg);
345 add_on_stage(_target_stage, tex);
347 GeomList::const_iterator gi;
348 for (gi = geom_list.begin(); gi != geom_list.end(); ++gi) {
349 const GeomInfo &geom_info = (*gi);
352 geom_info._geom_node->get_geom_state(geom_info._index);
353 int override = geom_info._geom_net_state->get_override(TextureAttrib::get_class_slot());
354 geom_state = geom_state->add_attrib(new_ta,
override);
359 geom_state = geom_state->add_attrib(ColorAttrib::make_flat(LColor(1.0f, 1.0f, 1.0f, 1.0f)));
366 geom_info._geom_net_state->get_attrib(ColorScaleAttrib::get_class_slot());
368 if (attrib !=
nullptr) {
369 geom_state = geom_state->add_attrib
370 (attrib->invert_compose(ColorScaleAttrib::make_identity()));
377 const RenderAttrib *ra = geom_info._state->get_attrib(TexMatrixAttrib::get_class_slot());
385 tex_mat = tex_mat->compose(TransformState::make_pos_hpr_scale
386 (LVecBase3(uv_trans[0], uv_trans[1], 0.0f),
387 LVecBase3(0.0f, 0.0f, 0.0f),
388 LVecBase3(uv_scale[0], uv_scale[1], 1.0f)));
390 if (tex_mat->is_identity()) {
392 geom_state = geom_state->remove_attrib(TexMatrixAttrib::get_class_slot());
396 (_target_stage, tex_mat->invert_compose(TransformState::make_identity()));
397 geom_state = geom_state->add_attrib(new_tma);
401 geom_info._geom_node->set_geom_state(geom_info._index, geom_state);
409 GeomNodeList::const_iterator gni;
410 for (gni = _geom_node_list.begin(); gni != _geom_node_list.end(); ++gni) {
411 const GeomNodeInfo &geom_node_info = (*gni);
414 geom_node_info._state->get_attrib(TextureAttrib::get_class_slot());
415 geom_node_info._geom_node->apply_attribs_to_vertices
416 (attribs, SceneGraphReducer::TT_tex_matrix, transformer);
424 void MultitexReducer::
427 if (grutil_cat.is_debug()) {
429 <<
"scan_geom_node(" << *node <<
", " << *state <<
", "
430 << *transform <<
")\n";
433 _geom_node_list.push_back(GeomNodeInfo(state, node));
436 for (
int gi = 0; gi < num_geoms; gi++) {
440 if (grutil_cat.is_debug()) {
442 <<
"geom " << gi <<
" net_state =\n";
443 geom_net_state->write(std::cerr, 2);
450 attrib = geom_net_state->get_attrib(TextureAttrib::get_class_slot());
451 if (attrib !=
nullptr) {
458 geom_state = geom_state->remove_attrib(TextureAttrib::get_class_slot());
465 int override = geom_net_state->get_override(TextureAttrib::get_class_slot());
467 geom_state = geom_state->add_attrib(ta,
override);
473 attrib = geom_net_state->get_attrib(TexMatrixAttrib::get_class_slot());
474 if (attrib !=
nullptr) {
478 StageList stage_list;
481 for (
int si = 0; si < num_stages; si++) {
485 stage_list.push_back(StageInfo(stage, ta, tma));
489 <<
"Ignoring invalid texture stage " << stage->
get_name() <<
"\n";
493 if (stage_list.size() >= 2) {
494 record_stage_list(stage_list, GeomInfo(state, geom_net_state, node, gi));
503 void MultitexReducer::
505 const MultitexReducer::GeomInfo &geom_info) {
506 if (grutil_cat.is_debug()) {
508 <<
"record_stage_list for " << geom_info._geom_node->get_name() <<
" g"
509 << geom_info._index <<
":\n";
510 StageList::const_iterator si;
511 for (si = stage_list.begin(); si != stage_list.end(); ++si) {
512 const StageInfo &stage_info = (*si);
513 grutil_cat.debug(
false)
514 <<
" " << *stage_info._stage <<
" " << *stage_info._tex
515 <<
" " << *stage_info._tex_mat <<
"\n";
519 _stages[stage_list].push_back(geom_info);
526 size_t MultitexReducer::
528 for (
size_t si = 0; si < stage_list.size(); si++) {
529 const StageInfo &stage_info = stage_list[si];
530 if (stage_info._stage == _target_stage) {
544 bool MultitexReducer::
545 determine_uv_range(LTexCoord &min_uv, LTexCoord &max_uv,
546 const MultitexReducer::StageInfo &model_stage,
548 const InternalName *model_name = model_stage._stage->get_texcoord_name();
549 bool got_any =
false;
551 GeomList::const_iterator gi;
552 for (gi = geom_list.begin(); gi != geom_list.end(); ++gi) {
553 const GeomInfo &geom_info = (*gi);
556 geom_info._geom_node->get_geom(geom_info._index)->make_copy();
560 if (format->has_column(model_name)) {
563 if (!texcoord.is_at_end()) {
564 const LVecBase2 &uv = texcoord.get_data2();
566 min_uv = max_uv = uv;
570 min_uv.set(min(min_uv[0], uv[0]), min(min_uv[1], uv[1]));
571 max_uv.set(max(max_uv[0], uv[0]), max(max_uv[1], uv[1]));
574 while (!texcoord.is_at_end()) {
575 const LVecBase2 &uv = texcoord.get_data2();
576 min_uv.set(min(min_uv[0], uv[0]), min(min_uv[1], uv[1]));
577 max_uv.set(max(max_uv[0], uv[0]), max(max_uv[1], uv[1]));
584 min_uv.set(0.0f, 0.0f);
585 max_uv.set(1.0f, 1.0f);
598 void MultitexReducer::
599 get_uv_scale(LVecBase2 &uv_scale, LVecBase2 &uv_trans,
600 const LTexCoord &min_uv,
const LTexCoord &max_uv)
const {
601 if (max_uv[0] != min_uv[0]) {
602 uv_scale[0] = (max_uv[0] - min_uv[0]);
607 if (max_uv[1] != min_uv[1]) {
608 uv_scale[1] = (max_uv[1] - min_uv[1]);
613 uv_trans[0] = (min_uv[0] + max_uv[0]) / 2.0f - uv_scale[0] * 0.5f;
614 uv_trans[1] = (min_uv[1] + max_uv[1]) / 2.0f - uv_scale[1] * 0.5f;
621 void MultitexReducer::
622 choose_texture_size(
int &x_size,
int &y_size,
623 const MultitexReducer::StageInfo &model_stage,
624 const LVecBase2 &uv_scale,
626 Texture *model_tex = model_stage._tex;
636 LVecBase3 inherited_scale = model_stage._tex_mat->get_scale();
638 PN_stdfloat u_scale = cabs(inherited_scale[0]) * uv_scale[0];
639 if (u_scale != 0.0f) {
640 while (u_scale >= 2.0f) {
644 while (u_scale <= 0.5f && x_size > 0) {
650 PN_stdfloat v_scale = cabs(inherited_scale[1]) * uv_scale[1];
651 if (v_scale != 0.0f) {
652 while (v_scale >= 2.0f) {
656 while (v_scale <= 0.5f && y_size > 0) {
662 if (x_size == 0 || y_size == 0) {
664 <<
"Texture size " << model_tex->
get_x_size() <<
" "
666 << model_stage._tex_mat->get_scale() <<
", reduced to size "
667 << x_size <<
" " << y_size <<
"; constraining to 1 1.\n";
673 if (max_texture_dimension > 0) {
674 x_size = min(x_size, (
int)max_texture_dimension);
675 y_size = min(y_size, (
int)max_texture_dimension);
681 if (win_x_size != 0 && x_size > win_x_size) {
683 while (x_size > win_x_size) {
689 if (win_y_size != 0 && y_size > win_y_size) {
691 while (y_size > win_y_size) {
701 void MultitexReducer::
702 make_texture_layer(
const NodePath &render,
703 const MultitexReducer::StageInfo &stage_info,
705 const LTexCoord &min_uv,
const LTexCoord &max_uv,
706 bool force_use_geom,
bool transparent_base) {
709 switch (stage_info._stage->get_mode()) {
710 case TextureStage::M_normal:
711 case TextureStage::M_normal_height:
712 case TextureStage::M_glow:
713 case TextureStage::M_gloss:
714 case TextureStage::M_height:
715 case TextureStage::M_selector:
716 case TextureStage::M_normal_gloss:
720 case TextureStage::M_modulate_glow:
721 case TextureStage::M_modulate_gloss:
722 case TextureStage::M_modulate:
723 cba = ColorBlendAttrib::make
724 (ColorBlendAttrib::M_add, ColorBlendAttrib::O_fbuffer_color,
725 ColorBlendAttrib::O_zero);
728 case TextureStage::M_decal:
729 if(transparent_base) {
730 cba = AlphaTestAttrib::make
731 (AlphaTestAttrib::M_greater, 0.0f);
733 cba = ColorBlendAttrib::make
734 (ColorBlendAttrib::M_add, ColorBlendAttrib::O_incoming_alpha,
735 ColorBlendAttrib::O_one_minus_incoming_alpha);
739 case TextureStage::M_blend:
740 cba = ColorBlendAttrib::make
741 (ColorBlendAttrib::M_add, ColorBlendAttrib::O_constant_color,
742 ColorBlendAttrib::O_one_minus_incoming_color,
743 stage_info._stage->get_color());
746 case TextureStage::M_replace:
747 cba = ColorBlendAttrib::make_off();
750 case TextureStage::M_add:
751 cba = ColorBlendAttrib::make
752 (ColorBlendAttrib::M_add, ColorBlendAttrib::O_one,
753 ColorBlendAttrib::O_one);
756 case TextureStage::M_combine:
758 switch (stage_info._stage->get_combine_rgb_mode()) {
759 case TextureStage::CM_modulate:
761 TextureStage::CombineSource source0 = stage_info._stage->get_combine_rgb_source0();
762 TextureStage::CombineSource source1 = stage_info._stage->get_combine_rgb_source1();
766 if (source1 < source0) {
767 source0 = stage_info._stage->get_combine_rgb_source1();
768 source1 = stage_info._stage->get_combine_rgb_source0();
771 if (source0 == TextureStage::CS_primary_color &&
772 source1 == TextureStage::CS_previous) {
778 }
else if (source0 == TextureStage::CS_texture &&
779 source1 == TextureStage::CS_constant) {
781 cba = ColorBlendAttrib::make
782 (ColorBlendAttrib::M_add, ColorBlendAttrib::O_constant_color,
783 ColorBlendAttrib::O_zero, stage_info._stage->get_color());
785 }
else if (source0 == TextureStage::CS_texture &&
786 source1 == TextureStage::CS_previous) {
788 cba = ColorBlendAttrib::make
789 (ColorBlendAttrib::M_add, ColorBlendAttrib::O_fbuffer_color,
790 ColorBlendAttrib::O_zero);
805 case TextureStage::M_blend_color_scale:
807 cba = ColorBlendAttrib::make
808 (ColorBlendAttrib::M_add, ColorBlendAttrib::O_constant_color,
809 ColorBlendAttrib::O_one_minus_incoming_color,
810 stage_info._stage->get_color());
816 if (!force_use_geom && stage_info._stage->get_texcoord_name() == _target_stage->get_texcoord_name()) {
819 CardMaker cm(stage_info._tex->get_name());
820 cm.set_uv_range(min_uv, max_uv);
821 cm.set_has_uvs(
true);
822 cm.set_frame(min_uv[0], max_uv[0], min_uv[1], max_uv[1]);
832 transfer_geom(geom_node, stage_info._stage->get_texcoord_name(),
837 geom.
set_color(LColor(1.0f, 1.0f, 1.0f, 1.0f));
840 if (!stage_info._tex_mat->is_identity()) {
854 void MultitexReducer::
857 bool preserve_color) {
859 GeomList::const_iterator gi;
860 for (gi = geom_list.begin(); gi != geom_list.end(); ++gi) {
861 const GeomInfo &geom_info = (*gi);
862 const Geom *orig_geom = geom_info._geom_node->get_geom(geom_info._index);
869 geom->set_vertex_data(geom->get_animated_vertex_data(
true, current_thread));
874 vdata->set_usage_hint(Geom::UH_stream);
876 if (vdata->has_column(_target_stage->get_texcoord_name())) {
878 GeomVertexReader texcoord(vdata, _target_stage->get_texcoord_name(), current_thread);
880 while (!texcoord.is_at_end()) {
881 const LVecBase2 &tc = texcoord.get_data2();
882 vertex.set_data3(tc[0], 0.0f, tc[1]);
886 if (texcoord_name !=
nullptr &&
887 texcoord_name != InternalName::get_texcoord()) {
891 vdata->get_format()->get_column(texcoord_name);
892 if (column !=
nullptr) {
893 vdata = vdata->replace_column
896 geom->set_vertex_data(vdata);
900 while (!from.is_at_end()) {
901 to.add_data2(from.get_data2());
906 CPT(
RenderState) geom_state = RenderState::make_empty();
907 if (preserve_color) {
909 const RenderAttrib *ca = geom_info._geom_net_state->get_attrib(ColorAttrib::get_class_slot());
911 geom_state = geom_state->add_attrib(ca);
913 const RenderAttrib *csa = geom_info._geom_net_state->get_attrib(ColorScaleAttrib::get_class_slot());
914 if (csa !=
nullptr) {
915 geom_state = geom_state->add_attrib(csa);
919 geom_node->
add_geom(geom, geom_state);
931 void MultitexReducer::
933 int &num_colors)
const {
934 GeomList::const_iterator gi;
935 for (gi = geom_list.begin(); gi != geom_list.end() && num_colors < 2; ++gi) {
936 const GeomInfo &geom_info = (*gi);
939 bool has_flat_color =
false;
940 bool has_vertex_color =
false;
942 LColor color_scale(1.0f, 1.0f, 1.0f, 1.0f);
943 const RenderAttrib *csa = geom_info._geom_net_state->get_attrib(ColorScaleAttrib::get_class_slot());
944 if (csa !=
nullptr) {
951 ColorAttrib::Type color_type = ColorAttrib::T_vertex;
952 const RenderAttrib *ca = geom_info._geom_net_state->get_attrib(ColorAttrib::get_class_slot());
954 color_type = DCAST(
ColorAttrib, ca)->get_color_type();
957 if (color_type == ColorAttrib::T_flat) {
960 has_flat_color =
true;
962 }
else if (color_type == ColorAttrib::T_vertex) {
964 const Geom *geom = geom_info._geom_node->get_geom(geom_info._index);
965 if (geom->get_vertex_data()->has_column(InternalName::get_color())) {
968 has_vertex_color =
true;
972 if (has_vertex_color) {
975 }
else if (has_flat_color) {
976 flat_color.set(flat_color[0] * color_scale[0],
977 flat_color[1] * color_scale[1],
978 flat_color[2] * color_scale[2],
979 flat_color[3] * color_scale[3]);
981 if (num_colors == 0) {
983 geom_color = flat_color;
985 }
else if (!flat_color.almost_equal(geom_color)) {
997 bool MultitexReducer::
999 StageList::const_iterator si;
1000 for (si = stage_list.begin(); si != stage_list.end(); ++si) {
1001 const StageInfo &stage_info = (*si);
1003 if (stage_info._stage->get_mode() == TextureStage::M_decal) {
1015 MultitexReducer::StageInfo::
1022 if (tma->has_stage(stage)) {
1023 _tex_mat = tma->get_transform(stage);