位置: 编程技术 - 正文

OpenGL教程翻译 第十三课 相机空间(opengl learn)

编辑:rootadmin
OpenGL教程翻译 第十三课 相机空间原文地址: 2D平面能看见的部分只是一个矩形。在该矩形的外部所有东西都将被减掉。把这个矩形渲染到屏幕是我们的目标。

推荐整理分享OpenGL教程翻译 第十三课 相机空间(opengl learn),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:opengl transform,opengl英文,opengl英文,opengl语言,opengl英文,opengl英文,opengl中文教程,opengl translate,内容如对您有帮助,希望把文章链接给更多的朋友!

理论上可以生成这样的变化矩阵,实现把一个位于3D空间的对象投影到坐落在世界坐标系任意位置的相机正前方的2D平面上。然而,这其中的数学变换比我们之前遇见的要复杂很多。而当相机被置于3D世界坐标系的源点并且方向沿着Z轴时的投影就简单了很多。比如,一个对象放在(0,0,5)处,同时相机放在(0,0,1)处并且方向朝向Z轴。如果我们把相机和对象朝着原点移动一个单位,那时两者的相对距离和方向(就相机的方向而言)保持不变,而区别只是相机此时位于原点。以同种方式移动场景中的所有物体使得我们能够正确渲染场,用之前学到的方法。

上面的例子很简单,因为相机的方向已经沿着Z轴,并且通常对准坐标系的轴。但是如果相机指向其他方向将会发生什么呢?看下面的图片。简单的说,这是一个2D坐标系统,我们从顶部看相机。

相机的方向原本是指向Z轴的,但是之后顺时针旋转度。就如你看到的,相机定义它自己的坐标系统,这个坐标系可能与世界坐标系相同(上面的图片),也可能不同(下面的图片)。所以实际上同时存在两个坐标系统。即一个用来指定对象的世界坐标系,和一个与相机的“轴”(target, up and right)对齐的相机坐标系统。这两个坐标系就是我们所知的世界空间和相机/视图空间。

上图中,绿球在世界空间中位于(0,y,z)。在相机空间中,它位于坐标系的左上角(换言之,它的X坐标为负,Z坐标为正)。我们需要找到绿球在相机空间中的位置。此时我们可以先简单的忘记所有关于世界空间的,仅仅只使用相机空间。在相机空间中,相机位于原点方向,指向Z轴。对象的指定和相机有关,并且可以用我们学过的方法来渲染对象。

相机顺时针旋转了度相当于绿球逆时针旋转了度。对象的移动总是和相机的移动相反。所以总的来说,我们需要增加两个新的变换,并将它们加入我们已有的变换管线中。我们需要,在让相机移动到原点的过程中保持对象和相机之间相对位置不变,同时也需要让对象沿着与相机旋转方向的反方向转动。

移动相机是非常简单的。如果相机位于(x,y,z),那么平移变换就是(-x,-y,-y)。原因很明显——相机在世界坐标系下用向量(x,y,z)做平移变换,所以想要相机回到原点,那么我们就需要使用此向量的相反向量进行平移。变换矩阵如下所示:

下一步是将相机转向世界坐标系中指定的位置。我们想要找到在相机定义的新坐标系下顶点的位置。所以实际的问题是:我们如何从一个坐标系转换到另一个坐标系?

再看看上面的图。世界坐标系是由三个线性无关的向量(1,0,0), (0,1,0) 和 (0,0,1)定义的。线性无关意思是我们找不到不全为0的x,y,z使得x*(1,0,0) &#; y(0,1,0) &#; z*(0,0,1) = (0,0,0)。用几何术语来说,这意味着这三个向量中的任意两个都可以确定一个垂直于第三个向量的平面。很容易可以看到相机坐标系是由向量(1,0,-1), (0,1,0), (1,0,1)确定的。标准化这些向量后,我们得到(0.,0,-0.),(0,1,0) 和(0.,0,0.)。

下面的图片展示了向量的位置是如何在两个不同的坐标系被指定的。

我们知道在世界坐标系空间中如何得到代表相机空间坐标轴的单位向量,也知道了在世界坐标系空间中向量的位置(x,y,z)。我们要找的是向量(x',y',z')。我们现在利用点积的一个叫做“标量投影”的属性。标量投影是一个任意的向量A和一个单位向量B点积的结果,产生B向量方向上A向量的延伸。换句话说,这个结果就是向量A在向量B上的投影。在上面的例子中,如果我们让向量(x,y,z)和代表相机X轴的单位向量之间做点积,那么我们将得到x'&#;。相同的方法我们可以得到y',z'。(x',y',z')是在相机空间中(x,y,z)的位置。

让我们看看如何把这个想法变成一个完整的标定相机方向的办法。这个办法叫做“UVN相机”,它仅仅是众多指定相机方向的办法中的一个。这个方法就是是,相机被下列的矩阵所定义:

1:N – 由相机指向它的目标的向量。在一些3D的文献中也被称为'look at'。这个向量对应于Z轴。

2:V – 直立时,这个向量是竖直向上的。如果你正在编写飞机模拟仿真的程序并且飞机是被反转的,那么向量最好是朝向地面的。这个向量对应于Y轴。

3:U – 这个向量从相机指向其右侧。它对应于X轴。

为了把一个位置从世界坐标系空间转换到被UVN向量定义的相机坐标系空间,我们需要在位置和UVN向量之间进行一个点乘运算。如下面的矩阵所示:

这一节的代码中,你将会注意到着色器中的全局变量'gWorld'已经被重命名为'gWVP'。这个改变体现了在许多书籍中这一系列变换为我们所知的方式。WVP代表World-View-Projection。

Code Walkthru在这一节中我决定做一个小的设计改变,把低级的矩阵操作代码从Pipeline类移到Matrix4f类中。Pipeline类让Matrix4f类调用不同的方法初始化它自己并且链接几个矩阵来生成最终的矩阵变换。

(pipeline.h:)

struct { Vector3f Pos; Vector3f Target; Vector3f Up;} m_camera;

Pipeline类有一些新的成员来储存相机参数。注意相机参数中缺少'U'轴。它将通过在target和up之间进行叉乘计算得到。此外这里有一个新的函数SerCamera来传递这些&#;。

(math3d.h:)

Vector3fVector3f::Cross(const Vector3f& v) const

{

const float _x = y * v.z - z * v.y;

const float _y = z * v.x - x * v.z;

const float _z = x * v.y - y * v.x;

return Vector3f(_x, _y, _z);

}

Vector3f类中有一个新的方法来计算两个Vector3f对象的叉积。两个向量的叉积会产生一个向量,它垂直于两个相乘向量组成的平面。当你记住这些向量有方向和幅度但是没有位置时,这个变的更直观。所有拥有相同的方向和大小的向量被认为是相等的,不论它们的起点在哪里。所以你也可以让两个向量的起点位于原点。这意味着你可以创建一个三角形,这个三角形有一个顶点是位于起点而另外两个顶点是向量的终点。这个三角形定义了一个平面,叉积产生了一个垂直于这个平面的向量。在维基百科(Wikipedia)中可以了解到更多关于叉积。

(math3d.h:)

Vector3f&Vector3f::Normalize()

{

const float Length = sqrtf(x * x &#; y* y &#; z * z);

x /= Length;

y /= Length;

z /= Length;

OpenGL教程翻译 第十三课 相机空间(opengl learn)

return *this;

}

为了生成UVN矩阵我们需要让这些向量成为单位向量。这个操作术语称作是向量的标准化,它由让向量的每个分量除以向量的长度得来。

(math3d.cpp:)

voidMatrix4f::InitCameraTransform(const Vector3f& Target, const Vector3f&Up)

{

Vector3f N = Target;

N.Normalize();

Vector3f U = Up;

U.Normalize();

U = U.Cross(Target);

Vector3f V = N.Cross(U);

m[0][0] = U.x; m[0][1] = U.y; m[0][2]= U.z; m[0][3] = 0.0f;

m[1][0] = V.x; m[1][1] = V.y; m[1][2]= V.z; m[1][3] = 0.0f;

m[2][0] = N.x; m[2][1] = N.y; m[2][2]= N.z; m[2][3] = 0.0f;

m[3][0] = 0.0f; m[3][1] = 0.0f;m[3][2] = 0.0f; m[3][3] = 1.0f;

}

这个函数生成了稍后在pipeline类中使用的相机转化矩阵。U,V,N向量计算后置于矩阵的每一行。因为顶点的位置向量将在矩阵的右边被乘(作为一列)。这意味着在U,V,N向量和位置向量之间做点乘。这将生成三个标量&#;,这三个&#;是在屏幕坐标系下XYZ的&#;。

这个函数被提供的参数是target和up向量。“right”向量是通过这两个向量的叉乘得到。因为不确定参数是否为单位向量,所以我们标准化这些向量。在生成U向量后,我们再通过target和right向量之间进行叉乘来计算up向量。在后面我们开始移动相机的时候,将会发现重新计算up向量的原因,只更新target向量而up向量保持不变是较为简单的。然而,这意味着在target和up向量之间的角度将不是度,导致这个坐标系统变得无效。通过计算right向量和up向量,我们将的得到一个每一对轴之间的角度都是度的坐标系统。

(pipeline.cpp:)

constMatrix4f* Pipeline::GetTrans()

{

Matrix4f ScaleTrans, RotateTrans,TranslationTrans, CameraTranslationTrans, CameraRotateTrans,PersProjTrans;

ScaleTrans.InitScaleTransform(m_scale.x,m_scale.y, m_scale.z);

RotateTrans.InitRotateTransform(m_rotateInfo.x,m_rotateInfo.y, m_rotateInfo.z);

TranslationTrans.InitTranslationTransform(m_worldPos.x,m_worldPos.y, m_worldPos.z);

CameraTranslationTrans.InitTranslationTransform(-m_camera.Pos.x,-m_camera.Pos.y, -m_camera.Pos.z);

CameraRotateTrans.InitCameraTransform(m_camera.Target,m_camera.Up);

PersProjTrans.InitPersProjTransform(m_persProj.FOV,m_persProj.Width, m_persProj.Height, m_persProj.zNear, m_persProj.zFar);

m_transformation = PersProjTrans *CameraRotateTrans * CameraTranslationTrans * TranslationTrans *

RotateTrans * ScaleTrans;

return &m_transformation;

}

让我们更新生成一个对象完整的变化矩阵的函数。现在只是新增了两个关于相机的新的矩阵就已经变得相当复杂。在完成了世界坐标系下的变换(结合对象的缩放,旋转,平移)后,我们通过移动相机到原点开始了对相机的变换。这个平移转换通过使用相机位置向量的反向量完成的。所以如果相机在(1,2,3),那么为了让相机回到原点我们需要把相机沿(-1,-2,-3)这个向量移动。之后我们基于相机的target和up向量而生成相机的旋转矩阵。那么相机部分的变换就完成了。最后生成坐标。

(tutorial.cpp:)

Vector3fCameraPos(1.0f, 1.0f, -3.0f);

Vector3fCameraTarget(0.f, 0.0f, 1.0f);

Vector3fCameraUp(0.0f, 1.0f, 0.0f);

p.SetCamera(CameraPos,CameraTarget, CameraUp);

在主渲染循环中我们使用新的方法。为了放置相机,我们从原点沿着Z轴的负方向后移动,然后向右移和向上移动。up向量就是Y轴的正半轴。我们把所有的这些送进Pipeline对象中,Pipeline类将处理接下来的工作。

3D图象算法(转) 原文链接3D简介我们首先从坐标系统开始。你也许知道在2D里我们经常使用Ren?笛卡儿坐标系统在平面上来识别点。我们使用二维(X,Y):X表示水平轴坐标,Y表

雨滴波纹核心代码 一、案例效果图:二、源代码下载地址:

opengl配置glut.h问题 注意:这解决方法不是所有人都适用,就如我,我只有把subsystem:console依然保持不变才能运行

标签: opengl learn

本文链接地址:https://www.jiuchutong.com/biancheng/369630.html 转载请保留说明!

上一篇:OpenCV2学习笔记(十七):VS2013中运行支持OpenGL的OpenCV工程(opencv轻松入门)

下一篇:3D图象算法(转)(3d图形计算器)

  • 小规模纳税人应交税费的二级科目
  • 注册税务师考试2023
  • 公司把股权转让给个人
  • 投资控股型公司什么意思
  • 增值税何时需要交税
  • 支付个人无发票怎么入账
  • 固定资产到期怎么处理
  • 退税 增值税
  • 代发工资的手续费是多少
  • 上传失败显示网络不佳
  • 个税生产经营所得B表在哪里
  • 美团扣点怎么做凭证
  • 固定资产报废相关规定
  • 公司作为二房东怎么给别人开发票
  • 库管和车间工人哪个好
  • 哪些费用发票可以报销
  • 本年利润和未分配利润怎么结转
  • 想用u盘装系统怎么弄
  • 购买办公用品是否缴纳印花税
  • windows modules installer worker怎么禁用
  • 坏账损失可以做销项税转出吗
  • neoDVDstd.exe - neoDVDstd是什么进程 有什么用
  • php跨域解决方案
  • 基础代谢
  • 软件是无形的,可见的物理实体
  • 微信小程序详细教程
  • 错账的类型及对应的更正方法
  • 公司账户的资金有利息吗
  • 车险增值税发票模板图片
  • php shell_exec
  • 微信小程序分包中插件样式丢失
  • 年终奖的个税税率表
  • 公司购买一辆小型货车
  • 老会计带新手教学真账实操
  • 应付账款用什么方法清查
  • sqlserver2008分页查询
  • windows图标显示不出来
  • centos 任务计划
  • smsvchost.exe是什么文件 电脑中Svchost.exe病毒解决办法
  • windows xp 7 10
  • 远程控制安全
  • centos安装nmtui
  • quickres.exe - quickres是什么进程 作用是什么
  • Windows7忘记开机密码一键还原
  • win102020h2版本
  • kavsvc.exe - kavsvc是什么进程 有什么作用
  • win10更新2021年6月
  • win8.1截图工具快捷键
  • Windows 8中Hyper-V虚拟机操作应用的具体步骤
  • Win8开启SmartScreen筛选器保护上网安全
  • win10预览在哪
  • 如何更改忘记密码中的问题
  • win7蓝牙驱动软件
  • jquery弹出框样式大全
  • 我是一个打酱油的怎样理解
  • 铁嘴的故事
  • cocos html
  • opengl es programming guide
  • ExtJS4如何给同一个formpanel不同的url
  • 使用jquery操作dom
  • js基础笔记
  • nodejs制作网站
  • android开发项目实战+源码教程
  • js怎么操作css
  • nodejs 写文件
  • win7 python
  • js做时钟让钟表转起来
  • 工具的图
  • 编写javascript代码
  • android简单app实例
  • 税务行政部门有哪些
  • 辽宁地方税务局发票查询
  • 省委巡视组收到的案件线索怎么分配
  • 查账征收个人经营所得税怎么申报
  • 北京税务局地税电话
  • 酒店,旅店的营业范围
  • 鸦片战争签订了条约
  • 甘肃省35条措施的内容是什么
  • 电子税务怎么弄
  • 国家土地征收管理办法
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设