3D数学中表示图形旋转有三种方式:
旋转矩阵,欧拉角,四元数
性质 矩阵 欧拉角 四元数
在坐标系间转换 能 不能 不能
连续或增量旋转 能,但是转换速度慢 不能 能,转换速度快
插值 基本不能 能,但可能遇到万向锁问题 能,且能平滑插值
易用程度 难 易 难
存储 9个数 3个数 4个数
对给定方位表达方式是否唯一 是 不是,对同一方位有无数种表达 不是,对同一方位有两种表达
可能导致非法 矩阵蠕变 任意三个数都能构成合法的欧拉角 可能会出现误差积累,从而产生非法的四元数
欧拉角会导致 万象锁问题 一般调整xyz层级 可以尽量避免但是不能根本解决
世界坐标系到物体坐标系过程 ----世界坐标系平移到惯性坐标系 惯性坐标系经过旋转到物体坐标系
下面使用旋转矩阵的表示方法来实现惯性坐标系到物体坐标系 以及反过来的转换:
#pragma once
#include "Vector3.h"
class RotationMatrix
{
public:
float m11, m12, m13;
float m21, m22, m23;
float m31, m32, m33;
void identify(); //单位矩阵
Vector3 intertialToObject(const Vector3 &v) const;
Vector3 ObjectTointertial(const Vector3 &v) const;
};
#include "pch.h"
#include "RotationMatrix.h"
void RotationMatrix::identify()
{
m11 = 1; m12 = 0; m13 = 0;
m21 = 0; m22 = 1; m23 = 0;
m31 = 0; m32 = 0; m33 = 1;
}
Vector3 RotationMatrix::intertialToObject(const Vector3 &v) const
{
return Vector3(v.x*m11 + v.y *m21 + v.z*m31, v.x*m12 + v.y *m22 + v.z*m32, v.x*m13 + v.y*m23 + v.z *m33);
}
//需要乘以旋转矩阵的逆矩阵 保证旋转矩阵是正交矩阵 转置矩阵=逆矩阵
Vector3 RotationMatrix::ObjectTointertial(const Vector3 &v) const
{
return Vector3(v.x*m11 + v.y*m12 + v.z*m13, v.x*m21 + v.y *m22 + v.z*m23, v.x*m31 + v.y* m32 + v.z *m33);
}
// 3DMath.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include "Vector3.h"
#include "Matrix4X3.h"
#include "MathUtil.h"
#include <math.h>
#include "RotationMatrix.h"
using namespace std;
float to_zero(float n)
{
if (abs(n) < 0.0001)
{
return 0;
}
return n;
}
void print_v(Vector3 &v)
{
cout << "[" << to_zero(v.x) << "," << to_zero(v.y) << "," << to_zero(v.z) << "]" << endl;
}
void print_m(Matrix4X3 &m)
{
cout << to_zero(m.m11) << "\t" << to_zero(m.m12) << "\t" << to_zero(m.m13) << endl;
cout << to_zero(m.m21) << "\t" << to_zero(m.m22) << "\t" << to_zero(m.m23) << endl;
cout << to_zero(m.m31) << "\t" << to_zero(m.m32) << "\t" << to_zero(m.m33) << endl;
}
int main()
{
cout << "Hello Rotation Matrix !\n";
RotationMatrix rm;
rm.m11 = 0.866f; rm.m12 = 0; rm.m13 =-0.5f;
rm.m21 = 0.0f; rm.m22 = 1.0f; rm.m23 = 0.0f;
rm.m31 = 0.5f; rm.m32 = 0.0f; rm.m33 = 0.866f;
Vector3 v(10, 20, 30);
Vector3 r;
r = rm.intertialToObject(v);
print_v(r);
r = rm.ObjectTointertial(r);
print_v(r);
system("pause");
return 0;
}