游戏框架其九:3D图像之数学基础

所有的3D效果,都是基于数学的支撑,以下是3DUI中用到的数学基础:

#pragma once
//========================================================================
// Geometry.h : Collection of code for 3D math and 3D shapes
//========================================================================

//========================================================================
//  Content References in Game Coding Complete 3rd Edition
// 
//  class Vec3
//  class Vec4
//  class Mat4x4
//  class Quaternion
//  class Plane
//  class Frustum
//


const float  GCC_PI = 3.14159265358979f;
const float  GCC_2PI = 2 * GCC_PI;


//
// Utility classes for vectors and matrices 
//


typedef D3DXVECTOR2 Vec2;


//
// Vec3 Description
//
//


typedef struct D3DXVECTOR3 {
    float x;
    float y;
    float z;
} D3DXVECTOR3, *LPD3DXVECTOR3;


class Vec3 : public D3DXVECTOR3 
{
public:
	inline float Length() { return D3DXVec3Length(this); }
    // 法线向量
	inline Vec3 *Normalize() { return static_cast<Vec3 *>(D3DXVec3Normalize(this, this)); }
	// 两个向量的点乘 和 两个向量的叉乘
    inline float Dot(const Vec3 &b) { return D3DXVec3Dot(this, &b); }
	inline Vec3 Cross(const Vec3 &b) const;

	Vec3(D3DXVECTOR3 &v3) { x = v3.x; y = v3.y; z = v3.z; }
	Vec3() : D3DXVECTOR3() { x = 0; y = 0; z = 0; }
	Vec3(const float _x, const float _y, const float _z) { x=_x; y=_y; z=_z; }
    Vec3(const double _x, const double _y, const double _z) { x = (float)_x; y = (float)_y; z = (float)_z; }
	inline Vec3(const class Vec4 &v4);
};

inline Vec3 Vec3::Cross(const Vec3 &b) const
{
	Vec3 out;
	D3DXVec3Cross(&out, this, &b);
	return out;
}




//
// Vec4 Description
//
//


typedef struct D3DXVECTOR4 {
    float x;
    float y;
    float z;
    float w;
} D3DXVECTOR4, *LPD3DXVECTOR4;

class Vec4 : public D3DXVECTOR4
{
public:
	inline float Length() { return D3DXVec4Length(this); }
	inline Vec4 *Normalize() { return static_cast<Vec4 *>(D3DXVec4Normalize(this, this)); }
	// If you want the cross product, use Vec3::Cross
	inline float Dot(const Vec4 &b) { return D3DXVec4Dot(this, &b); }

	Vec4(D3DXVECTOR4 &v4)  { x = v4.x; y = v4.y; z = v4.z; w = v4.w; }
	Vec4() : D3DXVECTOR4() { }
	Vec4(const float _x, const float _y, const float _z, const float _w) { x=_x; y=_y; z=_z; w=_w; }
	Vec4(const Vec3 &v3) { x = v3.x; y = v3.y; z = v3.z; w = 1.0f; }

};

inline Vec3::Vec3(const Vec4 &v4) { x = v4.x; y = v4.y; z = v4.z; }

extern Vec3 g_Up;
extern Vec3 g_Right;
extern Vec3 g_Forward;

extern Vec4 g_Up4;
extern Vec4 g_Right4;
extern Vec4 g_Forward4;



//
// Vec3List Description
// Vec4List Description
//
//   An STL list of Vectors
//


typedef std::list<Vec3> Vec3List;
typedef std::list<Vec4> Vec4List;



//
// Quaternion Description
//
//



typedef struct D3DXQUATERNION {
    float x;
    float y;
    float z;
    float w;
} D3DXQUATERNION, *LPD3DXQUATER

class Quaternion : public D3DXQUATERNION
{
public:

	// Modifiers
	void Normalize() { D3DXQuaternionNormalize(this, this); };
	void Slerp(const Quaternion &begin, const Quaternion &end, float cooef)
	{
		// performs spherical linear interpolation between begin & end 
		// NOTE: set cooef between 0.0f-1.0f
		D3DXQuaternionSlerp(this, &begin, &end, cooef);
	}

	// Accessors
	void GetAxisAngle(Vec3 &axis, float &angle) const
	{
		D3DXQuaternionToAxisAngle(this, &axis, &angle); 
	}

	// Initializers
	void Build(const class Mat4x4 &mat); 

	void BuildRotYawPitchRoll(
			const float yawRadians, 
			const float pitchRadians, 
			const float rollRadians)
	{
		D3DXQuaternionRotationYawPitchRoll(this, yawRadians, pitchRadians, rollRadians);
	}

	void BuildAxisAngle(const Vec3 &axis, const float radians)
	{
		D3DXQuaternionRotationAxis(this, &axis, radians);
	}
	
	Quaternion(D3DXQUATERNION &q) : D3DXQUATERNION(q) { }
	Quaternion() { }

	static const Quaternion g_Identity;
};

inline Quaternion operator * (const Quaternion &a, const Quaternion &b) 
{
	// for rotations, this is exactly like concatenating
	// matrices - the new quat represents rot A followed by rot B.
	Quaternion out;
	D3DXQuaternionMultiply(&out, &a, &b);
	return out;
}




//
// Mat4x4 Description
//
//


typedef struct D3DXMATRIX {
    float _ij;
} D3DXMATRIX, *LPD3DXMATRIX;

class Mat4x4 : public D3DXMATRIX
{
public:
	// Modifiers
	inline void SetPosition(Vec3 const &pos);
	inline void SetPosition(Vec4 const &pos);
	inline void SetScale(Vec3 const &scale);

	// Accessors and Calculation Methods
	inline Vec3 GetPosition() const;
	inline Vec3 GetDirection() const;
	inline Vec3 GetUp() const;
	inline Vec3 GetRight() const;
	inline Vec3 GetYawPitchRoll() const;
	inline Vec3 GetScale() const;
	inline Vec4 Xform(Vec4 &v) const;
	inline Vec3 Xform(Vec3 &v) const;
	inline Mat4x4 Inverse() const;

	Mat4x4(D3DXMATRIX &mat) { memcpy(&m, &mat.m, sizeof(mat.m)); }

	Mat4x4() : D3DXMATRIX() { }

	static const Mat4x4 g_Identity;

	// Initialization methods
	inline void BuildTranslation(const Vec3 &pos);
	inline void BuildTranslation(const float x, const float y, const float z );
	inline void BuildRotationX(const float radians) { D3DXMatrixRotationX(this, radians); }
	inline void BuildRotationY(const float radians) { D3DXMatrixRotationY(this, radians); }
	inline void BuildRotationZ(const float radians) { D3DXMatrixRotationZ(this, radians); }
	inline void BuildYawPitchRoll(const float yawRadians, const float pitchRadians, const float rollRadians)
		{ D3DXMatrixRotationYawPitchRoll(this, yawRadians, pitchRadians, rollRadians); }
	inline void BuildRotationQuat(const Quaternion &q) { D3DXMatrixRotationQuaternion(this, &q); }
	inline void BuildRotationLookAt(const Vec3 &eye, const Vec3 &at, const Vec3 &up) { D3DXMatrixLookAtRH(this, &eye, &at, &up); }
	inline void BuildScale(const float x, const float y, const float z );
};



inline void Mat4x4::SetPosition(Vec3 const &pos)
{
	m[3][0] = pos.x;
	m[3][1] = pos.y;
	m[3][2] = pos.z;
	m[3][3] = 1.0f;
}

inline void Mat4x4::SetPosition(Vec4 const &pos)
{
	m[3][0] = pos.x;
	m[3][1] = pos.y;
	m[3][2] = pos.z;
	m[3][3] = pos.w;
}

inline void Mat4x4::SetScale(Vec3 const &scale)
{
	m[1][1] = scale.x;
	m[2][2] = scale.y;
	m[3][3] = scale.z;
}


inline Vec3 Mat4x4::GetPosition() const
{
	return Vec3(m[3][0], m[3][1], m[3][2]);
}

inline Vec3 Mat4x4::GetDirection() const
{
	// Note - the following code can be used to double check the vector construction above.
	Mat4x4 justRot = *this;
	justRot.SetPosition(Vec3(0.f,0.f,0.f));
	Vec3 forward = justRot.Xform(g_Forward);
	return forward;
}

inline Vec3 Mat4x4::GetRight() const
{
	// Note - the following code can be used to double check the vector construction above.
	Mat4x4 justRot = *this;
	justRot.SetPosition(Vec3(0.f,0.f,0.f));
	Vec3 right = justRot.Xform(g_Right);
	return right;
}

inline Vec3 Mat4x4::GetUp() const
{
	// Note - the following code can be used to double check the vector construction above.
	Mat4x4 justRot = *this;
	justRot.SetPosition(Vec3(0.f,0.f,0.f));
	Vec3 up = justRot.Xform(g_Up);
	return up;
}




inline Vec3 Mat4x4::GetYawPitchRoll() const
{
   float yaw, pitch, roll;
	
   pitch = asin(-_32);

   double threshold = 0.001; // Hardcoded constant - burn him, he's a witch
   double test = cos(pitch);

   if(test > threshold) 
   {
      roll = atan2(_12, _22);
      yaw = atan2(_31, _33);
   }
   else 
   {
      roll = atan2(-_21, _11);
      yaw = 0.0;
   }

	return (Vec3(yaw, pitch, roll));
}


inline Vec3 Mat4x4::GetScale() const
{
	return Vec3(m[0][0], m[1][1], m[2][2]);
}

inline Vec4 Mat4x4::Xform(Vec4 &v) const
{
	Vec4 temp;
	D3DXVec4Transform(&temp, &v, this);
	return temp;
}

inline Vec3 Mat4x4::Xform(Vec3 &v) const
{
	Vec4 temp(v);
	Vec4 out;
	D3DXVec4Transform(&out, &temp, this);
	return Vec3(out.x, out.y, out.z);
}

inline Mat4x4 Mat4x4::Inverse() const
{
	Mat4x4 out;
	D3DXMatrixInverse(&out, NULL, this);
	return out;
}

inline void Mat4x4::BuildTranslation(const Vec3 &pos)
{
	*this = Mat4x4::g_Identity;
	m[3][0] = pos.x;
	m[3][1] = pos.y;
	m[3][2] = pos.z;
}

inline void Mat4x4::BuildTranslation(const float x, const float y, const float z )
{
	*this = Mat4x4::g_Identity;
	m[3][0] = x;
	m[3][1] = y;
	m[3][2] = z;
}

inline void Mat4x4::BuildScale(const float x, const float y, const float z )
{
	*this = Mat4x4::g_Identity;
	m[1][1] = x;
	m[2][2] = y;
	m[3][3] = z;
}


inline Mat4x4 operator * (const Mat4x4 &a, const Mat4x4 &b) 
{
	Mat4x4 out;
	D3DXMatrixMultiply(&out, &a, &b);

	return out;
}

inline void Quaternion::Build(const Mat4x4 &mat) 
{
	D3DXQuaternionRotationMatrix(this, &mat); 
}



//
// D3D9 Vertex Type Definitions
//
//  TRANSFORMED_VERTEX Description
//  UNTRANSFORMED_VERTEX Description
//  UNTRANSFORMED_LIT_VERTEX Description
//  D3D9Vertex_UnlitColored Description
//  D3D9Vertex_ColoredTextured Description
//  D3D9Vertex_Colored Description
//
//  Note: There's been a slight change from the book in this code.
//        Instead of #define D3DFVF_BlahBlah they are static constants;
//        find them at the top of Geometry.cpp
//
// See Game Coding Complete, 3rd Edition, Chapter 13, page 440-444


// A structure for our custom vertex type. We added texture coordinates
struct D3D9Vertex_Colored
{
    D3DXVECTOR3 position; // The position
    D3DCOLOR    color;    // The color

	static const DWORD FVF;
};

// A structure for our custom vertex type. We added texture coordinates
struct D3D9Vertex_ColoredTextured
{
    D3DXVECTOR3 position; // The position
    D3DCOLOR    color;    // The color
    float       tu, tv;   // The texture coordinates

	static const DWORD FVF;
};

struct D3D9Vertex_UnlitColored
{
    D3DXVECTOR3 position;	// The position in 3D space
    D3DXVECTOR3 normal;		// The normal vector (must be 1.0 units in length)
    D3DCOLOR    diffuse;    // The diffuse color
    D3DCOLOR    specular;   // The specular color

	static const DWORD FVF;
};

struct D3D9Vertex_UnlitTextured
{
    D3DXVECTOR3 position;
    D3DXVECTOR3 normal;
    float tu, tv;

    static const DWORD FVF;
};




struct D3D11_SimpleVertex
{
    Vec3 Pos;
    Vec3 Normal;
};

struct D3D11Vertex_UnlitTextured
{
	Vec3 Pos;
	Vec3 Normal;
	Vec2 Uv;
};

// Create our vertex input layout
const D3D11_INPUT_ELEMENT_DESC D3D11VertexLayout_UnlitTextured[] =
{
    { "POSITION",  0, DXGI_FORMAT_R32G32B32_float, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NORMAL",    0, DXGI_FORMAT_R32G32B32_float, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "TEXCOORD",  0, DXGI_FORMAT_R32G32_float,    0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

	
struct D3D11Vertex_UnlitTexturedColored
{
	Vec3 Pos;
	Vec3 Normal;
	Vec3 Diffuse;
	Vec2 Uv;
};

	// Create our vertex input layout
const D3D11_INPUT_ELEMENT_DESC D3D11VertexLayout_UnlitTexturedColored[] =
{
    { "POSITION",  0, DXGI_FORMAT_R32G32B32_float, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NORMAL",    0, DXGI_FORMAT_R32G32B32_float, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "COLOR",     0, DXGI_FORMAT_R32G32B32_float, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "TEXCOORD",  0, DXGI_FORMAT_R32G32_float,    0, 36, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};


struct D3D11Vertex_PositionColored
{
	Vec3 Pos;
	Vec3 Diffuse;
};

const D3D11_INPUT_ELEMENT_DESC D3D11VertexLayout_PositionColored[] =
{
    { "POSITION",  0, DXGI_FORMAT_R32G32B32_float, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "COLOR",     0, DXGI_FORMAT_R32G32B32_float, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};


const D3D11_INPUT_ELEMENT_DESC D3D11VertexLayout_Position[] =
{
    { "POSITION",  0, DXGI_FORMAT_R32G32B32_float, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
};



//
// TriangleIterator Definition - added post press
//
//    Allows a variety of different vertex buffers to be iterated as
//    a series of triangles.
//


class TriangleIterator
{
protected:
	Vec3 *m_Triangles;
	unsigned int m_Size;

public:
	TriangleIterator() { m_Triangles=0; m_Size=0; }
	virtual ~TriangleIterator() { SAFE_DELETE_ARRAY(m_Triangles); }

	bool InitializeStrippedMesh(LPDIRECT3DVERTEXBUFFER9 pVerts, int stride, int strips, int *triCountList );

	virtual unsigned int VGetSize() { return m_Size; }
	virtual void *VGet(unsigned int i);
};



//
// Plane Definition
//




class Plane : public D3DXPLANE
{
public:
	inline void Normalize();

	// normal faces away from you if you send in verts in counter clockwise order....
	inline void Init(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2);
	bool Inside(const Vec3 &point, const float radius) const;
	bool Inside(const Vec3 &point) const;
};

inline void Plane::Normalize()
{
	float mag;
	mag = sqrt(a * a + b * b + c * c);
	a = a / mag;
	b = b / mag;
	c = c / mag;
	d = d / mag;
}

inline void Plane::Init(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2)
{
	D3DXPlaneFromPoints(this, &p0, &p1, &p2);
	Normalize();
}




//
// Frustum Definition
//


class Frustum
{
public:
	enum Side { Near, Far, Top, Right, Bottom, Left, NumPlanes };

	Plane m_Planes[NumPlanes];	// planes of the frusum in camera space
	Vec3 m_NearClip[4];			// verts of the near clip plane in camera space
	Vec3 m_FarClip[4];			// verts of the far clip plane in camera space

	float m_Fov;				// field of view in radians
	float m_Aspect;				// aspect ratio - width divided by height
	float m_Near;				// near clipping distance
	float m_Far;				// far clipping distance

public:
	Frustum();

	bool Inside(const Vec3 &point) const;
	bool Inside(const Vec3 &point, const float radius) const;
	const Plane &Get(Side side) { return m_Planes[side]; }
	void SetFOV(float fov) { m_Fov=fov; Init(m_Fov, m_Aspect, m_Near, m_Far); }
	void SetAspect(float aspect) { m_Aspect=aspect; Init(m_Fov, m_Aspect, m_Near, m_Far); }
	void SetNear(float nearClip) { m_Near=nearClip; Init(m_Fov, m_Aspect, m_Near, m_Far); }
	void SetFar(float farClip) { m_Far=farClip; Init(m_Fov, m_Aspect, m_Near, m_Far); }
	void Init(const float fov, const float aspect, const float near, const float far);

	void Render();
};


inline Vec3 CalcVelocity(Vec3 const &pos0, Vec3 const &pos1, float time)
{
	// CalcVelocity - Chapter 15, page 526
	return (pos1 - pos0) / time;
}

inline Vec3 CalcAcceleration(Vec3 const &vel0, Vec3 const &vel1, float time)
{
	// CalcVelocity - Chapter 15, page 526
	return (vel1 - vel0) / time;
}

inline void HandleAccel(Vec3 &pos, Vec3 &vel, Vec3 &accel, float time)
{
	// CalcVelocity - Chapter 15, page 526
	vel += accel * time;
	pos += vel * time;
}

// converts Barycentric coordinates to world coordinates
// inputs are the 3 verts of the triangle, and the u,v barycentric coordinates
extern Vec3 BarycentricToVec3(Vec3 v0, Vec3 v1, Vec3 v2, float u, float v);

extern bool IntersectTriangle( const Vec3& orig, const Vec3& dir,
                        Vec3& v0, Vec3& v1, Vec3& v2,
                        float* t, float* u, float* v );
//========================================================================
// Geometry.cpp : Collection of code for 3D math and 3D shapes
//========================================================================

#include "GameCodeStd.h"
#include "Geometry.h"

//========================================================================
// 
// Note - FVFs are part of the fixed function pipeline, and were described in
//        Game Coding Complete, 3rd Edition. 
//
// Our custom FVF, which describes our custom vertex structure
// These were #define'd in the book - now they are static constants.
//
const DWORD D3D9Vertex_UnlitColored::FVF =
	(D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_SPECULAR);		
const DWORD D3D9Vertex_ColoredTextured::FVF = (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1);
const DWORD D3D9Vertex_Colored::FVF = (D3DFVF_XYZ|D3DFVF_DIFFUSE);
const DWORD D3D9Vertex_UnlitTextured::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;

const Mat4x4 Mat4x4::g_Identity(D3DXMATRIX(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1));
const Quaternion Quaternion::g_Identity(D3DXQUATERNION(0,0,0,1));

bool Plane::Inside(const Vec3 &point) const
{
	// Inside the plane is defined as the direction the normal is facing
	float result = D3DXPlaneDotCoord(this, &point);
	return (result >= 0.0f);
}

bool Plane::Inside(const Vec3 &point, const float radius) const
{
	float fDistance;	// calculate our distances to each of the planes

	// find the distance to this plane
	fDistance = D3DXPlaneDotCoord(this, &point);		

	// if this distance is < -radius, we are outside
	return (fDistance >= -radius);
}

//
// Frustum::Frustum					-
//
Frustum::Frustum()
{
	m_Fov = GCC_PI/4.0f;		// default field of view is 90 degrees
	m_Aspect = 1.0f;			// default aspect ratio is 1:1
	m_Near = 1.0f;				// default near clip plane is 1m away from the camera
	m_Far = 1000.0f;				// default near clip plane is 100m away from the camera
}


//
// Frustum::Inside
//
bool Frustum::Inside(const Vec3 &point) const
{
	for (int i=0; i<NumPlanes; ++i)
	{
		if (!m_Planes[i].Inside(point))
			return false;
	}

	return true;
}


//
// Frustum::Inside
//
bool Frustum::Inside(const Vec3 &point, const float radius) const
{
	for(int i = 0; i < NumPlanes; ++i) 
	{	
		if (!m_Planes[i].Inside(point, radius))
			return false;
	}	
	
	// otherwise we are fully in view
	return(true);
}

//
// Frustum::Init
//
void Frustum::Init(const float fov, const float aspect, const float nearClip, const float farClip)
{
	m_Fov = fov;
	m_Aspect = aspect;
	m_Near = nearClip;
	m_Far = farClip;

	float tanFovOver2 = (float)tan(m_Fov/2.0f);
	Vec3 nearRight = (m_Near * tanFovOver2) * m_Aspect * g_Right;
	Vec3 farRight = (m_Far * tanFovOver2) * m_Aspect * g_Right;
	Vec3 nearUp = (m_Near * tanFovOver2 ) * g_Up;
	Vec3 farUp = (m_Far * tanFovOver2)  * g_Up;

	// points start in the upper right and go around clockwise
	m_NearClip[0] = (m_Near * g_Forward) - nearRight + nearUp;
	m_NearClip[1] = (m_Near * g_Forward) + nearRight + nearUp;
	m_NearClip[2] = (m_Near * g_Forward) + nearRight - nearUp;
	m_NearClip[3] = (m_Near * g_Forward) - nearRight - nearUp;

	m_FarClip[0] = (m_Far * g_Forward) - farRight + farUp;
	m_FarClip[1] = (m_Far * g_Forward) + farRight + farUp;
	m_FarClip[2] = (m_Far * g_Forward) + farRight - farUp;
	m_FarClip[3] = (m_Far * g_Forward) - farRight - farUp;

	// now we have all eight points. Time to construct 6 planes.
	// the normals point away from you if you use counter clockwise verts.

	Vec3 origin(0.0f, 0.0f, 0.0f);
	m_Planes[Near].Init(m_NearClip[2], m_NearClip[1], m_NearClip[0]);
	m_Planes[Far].Init(m_FarClip[0], m_FarClip[1], m_FarClip[2]);
	m_Planes[Right].Init(m_FarClip[2], m_FarClip[1], origin);
	m_Planes[Top].Init(m_FarClip[1], m_FarClip[0], origin);
	m_Planes[Left].Init(m_FarClip[0], m_FarClip[3], origin);
	m_Planes[Bottom].Init(m_FarClip[3], m_FarClip[2], origin);
}



//
// Frustum::Render		
//
void Frustum::Render()
{
	D3D9Vertex_Colored verts[24];
	for (int i=0; i<8; ++i)
	{
		verts[i].color = g_White;
	}

	for (int i=0; i<8; ++i)
	{
		verts[i+8].color = g_Red;
	}

	for (int i=0; i<8; ++i)
	{
		verts[i+16].color = g_Blue;
	}


	// Draw the near clip plane
	verts[0].position = m_NearClip[0];	verts[1].position = m_NearClip[1];
	verts[2].position = m_NearClip[1];	verts[3].position = m_NearClip[2];
	verts[4].position = m_NearClip[2];	verts[5].position = m_NearClip[3];
	verts[6].position = m_NearClip[3];	verts[7].position = m_NearClip[0];

	// Draw the far clip plane
	verts[8].position = m_FarClip[0];	verts[9].position = m_FarClip[1];
	verts[10].position = m_FarClip[1];	verts[11].position = m_FarClip[2];
	verts[12].position = m_FarClip[2];	verts[13].position = m_FarClip[3];
	verts[14].position = m_FarClip[3];	verts[15].position = m_FarClip[0];

	// Draw the edges between the near and far clip plane
	verts[16].position = m_NearClip[0];	verts[17].position = m_FarClip[0];
	verts[18].position = m_NearClip[1];	verts[19].position = m_FarClip[1];
	verts[20].position = m_NearClip[2];	verts[21].position = m_FarClip[2];
	verts[22].position = m_NearClip[3];	verts[23].position = m_FarClip[3];

	DWORD oldLightMode;
	DXUTGetD3D9Device()->GetRenderState( D3DRS_LIGHTING, &oldLightMode );
	DXUTGetD3D9Device()->SetRenderState( D3DRS_LIGHTING, FALSE );

    DXUTGetD3D9Device()->SetFVF( D3D9Vertex_Colored::FVF );
	DXUTGetD3D9Device()->DrawPrimitiveUP( D3DPT_LINELIST, 12, verts, sizeof(D3D9Vertex_Colored) );

	DXUTGetD3D9Device()->SetRenderState( D3DRS_LIGHTING, oldLightMode );
}


Vec3 BarycentricToVec3(Vec3 v0, Vec3 v1, Vec3 v2, float u, float v)
{
	//V1 + U(V2 - V1) + V(V3 - V1).
	Vec3 result = v0 + u * (v1  - v0) + v * (v2 - v0);
	return result;
}


//--------------------------------------------------------------------------------------
// Given a ray origin (orig) and direction (dir), and three vertices of a triangle, this
// function returns TRUE and the interpolated texture coordinates if the ray intersects 
// the triangle
//--------------------------------------------------------------------------------------
bool IntersectTriangle( const Vec3& orig, const Vec3& dir,
                        Vec3& v0, Vec3& v1, Vec3& v2,
                        FLOAT* t, FLOAT* u, FLOAT* v )
{
    // Find vectors for two edges sharing vert0
    Vec3 edge1 = v1 - v0;
    Vec3 edge2 = v2 - v0;

    // Begin calculating determinant - also used to calculate U parameter
    Vec3 pvec;
    D3DXVec3Cross( &pvec, &dir, &edge2 );

    // If determinant is near zero, ray lies in plane of triangle
    FLOAT det = D3DXVec3Dot( &edge1, &pvec );

    Vec3 tvec;
    if( det > 0 )
    {
        tvec = orig - v0;
    }
    else
    {
        tvec = v0 - orig;
        det = -det;
    }

    if( det < 0.0001f )
        return FALSE;

    // Calculate U parameter and test bounds
    *u = D3DXVec3Dot( &tvec, &pvec );
    if( *u < 0.0f || *u > det )
        return FALSE;

    // Prepare to test V parameter
    Vec3 qvec;
    D3DXVec3Cross( &qvec, &tvec, &edge1 );

    // Calculate V parameter and test bounds
    *v = D3DXVec3Dot( &dir, &qvec );
    if( *v < 0.0f || *u + *v > det )
        return FALSE;

    // Calculate t, scale parameters, ray intersects triangle
    *t = D3DXVec3Dot( &edge2, &qvec );
    FLOAT fInvDet = 1.0f / det;
    *t *= fInvDet;
    *u *= fInvDet;
    *v *= fInvDet;

    return TRUE;
}



bool TriangleIterator::InitializeStrippedMesh(LPDIRECT3DVERTEXBUFFER9 pVerts, int stride, int strips, int *triCountList )
{
	char *pVertices = NULL;
	if( FAILED( pVerts->Lock( 0, 0, (void**)&pVertices, 0 ) ) )
        return false;

	for (int i=0; i<strips; ++i)
	{
		m_Size += triCountList[i];
	}

	m_Triangles = GCC_NEW Vec3[m_Size * 3];
	int src = 0;
	int dest = 0;

	for (int strip=0; strip<strips; ++strip )
	{
		int vertsInStrip = triCountList[strip]+2;
		GCC_ASSERT(vertsInStrip);

		m_Triangles[dest] = *((Vec3*)&pVertices[stride * src]);
		m_Triangles[dest+1] = *((Vec3*)&pVertices[stride * (src+1)]);
		m_Triangles[dest+2] = *((Vec3*)&pVertices[stride * (src+2)]);
		dest+=3;
		src+=3;
		for (int tri=1; tri<triCountList[strip]; ++tri)
		{
			// for every extra vertex in the triangle strip, you have to grab
			// the two previous verts in the dest list, reverse them, and copy them
			// forward. This will give you a triangle with the same winding
			m_Triangles[dest] = m_Triangles[dest-1];
			m_Triangles[dest+1] = m_Triangles[dest-2];
			m_Triangles[dest+2] = *((Vec3*)&pVertices[stride * (++src)]);
			dest+=3;
		}
	}
	GCC_ASSERT(dest==m_Size*3);
	pVerts->Unlock();

	return true;
}

void *TriangleIterator::VGet(unsigned int i) 
{	
	GCC_ASSERT(i<m_Size);
	return &m_Triangles[i*3]; 
}


下面一篇是基于Direct X 实现的渲染封装~~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值