【DirectX游戏编程】游戏中摄像机类的实现(上篇:如何获得观察坐标系转换矩阵)

本文深入解析了3D游戏中观察坐标系转换矩阵的构造原理,详细介绍了如何通过坐标系变换实现不同视角观察3D场景,并给出了计算观察坐标系转换矩阵的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们知道在DX中,坐标的转换是通过与矩阵相乘实现的,一个坐标乘一个转换矩阵得到的新坐标就是转换后的坐标(平移,旋转,缩放后的坐标)

物体的屏幕坐标 = 自身坐标系坐标 世界坐标系转换矩阵 观察坐标系转换矩阵 投影矩阵 视口转换矩阵

自身坐标系坐标 世界坐标系转换矩阵 可以的到物体在3D世界中的位置,相当于你把一个物体放在了3D世界中

然后你只要设置不同的观察坐标系转换矩阵就就可以实现在不同的地方、角度观察3D世界(就是实现你在3D世界中移动)

至于之后再乘 投影矩阵 视口转换矩阵 就是将3D世界转换成2D平面显示在2D的屏幕上


而要完成一个摄像机类,观察坐标系转换矩阵的获得是必不可少的,我们在渲染之前调用IDirect3DDevice9::SetTransfromD3DTS_VIEW,&观察坐标系转换矩阵)把观察坐标系转换矩阵告诉DX,这个矩阵就是从我们的摄像机类得到的。通过它,我们可以实现在游戏场景中的漫游。

 

观察坐标系就是以我们的眼睛为原点,右手方向为X轴正方向,头顶方向为Y轴正方向,正前方为Z轴正方向去描述物体位置坐标的坐标系(注意这个坐标系是左手系),看下面的图:


 

而我们的眼睛又处于世界坐标系中,所以可以用世界坐标系的坐标去表示观察坐标系的三个坐标轴和眼睛的位置。看下面的图:



(哈哈,注意到了吧,我们不一定是立正在地上的,还可能是歪着身体甚至躺着的......)

 

那让我们看看怎么得到“将物体从世界坐标系变换到观察坐标系”的转换矩阵:

如果是真的从一个物体在两个坐标系之间的变换去考虑的话,问题会变得十分复杂,所以我们换个思路去考虑。

如果我们的眼睛正好在世界坐标系的原点,右手方向正好为在世界坐标系的X轴正方向,头顶方向正好为在世界坐标系的Y轴正方向,又刚刚好向世界坐标系的Z轴正方向看去,那么观察坐标系不就和世界坐标系重合了吗?不就不用转换了吗?(实在太省事了....)

 

可惜事与愿违,那么多的巧合是在很难遇到,而且我们又太好动,总是走来走去,那这种假设就更加不科学了。

但就算眼睛的位置是随意的,我们也可以把它移到我们想要的位置啊!

 

看,如果我们让所有的物体都跟着我们一起动,当我们自己走到世界的原点,然后再立正站好,不就可以了吗?(整个世界跟着你动的感觉......实在太牛逼了。但实际上因为每个物体在变换时都会乘以你所提供的转换矩阵,相当于跟着你在动,所以这种假设是十分形象的。)

你原来的位置

走到世界的原点

转向正确的方向

(原谅我只画了俯视图—,—)

 

 

所以我们只要做两步:

1.先走到世界的原点

DX里,移动是通过和矩阵相乘来实现的(如果你连这个都不理解,最好去补一补基础)

假设我们的位置在 [ posX  posY  posZ ],那我们只需要往X负方向走posX的距离,往Y负方向走posY的距离,往Z负方向走posZ的距离。

所以我们可以用这个用这个转换矩阵去到我们到达世界的原点:


验证一下,看我们的位置坐标去与之相乘:


(为了实现DX里的平移变换运算,坐标都是 [x,y,z,w] 形式的四维坐标,我们只需要知道xyz坐标就是三维世界里的xyz坐标,w就让他等于1就好了。当然如果你表示的是向量,就要让w0,因为DX里规定向量的起点在原点,所以不能对向量进行平移操作,何况向量是指方向的,可以旋转和收缩就足够了。)

 

2.立正站好

我们虽然已经到了世界的原点,但可能是爬过去的,你正面着大地.....

来,让我们假设我们的右手方向原先是 [ Rx Ry Rz ] ,头顶方向原先是 [ Ux Uy Uz ],原来我们面向 [ Lx Ly Lz ]而且它们都是单位化的

我们要想办法立正,就是说让我们的右手指向 [ 1 0 0 ],头向 [ 0 1 0 ],面向 [ 0 0 1 ]

翻译成数学的语言就是乘以一个变换矩阵:




把它们合起来:


我们要做的就是求这个矩阵的逆矩阵。

由于 [ Rx Ry Rz ] [ Ux Uy Uz ][ Lx Ly Lz ] 都是单位化的(长度为1),实际上它是单位正交阵所以它的逆就是它的转置矩阵

(这是线性代数的东西了,上课睡觉和逃课的同学去翻下书吧)

 

所以就可以得到:


当然,DX里的矩阵都是44的,所以我们把它扩展一下(这个扩展还真不太好解释,记住就好,也不难吧)


好我们将两步连起来做一遍:


-pos·R = -posX * Rx - posY * Ry - posZ * Rz

-pos·U = -posX * Ux - posY * Uy - posZ *Uz

-pos·L = -posX * Lx - posY * Ly - posZ * Lz

(就是将两矩阵相乘,注意顺序,先走到原点再转向)

好了,这样我们就得到一个观察坐标系转换矩阵了。

 

通过上面这么长一段东西,我们发现,只要知道:

1.眼睛在世界坐标系中的位置

2.右手方向在世界坐标系中的向量表示

3.头顶方向在世界坐标系中的向量表示

4.正前方方向在世界坐标系中的向量表示

就能求出观察坐标系转换矩阵了

 

上篇到此为止,最重要的理论部分已经讲完了。在下篇里我会具体讲讲这个摄像机类的代码实现

PS:参考书——《DirectX 9.0 3D游戏开发编程基础》

 

 

本课程主要以口袋西游为例,学习一个网络游戏是怎么通过游戏服务器与玩家客户端进行通信交互的,通过OD,CE等工具对游戏进行调试,找到各个数据基址(例如角色基址,背包基址等),找出游戏里面的功能CALL(例如寻路CALL,打坐CALL等)及参数分析,并且编码实现功能。本课程可以带领你游戏逆向入门可以学会 CE,OD,找游戏基址,功能CALL等实现变态功能可以更深入的理解从高级语言到汇编语言的一个对应过程可以学会 逆向软件  外挂与反外挂 破解防破解  游戏安全的基础知识可以为以后的及逆向高级课程 打下良好的基础可以自己分析游戏数据,用C语言实现游戏外挂功能等重点:  本套课程的重点就是带领大家分析游戏数据,毫不客气的说,各位学完此套课程对分析游戏数据这块会有一个质的飞跃。课程目录  01.课程简介及功能演示  02.CE找人物基址人物属性偏移  03.OD找人物基址人物属性偏移  04.创建MFC DLL项目  05.代码实现输出人物信息  06.发包函数概述  07.怎么看待重写的发包函数  08.普通发包与线程发包  09.找打坐CALL及参数分析  10.代码实现打坐CALL  11.喊话CALL及参数分析  12.代码实现喊话CALL  13.找寻路CALL及参数分析  14.代码编写寻路CALL  15.穿装备CALL及参数分析  16.代码实现穿装备CALL  17.NPC对话CALL  18.代码实现NPC对话CALL  19.唤出宠物  20.宠物合体  21.收回宠物  22.取下宠物
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值