changeset 22192:20b225a3ebf8

Update to light (patch #8943) * gl-render.h, gl-render.cc (get_maxlights): New static function. (opengl_renderer::max_lights): New data member. (opengl_renderer::opengl_renderer): Use get_maxlights to initialize max_lights data member. (opengl_renderer::draw_all_lights): New function. Support local light sources. (opengl_renderer::draw_axes_children): Call draw_all_lights instead of doing the work here. (opengl_renderer::draw_surface): Remove warning for "phong". * scripts/plot/draw/light.m: Update docstring. Add and update demos. * doc/interpreter/genpropdoc.m: Update docstring.
author Markus Mützel <markus.muetzel@gmx.de>
date Sat, 23 Jul 2016 17:45:32 +0200
parents 8971508e21c8
children e35866e6a2e0
files doc/interpreter/genpropdoc.m libinterp/corefcn/gl-render.cc libinterp/corefcn/gl-render.h scripts/plot/draw/light.m
diffstat 4 files changed, 142 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/genpropdoc.m	Thu Jul 28 16:38:37 2016 -0400
+++ b/doc/interpreter/genpropdoc.m	Sat Jul 23 17:45:32 2016 +0200
@@ -1305,8 +1305,7 @@
       case "style"
         s.doc = "This string defines whether the light emanates from a \
 light source at infinite distance (@qcode{\"infinite\"}) or from a local \
-point source (@qcode{\"local\"}). Only the default value @qcode{\"infinite\"} \
-is supported.";
+point source (@qcode{\"local\"}).";
 
     endswitch
 
--- a/libinterp/corefcn/gl-render.cc	Thu Jul 28 16:38:37 2016 -0400
+++ b/libinterp/corefcn/gl-render.cc	Sat Jul 23 17:45:32 2016 +0200
@@ -587,6 +587,33 @@
 
 #endif
 
+static int
+get_maxlights (void)
+{
+#if defined (HAVE_OPENGL)
+
+  static int max_lights = 0;
+
+  // Check actual maximum number of lights possible
+  if (max_lights == 0)
+    {
+      for (max_lights = 0; max_lights < GL_MAX_LIGHTS; max_lights++)
+        {
+          glDisable (GL_LIGHT0 + max_lights);
+          if (glGetError ())
+            break;
+        }
+    }
+
+  return max_lights;
+#else
+
+  err_disabled_feature ("opengl_renderer", "OpenGL");
+
+#endif
+
+}
+
 opengl_renderer::opengl_renderer (void)
   : toolkit (), xform (), xmin (), xmax (), ymin (), ymax (),
     zmin (), zmax (), xZ1 (), xZ2 (), marker_id (), filled_marker_id (),
@@ -606,6 +633,9 @@
   if (! ok)
     error ("the size of GLsizei is smaller than the size of int");
 
+  // Check actual maximum number of lights possible
+  max_lights = get_maxlights ();
+
 #else
 
   err_disabled_feature ("opengl_renderer", "OpenGL");
@@ -1618,13 +1648,43 @@
 }
 
 void
+opengl_renderer::draw_all_lights (const base_properties& props, std::list<graphics_object>& obj_list)
+{
+  Matrix children = props.get_all_children ();
+
+  for (octave_idx_type i = children.numel () - 1; i >= 0; i--)
+    {
+      graphics_object go = gh_manager::get_object (children(i));
+
+      if (go.get_properties ().is_visible ())
+        {
+          if (go.isa ("light"))
+            {
+              if (num_lights < max_lights)
+                {
+                  current_light = GL_LIGHT0 + num_lights;
+                  set_clipping (go.get_properties ().is_clipping ());
+                  draw (go);
+                  num_lights++;
+                }
+              else
+                warning_with_id ("Octave:max-lights-exceeded",
+                  "light: Maximum number of lights (%d) in these axes is "
+                  "exceeded.", max_lights);
+            }
+          else if (go.isa ("hggroup"))
+            draw_all_lights (go.get_properties (), obj_list);
+          else
+            obj_list.push_back (go);
+        }
+    }
+}
+
+void
 opengl_renderer::draw_axes_children (const axes::properties& props)
 {
 #if defined (HAVE_OPENGL)
-
-  // Children
-
-  Matrix children = props.get_all_children ();
+  // list for non-light child objects
   std::list<graphics_object> obj_list;
   std::list<graphics_object>::iterator it;
 
@@ -1634,30 +1694,10 @@
   // display them in the order they were added to the array.
 
   num_lights = 0;
-
-  for (octave_idx_type i = children.numel () - 1; i >= 0; i--)
-    {
-      graphics_object go = gh_manager::get_object (children(i));
-
-      if (go.get_properties ().is_visible ())
-        {
-          if (go.isa ("light"))
-            {
-              if (num_lights < GL_MAX_LIGHTS)
-                {
-                  current_light = GL_LIGHT0 + num_lights;
-                  set_clipping (go.get_properties ().is_clipping ());
-                  draw (go);
-                  num_lights++;
-                }
-            }
-          else
-            obj_list.push_back (go);
-        }
-    }
+  draw_all_lights (props, obj_list);
 
   // disable other OpenGL lights
-  for (int i = num_lights; i < GL_MAX_LIGHTS; i++)
+  for (int i = num_lights; i < max_lights; i++)
     glDisable (GL_LIGHT0 + i);
 
   // save camera position and set ambient light color before drawing
@@ -1943,9 +1983,6 @@
   // FIXME: handle transparency
   Matrix a;
 
-  if (props.facelighting_is ("phong") || props.edgelighting_is ("phong"))
-    warning ("opengl_renderer: phong light model not supported");
-
   int fc_mode = (props.facecolor_is_rgb () ? 0 :
                  (props.facecolor_is ("flat") ? 1 :
                   (props.facecolor_is ("interp") ? 2 :
@@ -2296,7 +2333,7 @@
                             cb[k] = c(j-1, i, k);
                           glColor3fv (cb);
 
-                          if (fl_mode > 0)
+                          if (el_mode > 0)
                             {
                               for (int k = 0; k < 3; k++)
                                 cb[k] *= as;
@@ -2323,7 +2360,7 @@
                             cb[k] = c(j, i, k);
                           glColor3fv (cb);
 
-                          if (fl_mode > 0)
+                          if (el_mode > 0)
                             {
                               for (int k = 0; k < 3; k++)
                                 cb[k] *= as;
@@ -2393,7 +2430,7 @@
                             cb[k] = c(j, i-1, k);
                           glColor3fv (cb);
 
-                          if (fl_mode > 0)
+                          if (el_mode > 0)
                             {
                               for (int k = 0; k < 3; k++)
                                 cb[k] *= as;
@@ -2420,7 +2457,7 @@
                             cb[k] = c(j, i, k);
                           glColor3fv (cb);
 
-                          if (fl_mode > 0)
+                          if (el_mode > 0)
                             {
                               for (int k = 0; k < 3; k++)
                                 cb[k] *= as;
@@ -3015,10 +3052,12 @@
   glEnable (current_light);
 
   // light position
-  float pos[4] = { 0, 0, 0, 0 }; // X,Y,Z,attenuation
+  float pos[4] = { 0, 0, 0, 0 }; // X,Y,Z,infinite/local
   Matrix lpos = props.get_position ().matrix_value ();
   for (int i = 0; i < 3; i++)
     pos[i] = lpos(i);
+  if (props.style_is ("local"))
+    pos[3] = 1;
   glLightfv (current_light, GL_POSITION, pos);
 
   // light color
--- a/libinterp/corefcn/gl-render.h	Thu Jul 28 16:38:37 2016 -0400
+++ b/libinterp/corefcn/gl-render.h	Sat Jul 23 17:45:32 2016 +0200
@@ -169,6 +169,8 @@
 
   void draw_axes_children (const axes::properties& props);
 
+  void draw_all_lights (const base_properties& props, std::list<graphics_object>& obj_list);
+
 private:
   // The graphics toolkit associated with the figure being rendered.
   graphics_toolkit toolkit;
@@ -198,6 +200,7 @@
   // light object present and visible
   int num_lights;
   unsigned int current_light;
+  int max_lights;
 
 private:
   class patch_tesselator;
--- a/scripts/plot/draw/light.m	Thu Jul 28 16:38:37 2016 -0400
+++ b/scripts/plot/draw/light.m	Sat Jul 23 17:45:32 2016 +0200
@@ -51,8 +51,7 @@
 ##
 ## @item @qcode{"Style":} This string defines whether the light emanates from a
 ## light source at infinite distance (@qcode{"infinite"}) or from a local point
-## source (@qcode{"local"}).  Only the default value @qcode{"infinite"} is
-## supported.
+## source (@qcode{"local"}).
 ## @end table
 ##
 ## If @command{light} is called with an axes handle @var{hax}, it must be passed
@@ -177,7 +176,7 @@
 %! %% Diffuse and specular reflex
 %! clf;
 %! h_axes = axes ();
-%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2);
+%! [x,y,z] = meshgrid (-.2:0.04:.2, -.2:0.04:.2, -.2:0.04:.2);
 %! val = (x.^2 + y.^2 + z.^2);
 %!
 %! fv = isosurface (x, y, z, val, .039);
@@ -297,7 +296,7 @@
 %!demo
 %! %% Specular Exponent
 %! clf;
-%! [x,y,z] = meshgrid (-.2:0.01:.2, -.2:0.01:.2, -.2:0.01:.2);
+%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2);
 %! val = (x.^2 + y.^2 + z.^2);
 %!
 %! h_axes = axes ();
@@ -380,7 +379,7 @@
 %!demo
 %! %% Colored patch
 %! clf;
-%! [x,y,z] = meshgrid (-.2:0.01:.2, -.2:0.01:.2, -.2:0.01:.2);
+%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2);
 %! val = (x.^2 + y.^2 + z.^2);
 %!
 %! h_axes = axes ();
@@ -389,11 +388,72 @@
 %!             "FaceLighting", "Gouraud");
 %! set (h_patch, "SpecularExponent", 15);
 %! isonormals (x, y, z, val, h_patch);
+%! title ('Colored patch');
 %! h_light = light ("Position", [-1 1 1]);
 %! axis tight
 %! axis equal
 %! view (3);
 
+%!demo
+%! %% Colored mesh (patch)
+%! clf;
+%! [x,y,z] = meshgrid (-.2:0.05:.2, -.2:0.05:.2, -.2:0.05:.2);
+%! val = (x.^2 + y.^2 + z.^2);
+%!
+%! h_axes = axes ();
+%! fv = isosurface (x, y, z, val, .039, z);
+%! h_patch = patch (fv, 'FaceColor', 'w', 'EdgeColor', 'interp');
+%! isonormals (x, y, z, val, h_patch);
+%! title ('Colored mesh (patch)');
+%! h_light = light;
+%! lighting gouraud
+%! axis tight
+%! axis equal
+%! view (3);
+
+%!demo
+%! %% Colored mesh (surface)
+%! clf;
+%! h_mesh = mesh (peaks);
+%! title ('Colored mesh (surface)');
+%! h_light = light;
+%! lighting gouraud
+
+%!demo
+%! %% Light in hggroup
+%! clf;
+%! h_mesh = mesh (peaks);
+%! h_hg = hggroup ();
+%! title ('Light in hggroup');
+%! h_light = light ('Parent', h_hg);
+%! lighting gouraud
+
+%!demo
+%! %% Style local/infinite
+%! clf;
+%! [x,y,z] = meshgrid (-.2:0.02:.2, -.2:0.02:.2, -.2:0.02:.2);
+%! val = (x.^2 + y.^2 + z.^2);
+%!
+%! h_axes1 = subplot (1,2,1);
+%! fv = isosurface (x, y, z, val, .039);
+%! h_patch = patch (fv, 'FaceColor', 'r', 'EdgeColor', 'none');
+%! isonormals (x, y, z, val, h_patch);
+%! title ('"Style" set to "infinite" (default)');
+%! h_light = light ('Position', [.3 0 .3]);
+%! lighting gouraud
+%! axis equal
+%! view (3);
+%!
+%! h_axes2 = subplot (1,2,2);
+%! fv = isosurface (x, y, z, val, .039);
+%! h_patch = patch (fv, 'FaceColor', 'r', 'EdgeColor', 'none');
+%! isonormals (x, y, z, val, h_patch);
+%! title ('"Style" set to "local"');
+%! h_light = light ('Style', 'local', 'Position', [.3 0 .3]);
+%! lighting gouraud
+%! axis equal
+%! view (3);
+
 
 %!test
 %! hf = figure ("Visible", "off");