
			Mark's Useful 3D Maths stuff
			----------------------------

	This document is provided as is without any guarantee of the 
	accuracy of its content. It contains the bare essentials of 
	3D maths for computer graphics.


The 3x3matrix:

	... is capable of storing rotation and scale information 
	for a space. A nice way to think of a matrix is as a 
	"frame of reference". Think of the corner of a cube, with 
	arrows pointing in all three dimensions. Then think of 
	rotating the arrows, and changing their size, and what 
	this manipulation would do to an object in the cube. This is 
	how a 3x3matrix works. Now, if you look at each column in a 3x3,
	you will see that each column is a vector corresponding to an
	arrow from the corner of the cube. It's quite straight-forward
	really!


Magnitude of a Vector:

	This is the same as a standard distance calculation:

		|V| = (Vx*Vx + Vy*Vy + Vz*Vz)

Normalizing a Vector:

	To normalize a vector to a magnitude of 1.0 simply 
	divide each component by the overall magnitude:

		V' = V/|V|


Dot Product of two vectors (A.B):

	The dot product is probably the most fundamental operation 
	in 3D maths. It is most recognised for backface removal 
	and light-sourcing primarily, but even a standard transform
	uses dot products essentially.
  
	The dot product of vectors A and B is a scalar value 
	(1-dimensional). It is written as A.B and is calculated 
	thus:

		A.B = (Ax*Bx + Ay*By + Az*Bz)/(|A|*|B|)

	Note that where |A| = |B| = 1.0 no division is 
	necessary, one reason why vectors should be normalized 
	where possible.

	A.B is equal to the cosine of the angle between A and 
	B. This is useful for Back Face removal:

		if A.B >= 0 face is visible

	And for directional light sourcing:

		Intensity = source * A.B
	
	When A is a unit vector, A.B is equal to the length of 
	B projected onto A. This is useful for evaluating the
	distance of a point from a plane. 


Cross Product of two vectors (A x B)

	The cross Product of vectors A and B is another vector 
	C. It is written C = A x B. The calculation:

		Cx = Ay*Bz - By*Az
		Cy = Az*Bx - Bz*Ax
		Cz = Ax*By - Bx*Ay

	The vector C is perpendicular to A and B (Note: if A is 
	perpendicular to B and |A| = |B| = 1.0 then |C| = 1.0). 
	It is good practise to normalize a vector created this 
	way. A good use for Cross product is finding a surface 
	normal to a polygon.

	Given P,Q and R (three points on a polygon in order) 
	get normalized surface normal N.

		A = P-Q     get A and B as directional vectors
		B = R-Q

		C = A x B   get cross product

		N = C/|C|   normalize to a magnitude of 1.0




Solving 2D Vector equations:

	Given

		A*t + B*u + C = 0

	where A,B and C are 2D vectors,

		t = (Bx*Cy - By*Cx) / (Ax*By - Ay*Bx)

	Example:

	Find point of intersection of two lines in 2D
	Line1:
		P = H*u + J

	Line2:
		P = K*v + L

	putting them together:
		H*u + J = K*v + L
		H*u - K*v + (J-L) = 0
	


Solving 3D Vector equations:

	Given

		A*t + B*u + C*v + D = 0

	where A,B,C and D are 3D vectors,
	

	    ((Bx*Dy-By*Dx)*(Cy*Bz-Cz*By)-(By*Dz-Bz*Dy)*(Cx*By-Cy*Bx))
	t = ---------------------------------------------------------
	    ((Ax*By-Ay*Bx)*(Cy*Bz-Cz*By)-(Ay*Bz-Az*By)*(Cx*By-Cy*Bx))

	Example:

	Find point of intersection of line and plane in 3-space
	Line:       
		P = H*t + J
	
	Plane:      
		P = K*u + L*v + M

	putting them together:

		H*t + J = K*u + L*v + M
		H*t - K*u - L*v + (J-M) = 0


To transform vector V with 3x3matrix T:

	V'x = Vx * TXx + Vy * TYx + Vz * TZx
	V'y = Vx * TXy + Vy * TYy + Vz * TZy
	V'z = Vx * TXz + Vy * TYz + Vz * TZz

	To transform a 3x3matrix T1 with another 3x3matrix T2 simply 
	transform the three vectors (columns) of T1 in turn.


Reversing a 3x3matrix:

	To reverse a normalized 3x3matrix simply swap columns and 
	rows:

		Xy <=> Yx, Xz <=> Zx, ... etc

	The algorithm for reversing an arbitrary 3x3matrix is quite 
	complex, and unnecessary for simple 3d maths.



Perspective transform:

	given 3D vector V the 2D projection coords are 
	calculated thus:

		x = (Vx * k) / Vz
		y = (Vy * k) / Vz

	k is a scaling value. If the screen is n units across 
	and a is the view angle:

		k = n / (2*tan(a/2))

Using Z and 1/Z:

	There are certain advantages to using 1/Z values in 
	place of z values. In many calculations, one needs to
	divide by z, so sometimes it is better to just store 
	the inverse. One main reason is that 1/z can be linerly 
	interpolated. eg if there is a line drawn on the screen 
	which has one end at 50 units and the other at 100 units 
	away, the midpoint of the screen IS NOT the mid point of 
	the Z. however it is the mid-point of the 1/z. 
		
Perspective correction (for texture mapping):

	given:

	A-B:      an interval in 3D space, with x and y                 
	          components projected onto a 2D plane.
	dxy:      a ratio (0-1) for dividing A-B on the XY 
	          plane
	dz:       a ratio (0-1) for dividing A-B in Z dimension
	n:        XY units in A-B

	NOTE: Z+1 and Z-1 represent z and 1/z calculation

	Given dxy, dz = ...
		Z+1:  Az*dxy / ((Az - Bz)dxy + Bz)
		Z-1:  Bz*dxy / ((Bz - Az)dxy + Az)

	Given dz, dxy = ...
		Z+1:  Bz*dz / ((Bz - Az)dz + Az)
		Z-1:  Az*dz / ((Az - Bz)dz + Bz) 

	if dxy = 0.5, dz = ...
		Z+1:  Az / (Az + Bz)
		Z-1:  Bz / (Az + Bz)

	if dz = 0.5, dxy = ...
		Z+1:  Bz / (Az + Bz) 
		Z-1:  Az / (Az + Bz) 

	Distortion (k) = ...
		Z+1:  n(Az-Bz) / 2(Az + Bz) 
		Z-1:  n(Bz-Az) / 2(Az + Bz) 



Quadratic approximation (for texture mapping):

	This method is not really satisfactory for extreme 
	distortion.

	given: 
		u0-u2:   texture ordinates for an interval AB
		z0-z2:   z ordinates for interval AB
		n:       steps (pixels)

	find:
		z1:      middle z value = (z0+z2)/2
		u1:      texture ordinate at z1
		f0:      starting texture value (u0)
		f1:      first forward difference
		f2:      second forward difference

		u1 = u0 + z0(u2 - u0) / (z0 + z2)
		a = ( 2*u0 - 4*u1 + 2*u2 ) / (n*n)
		b = (-3*u0 + 4*u1 - u2) / n
		f0 = u0
		f1 = a + b
		f2 = 2*a

	values after n steps:

		f0 = f0 + n*f1 + n(n-1)*f2 / 2
		f1 = f1 + n*f2



Triangle Rendering (with texture mapping):

	Within an affine triangle the relative texture step 
	remains constant (both vertical and horizontal). This 
	means that only 1 division per component per triangle 
	(instead of per scan). Saves a lot of time.
	
	given:
	  A-B-C: a triangle with screen x and y components, 
	         texture vertices and z values.

	find: 
		
	          (At-Ct)(By-Cy) - (Bt-Ct)(Ay-Cy)
	dt/dx =   -------------------------------
	          (Ax-Cx)(By-Cy) - (Bx-Cx)(Ay-Cy)

	Triangles are easier to map but they do not 
	automatically correct perspective distortion in texture 
	mapping. One approach to this problem is to subdivide 
	the triangle (or other polygon) into smaller triangles.


Trig Functions (and relations):
       
	sin(a)sin(a) + cos(a)cos(a) = 1
	sin(a+b)=sin(a)cos(b)+sin(b)cos(a)
	cos(a+b)=cos(a)cos(b)-sin(a)sin(b)
	sin(2a) = 2sin(a)cos(a)
	cos(2a) = cos(a)cos(a)-sin(a)sin(a)
	1 + tan2(a) = sec(a)sec(a)
	sin(a)sin(a) = 1/2(1 - cos(2a))
	cos(a)cos(a) = 1/2(1 + cos(2a))



Quaternions:

	A quaternion is a 4D vector representing an axis of 
	rotation (V) and an angle of rotation (a). Easier to 
	store and interpolate than the equivalent matrix.

	[s,[x,y,z]]
	[cos(a/2), [sin(a/2)Vx, sin(a/2)Vy, sin(a/2)Vz]]

	Given two quaternions q1 and q2, they are transformed 
	as follows:

		q1q2 = [(s1s2-v1   v2),[s1v2 + s2v1 + v1 x v2]]

	The inverse quaternion is found:

		q(-1) = [s,-v]/|q|

	To make a 3x3 matrix from a (normalized) quat:

	    +--                                   --+
	    | 1-2yy-2xx  ,  2xy-2sz    ,  2xz+2sy   |
	M = | 2xy+2sz    ,  1-2xx-2zz  ,  2yz-2sx   |
	    | 2xz-2sy    ,  2yz+2sx    ,  1-2xx-2yy |
	    +---                                  --+




