Browse Source

fixes to MultitexReducer

David Rose 20 years ago
parent
commit
b7fd641aa9

+ 14 - 2
panda/src/egg2pg/eggLoader.cxx

@@ -410,7 +410,7 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
 
 ////////////////////////////////////////////////////////////////////
 //     Function: EggLoader::make_transform
-//       Access: Public, Static
+//       Access: Public
 //  Description: Creates a TransformState object corresponding to the
 //               indicated EggTransform.
 ////////////////////////////////////////////////////////////////////
@@ -525,7 +525,19 @@ make_transform(const EggTransform *egg_transform) {
     }
   }
 
-  return ts;
+  if (ts->components_given()) {
+    return ts;
+  }
+
+  // Finally, we uniquify all the matrix-based TransformStates we
+  // create by complete matrix value.  The TransformState class
+  // doesn't normally go this far, because of the cost of this
+  // additional uniquification step, but this is the egg loader so we
+  // don't mind spending a little bit of extra time here to get a more
+  // optimal result.
+  TransformStates::iterator tsi = _transform_states.insert(TransformStates::value_type(ts->get_mat(), ts)).first;
+  
+  return (*tsi).second;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 4 - 1
panda/src/egg2pg/eggLoader.h

@@ -81,7 +81,7 @@ public:
                     const LMatrix4d *transform, bool is_dynamic,
                     CharacterMaker *character_maker);
 
-  static CPT(TransformState) make_transform(const EggTransform *egg_transform);
+  CPT(TransformState) make_transform(const EggTransform *egg_transform);
 
 private:
   class TextureDef {
@@ -228,6 +228,9 @@ private:
   typedef pmap<VertexPoolTransform, PT(GeomVertexData) > VertexPoolData;
   VertexPoolData _vertex_pool_data;
 
+  typedef pmap<LMatrix4f, CPT(TransformState) > TransformStates;
+  TransformStates _transform_states;
+
   DeferredNodes _deferred_nodes;
 
 public:

+ 2 - 2
panda/src/egg2pg/eggRenderState.cxx

@@ -527,7 +527,7 @@ get_tex_gen(const EggTexture *egg_tex) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: EggRenderState::apply_tex_mat
-//       Access: Private, Static
+//       Access: Private
 //  Description: Applies the texture matrix from the indicated egg
 //               texture to the given TexMatrixAttrib, and returns the
 //               new attrib.
@@ -536,7 +536,7 @@ CPT(RenderAttrib) EggRenderState::
 apply_tex_mat(CPT(RenderAttrib) tex_mat_attrib, 
               TextureStage *stage, const EggTexture *egg_tex) {
   if (egg_tex->has_transform()) {
-    CPT(TransformState) transform = EggLoader::make_transform(egg_tex);
+    CPT(TransformState) transform = _loader.make_transform(egg_tex);
   
     if (tex_mat_attrib == (const RenderAttrib *)NULL) {
       tex_mat_attrib = TexMatrixAttrib::make();

+ 1 - 1
panda/src/egg2pg/eggRenderState.h

@@ -57,7 +57,7 @@ private:
                                         bool bface);
   static TexGenAttrib::Mode get_tex_gen(const EggTexture *egg_tex);
 
-  static CPT(RenderAttrib)
+  CPT(RenderAttrib)
   apply_tex_mat(CPT(RenderAttrib) tex_mat_attrib, 
                 TextureStage *stage, const EggTexture *egg_tex);
 

+ 1 - 1
panda/src/grutil/multitexReducer.I

@@ -79,7 +79,7 @@ operator < (const MultitexReducer::StageInfo &other) const {
     return _tex < other._tex;
   }
   if (_tex_mat != other._tex_mat) {
-    return _tex_mat < other._tex_mat;
+    return _tex_mat->sorts_less(*other._tex_mat, true);
   }
 
   return false;

+ 60 - 11
panda/src/grutil/multitexReducer.cxx

@@ -328,7 +328,7 @@ flatten(GraphicsOutput *window) {
       // for the first texture layer to apply onto.
       
       CardMaker cm("background");
-      cm.set_frame(0.0f, 1.0f, 0.0f, 1.0f);
+      cm.set_frame(min_uv[0], max_uv[0], min_uv[1], max_uv[1]);
       if (bake_in_color) {
         cm.set_color(geom_color);
       }
@@ -348,7 +348,8 @@ flatten(GraphicsOutput *window) {
     for (si = stage_list.begin(); si != stage_list.end(); ++si) {
       const StageInfo &stage_info = (*si);
 
-      make_texture_layer(render, stage_info, geom_list, force_use_geom);
+      make_texture_layer(render, stage_info, geom_list, 
+			 min_uv, max_uv, force_use_geom);
     }
 
     // Now modify the geometry to apply the new texture, instead of
@@ -362,7 +363,8 @@ flatten(GraphicsOutput *window) {
       
       CPT(RenderState) geom_state = 
         geom_info._geom_node->get_geom_state(geom_info._index);
-      geom_state = geom_state->add_attrib(new_ta);
+      int override = geom_info._geom_net_state->get_override(TextureAttrib::get_class_type());
+      geom_state = geom_state->add_attrib(new_ta, override);
 
       if (bake_in_color) {
         // If we have baked the color into the texture, we have to be
@@ -475,8 +477,9 @@ scan_geom_node(GeomNode *node, const RenderState *state,
       // Just a single texture on the Geom; we don't really need to do
       // anything to flatten the textures, then.  But we should ensure
       // that the correct TextureAttrib is applied to the Geom.
+      int override = geom_net_state->get_override(TextureAttrib::get_class_type());
       CPT(RenderState) geom_state = node->get_geom_state(gi);
-      geom_state = geom_state->add_attrib(ta);
+      geom_state = geom_state->add_attrib(ta, override);
       node->set_geom_state(gi, geom_state);
 
     } else {
@@ -734,6 +737,7 @@ void MultitexReducer::
 make_texture_layer(const NodePath &render, 
                    const MultitexReducer::StageInfo &stage_info, 
                    const MultitexReducer::GeomList &geom_list,
+		   const TexCoordf &min_uv, const TexCoordf &max_uv,
                    bool force_use_geom) {
   CPT(RenderAttrib) cba;
 
@@ -768,11 +772,56 @@ make_texture_layer(const NodePath &render,
     break;
 
   case TextureStage::M_combine:
-    // We don't support the texture combiner here right now.  For now,
-    // this is the same as modulate.
-    cba = ColorBlendAttrib::make
-      (ColorBlendAttrib::M_add, ColorBlendAttrib::O_fbuffer_color,
-       ColorBlendAttrib::O_zero);
+    // We only support certain modes of M_combine.
+    switch (stage_info._stage->get_combine_rgb_mode()) {
+    case TextureStage::CM_modulate:
+      {
+	TextureStage::CombineSource source0 = stage_info._stage->get_combine_rgb_source0();
+	TextureStage::CombineOperand operand0 = stage_info._stage->get_combine_rgb_operand0();
+	TextureStage::CombineSource source1 = stage_info._stage->get_combine_rgb_source1();
+	TextureStage::CombineOperand operand1 = stage_info._stage->get_combine_rgb_operand1();
+	// Since modulate doesn't care about order, let's establish
+	// the convention that the lowest-numbered source 
+	// operand is in slot 0 (just for purposes of comparison).
+	if (source1 < source0) {
+	  source0 = stage_info._stage->get_combine_rgb_source1();
+	  operand0 = stage_info._stage->get_combine_rgb_operand1();
+	  source1 = stage_info._stage->get_combine_rgb_source0();
+	  operand1 = stage_info._stage->get_combine_rgb_operand0();
+	}
+
+	if (source0 == TextureStage::CS_primary_color &&
+	    source1 == TextureStage::CS_previous) {
+	  // This is just a trick to re-apply the vertex (lighting)
+	  // color on the top of the texture stack.  We can ignore it,
+	  // since the flattened texture will do this anyway.
+	  return;
+	  
+	} else if (source0 == TextureStage::CS_texture &&
+		   source1 == TextureStage::CS_constant) {
+	  // Scaling the texture by a flat color.
+	  cba = ColorBlendAttrib::make
+	    (ColorBlendAttrib::M_add, ColorBlendAttrib::O_constant_color,
+	     ColorBlendAttrib::O_zero, stage_info._stage->get_color());
+	  
+	} else if (source0 == TextureStage::CS_texture &&
+		   source1 == TextureStage::CS_previous) {
+	  // Just an ordinary modulate.
+	  cba = ColorBlendAttrib::make
+	    (ColorBlendAttrib::M_add, ColorBlendAttrib::O_fbuffer_color,
+	     ColorBlendAttrib::O_zero);
+	  
+	} else {
+	  // Some other kind of modulate; we don't support it.
+	  return;
+	}
+      }
+      break;
+
+    default:
+      // Ignore this stage; we don't support it.
+      return;
+    }
     break;
 
   case TextureStage::M_blend_color_scale:
@@ -790,9 +839,9 @@ make_texture_layer(const NodePath &render,
     // If this TextureStage uses the target texcoords, we can just
     // generate a simple card the fills the entire buffer.
     CardMaker cm(stage_info._tex->get_name());
-    cm.set_uv_range(TexCoordf(0.0f, 0.0f), TexCoordf(1.0f, 1.0f));
+    cm.set_uv_range(min_uv, max_uv);
     cm.set_has_uvs(true);
-    cm.set_frame(0.0f, 1.0f, 0.0f, 1.0f);
+    cm.set_frame(min_uv[0], max_uv[0], min_uv[1], max_uv[1]);
     
     geom = render.attach_new_node(cm.generate());
 

+ 1 - 0
panda/src/grutil/multitexReducer.h

@@ -138,6 +138,7 @@ private:
   void make_texture_layer(const NodePath &render, 
                           const StageInfo &stage_info, 
                           const GeomList &geom_list,
+			  const TexCoordf &min_uv, const TexCoordf &max_uv,
                           bool force_use_geom);
   void transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name,
                      const GeomList &geom_list, bool preserve_color);

+ 16 - 0
panda/src/pgraph/transformState.I

@@ -17,6 +17,22 @@
 ////////////////////////////////////////////////////////////////////
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: TransformState::operator <
+//       Access: Published
+//  Description: Provides an arbitrary ordering among all unique
+//               TransformStates, so we can store the essentially
+//               different ones in a big set and throw away the rest.
+//
+//               This is the same as sorts_less(), except the
+//               uniquify_matrix value is implicit from the Config.prc
+//               file.
+////////////////////////////////////////////////////////////////////
+INLINE bool TransformState::
+operator < (const TransformState &other) const {
+  return sorts_less(other, uniquify_matrix);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: TransformState::make_pos
 //       Access: Published, Static

+ 8 - 2
panda/src/pgraph/transformState.cxx

@@ -110,14 +110,20 @@ TransformState::
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: TransformState::operator <
+//     Function: TransformState::sorts_less
 //       Access: Published
 //  Description: Provides an arbitrary ordering among all unique
 //               TransformStates, so we can store the essentially
 //               different ones in a big set and throw away the rest.
+//
+//               If uniquify_matrix is true, then matrix-defined
+//               TransformStates are also uniqified.  If
+//               uniquify_matrix is false, then only component-defined
+//               TransformStates are uniquified, which is less
+//               expensive.
 ////////////////////////////////////////////////////////////////////
 bool TransformState::
-operator < (const TransformState &other) const {
+sorts_less(const TransformState &other, bool uniquify_matrix) const {
   static const int significant_flags = 
     (F_is_invalid | F_is_identity | F_components_given | F_hpr_given | F_quat_given | F_is_2d);
 

+ 3 - 1
panda/src/pgraph/transformState.h

@@ -30,6 +30,7 @@
 #include "pStatCollector.h"
 #include "geomEnums.h"
 #include "reMutex.h"
+#include "config_pgraph.h"
 
 class GraphicsStateGuardianBase;
 class FactoryParams;
@@ -68,7 +69,8 @@ public:
   virtual ~TransformState();
 
 PUBLISHED:
-  bool operator < (const TransformState &other) const;
+  INLINE bool operator < (const TransformState &other) const;
+  bool sorts_less(const TransformState &other, bool uniquify_matrix) const;
   size_t get_hash() const;
 
   static CPT(TransformState) make_identity();