旋转矩阵可以通过观察向量构造,观察向量可以是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. JDBC代码示例

    package test; import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;imp ...

  2. linux(centos)下挂载nefs文件系统

    有时候,在将硬盘插到Linux系统上,挂载硬盘时一直提示:unknown filesystem type 'ntfs'.在尝试网上的方法也遇到了一些问题. 这是有的 linux 发行版并不默认支持挂载 ...

  3. Java收藏

    1.某大神的cnblogs博客关于java的随笔分类:http://www.cnblogs.com/viviman/category/444566.html 2.某大神的cnblogs博客关于java ...

  4. mac搭建本地svn

    1.终端,创建SVN资源文件库 svnadmin create /Volumes/DATA/SVNTest 2配置权限 上面的语句执行完之后在相应路径下可以找到该文件夹,打开之后 这里主要是修改con ...

  5. TransactionScope 使用记录

    最近使用TransactionScope来进行处理不同数据库的操作问题,当看到这里的时候肯都是在使用或者要使用的吧,关于他的使用网络上一大堆,我在使用的时候遇到了一下的问题,作为记录,可能会对以后使用 ...

  6. pyqt5

    使用python爬虫需要使用webkit执行javascript,查找资料可使用pyqt5,在此记录下安装步骤 windows 安装pyqt5 操作webkit 可用版本 1. 下载python 3. ...

  7. Oracle监听小问题

    啥情况 宁波_弈风 15:17:40   宁波_弈风 15:17:49 默认配置路径 宁波_弈风 15:18:09   宁波_弈风 15:19:13 我原来一直都在SAMPLE文件里面配置和保存,因为 ...

  8. 类A have-a 类B,类B访问类A public 成员

    需求是类A中包含类B,而类B又需要访问类A的public属性的成员. 首先类B中要访问类A的属性,那么对于类B而言,我们必须要知道有类A这个类,所以在类B的具体实现之前我们需要前向声明类A. 对于类A ...

  9. a标签不跳转

    <a href="javascript://">父级菜单</a> 结果是这种写法在一些浏览器下不能到达预期效果(无跳转),我没有花时间把这种写法在主流浏览器 ...

  10. 上下文管理、线程池、redis订阅和发布

    一:上下文管理: 对于一些对象在使用之后,需要关闭操作的.比如说:socket.mysql数据库连接.文件句柄等. 都可以用上下文来管理. 语法结构: Typical usage: @contextm ...