【坐标系】各引擎坐标系
WebGL坐标系
确认过了WebGL
你给个三角形A
深度是-0.5
,三角形B
深度是0
,开启深度检测后,画出来发现深度小的三角形(-0.5)
画在了前面,注意深度检测后就是深度大的在后面,由此得出WebGL/OpenGL 裁剪空间和NDC默认就是左手坐标系
然而为什么说一些引擎如threejs是右手坐标系
呢,是因为在投影矩阵里给第三行乘了个-1
,就是左乘一个Z方向反转矩阵(注意三行三列为-1,其他和单位矩阵一样),会导致z轴翻转
,转换成了所谓右手坐标系
,可以看下正射投影和透视投影算出的第三行和正常的投影矩阵比
THREE世界坐标系(右手)
RGB分别代表XYZ,相机位置是 0 0 200,目标物体位置是0 0 0
THREE相机坐标系(右手)
证明:
我们先假设相机坐标系是右手坐标系的,世界坐标系中相机位置是(0,0,200)
, 物体A绿色在(0,0,0)
, 物体B红色在(0,0,100)
,所以相机坐标系中,物体A绿色坐标为(0,0,-200)
,物体B红色坐标为(0,0,-100)
,我们知道THREE裁剪空间会对Z轴进行反转,所以经过裁剪空间处理后,物体A绿色坐标为(0,0,200)
,物体B红色坐标为(0,0,100)
,按照深度大的显示在后面的
原理,所以应该是红色物体显示在绿色物体前面
,由下图看假设是正确的
。
let camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 200);
camera.lookAt(new THREE.Vector3(0, 0,0));const boxA = new THREE.Mesh(new THREE.BoxGeometry(10, 10, 10), new THREE.MeshPhongMaterial({color: 'rgb(0,255,0)',
}));
boxA.position.x = 0;
boxA.position.y = 0;
boxA.position.z = 0;
scene.add(boxA);const boxB = new THREE.Mesh(new THREE.BoxGeometry(10, 10, 10), new THREE.MeshPhongMaterial({color: 'rgb(255,0,0)',}));
boxB.position.x = 0;
boxB.position.y = 0;
boxB.position.z = 100;
scene.add(boxB);
THREE裁剪空间
以three的正射投影为例,near=-1,far=1,算出的投影矩阵如下图所示,这都和unity是统一的
,最终裁剪空间会对z轴进行反转
Unity世界坐标系(左手)
RGB分别代表XYZ,相机位置是 0 0 0,目标物体位置是0 0 10
Unity相机坐标系(右手)
unity相机空间是右手坐标系
,相机朝向为z轴的负方向,下面证明一下。
我们先假设相机坐标系是右手坐标系的,世界坐标系中相机位置是(0,0,-20)
, 物体A绿色在(0,0,0)
, 物体B红色在(0,0,-10)
,所以相机坐标系中,物体A绿色坐标为(0,0,-20)
,物体B红色坐标为(0,0,-10)
,我们知道Unity裁剪空间会对Z轴进行反转,所以经过裁剪空间处理后,物体A绿色坐标为(0,0,20)
,物体B红色坐标为(0,0,10)
,按照深度大的显示在后面的
原理,所以应该是红色物体显示在绿色物体前面
,由下图看假设是正确的
。
Unity裁剪空间
以unity的正射投影为例,near=-1,far=1,算出的投影矩阵如下图所示
所以unity的正射投影矩阵为
这里三行三列为-1,,最终裁剪空间会对z轴进行反转
这就是因为在Unity里当World Space变到Camera Space时,需要做一个反转z轴的操作(因此Unity的视图变换矩阵,相比文章前面的推理还需再乘以一个z轴反转的矩阵)。然后我们做投影变换到Clip Space时,又要给它转回来(再做一次z反转),使得near clip plane在-1,far clip plane在1。
Unity中视图矩阵需要做个特殊处理
Unity和Three 坐标系异同(分析暂时有问题先不看)
three和unity的世界坐标系区别是three右手,unity左手,unity中使用从three计算得到的坐标应该世界矩阵再前乘 negatezMaT,对z轴反转
// 这里后面乘negatezMaT意思给模型矩阵前乘negatezMaT,将世界坐标系转到左手
Matrix4x4 viewMatrix = float16ToMatrix4x4(three.viewMatrix) * negatezMaT;
因为坐标系不同遇到的问题(基于opengl)
threejs
相机位置 (0,0,10)
,默认看向负半轴方向,小车位置是(0,0,0)
,具体代码如下,渲染结果如下。
<!DOCTYPE html>
<html lang="en"><head><title>three.js webgl - glTF loader</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"><link type="text/css" rel="stylesheet" href="main.css">
</head><body><div id="info"><a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - GLTFLoader<br />Battle Damaged Sci-fi Helmet by<a href="https://sketchfab.com/theblueturtle_" target="_blank" rel="noopener">theblueturtle_</a><br /><a href="https://hdrihaven.com/hdri/?h=royal_esplanade" target="_blank" rel="noopener">Royal Esplanade</a> by <ahref="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a></div><div id = "test" style="width: 1180px; height: 695px;"></div><script type="module">import * as THREE from '../build/three.module.js';import { OrbitControls } from './jsm/controls/OrbitControls.js';import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';let camera, scene, renderer;init();render();function init() {// const container = document.createElement('div');// document.body.appendChild(container);var canvasContainer = document.getElementById("test")document.body.appendChild(canvasContainer);camera = new THREE.PerspectiveCamera(60, canvasContainer.clientWidth / canvasContainer.clientHeight, 0.3, 1000);camera.position.set(0, 0, 10);console.log(camera)// camera.lookAt(new THREE.Vector3(0, 0, 0));scene = new THREE.Scene();scene.add(new THREE.DirectionalLight())// scene.add(new THREE.AmbientLight())window.camera = camera;const loader = new GLTFLoader().setPath('models/gltf/DamagedHelmet/glTF/');loader.load('DamagedHelmet.glb', function (gltf) {scene.add(gltf.scene);console.log(gltf.scene.position)render();});let axes = new THREE.AxisHelper(10);scene.add(axes);// var cameraPerspective = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.3, 20);window.cameraPerspective = cameraPerspective;cameraPerspective.position.set(0, 0, 10);var cameraPerspectiveHelper = new THREE.CameraHelper( cameraPerspective );window.cameraPerspectiveHelper = cameraPerspectiveHelper;scene.add( cameraPerspectiveHelper );scene.add( cameraPerspective );renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setPixelRatio(window.devicePixelRatio);// renderer.setSize(window.innerWidth, window.innerHeight);renderer.setSize(canvasContainer.clientWidth, canvasContainer.clientHeight);canvasContainer.appendChild(renderer.domElement);const controls = new OrbitControls(camera, renderer.domElement);controls.addEventListener('change', render); // use if there is no animation loopcontrols.minDistance = 2;controls.maxDistance = 100;controls.target.set(0, 0, 0);controls.update();}function render() {window.cameraPerspectiveHelper.update()window.cameraPerspective.updateMatrix()renderer.render(scene, camera);}</script></body></html>
小车位置是(0,0,0)
three相机位置是(0,0,10)
unity中
相机位置(0,0,-10)
,小车位置(0,0,0)
,最终渲染结果如下
小车和相机在世界坐标系下位置如下图所示
three和unity相机的模型矩阵分别是
three和unity中视图矩阵分别是
three和unity中投影矩阵分别是
看出来两个引擎中
视图矩阵
是第三行三列正好相反
投影矩阵
是相同的
目前发现了两个问题:
1.问题1
就算在unity中修改视图矩阵和three中一样,最终显示结果是下面这样
但是
,这个渲染结果和threejs渲染结果还是不一样看着似乎一样,但是它是X轴取反了
,而且是我强制改了双面渲染
,不然它的模型三角面顶点顺序都变了,这个就涉及到了世界坐标系左手和右手的转换问题,这块令人困惑。
2.问题2
这个汽车模型在three的世界坐标系(右手)中和在unity的世界坐标系(左手)中摆放好像是X轴取反了!
这是为啥
可以看那个字母m的朝向,是不是很奇怪。
参考
【1】.视图变换和投影变换矩阵的原理及推导,以及OpenGL,DirectX和Unity的对应矩阵
【坐标系】各引擎坐标系相关推荐
- OSG三维渲染引擎编程学习之十七:“第二章:OSG数学基础” 之 “2.7 世界坐标系、物体坐标系、摄像机坐标系”
第二章 OSG数学基础 OSG是一个优秀的三维渲染引擎,三维渲染涉及到大量的3D数学知识.3D数学是一门和计算机几何相关的科学,研究怎样用数值的方法来解决几何问题,因此,掌握并灵活运用3D数字知识是O ...
- 2.cocos2d-x坐标体系(UI坐标系,GL坐标系,本地坐标,世界坐标,节点坐标)
openGL & UI坐标体系 OpenGL坐标系:该坐标原点在屏幕左下角,x轴向右,y轴向上.这也就是cocos2dx中用到的坐标系. 屏幕坐标系:该坐标系的原点在屏幕左上角,x轴向右 ...
- AirSim(五)---理解篇: Airsim世界坐标系、NED坐标系、机体坐标系以及控制相关API接口函数
目录 1. 坐标系 coordinate system (1) AirSim API的坐标系:NED 坐标系 with SI unit (2) Unreal Engine的坐标系 (3)AirSim全 ...
- 屏幕坐标系和视口坐标系
一.屏幕坐标系 1.屏幕坐标系: 手机屏幕或者电脑屏幕的一个坐标系. 2.屏幕坐标是以像素来定义的, 屏幕左下角为原点(0,0), 右上角为(Screen.width,Screen.height), ...
- 【自动驾驶】16.计算机视觉:相机成像原理:世界坐标系、相机坐标系、图像坐标系、像素坐标系之间的转换
本篇博客为转载,我对其中的细节添加了一些说明. 原文链接:https://blog.csdn.net/chentravelling/article/details/53558096 0.前言 最近整理 ...
- 世界坐标系,相机坐标系和图像坐标系的转换(Python)
世界坐标系,相机坐标系和图像坐标系的转换(Python) 相机内参外参说明:相机内参外参_pan_jinquan的博客-CSDN博客_相机内参 计算机视觉:相机成像原理:世界坐标系.相机坐标系.图像坐 ...
- 单目视觉标定:世界坐标系、相机坐标系、图像坐标系、像素坐标系——简单粗暴,粗暴
转:https://blog.csdn.net/chentravelling/article/details/53558096 1.正文 图像处理.立体视觉等等方向常常涉及到四个坐标系:世界坐标系.相 ...
- 世界坐标系,摄像机坐标系、图像坐标系关系汇总
**摄像机标定:**在计算机视觉研究领域,摄像机标定是一个重要的环节.摄像机标定就是求取摄像机内外参数的过程. 世界坐标系:绝对坐标系,一般的三维场景都由这个坐标系来表示.摄像机可以放置在环境中的任何 ...
- 我国四大常用坐标系及高程坐标系【转载】
1.北京54坐标系(BJZ54) 北京54坐标系为参心大地坐标系,大地上的一点可用经度L54.纬度M54和大地高H54定位,它是以克拉索夫斯基椭球为基础,经局部平差后产生的坐标系. 新中国成立以后,我 ...
- 计算机视觉:相机成像原理:世界坐标系、相机坐标系、图像坐标系、像素坐标系之间的转换(转载)
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/chentravelling/article/details/53558096 0.前言 最近整理了& ...
最新文章
- 数据通信技术(十:OSPF特殊区域TOTALLY STUB配置(ZTE))
- 使用R构建Xgboost模型并绘制ROC曲线
- linux基础命令学习(四)用户与群组
- 复杂网络下多码率视频流切换关键技术
- linux系统部署静态网站,Linux笔记15 使用Apache服务部署静态网站。
- [saiku] 使用 Apache Phoenix and HBase 结合 saiku 做大数据查询分析
- php缓存页面,PHP缓存页面函数的简单示例
- 29.AngularJS 简介
- 假如时光能够倒流, 我会这么学习Java
- 互联网公司的三高问题
- win10分辨率设置正确但屏幕却被拉伸了,如何处理
- 服务器上发布的网站应用80端口时内网可以访问,外网不能访问
- 【视频教程】帝国CMS模板开发制作网站系列教程04
- 智能水表自动抄表协议cjt188远传协议,支持地址自动分配检查,灵活好用、Mbus通讯测试工具是一款水表等设备的测试工具
- sublimelinter java_程序员必备工具SublimeLinter安装使用指南
- python判断人生阶段
- vbs实现的支持拖动的txt文本切割器
- 机器学习算法(1)——Logistic Regression
- jenkins + UIAutomation 自动化脚本运行app
- 二、Kubernetes安装