旋转矩阵可以通过观察向量构造,观察向量可以是3D空间的两个或三个点。如果一个处于P1点的对象面向P2点,则观察向量就是P2-P1,如下图:

首先,前轴向量通过归一化的观察向量简单计算而来。

其次,左轴通过指定向上方向向量与前轴的差乘计算而来。向上方向向量用于确定对象的roll角度。并且她不必与前轴垂直。如果我们不考虑对象的roll旋转,我们可以使用(0,1,0)。这就是说对象始终向上站立着。

实际上,与前轴与左轴都正交的上轴向量可以动过另外前轴与左轴向量的差乘计算出来。为了拥有单位长度的向量,左轴与上轴在差乘之后需要归一化。

下面是从观察向量计算左轴、上轴与前轴的C++代码。第一段代码块是Vector3结构体变量的最简便实现。第二代码块从两点(位置与目标向量)计算3个轴。最后一个代码块从3点(位置、目标向量与向上向量)计算3轴。

// Vector3结构体的最简化实现
struct Vector3
{
float x;
float y;
float z; Vector3() : x(0), y(0), z(0) {}; // 构造函数
Vector3(float x, float y, float z) : x(x), y(y), z(z) {}; // 函数
Vector3& normalize(); //
Vector3 operator-(const Vector3& rhs) const; // 减法
Vector3 operator*(const Vector3& rhs) const; // 差乘
Vector3& operator*=(const float scale); // 缩放与更新
}; Vector3& Vector3::normalize() {
float invLength = 1 / sqrtf(x*x + y*y + z*z);
x *= invLength;
y *= invLength;
z *= invLength;
return *this;
} Vector3 Vector3::operator-(const Vector3& rhs) const {
return Vector3(x-rhs.x, y-rhs.y, z-rhs.z);
} Vector3 Vector3::cross(const Vector3& rhs) const {
return Vector3(y*rhs.z - z*rhs.y, z*rhs.x - x*rhs.z, x*rhs.y - y*rhs.x);
}
///////////////////////////////////////////////////////////////////////////////
// 从对象的位置与目标点计算变换轴
///////////////////////////////////////////////////////////////////////////////
void lookAtToAxes(const Vector3& position, const Vector3& target,
Vector3& left, Vector3& up, Vector3& forward)
{
// 计算前向量
forward = target - position;
forward.normalize(); // 基于前向量计算临时上向量
// 注意向上/下观察角度为90°的情况
// 例如:前向量在Y轴上
if(fabs(forward.x) < EPSILON && fabs(forward.z) < EPSILON)
{
// 前向量指向+Y轴
if(forward.y > 0)
up = Vector3(0, 0, -1);
// 前向量指向-Y轴
else
up = Vector3(0, 0, 1);
}
// 通常情况上向量为直立的
else
{
up = Vector3(0, 1, 0);
} // 计算左向量
left = up.cross(forward); // cross product
left.normalize(); // 重新计算正交化的上向量
up = forward.cross(left); // 差乘
up.normalize();
}
///////////////////////////////////////////////////////////////////////////////
// 从位置、目标与向上方向计算变换轴
///////////////////////////////////////////////////////////////////////////////
void lookAtToAxes(const Vector3& pos, const Vector3& target, const Vector3& upDir,
Vector3& left, Vector3& up, Vector3& forward)
{
// 计算前向量
forward = target - pos;
forward.normalize(); // 计算左向量
left = upDir.cross(forward); // 差乘
left.normalize(); // 计算正交化的上向量
up = forward.cross(left); // 差乘
up.normalize();
}

英文原文:http://www.songho.ca/opengl/gl_lookattoaxes.html 

OpenGL观察轴的更多相关文章

  1. OpenGL角轴

    概述 轴旋转 角轴 概述 OpenGL旋转矩阵 旋转角度直接影响OpenGL GL_MODELVIEW矩阵的前三列,准确地说是向左.向上与向前三轴元素.例如,如果一沿X轴的单位向量(1,0,0)与任一 ...

  2. OpenGL变换

    概述 OpenGL变换矩阵 实例:GL_MODELVIEW矩阵 实例:GL_PROJECTION矩阵 概述 OpenGL管线中,在光栅化操作之前,包括顶点位置与法线向量的几何数据经顶点操作与图元装配操 ...

  3. OpenGL变换【转】

    http://www.cnblogs.com/hefee/p/3811099.html OpenGL变换 概述 OpenGL变换矩阵 实例:GL_MODELVIEW矩阵 实例:GL_PROJECTIO ...

  4. 《Real Time Rendering》第四章 图形变换

    图形变换是一个将例如点.向量或者颜色等实体进行某种转换的操作.对于计算机图形学的先驱者,掌握图形变换是极为重要的.有了他们,你就可以对象.光源以及摄像机进行定位,变形以及动画添加.你也可以确认所有的计 ...

  5. cocos2d-x CCNode类

    文章引用自http://blog.csdn.net/qiurisuixiang/article/details/8763260 1 CCNode是cocos2d-x中一个非常重要的类.CCNode是场 ...

  6. [cocos2d-x] --- CCNode类详解

    Email : awodefeng@163.com 1 CCNode是cocos2d-x中一个很重要的类,CCNode是场景.层.菜单.精灵等的父类.而我们在使用cocos2d-x时,接触最多的就是场 ...

  7. TETeLasr Cutting System 开机回零问题

    TETeLasr Cutting System 开机回零问题    :打开 "轴信息"    :打开 加工参数-->机器参数-->脉冲当量: X轴==4000 Y轴== ...

  8. cocos2d CCNode类(节点属性大全)

    1 CCNode是cocos2d-x中一个很重要的类,CCNode是场景.层.菜单.精灵等的父类.而我们在使用cocos2d-x时,接触最多的就是场景.层.菜单.精灵等.所以有必要先弄懂CCNode类 ...

  9. OpenGL的几何变换4之内观察全景图

    上一次写了OpenGL的几何变换3之内观察全景图 上次采用的是图片分割化方式,这次采用数据分割化方式. 先说下思路,数据分割化方式呢,是只读取一张图片imgData,然后通过glTexCoord2f( ...

随机推荐

  1. X3850M2安装CertOS 7 KVM 2--DMMP

    1,在DS8000中调整vg为单台服务器.检查另一台服务器内已经没有磁盘信息. 2,在余下的服务器中安装DMMP. 参考:http://edwin-wang.com/2012/08/device-ma ...

  2. Apple Pay的快速实现

    一.在Apple开发者中心配置 AppleID 和 Merchant IDs 二.配置好证书后在Xcode中开启Apple Pay 三.代码实现 3.1 判断是否支持Apple Pay,如果支持又将支 ...

  3. Git进行代码管理的心得

    git从网上下载安装后 直接可在开始菜单中找到 打开可以看到一个类似命令窗口的东西 用代码进行用户名和邮箱的设置 虽然不知道为什么但是教程叫我这么做 (ˇˍˇ) 然后似乎就可以用了 进入文件夹 输入对 ...

  4. webpack vuejs项目学习心得

    最近在做移动端的项目,最近webpack和vuejs很火,就想到了用vuejs webpack来构建我的项目 先了解了一些webpack的入门基础 http://webpack.github.io/d ...

  5. python调用NLPIR - ICTCLAS2013实现中文分词

    环境:win7.VS2008.Python2.7.3 第一步:照着文档[2]将NLPIR库封装成Python的扩展: 第二步:新建一个名为“nlpir_demo”的目录,将第一步最后得到的名为“nlp ...

  6. Python中的可迭代对象与迭代器对象

    刚刚学习Python,对“可迭代对象”和"迭代器对象"的个人理解,不知道对不对. 1.几个概念 (1)迭代工具:包括for循环.列表解析.in成员关系测试.....等等在内的,用于 ...

  7. Memcache所有方法及参数详解

    memcache函数所有的方法列表如下: 参考http://www.php.net/manual/zh/function.Memcache-add.php Memcache::add - 添加一个值, ...

  8. Code Review Tools

    Code Review中文应该译作“代码审查”或是“代码评审”,这是一个流程,当开发人员写好代码后,需要让别人来review一下他的代码,这是一种有效发现BUG的方法.由此,我们可以审查代码的风格.逻 ...

  9. C++开发过程多线程同步lock的实现

    在程序开发过程经常使用到多线程,而多线程始终与锁存在紧密地联系,以下详细的介绍如何在C++程序开发过程中自定义锁的几种方法. 1. 下面给出一段代码展现如何通过Mutex实现锁的功能(window p ...

  10. HashPasswordForStoringInConfigFile中的Md5算法并非常用的Md5算法

    今天在开发一个软件时,同时在B/S版和C/S版中都要用到MD5加密,在ASP.NET中使用的是 /**//// <summary>    /// 取得MD5加密串    /// </ ...