changeset 18802:75f8926deef1

Fix Z-order stacking of patches and axes grid lines (bug #40722). * gl-render.h (set_polygon_offset): Change function prototype for offset argument to float. * gl-render.cc (set_polygon_offset): Change offset argument to type float. Now matches OpenGL prototype for glPolygonOffset. * gl-render.cc (patch_tesselator::patch_tesselator): Change constructor variable idx to a float, from int. * gl-render.cc (patch_tesselator::begin): Pass index directly to set_polygon_offset. * gl-render.cc (opengl_renderer::draw_patch): Call patch_tesselator with index of 1.0 for filled portion of patch to push it down below outline of patch. * patch.m: For 2-D patches, set zlim to [-1,1] so that axes 'layer' property works.
author Rik <rik@octave.org>
date Sat, 17 May 2014 12:56:11 -0700
parents 10082673a8f0
children ff39ddf84a19
files libinterp/corefcn/gl-render.cc libinterp/corefcn/gl-render.h scripts/plot/draw/patch.m
diffstat 3 files changed, 26 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/gl-render.cc	Fri May 16 08:20:11 2014 -0700
+++ b/libinterp/corefcn/gl-render.cc	Sat May 17 12:56:11 2014 -0700
@@ -401,7 +401,7 @@
 opengl_renderer::patch_tesselator : public opengl_tesselator
 {
 public:
-  patch_tesselator (opengl_renderer *r, int cmode, int lmode, int idx = 0)
+  patch_tesselator (opengl_renderer *r, int cmode, int lmode, float idx = 0.0)
     : opengl_tesselator (), renderer (r),
       color_mode (cmode), light_mode (lmode), index (idx),
       first (true), tmp_vdata ()
@@ -419,7 +419,7 @@
       glShadeModel (GL_FLAT);
 
     if (is_filled ())
-      renderer->set_polygon_offset (true, 1+index);
+      renderer->set_polygon_offset (true, index);
 
     glBegin (type);
   }
@@ -437,9 +437,8 @@
       = reinterpret_cast<vertex_data::vertex_data_rep *> (data);
     //printf ("patch_tesselator::vertex (%g, %g, %g)\n", v->coords(0), v->coords(1), v->coords(2));
 
-    // NOTE: OpenGL can re-order vertices so "first" is basically meaningless
-    // in this callback routine.  For "flat" coloring of FaceColor the first
-    // vertex must be identified in the draw_patch routine.
+    // NOTE: OpenGL can re-order vertices.  For "flat" coloring of FaceColor
+    // the first vertex must be identified in the draw_patch routine.
 
     if (color_mode == 2 || (color_mode == 1 && ! is_filled ()))
       {
@@ -2338,11 +2337,11 @@
           if (fl_mode > 0)
             glEnable (GL_LIGHTING);
 
-          // FIXME: use __index__ property from patch object
-          // -1.25 chosen to provide sufficient Z-offset for
-          // 'layer' property of 2-D plots and not to provoke
-          // Z-fighting with tesselator outline.
-          patch_tesselator tess (this, fc_mode, fl_mode, -1.25);
+          // NOTE: Push filled part of patch backwards to avoid Z-fighting with
+          // tesselator outline.  A value of 1.0 seems to work fine.  Value
+          // can't be too large or the patch will be pushed below the axes
+          // planes at +2.5.
+          patch_tesselator tess (this, fc_mode, fl_mode, 1.0);
 
           for (int i = 0; i < nf; i++)
             {
@@ -2431,9 +2430,11 @@
           set_linestyle (props.get_linestyle (), false);
           set_linewidth (props.get_linewidth ());
 
-
-          // FIXME: use __index__ property from patch object;
-          //        should we offset patch contour as well?
+          // NOTE: patch contour cannot be offset.  Offset must occur with the
+          // filled portion of the patch above.  The tesselator uses
+          // GLU_TESS_BOUNDARY_ONLY to get the outline of the patch and OpenGL
+          // automatically sets the glType to GL_LINE_LOOP.  This primitive is
+          // not supported by glPolygonOffset which is used to do Z offsets. 
           patch_tesselator tess (this, ec_mode, el_mode);
 
           for (int i = 0; i < nf; i++)
@@ -2819,13 +2820,13 @@
 }
 
 void
-opengl_renderer::set_polygon_offset (bool on, double offset)
+opengl_renderer::set_polygon_offset (bool on, float offset)
 {
   if (on)
     {
-      glPolygonOffset (offset, offset);
       glEnable (GL_POLYGON_OFFSET_FILL);
       glEnable (GL_POLYGON_OFFSET_LINE);
+      glPolygonOffset (offset, offset);
     }
   else
     {
--- a/libinterp/corefcn/gl-render.h	Fri May 16 08:20:11 2014 -0700
+++ b/libinterp/corefcn/gl-render.h	Sat May 17 12:56:11 2014 -0700
@@ -93,7 +93,7 @@
   virtual void setup_opengl_transformation (const axes::properties& props);
 
   virtual void set_color (const Matrix& c);
-  virtual void set_polygon_offset (bool on, double offset = 0.0);
+  virtual void set_polygon_offset (bool on, float offset = 0.0);
   virtual void set_linewidth (float w);
   virtual void set_linestyle (const std::string& s, bool stipple = false);
   virtual void set_clipbox (double x1, double x2, double y1, double y2,
--- a/scripts/plot/draw/patch.m	Fri May 16 08:20:11 2014 -0700
+++ b/scripts/plot/draw/patch.m	Sat May 17 12:56:11 2014 -0700
@@ -88,6 +88,15 @@
     print_usage ();
   endif
 
+  ## FIXME: This is a hack to get 'layer' command to work for 2D patches
+  ##        Alternative is much more complicated surgery in graphics.cc.
+  ##        of get_children_limits() for 'z' axis and 'patch' object type.
+  if (! ishold ())
+    if (isempty (get (htmp, "zdata")))
+      set (hax, "zlim", [-1 1]);
+    endif
+  endif
+
   if (nargout > 0)
     h = htmp;
   endif