Browse Source

Use apply_attribs() to doubleside or reverse triangles

David Rose 18 years ago
parent
commit
3de6d5ac4f

+ 2 - 0
panda/src/pgraph/accumulatedAttribs.I

@@ -41,6 +41,7 @@ AccumulatedAttribs(const AccumulatedAttribs &copy) :
   _tex_matrix(copy._tex_matrix),
   _texture(copy._texture),
   _clip_plane(copy._clip_plane),
+  _cull_face(copy._cull_face),
   _other(copy._other)
 {
 }
@@ -58,5 +59,6 @@ operator = (const AccumulatedAttribs &copy) {
   _tex_matrix = copy._tex_matrix;
   _texture = copy._texture;
   _clip_plane = copy._clip_plane;
+  _cull_face = copy._cull_face;
   _other = copy._other;
 }

+ 55 - 0
panda/src/pgraph/accumulatedAttribs.cxx

@@ -24,6 +24,7 @@
 #include "texMatrixAttrib.h"
 #include "textureAttrib.h"
 #include "clipPlaneAttrib.h"
+#include "cullFaceAttrib.h"
 #include "config_pgraph.h"
 
 
@@ -65,6 +66,13 @@ write(ostream &out, int attrib_types, int indent_level) const {
       _clip_plane->write(out, indent_level);
     }
   }
+  if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
+    if (_cull_face == (const RenderAttrib *)NULL) {
+      indent(out, indent_level) << "no cull face\n";
+    } else {
+      _cull_face->write(out, indent_level);
+    }
+  }
   if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
     _other->write(out, indent_level);
   }
@@ -159,6 +167,20 @@ collect(PandaNode *node, int attrib_types) {
     }
   }
 
+  if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
+    const RenderAttrib *node_attrib = 
+      node->get_attrib(CullFaceAttrib::get_class_type());
+    if (node_attrib != (const RenderAttrib *)NULL) {
+      // The node has a cull face attribute; apply it.
+      if (_cull_face == (const RenderAttrib *)NULL) {
+        _cull_face = node_attrib;
+      } else {
+        _cull_face = _cull_face->compose(node_attrib);
+      }
+      node->clear_attrib(CullFaceAttrib::get_class_type());
+    }
+  }
+
   if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
     // Collect everything else.
     nassertv(_other != (RenderState *)NULL);
@@ -192,6 +214,13 @@ collect(PandaNode *node, int attrib_types) {
       collect_state = collect_state->remove_attrib(ClipPlaneAttrib::get_class_type());
       keep_state = keep_state->add_attrib(attrib, override);
     }
+
+    attrib = collect_state->get_attrib(CullFaceAttrib::get_class_type());
+    if (attrib != (const RenderAttrib *)NULL) {
+      int override = collect_state->get_override(CullFaceAttrib::get_class_type());
+      collect_state = collect_state->remove_attrib(CullFaceAttrib::get_class_type());
+      keep_state = keep_state->add_attrib(attrib, override);
+    }
     
     _other = _other->compose(collect_state);
     node->set_state(keep_state);
@@ -278,6 +307,19 @@ collect(const RenderState *state, int attrib_types) {
     }
   }
 
+  if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
+    const RenderAttrib *node_attrib = 
+      new_state->get_attrib(CullFaceAttrib::get_class_type());
+    if (node_attrib != (const RenderAttrib *)NULL) {
+      if (_cull_face == (const RenderAttrib *)NULL) {
+        _cull_face = node_attrib;
+      } else {
+        _cull_face = _cull_face->compose(node_attrib);
+      }
+      new_state = new_state->remove_attrib(CullFaceAttrib::get_class_type());
+    }
+  }
+
   if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
     // Collect everything else.
     nassertr(_other != (RenderState *)NULL, new_state);
@@ -357,6 +399,19 @@ apply_to_node(PandaNode *node, int attrib_types) {
     }
   }
 
+  if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
+    if (_cull_face != (RenderAttrib *)NULL) {
+      const RenderAttrib *node_attrib =
+        node->get_attrib(CullFaceAttrib::get_class_type());
+      if (node_attrib != (RenderAttrib *)NULL) {
+        node->set_attrib(_cull_face->compose(node_attrib));
+      } else {
+        node->set_attrib(_cull_face);
+      }
+      _cull_face = (RenderAttrib *)NULL;
+    }
+  }
+
   if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
     node->set_state(_other->compose(node->get_state()));
     _other = RenderState::make_empty();

+ 1 - 0
panda/src/pgraph/accumulatedAttribs.h

@@ -52,6 +52,7 @@ public:
   CPT(RenderAttrib) _tex_matrix;
   CPT(RenderAttrib) _texture;
   CPT(RenderAttrib) _clip_plane;
+  CPT(RenderAttrib) _cull_face;
   CPT(RenderState) _other;
 };
 

+ 21 - 0
panda/src/pgraph/geomNode.cxx

@@ -114,6 +114,27 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
     }
   }
 
+  if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
+    if (attribs._cull_face != (const RenderAttrib *)NULL) {
+      const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, attribs._cull_face);
+      CullFaceAttrib::Mode mode = cfa->get_effective_mode();
+      switch (mode) {
+      case CullFaceAttrib::M_cull_none:
+        // Doublesided polys.  Duplicate them.
+        transformer.doubleside(this);
+        break;
+        
+      case CullFaceAttrib::M_cull_counter_clockwise:
+        // Reverse winding order.
+        transformer.reverse(this);
+        break;
+        
+      default:
+        break;
+      }
+    }
+  }
+
   Thread *current_thread = Thread::get_current_thread();
   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);

+ 75 - 0
panda/src/pgraph/geomTransformer.cxx

@@ -499,6 +499,81 @@ reverse_normals(Geom *geom) {
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomTransformer::doubleside
+//       Access: Public
+//  Description: Duplicates triangles in this GeomNode so that each
+//               triangle is back-to-back with another triangle facing
+//               in the opposite direction.  If the geometry has
+//               vertex normals, this will also duplicate and reverse
+//               the normals, so that lighting will work correctly
+//               from both sides.  Note that calling this when the
+//               geometry is already doublesided (with back-to-back
+//               polygons) will result in multiple redundant coplanar
+//               polygons.
+//
+//               Also see CullFaceAttrib, which can enable rendering
+//               of both sides of a triangle without having to
+//               duplicate it (but which doesn't necessarily work in
+//               the presence of lighting).
+//
+//               Returns true if any Geoms are modified, false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+bool GeomTransformer::
+doubleside(GeomNode *node) {
+  int num_geoms = node->get_num_geoms();
+  for (int i = 0; i < num_geoms; ++i) {
+    CPT(Geom) orig_geom = node->get_geom(i);
+    bool has_normals = (orig_geom->get_vertex_data()->has_column(InternalName::get_normal()));
+    if (has_normals) {
+      // If the geometry has normals, we have to duplicate it to
+      // reverse the normals on the duplicate copy.
+      PT(Geom) new_geom = orig_geom->reverse();
+      reverse_normals(new_geom);
+      node->add_geom(new_geom, node->get_geom_state(i));
+      
+    } else {
+      // If there are no normals, we can just doubleside it in
+      // place.  This is preferable because we can share vertices.
+      orig_geom.clear();
+      node->modify_geom(i)->doubleside_in_place();
+    }
+  }
+  
+  return (num_geoms != 0);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomTransformer::reverse
+//       Access: Public
+//  Description: Reverses the winding order of triangles in this
+//               GeomNode so that each triangle is facing in the
+//               opposite direction.  If the geometry has vertex
+//               normals, this will also reverse the normals, so that
+//               lighting will work correctly.
+//
+//               Also see CullFaceAttrib, which can effectively change
+//               the facing of a triangle having to modify its
+//               vertices (but which doesn't necessarily work in the
+//               presence of lighting).
+//
+//               Returns true if any Geoms are modified, false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+bool GeomTransformer::
+reverse(GeomNode *node) {
+  int num_geoms = node->get_num_geoms();
+  for (int i = 0; i < num_geoms; ++i) {
+    PT(Geom) geom = node->modify_geom(i);
+    geom->reverse_in_place();
+    reverse_normals(geom);
+  }
+  
+  return (num_geoms != 0);
+}
+  
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomTransformer::collect_vertex_data
 //       Access: Public

+ 2 - 0
panda/src/pgraph/geomTransformer.h

@@ -76,6 +76,8 @@ public:
   bool remove_column(GeomNode *node, const InternalName *column);
 
   bool reverse_normals(Geom *geom);
+  bool doubleside(GeomNode *node);
+  bool reverse(GeomNode *node);
 
   int collect_vertex_data(Geom *geom, int collect_bits);
   int collect_vertex_data(GeomNode *node, int collect_bits);

+ 0 - 126
panda/src/pgraph/sceneGraphReducer.cxx

@@ -29,8 +29,6 @@
 PStatCollector SceneGraphReducer::_flatten_collector("*:Flatten:flatten");
 PStatCollector SceneGraphReducer::_apply_collector("*:Flatten:apply");
 PStatCollector SceneGraphReducer::_remove_column_collector("*:Flatten:remove column");
-PStatCollector SceneGraphReducer::_doubleside_collector("*:Flatten:doubleside");
-PStatCollector SceneGraphReducer::_reverse_collector("*:Flatten:reverse");
 PStatCollector SceneGraphReducer::_collect_collector("*:Flatten:collect");
 PStatCollector SceneGraphReducer::_make_nonindexed_collector("*:Flatten:make nonindexed");
 PStatCollector SceneGraphReducer::_unify_collector("*:Flatten:unify");
@@ -145,52 +143,6 @@ remove_column(PandaNode *root, const InternalName *column) {
   return r_remove_column(root, column, _transformer);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: SceneGraphReducer::doubleside
-//       Access: Published
-//  Description: Duplicates triangles in the GeomNodes at this level
-//               and below so that each triangle is back-to-back with
-//               another triangle facing in the opposite direction.
-//               If the geometry has vertex normals, this will also
-//               duplicate and reverse the normals, so that lighting
-//               will work correctly from both sides.  Note that
-//               calling this when the geometry is already doublesided
-//               (with back-to-back polygons) will result in multiple
-//               redundant coplanar polygons.
-//
-//               Also see CullFaceAttrib, which can enable rendering
-//               of both sides of a triangle without having to
-//               duplicate it (but which doesn't necessarily work in
-//               the presence of lighting).
-//
-//               Returns the number of GeomNodes modified.
-////////////////////////////////////////////////////////////////////
-int SceneGraphReducer::
-doubleside(PandaNode *root) {
-  PStatTimer timer(_doubleside_collector);
-  return r_doubleside(root, _transformer);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: SceneGraphReducer::reverse
-//       Access: Published
-//  Description: Reverses the winding order in the GeomNodes at this
-//               level and below so that each triangle is facing in
-//               the opposite direction it was originally.  If the
-//               geometry has vertex normals, the normals will be
-//               reversed as well.
-//
-//               Also see CullFaceAttrib, which can change the visible
-//               direction of a triangle without having to duplicate
-//               it (but which doesn't necessarily work in the
-//               presence of lighting).
-////////////////////////////////////////////////////////////////////
-int SceneGraphReducer::
-reverse(PandaNode *root) {
-  PStatTimer timer(_reverse_collector);
-  return r_reverse(root, _transformer);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: SceneGraphReducer::unify
 //       Access: Published
@@ -763,84 +715,6 @@ r_remove_column(PandaNode *node, const InternalName *column,
   return num_changed;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: SceneGraphReducer::r_doubleside
-//       Access: Private
-//  Description: The recursive implementation of doubleside().
-////////////////////////////////////////////////////////////////////
-int SceneGraphReducer::
-r_doubleside(PandaNode *node, GeomTransformer &transformer) {
-  int num_changed = 0;
-
-  if (node->is_geom_node()) {
-    PT(GeomNode) gnode = DCAST(GeomNode, node);
-    int num_geoms = gnode->get_num_geoms();
-    for (int i = 0; i < num_geoms; ++i) {
-      CPT(Geom) orig_geom = gnode->get_geom(i);
-      bool has_normals = (orig_geom->get_vertex_data()->has_column(InternalName::get_normal()));
-      if (has_normals) {
-        // If the geometry has normals, we have to duplicate it to
-        // reverse the normals on the duplicate copy.
-        PT(Geom) new_geom = orig_geom->reverse();
-        transformer.reverse_normals(new_geom);
-        gnode->add_geom(new_geom, gnode->get_geom_state(i));
-
-      } else {
-        // If there are no normals, we can just doubleside it in
-        // place.  This is preferable because we can share vertices.
-        orig_geom.clear();
-        gnode->modify_geom(i)->doubleside_in_place();
-      }
-    }
-
-    if (num_geoms != 0) {
-      ++num_changed;
-    }
-  }
-    
-  PandaNode::Children children = node->get_children();
-  int num_children = children.get_num_children();
-  for (int i = 0; i < num_children; ++i) {
-    num_changed +=
-      r_doubleside(children.get_child(i), transformer);
-  }
-
-  return num_changed;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: SceneGraphReducer::r_reverse
-//       Access: Private
-//  Description: The recursive implementation of reverse().
-////////////////////////////////////////////////////////////////////
-int SceneGraphReducer::
-r_reverse(PandaNode *node, GeomTransformer &transformer) {
-  int num_changed = 0;
-
-  if (node->is_geom_node()) {
-    PT(GeomNode) gnode = DCAST(GeomNode, node);
-    int num_geoms = gnode->get_num_geoms();
-    for (int i = 0; i < num_geoms; ++i) {
-      PT(Geom) geom = gnode->modify_geom(i);
-      geom->reverse_in_place();
-      transformer.reverse_normals(geom);
-    }
-
-    if (num_geoms != 0) {
-      ++num_changed;
-    }
-  }
-    
-  PandaNode::Children children = node->get_children();
-  int num_children = children.get_num_children();
-  for (int i = 0; i < num_children; ++i) {
-    num_changed +=
-      r_reverse(children.get_child(i), transformer);
-  }
-
-  return num_changed;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: SceneGraphReducer::r_collect_vertex_data
 //       Access: Private

+ 3 - 8
panda/src/pgraph/sceneGraphReducer.h

@@ -55,7 +55,8 @@ PUBLISHED:
     TT_color_scale     = 0x004,
     TT_tex_matrix      = 0x008,
     TT_clip_plane      = 0x010,
-    TT_other           = 0x020,
+    TT_cull_face       = 0x020,
+    TT_other           = 0x040,
   };
 
   enum CombineSiblings {
@@ -129,15 +130,13 @@ PUBLISHED:
   INLINE void set_combine_radius(float combine_radius);
   INLINE float get_combine_radius() const;
 
-  INLINE void apply_attribs(PandaNode *node, int attrib_types = ~TT_clip_plane);
+  INLINE void apply_attribs(PandaNode *node, int attrib_types = ~(TT_clip_plane | TT_cull_face));
   INLINE void apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
                             int attrib_types, GeomTransformer &transformer);
 
   int flatten(PandaNode *root, int combine_siblings_bits);
 
   int remove_column(PandaNode *root, const InternalName *column);
-  int doubleside(PandaNode *root);
-  int reverse(PandaNode *root);
 
   INLINE int collect_vertex_data(PandaNode *root, int collect_bits = ~0);
   INLINE int make_nonindexed(PandaNode *root, int nonindexed_bits = ~0);
@@ -172,8 +171,6 @@ protected:
 
   int r_remove_column(PandaNode *node, const InternalName *column,
                       GeomTransformer &transformer);
-  int r_doubleside(PandaNode *node, GeomTransformer &transformer);
-  int r_reverse(PandaNode *node, GeomTransformer &transformer);
 
   int r_collect_vertex_data(PandaNode *node, int collect_bits,
                             GeomTransformer &transformer);
@@ -190,8 +187,6 @@ private:
   static PStatCollector _flatten_collector;
   static PStatCollector _apply_collector;
   static PStatCollector _remove_column_collector;
-  static PStatCollector _doubleside_collector;
-  static PStatCollector _reverse_collector;
   static PStatCollector _collect_collector;
   static PStatCollector _make_nonindexed_collector;
   static PStatCollector _unify_collector;