当前位置: 首页 新闻详细

程序员需要什么学历,腾讯资深程序员解密游戏引擎开发,建议一定学好数学

一、程序员需要什么学历

程序员通常需要至少大专以上的教育背景。一些知名企业,如腾讯和华为,倾向于招聘985或211工程院校的本科生。然而,实际上,对于程序员职位,教育程度的要求因公司而异。技术岗位尤其看重实际技能,技术能力强的候选人可能会得到学历要求上的放宽。因此,尽管建议最低学历为大专,学历不足的程序员在求职时可能会遇到限制,特别是如果他们希望加入知名企业或获得晋升。提升学历对于想在编程职业道路上取得长远成就的人来说,同样重要。

程序员必须掌握的技能包括:

1.熟练使用开发工具:程序员应至少熟练掌握两种至三种开发工具。C/C++和Java是强烈推荐的,因为C/C++的高效率和灵活性使其成为开发中的强大工具,而Java在企业级应用中广泛使用。

2.需求理解能力:程序员需要准确理解任务单上的需求。他们不仅要关注软件的功能需求,还要注意性能需求。此外,他们应能评估自己的模块对整个项目的影响及潜在风险。

二、程序员用的最多的5款app,一款没用过一定是假程序员!

如果你偷窥到程序员手机里面装有撩妹的app,那么不用惊讶,因为程序员偶尔也需要浪一下嘛!
  如果你发现程序员手机装有以下5款app,那么丝毫不用质疑,因为程序员比谁都更需要技术活。继续看下去,注意哦,前方高能,要是你手机里没有其中任何一款app,你一定是假程序员!
  第一款:CSDNAPP
  用途:技术难题解答
  CSDNAPP是全球最大的IT中文社区,这一点应该没有人想反驳吧?程序员在程序开发中遇到了技术难题,可以跳过你们的技术总监,直接来CSNDAPP,在这里都会有牛人随时为你答疑解惑。

牛客含有公司真题模考:腾讯,百度,阿里巴巴,Google,微软,华为,英特尔等名企历年笔试面试真题,提供网易,360,滴滴,今头条,美团,乐视,搜狐畅游等名企内推,校园招聘和实习兼职信息。

腾讯资深程序员解密游戏引擎开发,建议一定学好数学

原创2020-03-1017:51·异步社区


对很多爱玩游戏的男生来说,游戏行业一定会有值得热爱的工作。但入行之后才知道玩游戏和开发游戏是两回事!


给无数人带去快乐的游戏,开发难度大吗?入行门槛高吗?

无数对游戏行业憧憬的人都有这样的疑问。


我们先从和游戏开发密切相关的引擎说起吧。


游戏引擎技术在国外发展十分迅速,但国内游戏行业起步相对较晚,再加上从业者有时急于求成,引擎的人才积累远远不如国外。


游戏引擎到底是什么呢?


在游戏玩家看来,游戏画面的表现力越好,游戏场面的震撼程度越大,游戏体验的真实感越强,底层的游戏引擎就可能越强大。

(图片来源:绝地逃生)

从专业角度来说,游戏引擎是指一些已编写好的可编辑计算机游戏系统或者一些交互式实时图像应用程序的核心组件。这些系统为游戏设计者提供编写游戏所需的各种工具,其目的在于让游戏设计者能容易和快速地写出游戏程序而不用从零开始。


不管游戏是怎样的形式(是角色扮演游戏、即时策略游戏、冒险解谜游戏或是动作射击游戏),哪怕是一个只有1兆的小游戏,也需要游戏引擎技术。


引擎相当于游戏的框架,框架打好后,关卡设计师、建模师、动画师可往里填充内容,对于开发游戏来说乃重中之重。


当然,勇于迎难而上的人并不少,在兴趣的驱动下,学习游戏引擎技术开发并非遥不可及的事。那今天先给大家讲一下游戏引擎开发路上的第一个拦路虎——数学算法


基本数学

从VSMath这个文件说起


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

以下几个宏定义是用来判断精度的,尤其是判断两个浮点数是否相等,因为绝对的相等是没有的,误差必须考虑进去。

#defineVSFRONT0#defineVSBACK1#defineVSON2#defineVSCLIPPED3#defineVSCULLED4#defineVSVISIBLE5#defineVSINTERSECT3#defineVSOUT4#defineVSIN5#defineVSNOINTERSECT6//弧度和角度转换函数inlineVSREALRadianToAngle(VSREALRadian){return(Radian*180.0f)/VSPI;}inlineVSREALAngleToRadian(VSREALAngle){return(Angle*VSPI)/180.0f;}//判断是否为2NinlineboolIsTwoPower(unsignedintuiN){return!(uiN(uiN-1));}inlineunsignedshortFloatToHalf(VSREALValue)inlineVSREALHalfToFloat(unsignedshortValue)inlineunsignedintCompressUnitFloat(VSREALf,unsignedintBit=16)inlineunsignedintCompressFloat(VSREALf,VSREALMax,VSREALMin,unsignedintBit=16)inlineVSREALDecompressUnitFloat(unsignedintquantized,unsignedintBit=16)inlineVSREALDecompressFloat(unsignedintquantized,VSREALMax,VSREALMin,unsignedintBit=16)//计算正弦和余弦查找表,加快正弦和余弦计算速度for(unsignedinti=0;i<=360;i++){VSREALiRadian=AngleToRadian(VSREAL(i));FastSin[i]=SIN(iRadian);FastCos[i]=COS(iRadian);}inlineVSREALVSMATH_APIGetFastSin(unsignedinti);inlineVSREALVSMATH_APIGetFastCos(unsignedinti);VSREALGetFastSin(unsignedinti){returnFastSin[i];}VSREALGetFastCos(unsignedinti){returnFastCos[i];}

下面两个函数通过给定长度的数据来计算出一个哈希索引,返回值为32位的哈希。

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

对于引擎而言,相关的数据都不多,所以冲突为0。

voidVSInitCRCTable()unsignedintCRC32Compute(constvoid*pData,unsignedintuiDataSize)

最后介绍SSE(StreamingSIMDExtensions,其中SIMD是SingleInstructionMultipleData缩写,表示单指令多数据)指令加速数学库。

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


VSFastFunction文件里面用到的是汇编SSE库,在VSVector3、VSMatrix3X3、VSMatrix4X4文件中用到的高级语言版SSE库,较容易理解。

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

//汇编版SSE库voidVSFastAdd(constVSMatrix3X3WInM1,constVSMatrix3X3WInM2,VSMatrix3X3WOutM){//VS支持内嵌汇编__asm{moveax,[InM2];movecx,[InM1];movupsxmm4,[eax];movupsxmm5,[eax+16];movupsxmm6,[eax+32];movupsxmm7,[eax+48];moveax,[OutM];movupsxmm0,[ecx];movupsxmm1,[ecx+16];movupsxmm2,[ecx+32];movupsxmm3,[ecx+48];addpsxmm0,xmm4;movups[eax],xmm0;addpsxmm1,xmm5;movups[eax+16],xmm1;addpsxmm2,xmm6;movups[eax+32],xmm2;addpsxmm3,xmm7;movups[eax+48],xmm3;}}//高级语言版SSE库voidVSMatrix3X3W::operator-=(VSREALf){__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];}

基本数学单元

三维向量


VSVector3表示三维向量,这个类既可表示一个3D向量,也可以表示一个点。

所以这个类提供了3D向量应该具有的函数和作为一个空间点应该具有的函数。

classVSMATH_APIVSVector3{public:union{VSREALm[3];struct{VSREALx,y,z;};};}

矩阵类与向量类一样,都定义了union类型,通过数组方式或下标方式均可以访问这个向量的类属性。

VSVector3类中的相关函数如下。

//长度inlineVSREALGetLength(void)const;//长度的平方inlineVSREALGetSqrLength(void)const;//乘以-1inlinevoidNegate(void);//单位化inlinevoidNormalize(void);//叉积inlinevoidCross(constVSVector3v1,constVSVector3v2);//点积VSREALoperator*(constVSVector3v)const;//两个向量的夹角(弧度)VSREALAngleWith(VSVector3v);//用四元数旋转向量VSQuatoperator*(constVSQuatq)const;//3×3矩阵变换向量VSVector3operator*(constVSMatrix3X3m)const;//4×4矩阵变换向量VSVector3operator*(constVSMatrix3X3Wm)const;//向量加减voidoperator+=(constVSVector3v);voidoperator-=(constVSVector3v);VSVector3operator+(constVSVector3v)const;VSVector3operator-(constVSVector3v)const;//向量和常量加减voidoperator*=(VSREALf);voidoperator/=(VSREALf);voidoperator+=(VSREALf);voidoperator-=(VSREALf);booloperator==(constVSVector3v)const;VSVector3operator*(VSREALf)const;VSVector3operator/(VSREALf)const;VSVector3operator+(VSREALf)const;VSVector3operator-(VSREALf)const;

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


四维向量


VSVector3W表示四维向量,该类是在VSVector3上加了w分量,主要是为了方便与4×4矩阵进行运算。这对于w分量非1情况下的空间变换起了很大作用。另一个应用场景是用作颜色。

classVSMATH_APIVSVector3WtypedefclassVSVector3WVSColorRGBA;

以下是颜色操作的相关函数,都用于实现32位DWORD类型与4个float类型的相互转换。

DWORDGetDWARGB()const;DWORDGetDWRGBA()const;DWORDGetDWBGRA()const;DWORDGetDWABGR()const;voidGetUCColor(unsignedcharR,unsignedcharG,unsignedcharB,unsignedcharA)const;voidCreateFromARGB(DWORDARGB);voidCreateFromBGRA(DWORDBGRA);voidCreateFromRGBA(DWORDRGBA);voidCreateFormABGR(DWORDABGR);

下面几个关于颜色的组合函数都用于实现VSColorRGBA类型和DWORD类型的相互转换。

inlineDWORDVSDWCOLORARGB(unsignedchara,unsignedcharr,unsignedcharg,unsignedcharb){return(DWORD)((((a)0xff)<<24)|(((r)0xff)<<16)|(((g)0xff)<<8)|((b)0xff)));}inlineDWORDVSDWCOLORBGRA(unsignedchara,unsignedcharr,unsignedcharg,unsignedcharb){return(DWORD)((((b)0xff)<<24)|(((g)0xff)<<16)|(((r)0xff)<<8)|((a)0xff)));}inlineDWORDVSDWCOLORRGBA(unsignedchara,unsignedcharr,unsignedcharg,unsignedcharb){return(DWORD)((((r)0xff)<<24)|(((g)0xff)<<16)|(((b)0xff)<<8)|((a)0xff)));}inlineDWORDVSDWCOLORABGR(unsignedchara,unsignedcharr,unsignedcharg,unsignedcharb){return(DWORD)((((a)0xff)<<24)|(((b)0xff)<<16)|(((g)0xff)<<8)|((r)0xff)));}inlinevoidVSDWCOLORGetARGB(DWORDARGB,unsignedchara,unsignedcharr,unsignedcharg,unsignedcharb){a=(ARGB>>24)0xff;r=(ARGB>>16)0xff;g=(ARGB>>8)0xff;b=(ARGB)0xff;}inlinevoidVSDWCOLORGetBGRA(DWORDBGRA,unsignedchara,unsignedcharr,unsignedcharg,unsignedcharb){b=(BGRA>>24)0xff;g=(BGRA>>16)0xff;r=(BGRA>>8)0xff;a=(BGRA)0xff;}inlinevoidVSDWCOLORGetRGBA(DWORDRGBA,unsignedchara,unsignedcharr,unsignedcharg,unsignedcharb){r=(RGBA>>24)0xff;g=(RGBA>>16)0xff;b=(RGBA>>8)0xff;a=(RGBA)0xff;}inlinevoidVSDWCOLORGetABGR(DWORDABGR,unsignedchara,unsignedcharr,unsignedcharg,unsignedcharb){a=(ABGR>>24)0xff;b=(ABGR>>16)0xff;g=(ABGR>>8)0xff;r=(ABGR)0xff;}

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


3×3矩阵


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


需要提醒的是:一定要分清是左手还是右手坐标系,矩阵和向量是左乘还是右乘,矩阵是以行矩阵为主还是以列矩阵为主,并明白旋转的正方向是如何定义的。


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

//通过一个朝向创建旋转矩阵voidCreateFromDirection(VSVector3Direction,constVSVector3Up=VSVector3(0,1,0));voidCreateRotX(VSREALa);//绕x轴旋转voidCreateRotY(VSREALa);//绕y轴旋转voidCreateRotZ(VSREALa);//绕z轴旋转//绕z轴、x轴和y轴构建欧拉角voidCreateEluer(VSREALRoll,VSREALPitch,VSREALYaw)voidCreateAxisAngle(constVSVector3vAxis,VSREALa);//绕vAxis旋转a弧度//通过3个基向量创建旋转矩阵voidCreateRot(constVSVector3U,constVSVector3V,constVSVector3N);以下几个函数也要了解一下。

有时在引擎里也要获取矩阵的行向量和列向量,尤其是从一个物体的旋转矩阵中得到它的前方向、上方向和右方向(3个基向量U、V、N)。

//按行获得向量voidGetRowVector(VSVector3Row[3])const;//按行、按列获得向量voidGetColumnVector(VSVector3Column[3])const;voidGetRowVector(VSVector3Row0,VSVector3Row1,VSVector3Row2)const;voidGetColumnVector(VSVector3Column0,VSVector3Column1,VSVector3Column2)const;//获得基向量voidGetUVN(VSVector3UVN[3])const;voidGetUVN(VSVector3U,VSVector3V,VSVector3N)const;

有时也需要创建缩放矩阵,大部分引擎的缩放根据原点进行。

//创建缩放矩阵,根据原点缩放voidCreateScale(VSREALfX,VSREALfY,VSREALfZ);//根据轴缩放voidCreateScale(constVSVector3Axis,VSREALfScale);

从一个矩阵中获取旋转量和缩放量也较常用到。

voidGetScale(VSVector3Scale)const;voidGetScaleAndRotater(VSVector3Scale);

腾讯的程序员用什么开发工具好呢

下面的两个函数很少使用,本引擎用这两个函数来求点集的OBB包围盒。

//构造一个行向量、一个列向量inlinevoidCreateFromTwoVector(constVSVector3v1,constVSVector3v2);//求特征值、特征向量voidGetEigenSystem(VSREALEigenValue[3],VSVector3Eigen[3])const;

矩阵的乘法以及矩阵和向量的乘法采用以下函数实现。

inlineVSMatrix3X3operator*(constVSMatrix3X3Matrix)const;//矩阵相乘inlineVSVector3operator*(constVSVector3vc)const;//矩阵和向量相乘

矩阵只有相乘才有实际意义,矩阵相乘可以视为矩阵的“加法”。

听到这里很多读者可能很迷惑,相乘怎么是加法?

学过“离散数学”的人都学过群论,其中经常提到的加法只是特定范围的加法,不同的群有各自的加法。


举个例子:整数1的加法就是传统的加法1+1=2,减法11=0,也就是1+(?1)。

而矩阵的加法就是M1和M2相乘等于M,矩阵的减法就是M1和M2的逆矩阵相乘,只不过这个加法不满足交换律。

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

在理解了这个的基础上,引出矩阵的插值概念。

查看以下代码。

voidVSMatrix3X3::LineInterpolation(VSREALt,constVSMatrix3X3M1,constVSMatrix3X3M2){*this=M1*(1.0f-t)+M2*t;}voidVSMatrix3X3::Slerp(VSREALt,constVSMatrix3X3M1,constVSMatrix3X3M2){VSMatrix3X3M1Transpose,Temp;M1Transpose.TransposeOf(M1);Temp=M1Transpose*M2;VSREALfAnagle;VSVector3Axis;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矩阵创建voidCreateFrom3X3(constVSMatrix3X3Mat);//平移矩阵voidCreateTranslate(VSREALdx,VSREALdy,VSREALdz);voidCreateTranslate(constVSVector3V);

下面的函数为物体创建局部变换矩阵。

如果两个物体A、B都在同一个空间M下,B若要变换到A的空间下,则为A物体创建变换矩阵。

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


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

voidCreateInWorldObject(constVSVector3U,constVSVector3V,constVSVector3N,constVSVector3Point);

公告板(billboard)是一种特殊的面片,此处不过多介绍。一般公告板有两种:一种是完全面向相机的,一般多为粒子;另一种是只能沿y轴旋转的,尽量面向相机方向。

//建立公告牌变换矩阵voidCreateFormBillboard(constVSVector3vcPos,//公告牌位置constVSMatrix3X3CameraRotMatrix,//相机或其他矩阵boolbAxisY);//是否只选择沿y轴旋转

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

//构建相机矩阵(根据观察方向)boolCreateFromLookDir(constVSVector3vcPos,//相机位置constVSVector3vcDir,//观察方向constVSVector3vcWorldUp=VSVector3(0,1,0));//构建相机矩阵(根据目标位置)boolCreateFromLookAt(constVSVector3vcPos,//相机位置constVSVector3vcLookAt,//观察位置constVSVector3vcWorldUp=VSVector3(0,1,0));//上方向//建立透视投影矩阵boolCreatePerspective(VSREALfFov,//x方向的张角VSREALfAspect,//宽高比VSREALfZN,//近剪裁面VSREALfZF);//远剪裁面//建立正交投影矩阵boolCreateOrthogonal(VSREALfW,//宽VSREALfH,//高VSREALfZN,//近剪裁面VSREALfZF);//远剪裁面//建立视口矩阵boolCreateViewPort(VSREALfX,VSREALfY,VSREALfWidth,VSREALfHeight,VSREALfMinz,VSREALfMaxz);

下面几个也是常用的函数,因为在3×3矩阵里都有得到旋转和缩放分量的函数,所以未在4×4矩阵里直接提供。

inlinevoidIdentity(void);//单位矩阵inlinevoidTransposeOf(constVSMatrix3X3WMatrix);//转置inlinevoidInverseOf(constVSMatrix3X3WMat);//求逆inlineVSMatrix3X3WGetTranspose()const;//转置inlineVSMatrix3X3WGetInverse()const;//求逆inlineVSVector3GetTranslation(void)const;//得到平移量inlinevoidGet3X3(VSMatrix3X3Mat)const;//得到3*3部分

下面几个也是比较常用的,但VSVector3和4×4矩阵相乘是点与4×4矩阵相乘,表示对点的空间变换。

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

inlineVSMatrix3X3Woperator*(constVSMatrix3X3WMatirx)const;//矩阵相乘inlineVSVector3operator*(constVSVector3vc)const;//矩阵和向量乘inlineVSVector3Woperator*(constVSVector3Wvc)const;//矩阵和向量乘//应用3*3的部分inlineVSVector3Apply3X3(constVSVector3v)const;//应用平移inlineVSVector3ApplyTranlate(constVSVector3Point)const;

四元数


VSQuat表示四元数类。下面的函数创建四元数。

//通过旋转轴和旋转角构造四元数voidCreateAxisAngle(constVSVector3Axis,VSREALfAngle);//由欧拉角构造四元数voidCreateEule(VSREALfRoll,VSREALfPitch,VSREALfYaw);

通过旋转矩阵得到四元数的函数写在了VSMatrix3X3里面。

//得到欧拉角voidGetEulers(VSREALfRoll,VSREALfPitch,VSREALfYaw)const;//从四元数得到变换矩阵voidGetMatrix(VSMatrix3X3Matrix)const;//取得旋转轴和旋转角voidGetAxisAngle(VSVector3Axis,VSREALfAngle)const;

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

//单位化voidNormalize();//求共轭VSQuatGetConjugate()const;//得到长度VSREALGetLength(void)const;//求逆VSQuatGetInverse()const;//求点积VSREALDot(constVSQuatq)const;//求共轭VSQuatoperator~(void)const;//求幂VSQuatPow(VSREALexp)const;//求以e为底的对数VSQuatLn()const;//求以e为底的指数VSQuatExp()const;voidoperator/=(VSREALf);VSQuatoperator/(VSREALf)const;voidoperator*=(VSREALf);VSQuatoperator*(VSREALf)const;VSQuatoperator*(constVSVector3v)const;VSQuatoperator*(constVSQuatq)const;voidoperator*=(constVSQuatq);voidoperator+=(constVSQuatq);VSQuatoperator+(constVSQuatq)const;voidoperator-=(constVSQuatq);VSQuatoperator-(constVSQuatq)const;booloperator==(constVSQuatq)const;

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

//求q2绕q1旋转后的四元数voidRotate(constVSQuatq1,constVSQuatq2);//旋转一个向量VSVector3Rotate(constVSVector3v)const;

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

//插值voidSlerp(VSREALt,constVSQuatq1,constVSQuatq2);//三角形二维球型插值voidTriangleSlerp(VSREALt1,VSREALt2,constVSQuatq1,constVSQuatq2,constVSQuatq3);//四元数样条插值voidSlerp(VSREALt,constVSQuatq1,constVSQuatq2,constVSQuats1,constVSQuats2);voidSlerpSValueOf(constVSQuatq1,constVSQuatq2,constVSQuatq3);

基本图形单元

这一节主要介绍引擎中常用的基本图元,相机裁剪、射线检测、物体碰撞等都与它们密切相关,每一个图元是一个类,类的属性是根据空间几何定义来封装的,类的方法也很容易分类,主要是与其他图元的位置关系,或者与其他图元的距离判定(《计算机图形学几何工具算法详解》一书中有详细的算法描述)。

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



点用VSVector3类表示。


直线、射线、线段


VSLine3表示直线,直线定义为一个点和一个方向,与射线的区别为直线的方向可以为负方向,这个方向一定是单位化的。

P=P0+tDir

上面的等式是直线的参数化方程,t为参数。

给定t,就可以算出P;给定P,则可以算出t。

//给定点P,求tboolGetParameter(constVSVector3Point,VSREALfLineParameter)const;//构建直线inlinevoidSet(constVSVector3Orig,constVSVector3Dir);//得到P0和dirinlineconstVSVector3GetOrig()const;inlineconstVSVector3GetDir()const;//给定t,求PinlineVSVector3GetParameterPoint(VSREALfLineParameter)const;

下面的函数用于判断直线与其他图元的位置关系。

//判断直线与三角形的位置关系。bCull为是否为背面剪裁,是否考虑朝向,t返回相交长度//VSNOINTERSECTVSNTERSECTintRelationWith(constVSTriangle3Triangle,boolbCull,VSREALfLineParameter,VSREALfTriangleParameter[3])const;//判断直线与平面的位置关系//VSNOINTERSECTVSNTERSECTVSONVSBACKVSFRONTintRelationWith(constVSPlane3Plane,boolbCull,VSREALfLineParameter)const;//判断直线与矩形的位置关系//VSNOINTERSECTVSNTERSECTintRelationWith(constVSRectangle3Rectangle,boolbCull,VSREALfLineParameter,VSREALfRectangleParameter[2])const;//判断直线与球的位置关系//VSNOINTERSECTVSNTERSECTintRelationWith(constVSSphere3sphere,unsignedintQuantity,VSREALtNear,VSREALtFar)const;//判断直线与OBB的位置关系//VSNOINTERSECTVSNTERSECTintRelationWith(constVSOBB3OBB,unsignedintQuantity,VSREALtNear,VSREALtFar)const;//判断直线与AABB的位置关系//VSNOINTERSECTVSNTERSECTintRelationWith(constVSAABB3AABB,unsignedintQuantity,VSREALtNear,VSREALtFar)const;//判断直线与多边形的位置关系//VSNOINTERSECTVSNTERSECTintRelationWith(constVSPolygon3Polygon,VSREALfLineParameter,boolbCull,intiIndexTriangle,VSREALfTriangleParameter[3])const;

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

//计算点到直线的距离VSREALSquaredDistance(constVSVector3Point,VSREALfLineParameter)const;//计算直线和直线的距离VSREALSquaredDistance(constVSLine3Line,VSREALfLine1Parameter,VSREALfLine2Parameter)const;//计算直线和射线的距离VSREALSquaredDistance(constVSRay3Ray,VSREALfLineParameter,VSREALfRayParameter)const;//计算直线和线段的距离VSREALSquaredDistance(constVSSegment3Segment,VSREALfLineParameter,VSREALfSegmentParameter)const;//计算直线和三角形的距离VSREALSquaredDistance(constVSTriangle3Triangle,VSREALfLineParameter,VSREALfTriangleParameter[3])const;//计算直线和矩形的距离VSREALSquaredDistance(constVSRectangle3Rectangle,VSREALfLineParameter,VSREALfRectangleParameter[2])const;//计算直线和OBB的距离VSREALSquaredDistance(constVSOBB3OBB,VSREALfLineParameter,VSREALfOBBParameter[3])const;//计算直线和球的距离VSREALDistance(constVSSphere3Sphere,VSREALfLineParameter,VSVector3SpherePoint)const;//计算直线和平面的距离VSREALDistance(constVSPlane3Plane,VSVector3LinePoint,VSVector3PlanePoint)const;//计算直线和AABB的距离VSREALSquaredDistance(constVSAABB3AABB,VSREALfLineParameter,VSREALfAABBParameter[3])const;//计算直线和多边形的距离VSREALSquaredDistance(constVSPolygon3Polygon,VSREALfLineParameter,intIndexTriangle,VSREALfTriangleParameter[3])const;

VSRay3表示射线,射线和直线的唯一区别在于t可以为负。

VSSegment3表示线段,线段不同于直线,它有端点属性。

对于P=P0+tDir来说,t是有范围的,所以它的定义方式有两种:第一种基于两个点,第二种基于方向和长度。

inlinevoidSet(constVSVector3Orig,constVSVector3End);inlinevoidSet(constVSVector3Orig,constVSVector3Dir,VSREALfLen);

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


VSPlane表示平面,平面的参数化方程为N(P0–P1)=0。

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

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

//通过平面法向量和平面上一点确定一个平面inlinevoidSet(constVSVector3N,constVSVector3P);//通过平面法向量和D确定一个平面inlinevoidSet(constVSVector3N,VSREALfD);//通过3个点确定一个平面inlinevoidSet(constVSVector3P0,constVSVector3P1,constVSVector3P2);inlinevoidSet(constVSVector3Point[3]);

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

//计算点到平面的距离VSREALDistance(constVSVector3Point,VSVector3PlanePoint)const;//计算平面和球的距离VSREALDistance(constVSSphere3Sphere,VSVector3SpherePoint)const;//计算直线和平面的距离VSREALDistance(constVSLine3Line,VSVector3PlanePoint,VSVector3LinePoint)const;//计算射线和平面的距离VSREALDistance(constVSRay3Ray,VSVector3PlanePoint,VSVector3RayPoint)const;//计算线段和平面的距离VSREALDistance(constVSSegment3Segment,VSVector3PlanePoint,VSVector3SegmentPoint)const;//计算平面和平面的距离VSREALDistance(constVSPlane3Plane,VSVector3Plane1Point,VSVector3Plane2Point)const;//计算平面和三角形的距离VSREALDistance(constVSTriangle3Triangle,VSVector3PlanePoint,VSVector3TrianglePoint)const;//计算矩形和平面的距离VSREALDistance(constVSRectangle3Rectangle,VSVector3PlanePoint,VSVector3RectanglePoint)const;//计算OBB和平面的距离VSREALDistance(constVSOBB3OBB,VSVector3PlanePoint,VSVector3OBBPoint)const;//计算AABB和平面的距离VSREALDistance(constVSAABB3AABB,VSVector3PlanePoint,VSVector3AABBPoint)const;//计算平面和多边形的距离VSREALDistance(constVSPolygon3Polygon,VSVector3PlanePoint,intIndexTriangle,VSVector3TrianglePoint)const;

下面的函数用于判断平面与其他图元的位置关系。

//判断点和平面的位置关系//VSFRONTVSBACKVSPLANARintRelationWith(constVSVector3Point)const;//判断直线和平面的位置关系/VSNOINTERSECTVSNTERSECTVSONVSBACKVSFRONTintRelationWith(constVSLine3Line,boolbCull,VSREALfLineParameter)const;//判断射线和平面的位置关系//VSNOINTERSECTVSNTERSECTVSONVSBACKVSFRONTintRelationWith(constVSRay3Ray,boolbCull,VSREALfRayParameter)const;//判断线段和平面的位置关系//VSNOINTERSECTVSNTERSECTVSONVSBACKVSFRONTintRelationWith(constVSSegment3Segment,boolbCull,VSREALfSegmentParameter)const;//判断平面和OBB的位置关系//VSFRONTVSBACKVSINTERSECTintRelationWith(constVSOBB3OBB)const;//判断平面和AABB的位置关系//VSFRONTVSBACKVSINTERSECTintRelationWith(constVSAABB3AABB)const;//判断平面和球的位置关系//VSFRONTVSBACKVSINTERSECTintRelationWith(constVSSphere3Sphere)const;//判断平面和三角形的位置关系//VSONVSFRONTVSBACKVSINTERSECTintRelationWith(constVSTriangle3Triangle)const;intRelationWith(constVSTriangle3Triangle,VSSegment3Segment)const;//判断参数平面和平面的位置关系//VSNOINTERSECTVSINTERSECTintRelationWith(constVSPlane3Plane)const;intRelationWith(constVSPlane3Plane,VSLine3Line)const;//判断平面和矩形的位置关系//VSONVSFRONTVSBACKVSINTERSECTintRelationWith(constVSRectangle3Rectangle)const;intRelationWith(constVSRectangle3Rectangle,VSSegment3Segment)const;//判断平面和多边形的位置关系//VSONVSFRONTVSBACKVSINTERSECTintRelationWith(constVSPolygon3Polygon)const;intRelationWith(constVSPolygon3Polygon,VSSegment3Segment)const;//判断平面和圆柱的位置关系intRelationWith(constVSCylinder3Cylinder3)const;

VSTriangle3表示三角形类,三角形类从平面类派生而来,它的构造方式很简单,就是3个点。

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

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

boolGetParameter(constVSVector3Point,VSREALfTriangleParameter[3])const;inlineVSVector3GetParameterPoint(VSREALfTriangleParameter[3])const;

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


球体、有向包围盒、立方体


VSSphere3表示球体,VSOBB3表示有向包围盒,VSAABB3表示立方体。因为没有实现物理引擎,所以圆柱体、胶囊体和椭球体等都没单独实现。在引擎里面球体和立方体用得最多,都用在场景管理里。除了这些之外,还有一些合并算法,球体与球体合并,立方体与立方体合并。


不同游戏引擎的内部架构千差万别,而且游戏引擎涉及的知识点甚多,很少有人能全面把握每一个知识细节。


同时,游戏引擎属于实践性的工程,必须有足够令人信服的演示示例以及代码支持,加上商用引擎的授权、作者个人时间有限等各方面的因素,导致市面上的游戏引擎图书要么泛泛而谈,要么距离真正开发游戏相去甚远。


如果你还想了解游戏引擎的基本原理和作用、了解大公司开发引擎的基本流程、获得良好的游戏引擎方面的知识储备,这本《游戏引擎原理与实践卷1基础框架》推荐给大家,本书专门配套的引擎和示例,可以了解开发游戏引擎的具体细节。

本书是腾讯游戏引擎设计师程东哲基于多年经验和积累的力作,详尽示例,诠释游戏引擎制作与开发技术,Milo等游戏业内资-深专家鼎力推荐。


关注”异步图书"微信号,回复:“51807”,下载本书配套资源。


-END-

发布人:qq513975814 发布时间:2024-08-03