Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 60 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
60
Dung lượng
0,9 MB
Nội dung
Vector2::Vector2( double x, double y ) { Set( x, y ); } Vector2::Vector2( int x, int y ) { Set((double)x,(double)y); } Vector2::Vector2(const D3DXVECTOR2& dv) { x=dv.x; y=dv.y; } Vector2::Vector2(const D3DXVECTOR3& dv) { x=dv.x; y=dv.y; } Vector2& Vector2::operator=( const Vector2& V) { Set( V ); return *this; } void Vector2::Set( double x1,double y1 ) { x=x1; y=y1; } void Vector2::Set( const Vector2& V) { x=V.x; y=V.y; } void Vector2::Move( double mx,double my ) { x+=mx; y+=my; } 160 Chapter 7 n Vectors and Matrices Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com void Vector2::operator+=(const Vector2& V) { x+=V.x; y+=V.y; } void Vector2::operator-=(const Vector2& V) { x-=V.x; y-=V.y; } void Vector2::operator*=(const Vector2& V) { x*=V.x; y*=V.y; } void Vector2::operator/=(const Vector2& V) { x/=V.x; y/=V.y; } Vector2 Vector2::operator/(const double& d) { Vector2 v( x/d, y/d ); return v; } //equality operator comparison includes double rounding bool Vector2::operator==( const Vector2& V ) const { return ( (((V.x - 0.0001f) < x) && (x < (V.x + 0.0001f))) && (((V.y - 0.0001f) < y) && (y < (V.y + 0.0001f))) ); } //inequality operator bool Vector2::operator!=( const Vector2& V ) const { return (!(*this == V)); } Vectors and Points 161 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com D3DXVECTOR3 Vector2::ToD3DXVECTOR3() { return D3DXVECTOR3( (float)x, (float)y, 0.0f ); } D3DXVECTOR2 Vector2::ToD3DXVECTOR2() { return D3DXVECTOR2( (float)x, (float)y ); } Vector3 Class Also found in the Vector.h file is the Vector3 class interface: class Vector3 { public: double x, y, z; virtual ~Vector3() {} Vector3(); Vector3(const Vector3& V); Vector3(double x, double y, double z); Vector3(int x, int y, int z); Vector3(const D3DXVECTOR2& dv); Vector3(const D3DXVECTOR3& dv); Vector3& operator=( const Vector3& V); //manipulation functions void Set(double x1,double y1,double z1); void Set(const Vector3& V); double getX() { return x; } void setX(double value) { x = value; } double getY() { return y; } void setY(double value) { y = value; } double getZ() { return z; } void setZ(double value) { z = value; } void Move( double mx,double my,double mz); void operator+=(const Vector3& V); void operator-=(const Vector3& V); void operator*=(const Vector3& V); 162 Chapter 7 n Vectors and Matrices Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com void operator/=(const Vector3& V); Vector3 operator/(const double& d); bool operator==( const Vector3& V ) const; bool operator!=( const Vector3& V ) const; //exporters to Direct3D vectors D3DXVECTOR3 ToD3DXVECTOR3(); D3DXVECTOR2 ToD3DXVECTOR2(); }; Also in the Vector.cpp source code file is the Vector3 class implementation: Vector3::Vector3() { x=y=z=0; } Vector3::Vector3( const Vector3& V ) { *this = V; } Vector3::Vector3( double x, double y, double z ) { Set( x, y, z ); } Vector3::Vector3( int x, int y, int z) { Set((double)x,(double)y,(double)z); } Vector3::Vector3(const D3DXVECTOR2& dv) { x=dv.x; y=dv.y; z=0.0; } Vector3::Vector3(const D3DXVECTOR3& dv) { x=dv.x; y=dv.y; z=dv.z; } Vectors and Points 163 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com //assignment operator Vector3& Vector3::operator=( const Vector3& V) { Set(V); return *this; } void Vector3::Set( double x1,double y1,double z1 ) { x=x1; y=y1; z=z1; } void Vector3::Set( const Vector3& V) { x=V.x; y=V.y; z=V.z; } void Vector3::Move( double mx,double my,double mz) { x+=mx; y+=my; z+=mz; } void Vector3::operator+=(const Vector3& V) { x+=V.x; y+=V.y; z+=V.z; } void Vector3::operator-=(const Vector3& V) { x-=V.x; y-=V.y; z-=V.z; } void Vector3::operator*=(const Vector3& V) { x*=V.x; y*=V.y; z*=V.z; } void Vector3::operator/=(const Vector3& V) { x/=V.x; y/=V.y; z/=V.z; } 164 Chapter 7 n Vectors and Matrices Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Vector3 Vector3::operator/(const double& d) { Vector3 v( x/d, y/d, z/d); return v; } //equality operator comparison includes rounding bool Vector3::operator==( const Vector3& V ) const { return ( (((V.x - 0.0001f) < x) && (x < (V.x + 0.0001f))) && (((V.y - 0.0001f) < y) && (y < (V.y + 0.0001f))) && (((V.z - 0.0001f) < z) && (z < (V.z + 0.0001f))) ); } //inequality operator bool Vector3::operator!=( const Vector3& V ) const { return (!(*this == V)); } D3DXVECTOR3 Vector3::ToD3DXVECTOR3() { return D3DXVECTOR3( (float)x, (float)y, (float)z); } D3DXVECTOR2 Vector3::ToD3DXVECTOR2() { return D3DXVECTOR2( (float)x, (float)y ); } Math Functions We’re going to create a new Math class to provide reusable functions for vectors and matrices. The Math class provides reusable functions that could be imple- mented in the other classes ( Vector2, etc.), but we want to define these functions as static and keep the data types as lightweight as possible. The math functions will be overloaded in some cases with various parameters to support both the Math Functions 165 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Vector2 and Vector3 classes and some intrinsic data types. Here are some of the calculations the new Math class will provide: n Distance n Length n Dot product n Cross product n Normal n Radian conversion n Degree conversion n Linear velocity n Angle-to-target vector We’ll gloss over the more mundane (but still very important) functions and jump right into an explanation of the two more valuable ones: linear velocity and angle-to-target vector. Advice I found the following website to be a helpful reference for the math behind computer graphics concepts such as points, lines, vectors, and matrices: http://programmedlessons.org/VectorLessons/ vectorIndex.html. Linear Velocity Have you ever wondered how some shooter-style games are able to fire projectiles (be they bullets, missiles, plasma bolts, phaser beams, or what have you) at any odd angle away from the player’s ship, as well as at any angle from enemy sprites? These projectiles are moving using velocity values (for X and Y) that are based on the object’s direction (or angle) of movement. Given any angle, we can calculate the velocity needed to move in precisely that direction. This applies to aircraft, sea vessels, spacecraft, as well as projectiles, missiles, lasers, plasma bolts, or any other object that needs to move at a given angle (presumably toward a target). 166 Chapter 7 n Vectors and Matrices Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com The X velocity of a game entity can be calculated for any angle, and that value is then multiplied by the speed at which you want the object to move in the given direction. The LinearVelocityX function (below) automatically orients the angle to quadrant four of the Cartesian coordinate system and converts the angle from degrees to radians. Since the cosine function gives us the horizontal value of a point on a circle, we use cosine to calculate the X velocity as if we were drawing a circle based on a small radius. double Math::linearVelocityX(double angle) { angle -= 90; if (angle < 0) angle = 360 + angle; return cos( toRadians( angle )); } Likewise for the Y velocity value, we use the Y position on the edge of a circle (based on radius) for the calculation using the sine function. double Math::linearVelocityY(double angle) { angle -= 90; if (angle < 0) angle = 360 + angle; return sin( toRadians( angle )); } As it turns out, the “velocity” of an object based on an angle—that is, its linear velocity—is simply the same pair of X,Y values that would be calculated when tracing the boundary of a circle (based on a radius). Angle to Target Calculating the angle from one point to another (as in the case where one sprite is targeting another) is extremely useful (if not crucial) in most games. Imagine you are working on a real-time strategy game. You must program the game so that the player can select units with the mouse and right-click a target location where the unit must move to. Even a simple process like that requires a calculation—between the unit’s location and the selected target location in the game. In the space shooter genre, in order to fire at the player’s ship, enemies must be able to face the player to fire in the correct direction. I could provide you with many more examples, but I suspect you get the point. The key to this important need is a calculation that I like to call angle to target. Math Functions 167 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com The calculation is very simple—about as simple as calculating angular velocity, which is much simpler than the Distance function. We need to use another trigonometry function this time: atan2(). This is a standard C math library function that calculates the arctangent of two deltas—first the Y delta, then the X delta. A delta is the difference between two values. For our purposes here, we need to get the delta of both X and Y for two points. For instance, if Point A is located at X1,Y1, and Point B is located at X2,Y2, then we can calculate the delta of the two points like so: deltaX = X2 - X1 deltaY = Y2 - Y1 The atan2() function requires the deltaY first, then the deltaX parameter. Here is the AngleToTarget method as it appears in the Math class: double Math::angleToTarget(double x1, double y1, double x2, double y2) { double deltaX = (x2-x1); double deltaY = (y2-y1); return atan2(deltaY,deltaX); } I have coded an overloaded version of this function so you can pass Vector3 values: double Math::angleToTarget(Vector3& A,Vector3& B) { return angleToTarget(A.getX(),A.getY(),B.getX(),B.getY()); } Math Class Header Here is the header for the Math class with some constants pre-defined for convenience: #pragma once #include "stdafx.h" #include "Vector.h" namespace Octane { const double PI = 3.1415926535; const double PI_over_180 = PI / 180.0f; const double PI_under_180 = 180.0f / PI; 168 Chapter 7 n Vectors and Matrices Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com class Math { public: static double toDegrees(double radian); static double toRadians(double degree); static double wrapAngleDegs(double degs); static double wrapAngleRads(double rads); static double wrapValue(double value, double min, double max); static double Limit(double value, double min, double max); //***addition static double linearVelocityX(double angle); static double linearVelocityY(double angle); static Vector2 linearVelocity(double angle); static double angleToTarget(double x1,double y1,double x2,double y2); static double angleToTarget(Vector3& source,Vector3& target); static double angleToTarget(Vector2& source,Vector2& target); static double Distance(double x1,double y1,double z1, double x2,double y2,double z2); static double Distance(double x1,double y1,double x2,double y2); static double Distance(Vector3& A, Vector3& B); static double Distance(Vector2& A, Vector2& B); static double Length(double x,double y,double z); static double Length(double x,double y); static double Length(Vector3& V); static double Length(Vector2& V); static double dotP roduct(double x1,double y1,double z1,double x2, double y2,double z2); static double dotProduct(double x1,double y1,double x2,double y2); static double dotProduct(Vector3& A, Vector3& B); static double dotProduct(Vector2& A, Vector2& B); static Vector3 crossProduct(double x1,double y1,double z1,double x2, double y2,double z2); static Vector3 crossProduct(Vector3& A, Vector3& B); static Vector3 Normal(double x,double y,double z); static Vector3 Normal(Vector3& V); }; }; Math Class Implementation Now we can go over the code for the Math implementation file. The Math class includes the angular velocity and angle-to-target functions, which I will explain in detail in subsequent sections of the chapter. Math Functions 169 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... DirectX SDK defines a D3DMATRIX struct in the d3dx9math.h header file like so: typedef struct _D3DMATRIX union { struct { float float float float { _11, _21, _31, _41 , _12, _22, _32, _42 , _13, _23, _33, _43 , _ 14; _ 24; _ 34; _44 ; }; float m [4] [4] ; }; } D3DMATRIX; This is the base struct for handling matrices in Direct3D Another data type called D3DXMATRIX extends D3DMATRIX by adding calculations with overloaded... overloaded constructors, including this one: D3DXMATRIX( FLOAT _11, FLOAT _21, FLOAT _31, FLOAT _41 , FLOAT FLOAT FLOAT FLOAT _12, _22, _32, _42 , FLOAT FLOAT FLOAT FLOAT _13, _23, _33, _43 , FLOAT FLOAT FLOAT FLOAT _ 14, _ 24, _ 34, _44 ); Using this D3DXMATRIX constructor with your own Matrix class, as well as the float m [4] [4] array and the individual float properties _11, _12, _13, etc., it’s entirely possible... CONST FLOAT * ); D3DXMATRIX( CONST D3DMATRIX& ); D3DXMATRIX( CONST D3DXFLOAT16 * ); D3DXMATRIX( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _ 14, FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _ 24, FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _ 34, FLOAT _41 , FLOAT _42 , FLOAT _43 , FLOAT _44 ); // access grants FLOAT& operator () ( UINT Row, UINT Col ); FLOAT operator () ( UINT Row, UINT Col ) const; Simpo PDF Merge and Split... multiplying by 2), that might be represented as: [ 10Ã2, 18Ã2, 47 Ã2, 12Ã2 ] = [ 20, 36, 94, 24 ] Figure 7.3 shows a typical 4 Â 4 matrix Most math references will refer to a 3 Â 3 matrix, and this is indeed the type of matrix needed to perform a single transform (such as translation or rotation) But in 3D graphics programming we use a 4 Â 4 matrix because it can represent more than one transform at a... void game_ render3d() {} bool game_ preload() { g _engine- >setAppTitle("Math Vector Demo"); g _engine- >setScreen(800,600,32,false); return true; } bool game_ init(HWND hwnd) { font = new Font("Arial Bold",18); if (!font) { debug ( "Error creating font" ( endl; 176 Simpo 7 n Vectors and Matrices Chapter PDF Merge and Split Unregistered Version - http://www.simpopdf.com return false; } return true; } void game_ end()... Split Unregistered Version - http://www.simpopdf.com Table 7.1 X rotation matrix C1 R1 R2 R3 R4 C2 C3 C4 1 0 0 0 0 cos(y) sin(y) 0 0 Àsin(y) cos(y) 0 0 0 0 1 Table 7.2 Y rotation matrix C1 R1 R2 R3 R4 C2 C3 C4 cos(y) 0 sin(y) 0 0 1 0 0 Àsin(y) 0 cos(y) 0 0 0 0 1 Table 7.3 Z rotation matrix C1 R1 R2 R3 R4 C2 C3 C4 cos(y) sin(y ) 0 0 Àsin(y ) cos(y) 0 0 0 0 1 0 0 0 0 1 calculated (for rotations X, Y, and... D3DMATRIX struct’s matrix elements (_11, _12, etc.) #include "stdafx.h" #include "Engine. h" #include "Vector.h" #include "Matrix.h" using namespace std; using namespace Octane; Font *font=NULL; bool game_ preload() { g _engine- >setAppTitle("Math Matrix Demo"); g _engine- >setScreen(10 24, 768,32,false); return true; } bool game_ init(HWND hwnd) { font = new Font("Arial Bold",18); Simpo PDF Merge and Split... Think of a 4 Â 4 matrix as an encoded transform containing (potentially) the translation, rotation, and scaling matrices We could use a 4 Â 4 matrix to represent the transforms of anything—a mesh, an entire environment, or a light, or even a camera All operations involving a real number are performed on all of the elements inside the matrix For example: [ 2.0, 5.0, 9.0, 3.0 ] Ã 0.5 ¼ [ 1.0, 2.5, 4. 5, 1.5... PDF Merge and Split Unregistered Version - http://www.simpopdf.com Figure 7.3 A 4 Â 4 matrix is used for fast 3D transform calculations Figure 7 .4 A matrix is described in terms of rows X columns Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Matrices 181 Figure 7.5 This 3 Â 4 matrix has 3 rows and 4 columns Figure 7.6 A zero matrix is a matrix with all elements set to zero... rendered: WorldMatrix = RotationMatrix * ScalingMatrix * TranslateMatrix; If RotationMatrix ¼ [ 2, 3, 1, 5] (simplified for illustration—assume there are 4 rows), and ScalingMatrix = [ 8, 3, 9, 4 ], then: [ 2, 3, 1, 5] Ã [ 8, 3, 9, 4 ] ¼ [ 2Ã8, 3Ã3, 1Ã9, 5 4 ] ¼ [16, 9, 9, 20 ] This combined matrix is then multiplied by the next matrix in the calculation If TranslateMatrix ¼ [ 0, 10, 10, À5 ], then: [ 16, . elapsed=0.0f; //unused functions void game_ render3d() {} bool game_ preload() { g _engine- >setAppTitle("Math Vector Demo"); g _engine- >setScreen(800,600,32,false); return true; } bool game_ init(HWND hwnd) { font. as: [ 10, 18, 47 , 12 ] and perform the same calculation on each matrix element (say, multiplying by 2), that might be represented as: [10 Ã 2, 18 Ã 2, 47 Ã 2, 12 Ã 2 ] = [ 20, 36, 94, 24 ] Figure. (Figure 7 .4) , but we most commonly use a 3 Â 3or4Â 4 matrix for 3D graphics transforms. To get the orientation correct: An mXnmatrix consists of m rows and n columns. Figure 7.5 shows a 3 Â 4 matrix. Zero