Browse Source

Support wireframe and point rendering modes in OpenGL ES

rdb 10 years ago
parent
commit
87451d8000

+ 13 - 0
panda/src/display/standardMunger.I

@@ -23,3 +23,16 @@ INLINE GraphicsStateGuardian *StandardMunger::
 get_gsg() const {
   return (GraphicsStateGuardian *)GeomMunger::get_gsg();
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: StandardMunger::get_render_mode
+//       Access: Protected
+//  Description: Returns the render mode active on this munger.
+//               Intended for derived classes that may have to munge
+//               differently depending on render mode.
+////////////////////////////////////////////////////////////////////
+INLINE RenderModeAttrib::Mode StandardMunger::
+get_render_mode() const {
+  return (_render_mode != NULL) ? _render_mode->get_mode()
+                                : RenderModeAttrib::M_filled;
+}

+ 2 - 0
panda/src/display/standardMunger.h

@@ -49,6 +49,8 @@ protected:
   virtual int geom_compare_to_impl(const GeomMunger *other) const;
   virtual CPT(RenderState) munge_state_impl(const RenderState *state);
 
+  INLINE RenderModeAttrib::Mode get_render_mode() const;
+
 private:
   int _num_components;
   NumericType _numeric_type;

+ 44 - 0
panda/src/glstuff/glGeomMunger_src.cxx

@@ -362,6 +362,45 @@ premunge_format_impl(const GeomVertexFormat *orig) {
   return format;
 }
 
+#ifdef OPENGLES
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(GeomMunger)::munge_geom_impl
+//       Access: Protected, Virtual
+//  Description: Converts a Geom and/or its data as necessary.
+////////////////////////////////////////////////////////////////////
+void CLP(GeomMunger)::
+munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data,
+                Thread *current_thread) {
+  StandardMunger::munge_geom_impl(geom, vertex_data, current_thread);
+
+  // OpenGL ES has no polygon mode, so we have to emulate it.
+  RenderModeAttrib::Mode render_mode = get_render_mode();
+  if (render_mode == RenderModeAttrib::M_point) {
+    geom = geom->make_points();
+  } else if (render_mode == RenderModeAttrib::M_wireframe) {
+    geom = geom->make_lines();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(GeomMunger)::premunge_geom_impl
+//       Access: Protected, Virtual
+//  Description: Converts a Geom and/or its data as necessary.
+////////////////////////////////////////////////////////////////////
+void CLP(GeomMunger)::
+premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data) {
+  StandardMunger::premunge_geom_impl(geom, vertex_data);
+
+  // OpenGL ES has no polygon mode, so we have to emulate it.
+  RenderModeAttrib::Mode render_mode = get_render_mode();
+  if (render_mode == RenderModeAttrib::M_point) {
+    geom = geom->make_points();
+  } else if (render_mode == RenderModeAttrib::M_wireframe) {
+    geom = geom->make_lines();
+  }
+}
+#endif  // OPENGLES
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CLP(GeomMunger)::compare_to_impl
 //       Access: Protected, Virtual
@@ -397,6 +436,11 @@ compare_to_impl(const GeomMunger *other) const {
 int CLP(GeomMunger)::
 geom_compare_to_impl(const GeomMunger *other) const {
   const CLP(GeomMunger) *om = DCAST(CLP(GeomMunger), other);
+#ifdef OPENGLES
+  if (get_render_mode() != om->get_render_mode()) {
+    return get_render_mode() < om->get_render_mode() ? -1 : 1;
+  }
+#endif
   if (_texture != om->_texture) {
     return _texture < om->_texture ? -1 : 1;
   }

+ 6 - 0
panda/src/glstuff/glGeomMunger_src.h

@@ -42,6 +42,12 @@ protected:
                                                   const GeomVertexAnimationSpec &animation);
   virtual CPT(GeomVertexFormat) premunge_format_impl(const GeomVertexFormat *orig);
 
+#ifdef OPENGLES
+  virtual void munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &data,
+                               Thread *current_thread);
+  virtual void premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &data);
+#endif
+
   virtual int compare_to_impl(const GeomMunger *other) const;
   virtual int geom_compare_to_impl(const GeomMunger *other) const;
 

+ 13 - 0
panda/src/gobj/geom.I

@@ -242,6 +242,19 @@ make_points() const {
   return new_geom;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Geom::make_lines
+//       Access: Published
+//  Description: Returns a new Geom with lines at all the edges.
+//               See GeomPrimitive::make_lines().
+////////////////////////////////////////////////////////////////////
+INLINE PT(Geom) Geom::
+make_lines() const {
+  PT(Geom) new_geom = make_copy();
+  new_geom->make_lines_in_place();
+  return new_geom;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Geom::make_patches
 //       Access: Published

+ 38 - 0
panda/src/gobj/geom.cxx

@@ -750,6 +750,44 @@ unify_in_place(int max_indices, bool preserve_order) {
   reset_geom_rendering(cdata);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Geom::make_lines_in_place
+//       Access: Published
+//  Description: Replaces the GeomPrimitives within this Geom with
+//               corresponding GeomLines, representing a wireframe
+//               of the primitives.  See GeomPrimitive::make_lines().
+//
+//               Don't call this in a downstream thread unless you
+//               don't mind it blowing away other changes you might
+//               have recently made in an upstream thread.
+////////////////////////////////////////////////////////////////////
+void Geom::
+make_lines_in_place() {
+  Thread *current_thread = Thread::get_current_thread();
+  CDWriter cdata(_cycler, true, current_thread);
+
+#ifndef NDEBUG
+  bool all_is_valid = true;
+#endif
+  Primitives::iterator pi;
+  for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
+    CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_lines();
+    (*pi) = (GeomPrimitive *)new_prim.p();
+
+#ifndef NDEBUG
+    if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
+      all_is_valid = false;
+    }
+#endif
+  }
+
+  cdata->_modified = Geom::get_next_modified();
+  reset_geom_rendering(cdata);
+  clear_cache_stage(current_thread);
+
+  nassertv(all_is_valid);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Geom::make_points_in_place
 //       Access: Published

+ 2 - 0
panda/src/gobj/geom.h

@@ -102,6 +102,7 @@ PUBLISHED:
   INLINE PT(Geom) rotate() const;
   INLINE PT(Geom) unify(int max_indices, bool preserve_order) const;
   INLINE PT(Geom) make_points() const;
+  INLINE PT(Geom) make_lines() const;
   INLINE PT(Geom) make_patches() const;
 
   void decompose_in_place();
@@ -110,6 +111,7 @@ PUBLISHED:
   void rotate_in_place();
   void unify_in_place(int max_indices, bool preserve_order);
   void make_points_in_place();
+  void make_lines_in_place();
   void make_patches_in_place();
 
   virtual bool copy_primitives_from(const Geom *other);

+ 60 - 0
panda/src/gobj/geomPrimitive.cxx

@@ -1044,6 +1044,66 @@ make_points() const {
   return points;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomPrimitive::make_lines
+//       Access: Published
+//  Description: Returns a new GeomLines primitive that represents
+//               each of the edges in the original primitive rendered
+//               as a line.  If the original primitive is already a
+//               GeomLines primitive, returns the original primitive
+//               unchanged.
+////////////////////////////////////////////////////////////////////
+CPT(GeomPrimitive) GeomPrimitive::
+make_lines() const {
+  if (is_exact_type(GeomLines::get_class_type())) {
+    return this;
+  }
+
+  PrimitiveType prim_type = get_primitive_type();
+  if (prim_type == PT_lines) {
+    // It's a line strip, just decompose it.
+    return decompose();
+
+  } else if (prim_type != PT_polygons && prim_type != PT_patches) {
+    // Don't know how to represent this in wireframe.
+    return this;
+  }
+
+  if (prim_type == PT_polygons && !is_exact_type(GeomTriangles::get_class_type())) {
+    // Decompose tristrips.  We could probably make this more efficient
+    // by making a specific implementation of make_lines for GeomTristrips.
+    return decompose()->make_lines();
+  }
+
+  // Iterate through the primitives.
+  int num_primitives = get_num_primitives();
+  int verts_per_prim = get_num_vertices_per_primitive();
+
+  PT(GeomVertexArrayData) new_vertices = make_index_data();
+  new_vertices->unclean_set_num_rows(num_primitives * verts_per_prim * 2);
+
+  GeomVertexWriter new_index(new_vertices, 0);
+
+  for (int i = 0; i < num_primitives; ++i) {
+    int begin = get_primitive_start(i);
+    int end = get_primitive_end(i);
+    if (begin == end) {
+      continue;
+    }
+    for (int vi = begin; vi < end - 1; vi++) {
+      new_index.set_data1i(get_vertex(vi));
+      new_index.set_data1i(get_vertex(vi + 1));
+    }
+    new_index.set_data1i(get_vertex(end - 1));
+    new_index.set_data1i(get_vertex(begin));
+  }
+
+  PT(GeomPrimitive) lines = new GeomLines(UH_dynamic);
+  lines->set_vertices(new_vertices);
+
+  return lines;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitive::make_patches
 //       Access: Published

+ 1 - 0
panda/src/gobj/geomPrimitive.h

@@ -134,6 +134,7 @@ PUBLISHED:
   CPT(GeomPrimitive) reverse() const;
   CPT(GeomPrimitive) match_shade_model(ShadeModel shade_model) const;
   CPT(GeomPrimitive) make_points() const;
+  CPT(GeomPrimitive) make_lines() const;
   CPT(GeomPrimitive) make_patches() const;
 
   int get_num_bytes() const;