# Introduction to 3D Game Programming with DirectX 9.0c: A Shader Approach 1598220160, 9781598220162

##### This book presents an introduction to programming interactive computer graphics, with an emphasis on game development, u

267 101 14MB

English Pages 626 [413] Year 2006

00.0 Introduction to 3D Game Programming with DirectX 9.0c - A Shader Approach
Introduction
00.1 Introduction
00.2 Changes from an Earlier Version
00.3 Intended Audience
00.4 Prerequisites
00.5 Required Development Tools and Recommended Hardware
00.6 Use of the D3DX Library
00.7 Using the DirectX SDK Documentation and SDK Samples
00.8 Clarity
00.9 Sample Programs and Online Supplements
Chapter 1 Vector Algebra
01.01 Chapter 1_Vector Algebra - Overview
01.1 Vectors
01.2 Length and Unit Vectors
01.3 The Dot Product
01.4 The Cross Product
01.5 Change of Frame
01.6 Rays Lines and Segments
01.7 D3DX Vectors
01.8 Summary
01.9 Exercises
Chapter 2_Matrix Algebra - Overview
02.1 Definition
02.2 Matrix Multiplication
02.3 The Transpose of a Matrix
02.4 The Identity Matrix
02.5 The Inverse of a Matrix
02.6 D3DX Matrices
02.7 Summary
02.8 Exercises
Chapter 3_Transformations and Planes - Overview
03.1 Linear Transformations
03.2 Affine Transformations
03.3 D3DX Transformation Functions
03.4 Composition of Affine Transformations
03.5 Planes
03.6 Summary
03.7 Exercises
Part II_Direct3D Foundations
04.01 Chapter 4_Direct3D Initialization - Overview
04.1 Direct3D Overview
04.2 Some Preliminaries
04.3 Initializing DirectSD
04.4 Lost Devices
04.5 The Demo Application Framework
04.6 Demo Application_Hello Direct3D
04.7 Debugging Direct3D Applications
04.8 Summary
04.9 Exercises
Chapter 5_Timing Direct Input and Animation and Sprites - Overview
05.1 The Performance Timer
05.2 Direct Input Primer
05.3 Sprites and Animation
05.4 Summary
05.5 Exercises
Chapter 6_The Rendering Pipeline - Overview
06.1 The 3D Illusion
06.2 Model Representation
6.2.3 Indices
06.3 The Virtual Camera
06.4 The Rendering Pipeline
6.4.8 Rasterization
06.5 Summary
06.6 Exercises
Chapter 7_Drawing in Direct3D - Part I - Overview
07.1 Vertex_Index Buffers
07.2 Drawing Methods
07.3 Drawing Preparations
7.3.3 Setting the Vertex Declaration
07.4 Cube Demo
07.5 Summary
07.6 Exercises
Chapter 8_Drawing in Direct3D - Part II - Overview
08.2 Shaders and the FX Framework
8.2.4 Creating an Effect
08.3 Applying the Effect
08.4 Triangle Grid Demo
08.5 D3DX Geometric Objects
08.6 Summary
08.7 Exercises
Chapter 9_Color - Overview
09.1 Color Representation
09.2 Vertex Colors
09.3 Color Cube Demo
09.4 Digression_Traveling Sine Waves
09.5 Colored Waves Demo
09.6 Summary
09.7 Exercises
Chapter 10_Lighting - Overview
10.1 Light and Material Interaction
10.2 Diffuse Lighting
10.2.4.4 The Pixel Shader and Technique
10.3 Ambient Lighting
10.4 Specular Lighting
10.5 Point Lights
10.6 Spotlights
10.7 Attenuation
10.8 The Point Light Demo
10.9 The Spotlight Demo
10.11 Summary
10.12 Exercises
Chapter 11_Texturing - Overview
11.1 Texture Coordinates
11.2 Creating and Enabling a Texture
11.3 Filters
11.4 Mipmaps
11.5 Crate Demo
11.7 Tiled Ground Demo
11.8 Multi-texturing
11.9 Spherical and Cylindrical Texturing
11.10 Texture Animation
11.11 Compressed Textures and the DXTex Tool
11.12 Summary
11.13 Exercises
Chapter 12_Blending - Overview
12.1 The Blending Equation
12.2 Blend Factors
12.3 Transparent Teapot Demo
12.4 Transparent Teapot Demo with Texture Alpha Channel
12.5 The Alpha Test
12.6 Summary
12.7 Exercises
Chapter 13_Stenciling - Overview
13.1 Using the Stencil Buffer
13.2 Mirror Demo
13.4 Summary
13.5 Exercises
Chapter 14_Meshes - Overview
14.1 Geometry Info
14.2 Subsets and the Attribute Buffer
14.3 Drawing
14.5 Optimizing
14.6 The Attribute Table
14.7 Cloning
14.8 Creating a Mesh (DSDXCreateMesh)
14.9 .X Files
14.10 Bounding Volumes
14.11 Survey of Other D3DX Mesh Functions
14.12 Summary
14.13 Exercises
Chapter 15_Mesh Hierarchy Animation Part I - Rigid Meshes - Overview
15.1 Robot Arm Demo
15.2 Solar System Demo
15.3 Keyframes and Animation
15.4 Summary
15.5 Exercises
Chapter 16
Mesh Hierarchy Animation Part II - Skinned Meshes - Overview
16.1 Overview of Skinned Meshes
16.2 Skinned Mesh Demo
16.3 Summary
16.4 Exercises
Chapter 17_Terrain Rendering - Part I - Overview
17.1 Heightmaps
17.2 Basic Terrain Demo
17.3 Multi-Sub-Grid Terrain
17.4 Building a Flexible Camera
17.5 "Walking" on the Terrain
17.6 Summary
17.7 Exercises
Chapter 18_Terrain Rendering - Part II - Overview
18.1 Sub-Grid Culling and Sorting
18.2 Trees and Castle
18.3 Fog
18.4 Grass
18.5 Water
18.6 Summary
18.7 Exercises
Chapter 19_Particle Systems
19.1 Particles and Point Sprites
19.2 Particle System Framework
19.3 Example 1_Fire Ring
19.4 Example 2_Rain
19.5 Example 3_Sprinkler
19.6 Example 4_Bolt Gun
19.7 Summary
19.8 Exercises
Chapter 20_Picking
20.1 Screen to Projection Window Transform
20.2 World Space Picking Ray
20.3 Ray_Object Intersection Tests
20.4 Tri-Pick Demo
20.5 Asteroids Demo
20.6 Summary
20.7 Exercises
Chapter 21_Advanced Texturing - Part I - Overview
21.1 Cube Mapping
21.2 Normal Mapping
21.3 Render to Texture
21.4 Summary
21.5 Exercises
Chapter 22_Advanced Texturing - Part II - Overview
22.1 Projective Texturing
22.3 Displacement Mapping
22.4 Summary
22.5 Exercises
Appendix A_Introduction to Windows Programming - Highlights
23.1 Appendix A_Introduction to Windows Programming - Overview
24 Appendix A_Introduction to Windows Programming - A Better Message Loop
24 Appendix A_Introduction to Windows Programming - Explaining Hello World
24 Appendix A_Introduction to Windows Programming - Hello World Windows Application
24 Appendix A_Introduction to Windows Programming - Summary
24 Appendix B_High-Level Shading Language Reference - Keywords and Operators
24 Appendix B_High-Level Shading Language Reference - Program Flow
24 Appendix B_High-Level Shading Language Reference - User Defined Functions
24 Appendix B_High-Level Shading Language Reference - Variable Types
24 Part III_Applied Direct3D and the D3DX Library
References
##### Citation preview

1

2

3

Changes from an Earlier Version This update to the author's Introduction to 3D Game Programming with DirectX 9.0 has been rewritten almost from scratch. This book largely abandons the fixed pipeline used in the earlier version to give a complete programmable, or shader, approach. From Chapter 8 onward, we are transforming, lighting, and coloring vertices and pixels in vertex and pixel shaders. This significant revision in approach reflects the fact that the fixed pipeline will not exist in DirectX 10. Another key feature is the inclusion of end of chapter exercises. The exercises serve three purposes: first, to test the reader's understanding of each chapter's contents; second, to provide the reader with Direct3D programming experience; and third, to extend the chapter's topics by asking the reader to investigate new ideas on his or her own. In many cases, the exercises are not of the "plug and chug" type, but require the reader to determine how to apply the chapter's topics to the particular assignment. Readers are encouraged to complete chapter exercises before moving on to the next chapter.

4

Intended Audience This book was designed with the following three audiences in mind: Intermediate level C++ programmers who would like an introduction to 3D programming using the latest iteration of Direct3D — Direct3D 9.0. 3D programmers experienced with an API other than DirectX (e.g., OpenGL) who would like an introduction to Direct3D 9.0. Experienced fixed-function Direct3D programmers who would like to take a shader approach.

5

Prerequisites It should be emphasized that this is an introduction to Direct3D, shader, and game programming; it is not an introduction to general computer programming. The reader should satisfy the following prerequisites: General knowledge of high school mathematics: algebra, trigonometry, and (mathematical) functions, for example. Competent with Visual Studio: should know how to create projects, add files, and specify external libraries to link, for example. Intermediate C++ and data structure skills: comfortable with pointers, arrays, operator overloading, linked lists, inheritance and polymorphism, for example. We also use a small subset of the STL, in particular, std::string, std::vector, and std::list. Familiarity with Windows programming with the Win32 API is helpful but not required; we provide a Win32 primer in Appendix A.

6

Step-by-step instructions for setting up a DirectX project in Visual Studio .NET 2002 and Visual Studio .NET 2005 are provided on this book's website (www.moon-labs.com) and the publisher's website (www.wordware.com/files/dx9c).

7

Use of the D3DX Library Since version 7.0, DirectX has shipped with the D3DX (Direct3D Extension) library. This library provides a set of functions, classes, and interfaces that simplify common 3D graphics-related operations, such as math operations, texture and image operations, mesh operations, and shader operations (e.g., compiling and assembling). That is to say, D3DX contains many features that would be a chore to implement on your own. We use the D3DX library throughout this book because it allows us to focus on more interesting material. For instance, we would rather not spend pages explaining how to load various image formats (such as .bmps and .jpegs) into a Direct3D texture interface when we can do it in a single call to the D3DX function D3DXCeateTextureFromFile. In other words, D3DX makes us more productive and lets us focus more on actual content rather than spending time reinventing the wheel. Other reasons to use D3DX: D3DX is general and can be used with a wide range of different types of 3D applications. D3DX is fast, at least as fast as general functionality can be. Other developers use D3DX; therefore, you will most likely encounter code that uses D3DX. Consequently, whether you choose to use D3DX or not, you should become familiar with it so that you can read code that uses it. D3DX already exists and has been thoroughly tested. Furthermore, it becomes more improved and feature rich with each iteration of DirectX.

8

Using the DirectX SDK Documentation and SDK Samples Direct3D is a huge API and we cannot hope to cover all of its details in this one book. Therefore, to obtain extended information it is imperative that you learn how to use the DirectX SDK documentation. You can launch the C++ DirectX online documentation by executing the DirectX9_c file in the \DirectX SDK\Documentation\DirectX9 directory, where DirectX SDK is the directory to which you installed DirectX. The DirectX documentation covers just about every part of the DirectX API; therefore, it is very useful as a reference, but because the documentation doesn't go into much depth and assumes some previous knowledge, it isn't the best learning tool. However, it does get better and better with every new DirectX version released. As said, the documentation is primarily useful as a reference. Suppose you come across a DirectX-related type or function that you would like more information on (e.g., D3DXMatrixInverse). You simply do a search in the documentation index and you get a description of the object type or, in this case, function, as shown in Figure 1.

Figure 1: The C++ SDK documentation viewer. Note In this book we may direct you to the documentation for further details from time to time. The SDK documentation also contains some introductory tutorials at the URL \directx9_c.chm::/dx9_graphics_tutorials_and_samples.htm. These tutorials correspond to some of the topics in the first part of this book. We recommend that you study these tutorials at the same time you read through Part I so that you can get alternative explanations and examples. We would also like to point out the available Direct3D sample programs that ship with the DirectX SDK. The C++ Direct3D samples are located in the DirectX SDK\C++\Direct3D directory. Each sample illustrates how to implement a particular effect in Direct3D. These samples are fairly advanced for a beginning graphics programmer, but by the end of this book you should be ready to study them. Examination of the samples is a good "next step" after finishing this book.

9

Clarity We want to emphasis that the program samples for this book were written with clarity in mind and not performance. Thus, many of the samples may be implemented inefficiently. Keep this in mind if you are using any of the sample code in your own projects, as you may wish to rework it for better efficiency.

10

Sample Programs and Online Supplements The website for this book (www.moon-labs.com) plays an integral part in getting the most out of this book. On the website you will find the complete source code and project files for every sample in this book. In many cases, DirectX programs are too large to fully embed in a textbook; therefore, we only embed relevant code fragments based on the ideas being shown. It is highly recommended that the reader study the corresponding demo code to see the program in its entirety. (We have aimed to make the demos small and focused for easy study.) As a general rule, the reader should be able to implement a chapter's demo(s) on his or her own after reading the chapter and spending some time studying the demo code. In fact, a good exercise is trying to implement the samples on your own using the book and sample code as a reference. In addition to sample programs, the website also contains a message board. We encourage readers to communicate with each other and post questions on topics they do not understand or need clarification on. In many cases, getting alternative perspectives and explanations on a concept shortens the time it takes to comprehend it. And lastly, the website will contain additional program samples and tutorials on topics that we could not fit into this book for one reason or another. The companion files can also be downloaded from www.wordware.com/files/dx9c.

11

Part I: Mathematical Prerequisites Chapter List Chapter 1: Vector Algebra Chapter 2: Matrix Algebra Chapter 3: Transformations and Planes

Part Overview Video games attempt to simulate a virtual world; however, computers, by their very nature, crunch numbers. Thus the problem of how to convey a world to a computer arises. The answer is to describe our worlds, and the interactions therein, completely mathematically. Consequently, mathematics plays a fundamental role in video game development. In this prerequisites part, we introduce the mathematical tools that will be used throughout this book. The emphasis is on vectors, coordinate systems, matrices, and transformations, as these tools are used in just about every sample program of this book. In addition to the mathematical explanations, a survey and demonstration of the relevant classes and functions from the D3DX math library are provided. Note that the topics covered here are only those essential to understanding the rest of this book; it is by no means a comprehensive treatment of video game mathematics, as entire books are devoted to this topic. For readers desiring a more complete reference to video game mathematics, we recommend [Verth04] and [Lengyel02]. Chapter 1, "Vector Algebra" Vectors are, perhaps, the most fundamental mathematical objects used in computer games. We use vectors to represent positions, displacements, directions, velocities, and forces, for example. In this chapter, we study vectors and the operations used to manipulate them. Chapter 2, "Matrix Algebra" Matrices provide an efficient and compact way of representing transformations. In this chapter, we become familiar with matrices and the operations defined on them. Chapter 3, "Transformations and Planes" This chapter examines three fundamental geometric transformations: scaling, rotation, and translation. We use these transformations to manipulate 3D objects in space. In addition, a brief primer on 3D planes is provided; planes are useful for dividing and sorting 3D space.

12

Chapter 1: Vector Algebra Overview Vectors play a crucial role in computer graphics, collision detection, and physical simulation, all of which are common components in contemporary video games. Our approach here is informal and practical; for a more theoretical development, see [Schneider03]. We emphasize the importance of vectors by noting that they are used in just about every demo program in this book. Objectives: To develop an understanding of vectors, their geometry, and the operations defined on them. To learn how we can convert the coordinates of points and vectors from one coordinate system to another. To find out how vectors can be used to analytically describe other geometric objects such as rays, lines, and line segments. To become familiar with a subset of classes and functions provided by the D3DX library that are used for vector mathematics.

13

1.1 Vectors A vector refers to a quantity that possesses both magnitude and direction. Quantities that possess both magnitude and direction are called vector-valued quantities. Examples of vector-valued quantities are forces (a force is applied in a particular direction with a certain strength — magnitude), displacements (the net direction and distance a particle moved), and velocities (speed and direction). Thus, vectors are used to represent forces, displacements, and velocities. In addition, we also use vectors to specify pure directions, such as the direction the player is looking in a 3D game, the direction a polygon is facing, the direction in which a ray of light travels, or the direction in which a ray of light reflects off a surface. A first step in characterizing a vector mathematically is geometrically: We graphically specify a vector by a directed line segment (see Figure 1.1), where the length denotes the magnitude of the vector and the aim denotes the direction of the vector. We note that the location in which we draw a vector is immaterial because changing the location does not change the magnitude or direction. Consequently, two vectors are equal if and only if they have the same length and point in the same direction. Thus, the vectors and shown in Figure 1.1 are actually equal, that is , because they have the same length and point in the same direction. In fact, because location is unimportant for vectors, we can always translate a vector without changing its meaning (since a translation changes neither length nor direction). Observe that we could translate hence their equality.

Figure 1.1: Vectors drawn on a 2D plane. Note other.

such that it completely overlaps with

(and conversely), thereby making them indistinguishable —

; since they point in the same direction and have the same length, they are translations of each

1.1.1 Vectors and Coordinate Systems We could now define useful geometric operations on vectors, which can then be used to solve problems involving vector-valued quantities. However, since the computer cannot work with vectors geometrically, we need to find a way of specifying vectors numerically instead. So what we do is introduce a 3D coordinate system in space, and translate all the vectors so that their tails coincide with the origin (Figure 1.2). Then we can identify a vector by specifying the coordinates of its head, and write

= (x, y, z) as shown in Figure 1.3. Now we can represent a vector with three floats in a computer program.

Figure 1.2: Because translate

and

have the same length and point in the same direction (they are parallel), we say

such that it completely coincides with

, and observe that we can

. When a vector's tail coincides with the origin, we say that it is in standard position.

14

Figure 1.3: A vector specified by coordinates relative to a coordinate system. Consider Figure 1.4, which shows a vector and two frames in space. (Note that we use the terms frame, frame of reference, space, and coordinate system to all mean the same thing in this book.) We can translate

so that it is in standard position in either of the two frames. Observe, however, that the coordinates of the

vector differ based on the frame relative to which the vector is described. In other words, the same vector frames.

Figure 1.4: The same vector

has a different coordinate representation for distinct

has different coordinates when described relative to different frames.

The idea is analogous to, say, temperature. Water boils at Celsius or Fahrenheit. The physical temperature of boiling water is the same no matter the scale (i.e., we can't lower the boiling point by picking a different scale), but we assign a different scalar number to the temperature based on the scale we use. Similarly, for a vector, its direction and magnitude, which are embedded in the directed line segment, do not change, only the coordinates of it change based on the frame of reference we use to describe it. For example, wind blows in a particular direction and at some speed. We can measure the wind speed and direction relative to different frames of reference. For each distinct frame, we record different measurements. Nevertheless, the measurements are describing the same vector; that is, the frame of reference we pick cannot physically change the direction in which the wind blows nor does it change the magnitude of the wind. This is important because it means whenever we identify a vector by coordinates, those coordinates are relative to some frame of reference. Often, we will utilize more than one frame of reference and, therefore, will need to keep track of which frame the coordinates of a vector are described relative to; additionally, we will need to know how to convert vector coordinates from one frame to another (§1.5 shows how this conversion is done). Note We see that both vectors and points can be described by coordinates (x, y, z) relative to a frame. However, they are not the same; a point represents a location in 3-space, whereas a vector represents a magnitude and direction.

1.1.2 Left-Handed Versus Right-Handed Coordinate Systems DirectSD uses a so-called left-handed coordinate system. If you take your left hand and aim your fingers down the positive x-axis, and then curl your fingers toward the positive y-axis, your thumb points roughly in the direction of the positive z-axis. Figure 1.5 illustrates the differences between left-handed and right-handed coordinate systems.

Figure 1.5: On the left we have a left-handed coordinate system. Observe that the positive z-axis goes into the page. On the right we have a right-handed coordinate system. Observe that the positive z-axis comes out of the page. Observe that for the right-handed coordinate system, if you take your right hand and aim your fingers down the positive x-axis, and then curl your fingers toward the positive y -axis, your thumb points roughly in the direction of the positive z-axis.

1.1.3 Basic Vector Operations We now define equality, addition, scalar multiplication, and subtraction on vectors using the coordinate representation.

Two vectors are equal if and only if their corresponding components are equal. Let only if u x = vx , u y = vy , and u z = vz .

= (u x , u y , u z ) and

= (vx , vy , vz ). Then

if and

15 We add vectors component wise; as such, it only makes sense to add vectors of the same dimension. Let Then

= (u x , u y , u z ) and

= (vx , vy , vz ).

.

We can multiply a scalar (i.e., a real number) and a vector, and the result is a vector. Let k be a scalar, and let ku y , ku z ). This is called scalar multiplication.

= (u x , u y , u z ), then

We define subtraction in terms of vector addition and scalar multiplication. That is,

= (ku x ,

.

Example 1.1

Let

= (1,2,3),

= (1,2,3),

= (3,0,-2), and k = 2. Then,

;

Clearly,

;

; = 2(3,0,-2) = (6,0,-4).

The difference in the third line illustrates a special vector, called the zero-vector, which has zeros for all of its components and is denoted by

.

Note When comparing floating-point numbers, care must be taken due to floating-point imprecision. Two floating-point numbers that we expect to be equal may differ slightly, and therefore we test to see if they are approximately equal. We do this by defining an EPSILON constant, which is a very small value we use as a "buffer." We say two values are approximately equal if their distance is less than EPSILON. In other words, EPSILON gives us some tolerance for floatingpoint imprecision. The following function illustrates how EPSILON can be used to test if two floating-point values are equal: const float EPSILON = 0.001f; bool Equals(float lhs, float rhs) { // if lhs == rhs their difference should be zero return fabs(lhs - rhs) < EPSILON ? true : false; }

Example 1.2 We'll illustrate this example with 2D vectors to make the drawings simpler. The ideas are the same as in 3D; we just work with one less component in 2D.

Let

. How do

and

compare geometrically? We note

= (-1, -1/2). Graphing both

and

(Figure 1.6a), we notice that is in the direction directly opposite of and its length is 1/2 that of . Thus, geometrically, negating a vector can be thought of as "flipping" its direction, and scalar multiplication can be thought of as scaling the length of the vector.

Let

) and

parallel translate

. Then

. Figure 1.6b shows what vector addition means geometrically: We

so that its tail coincides with the head of

. (Note that we could have just as well translated

. Then, the sum is the vector originating at the tail of

so that its tail coincided with the head of

, then

and ending at the head of would be the vector

originating at the tail of and ending at the head of .) Observe also that our rules of vector addition agree with what we would intuitively expect to happen physically when we add forces together to produce a net force: If we add two forces (vectors) in the same direction, we get another stronger force (longer vector) in that direction. If we add two forces (vectors) in opposition to each other, then we get a weaker net force (shorter vector).

Let

and

Essentially, the difference then

. Then

. Figure 1.6c shows what vector subtraction means geometrically.

gives us a vector aimed from the head of

gives us a vector aimed from the point

one point to another. Observe also that the length of

to the point

and

as points,

; this interpretation is important as we will often want the vector aimed from

is the distance from

to

.

16

Figure 1.6: (a) The geometric interpretation of scalar multiplication. (b) The geometric interpretation of vector addition. (c) The geometric interpretation of vector subtraction.

17

1.2 Length and Unit Vectors Geometrically, the magnitude of a vector is the length of the directed line segment. We denote the magnitude of a vector by double vertical bars (e.g.,

denotes

the magnitude of ). Now, given a vector = (x, y, z), we wish to compute its magnitude algebraically. The magnitude of a 3D vector can be computed by applying the Pythagorean theorem twice; see Figure 1.7.

Figure 1.7: The 3D length of a vector can be computed by applying the Pythagorean theorem twice.

First, we look at the triangle in the xz-plane with sides x, z, and hypotenuse a. From the Pythagorean theorem, we have

triangle with sides a, y, and hypotenuse

. Now look at the

. From the Pythagorean theorem again, we arrive at the following magnitude formula:

(1.1)

For some applications, we do not care about the length of the vector because we want to use a vector to represent a pure direction. For such direction-only vectors, we want the length of the vector to be exactly one. When we make a vector unit length, we say that we are normalizing the vector. We can normalize a vector by dividing each of its components by its magnitude: (1.2)

Example 1.3

Normalize the vector

To verify that

= (-1, 3, 4). We have

is indeed a unit vector, we compute its length:

. Thus,

18

1.3 The Dot Product The dot product is a form of vector multiplication that results in a scalar value; for this reason, it is sometimes referred to as the scalar product. Let u z ) and

= (u x , u y ,

= (vx , vy , vz ); then the dot product is defined as follows:

(1.3)

In words, the dot product is the sum of the products of the individual components. The dot product definition does not present an obvious geometric meaning. Using the law of cosines, we can find the relationship (1.4)

Equation 1.4 says that the dot product between two vectors is the cosine of the angle between them scaled by the vectors' magnitudes. Thus, if both are unit vectors, then

is the cosine of the angle between them (i.e.,

).

Equation 1.4 provides us with some useful geometric properties of the dot product: If

If

If

, then

, then

, then

(i.e., the vectors are orthogonal).

(i.e., the vectors are parallel) and both

(i.e., the vectors are parallel) and

and

and

point in opposite directions.

If

, then the angle θ between the two vectors is less than 90 degrees (i.e., the vectors make an acute angle).

If

, then the angle θ between the two vectors is greater than 90 degrees (i.e., the vectors make an obtuse angle).

Note The term "orthogonal" can be used as a synonym for "perpendicular." Example 1.4

Let

point in the same direction.

= (l, 2, 3) and

= (-4, 0, -1). Find the angle between

Applying Equvation 1.4 tells us that

We can solve for thera using the trig arccosine function:

Example 1.5

and

. First observe that

and

19 Consider Figure 1.8. Given

and the unit vector

Figure 1.8: The orthogonal projection of

First, observe from the figure that since

the orthogonal projection of

on

using the dot product.

.

is a unit vector, we have

; therefore,

We call

, find a formula for

. Thus we must determine k. Using trigonometry, we know that

. However, because

on

. If we interpret

as a force,

. If

is not of unit length, we can always normalize it first to make it unit length.

is a unit vector, we can say this in another way:

can be thought of as the portion of the force

that acts in the direction

20

1.4 The Cross Product The second form of multiplication vector math defines is the cross product. Unlike the dot product, which evaluates to a scalar, the cross product evaluates to another vector. Taking the cross product of two 3D vectors, is orthogonal to

, and

is orthogonal to

and

, yields another vector,

; see Figure 1.9. If

, that is mutually orthogonal to

= (u x , u y , u z ) and

and

. By that we mean

= (vx ,vy , vz ), then the cross product is computed like so:

(1.5)

Figure 1.9: The cross product of two 3D vectors,

and

hand and aim the fingers in the direction of the first vector points in the direction of

, yields another vector,

, that is mutually orthogonal to

, and then curl your fingers toward

and

. If you take your left

along an angle 0 = θ = p , then your thumb roughly

; this is called the left-hand-thumb rule.

Example 1.6

Let to

= (2, 1, 3) and

= (2, 0, 0). Compute

and

, and then verify that

is orthogonal to

and that

is orthogonal

. Applying formula 1.5 we have,

and

This result makes one thing clear, generally speaking:

Therefore, we say that the cross product is anti-commutative. In fact, it can be

shown that . You can determine the vector returned by the cross product by the left-hand-thumb rule. If you curve the fingers of your left hand from the direction of the first vector toward the second vector (always take the path with the smallest angle), your thumb points in the direction of the returned vector, as shown in Figure 1.9.

To show that is orthogonal to orthogonal). Because

and that

is orthogonal to

, we recall from §1.3 that if

and

we conclude that

is orthogonal to

and that

is orthogonal to

.

, then

(i.e., the vectors are

21

1.5 Change of Frame Suppose that the scalar 100° C represents the temperature of boiling water relative to the Celsius scale. How do we describe the same temperature of boiling water relative to the Fahrenheit scale? In other words, what is the scalar, relative to the Fahrenheit scale, that represents the temperature of boiling water? To make this conversion (or change of frame), we need to know how the Celsius and Fahrenheit scales relate. They are related as follows: Therefore, T F =

.

(100°)+32°=212°. That is, the temperature of boiling water is 212° Fahrenheit.

This simple example illustrates that we can convert a scalar k that describes some quantity relative to a frame A into a new scalar k' that describes the same quantity relative to a different frame B, provided that we know how frame A and B are related. In this section, we look at a similar problem, but instead of scalars, we are interested in how to convert vector coordinates from one frame to another.

1.5.1 Vectors

Consider Figure 1.10 in which we have two frames, A and B, and a vector, by coordinates relative to frame A, and let us write

. To avoid ambiguity, let us write when we are specifying

when we are specifying by coordinates relative to frame B. Now, suppose

we are given . How do we find In other words, given the coordinates identifying a vector relative to one frame, how do we find the coordinates that identify the same vector relative to a different frame?

Figure 1.10: Two frames, A and B, and a vector,

. The same vector

has different coordinates relative to the two frames.

First, because we are talking about vectors in which location does not matter, we translate the coordinate systems so that their origins coincide as shown in Figure 1.11. Now let and Then from Figure 1.11, we see that

be unit vectors relative to frame B, which aim, respectively, along the x- and y-axes of frame A.

22

Figure 1.11: The geometry of identifying

relative to frame B.

Note the relationship between the two frames that allowed us to do this conversion: The relationship was that we described the axes of frame A relative to frame B with the vectors

and

. Thus, if we are given

Generalizing to 3D, if = (x, y, z), then frame A relative to frame B.

and we know the vectors

and

, where

, then we can always find

,

, and

.

describe the x-, y-, and z-axes of

We call the process of converting the coordinates that describe a vector relative to a frame A into new coordinates that describe the same vector relative to frame B a change of frame or change of coordinates transformation. Note The vectors

,

, and

actually do not need to be unit vectors. If they are not, it means that the two coordinate systems also differ in scale (in

addition to orientation and position). For example, if frame A used meters and frame B used centimeters, then magnitudes of 100 centimeters since there are 100 centimeters per meter.

,

, and

would have

Note The coordinate system chosen is somewhat arbitrary; however, picking a convenient coordinate system can sometimes make a problem easier. In other words, the geometry might have simpler coordinates in one coordinate system and more complex coordinates in another. Moreover, it is sometimes useful to use multiple coordinate systems. For example, we may want an answer in coordinate system A, but the problem is solved more easily in coordinate system B. In this case, we convert from A to B, solve the problem in B, and then convert back to A to give the answer.

1.5.2 Points We can also use a vector to represent a 3D location in space; we call this a position vector or point. In this case, the location of the tip of the vector (when the vector is in standard position; see §1.1.1) is the characteristic of interest, not the direction and magnitude. Since location is important for points, we cannot just translate the coordinate systems like we did in the previous section; this makes the change of frame transformation for points slightly different.

If

represents a point

relative to frame A, how do we describe the same point relative to frame B? In other words, what is

From Figure 1.12, we see that

23

Figure 1.12: The geometry of identifying point

where

relative to frame B.

= (Ox , Oy ) describes the origin of frame A relative to frame B, and

frame B. In 3D, if

= (x, y, z), then

= (u x , u y ) and

= (vx , vy ) describe the x- and y-axes of frame A relative to .

24

1.6 Rays, Lines, and Segments Suppose a player in a game we are working on fires his gun at an enemy. How would we determine whether the bullet starting from a particular position and aimed in a direction hit the target? One approach would be to model the bullet with a ray and model the enemy with a bounding sphere. (A bounding sphere is simply a sphere that tightly surrounds an object, thus roughly approximating its volume.) Then mathematically we can determine whether the ray hit the sphere and where. In this section we learn how to model rays mathematically. A ray can be described with an origin and a direction, as shown in Figure 1.13. The parametric equation of a ray is:

Figure 1.13: A ray described by an origin to zero.

and direction

. We can generate points on the ray by plugging in scalars for t that are greater than or equal

where is the origin of the ray, is a vector specifying the direction of the ray (not necessarily of unit length), and t is the parameter. By plugging in different values for t we obtain different points on the ray. The parameter t must be in the interval [0, 8) to describe a ray. Values less than zero will generate points behind the ray (i.e., on the line that coincides with the ray). In fact, if we let t ∈ (- 8, 8), then we have a line in 3-space.

Now suppose we wish to define a line segment by the points

and

. We first construct a vector

Figure 1.14. Then, for t ∈[0,1], the graph of the equation is the line segment defined by range t ∈[0,1], then you get a point on the line that coincides with the segment but which is not on the segment.

from and

to

, as shown in

. Note that if you go outside the

Figure 1.14: We generate points on the line segment by plugging in different values for t in [0,1]. For example, the midpoint of the line segment is given at t = ½. Also note that if t = 0, we get

, and if t = 1, we get

.

25

1.7 D3DX Vectors In this section, we spend some time becoming familiar with the D3DXVECTOR3 class, which is the class we often use to store the coordinates of both points and vectors in code relative to some coordinate system. Its class definition is: typedef struct D3DXVECTOR3 : public D3DVECTOR { public: D3DXVECTOR3() {}; D3DXVECTOR3( CONST FLOAT * ); D3DXVECTOR3( CONST D3DVECTOR& ); D3DXVECTOR3( CONST D3DXFLOAT16 * ); D3DXVECTOR3( FLOAT x, FLOAT y, FLOAT z ); // casting operator FLOAT* (); operator CONST FLOAT* () const; // assignment operators D3DXVECTOR3& operator += D3DXVECTOR3& operator -= D3DXVECTOR3& operator *= D3DXVECTOR3& operator /=

( ( ( (

CONST CONST FLOAT FLOAT

D3DXVECTOR3& ); D3DXVECTOR3& ); ); );

// unary operators D3DXVECTOR3 operator + () const; D3DXVECTOR3 operator - () const; // binary operators D3DXVECTOR3 operator D3DXVECTOR3 operator D3DXVECTOR3 operator D3DXVECTOR3 operator

+ * /

( ( ( (

CONST CONST FLOAT FLOAT

D3DXVECTOR3& ) const; D3DXVECTOR3& ) const; ) const; ) const;

friend D3DXVECTOR3 operator * (FLOAT, CONST struct D3DXVECTOR3& ); BOOL operator == ( CONST D3DXVECTOR3& ) const; BOOL operator != ( CONST D3DXVECTOR3& ) const; } D3DXVECTOR3, *LPD3DXVECTOR3; Note that D3DXVECTOR3 inherits its coordinate data from D3DVECTOR , which is defined as: typedef struct _D3DVECTOR { float x; float y; float z; } D3DVECTOR; In addition to the above class, the D3DX library includes the following useful functions for computing the length of a vector, normalizing a vector, computing the dot product of two vectors, and computing the cross product of two vectors.

FLOAT D3DXVec3Length(

// Returns

CONST D3DXVECTOR3 *pV);

// Input

D3DXVECTOR3* D3DXVec3Normalize(

D3DXVECTOR3 *pout,

// Outputs

CONST D3DXVECTOR3 *pV);

// Input

FLOAT D3DXVec3Dot( CONST D3DXVECTOR3 *pV1,

// Outputs // Input

CONST D3DXVECTOR3 *pV2); // Input D3DXVECTOR3 *D3DXVec3Cross( D3DXVECTOR3 *pout,

// Outputs

CONST D3DXVECTOR3 *pV1,

// Input

CONST D3DXVECTOR3 *pV2); // Input Note Remember to link the d3dx9.lib library file with your application to use any D3DX code; moreover, you will also need to #include . The following short code provides some examples on how to use the D3DXVECTOR3 class and the four functions mentioned above. #include #include using namespace std; // Overload the "