Luaメソッド:新クォータニオンからオイラー角への変換
作成:EEX_bsg.icon
試していないから、何がどう上手く動かないのかは分かってないけどね
下記のサイトを参考に...というかまるまるコピーしてLuaに書き直した
使ってみたけどもどうやら上手く動いてそうなので、スクラップボックスに載せておく
クォータニオンをよく理解していないのでどう計算してるかはよくわかってないEEX_bsg.icon
メソッドと書いてるくせにモジュールにしているのは、EEX_bsg.icon がなんとなくそうしたかったから
モジュール化した時の動作確認はしていないけれども、元のプログラムはしっかり動いているので大丈夫だろう
読み込み側(使用例)
code:main.lua
--モジュール読み込み
require("new quaternion to euler")
--適当なベクトル
local vec1 = vector.new(0, 0, 0)
local vec2 = vector.new(1, 2, 3)
--二つのベクトルの間の角度を求める
local rotation = quaternion.from_to_rotation(vec1, vec2)
--クォータニオンをオイラー角に変換
rotation = quaternion_to_euler.calc(rotation)
--printログに表示してみる
print("x:" .. math.ceil(rotation.x*100)/100 .. " y:" .. math.ceil(rotation.y*100)/100 .. " z:" .. math.ceil(rotation.z*100)/100)
モジュール
Rad2Degはラジアンと度の変換用定数(なんとなくDeg2Radも入れといた)
↑なんかmathライブラリに変換の関数あるっぽいけど元のサイトと同じようにしてる
approximatelyは近似値判定用
calcは本命のクォータニオンとオイラー角の変換
引数にクォータニオンを入れるとオイラー角のベクトルが返ってくる
code:new quaternion_to_euler.lua
module("quaternion_to_euler", package.seeall)
local Rad2Deg = 360 / (math.pi * 2)
local Deg2Rad = (math.pi * 2) / 360
local function approximately(a, b)
threshold = 0.000001
diff = math.abs(a - b)
return diff < threshold
end
local function calc(r)
local x = r.x;
local y = r.y;
local z = r.z;
local w = r.w;
local x2 = x * x;
local y2 = y * y;
local z2 = z * z;
local xy = x * y;
local xz = x * z;
local yz = y * z;
local wx = w * x;
local wy = w * y;
local wz = w * z;
-- 1 - 2y^2 - 2z^2
local m00 = 1 - (2 * y2) - (2 * z2);
-- 2xy + 2wz
local m01 = (2 * xy) + (2 * wz);
-- 2xy - 2wz
local m10 = (2 * xy) - (2 * wz);
-- 1 - 2x^2 - 2z^2
local m11 = 1 - (2 * x2) - (2 * z2);
-- 2xz + 2wy
local m20 = (2 * xz) + (2 * wy);
-- 2yz+2wx
local m21 = (2 * yz) - (2 * wx);
-- 1 - 2x^2 - 2y^2
local m22 = 1 - (2 * x2) - (2 * y2);
local tx, ty, tz;
if approximately(m21, 1) then
tx = math.pi / 2;
ty = 0;
tz = math.atan2(m10, m00);
elseif approximately(m21, -1) then
tx = -math.pi / 2;
ty = 0;
tz = math.atan2(m10, m00);
else
tx = math.asin(-m21);
ty = math.atan2(m20, m22);
tz = math.atan2(m01, m11);
end
tx = tx * Rad2Deg;
ty = ty * Rad2Deg;
tz = tz * Rad2Deg;
return vector.new(tx, ty, tz);
end