[27 Dec 2012]

# Useful vectors in Computer Graphics

Normal of a triangle

Calculation of normals for triangles can be useful when polygonal mesh was saved without normals, when it’s required to determine normal to plane, etc. To calculate normal to triangle we need two vectors: a and b. Cross product of these vectors will give normal to the triangle. Direction of normal depends on order of vectors in cross product.

 $\vec{a} = C - A$ $\vec{b} = B - A$ $\vec{n} = \vec{a} \times \vec{b}$
Normal at a vertex

In polygonal meshes each vertex is usually shared by multiple triangles. How to determine normal for such vertex? We can copy each shared vertex in such a way that it will be unique for triangle, and assign triangle’s normals to appropriate vertices. This will lead to visible changes between polygons during lighting. This may be desirable effect, for example, for cube mesh, where each side has normals that are equal to normals of triangles. If visual difference between polygons is undesirable, then normals should be smoothed. There’re following methods for calculation of smoothed normals (result should be normalized in all cases):

• add together normals of all triangles that share vertex. N=N1+N2+N3. This method is used most often.
• multiply normal of each triangle by area of the appropriate triangle. Then add together normals of all triangles that share vertex. N=N1*A1+N2*A2+N3*A3. Area of a triangle is calculated as half of the cross product of triangles edges.
• multiply normal of each triangle by angle adjacent to the vertex. N=N1*q1+N2*q2+N3*q3. Angle is calculated as acos of dot product of edges that are adjacent to the vertex.
• combined method. Normals are weighted by areas of triangles and by adjacent angles. N=N1*A1*q1+N2*A2*q2+N3*A3*q3.
Normal to a line

To find normal to a line in 2D space it's required only to swap x and y components of line's direction, and to invert one of them. So if line has direction (x, y), then normals to this line are n=(-y, x) or
n=(y, -x). These two normals point in opposite directions.

Line has infinite number of normals in 3D space. To find any of these normals, we can use cross product. Let line has direction a. Take an arbitrary vector b with direction that isn't equal to a (and not opposite). Result of cross product (n) of vectors a and b will be perpendicular to line.

Tangent and normal to curve

Tangent to curve can be calculated with help of first derivative of curve's equation, and normal as perpendicular to tangent. For example for 2D case, for equations like y=f(x):

 Equation of curve $y=x^{2}$ Point where tangent is required $x=2;\:y=4$ First derivative of curve's equation ${y}'(x)=2x$

Find gradient at the point of interest (pass x coordinate of the point to derivative). Gradient shows how y depends on change of x.

 Gradient at point (2,4) $x=2\:=>\:{y}'(x)=4$

So, if x changes by 1, then y changes by 4. Find equation of tangent line with tilt that corresponds to gradient, and passes through point (2,4). You can use equation of line for this:

 Equation of line $y-y1=y'(x)(x-x1)$ Equation of line in form y=f(x) $y=y'(x)(x-x1)+y1$ Tangent at point (2,4) $y=4x-4$
Tangent to curve without explicit equation

In many cases equation of curve is unknown. In case if curve is parametric, like Bezier curve, then each point along the curve can be represented as parametric value t. If t represents point on the curve, then t+Δ represents next point on the curve (imagine that Δ is infinitesimally small value). Tangent to curve at point t can be calculated as direction from point t to point t+Δ. For floating point calculations Δ is small value, but at the same time it should be sufficient to calculate direction. The direction will be close to real tangent. Normal is calculated as perpendicular to tangent.

Light vector, eye vector and half vector

During calculation of lighting following vectors are used:

• n - normal to the surface. Usually it's calculated by interpolation of normals of triangle's vertices.
• v - eye vector. It's calculated as direction from point on the surface P to position of the camera.
• L - light vector. It's calculated as direction from point on the surface P to position of the light. If light source doesn't have defined position (like directional light), then light vector is equal to direction of light source. If light isn't point light source, and it has physical volume, then position of light is defined as finite number of positions inside light's volume.
• r - reflected vector. It's used for simulation of highlights, mirror surfaces, calculation of bounced rays, etc.
• t - refracted vector. It's used for simulation of transparent and translucent objects.
• h - half vector. It's calculated as normalized sum of vectors L and v. From the image you can see that angle between vectors n and h is approximation to angle between vectors v and r. This property is used during calculaiton of specular lighting in standard Blinn-Phong lighting model (so there's no need to calculate reflected vector r).
Reflected vector

Reflected vector is calculated as reflection about the axis (in our case - about normal of the surface). In GLSL reflected vector can be calculated with help of reflect() function. It requires incident vector and normal vector as input arguments. Actual calculation of reflected vector is following (n and L vectors should be normalized):

• calculate length of t - projection of vector L on vector n (dot product of n and L).
• calculate position of point T1 as doubled t in direction of n.
• calculate point T2 by substraction of L from T1.
• reflected vector is equal to vector from point on the surface P to point T2.

$r = 2(n\cdot l)n-l$
Refracted vector

Refracted vector is calculated according to Slell's Law. In GLSL refracted vector can be calculated with help of refract() function. It requires incident vector, normal vector and ratio of indexes of refraction (n1/n2) as input parameters. Actual calculation of refracted vector is following (n and L vectors should be normalized):

 Cosine of angle near incident ray $cos(\theta)=n\cdot(-L)$ Sine of angle near incident ray $sin(\theta)=\sqrt{1-cos^{2}(\theta)}$ Cosine of angle near refracted ray $cos(\gamma)=\sqrt{1-sin^{2}(\gamma)}$ Sine of angle near refracted ray $sin(\gamma)=sin(\theta)\frac{n1}{n2}$
Now we can calculate cosine of angle γ:
 Substitute sine θ with cosine θ $sin(\gamma)=\frac{n1}{n2}\sqrt{1-cos^2(\theta)}$ Substitute sine γ with cosine θ $cos(\gamma)=\sqrt{1-\frac{n1^{2}}{n2^{2}}(1-cos^2(\theta))}$

Now we have all required values for calculation of refracted vector. As you can see from the image, refracted vector is based on two components: part along incident ray and part along normal (yellow line). So final formula for refracted ray is:

$R=\frac{n1}{n2}L+(\frac{n1}{n2}cos(\theta)-cos(\gamma))n$
Orthogonalization of vectors

Three self orthogonal vectors can be used to create new coordinate system, frame of reference, tangent space, etc. Imagine that we have three vectors and these vectors should be axes of new coordinate system. But these vectors aren't necessarily perpendicular. The algorithm for transformation of three arbitrary vectors to orthonormal basis is called orthogonalization. Orthogonalized vectors will differ from initial vectors. In most cases orthogonalization is done by Gram-Schmidt process:

• Among three vectors select vector that will coincide with the axis Y'. For example, vector Y.
$Y'=Y$
• Select next vector - X. It is not perpendicular to Y' axis. The deviation from perpendicularity can be expressed as displacement d1 along direction that is opposite to axis Y'. Offset can be determined by dot product. So add offset to vector X and normalize result. Result will be orthogonal to Y', and it is new axis - X'.
$X'=X-(Y'\cdot X)Y'$
• Now take vector Z. It is not perpendicular to both Y' and X' axes. Determine diviations from perpendicularity for vector Z (d2 and d3) for axes X' and Y'. Offset vector Z along -X' by distance d2 and along -Y' by distance d3, and normalize result. Now you have Z' axis.
$Z'=Z-(Y'\cdot Z)Y'-(X'\cdot Z)X'$

Result of Gram-Schmidt orthogonalization depends on choise of first vector. First vecror will coincide with axis, and other two vectors will be modified in order to be orthogonal. In many cases it's ok, for example, during calculation of tangent space, when normal of the surface should be fixed. But for some cases it's preferable to preserve similarity between initial vectors and orthogonalized vectors as much as possible. In such case you can use iterative Gram-Schmidt orthogonalization. On each iteration take next vector, calculate required offset, but modify vector only by small amount of offset. Repeat this for some time, and then perform standard Gram-Schmidt orthogonalization. New axes will be more similar to the initial vectors.

• Sun and Black Cat- Igor Dykhta () © 2007-2014