OpenGL观察轴
旋转矩阵可以通过观察向量构造,观察向量可以是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观察轴的更多相关文章
- OpenGL角轴
概述 轴旋转 角轴 概述 OpenGL旋转矩阵 旋转角度直接影响OpenGL GL_MODELVIEW矩阵的前三列,准确地说是向左.向上与向前三轴元素.例如,如果一沿X轴的单位向量(1,0,0)与任一 ...
- OpenGL变换
概述 OpenGL变换矩阵 实例:GL_MODELVIEW矩阵 实例:GL_PROJECTION矩阵 概述 OpenGL管线中,在光栅化操作之前,包括顶点位置与法线向量的几何数据经顶点操作与图元装配操 ...
- OpenGL变换【转】
http://www.cnblogs.com/hefee/p/3811099.html OpenGL变换 概述 OpenGL变换矩阵 实例:GL_MODELVIEW矩阵 实例:GL_PROJECTIO ...
- 《Real Time Rendering》第四章 图形变换
图形变换是一个将例如点.向量或者颜色等实体进行某种转换的操作.对于计算机图形学的先驱者,掌握图形变换是极为重要的.有了他们,你就可以对象.光源以及摄像机进行定位,变形以及动画添加.你也可以确认所有的计 ...
- cocos2d-x CCNode类
文章引用自http://blog.csdn.net/qiurisuixiang/article/details/8763260 1 CCNode是cocos2d-x中一个非常重要的类.CCNode是场 ...
- [cocos2d-x] --- CCNode类详解
Email : awodefeng@163.com 1 CCNode是cocos2d-x中一个很重要的类,CCNode是场景.层.菜单.精灵等的父类.而我们在使用cocos2d-x时,接触最多的就是场 ...
- TETeLasr Cutting System 开机回零问题
TETeLasr Cutting System 开机回零问题 :打开 "轴信息" :打开 加工参数-->机器参数-->脉冲当量: X轴==4000 Y轴== ...
- cocos2d CCNode类(节点属性大全)
1 CCNode是cocos2d-x中一个很重要的类,CCNode是场景.层.菜单.精灵等的父类.而我们在使用cocos2d-x时,接触最多的就是场景.层.菜单.精灵等.所以有必要先弄懂CCNode类 ...
- OpenGL的几何变换4之内观察全景图
上一次写了OpenGL的几何变换3之内观察全景图 上次采用的是图片分割化方式,这次采用数据分割化方式. 先说下思路,数据分割化方式呢,是只读取一张图片imgData,然后通过glTexCoord2f( ...
随机推荐
- Fragment中的onKeyDown事件让Activity处理--处理特殊按键比如移动终端扫描
一些特殊按键事件需要在Activity中处理public void onKeyDown(int keyCode, KeyEvent event){ //让Activity处理 getActivity( ...
- Session阻塞 读写锁引发的小问题
引子 我们来看两个ajax方法,先后的问题,会有什么样的结果? Javascript: $(function () { //第一个 $.ajax({ type: "POST&qu ...
- C语言程序设计第7堂作业
一.本次课主要内容: 本次以计算圆柱体体积为例,通过定义体积计算功能的函数和主函数调用的例子,引出函数定义的一般形式:函数首部加函数体,且在函数结尾处通过return 语句返回结果.本节要重 ...
- 安装R语言扩展包diveRsity-1
今天去了学院的运动会呢-扮熊本熊超开心-写完这篇我补上我的图么么哒 ××××××××××××文末高能预警!!!!!这个包的安装并不是本周的任务!!!!!我真是萌萌哒×××××××××××××× ××× ...
- Android四大组件-Activity
http://android.tgbus.com/Android/androidnews/201204/419485.shtml
- 重载运算符:类成员函数or友元函数
类成员函数: bool operator ==(const point &a)const { return x==a.x; } 友元函数: friend bool operator ==(co ...
- 初学SQL常用到的一些指令
一.库 查看有哪些库:show databases; 进入某个库:use 库名; 新增库:create database atm; (atm为库名) 删除库:drop database if exis ...
- [转载 ]POJ 1273 最大流模板
转载 百度文库花了5分下的 不过确实是自己需要的东西经典的最大流题POJ1273 ——其他练习题 POJ3436 . 题意描述: 现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给 ...
- Protobuf - 使用scons编译proto文件
使用protobuf过程中,需要先对消息结构进行定义,文件以.proto格式结尾.然后要使用google提供的protoc命令行,把.proto文件转成对应的代码文件. protoc --proto_ ...
- IOS中延迟执行的几种方法
前几天去国美在线面试,就遇到了上面的问题,当时是笔试,只写出来了第一种方法,现在整理了一下. //1.performSelector方法:在当前线程中执行的方法,使用默认模式,并延迟执行@select ...