四元數——概念以及相關數學公式 實現繞座標軸旋轉以及獲取旋轉角和旋轉軸

四元數與複數

複數 平面幾何意義一個向量 (2D)

複數做乘法 幾何上是一個新的向量 向量旋轉一定的角度 (2D)

 

擴展到3D 3個虛部的複數 四元數

 

[w (x y z)] = w+xi+yj+zk

 

i j k 的平方爲-1 三個虛部

 

四元數與軸-角對

繞着任意旋轉軸旋轉任意角度

 

負四元數 全部取反

單位四元數 表示沒有

四元數的模

模爲1的四元數 規範化的四元數

共軛

3d數學中使用的四元數 模都爲1  四元數的逆等於 四元數的共軛 旋轉方向相反

四元數叉乘

四元數的旋轉

P用q旋轉 p用a b依次旋轉 如果不習慣ba順序 可以修改叉乘的計算方式  (下圖計算 w x y z 錯誤 應該是

w = w1w2-x12-y1y2-z1z2

x =  w1 x2 + x1w2 + z1y2 - y1z2

y = w1y2  + y1w2 + x1z2 - z1x2

z = w1z2 + z1w2+ y1x2 - x1y2)

四元數角位移 四元數的差  數學上四元數的除法

方位a 與方位b之間的夾角 d

旋轉角的倍數 q旋轉30 q的三分之一冪就是10度

#pragma once
#include "Vector3.h"
class Quaternion
{
public:
	float w, x, y, z;

	void Identify() { w = 1; x = 0;  y = 0; z = 0; } //單位四元數

	void setToRotateAboutX(float theta);
	void setToRotateAboutY(float theta);
	void setToRotateAboutZ(float theta);
	void setToRotateAboutAxis(const Vector3 &axis,float theta);

	float getRotationAngle() const;
	Vector3 getRotationAxis() const;
};

extern const Quaternion kQuaternionIdentify;
#include "pch.h"
#include "Quaternion.h"
#include <math.h>
#include <assert.h>
#include "MathUtil.h"

const Quaternion kQuaternionIdentify = { 1.0f,0.0f,0.0f,0.0f };

void Quaternion::setToRotateAboutX(float theta)
{
	//計算半角
	float thetaOver2 = theta * 0.5f;
	//計算w 
	w = cos(thetaOver2);
	x = sin(thetaOver2)*1;
	y = 0.0f;
	z = 0.0f;
}

void Quaternion::setToRotateAboutY(float theta)
{
	//計算半角
	float thetaOver2 = theta * 0.5f;
	//計算w 
	w = cos(thetaOver2);
	x = 0.0f;
	y = sin(thetaOver2) * 1;
	z = 0.0f;
}

void Quaternion::setToRotateAboutZ(float theta)
{
	//計算半角
	float thetaOver2 = theta * 0.5f;
	//計算w 
	w = cos(thetaOver2);
	x = 0.0f;
	y = 0.0f;
	z = sin(thetaOver2) * 1;
}

void Quaternion::setToRotateAboutAxis(const Vector3 &axis, float theta)
{
	assert(fabs(VecMag(axis) - 1.0f) < 0.01f);

	float thetaOver2 = theta * 0.5f;
	float sinThetaOver2 = sin(thetaOver2);

	w = cos(thetaOver2);
	x = axis.x*sinThetaOver2;
	y = axis.y*sinThetaOver2;
	z = axis.z*sinThetaOver2;
}

//四元數算出旋轉角
float Quaternion::getRotationAngle() const 
{
	//根據w 算出半角
	float thetaOver2 = safeAcos(w);
	
	return 2 * thetaOver2;
}

//四元數算出旋轉軸
Vector3 Quaternion::getRotationAxis() const
{
	float sinThetaOver2Sq = 1.0f - w * w;
	float sinThetaOver2 = sqrt(sinThetaOver2Sq);

	float oneOverSinThetaOver2 = 1 / sinThetaOver2;
	float nx = x* oneOverSinThetaOver2;
	float ny = y * oneOverSinThetaOver2;
	float nz = z* oneOverSinThetaOver2;

	return Vector3(nx,ny,nz);
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章