位置: 编程技术 - 正文

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图形计算器)

  • 建筑公司收到预付款怎么开票
  • 怎么查历年
  • 银行存款支付运费会计科目
  • 由第三方代付款开票给对方合规吗
  • 湖北工会工作网
  • 个人投资企业投资人签字
  • 分步法和分批法思维导图
  • 固定资产折旧摊销表A105080
  • 收到投资款现金流量项目是什么
  • 缴纳印花税需要计提吗?
  • 小规模纳税人税率有几种
  • 淘宝开企业店铺需要什么资料
  • 给职工买的意外险怎么做账
  • 什么叫社保人员
  • 哪些外籍个人应在中国缴纳个税?
  • 个人独资企业收款码
  • 存货盘亏损失
  • 没有认缴到位的股票
  • 给员工买饮料
  • 投资收益或亏损影响营业利润吗
  • 旅行社代订的住宿费可以抵扣吗
  • 装win7ahci
  • win10右键新建卡死
  • 吊兰怎么养才能开花
  • 企业要方便客户与企业的沟通,尽可能降低
  • 劳务派遣发票会扣税吗
  • 工业企业销售收入和产值,税金比例
  • 薰衣草 英国
  • 格雷厄姆岛
  • 东洛锡安的金黄麦田,苏格兰 (© Scott Masterton/plainpicture)
  • laravel框架用到哪些设计模式
  • 采购周转材料会计分录怎么写
  • 独立核算统负盈亏和独立核算自负盈亏的区别
  • Smarty实现页面静态化(生成HTML)的方法
  • vue前端怎么运行
  • Vue 3 介绍
  • 如何防止sql注入 java
  • 手工明细账簿怎么登账
  • 安全文明措施费费率一般为多少
  • 将外购商品用于个人消费
  • 减按10%的税率是什么意思
  • 单位有残疾人能享受
  • 劳务派遣应如何签合同
  • 工会经费计提按应付职工薪酬借方还是贷方?
  • 图文详解管道支架制作安装标准
  • 织梦如何使用
  • mysql批量处理
  • 政府会计制度下基建账
  • 如何把有余额的账单删除
  • 零售药店过期药品整改报告
  • 专利财政补贴
  • 上年度漏提折旧
  • 预收账款开票怎么做账
  • 不良品怎么入账
  • 购入不需要安装的固定资产会计科目
  • 出包方式建造固定资产的成本包括
  • 员工借款后离职怎么处理
  • 企业日常发放的贷款
  • 租赁费属于酌量性固定成本
  • 提高纳税遵从度依靠行政执法还是纳税服务
  • centos rpm命令
  • windows2003服务不能开启
  • win7提示无法访问权限
  • win8启动文件夹在哪里
  • 怎么在centos中创建一个文件
  • windows 10的屏幕键盘快捷键在哪里
  • win7系统安装ie11浏览器
  • 重装win7旗舰版重启后黑屏
  • opengl粒子系统烟花
  • 设计模式工厂模式使用场景
  • node.js中使用文件流进行文件复制,首先需要创建一个
  • javascript语言基础
  • python设计gui
  • 简述javascript中的函数
  • js延时加载方式
  • 浅析是什么意思
  • 什么是委托代征专用账户管理
  • 走逃失踪纳税人如何处理
  • 新疆税务干部学校招聘
  • 发票抽奖还有吗
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设