Search code examples
matlabopenglnormalsmorphing

Calculate vertex normals for parametrically morphed sphere


I want to morph sphere, using the following equation:

R=1+k*(cos(4*elev)+sin(4*az)),

Spherical coordinates elev and az are transferred as gl_Vertex. The problem is to calculate normals for such morphing. I may calculate them, just shifting az and elev a bit, the obtain 2 more "virtual" vertices and use standard approach with cross-product, but it looks rather ugly and expensive approach.

Is their are any way to calculate normals also parametrically for such kind of morphing?

UPDATE:

Thanks to @meowgoesthedog, but I still have problems. My implementation of this formula (code below) did not work:

Am i correct and it should be:

cos(theta)*(k*(cos(4*theta)+sin(4*phi))+1) or cos(theta*(k*(cos(4*theta)+sin(4*phi))+1))?

Are normals calculated in cartesian coordinate system?

My code in Matlab:

close all
clear all
N=100;
phi_range=linspace(-pi,pi,N+2);
theta_range=linspace(-pi/2,pi/2,N);
phi_range([1,end])=[];
k=6;
% generate morphed sphere
PHI=repmat(phi_range,N,1);
THETA=repmat(theta_range',1,N);
R=1+k*cos(4*THETA)+k*sin(4*PHI);
% convert to cartesian coordinates
[X,Y,Z]=sph2cart(PHI,THETA,R);
%% meowgoesthedog formula
S=k.*(cos(4.*THETA)+sin(4.*PHI))+1;
V1_x = cos(PHI).*(cos(THETA).*S-4.*k.*sin(THETA).*sin(4.*THETA));
V1_y = sin(PHI).*(cos(THETA).*S-4.*k.*sin(THETA).*sin(4.*THETA));
V1_z = -sin(THETA).*S-4.*k.*sin(4.*THETA).*cos(THETA);

V2_x = sin(THETA).*(4.*k.*cos(PHI).*cos(4.*PHI)-sin(PHI).*S);
V2_y = sin(THETA).*(4.*k.*sin(PHI).*cos(4.*PHI)+cos(PHI).*S);
V2_z = 4.*k.*cos(THETA).*cos(4.*THETA);

V1=cat(3,V1_x,V1_y,V1_z);
V2=cat(3,V2_x,V2_y,V2_z);

Normals=cross(V1,V2);
% normalize
Normals=Normals./sqrt(sum(Normals.^2,3));
%% plot and compare results:
hold all
surfnorm(X,Y,Z,'EdgeAlpha',0.5)
quiver3(X,Y,Z,Normals(:,:,1),Normals(:,:,2),Normals(:,:,3),'m')

On figures below red - correct normals, magenta which I calculate.

enter image description here

enter image description here


Solution

  • We can compute an analytical expression for the normal using differential geometry. Let's first state the form of the Cartesian parametric coordinate:

    enter image description here

    Locally at any point on the surface, there is a 2D coordinate system spanned by the unit vectors in the directions of increasing θ and φ.

    enter image description here

    These vectors are given by:

    enter image description here

    The normal is simply given by the cross-product of these two vectors (un-normalized):

    enter image description here

    After some very tedious algebra we obtain:

    enter image description here

    (The formula becomes too long to legibly display past this point, and probably not as efficient to evaluate either.)


    EDIT

    It appears that I have used the conventional definition of θ (angle from the +Z axis) instead of Matlab's elev. Redefining the equations this would give:

    enter image description here

    Where ψ = ½π - θ is the elevation.