Path: news.mathworks.com!not-for-mail
From: <HIDDEN>
Newsgroups: comp.soft-sys.matlab
Subject: Re: problem with surface lighting (OpenGL)
Date: Mon, 20 Apr 2009 19:20:02 +0000 (UTC)
Organization: Pierburg GmbH
Lines: 64
Message-ID: <gsiht2$30j$1@fred.mathworks.com>
References: <gs77e9$fbj$1@fred.mathworks.com> <gsf17e$8cs$1@fred.mathworks.com>
Reply-To: <HIDDEN>
NNTP-Posting-Host: webapp-02-blr.mathworks.com
Content-Type: text/plain; charset="ISO-8859-1"
Content-Transfer-Encoding: 8bit
X-Trace: fred.mathworks.com 1240255202 3091 172.30.248.37 (20 Apr 2009 19:20:02 GMT)
X-Complaints-To: news@mathworks.com
NNTP-Posting-Date: Mon, 20 Apr 2009 19:20:02 +0000 (UTC)
X-Newsreader: MATLAB Central Newsreader 872224
Xref: news.mathworks.com comp.soft-sys.matlab:534155


Thank you, Chaos, for your support, but I had no success with your figure settings and direct printing.
And thanks to Mike for your bug confirmation. Your post gave me the idea to compute the face normals by myself and simply use them with the 'VertexNormals' parameter in surf.
I've written a small function, 'facenorm':

% ---
function N = facenorm(X,Y,Z)

% FACENORM compute alternate surface normals to be used with surface plots
%
% ...

% input checking left to surf et.al. ...

coord = cat(3,X,Y,Z);

% edge vectors of a face
d11 = diff(coord(:,1:end-1,:),1,1);
d12 = diff(coord(1:end-1,:,:),1,2);

% opposite edge vectors
d21 = diff(coord(end:-1:1,end:-1:2,:),1,1);
d22 = diff(coord(end:-1:2,end:-1:1,:),1,2);

% normals of the opposing edges
n1 = cross(d12,d11,3);
n2 = cross(d22,d21,3);

% add the normals to get an average normal of the face
n = n1 + n2(end:-1:1,end:-1:1,:);

% prepare for surf and normalize
N = NaN(size(n)+[1 1 0]);
N(2:end,2:end,:) = n;
mag = sqrt(sum(N.^2,3));
mag(mag==0)=eps;
N = N./repmat(mag,[1 1 3]);

% ---

See what it does:

  % generate some demo data
  [Y,Z,X] = cylinder([0.8 1 1 0.8],144);
  idxShift = mod(1:size(X,2),4)>1;
  X(2,idxShift) = X(2,idxShift)-0.2;
  X(3,idxShift) = X(3,idxShift)+0.2;
 
  % standard surf plot
  figure(1)
  surf(X,Y,Z,'EdgeAlpha',0.2,'FaceColor','c')
  axis equal
  light('Position',[0 0 1],'Style','infinite')
  view(0,60)
  
  % same plot with alternate surface normals 
  % (giving a symmetrical lighting as it should)
  figure(10)
  surf(X,Y,Z,'EdgeAlpha',0.2,'FaceColor','c',...
             'VertexNormals',facenorm(X,Y,Z))
  axis equal
  light('Position',[0 0 1],'Style','infinite')
  view(0,60)

To me, the second plot looks quite promising, but I'm not sure whether it will work in general, or what drawbacks there are. If anyone likes to look at it, I'd be glad (e.g. I heavily suspect it can be simplified), but hopefully it does the trick for me as it is.