[comp.graphics] Matrix Operations on Normals

gessel@cs.swarthmore.edu (Dan Gessel) (02/03/89)

I have a question about matrix operations on vertex lists defining objects
within a ray tracer. I use a triangular primatve that goes through a recursive
subdivision to either smooth out the surface or make it fractal during the ray
trace calculation. This allows for very fine detail over the surface
without having to store large amount of information.

Stored in the vertex list is not only the coordinates of the vertex, but also
the normal to the surface at that point. These normals define the smoothing
operations required. I use matrices to perform rotations and would like to for
scaling operations. The first is no problem, I rotate the vertices and the
normals through simple matrix multiplication, but if I want to stretch the 
object, the normals would be increased in length in the direction of the
stretch. If we think of a sphere, it will stretch to an oval shape. We can
figure that the opposite should happen, the normals should decrease in the
direction of the stretch to the oval shape.

That is, given a matrix operation to be performed on a  surface, how does this
operation affect the normals? Any solutions or sources would be appreciated.

Daniel Mark Gessel
gessel@cs.swarthmore.edu

I apologize if this went up  twice. I posted it yesterday and found it marked
unavailable this morning, not simply already read, so I assumed it didn't go
through.

cme@cloud9.Stratus.COM (Carl Ellison) (02/05/89)

If you have either a plane equation or just a normal (4 or 3 components
respectively; homogeneous coordinates or raw 3D) which you want to
rotate via some matrix, M, (4x4 or 3x3, respectively) the answer is
found in math or physics books on tensors.

Between a vertex, v, and a normal, n, one is covariant and the other is
contravariant.  (I'm not sure, but I think the normal is covariant...
That doesn't matter so much for what follows.)

The solution comes from the fact that the dot product v.n is an invariant.
That is, if you rotate coordinate systems, the scalar result of v.n
should remain unchanged ... or v'.n' (each in the new system) should
= v.n

Assuming v is a row vector so that v' = vM, the normal would be a column
vector and n' = inverse(M)n.

v'.n' = v M inverse(M) n = v.n

It's been ages since I worked this out for matrices with both scaling and
skew.  I'll leave that to fellow netters.  I'm away from graphics devices
at the moment.

Enjoy,

--Carl Ellison                      UUCP::  cme@cloud9.Stratus.COM
SNail:: Stratus Computer; 55 Fairbanks Blvd.; Marlborough MA 01752
Disclaimer::  (of course)

ph@miro.Berkeley.EDU (Paul Heckbert) (02/06/89)

Daniel Gessel (gessel@cs.swarthmore.edu) asks:
>... given a matrix operation to be performed on a surface, how does this
>operation affect the normals?

Good question.  It's non-intuitive; you might think that you transform
normals by the same matrix as points, but that doesn't work in general.

Let's assume you're transforming points like so:

	p' = p M

				  [m00 m01 m02 m03]
				  [m10 m11 m12 m13]
	(x' y' z' w') = (x y z 1) [m20 m21 m22 m23]
				  [m30 m31 m32 m33]

where p is the original point, p' is the transformed point, and M is the
homogeneous transformation matrix.  [ref: Foley & van Dam,
Fundamentals of Interactive Computer Graphics].

Normals transform like planes.
Points are row vectors and planes are column vectors.
Given a plane n: (ax+by+cz+d=0), it transforms
to the plane n': (a'x'+b'y'+c'z'+d'=0) like so:

	n' = M~ n

	(a')   [m00 m01 m02 m03]~ (a)
	(b')   [m10 m11 m12 m13]  (b)
	(c') = [m20 m21 m22 m23]  (c)
	(d')   [m30 m31 m32 m33]  (d)

where M~ means the matrix inverse or adjoint of M.
( The adjoint is the transpose of the matrix of cofactors.  It is
preferable to the inverse matrix in homogeneous matrix algebra because it
is a scalar multiple of the inverse, and it always exists, while the
inverse does not.  inv(M)=adj(M)/det(M) )
Represent the normal (a,b,c) at a surface point by the tangent plane
with coefficients (a,b,c,d), transform as above, then normalize (a',b',c').

If you'd rather think of your planes/normals as row vectors then transpose
the above and you get n'^ = n^ M~^, where "^" denotes transposition.

That's the formula.  If you're interested in why, then read on.

-------------

Varying d selects from the family of planes perpendicular to normal (a,b,c).
You might wonder: what does "d" mean when one is transforming normals,
and why set it to 0?
Its effects on n' depend on the type of transformation in M.

There are shortcuts to the general formula if M is a simple transformation.
If M is just a rotation then M~^=M,
so you can get away with the formula n'^ = n^ M.  If M is just a translation
then its inverse will be a translation, so d' may not equal d,
but (a',b',c')=(a,b,c), so the normal is unchanged.
If M is scale(A,B,C) (scale x by A, scale y by B, scale z by C)
then M~^ = scale(1/A,1/B,1/C).  If it's a uniform scale (A=B=C) then
normalization will undo the scaling, so normalized(n')=n.
If the scale is differential (NOT A=B=C) then you can't use the shortcuts
n'=n or n'^=n^M.
If M is a concatenation of scales, rotates, and translates then M is 4x3
with last column of (0,0,0,1), and so is its inverse, so a', b', and c'
are unaffected by d (parallel planes transform to parallel planes).

In the most general case, when M contains a perspective transformation
(when its last column is not (0,0,0,1)) then its inverse is also a perspective
transformation, and a', b', and c' ARE affected by d.  In this case
parallel planes transform to nonparallel planes.
That makes sense intuitively: the yz plane passing through your eye is
perpendicular to your line of sight, but translate it left or right and
it becomes either front-facing or backfacing in the perspective coordinate
system centered on your eye; its normal vector in that space
depends on its lateral translation d.

The conclusion is that if you're transforming normals then you don't
care about d', and if M has no perspective in it then the value of d is
irrelevant, but if M does have perspective in it
then d influences the transformed normal, and you should choose d
such that (ax+by+cz+d=0) is the tangent plane at your surface point.

------

Why transform by the inverse of M?  That's fairly easy to show.
If our plane equation is pn=0 in one coordinate system then we want to
find the new plane equation n' such that p'n'=0 in the transformed coordinate
system.  We already know p'=pM, and multiplying both sides by M~ on
the right, we have p=p'M~.  Substituting into pn=0 we have p'M~n=0.
If this is to be true for all p' then n'=M~n.

------

Has anybody seen normal/plane transformation explained well in a textbook?

Paul Heckbert, CS grad student
508-7 Evans Hall, UC Berkeley		UUCP: ucbvax!miro.berkeley.edu!ph
Berkeley, CA 94720			ARPA: ph@miro.berkeley.edu