13. OpenGL Lighting

advertisement
OpenGL Lighting
13. OpenGL Lighting
• Overview of Lighting in OpenGL
In order for lighting to have an effect in OpenGL, two
things are required:
A light
An object to be lit
Lights can be set to any color, and can have a wide
variety of parameters which determine where they are
located, in what direction they shine, and how they
interact with objects in the world.
Objects have a variety of parameters which determine
how they reflect the light which hits them.
The color(s) of an object is determined by the combining
the parameters of the light(s) in the world with the
object’s parameters.
E.R. Bachmann & P.L. McDowell
MV 4202 Page 1 of 32
OpenGL Lighting
• Types of Light in OpenGL
The three types of lights used in OpenGL are defined as
follows:
Ambient:
Bounced light which has been scattered so much that it
is impossible to tell the direction to its source
(disappears if the light is turned off)
Diffuse:
Directional light which is brighter on perpendicular
surfaces. Its reflection is scattered evenly.
Specular:
Directional light which tends to reflect in a preferred
direction (associated with shininess)
Each of these three components has an effect on the
lighting of each object in the world – the actual light at a
location is the sum of the three types of lights
Just as in space, light is not noticable until it hits an object,
and then its effect depends upon the object
E.R. Bachmann & P.L. McDowell
MV 4202 Page 2 of 32
OpenGL Lighting
• Components of Lighting in OpenGL
o OpenGL approximates light and lighting as if light
could be broken into red, green and blue components
- Light sources are characterized by the amount of
red, green, and blue they emit
o Each light emits one or more of the three separate
types of light:
- Ambient, diffuse and specular
- Each of these types has a red, green, and blue
component
o In addition to the lights that can be placed in a scene,
the entire scene can be lit by a global ambient light,
which will affect the lighting of every object in the
scene, regardless of location or position
o The lights in a scene can be attenuated
E.R. Bachmann & P.L. McDowell
MV 4202 Page 3 of 32
OpenGL Lighting
• Material
o Each object is composed of a material which has four
properties that determine how the lighting model
treats the object:
- emissive, ambient, diffuse and specular
• ambient, diffuse and specular interact with the
corresponding types of light and determine what
percentage of the respective types of light are
reflected
• emissive allows an object to be a certain color
even if not illuminated by any lights in the world
emissive is most often used to simulate lamps
and other light sources in a scene
E.R. Bachmann & P.L. McDowell
MV 4202 Page 4 of 32
OpenGL Lighting
• Using Lighting in OpenGL
There are four steps required to add lighting to scene:
- Define a normal vector for each vertex of all the
objects
- Define material properties for all of the objects in
the scene
- Create, position and enable one or more light
sources
- Create and select a light model
• Setting Material Properties
An object’s material properties determine how it reflects
the various types of light produced by light sources
The material properties of an object may also be set to
make it appear to emit light
Material properties are set using
void glMaterial{if}( GLenum face, GLenum pname,
TYPE param );
void glMaterial{if}v( GLenum face, GLenum pname,
TYPE *param );
where
E.R. Bachmann & P.L. McDowell
MV 4202 Page 5 of 32
OpenGL Lighting
- face may be GL_FRONT, GL_BACK, or
GL_FRONT_AND_BACK to indicate which face
the property is being specified for
- pname identifies the property being set
- param specifies the value to which the property is
being set
- The nonvector version works only for setting the
shininess of an object (pname of GL_SHININESS)
E.R. Bachmann & P.L. McDowell
MV 4202 Page 6 of 32
OpenGL Lighting
♦ Ambient Reflection (GL_AMBIENT)
Ambient reflection is most noticeable when an object
receives no direct illumination
Ambient reflectance isn’t affected by the position of
the viewpoint
The ambient RGB values of a material determine the
proportion of the RGB components of ambient light
which are reflected by the material
The ambient term is the ambient color of the light
scaled by the material property
ambient term = ambientlight * ambientmaterial
(13.2)
The ambient components of a material are set by
calling glMaterial with GL_AMBIENT as the pname
argument
Example 13.12
GLfloat mat_amb[] = { 0.1, 0.5, 0.8, 1.0 };
glMaterialfv( GL_FRONT_AND_BACK,
GL_AMBIENT,
mat_amb );
E.R. Bachmann & P.L. McDowell
MV 4202 Page 7 of 32
OpenGL Lighting
♦ Diffuse Reflection (GL_DIFFUSE)
Diffuse reflection is most intense where the light
direction is perpendicular to the object’s surface
It is affected by the angle of the incident light relative
to the normal direction
Diffuse reflectance isn’t affected by the position of the
viewpoint
The diffuse term takes into account the diffuse color
of the light, whether the light falls directly on the
vertex, and the diffuse color of the material
The diffuse term is given by
(max{L • n, 0}) * diffuselight * diffusematerial
(13.3)
where
- L is a unit vector pointing from the vertex to the
light position
- n is the unit normal vector at the vertex
The diffuse components of a material are set by calling
glMaterial with GL_DIFFUSE as the pname argument
Example 13.13
GLfloat mat_dif[] = { 0.1, 0.5, 0.8, 1.0 };
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_dif );
E.R. Bachmann & P.L. McDowell
MV 4202 Page 8 of 32
OpenGL Lighting
♦ Diffuse and Ambient Reflection
(GL_AMBIENT_AND _DIFFUSE)
The diffuse and ambient reflectance of an object are
normally the same color and intensity
Using GL_AMBIENT_AND _DIFFUSE as the pname
may be used to set them both
Example 13.14
GLfloat mat_amb_dif[] = {0.1, 0.5, 0.8, 1.0};
glMaterialfv( GL_FRONT,
GL_AMBIENT_AND_DIFFUSE,
mat_amb_dif );
♦ Specular Reflection
Specular reflection produces highlights
Depends on both the angle from the viewpoint to the
object and the angle from the light source to the
object
It is brightest along the direct angle of reflection
Specular highlights are normally white or light gray in
color
The specular term is given by
(max{s • n, 0})shininess * specularlight * specularmaterial (13.4)
where
E.R. Bachmann & P.L. McDowell
MV 4202 Page 9 of 32
OpenGL Lighting
- s is the normalized sum of two unit vectors from
◊ the vertex to the light position (or the light
direction)
◊ the vertex to the viewpoint (or (0, 0, 1) for non
local view points)
- n is the unit vector at the vertex
- If s • n = 0, there is no specular term
Example 13.15
GLfloat mat_spec[] = {1.0, 1.0, 1.0, 1.0};
glMaterialfv( GL_FRONT,
GL_SPECULAR,
mat_spec );
The shininess term in 13.4 determines the size and
brightness of the highlight
- The higher the value the smaller and brighter the
highlight
- Smaller values will produce a larger less focused
(dimmer) highlight
The shininess term is in the range [0.0, 128.0]
Shininess is set by calling glMaterial with
GL_SHININESS as the pname argument
Example 13.16
glMaterialf(GL_FRONT, GL_SHININESS, 5.0 );
E.R. Bachmann & P.L. McDowell
MV 4202 Page 10 of 32
OpenGL Lighting
♦ Emission (GL_EMISSION)
Specifying an RGBA color for GL_EMISSION will
make an object appear to be giving off light of that
color
Specifying an RGBA color for GL_EMISSION does
not turn the object into a light source
Objects with an emissive property will be visible even
if there are no light sources
Example 13.17
GLfloat mat_emiss[] = {0.3, 0.2, 0.2, 0.0};
glMaterialfv(GL_FRONT, GL_EMISSION,mat_emiss );
E.R. Bachmann & P.L. McDowell
MV 4202 Page 11 of 32
OpenGL Lighting
Example 13.18
Setting the material properties.
GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat mat_ambient[] = { 0.7, 0.7, 0.7, 1.0 };
GLfloat mat_ambient_color[] =
{ 0.8, 0.8, 0.2, 1.0 };
GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8, 1.0};
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0};
GLfloat no_shininess[] = { 0.0 };
GLfloat low_shininess[] = { 5.0 };
GLfloat high_shininess[] = { 100.0 };
GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0};
glClear(GL_COLOR_BUFFER_BIT |
G L_DEPTH_BUFFER_BIT);
//
//
//
draw sphere in first row, first column
diffuse reflection only; no ambient or
specular
glPushMatrix();
glTranslatef( -3.75, 3.0, 0.0 );
glMaterialfv( GL_FRONT, GL_AMBIENT, no_mat );
glMaterialfv( GL_FRONT,
GL_DIFFUSE,
mat_diffuse );
glMaterialfv( GL_FRONT, GL_SPECULAR, no_mat );
glMaterialfv( GL_FRONT,
GL_SHININESS,
no_shininess );
glMaterialfv( GL_FRONT, GL_EMISSION, no_mat );
glutSolidSphere( 1.0, 16, 16 );
glPopMatrix();
. . .
E.R. Bachmann & P.L. McDowell
MV 4202 Page 12 of 32
OpenGL Lighting
• Using glColorMaterial
Often it is desirable to use the current color specified
using glColor*() as the ambient and diffuse color of the
material
glColorMaterial allows the ambient, diffuse, or specular
properties of a material to be set to the current color
Usage:
void glColorMaterial( GLenum face, GLenum mode );
where
- face specifies which polygon face the current color
will be applied
Possible values for face:
◊ GL_FRONT
◊ GL_BACK
◊ GL_FRONT_AND_BACK
- mode specifies the property to be set to the
current color
Possible values for mode:
◊ GL_AMBIENT
◊ GL_DIFFUSE
E.R. Bachmann & P.L. McDowell
MV 4202 Page 13 of 32
OpenGL Lighting
◊ GL_AMBIENT_AND_DIFFUSE
◊ GL_SPECULAR
- The current color may only be applied in one
mode at a time; i.e., it is not possible to set both
the specular and either ambient or diffuse colors to
the current color at the same time
♦ Enabling glColorMaterial
Before glColorMaterial can be used, it must be
enabled with
glEnable( GL_COLOR_MATERIAL );
Example 13.19
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
glEnable( GL_COLOR_MATERIAL );
glColorMaterial( GL_FRONT,
GL_AMBIENT_AND_DIFFUSE );
// Set the ambient and diffuse properties
glColor3f( 0.2, 0.5, 0.8 );
// Set the specular color
glMaterialfv( GL_FRONT, GL_SPECULAR,
mat_specular );
glColor3f( 1.0, 1.0, 1.0 );
// Draw the object
auxSolidSphere( 1.0 );
E.R. Bachmann & P.L. McDowell
MV 4202 Page 14 of 32
OpenGL Lighting
• Creating, Positioning and Enabling Lights
OpenGL allows the inclusion of at least eight separate
light sources
Each light source is given a predefined name as
follows:
GL_LIGHT0
GL_LIGHT1
.
.
.
GL_LIGHT7
Each must be individually turned on and off using
glEnable and glDisable respectively:
glEnable( GL_LIGHT0 );
glDisable( GL_LIGHT0 );
Lighting as a whole is enabled and disabled similarly
glEnable( GL_LIGHTING );
E.R. Bachmann & P.L. McDowell
MV 4202 Page 15 of 32
OpenGL Lighting
If lighting is disabled, the current color is mapped
onto the current vertex
- No calculations concerning normals, light sources,
lighting model and material properties are
performed
-
Each light source will have numerous characteristics or
properties:
- Color and intensities of its ambient, diffuse and
specular components
- Position
- Direction
- Constant, linear and quadratic attenuation factors
- Spotlight exponent and cutoff factors
The properties of each light are set using:
void glLight{if}( GLenum light, GLenum pname,
TYPE param );
void glLight{if}v( GLenum light, GLenum pname,
TYPE *param );
where
E.R. Bachmann & P.L. McDowell
MV 4202 Page 16 of 32
OpenGL Lighting
- light specifies the name of the light
(e.g., GL_LIGHT0)
- pname specifies the property being set
- param specifies the value to which the property is
being set
- The nonvector version can only be used to set
single-value characteristics
Pname may be any of the following to set the respective
properties:
- GL_AMBIENT
Ambient RGBA intensity of the light
Example 13.1
GLFloat lt_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
glLightfv( GL_LIGHT0, GL_AMBIENT, lt_ambient );
- GL_DIFFUSE
Diffuse RGBA intensity of the light
Example 13.2
GLFloat lt_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv( GL_LIGHT0, GL_DIFFUSE, lt_diffuse );
E.R. Bachmann & P.L. McDowell
MV 4202 Page 17 of 32
OpenGL Lighting
- GL_SPECULAR
Specular RGBA intensity of the light
Example 13.3
GLFloat lt_spec[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv( GL_LIGHT0, GL_SPECULAR, lt_spec );
- GL_POSITION
Sets either the position or direction of a light based
upon the value of the fourth element of param
◊ 1.0 indicates that the first three elements give
the xyz position of the light
◊ 0.0 indicates that the first three elements define
a vector which points in the direction from which
the light is coming
Example 13.4
A directional light
GLFloat lt_direct[] = { 1.0, 1.0, 1.0, 0.0 };
glLightfv( GL_LIGHT0, GL_POSITION, lt_direct );
Example 13.5
A positional light
E.R. Bachmann & P.L. McDowell
MV 4202 Page 18 of 32
OpenGL Lighting
GLFloat lt_posit[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv( GL_LIGHT0, GL_POSITION, lt_posit );
- GL_SPOT_DIRECTION
xyz direction of a spot light
◊ vector indicates the direction the light is pointing
Example 13.6
GLFloat spot_direction[] =
{ -1.0, -1.0, 0.0 };
glLightfv( GL_LIGHT0, GL_SPOT_DIRECTION,
spot_direction );
- GL_SPOT_CUTOFF
Defines the spotlight cutoff angle in degrees
cutoff angle
spotlight
Default cutoff angle is 180 degrees
E.R. Bachmann & P.L. McDowell
MV 4202 Page 19 of 32
OpenGL Lighting
Example 13.7
glLightf( GL_LIGHT0, GL_SPOT_CUTOFF, 45.0 );
- GL_SPOT_EXPONENT
Controls how concentrated the light is
Lower values cause the light to attenuate near the
edges of the cone
◊ default exponent is 0
◊ higher values result in a more focused light
source
- GL_CONSTANT_ATTENUATION
GL_LINEAR_ATTENUATION
GL_QUADRATIC_ATTENUATION
Set the constants of the attenuation factor used to
attenuate positional lights
E.R. Bachmann & P.L. McDowell
MV 4202 Page 20 of 32
OpenGL Lighting
attenuationfactor =
1
k c + kl d + k q d 2
(13.1)
- 13.1 is multiplied by the contribution of the
associated light source for each vertex
- kc, kl, and kq are the constant, linear and quadratic
attenuation factors, respectively
- default values: kc = 1, kl = 0, and kq = 0
- d is the distance from the light source to the vertex
- Using attenuated lighting slows performance
Example 13.8
glLightf(GL_LIGHT2,GL_CONSTANT_ATTENTUATION,2.0);
glLightf( GL_LIGHT2, GL_LINEAR_ATTENTUATION, 1.0 );
glLightf(GL_LIGHT2, GL_QUADRATIC_ATTENTUATION,0.5);
E.R. Bachmann & P.L. McDowell
MV 4202 Page 21 of 32
OpenGL Lighting
• Selecting a Lighting Model
The lighting model is concerned with three factors:
- The global ambient light intensity
- Local or infinitely distance viewpoint
- Differences between the lighting of the front and
the back polygon faces
The properties of the lighting model are set using
glLightModel{if}( GLenum pname, TYPE param );
glLightModel{if}v( GLenum pname, TYPE *param );
where
- pname is the property being set
- param is the value to which the property is being
set
- Possibilities for pname are
◊ GL_LIGHT_MODEL_AMBIENT
Set ambient RGBA intensity of the entire scene
◊ GL_LIGHT_MODEL_LOCAL_VIEWER
How specular reflections are computed
◊ GL_LIGHT_MODEL_TWO_SIDE
One-sided or two-sided lighting
E.R. Bachmann & P.L. McDowell
MV 4202 Page 22 of 32
OpenGL Lighting
♦ Global Ambient Light
Global ambient light is not from any particular source
- It is present in the scene even if no lights are
enabled
Example 13.9
Specify the global ambient RGBA intensity
glFloat lmodel_ambient[]={0.2, 0.2, 0.2, 1.0};
glLightModelfv( GL_LIGHT_MODEL_AMBIENT,
lmodel_ambient );
♦ Local or Infinite Viewpoint
The location of the viewpoint affects the calculations
for the highlights produced by specular reflectance
The intensity of a highlight depends on
- the vertex normal
- the direction from the vertex to the light source
- the direction from the vertex to the viewpoint
With an infinite viewpoint, the direction from every
vertex remains constant
With a local viewpoint, the direction is different for
each vertex
E.R. Bachmann & P.L. McDowell
MV 4202 Page 23 of 32
OpenGL Lighting
Example 13.10
Placing the viewpoint at the origin of the viewing (eye)
coordinates:
glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER,
GL_TRUE );
♦ Two-sided Lighting
By default, OpenGL only performs lighting
calculations for the front side of polygons
Lighting may be enabled for both polygon faces
Example 13.11
Lighting both polygon faces:
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE,
GL_TRUE );
E.R. Bachmann & P.L. McDowell
MV 4202 Page 24 of 32
OpenGL Lighting
• The OpenGL Lighting Calculation
The lit color of a vertex in the RGBA mode is
determined by
vertexcolor = emissionmaterial + (ambientlight model × ambient material )


1

 × (spotlight effect )i

+∑
2 


t =0  kc + k f d + k q d 

n −1
[
× ambientlight × ambient material
(
+ max{Li ⋅ n, 0}× diffuselight i × diffuse material
(
+ max{si ⋅ n, 0}
shininess
)
× specularlighti × specularmaterial
)])
(13.5)
• Looking at this calculation, it is
• Efficiency Note
• Lighting is expensive -- all of the following increase
the computational load:
E.R. Bachmann & P.L. McDowell
MV 4202 Page 25 of 32
OpenGL Lighting
-
Multiple Lights
Attenuation
Two-sided Lighting
Local Viewpoint
• Looking at equation 13.5, it is easy to see why
lighting is expensive and why each of these
increases the computational load.
• Shading in OpenGL
OpenGL provides two different shading models
♦ Flat Shading (GL_FLAT)
Lines or filled polygons are drawn in a single color
The color of one particular vertex determines the color
for the entire primitive
- For a line segment, the color of the line is the
current color when the last vertex is specified
- See text Table 4-2 to determine how OpenGL
selects the color of a Flat shaded polygon
• Smooth or Gouraud Shading (GL_SMOOTH)
E.R. Bachmann & P.L. McDowell
MV 4202 Page 26 of 32
OpenGL Lighting
The color of the interior points of primitives is
interpolated between the colors of the vertices which
define the primitive
The color of each vertex is treated individually
To specify a shade model use
void glShadeModel( GLenum mode );
where
- mode is either GL_SMOOTH (default) or GL_FLAT
• Positioning and Directing Lights
Light sources are subject to the same matrix
transformations as a primitive object
E.R. Bachmann & P.L. McDowell
MV 4202 Page 27 of 32
OpenGL Lighting
- Lights are positioned and directed relative to the
current local coordinate system as described by
the current modelview matrix
- The position and direction of a light can be
manipulated by changing the contents of the
modelview matrix stack
- The positioning of a light does not affect the
modelview matrix stack (a translation matrix is not
generated)
♦ Stationary Lights
To fix the position of a light, set it’s position after the
projection matrices have been set and viewing
transformations are on the stack
- Only the viewing transformations should be on the
modelview stack when the light is positioned
- Do the viewing transformations, position the light
then do the modeling transformations and draw the
objects in the scene
♦ Moving Light
To move a light relative to an object, position it by
translating and rotating it relative to the local coordinate
system of the object
♦ Light tied to the Viewpoint
E.R. Bachmann & P.L. McDowell
MV 4202 Page 28 of 32
OpenGL Lighting
To create a light which moves with the viewpoint, set the
light position and position it when there are no viewing
transformations on the stack
- Only the Identity matrix should be on the
modelview stack
- Both the light and the view point will be affected in
the same way
- IOW, position the light after the modelview stack
has been cleared to the identity matrix, but before
any viewing or modeling transformation are
completed!
• Shadows
OpenGL does not directly support shadows
“Fake shadows” can be created by projecting three
dimensional objects onto a two dimensional plane
The following function creates a shadow matrix:
E.R. Bachmann & P.L. McDowell
MV 4202 Page 29 of 32
OpenGL Lighting
It takes as arguments
- Three points that lie in the plane onto which the
shadow will be projected
- The position of the light source casting the shadow
- A pointer to the projection matrix which is being
returned
Two utility functions reduceToUnit and calcNormal are
also shown
♦ makeShadowMatrix
// Creates a shadow projection matrix out of the plane equation
// coefficients and the position of the light. The return value
// is stored in destMat[][]
void MakeShadowMatrix( GLfloat points[3][3],
GLfloat lightPos[4],
GLfloat destMat[4][4] )
{
GLfloat planeCoeff[4];
GLfloat dot;
// Find the plane equation coefficients.
// Find the first three coefficients the same way we
// find a normal.
calcNormal( points, planeCoeff );
// Find the last coefficient by back substitutions
planeCoeff[3] = - ((planeCoeff[0]*points[2][0]) +
(planeCoeff[1]*points[2][1]) +
(planeCoeff[2]*points[2][2]));
// Dot product of plane and light position
dot = planeCoeff[0] * lightPos[0] +
planeCoeff[1] * lightPos[1] +
E.R. Bachmann & P.L. McDowell
MV 4202 Page 30 of 32
OpenGL Lighting
planeCoeff[2] * lightPos[2] +
planeCoeff[3] * lightPos[3];
// Now make the projection matrix
// First column
destMat[0][0] = dot - lightPos[0] * planeCoeff[0];
destMat[1][0] = 0.0f - lightPos[0] * planeCoeff[1];
destMat[2][0] = 0.0f - lightPos[0] * planeCoeff[2];
destMat[3][0] = 0.0f - lightPos[0] * planeCoeff[3];
// Second column
destMat[0][1] = 0.0f - lightPos[1] * planeCoeff[0];
destMat[1][1] = dot - lightPos[1] * planeCoeff[1];
destMat[2][1] = 0.0f - lightPos[1] * planeCoeff[2];
destMat[3][1] = 0.0f - lightPos[1] * planeCoeff[3];
// Third Column
destMat[0][2] = 0.0f - lightPos[2] * planeCoeff[0];
destMat[1][2] = 0.0f - lightPos[2] * planeCoeff[1];
destMat[2][2] = dot - lightPos[2] * planeCoeff[2];
destMat[3][2] = 0.0f - lightPos[2] * planeCoeff[3];
// Fourth Column
destMat[0][3] = 0.0f - lightPos[3] * planeCoeff[0];
destMat[1][3] = 0.0f - lightPos[3] * planeCoeff[1];
destMat[2][3] = 0.0f - lightPos[3] * planeCoeff[2];
destMat[3][3] = dot - lightPos[3] * planeCoeff[3];
} // end makeShadowMatrix
♦ calcNormal
// Points p1, p2, & p3 specified in counter clock-wise order
void calcNormal( float v[3][3], float out[3] )
{
float v1[3],v2[3];
static const int x = 0;
static const int y = 1;
static const int z = 2;
// Calculate two vectors from the three points
v1[x] = v[0][x] - v[1][x];
v1[y] = v[0][y] - v[1][y];
v1[z] = v[0][z] - v[1][z];
v2[x] = v[1][x] - v[2][x];
E.R. Bachmann & P.L. McDowell
MV 4202 Page 31 of 32
OpenGL Lighting
v2[y] = v[1][y] - v[2][y];
v2[z] = v[1][z] - v[2][z];
// Take the cross product of the two vectors to get
// the normal vector which will be stored in out
out[x] = v1[y]*v2[z] - v1[z]*v2[y];
out[y] = v1[z]*v2[x] - v1[x]*v2[z];
out[z] = v1[x]*v2[y] - v1[y]*v2[x];
// Normalize the vector (shorten length to one)
ReduceToUnit(out);
} // end calNormal
♦ ReduceToUnit
// Reduces a normal vector specified as a set of
// three coordinates, to a unit normal vector of length one.
void ReduceToUnit( float vector[3] )
{
float length;
// Calculate the length of the vector
length = (float)sqrt( (vector[0]*vector[0]) +
(vector[1]*vector[1]) +
(vector[2]*vector[2]) );
// Keep the program from blowing up by providing an
// acceptable value for vectors that may evaluate
// close to zero.
if ( length > 0.0f ) {
vector[0] /= length;
vector[1] /= length;
vector[2] /= length;
} // end if
} // end ReduceToUnit
E.R. Bachmann & P.L. McDowell
MV 4202 Page 32 of 32
Download