游戏引擎开发路上的第一个拦路虎——数学算法

游戏引擎开发路上的第一个拦路虎——数学算法

无论游戏是什么形式(无论是角色扮演游戏、即时策略游戏、冒险解谜游戏还是动作射击游戏),即使是只有1兆字节的小游戏也需要游戏引擎技术。

引擎相当于游戏的框架。 框架完成后,关卡设计师、建模师、动画师就可以填写内容,这是开发游戏的重中之重。

应用引擎原理游戏怎么关闭_应用引擎是什么_游戏引擎原理及应用

当然,勇敢面对困难的人也有很多。 在兴趣的驱动下,学习游戏引擎技术开发并不是遥不可及。 那么今天我就给大家讲一下游戏引擎开发路上的第一个障碍——数学算法。

基础数学

让我们从文件 VSMath 开始

该文件封装了C语言中常用的数学函数,以及大量的宏定义。

下面的宏定义是用来判断精度的,特别是判断两个浮点数是否相等,因为没有绝对的相等,必须考虑到误差。

#define VSFRONT 0
#define VSBACK 1
#define VSON 2
#define VSCLIPPED 3
#define VSCULLED 4
#define VSVISIBLE 5
#define VSINTERSECT 3
#define VSOUT 4
#define VSIN 5
#define VSNOINTERSECT 6
//弧度和角度转换函数
inline VSREAL RadianToAngle(VSREAL Radian)
{
 return ( Radian * 180.0f ) / VSPI ;
}
inline VSREAL AngleToRadian(VSREAL Angle)
{
 return ( Angle * VSPI ) / 180.0f;
}
//判断是否为 2
N
inline bool IsTwoPower(unsigned int uiN)
{
 return !(uiN & (uiN - 1));
}
inline unsigned short FloatToHalf(VSREAL Value)
inline VSREAL HalfToFloat(unsigned short Value)
inline unsigned int CompressUnitFloat(VSREAL f, unsigned int Bit = 16)
inline unsigned int CompressFloat(VSREAL f, VSREAL Max , VSREAL Min ,
 unsigned int Bit = 16)

inline VSREAL DecompressUnitFloat(unsigned int quantized,unsigned int Bit = 16)
inline VSREAL DecompressFloat(unsigned int quantized,VSREAL Max ,
 VSREAL Min ,unsigned int Bit = 16)

//计算正弦和余弦查找表,加快正弦和余弦计算速度
for (unsigned int i = 0 ; i <= 360 ; i++)
{
 VSREAL iRadian = AngleToRadian(VSREAL(i));
 FastSin[i] = SIN(iRadian);
 FastCos[i] = COS(iRadian);
}
inline VSREAL VSMATH_API GetFastSin(unsigned int i);
inline VSREAL VSMATH_API GetFastCos(unsigned int i);
VSREAL GetFastSin(unsigned int i)
{
 return FastSin[i];
}
VSREAL GetFastCos(unsigned int i)
{
 return FastCos[i];
}

以下两个函数根据给定长度的数据计算哈希索引并返回 32 位哈希。

如果提供的数据量很大,可能会出现冲突,即两个不同的数据返回相同的值。

对于引擎来说,相关数据不多,所以冲突为0。

void VSInitCRCTable()
unsigned int CRC32Computeconst void *pData, unsigned int uiDataSize )

最后介绍一下SSE(Streaming SIMD Extensions,其中SIMD是Single Instruction Multiple Data的缩写,意为单指令多数据)指令加速数学库。

本书使用两个版本的库,一个是汇编版本,另一个是“高级语言”版本。 高级语言版本比汇编版本使用起来更方便。

VSFastFunction 文件中使用了程序集 SSE 库。 VSVector3、VSMatrix3X3 和 VSMatrix4X4 文件中使用的 SSE 库的高级语言版本更容易理解。

常规加法指令一次只能完成1次加法运算,而SSE库中的加法指令一次最多可以完成4次加法运算。 下面给出了SSE库的汇编版本和高级语言版本。

//汇编版 SSE 库
void VSFastAdd(const VSMatrix3X3W & InM1,const VSMatrix3X3W & InM2,
 VSMatrix3X3W & OutM)
{
 //VS 支持内嵌汇编
 __asm
 {
 mov eax, [InM2];
 mov ecx, [InM1];
 movups xmm4, [eax];
 movups xmm5, [eax+16];
 movups xmm6, [eax+32];
 movups xmm7, [eax+48];
 mov eax, [OutM];
 movups xmm0, [ecx];
 movups xmm1, [ecx+16];
 movups xmm2, [ecx+32];
 movups xmm3, [ecx+48];
 addps xmm0, xmm4;
 movups [eax], xmm0;
 addps xmm1, xmm5;
 movups [eax+16], xmm1;
 addps xmm2, xmm6;
 movups [eax+32], xmm2;
 addps xmm3, xmm7;
 movups [eax+48], xmm3;
 }
}
//高级语言版 SSE 库
void VSMatrix3X3W::operator -=(VSREAL f)
{
 __m128 _v1 = _mm_set_ps(m[0],m[1],m[2],m[3]);
 __m128 _v2 = _mm_set_ps(m[4],m[5],m[6],m[7]);
 __m128 _v3 = _mm_set_ps(m[8],m[9],m[10],m[11]);
 __m128 _v4 = _mm_set_ps(m[12],m[13],m[14],m[15]);
 __m128 _f = _mm_set_ps(f,f,f,f);
 __m128 _r1 = _mm_sub_ps(_v1,_f);
 __m128 _r2 = _mm_sub_ps(_v2,_f);
 __m128 _r3 = _mm_sub_ps(_v3,_f);
 __m128 _r4 = _mm_sub_ps(_v4,_f);
 M[0][0] = _r1.m128_f32[3]; M[0][1] = _r1.m128_f32[2];
 M[0][2] = _r1.m128_f32[1]; M[0][3] = _r1.m128_f32[0];
 M[1][0] = _r2.m128_f32[3]; M[1][1] = _r2.m128_f32[2];
 M[1][2] = _r2.m128_f32[1]; M[1][3] = _r2.m128_f32[0];
 M[2][0] = _r3.m128_f32[3]; M[2][1] = _r3.m128_f32[2];
 M[2][2] = _r3.m128_f32[1]; M[2][3] = _r3.m128_f32[0];
 M[3][0] = _r4.m128_f32[3]; M[3][1] = _r4.m128_f32[2];
 M[3][2] = _r4.m128_f32[1]; M[3][3] = _r4.m128_f32[0];
}

基本数学单位

3D矢量

VSVector3 表示三维向量。 此类可以表示 3D 矢量或点。

所以这个类提供了3D向量应该具有的功能和空间点应该具有的功能。

class VSMATH_API VSVector3
{

public:
 union
 {
 VSREAL m[3];
 struct
 {

 VSREAL x, y, z;
 };
 };
}

矩阵类和向量类一样游戏引擎原理及应用,定义了联合类型,并且可以通过数组方法或下标方法访问此向量的类属性。

VSVector3类中的相关函数如下。

//长度
inline VSREAL GetLength(void)const;
//长度的平方
inline VSREAL GetSqrLength(void) const;
//乘以-1
inline void Negate(void);
//单位化
inline void Normalize(void);
//叉积
inline void Cross(const VSVector3 &v1,const VSVector3 &v2);
//点积
VSREAL operator * (const VSVector3 &v)const;
//两个向量的夹角(弧度)
VSREAL AngleWith( VSVector3 &v);
//用四元数旋转向量
VSQuat operator * (const VSQuat &q)const;
//3×3 矩阵变换向量
VSVector3 operator * (const VSMatrix3X3 &m)const;
//4×4 矩阵变换向量
VSVector3 operator * (const VSMatrix3X3W &m)const;
//向量加减
void operator += (const VSVector3 &v);
void operator -= (const VSVector3 &v);
VSVector3 operator + (const VSVector3 &v)const;
VSVector3 operator - (const VSVector3 &v)const;
//向量和常量加减
void operator *= (VSREAL f);
void operator /= (VSREAL f);
void operator += (VSREAL f);
void operator -= (VSREAL f);
bool operator ==(const VSVector3 &v)const;
VSVector3 operator * (VSREAL f)const;
VSVector3 operator / (VSREAL f)const;
VSVector3 operator + (VSREAL f)const;
VSVector3 operator - (VSREAL f)const;

读者应充分理解上述函数的实现和意义,特别是点积、叉积以及与矩阵的变换。

四维向量

VSVector3W 表示四维向量。 该类在VSVector3中添加了aw组件,主要是为了方便4×4矩阵的运算。 当 w 分量非 1 时,这在空间变换中起着重要作用。 另一个应用场景是作为颜色。

class VSMATH_API VSVector3W
typedef class VSVector3W VSColorRGBA;

下面是颜色操作的相关函数,都是用来实现32位DWORD类型和四种float类型之间的相互转换。

DWORD GetDWARGB()const;
DWORD GetDWRGBA()const;
DWORD GetDWBGRA()const;
DWORD GetDWABGR()const;
void GetUCColor(unsigned char &R,unsigned char &G,unsigned char &B,
 unsigned char &A)
const
;
void CreateFromARGB(DWORD ARGB);
void CreateFromBGRA(DWORD BGRA);
void CreateFromRGBA(DWORD RGBA);
void CreateFormABGR(DWORD ABGR);

下面的颜色组合函数用于实现VSColorRGBA类型和DWORD类型之间的转换。

inline DWORD VSDWCOLORARGB(unsigned char a, unsigned char r,
 unsigned char g,unsigned char b)

{
 return (DWORD)
 ((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)));
}
inline DWORD VSDWCOLORBGRA(unsigned char a, unsigned char r,
 unsigned char g,unsigned char b)

{
 return (DWORD)
 ((((b)&0xff)<<24)|(((g)&0xff)<<16)|(((r)&0xff)<<8)|((a)&0xff)));
}
inline DWORD VSDWCOLORRGBA(unsigned char a, unsigned char r,
 unsigned char g,unsigned char b)

{
 return (DWORD)
 ((((r)&0xff)<<24)|(((g)&0xff)<<16)|(((b)&0xff)<<8)|((a)&0xff)));
}
inline DWORD VSDWCOLORABGR(unsigned char a, unsigned char r,
 unsigned char g,unsigned char b)

{
 return (DWORD)
 ((((a)&0xff)<<24)|(((b)&0xff)<<16)|(((g)&0xff)<<8)|((r)&0xff)));
}
inline void VSDWCOLORGetARGB(DWORD ARGB,unsigned char &a,
 unsigned char &r, unsigned char &g,unsigned char &b)

{
 a = (ARGB>>24) & 0xff;
 r = (ARGB>>16) & 0xff;
 g = (ARGB>>8) & 0xff;
 b = (ARGB) & 0xff;
}
inline void VSDWCOLORGetBGRA(DWORD BGRA,unsigned char &a,
 unsigned char &r, unsigned char &g,unsigned char &b)

{
 b = (BGRA>>24) & 0xff;
 g = (BGRA>>16) & 0xff;
 r = (BGRA>>8) & 0xff;
 a = (BGRA) & 0xff;
}
inline void VSDWCOLORGetRGBA(DWORD RGBA,unsigned char &a,
 unsigned char &r, unsigned char &g,unsigned char &b)

{
 r = (RGBA>>24) & 0xff;
 g = (RGBA>>16) & 0xff;
 b = (RGBA>>8) & 0xff;
 a = (RGBA) & 0xff;
}
inline void VSDWCOLORGetABGR(DWORD ABGR,unsigned char &a,
 unsigned char &r, unsigned char &g,unsigned char &b)

{
 a = (ABGR>>24) & 0xff;
 b = (ABGR>>16) & 0xff;
 g = (ABGR>>8) & 0xff;
 r = (ABGR) & 0xff;
}

图形渲染时,颜色需要在unsigned char、DWORD和float之间进行转换,不同的格式代表不同的颜色范围。

3×3矩阵

VSMatrix3X3 表示 3×3 矩阵。 3×3矩阵主要用于在变换中实现矩阵旋转、缩放或两者的组合。

需要提醒的是:一定要区分是左手坐标系还是右手坐标系游戏引擎原理及应用,矩阵和向量是左乘还是右乘,矩阵主要是行矩阵还是列矩阵,并了解如何定义正旋转方向。

以下是创建旋转矩阵的几个函数。

//通过一个朝向创建旋转矩阵
void CreateFromDirection(VSVector3 & Direction ,
const VSVector3 &Up = VSVector3(0,1,0
))
;
void CreateRotX(VSREAL a)// 绕 x 轴旋转
void CreateRotY(VSREAL a)// 绕 y 轴旋转
void CreateRotZ(VSREAL a)// 绕 z 轴旋转
//绕 z 轴、x 轴和 y 轴构建欧拉角
void CreateEluer(VSREAL Roll,VSREAL Pitch, VSREAL Yaw)
void CreateAxisAngle(const VSVector3 &vAxis, VSREAL a)
;//绕 vAxis 旋转 a 弧度 
//通过 3 个基向量创建旋转矩阵
void CreateRot(const VSVector3 &U,const VSVector3 &V,const VSVector3 & N);以下几个函数也要了解一下。

有时需要获取引擎中矩阵的行向量和列向量,尤其是从物体的旋转矩阵中获取向前、向上和向右方向(三个基向量U、V、N)。

//按行获得向量
void GetRowVector(VSVector3 Row[3])const;
//按行、按列获得向量
void GetColumnVector(VSVector3 Column[3])const;
void GetRowVector(VSVector3 &Row0,VSVector3 &Row1,VSVector3 &Row2)const;
void GetColumnVector(VSVector3 &Column0,VSVector3 &Column1,
 VSVector3 &Column2)
const
;
//获得基向量
void GetUVN(VSVector3 UVN[3])const;
void GetUVN(VSVector3 & U,VSVector3 &V,VSVector3 &N)const;

有时还需要创建缩放矩阵。 大多数引擎根据原点进行缩放。

//创建缩放矩阵,根据原点缩放
void CreateScale(VSREAL fX,VSREAL fY,VSREAL fZ);
//根据轴缩放
void CreateScale(const VSVector3 & Axis,VSREAL fScale);

从矩阵中获取旋转和缩放量也是常用的。

void GetScale(VSVector3 & Scale)const;
void GetScaleAndRotater(VSVector3 & Scale);

下面两个函数很少用到。 该引擎使用这两个函数来查找点集的 OBB 边界框。

//构造一个行向量、一个列向量
inline void CreateFromTwoVector(const VSVector3 & v1,const VSVector3 & v2);
//求特征值、特征向量
void GetEigenSystem(VSREAL EigenValue[3],VSVector3 Eigen[3])const;

矩阵乘法以及矩阵与向量乘法是使用以下函数实现的。

inline VSMatrix3X3 operator * (const VSMatrix3X3 &Matrix)const// 矩阵相乘
inline VSVector3 operator * (const VSVector3 &vc)const// 矩阵和向量相乘

只有矩阵乘法才有实际意义,矩阵乘法可以看成是矩阵的“加法”。

很多读者听了之后可能会感到困惑。 乘法怎么能变成加法?

任何学过“离散数学”的人都学过群论。 里面经常提到的加法只是特定范围的加法,不同的群体有自己的加法。

例如:整数1的加法是传统的加法1 + 1 = 2,减法1 1 = 0,即1 + (−1)。

矩阵加法是M1和M2等于M的乘法,矩阵减法是M1和M2的逆矩阵乘法,但这种加法不满足交换律。

矩阵中的“0”是单位矩阵,也称为E。

理解这一点的基础上,引入了矩阵插值的概念。

查看下面的代码。

void VSMatrix3X3::LineInterpolation(VSREAL t,const VSMatrix3X3 & M1,
 const VSMatrix3X3 &M2)
{
 *this = M1 * (1.0f - t) + M2 * t;
}
void VSMatrix3X3::Slerp(VSREAL t,const VSMatrix3X3 & M1,
 const VSMatrix3X3 &M2)
{
 VSMatrix3X3 M1Transpose,Temp;
 M1Transpose.TransposeOf(M1);
 Temp = M1Transpose * M2;
 VSREAL fAnagle;
 VSVector3 Axis;
 Temp.GetAxisAngle(Axis,fAngle);
 Temp.CreateAxisAngle(Axis,fAngle * t);
 *this = M1 * Temp;
}

本质上,对于旋转矩阵的插值,第一个函数的插值算法是不正确的。 虽然插值公式为M1(1.0ft) +M2t,但“+”表示矩阵乘法,因此第二个函数的插值算法是正确的。

在第二个函数中,插值公式为M1(M1t)1M2t。 这里的t并不是简单地乘以矩阵。 矩阵必须改为轴和角度,然后将t和角度相乘。

4×4矩阵

VSMatrix3X3W 表示 4×4 矩阵。 该函数最常用于空间变换。

下面是创建一个4×4的矩阵。 缩放和旋转是通过VSMatrix3X3实现的。

//用 3*3 矩阵创建
void CreateFrom3X3(const VSMatrix3X3 & Mat);
//平移矩阵
void CreateTranslate(VSREAL dx, VSREAL dy, VSREAL dz);
void CreateTranslate(const VSVector3 & V);

以下函数为对象创建一个局部变换矩阵。

如果两个对象A和B在同一个空间M中,并且B想要变换到A的空间中,则为A对象创建一个变换矩阵。

其中,U、V、N是物体A在空间M中的基向量,Point是A在空间M中的位置。

举个简单的例子:如果M是世界空间,那么世界空间中的所有物体都要变换到相机空间,那么U、V、N就是相机在世界中的三个基向量(或者说轴向)空间,Point 是相机在世界空间中的位置。

void CreateInWorldObject(const VSVector3 &U,const VSVector3 &V,const VSVector3 &
 N,const VSVector3 &Point)
;

公告牌是一种特殊的面,这里不做介绍。 一般来说,公告板有两种类型:一种是完全面向摄像头,通常由颗粒组成;另一种是完全面向摄像头,通常由颗粒组成。 另一种是只能沿y轴旋转并尽量面向相机方向。

//建立公告牌变换矩阵
void CreateFormBillboard(const VSVector3 &vcPos, //公告牌位置
 const VSMatrix3X3 &CameraRotMatrix, //相机或其他矩阵
 bool bAxisY)
//是否只选择沿 y 轴旋转

以下是创建相机矩阵、透视投影矩阵、正交投影矩阵和视口矩阵的函数。

//构建相机矩阵(根据观察方向)
bool CreateFromLookDir(const VSVector3 &vcPos, //相机位置
 const VSVector3 &vcDir, //观察方向
 const VSVector3 &vcWorldUp = VSVector3(0,1,0));
//构建相机矩阵(根据目标位置)
bool CreateFromLookAt(const VSVector3 &vcPos, //相机位置
 const VSVector3 &vcLookAt, //观察位置
 const VSVector3 &vcWorldUp = VSVector3(0,1,0)); //上方向
//建立透视投影矩阵
bool CreatePerspective(VSREAL fFov , //x 方向的张角
 VSREAL fAspect, //宽高比
 VSREAL fZN , //近剪裁面
 VSREAL fZF); //远剪裁面
//建立正交投影矩阵
bool CreateOrthogonal(VSREAL fW , //宽
 VSREAL fH, //高
 VSREAL fZN , //近剪裁面
 VSREAL fZF); //远剪裁面
//建立视口矩阵
bool CreateViewPort(VSREAL fX,VSREAL fY,VSREAL fWidth,VSREAL fHeight,VSREAL fMinz,VSREAL
fMaxz);

以下功能也是常用的。 因为3×3矩阵中有获取旋转和缩放分量的函数,所以4×4矩阵中没有直接提供。

inline void Identity(void)//单位矩阵
inline void TransposeOf(const VSMatrix3X3W &Matrix)//转置
inline void InverseOf(const VSMatrix3X3W & Mat)//求逆
inline VSMatrix3X3W GetTranspose()const//转置
inline VSMatrix3X3W GetInverse()const//求逆
inline VSVector3 GetTranslation(void)const//得到平移量
inline void Get3X3(VSMatrix3X3 & Mat)const//得到 3*3 部分

下面的也常用,不过VSVector3和4×4矩阵的乘法是点和4×4矩阵的乘法,代表点的空间变换。

如果要对向量进行空间变换,应使用Apply3X3。

inline VSMatrix3X3W operator * (const VSMatrix3X3W &Matirx)const// 矩阵相乘
inline VSVector3 operator * (const VSVector3 &vc)const// 矩阵和向量乘
inline VSVector3W operator * (const VSVector3W &vc)const// 矩阵和向量乘
//应用 3*3 的部分
inline VSVector3 Apply3X3(const VSVector3 &v)const;
//应用平移
inline VSVector3 ApplyTranlate(const VSVector3 &Point)const;

四元数

VSQuat 代表四元数类。 以下函数创建一个四元数。

//通过旋转轴和旋转角构造四元数
void CreateAxisAngle(const VSVector3& Axis,VSREAL fAngle);
//由欧拉角构造四元数
void CreateEule(VSREAL fRoll, VSREAL fPitch, VSREAL fYaw);

通过旋转矩阵获取四元数的函数是在VSMatrix3X3中编写的。

//得到欧拉角
void GetEulers(VSREAL &fRoll, VSREAL &fPitch, VSREAL &fYaw)const;
//从四元数得到变换矩阵
void GetMatrix(VSMatrix3X3 &Matrix)const;
//取得旋转轴和旋转角
void GetAxisAngle(VSVector3 & Axis , VSREAL & fAngle)const;

四元数的一些常用函数如下。

//单位化
void Normalize();
//求共轭
VSQuat GetConjugate()const;
//得到长度
VSREAL GetLength(void)const;
//求逆
VSQuat GetInverse()const;
//求点积
VSREAL Dot(const VSQuat& q)const;
//求共轭
VSQuat operator ~(voidconst;
//求幂
VSQuat Pow(VSREAL exp)const;
//求以 e 为底的对数
VSQuat Ln()const;
//求以 e 为底的指数
VSQuat Exp()const;
void operator /= (VSREAL f);
VSQuat operator / (VSREAL f)const;
void operator *= (VSREAL f);
VSQuat operator * (VSREAL f)const;
VSQuat operator * (const VSVector3 &v) const;
VSQuat operator * (const VSQuat &q) const;
void operator *= (const VSQuat &q);
void operator += (const VSQuat &q);
VSQuat operator + (const VSQuat &q) const;
void operator -= (const VSQuat &q);
VSQuat operator - (const VSQuat &q) const;
bool operator ==(const VSQuat &q)const;

四元数旋转的示例代码如下。

//求 q2 绕 q1 旋转后的四元数
void Rotate(const VSQuat &q1, const VSQuat &q2);
//旋转一个向量
VSVector3 Rotate(const VSVector3 &v)const;

四元数插值的相关实现请参考《3D数学基础:图形与游戏开发》一书。

//插值
void Slerp(VSREAL t,const VSQuat & q1,const VSQuat & q2);
//三角形二维球型插值
void TriangleSlerp(VSREAL t1,VSREAL t2, const VSQuat & q1,const VSQuat & q2,
 const VSQuat & q3)
;
//四元数样条插值
void Slerp(VSREAL t,const VSQuat & q1,const VSQuat & q2,const VSQuat & s1,
 const VSQuat & s2)
;
void SlerpSValueOf(const VSQuat & q1,const VSQuat & q2,const VSQuat & q3);

基本图形单元

本节主要介绍引擎中常用的基本原语。 相机裁剪、光线检测、物体碰撞等都与它们密切相关。 每个图元都是一个类,类的属性根据空间几何定义进行封装。 该类的方法也很容易分类,主要是根据与其他图元的位置关系,或者与其他图元的距离确定(算法的详细说明可以在《计算机图形学几何工具算法详解》一书中找到) ”)。

下图展示了原始类的继承关系。

游戏引擎原理及应用_应用引擎原理游戏怎么关闭_应用引擎是什么

观点

点由 VSVector3 类表示。

直线、射线、线段

VSLine3 代表直线。 直线被定义为一个点和一个方向。 与射线不同的是,直线的方向可以是负方向,而且这个方向必须统一。

P = P0 + tDir

上式是一个直线参数方程,以t为参数。

给定t,就可以计算P; 给定 P,您可以计算 t。

//给定点 P,求 t
bool GetParameter(const VSVector3 &Point,VSREAL &fLineParameter )const;
//构建直线
inline void Set(const VSVector3 & Orig,const VSVector3 &Dir);
//得到 P0 和 dir
inline const VSVector3 & GetOrig()const;
inline const VSVector3 & GetDir()const;
//给定 t,求 P
inline VSVector3 GetParameterPoint(VSREAL fLineParameter)const;

下面的函数用于确定直线与其他图元之间的位置关系。

//判断直线与三角形的位置关系。bCull 为是否为背面剪裁,是否考虑朝向,t 返回相交长度
//VSNOINTERSECT VSNTERSECT
int RelationWith(const VSTriangle3 & Triangle, bool bCull,VSREAL &fLineParameter,
 VSREAL fTriangleParameter[3])
const
;
//判断直线与平面的位置关系
//VSNOINTERSECT VSNTERSECT VSON VSBACK VSFRONT
int RelationWith(const VSPlane3 &Plane, bool bCull,VSREAL &fLineParameter)const;
//判断直线与矩形的位置关系
//VSNOINTERSECT VSNTERSECT
int RelationWith(const VSRectangle3 &Rectangle,bool bCull,VSREAL &fLineParameter,
 VSREAL fRectangleParameter[2])
const
;
//判断直线与球的位置关系
//VSNOINTERSECT VSNTERSECT
int RelationWith(const VSSphere3 &sphere, unsigned int &Quantity,VSREAL &tNear,
 VSREAL &tFar)
const
;
//判断直线与 OBB 的位置关系
//VSNOINTERSECT VSNTERSECT
int RelationWith(const VSOBB3 &OBB, unsigned int &Quantity,VSREAL &tNear,VSREAL
 &tFar)
const
;
//判断直线与 AABB 的位置关系
//VSNOINTERSECT VSNTERSECT
int RelationWith(const VSAABB3 &AABB, unsigned int &Quantity,VSREAL &tNear,VSREAL &
 tFar)
const
;
//判断直线与多边形的位置关系
//VSNOINTERSECT VSNTERSECT
int RelationWith(const VSPolygon3 &Polygon,VSREAL &fLineParameter, bool bCull,int &
 iIndexTriangle,VSREAL fTriangleParameter[3])
const
;

以下函数用于计算一条线与其他图元的距离。

//计算点到直线的距离
VSREAL SquaredDistance(const VSVector3 &Point,VSREAL &fLineParameter)const;
//计算直线和直线的距离
VSREAL SquaredDistance(const VSLine3 &Line,VSREAL &fLine1Parameter,VSREAL &fLine2
 Parameter)
const
;
//计算直线和射线的距离
VSREAL SquaredDistance(const VSRay3 &Ray,VSREAL &fLineParameter,VSREAL &
 fRayParameter)
const
;
//计算直线和线段的距离
VSREAL SquaredDistance(const VSSegment3 & Segment,VSREAL &fLineParameter,VSREAL &
 fSegmentParameter)
const
;
//计算直线和三角形的距离
VSREAL SquaredDistance(const VSTriangle3& Triangle,VSREAL &fLineParameter,VSREAL
 fTriangleParameter[3])
const
;
//计算直线和矩形的距离
VSREAL SquaredDistance(const VSRectangle3& Rectangle,VSREAL &fLineParameter,VSREAL
 fRectangleParameter[2])
const
;
//计算直线和 OBB 的距离
VSREAL SquaredDistance(const VSOBB3 & OBB,VSREAL &fLineParameter,VSREAL
 fOBBParameter[3])
const
;
//计算直线和球的距离
VSREAL Distance(const VSSphere3 &Sphere,VSREAL &fLineParameter,VSVector3 &
 SpherePoint)
const
;
//计算直线和平面的距离
VSREAL Distance(const VSPlane3 &Plane,VSVector3 &LinePoint,VSVector3 &PlanePoint)
 const
;
//计算直线和 AABB 的距离
VSREAL SquaredDistance(const VSAABB3 &AABB,VSREAL &fLineParameter, VSREAL
 fAABBParameter[3])
const
;
//计算直线和多边形的距离
VSREAL SquaredDistance(const VSPolygon3 & Polygon,VSREAL &fLineParameter,int&
 IndexTriangle,VSREAL fTriangleParameter[3])
const
;

VSRay3代表射线。 射线和直线之间的唯一区别是 t 可以为负值。

VSSegment3表示线段,与直线不同的是它具有端点属性。

对于P = P0 + tDir,t有一个范围,因此有两种定义方式:第一种是基于两个点,第二种是基于方向和长度。

inline void Set(const VSVector3 &Orig,const VSVector3 &End);
inline void Set(const VSVector3 &Orig,const VSVector3 &Dir,VSREAL fLen);

平面、三角形、矩形、多边形

VSPlane代表一个平面,该平面的参数方程为N(P0-P1)=0。

平面法线垂直于平面上所有直线,简化为NP0+D=0,D=NP1为常数; 平面上所有点 P 满足 NP + D = 0。

下面的函数都可以创建一个平面。

//通过平面法向量和平面上一点确定一个平面
inline void Set(const VSVector3 &N, const VSVector3 &P);
//通过平面法向量和 D 确定一个平面
inline void Set(const VSVector3 &N , VSREAL fD);
//通过 3 个点确定一个平面
inline void Set(const VSVector3 &P0, const VSVector3 &P1, const VSVector3 &P2);
inline void Set(const VSVector3 Point[3]);

以下函数用于计算平面与其他图元的距离。

//计算点到平面的距离
VSREAL Distance(const VSVector3 &Point,VSVector3 &PlanePoint)const;
//计算平面和球的距离
VSREAL Distance(const VSSphere3 &Sphere,VSVector3 & SpherePoint)const;
//计算直线和平面的距离
VSREAL Distance(const VSLine3 &Line,VSVector3 &PlanePoint, VSVector3 &LinePoint)const;
//计算射线和平面的距离
VSREAL Distance(const VSRay3 & Ray,VSVector3 &PlanePoint,VSVector3 &RayPoint)const;
//计算线段和平面的距离
VSREAL Distance(const VSSegment3 & Segment,VSVector3 &PlanePoint, VSVector3 &
Segment Point)
const
;
//计算平面和平面的距离
VSREAL Distance(const VSPlane3 &Plane,VSVector3 &Plane1Point,VSVector3 & Plane2Point)
const
;
//计算平面和三角形的距离
VSREAL Distance(const VSTriangle3 &Triangle,VSVector3 &PlanePoint, VSVector3 &
Triangle Point)
const
;
//计算矩形和平面的距离
VSREAL Distance(const VSRectangle3 &Rectangle,VSVector3 &PlanePoint,VSVector3 &
Rectangle Point)
const
;
//计算 OBB 和平面的距离
VSREAL Distance(const VSOBB3& OBB,VSVector3 &PlanePoint,VSVector3 & OBBPoint)const;
//计算 AABB 和平面的距离
VSREAL Distance(const VSAABB3 &AABB,VSVector3 &PlanePoint,VSVector3 & AABBPoint)const;
//计算平面和多边形的距离
VSREAL Distance(const VSPolygon3 &Polygon,VSVector3 &PlanePoint,int& IndexTriangle,
VSVector3 &TrianglePoint)
const
;

以下函数用于确定平面与其他图元之间的位置关系。

//判断点和平面的位置关系
//VSFRONT VSBACK VSPLANAR
int RelationWith(const VSVector3 &Point)const;
//判断直线和平面的位置关系
/VSNOINTERSECT VSNTERSECT VSON VSBACK VSFRONT
int RelationWith(const VSLine3 &Line, bool bCull,VSREAL &fLineParameter)const
;
//判断射线和平面的位置关系
//VSNOINTERSECT VSNTERSECT VSON VSBACK VSFRONT
int RelationWith(const VSRay3 &Ray, bool bCull,VSREAL &fRayParameter)const;
//判断线段和平面的位置关系
//VSNOINTERSECT VSNTERSECT VSON VSBACK VSFRONT
int RelationWith(const VSSegment3 &Segment, bool bCull,VSREAL &fSegmentParameter)
const
;
//判断平面和 OBB 的位置关系
//VSFRONT VSBACK VSINTERSECT
int RelationWith(const VSOBB3 &OBB)const;
//判断平面和 AABB 的位置关系
//VSFRONT VSBACK VSINTERSECT
int RelationWith(const VSAABB3 &AABB)const;
//判断平面和球的位置关系
//VSFRONT VSBACK VSINTERSECT
int RelationWith(const VSSphere3 &Sphere)const;
//判断平面和三角形的位置关系
//VSON VSFRONT VSBACK VSINTERSECT
int RelationWith(const VSTriangle3 &Triangle)const;
int RelationWith(const VSTriangle3 &Triangle ,VSSegment3 & Segment)const;
//判断参数平面和平面的位置关系
//VSNOINTERSECT VSINTERSECT
int RelationWith(const VSPlane3 &Plane)const;
int RelationWith(const VSPlane3 &Plane,VSLine3 &Line)const;
//判断平面和矩形的位置关系
//VSON VSFRONT VSBACK VSINTERSEC
Tint RelationWith(const VSRectangle3 & Rectangle)const;
int RelationWith(const VSRectangle3 &Rectangle,VSSegment3 &Segment)const;
//判断平面和多边形的位置关系
//VSON VSFRONT VSBACK VSINTERSECTint RelationWith(const VSPolygon3 &Polygon)const;
int RelationWith(const VSPolygon3 &Polygon,VSSegment3 & Segment)const;
//判断平面和圆柱的位置关系
int RelationWith(const VSCylinder3 &Cylinder3)const;

VSTriangle3 代表三角形类。 三角形类是从平面类派生出来的。 它的构造方法很简单,就是3点。

P=P1U+P2V+P3(1 UV) 是三角形的参数方程。

给定点P,可以通过公式导出参数U和V; 给定参数 U 和 V,也可以推导出 P。

bool GetParameter(const VSVector3 &Point,VSREAL fTriangleParameter[3])const;
inline VSVector3 GetParameterPoint(VSREAL fTriangleParameter[3])const;

VSRectangle3 表示矩形类,它也是从平面类派生出来的,由两个垂直向量和一个点定义。

球体、定向边界框、立方体

VSSphere3 表示球体,VSOBB3 表示有向边界框,VSAABB3 表示立方体。 因为没有实现物理引擎,所以圆柱体、胶囊、椭球体等没有单独实现。 球体和立方体在引擎中最常用,并且用于场景管理。 除此之外,还有一些合并算法,将球体与球体合并,将立方体与立方体合并。

不同游戏引擎的内部架构差异很大3D素材,游戏引擎涉及的知识点也很多。 很少有人能够完全掌握每一个知识细节。

同时,游戏引擎是一个实用的项目,必须有足够令人信服的演示示例和代码支持。 另外,商业引擎的授权以及作者个人时间有限等多种因素,导致市面上的游戏引擎书籍要么笼统,要么通用。 谈论它与实际开发游戏相去甚远。

如果你还想了解游戏引擎的基本原理和功能,了解大公司引擎开发的基本流程,打好游戏引擎的知识基础,这本书《游戏引擎原理与实践第一卷基本框架》是推荐给大家。 书中专门配备了引擎和示例3D场景,让您可以了解开发游戏引擎的具体细节。

游戏引擎原理及应用_应用引擎原理游戏怎么关闭_应用引擎是什么

本书是腾讯游戏引擎设计师程东哲基于多年经验和积累的力作。 通过详细的实例讲解了游戏引擎的制作和开发技术。 受到Milo等游戏行业资深专家的大力推荐。

文章来源:http://mp.weixin.qq.com/s?src=11×tamp=1705982883&ver=5035&signature=Pg4*qiTLxWYbIWOepzgodtfMwemKGiS2PXJ3rqnp3WE5KgxnfnO8JqWAB1m-ugSOlBYtWhx1AhWuXqrAXpdldNMEzOLgiKHLtaQXTullVPYMzP3cdEPZJTDdC2*uKXZv&new=1