在3D游戏中获得游戏人物敌人坐标xyz后,并不能直接绘制到屏幕上,需要进行一系列的转换算法,目前主流的算法包括三角函数转换与矩阵变换,三角函数转换方法过时且繁琐,这里不推荐使用,本文主讲矩阵变换原理:

一、游戏中多种坐标矩阵的转换关系

游戏中用CE可以找到敌人的world space坐标,也就是XYZ的游戏世界空间坐标, 通过矩阵变换得到Clip Space坐标(剪切坐标),通过透视分割算法得到NDC坐标,最后将NDC坐标视窗映射矩阵即可获得屏幕坐标。

二、D3D和opengl中矩阵存储形式

Direct3D 采用行主序(Row major)存储

“Effect matrix parameters and HLSL matrix variables can define whether the value is a row-major or column-major matrix; however, the DirectX APIs always treat D3DMATRIX and D3DXMATRIX as row-major.”

OpenGL 采用列主序(Colume major)存储

“The m parameter points to a 4x4 matrix of single- or double-precision floating-point values stored in column-major order. That is, the matrix is stored as follows”

  存储顺序说明了线性代数中的矩阵如何在线性的内存数组中存储,d3d 将每一行在数组中按行存储,而opengl将每一列存储到数组的每一行中:

  因此,对于线程代数中的同一个矩阵,则在d3d和OpenGL中有不同的表示形式:

                  线代矩阵:a11,a12,a13,a14            d3d保存:  a11,a12,a13,a14            OpenGL保存: a11,a21,a31,a41a21,a22,a23,a24                         a21,a22,a23,a24                       a12,a22,a32,a42a31,a32,a33,a34                         a31,a32,a33,a34                       a13,a23,a33,a43a41,a42,a43,a44                         a41,a42,a43,a44                       a14,a24,a34,a44

三、算法实现流程(以D3D为例)

1.假设敌人的世界坐标为X, Y, Z,W;其中W为其次项,一般设置为1(D3D规范如此,这个不必计较)

2.计算剪切坐标:

剪切坐标X = a11*X + a12*Y + a13*Z + a14

剪切坐标Y = a21*X + a22*Y + a23*Z + a24

剪切坐标Z = a31*X + a32*Y + a33*Z + a34

剪切坐标W = a41*X + a42*Y + a43*Z + a44

(此处注意设置筛选条件,仅剪切坐标w>0的才可以继续以下操作,小于0的可以忽略,因为不在你的视角内,PS:不信的同学可以最后试一下加与不加的区别)

3.计算NDC坐标:(透视分割算法:用剪切坐标XYZ除以W即可)

NDC坐标X = 剪切坐标X / 剪切坐标W

NDC坐标Y = 剪切坐标Y / 剪切坐标W

NDC坐标Z = 剪切坐标Z / 剪切坐标W

4.NDC坐标转屏幕坐标:

转换公式如下:

屏幕坐标.x = 窗口宽度 ÷ 2 × NDC坐标.x + NDC坐标.x + 窗口宽度 ÷ 2
屏幕坐标.y = -(窗口高度 ÷ 2 × NDC坐标.y) + NDC坐标.y + 窗口高度 ÷ 2

至此,已经描述完世界坐标转换屏幕坐标的算法了

如果对NDC转屏幕坐标感兴趣的小伙伴可以继续往下看:

四、NDC转屏幕公式解析

如图所示,我们通过视口变换矩阵ViewPort与NDC坐标进行矩阵乘,即可得到以上公式,但是对于屏幕坐标Y的公式不可由该矩阵乘推得,注意公式前面的符号:屏幕坐标.y = -(窗口高度 ÷ 2 × NDC坐标.y) + NDC坐标.y + 窗口高度 ÷ 2,

按照矩阵乘推理,应该没有负号,但是此处有,原因如下:

先普及下正常的屏幕坐标系和屏幕视口坐标系的区别:

由此可以知道,在与VIewPort做矩阵乘运算中,Y应该为与原来相反,所以在

[x,

y;

z,

1]竖矩阵中将y加上符号,再做矩阵乘,即可得到以上正确的算法公式,自己动手算一遍就会懂了。

参考文献:

https://www.bilibili.com/video/BV1UK4y1D781/?spm_id_from=trigger_reload

https://www.cnblogs.com/icmzn/p/13531265.html

https://space.bilibili.com/442168898/channel/detail?cid=123750

https://www.bilibili.com/video/av286268338/

游戏世界三维坐标转换为屏幕坐标原理分析:三角函数转换与矩阵变换相关推荐

  1. 三维坐标转换为二维坐标

    三维坐标转换为二维坐标 最近做项目用到三维坐标转换为二维平面坐标的转换公式.看了网上的很多资料,都不太适用自己的项目.最后决定自己来推导. 具体问题描述 如下图所示,将二维平面上的三维坐标系O-X'Y ...

  2. 经纬度坐标转换为屏幕坐标

    经纬度坐标转换成屏幕坐标 地理坐标定义规则:X轴(代表经度)向右递增,Y轴(纬度)向上递增,就好比小学学过的平面坐标.向左.向下的规则.屏幕坐标定义规则:X轴向右递增,Y轴向下递增. 可以看出,地理坐 ...

  3. java地理坐标转屏幕_(转)经纬度坐标转换为屏幕坐标

    经纬度坐标转换成屏幕坐标 地理坐标定义规则:X轴(代表经度)向右递增,Y轴(纬度)向上递增,就好比小学学过的平面坐标.向左.向下的规则.屏幕坐标定义规则:X轴向右递增,Y轴向下递增. 可以看出,地理坐 ...

  4. 三维视觉 | 01 摄像机原理及坐标系转换

    最早接触视觉三维是本科毕设的时候,当时做的是目标检测与三维定位.所以一直想有机会也分享一下视觉三维重建的知识,最近有空,索性就将一些零碎的知识整理分享出来,有问题欢迎大家评论区留言! 文章目录 一.摄 ...

  5. 目前已知摄像头的三维坐标和三维朝向,已知摄像头画面宽高,某一物体在该画面中的位置坐标,以及该物体中心距离摄像头的距离,求该物体在现实世界中的坐标,用c++实现,使用小孔成像原理,直接上代码...

    求解这个问题的过程可以分为以下步骤: 将摄像机坐标系下的物体坐标转换为图像坐标系下的坐标,图像坐标系下的坐标是以图像左上角为原点,x轴向右,y轴向下的二维平面坐标. 将图像坐标系下的坐标转换为归一化平 ...

  6. 【我的世界原理分析】1.光照原理

    [我的世界原理分析]1.光照原理 前言 1.平滑光照 2.环境光 3.光照算法 前言 最近在研究类我的世界这样的游戏,方便以后开发以及提供给更多人一个思路.大家多多评论留言我会不断更新更多相关内容. ...

  7. 三维坐标 偏转_三维坐标变换原理-平移, 旋转, 缩放

    给定一个二维点(x, y),那么形如(kx, ky, k)的所有三元组就都是等价的,它们就是这个点的齐次坐标(homogeneous).齐次坐标就是将一个原本是n维的向量用一个n+1维向量来表示,是指 ...

  8. OpenGL 获取当前屏幕坐标对应的三维坐标

    转自原文 OpenGL 获取当前屏幕坐标对应的三维坐标,使用很简单glu库中的一个函数 #include <GL/glut.h> #include <stdlib.h> #in ...

  9. 游戏光枪坐标定位原理及算法

    http://b2b.hc360.com/supplyself/347075653.html 品牌: CRZMAN 型号: WII 适用送礼场合: 广告促销,商务馈赠,节日,乔迁,生日,展销会,开业典 ...

最新文章

  1. POJ 2976 Dropping tests【二分 最大化平均值】
  2. java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory
  3. C++学习笔记——虚函数
  4. mysql三高讲解(二):2.1 索引组织表
  5. Spark Streaming实例
  6. C语言常用库函数(含详细用法)
  7. FORTRAN文件读写操作 from《FORTRAN95 程序设计》
  8. 鞋店商城小程序开发价值
  9. 使用Visual Paradigm画ER图/Visual ER图
  10. 毕业论文尾注和参考文献
  11. centos系统添加桌面图标
  12. SpringBoot将图片/文件传至前端
  13. 【C语言】函数详解(入门到进阶)
  14. 《U-Net: Convolutional Networks for Biomedical Image Segmentation》学习笔记
  15. 【读书推荐】中国是部金融史
  16. Java实现 LeetCode 476 数字的补数
  17. 电脑连接蓝牙耳机声音总是断断续续:
  18. javac -d . hello.java中的 -d .是什么作用?
  19. ShareSDK移动APP社会化分享组件
  20. 【安信可A9G专题⑤】A9G模组AT指令MQTT接入阿里云实现APP控制

热门文章

  1. 点餐小程序实战教程03-店铺信息展示
  2. vi 放弃更改退出 保存更改退出。
  3. centos下ftp安装及添加账户
  4. 兰德系数(Rand Index)
  5. 你知道有哪些正规的兼职平台吗?
  6. 【Nvivo】什么是定性研究
  7. 【Python】多图形混合排版,如何在Matplotlib/Seaborn中实现?
  8. 桌面计算机图标怎样优化,桌面图标怎么变小,详细教您电脑桌面图标的太大怎么调小...
  9. Pinia(小菠萝)使用方法
  10. Onenote插入代码块