[27 Dec 2012] | ## Useful vectors in Computer Graphics |

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.

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):

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 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):

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

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:

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.

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 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):

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):

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:

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:

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