返回


这两天学习了3D图形学。独自花了2天时间设计了一个自由移动的DX9的摄像机类。下面我仔细讲述一下我的Camera类是如何完成的。

e3d_camere.h

#ifndef __e3d_camera__
#define __e3d_camera__
#include <d3dx9.h>namespace e3d {class Camera{public:Camera(IDirect3DDevice9* Device = 0):m_right(D3DXVECTOR3(1.f, 0.f, 0.f)),m_up(D3DXVECTOR3(0.f, 1.f, 0.f)),m_look(D3DXVECTOR3(0.f, 0.f, 1.f)),m_position(D3DXVECTOR3(0.f, 0.f, 0.f)),m_aspect(800.f / 600),m_fovY(D3DX_PI*0.25),m_nearZ(1.f),m_farZ(1000.f),m_view(),m_proj(),_Device(0) {D3DXMatrixIdentity(&m_view);_Device = Device;D3DXMATRIX V;D3DXMatrixLookAtLH(&V, &m_position, &m_look, &m_up);//Device->SetTransform(D3DTS_VIEW, &V);D3DXMatrixPerspectiveFovLH(&m_proj,m_fovY, // 90 - degreem_aspect,m_nearZ,m_farZ);}//设置摄像机位置void SetPosition(float x, float y, float z) { m_position.x = x; m_position.y = y; m_position.z = z;}void SetPositionXM(D3DXVECTOR3 pos) {m_position = pos; }//获得摄像位置及朝向相关参数D3DXVECTOR3 GetPosition()  const { return m_position; }D3DXVECTOR3 GetRight()      const { return m_right; }D3DXVECTOR3 GetUp()            const { return m_up; }D3DXVECTOR3 GetLook()     const { return m_look; }D3DXVECTOR3 GetPositionXM() const { return m_position; }D3DXVECTOR3 GetRightXM()    const { return m_right; }D3DXVECTOR3 GetUpXM()      const { return m_up; }D3DXVECTOR3 GetLookXM()       const { return m_look; }//获得投影相关参数float GetNearZ()  const { return m_nearZ; }float GetFarZ()        const { return m_farZ; }float GetFovY()     const { return m_fovY; }float GetFovX()     const { return atan(m_aspect * tan(m_fovY * 0.5f)) * 2.f; }float GetAspect()    const { return m_aspect; }//获得相关矩阵D3DXMATRIX View()             const { return m_view; }D3DXMATRIX Projection()     const { return m_proj; }D3DXMATRIX ViewProjection() const { return m_view * m_proj; }//设置投影相关参数void SetLens(float fovY, float ratioAspect, float nearZ, float farZ){m_fovY = fovY;m_aspect = ratioAspect;m_nearZ = nearZ;m_farZ = farZ;D3DXMatrixPerspectiveFovLH(&m_proj,m_fovY, // 90 - degreem_aspect,m_nearZ,m_farZ);}//通过位置+观察点来设置视角矩阵void LookAtXM(D3DXVECTOR3 pos, D3DXVECTOR3 lookAt, D3DXVECTOR3 worldUp) {D3DXVECTOR3 look, right, up;D3DXVec3Normalize(&look,&(lookAt - pos));D3DXVec3Cross(&right, &worldUp, &worldUp);D3DXVec3Normalize(&right, &right);D3DXVec3Cross(&up, &look, &right);//XMVECTOR right = XMVector3Normalize(XMVector3Cross(worldUp, look));//XMVECTOR up = XMVector3Cross(look, right);m_position = pos;m_right = right;m_up = up;m_look = look;//XMStoreFloat3(&m_position, pos);//XMStoreFloat3(&m_right, right);//XMStoreFloat3(&m_up, up);//XMStoreFloat3(&m_look, look);}void LookAt(D3DXVECTOR3 pos, D3DXVECTOR3 lookAt, D3DXVECTOR3 worldUp) {LookAtXM(pos, lookAt, worldUp);}//基本操作void Walk(float dist)            //前后行走{ D3DXVECTOR3 pos = m_position;D3DXVECTOR3 look = m_look;pos += D3DXVECTOR3(dist * look.x,dist * look.y,dist * look.z);m_position = pos;}void Strafe(float dist)     //左右平移{D3DXVECTOR3 pos = m_position;D3DXVECTOR3 right = m_right;pos += D3DXVECTOR3(dist * right.x, dist * right.y, dist * right.z);m_position = pos;}void Pitch(float angle)       //上下点头{D3DXMATRIX rotation;D3DXMatrixRotationAxis(&rotation, &m_right, angle);D3DXVec3TransformCoord(&m_up, &m_up, &rotation);D3DXVec3TransformCoord(&m_look, &m_look, &rotation);//XMStoreFloat3(&m_up, XMVector3TransformNormal(XMLoadFloat3(&m_up), rotation));//XMStoreFloat3(&m_look, XMVector3TransformNormal(XMLoadFloat3(&m_look), rotation));}void Yaw(float angle)        //上下点头{D3DXMATRIX rotation;D3DXMatrixRotationAxis(&rotation, &m_up, angle);D3DXVec3TransformCoord(&m_right, &m_right, &rotation);D3DXVec3TransformCoord(&m_look, &m_look, &rotation);//XMStoreFloat3(&m_up, XMVector3TransformNormal(XMLoadFloat3(&m_up), rotation));//XMStoreFloat3(&m_look, XMVector3TransformNormal(XMLoadFloat3(&m_look), rotation));}void RotateY(float angle)     //左右插头{//XMMATRIX rotation  = XMMatrixRotationY(angle);D3DXMATRIX rotation;D3DXMatrixRotationY(&rotation, angle);D3DXVec3TransformCoord(&m_right, &m_right, &rotation);D3DXVec3TransformCoord(&m_up, &m_up, &rotation);D3DXVec3TransformCoord(&m_look, &m_look, &rotation);//XMStoreFloat3(&m_right, XMVector3TransformNormal(XMLoadFloat3(&m_right), rotation));//XMStoreFloat3(&m_up, XMVector3TransformNormal(XMLoadFloat3(&m_up), rotation));//XMStoreFloat3(&m_look, XMVector3TransformNormal(XMLoadFloat3(&m_look), rotation));}void UpdateView() {      //更新相关矩阵D3DXVECTOR3 r = m_right;D3DXVECTOR3 u = m_up;D3DXVECTOR3 l = m_look;D3DXVECTOR3 p = m_position;D3DXVec3Cross(&r, &u, &l);D3DXVec3Normalize(&r, &r);D3DXVec3Cross(&u, &l, &r);D3DXVec3Normalize(&u, &u);D3DXVec3Normalize(&l, &l);//r = XMVector3Normalize(XMVector3Cross(u, l));//u = XMVector3Normalize(XMVector3Cross(l, r));//l = XMVector3Normalize(l);float x = -D3DXVec3Dot(&p, &r);float y = -D3DXVec3Dot(&p, &u);float z =- D3DXVec3Dot(&p, &l);//float x = -XMVectorGetX(XMVector3Dot(p, r));//float y = -XMVectorGetX(XMVector3Dot(p, u));//float z = -XMVectorGetX(XMVector3Dot(p, l));m_right = r;m_up = u;m_look = l;m_position = p;//XMStoreFloat3(&m_right, r);//XMStoreFloat3(&m_up, u);//XMStoreFloat3(&m_look, l);//XMStoreFloat3(&m_position, p);m_view(0, 0) = m_right.x; m_view(0, 1) = m_up.x; m_view(0, 2) = m_look.x;   m_view(0, 3) = 0;m_view(1, 0) = m_right.y;    m_view(1, 1) = m_up.y; m_view(1, 2) = m_look.y;   m_view(1, 3) = 0;m_view(2, 0) = m_right.z;    m_view(2, 1) = m_up.z; m_view(2, 2) = m_look.z;   m_view(2, 3) = 0;m_view(3, 0) = x;        m_view(3, 1) = y;  m_view(3, 2) = z;      m_view(3, 3) = 1;}private:D3DXVECTOR3  m_right;            //位置及三个坐标轴参数D3DXVECTOR3 m_up;D3DXVECTOR3    m_look;D3DXVECTOR3  m_position;float    m_aspect;               //投影相关参数float   m_fovY;float    m_nearZ;float   m_farZ;D3DXMATRIX   m_view;             //视角矩阵D3DXMATRIX    m_proj;             //投影矩阵IDirect3DDevice9* _Device;};
}
#endif // !__e3d_camera__

以上是代码。接下来我会简单地阐明Camera涉及到的数学知识。

用以下4种向量可以来描述摄像机

  • 右向量(right vector)
  • 上向量(up vector)
  • 观察向量(look vector)
  • 位置向量(position vector)

所以说摄像机的Walk(前进后退)和Strafe(左右移动)很好解释。仅需要将positon向量加上look或者right向量。这里我的摄像机没有设计向上升。其实同理让positon加上up向量然后通过UpdateView计算出view(视角矩阵即可)。


下面我说一下左右上下旋转视角。

上下点头

通过D3DXMatrixRotationAxis函数与right向量和角度计算出绕right轴旋转的矩阵。然后通过up和look向量与矩阵相乘更新up和look向量

左右摇头

和上下点头类似这里不再赘述。


数学部分:

先平移后旋转。

平移矩阵很简单

1    0    0    0
0    1    0    0
0    0    1    0
-px -py  -pz   1

旋转矩阵通过up look right向量共同求得

rx   ux   dx   0
ry   uy   dy   0
rz   uz   dz   0
0    0    0    1

矩阵相乘得到

m_view(0, 0) = m_right.x;   m_view(0, 1) = m_up.x; m_view(0, 2) = m_look.x;   m_view(0, 3) = 0;m_view(1, 0) = m_right.y;    m_view(1, 1) = m_up.y; m_view(1, 2) = m_look.y;   m_view(1, 3) = 0;m_view(2, 0) = m_right.z;    m_view(2, 1) = m_up.z; m_view(2, 2) = m_look.z;   m_view(2, 3) = 0;m_view(3, 0) = x;        m_view(3, 1) = y;  m_view(3, 2) = z;      m_view(3, 3) = 1;

以上这些为我学习3d打下坚实基础。也设计出一个完整的摄像机类让我对游戏引擎的设计也会收获很多经验。

一个3D摄像机的设计与实现相关推荐

  1. 德州仪器(TI)3D机器视觉参考设计

    德州仪器(TI)3D机器视觉参考设计 http://www.elecfans.com/kongzhijishu/jiqishijue/362268_a.html 3D机器视觉参考设计包含德州仪器的DL ...

  2. 一个3D车道线检测方法PersFormer及其开源OpenLane数据集

    来源丨计算机视觉深度学习和自动驾驶 arXiv上2022年3月论文"PersFormer: 3D Lane Detection via Perspective Transformer and ...

  3. 计算机3d影视的应用,浅析CG技术在3D电影场景设计中的应用

    [摘要] 3D电影的场景设计在造型手法.空间表现上和传统电影有着相当大的区别,这得益于计算机CG技术,能够创造出完全由计算机虚拟而传统手法无法获取的形象和镜头运动,实现了科学技术和艺术的完美结合.计算 ...

  4. 惊! 花椒程序员new了一个3D女朋友!

    背景 随着花椒直播业务的拓展及主播.看播群体对于多维度动态观感需求的提高,传统的2D平面渲染已逐渐不能满足需求,而突出立体感,互动性,随机性.个性化的3D技术越来越得到重视.通过3D渲染技术可以实现礼 ...

  5. 惊! 程序员S哥new了一个3D女朋友!

    一.背景 随着花椒直播业务的拓展及主播.看播群体对于多维度动态观感需求的提高,传统的2D平面渲染已逐渐不能满足需求,而突出立体感,互动性,随机性.个性化的3D技术越来越得到重视.通过3D渲染技术可以实 ...

  6. Unity 3D 环境特效||Unity 3D 游戏场景设计实例

    Unity 3D 环境特效 一般情况下,要在游戏场景中添加雾特效和水特效较为困难,因为需要开发人员懂得着色器语言且能够熟练地使用它进行编程. Unity 3D 游戏开发引擎为了能够简单地还原真实世界中 ...

  7. y空间兑换代码_如何用不到 2KB 的 JavaScript 代码写一个 3D 赛车游戏?

    几个月前,JS1k游戏制作节(JS1K game jam)传出不再举办消息后,许多游戏迷开始哀嚎. Frank Force 也是其中一位,但他还有另一层身份--一位德克萨斯州奥斯汀的独立游戏设计师.F ...

  8. Godot引擎 4.0 文档 - 第一个 3D 游戏

    本文为Google Translate英译中结果,DrGraph在此基础上加了一些校正.英文原版页面: Your first 3D game - Godot Engine (stable) docum ...

  9. Unity与C#创建一个3D平台游戏 Learn to Create a 3D Platformer Game with Unity C#

    游戏开发变得容易了.使用Unity学习C#并创建您自己的3D平台! 你会学到什么 学习现代通用编程语言C#. 了解Unity中3D开发的功能 发展强大的可转移的解决问题的技能 了解游戏开发过程 了解面 ...

最新文章

  1. 2021年春季学期-信号与系统-第十一次作业参考答案-第一小题
  2. 编译Hadoop源码
  3. richtextbox自动滚动到最下面_工业自动化直线运动部件大全,导轨、轴承、衬套、丝杠、导向轴简介说明...
  4. 求1~n这n个整数十进制表示中1出现的次数
  5. html禁止输入字符,javascript – 如何限制在html表中使用的contenteditable中的字符输入...
  6. 综述 | 联邦学习-新兴的人工智能基础技术
  7. Android Oreo 常见问题 2.0 | Android 开发者 FAQ Vol.9
  8. hbase 学习(十二)非mapreduce生成Hfile,然后导入hbase当中
  9. docker改变镜像源
  10. linux命令行删除N天前的数据的命令
  11. 邮箱不能发送大附件,什么邮箱可以发送超大附件?
  12. Cannot resolve the name 'repository:auditing-attributes' to a(n) 'attribute grou
  13. 常见文件扩展名(后缀)
  14. linux下制作mac os x,桌面应用|Ubuntu 14.04 下的MAC OS X 主题安装
  15. 计算机网络按网络的传输介质分类可以分为:广域网和无线网两种.,常用的网络传输介质类别和各自特点...
  16. ERP基础数据 金蝶
  17. python实现pdf合并
  18. 使用Github和PicGO搭建免费图床
  19. 1星《微信软文营销实战技巧》:标题党,作者没有实战经验
  20. 硅谷首富:拉里 埃里森

热门文章

  1. 3-8SQL注入网站实际案例第四步:第三者上位点测试与利用
  2. Unity UI 框架
  3. 操作系统中磁盘调度算法详解
  4. MySQL数据查询---连接查询
  5. JAVA生成安卓签名证书
  6. 贪心算法实现最大收益
  7. win7+linux双系统
  8. 呼叫中心电话客服系统搭建的种类有哪些
  9. 计算机管理邮箱,用WindowsLiveMail一次管理多个邮箱
  10. 哈工大计算机科学与技术硕士培养方案,计算机科学与技术学科硕士研究生培养方案哈工大计算机学院[文].pdf...