# HG changeset patch
# User Markus Mützel <markus.muetzel@gmx.de>
# Date 1489338521 -3600
#      Sun Mar 12 18:08:41 2017 +0100
# Node ID 3fa4f25037d777221ab0acc1ff703dd489106189
# Parent  046593530e950a2caa115cccc10a9f45de23c40d
Add basic support of "facealpha" for surfaces and patches in OpenGL (bug #39535)

* gl-render.cc (draw_surface, draw_patch): Pass alpha value of faces to OpenGL.
* doc/interpreter/genpropdoc.m: Add documentation for surface and patch facealpha.
* scripts/plot/draw/surface.m: Add cross-reference to Surface Properties.
* scripts/plot/draw/patch.m: Add cross-reference to Patch Properties.

diff -r 046593530e95 -r 3fa4f25037d7 doc/interpreter/genpropdoc.m
--- a/doc/interpreter/genpropdoc.m	Mon Oct 09 18:59:20 2017 +0200
+++ b/doc/interpreter/genpropdoc.m	Sun Mar 12 18:08:41 2017 +0100
@@ -1169,8 +1169,17 @@
 @qcode{\"gouraud\"}.";
 
       case "facealpha"
-        s.doc = sprintf (doc_notimpl, "Transparency");
-        s.valid = valid_scalmat;
+        s.doc = "Transparency level of the faces of the surface object.  Only \
+double values are supported at present where a value of 0 means complete \
+transparency and a value of 1 means solid faces without transparency.  Setting \
+the property to @qcode{\"flat\"}, @qcode{\"interp\"} or @qcode{\"texturemap\"} \
+causes the faces to not being rendered.  Additionally, the faces are not sorted \
+from back to front which might lead to unexpected results when rendering \
+layered transparent faces.";
+        s.valid = packopt ({"scalar", ...
+                            "@qcode{\"flat\"}", ...
+                            "@qcode{\"interp\"}", ...
+                            "@qcode{\"texturemap\"}"});
 
       case "facecolor"
       case "facelighting"
@@ -1292,8 +1301,16 @@
 @qcode{\"gouraud\"}.";
 
       case "facealpha"
-        s.doc = sprintf (doc_notimpl, "Transparency");
-        s.valid = valid_scalmat;
+        s.doc = "Transparency level of the faces of the patch object.  Only \
+double values are supported at present where a value of 0 means complete \
+transparency and a value of 1 means solid faces without transparency.  Setting \
+the property to @qcode{\"flat\"} or @qcode{\"interp\"} causes the faces to not \
+being rendered.  Additionally, the faces are not sorted from back to front \
+which might lead to unexpected results when rendering layered transparent \
+faces.";
+        s.valid = packopt ({"scalar", ...
+                            "@qcode{\"flat\"}", ...
+                            "@qcode{\"interp\"}"});
 
       case "facecolor"
         ## Don't provide a default value, and mark colorspec with
diff -r 046593530e95 -r 3fa4f25037d7 libinterp/corefcn/gl-render.cc
--- a/libinterp/corefcn/gl-render.cc	Mon Oct 09 18:59:20 2017 +0200
+++ b/libinterp/corefcn/gl-render.cc	Sun Mar 12 18:08:41 2017 +0100
@@ -488,7 +488,7 @@
 
           if (col.numel () == 3)
             {
-              glColor3dv (col.data ());
+              glColor4d (col(0), col(1), col(2), v->alpha);
               if (light_mode > 0)
                 {
                   float buf[4] = { 0, 0, 0, 1 };
@@ -2323,6 +2323,7 @@
     Matrix fcolor = (fc_mode == TEXTURE ? Matrix (1, 3, 1.0)
                                         : props.get_facecolor_rgb ());
     Matrix ecolor = props.get_edgecolor_rgb ();
+    double fa = 1.0;
 
     float as = props.get_ambientstrength ();
     float ds = props.get_diffusestrength ();
@@ -2374,11 +2375,12 @@
 
     if (! props.facecolor_is ("none"))
       {
-        if (props.get_facealpha_double () == 1)
+        if (fa_mode == 0)
           {
+            fa = props.get_facealpha_double ();
             if (fc_mode == UNIFORM || fc_mode == TEXTURE)
               {
-                glColor3dv (fcolor.data ());
+                glColor4d (fcolor(1), fcolor(2), fcolor(3), fa);
                 if (fl_mode > 0)
                   {
                     for (int i = 0; i < 3; i++)
@@ -2449,7 +2451,8 @@
                         // FIXME: is there a smarter way to do this?
                         for (int k = 0; k < 3; k++)
                           cb[k] = c(j-1, i-1, k);
-                        glColor3fv (cb);
+                        cb[3] = fa;
+                        glColor4fv (cb);
 
                         if (fl_mode > 0)
                           {
@@ -2478,7 +2481,8 @@
                       {
                         for (int k = 0; k < 3; k++)
                           cb[k] = c(j-1, i, k);
-                        glColor3fv (cb);
+                        cb[3] = fa;
+                        glColor4fv (cb);
 
                         if (fl_mode > 0)
                           {
@@ -2508,7 +2512,8 @@
                       {
                         for (int k = 0; k < 3; k++)
                           cb[k] = c(j, i, k);
-                        glColor3fv (cb);
+                        cb[3] = fa;
+                        glColor4fv (cb);
 
                         if (fl_mode > 0)
                           {
@@ -2537,7 +2542,8 @@
                       {
                         for (int k = 0; k < 3; k++)
                           cb[k] = c(j, i-1, k);
-                        glColor3fv (cb);
+                        cb[3] = fa;
+                        glColor4fv (cb);
 
                         if (fl_mode > 0)
                           {
@@ -2572,7 +2578,7 @@
           }
         else
           {
-            // FIXME: implement transparency
+            // FIXME: implement flat, interp and texturemap transparency
           }
       }
 
@@ -2916,6 +2922,7 @@
     Matrix c;
     const Matrix n = props.get_vertexnormals ().matrix_value ();
     Matrix a;
+    double fa = 1.0;
 
     int nv = v.rows ();
     int nf = f.rows ();
@@ -3010,6 +3017,9 @@
         has_facealpha = ((a.numel () > 0) && (a.rows () == f.rows ()));
       }
 
+    if (fa_mode == 0)
+      fa = props.get_facealpha_double ();
+
     octave_idx_type fr = f.rows ();
     std::vector<vertex_data> vdata (f.numel ());
 
@@ -3046,7 +3056,9 @@
               else
                 cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2);
             }
-          if (a.numel () > 0)
+          if (fa_mode == 0)
+            aa = fa;
+          else if (a.numel () > 0)
             {
               if (has_facealpha)
                 aa = a(i);
@@ -3063,11 +3075,11 @@
     if (! props.facecolor_is ("none"))
       {
         // FIXME: adapt to double-radio property
-        if (props.get_facealpha_double () == 1)
+        if (fa_mode == 0)
           {
             if (fc_mode == UNIFORM)
               {
-                glColor3dv (fcolor.data ());
+                glColor4d (fcolor(0), fcolor(1), fcolor(2), fa);
                 if (fl_mode > 0)
                   {
                     float cb[4] = { 0, 0, 0, 1 };
@@ -3122,7 +3134,7 @@
 
                         if (col.numel () == 3)
                           {
-                            glColor3dv (col.data ());
+                            glColor4d (col(0), col(1), col(2), fa);
                             if (fl_mode > 0)
                               {
                                 float cb[4] = { 0, 0, 0, 1 };
@@ -3155,7 +3167,7 @@
           }
         else
           {
-            // FIXME: implement transparency
+            // FIXME: implement flat and interp transparency
           }
       }
 
diff -r 046593530e95 -r 3fa4f25037d7 scripts/plot/draw/patch.m
--- a/scripts/plot/draw/patch.m	Mon Oct 09 18:59:20 2017 +0200
+++ b/scripts/plot/draw/patch.m	Sun Mar 12 18:08:41 2017 +0100
@@ -65,9 +65,10 @@
 ## object.
 ##
 ## Implementation Note: Patches are highly configurable objects.  To truly
-## customize them requires setting patch properties directly.  Useful patch
-## properties are: @qcode{"cdata"}, @qcode{"edgecolor"},
-## @qcode{"facecolor"}, @qcode{"faces"}, @qcode{"facevertexcdata"}.
+## customize them requires setting patch properties directly 
+## (@pxref{Patch Properties}).  Useful patch properties include: @qcode{"cdata"},
+## @qcode{"edgecolor"}, @qcode{"facecolor"}, @qcode{"faces"},
+## @qcode{"facevertexcdata"}.
 ## @seealso{fill, get, set}
 ## @end deftypefn
 
diff -r 046593530e95 -r 3fa4f25037d7 scripts/plot/draw/surface.m
--- a/scripts/plot/draw/surface.m	Mon Oct 09 18:59:20 2017 +0200
+++ b/scripts/plot/draw/surface.m	Sun Mar 12 18:08:41 2017 +0100
@@ -35,7 +35,8 @@
 ## taken to be @code{1:rows (@var{z})} and @var{y} is
 ## @code{1:columns (@var{z})}.
 ##
-## Any property/value input pairs are assigned to the surface object.
+## Any property/value input pairs are assigned to the surface object
+## (@pxref{Surface Properties}).
 ##
 ## If the first argument @var{hax} is an axes handle, then plot into this axis,
 ## rather than the current axes returned by @code{gca}.
