Mercurial > octave
changeset 22247:c8fc60a183a3
Add function material. (patch #9013)
* scripts/plot/appearance/material.m: New function.
* scripts/plot/appearance/module.mk: Update build system.
* NEWS: Announce new function.
* __unimplemented__.m: Remove "material" from list.
* doc/interpreter/plot.txi: Add doc string.
* light.m: Add "material" to "see also".
author | Markus Muetzel <markus.muetzel@gmx.de> |
---|---|
date | Mon, 18 Jul 2016 17:46:05 +0200 |
parents | fa917f1f0faf |
children | 60986498af9e |
files | NEWS doc/interpreter/plot.txi scripts/help/__unimplemented__.m scripts/plot/appearance/material.m scripts/plot/appearance/module.mk scripts/plot/draw/light.m |
diffstat | 6 files changed, 317 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Wed Aug 10 00:56:51 2016 +0100 +++ b/NEWS Mon Jul 18 17:46:05 2016 +0200 @@ -117,6 +117,7 @@ hash im2double localfunctions + material normest1 ode45 odeget
--- a/doc/interpreter/plot.txi Wed Aug 10 00:56:51 2016 +0100 +++ b/doc/interpreter/plot.txi Mon Jul 18 17:46:05 2016 +0200 @@ -398,6 +398,8 @@ @DOCSTRING(lighting) +@DOCSTRING(material) + @DOCSTRING(meshgrid) @DOCSTRING(ndgrid)
--- a/scripts/help/__unimplemented__.m Wed Aug 10 00:56:51 2016 +0100 +++ b/scripts/help/__unimplemented__.m Mon Jul 18 17:46:05 2016 +0200 @@ -713,7 +713,6 @@ "lsqr", "makehgtform", "mapreduce", - "material", "matfile", "matlabrc", "memmapfile",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/plot/appearance/material.m Mon Jul 18 17:46:05 2016 +0200 @@ -0,0 +1,312 @@ +## Copyright (C) 2016 Markus Muetzel +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {} {} material shiny +## @deftypefnx {} {} material dull +## @deftypefnx {} {} material metal +## @deftypefnx {} {} material default +## @deftypefnx {} {} material ([@var{as}, @var{ds}, @var{ss}]) +## @deftypefnx {} {} material ([@var{as}, @var{ds}, @var{ss}, @var{se}]) +## @deftypefnx {} {} material ([@var{as}, @var{ds}, @var{ss}, @var{se}, @var{scr}]) +## @deftypefnx {} {} material (@var{hlist}, @dots{}) +## @deftypefnx {} {@var{mtypes} =} material () +## @deftypefnx {} {@var{refl_props} =} material (@var{mtype_string}) +## Set reflectance properties for the lighting of surfaces and patches. +## +## This function changes the ambient, diffuse, and specular strengths, as well +## as the specular exponent and specular color reflectance, of all +## @code{patch} and @code{surface} objects in the current axes. This can be +## used to simulate, to some extent, the reflectance properties of certain +## materials when used with @code{light}. +## +## When called with a string, the aforementioned properties are set +## according to the values in the following table: +## +## @multitable @columnfractions .0 .2 .15 .15 .15 .15 .15 .0 +## @headitem @tab @var{mtype} @tab ambient- strength @tab diffuse- +## strength @tab specular- strength @tab specular- exponent @tab specular- +## color- reflectance @tab +## @item @tab @qcode{"shiny"} @tab 0.3 @tab 0.6 @tab 0.9 @tab 20 @tab 1.0 @tab +## @item @tab @qcode{"dull"} @tab 0.3 @tab 0.8 @tab 0.0 @tab 10 @tab 1.0 @tab +## @item @tab @qcode{"metal"} @tab 0.3 @tab 0.3 @tab 1.0 @tab 25 @tab 0.5 @tab +## @item @tab @qcode{"default"} @tab @qcode{"default"} @tab @qcode{"default"} @tab @qcode{"default"} @tab +## @qcode{"default"} @tab @qcode{"default"} @tab +## @end multitable +## +## When called with a vector of three elements, the ambient, diffuse, and +## specular strengths of all @code{patch} and @code{surface} objects in the +## current axes are updated. An optional fourth vector element updates the +## specular exponent, and an optional fifth vector element updates the +## specular color reflectance. +## +## A list of graphic handles can also be passed as the first argument. In +## this case, the properties of these handles and all child @code{patch} and +## @code{surface} objects will be updated. +## +## Additionally, @code{material} can be called with a single output argument. +## If called without input arguments, a column cell vector @var{mtypes} with +## the strings for all available materials is returned. If the one input +## argument @var{mtype_string} is the name of a material, a 1x5 cell vector +## @var{refl_props} with the reflectance properties of that material is +## returned. In both cases, no graphic properties are changed. +## +## @seealso{light, fill, mesh, patch, pcolor, surf, surface} +## @end deftypefn + +## Author: mmuetzel + +function retval = material (varargin) + + if (! ((nargout == 0 && (nargin == 1 || nargin == 2)) || + (nargout == 1 && (nargin == 0 || nargin == 1))) ) + print_usage (); + endif + + ## resolve input + if (nargout == 0) + ## Check whether first argument is list of graphics handles. + if (all (ishandle (varargin{1}))) + h = varargin{1}; + varargin(1) = []; + else + h = gca (); + endif + + ## There must be one (additional) argument. + if (numel (varargin) != 1) + if (nargin == 2) + error (["material: When called with two arguments, the first argument " ... + "must be a list of handles to graphics objects."]); + else + print_usage (); + endif + endif + elseif (nargin == 0) + ## Return name of materials. + retval = {"shiny"; "dull"; "metal"; "default"}; + return; + endif + + mtype = varargin{1}; + + se = []; + scr = []; + + ## check material type + if (ischar (mtype)) + switch (lower (mtype)) + case "shiny" + as = 0.3; + ds = 0.6; + ss = 0.9; + se = 20; + scr = 1.0; + + case "dull" + as = 0.3; + ds = 0.8; + ss = 0.0; + se = 10; + scr = 1.0; + + case "metal" + as = 0.3; + ds = 0.3; + ss = 1.0; + se = 25; + scr = .5; + + case "default" + as = "default"; + ds = "default"; + ss = "default"; + se = "default"; + scr = "default"; + + otherwise + error ("material: unknown material type '%s'", mtype); + + endswitch + + if (nargout == 1) + ## Return 1x5 cell vector with reflectance properties. + retval = {as, ds, ss, se, scr}; + return; + endif + + elseif (nargout == 1) + ## If we reach here with one output argument, the input was wrong. + print_usage (); + + elseif (isvector (mtype)) + num_mtype = numel (mtype); + if (num_mtype < 2 || num_mtype > 5) + error ("material: incorrect number of elements in material vector"); + endif + as = mtype(1); + ds = mtype(2); + ss = mtype(3); + if (num_mtype >= 4) + se = mtype(4); + if (num_mtype == 5) + scr = mtype(5); + endif + endif + + else + error ("material: MTYPE must be a named material or a vector"); + endif + + ## find all patch and surface objects in current axes + hps = findobj (h, "Type", "patch", "-or", "Type", "surface"); + + ## set properties + set (hps, + "ambientstrength", as, "diffusestrength", ds, "specularstrength", ss); + + if (! isempty (se)) + set (hps, "specularexponent", se); + if (! isempty (scr)) + set (hps, "specularcolorreflectance", scr); + endif + endif + +endfunction + + +%!demo +%! clf; +%! %% patch +%! h_axes = axes; +%! [x,y,z] = meshgrid (-2:0.2:2, -2:0.2:2, -2:0.2:2); +%! val = x.^2 + y.^2 + z.^2; +%! fv1 = isosurface (x, y, z, val, 1); +%! h_patch = patch (fv1, "FaceColor", "r", "EdgeColor", "none", "FaceLighting", "Gouraud"); +%! isonormals (x, y, z, val, h_patch) +%! axis equal; axis tight +%! view (3) +%! drawnow +%! h_light = light (); +%! material ([0 0.5 1 10 .5]) + +%!demo +%! clf +%! %% surface +%! h_axes = axes; +%! h_surf = surf (h_axes, peaks, "LineStyle", "none", "FaceLighting", "Gouraud"); +%! view (3) +%! h_light = light (); +%! material metal + +%!test +%! hf = figure ("Visible", "off"); +%! unwind_protect +%! hp = patch; +%! hs = surface; +%! material dull +%! assert (get (hp, "ambientstrength"), 0.3); +%! assert (get (hs, "ambientstrength"), 0.3); +%! assert (get (hp, "diffusestrength"), 0.8); +%! assert (get (hs, "diffusestrength"), 0.8); +%! assert (get (hp, "specularstrength"), 0.0); +%! assert (get (hs, "specularstrength"), 0.0); +%! assert (get (hp, "specularexponent"), 10); +%! assert (get (hs, "specularexponent"), 10); +%! assert (get (hp, "specularcolorreflectance"), 1.0); +%! assert (get (hs, "specularcolorreflectance"), 1.0); +%! material default +%! assert (get (hp, "ambientstrength"), get (0, "defaultpatchambientstrength")); +%! assert (get (hs, "ambientstrength"), get (0, "defaultsurfaceambientstrength")); +%! assert (get (hp, "diffusestrength"), get (0, "defaultpatchdiffusestrength")); +%! assert (get (hs, "diffusestrength"), get (0, "defaultsurfacediffusestrength")); +%! assert (get (hp, "specularstrength"), get (0, "defaultpatchspecularstrength")); +%! assert (get (hs, "specularstrength"), get (0, "defaultsurfacespecularstrength")); +%! assert (get (hp, "specularexponent"), get (0, "defaultpatchspecularexponent")); +%! assert (get (hs, "specularexponent"), get (0, "defaultsurfacespecularexponent")); +%! assert (get (hp, "specularcolorreflectance"), get (0, "defaultpatchspecularcolorreflectance")); +%! assert (get (hs, "specularcolorreflectance"), get (0, "defaultsurfacespecularcolorreflectance")); +%! material ([0.5 0.6 0.7 20 0.8]) +%! assert (get (hp, "ambientstrength"), 0.5); +%! assert (get (hs, "ambientstrength"), 0.5); +%! assert (get (hp, "diffusestrength"), 0.6); +%! assert (get (hs, "diffusestrength"), 0.6); +%! assert (get (hp, "specularstrength"), 0.7); +%! assert (get (hs, "specularstrength"), 0.7); +%! assert (get (hp, "specularexponent"), 20); +%! assert (get (hs, "specularexponent"), 20); +%! assert (get (hp, "specularcolorreflectance"), 0.8); +%! assert (get (hs, "specularcolorreflectance"), 0.8); +%! material (hp, "shiny") +%! assert (get (hp, "ambientstrength"), 0.3); +%! assert (get (hs, "ambientstrength"), 0.5); +%! assert (get (hp, "diffusestrength"), 0.6); +%! assert (get (hs, "diffusestrength"), 0.6); +%! assert (get (hp, "specularstrength"), 0.9); +%! assert (get (hs, "specularstrength"), 0.7); +%! assert (get (hp, "specularexponent"), 20); +%! assert (get (hs, "specularexponent"), 20); +%! assert (get (hp, "specularcolorreflectance"), 1.0); +%! assert (get (hs, "specularcolorreflectance"), 0.8); +%! material (hf, "metal") +%! assert (get (hp, "ambientstrength"), 0.3); +%! assert (get (hs, "ambientstrength"), 0.3); +%! assert (get (hp, "diffusestrength"), 0.3); +%! assert (get (hs, "diffusestrength"), 0.3); +%! assert (get (hp, "specularstrength"), 1.0); +%! assert (get (hs, "specularstrength"), 1.0); +%! assert (get (hp, "specularexponent"), 25); +%! assert (get (hs, "specularexponent"), 25); +%! assert (get (hp, "specularcolorreflectance"), 0.5); +%! assert (get (hs, "specularcolorreflectance"), 0.5); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test +%! mtypes = material (); +%! assert (iscell (mtypes)); +%! assert (size (mtypes, 2), 1); +%! assert (all (cellfun (@ischar, mtypes))); + +%!test +%! refl_props = material ("metal"); +%! assert (refl_props, {0.3, 0.3, 1, 25, 0.5}) + +## Test input validation +%!error <Invalid call to material> material () +%!error <Invalid call to material> material (-1, 2, 3) +%!error <Invalid call to material> a = material (-1) +%!error <Invalid call to material> a = material (-1, 2) +%!error <Invalid call to material> a = material ({}) +%!error <Invalid call to material> a = material ([.3 .4 .5]) +%!error <Invalid call to material> [a, b] = material () +%!error <first argument must be a list of handles> material (-1, "metal") +%!error <unknown material type 'foo'> material foo +%!error <incorrect number of elements in material vector> material (-1) +%!error <incorrect number of elements in material vector> material ([1 2 3 4 5 6]) +%!error <MTYPE must be a named material or a vector> material ({}) + +%!error <Invalid call to material.> +%! hf = figure ("visible", "off"); +%! unwind_protect +%! material (hf); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect +
--- a/scripts/plot/appearance/module.mk Wed Aug 10 00:56:51 2016 +0100 +++ b/scripts/plot/appearance/module.mk Mon Jul 18 17:46:05 2016 +0200 @@ -22,6 +22,7 @@ scripts/plot/appearance/hidden.m \ scripts/plot/appearance/legend.m \ scripts/plot/appearance/lighting.m \ + scripts/plot/appearance/material.m \ scripts/plot/appearance/orient.m \ scripts/plot/appearance/pbaspect.m \ scripts/plot/appearance/shading.m \
--- a/scripts/plot/draw/light.m Wed Aug 10 00:56:51 2016 +0100 +++ b/scripts/plot/draw/light.m Mon Jul 18 17:46:05 2016 +0200 @@ -59,7 +59,7 @@ ## ## Optionally, the handle to the light object is returned in @var{h}. ## -## @seealso{get, set, patch, surface, lighting} +## @seealso{get, set, patch, surface, lighting, material} ## @end deftypefn ## Author: mmuetzel