約 4,583,719 件
https://w.atwiki.jp/sampleisbest/pages/225.html
開発環境 Microsoft Visual C# 2010 Express (SP1) 実行環境 Microsoft Windows XP Home Edition (SP3) プロジェクトの種類 空のプロジェクト プロジェクト名 Quaternion Program.cs using System; using Microsoft.Xna.Framework; // .NET参照 class Program { static void Main() { Quaternion q1, q2; float rad = MathHelper.ToRadians(45); float y = (float)Math.Sin(rad); float r = (float)Math.Cos(rad); Console.WriteLine("lat=0 +xから+zへ"); q1 = new Quaternion(1, 0, 0, 0); q2 = new Quaternion(0, 0, 1, 0); Slerp(q1, q2); Console.WriteLine("lat=45 +xから+zへ"); q1 = new Quaternion(r, y, 0, 0); q2 = new Quaternion(0, y, r, 0); Slerp(q1, q2); Console.WriteLine("lat=45 +xから-xへ"); q1 = new Quaternion(r, y, 0, 0); q2 = new Quaternion(-r, y, 0, 0); Slerp(q1, q2); Console.ReadLine(); } static void Slerp(Quaternion q1, Quaternion q2) { for (int n = 0; n = 4; n++) { float t = n / 4.0f; Quaternion q = Quaternion.Slerp(q1, q2, t); float lat = MathHelper.ToDegrees((float)Math.Asin(q.Y)); float xz = MathHelper.ToDegrees((float)Math.Atan2(q.Z, q.X)); float xy = MathHelper.ToDegrees((float)Math.Atan2(q.Y, q.X)); Console.WriteLine(String.Format( "t={0 f2} x={1 f2} y={2 f2} z={3 f2} w={4 f2} lat={5 f2} long={6 f2} xy={7 f2}", t, q.X, q.Y, q.Z, q.W, lat, xz, xy)); } } } 出力 lat=0 +xから+zへ t=0.00 x=1.00 y=0.00 z=0.00 w=0.00 lat=0.00 long=0.00 xy=0.00 t=0.25 x=0.92 y=0.00 z=0.38 w=0.00 lat=0.00 long=22.50 xy=0.00 t=0.50 x=0.71 y=0.00 z=0.71 w=0.00 lat=0.00 long=45.00 xy=0.00 t=0.75 x=0.38 y=0.00 z=0.92 w=0.00 lat=0.00 long=67.50 xy=0.00 t=1.00 x=0.00 y=0.00 z=1.00 w=0.00 lat=0.00 long=90.00 xy=0.00 lat=45 +xから+zへ t=0.00 x=0.71 y=0.71 z=0.00 w=0.00 lat=45.00 long=0.00 xy=45.00 t=0.25 x=0.58 y=0.79 z=0.21 w=0.00 lat=52.06 long=20.10 xy=53.79 t=0.50 x=0.41 y=0.82 z=0.41 w=0.00 lat=54.74 long=45.00 xy=63.43 t=0.75 x=0.21 y=0.79 z=0.58 w=0.00 lat=52.06 long=69.90 xy=75.00 t=1.00 x=0.00 y=0.71 z=0.71 w=0.00 lat=45.00 long=90.00 xy=90.00 lat=45 +xから-xへ t=0.00 x=0.71 y=0.71 z=0.00 w=0.00 lat=45.00 long=0.00 xy=45.00 t=0.25 x=0.38 y=0.92 z=0.00 w=0.00 lat=67.50 long=0.00 xy=67.50 t=0.50 x=0.00 y=1.00 z=0.00 w=0.00 lat=89.98 long=0.00 xy=90.00 t=0.75 x=-0.38 y=0.92 z=0.00 w=0.00 lat=67.50 long=180.00 xy=112.50 t=1.00 x=-0.71 y=0.71 z=0.00 w=0.00 lat=45.00 long=180.00 xy=135.00
https://w.atwiki.jp/sampleisbest/pages/233.html
開発環境 Microsoft Visual C# 2010 Express (SP1) 実行環境 Microsoft Windows XP Home Edition (SP3) プロジェクトの種類 空のプロジェクト プロジェクト名 Quaternion Program.cs // Quaternion5 回転とSlerp using System; using Microsoft.Xna.Framework; // .NET参照 class Program { static void Main() { float rad = MathHelper.ToRadians(30); float y = (float)Math.Sin(rad); float r = (float)Math.Cos(rad); Vector3 v1 = new Vector3(r, y, 0); Vector3 v2 = new Vector3(0, y, r); Print(v1); Print(v2); // 外積で回転軸ベクトルを求める Vector3 cross = Vector3.Cross(v2, v1); cross.Normalize(); Print(cross); // 内積でベクトル間の角度を求める float dot = Vector3.Dot(v1, v2); // |v1||v2|cosθ float angle = (float)Math.Acos(dot); Console.WriteLine(string.Format("angle={0 f2}", MathHelper.ToDegrees(angle))); Console.WriteLine("回転"); Quaternion p = new Quaternion(v1, 0); for (int t = 0; t = 4; t++) { Quaternion rot = Quaternion.CreateFromAxisAngle(cross, angle * t / 4); Quaternion q = Quaternion.Conjugate(rot) * p * rot; Console.Write(string.Format("t={0} / ", t)); Print(q); } Console.WriteLine("Quaternion.Slerp"); Quaternion q1 = new Quaternion(v1, 0); Quaternion q2 = new Quaternion(v2, 0); for (int t = 0; t = 4; t++) { Quaternion q = Quaternion.Slerp(q1, q2, t / (float)4); Console.Write(string.Format("t={0} / ", t)); Print(q); } Console.ReadLine(); } static void Print(Vector3 v) { Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} len={3 f2}", v.X, v.Y, v.Z, v.Length())); } static void Print(Quaternion q) { Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} w={3 f2} len={4 f2}", q.X, q.Y, q.Z, q.W, q.Length())); } } 出力 x=0.87 y=0.50 z=0.00 len=1.00 x=0.00 y=0.50 z=0.87 len=1.00 x=-0.45 y=0.77 z=-0.45 len=1.00 angle=75.52 回転 t=0 / x=0.87 y=0.50 z=0.00 w=0.00 len=1.00 t=1 / x=0.75 y=0.60 z=0.29 w=0.00 len=1.00 t=2 / x=0.55 y=0.63 z=0.55 w=0.00 len=1.00 t=3 / x=0.29 y=0.60 z=0.75 w=0.00 len=1.00 t=4 / x=0.00 y=0.50 z=0.87 w=0.00 len=1.00 Quaternion.Slerp t=0 / x=0.87 y=0.50 z=0.00 w=0.00 len=1.00 t=1 / x=0.75 y=0.60 z=0.29 w=0.00 len=1.00 t=2 / x=0.55 y=0.63 z=0.55 w=0.00 len=1.00 t=3 / x=0.29 y=0.60 z=0.75 w=0.00 len=1.00 t=4 / x=0.00 y=0.50 z=0.87 w=0.00 len=1.00
https://w.atwiki.jp/sampleisbest/pages/232.html
開発環境 Microsoft Visual C# 2010 Express (SP1) 実行環境 Microsoft Windows XP Home Edition (SP3) プロジェクトの種類 空のプロジェクト プロジェクト名 Quaternion 四元数(しげんすう、クォータニオン)の用途には2種類ある。 1.座標を表す。 2.回転軸と角度を表す。 1.の方は値のセットも取得も行う。 2.の方は値をセットし利用はするが、取得はあまり行わない。 3次元の座標の四元数での表現 ある座標(x,y,z)を四元数で表すには、 Quaternion p = new Quaternion(new Vector3(x, y, z), 0); とする。 ちなみに、4番目の要素wをゼロ以外の値にしても問題ないようだが、ゼロ以外にする意味はないと思う。 回転の四元数での表現 原点を回転の中心として、回転の軸が(x,y,z)で (右手系の座標定義では、ベクトル(x,y,z)の進む方向に向かって眺めて反時計回りに) t度回す回転を表す四元数は Quaternion q = Quaternion.CreateFromAxisAngle(new Vector3(x, y, z), MathHelper.ToRadians(t)); Quaternion r = Quaternion.Quaternion.Conjugate(Q); と作る。(ちなみにrはqの共役四元数という) 回転を実行するには、 Quaternion rpq = r * p * q; と計算する。rpqの(x,y,z)が回転した後の座標である。 原点以外を通る回転軸の場合、回転軸が原点を通るように座標を平行移動して回転し、平行移動しなおす。 (もっといい方法があるかもしれない) 参考 四元数で3次元の回転を計算する方法 クォータニオンを学んでみよう! 床井研究室 - ゲームグラフィックス特論 Program.cs // Quaternion4.1 using System; using Microsoft.Xna.Framework; // .NET参照 class Program { static void Main() { Vector3 v = new Vector3(0, 1, 0); // 回転軸の方向を表すベクトル for (int t = 0; t = 360; t += 45) { Quaternion q = Quaternion.CreateFromAxisAngle(v, MathHelper.ToRadians(t)); Console.Write(string.Format("t={0} / ", t)); Print(q); } Console.ReadLine(); } static void Print(Quaternion q) { Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} w={3 f2} len={4 f2}", q.X, q.Y, q.Z, q.W, q.Length())); } } 出力 t=0 / x=0.00 y=0.00 z=0.00 w=1.00 len=1.00 t=45 / x=0.00 y=0.38 z=0.00 w=0.92 len=1.00 t=90 / x=0.00 y=0.71 z=0.00 w=0.71 len=1.00 t=135 / x=0.00 y=0.92 z=0.00 w=0.38 len=1.00 t=180 / x=0.00 y=1.00 z=0.00 w=0.00 len=1.00 t=225 / x=0.00 y=0.92 z=0.00 w=-0.38 len=1.00 t=270 / x=0.00 y=0.71 z=0.00 w=-0.71 len=1.00 t=315 / x=0.00 y=0.38 z=0.00 w=-0.92 len=1.00 t=360 / x=0.00 y=0.00 z=0.00 w=-1.00 len=1.00 考察 t=0のときqはQuaternion.Identity(=(0,0,0,1))と同じ値になり無回転を表す。 t=180のときqは(0,1,0)の座標と同じ値であるが、使われ方によってその意味は異なる。 Program.cs // Quaternion4.2 任意の回転軸で点を回転 using System; using Microsoft.Xna.Framework; // .NET参照 class Program { static void Main() { float a = (float)Math.Sin(MathHelper.ToRadians(45)) * 10; Quaternion p = new Quaternion(new Vector3(a, a, 0), 0); // 回転させたい点 Vector3 v = new Vector3(0, 1, 0); // 回転軸の方向を表すベクトル for (int t = 0; t = 360; t += 45) { Quaternion q = Quaternion.CreateFromAxisAngle(v, MathHelper.ToRadians(t)); //Quaternion r = Quaternion.CreateFromAxisAngle(-v, MathHelper.ToRadians(n)); Quaternion r = Quaternion.Conjugate(q); // 共役。↑と同じ Quaternion rpq = r * p * q; Console.Write(string.Format("t={0} / ", t)); Print(rpq); } Console.ReadLine(); } static void Print(Quaternion q) { Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} w={3 f2} len={4 f2}", q.X, q.Y, q.Z, q.W, q.Length())); } } 出力 t=0 / x=7.07 y=7.07 z=0.00 w=0.00 len=10.00 t=45 / x=5.00 y=7.07 z=5.00 w=0.00 len=10.00 t=90 / x=0.00 y=7.07 z=7.07 w=0.00 len=10.00 t=135 / x=-5.00 y=7.07 z=5.00 w=0.00 len=10.00 t=180 / x=-7.07 y=7.07 z=0.00 w=0.00 len=10.00 t=225 / x=-5.00 y=7.07 z=-5.00 w=0.00 len=10.00 t=270 / x=0.00 y=7.07 z=-7.07 w=0.00 len=10.00 t=315 / x=5.00 y=7.07 z=-5.00 w=0.00 len=10.00 t=360 / x=7.07 y=7.07 z=0.00 w=0.00 len=10.00 Program.cs // Quaternion4.3 任意の回転軸・原点で点を回転 using System; using Microsoft.Xna.Framework; // .NET参照 class Program { static void Main() { Vector3 v = new Vector3(0, 1, 0); // 回転軸の方向を表すベクトル Vector3 o = new Vector3(10, 0, 0); // 回転の原点 Quaternion p = new Quaternion(new Vector3(20, 0, 0) - o, 0); // 回転させたい点-回転の原点 for (int t = 0; t = 360; t += 45) { Quaternion q = Quaternion.CreateFromAxisAngle(v, MathHelper.ToRadians(t)); //Quaternion r = Quaternion.CreateFromAxisAngle(-v, MathHelper.ToRadians(n)); Quaternion r = Quaternion.Conjugate(q); // 共役。↑と同じ Quaternion rpq = r * p * q; Vector3 pos = QV(rpq) + o; // 回転後の点+回転の原点 Console.Write(string.Format("t={0} / ", t)); Print(pos); } Console.ReadLine(); } static void Print(Vector3 v) { Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2}", v.X, v.Y, v.Z)); } static Vector3 QV(Quaternion q) { return new Vector3(q.X, q.Y, q.Z); } } 出力 t=0 / x=20.00 y=0.00 z=0.00 t=45 / x=17.07 y=0.00 z=7.07 t=90 / x=10.00 y=0.00 z=10.00 t=135 / x=2.93 y=0.00 z=7.07 t=180 / x=0.00 y=0.00 z=0.00 t=225 / x=2.93 y=0.00 z=-7.07 t=270 / x=10.00 y=0.00 z=-10.00 t=315 / x=17.07 y=0.00 z=-7.07 t=360 / x=20.00 y=0.00 z=0.00
https://w.atwiki.jp/sampleisbest/pages/229.html
開発環境 Microsoft Visual C# 2010 Express (SP1) 実行環境 Microsoft Windows XP Home Edition (SP3) プロジェクトの種類 空のプロジェクト プロジェクト名 Quaternion 参考 床井研究室 - ゲームグラフィックス特論 クォータニオンを"使わない"球面線形補間 Program.cs // Quaternion2 球面線形補間の実験2 using System; using Microsoft.Xna.Framework; // .NET参照 class Program { static void Main() { float rad = MathHelper.ToRadians(120); float x = (float)Math.Cos(rad); float y = (float)Math.Sin(rad); Vector3 v1 = new Vector3(1, 0, 0); Vector3 v2 = new Vector3(x, y, 0); Quaternion q1 = new Quaternion(v1, 0); Quaternion q2 = new Quaternion(v2, 0); Print(v1); Print(v2); Print(q1); Print(q2); int div = 4; float dot = Vector3.Dot(v1, v2); Console.WriteLine(string.Format("dot={0 f2}", dot)); Console.WriteLine("Quaternion.Slerp"); for (int n = 0; n = div; n++) { float t = n / (float)div; Quaternion q = Quaternion.Slerp(q1, q2, t); float lat = MathHelper.ToDegrees((float)Math.Asin(q.Y)); Console.Write(string.Format("{0} lat={1 f1} / ", n, lat)); Print(q); } Console.WriteLine("Slerp(Quaternion)"); for (int n = 0; n = div; n++) { float t = n / (float)div; Quaternion q = Slerp(q1, q2, t); float lat = MathHelper.ToDegrees((float)Math.Asin(q.Y)); Console.Write(string.Format("{0} lat={1 f1} / ", n, lat)); Print(q); } Console.WriteLine("Slerp(Vector3)"); for (int n = 0; n = div; n++) { float t = n / (float)div; Vector3 v = Slerp(v1, v2, t); float lat = MathHelper.ToDegrees((float)Math.Asin(v.Y)); Console.Write(string.Format("{0} lat={1 f1} / ", n, lat)); Print(v); } Console.ReadLine(); } static void Print(Vector3 v) { Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} len={3 f2}", v.X, v.Y, v.Z, v.Length())); } static void Print(Quaternion q) { Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} w={3 f2} len={4 f2}", q.X, q.Y, q.Z, q.W, q.Length())); } static Vector3 Slerp(Vector3 value1, Vector3 value2, float amount) { value1.Normalize(); value2.Normalize(); float dot = Vector3.Dot(value1, value2); // cosθ float angle = (float)Math.Acos(dot); // 2ベクトル間の角度 float Ps = (float)Math.Sin(angle * (1 - amount)); float Pe = (float)Math.Sin(angle * amount); Vector3 v = (Ps * value1 + Pe * value2) / (float)Math.Sin(angle); v.Normalize(); return v; } static Quaternion Slerp(Quaternion value1, Quaternion value2, float amount) { value1.Normalize(); value2.Normalize(); float dot = Quaternion.Dot(value1, value2); // cosθ float angle = (float)Math.Acos(dot); // 2ベクトル間の角度 float sinTheta = (float)Math.Sin(angle); float Ps = (float)Math.Sin(angle * (1 - amount)) / sinTheta; float Pe = (float)Math.Sin(angle * amount) / sinTheta; Quaternion q = value1 * Ps + value2 * Pe; q.Normalize(); return q; } } 出力 x=1.00 y=0.00 z=0.00 len=1.00 x=-0.50 y=0.87 z=0.00 len=1.00 x=1.00 y=0.00 z=0.00 w=0.00 len=1.00 x=-0.50 y=0.87 z=0.00 w=0.00 len=1.00 dot=-0.50 Quaternion.Slerp 0 lat=0.0 / x=1.00 y=0.00 z=0.00 w=0.00 len=1.00 1 lat=-15.0 / x=0.97 y=-0.26 z=0.00 w=0.00 len=1.00 2 lat=-30.0 / x=0.87 y=-0.50 z=0.00 w=0.00 len=1.00 3 lat=-45.0 / x=0.71 y=-0.71 z=0.00 w=0.00 len=1.00 4 lat=-60.0 / x=0.50 y=-0.87 z=0.00 w=0.00 len=1.00 Slerp(Quaternion) 0 lat=0.0 / x=1.00 y=0.00 z=0.00 w=0.00 len=1.00 1 lat=30.0 / x=0.87 y=0.50 z=0.00 w=0.00 len=1.00 2 lat=60.0 / x=0.50 y=0.87 z=0.00 w=0.00 len=1.00 3 lat=90.0 / x=0.00 y=1.00 z=0.00 w=0.00 len=1.00 4 lat=60.0 / x=-0.50 y=0.87 z=0.00 w=0.00 len=1.00 Slerp(Vector3) 0 lat=0.0 / x=1.00 y=0.00 z=0.00 len=1.00 1 lat=30.0 / x=0.87 y=0.50 z=0.00 len=1.00 2 lat=60.0 / x=0.50 y=0.87 z=0.00 len=1.00 3 lat=90.0 / x=0.00 y=1.00 z=0.00 len=1.00 4 lat=60.0 / x=-0.50 y=0.87 z=0.00 len=1.00 考察 クォータニオンの内積は|q1||q2|cosθであり、θが+-90°を超えるとマイナスになる。 つまりベクトルの地球を突き抜けた後ろ側が近くなる。 円周でたとえるなら、0°と120°のベクトルでは120°の後ろ側-60°との距離が最短になる。 それがQuaternion.Slerpの仕様なのかお節介なのかは分からない。 Slerp関数を用意するなら球面線形補間はVector3で済む。
https://w.atwiki.jp/sampleisbest/pages/237.html
開発環境 Microsoft Visual C# 2010 Express (SP1) 実行環境 Microsoft Windows XP Home Edition (SP3) プロジェクトの種類 空のプロジェクト プロジェクト名 Quaternion 参考 航法(航海)計算#大圏航法 四元数で3次元の回転を計算する方法 (ソースコード付き) Program.cs // Quaternion6 大圏コース逆算 using System; using Microsoft.Xna.Framework; // .NET参照 class Program { static void Main() { float startLatDeg = 35; float startLonDeg = 135; float angleDeg = 53.22f; float distNM = 4863.88f; float startLatRad = MathHelper.ToRadians(startLatDeg); float startLonRad = MathHelper.ToRadians(startLonDeg); float angleRad = MathHelper.ToRadians(angleDeg); float dist = distNM * 1.852f / 20000; Console.WriteLine(string.Format("dist={0 f2}", dist)); // +Z=0 +X=90 float y = (float)Math.Sin(startLatRad); float r = (float)Math.Cos(startLatRad); float z = (float)Math.Cos(startLonRad) * r; float x = (float)Math.Sin(startLonRad) * r; Vector3 axis = new Vector3(x, y, z); // 回転軸 Print(axis); // +Z=0 +X=90 float rad = startLatRad + dist * MathHelper.Pi; y = (float)Math.Sin(rad); r = (float)Math.Cos(rad); z = (float)Math.Cos(startLonRad) * r; x = (float)Math.Sin(startLonRad) * r; Vector3 v = new Vector3(x, y, z); // 回転する座標 Print(v); Quaternion p = new Quaternion(v, 0); Quaternion rot = Quaternion.CreateFromAxisAngle(axis, angleRad); Quaternion q = Quaternion.Conjugate(rot) * p * rot; Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} w={3 f2} len={4 f2}", q.X, q.Y, q.Z, q.W, q.Length())); PrintLatLon(q.X, q.Y, q.Z); Console.ReadLine(); } static void Print(Vector3 v) { Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} len={3 f2}", v.X, v.Y, v.Z, v.Length())); PrintLatLon(v.X, v.Y, v.Z); } static void PrintLatLon(float x, float y, float z) { Console.WriteLine(string.Format("lat={0 f1} lon={1 f1}", MathHelper.ToDegrees((float)Math.Asin(y)), MathHelper.ToDegrees((float)Math.Atan2(x, z)))); } } 出力 dist=0.45 x=0.58 y=0.57 z=-0.58 len=1.00 lat=35.0 lon=135.0 x=-0.31 y=0.90 z=0.31 len=1.00 lat=63.9 lon=-45.0 x=-0.71 y=0.57 z=-0.41 w=0.00 len=1.00 lat=35.0 lon=-120.0 Program.cs // Quaternion6 2.Vector4 ver. using System; using Microsoft.Xna.Framework; // .NET参照 class Program { static void Main() { float startLatDeg = 35; float startLonDeg = 135; float angleDeg = 53.22f; float distNM = 4863.88f; float startLatRad = MathHelper.ToRadians(startLatDeg); float startLonRad = MathHelper.ToRadians(startLonDeg); float angleRad = MathHelper.ToRadians(angleDeg); float dist = distNM * 1.852f / 20000; Console.WriteLine(string.Format("dist={0 f2}", dist)); // +Z=0 +X=90 float y = (float)Math.Sin(startLatRad); float r = (float)Math.Cos(startLatRad); float z = (float)Math.Cos(startLonRad) * r; float x = (float)Math.Sin(startLonRad) * r; Vector3 axis = new Vector3(x, y, z); // 回転軸 Print(axis); // +Z=0 +X=90 float rad = startLatRad + dist * MathHelper.Pi; y = (float)Math.Sin(rad); r = (float)Math.Cos(rad); z = (float)Math.Cos(startLonRad) * r; x = (float)Math.Sin(startLonRad) * r; Vector3 v = new Vector3(x, y, z); // 回転する座標 Print(v); Vector4 p = new Vector4(v, 0); Vector4 rot = CreateFromAxisAngle(axis, angleRad); Vector4 conj = new Vector4(-rot.X, -rot.Y, -rot.Z, rot.W); Vector4 q = MulQ(MulQ(conj, p), rot); Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} w={3 f2} len={4 f2}", q.X, q.Y, q.Z, q.W, q.Length())); PrintLatLon(q.X, q.Y, q.Z); Console.ReadLine(); } static Vector4 CreateFromAxisAngle(Vector3 axis, float angle) { // 回転軸の正規化 float norm = axis.Length(); if (norm = 0) return Vector4.Zero; norm = 1 / (float)Math.Sqrt(norm); axis *= norm; angle *= 0.5f; float c = (float)Math.Cos(angle); float s = (float)Math.Sin(angle); Vector4 v = new Vector4(axis * s, c); return v; } static Vector4 MulQ(Vector4 v1, Vector4 v2) { Vector4 v; v.X = (v1.W * v2.X) + (v1.X * v2.W) + (v1.Y * v2.Z) - (v1.Z * v2.Y); v.Y = (v1.W * v2.Y) + (v1.Y * v2.W) + (v1.Z * v2.X) - (v1.X * v2.Z); v.Z = (v1.W * v2.Z) + (v1.Z * v2.W) + (v1.X * v2.Y) - (v1.Y * v2.X); v.W = (v1.W * v2.W) - (v1.X * v2.X) - (v1.Y * v2.Y) - (v1.Z * v2.Z); return v; } static void Print(Vector3 v) { Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} len={3 f2}", v.X, v.Y, v.Z, v.Length())); PrintLatLon(v.X, v.Y, v.Z); } static void PrintLatLon(float x, float y, float z) { Console.WriteLine(string.Format("lat={0 f1} lon={1 f1}", MathHelper.ToDegrees((float)Math.Asin(y)), MathHelper.ToDegrees((float)Math.Atan2(x, z)))); } }
https://w.atwiki.jp/sampleisbest/pages/230.html
開発環境 Microsoft Visual C# 2010 Express (SP1) 実行環境 Microsoft Windows XP Home Edition (SP3) プロジェクトの種類 空のプロジェクト プロジェクト名 Quaternion 参考 床井研究室 - ゲームグラフィックス特論 クォータニオンを"使わない"球面線形補間 Program.cs // Quaternion3 球面線形補間の実験3 using System; using Microsoft.Xna.Framework; // .NET参照 class Program { static void Main() { float rad = MathHelper.ToRadians(60); float x = (float)Math.Cos(rad); float y = (float)Math.Sin(rad); Vector3 v1 = new Vector3(1, 0, 0); Vector3 v2 = new Vector3(x, y, 0); Vector3 v3 = new Vector3(-x, y, 0); Print(v1); Print(v2); Print(v3); float dot; dot = Vector3.Dot(v1, v2); Console.WriteLine(string.Format("dot={0 f2}", dot)); Console.WriteLine("0°→60°"); Test(v1, v2); dot = Vector3.Dot(v1, v3); Console.WriteLine(string.Format("dot={0 f2}", dot)); Console.WriteLine("0°→120°"); Test(v1, v3); Console.ReadLine(); } static void Print(Vector3 v) { Console.WriteLine(string.Format("x={0 f2} y={1 f2} z={2 f2} len={3 f2}", v.X, v.Y, v.Z, v.Length())); } static void Test(Vector3 v1, Vector3 v2) { for (int n = 0; n = 4; n++) { float t = n / 4.0f; Vector3 v = Slerp(v1, v2, t); float lat = MathHelper.ToDegrees((float)Math.Asin(v.Y)); Console.Write(string.Format("{0} lat={1 f1} / ", n, lat)); Print(v); } } static Vector3 Slerp(Vector3 value1, Vector3 value2, float amount) { value1.Normalize(); value2.Normalize(); float dot = Vector3.Dot(value1, value2); // cosθ float angle = (float)Math.Acos(dot); // 2ベクトル間の角度 float Ps = (float)Math.Sin(angle * (1 - amount)); float Pe = (float)Math.Sin(angle * amount); Vector3 v = (Ps * value1 + Pe * value2) / (float)Math.Sin(angle); v.Normalize(); return v; } } 出力 x=1.00 y=0.00 z=0.00 len=1.00 x=0.50 y=0.87 z=0.00 len=1.00 x=-0.50 y=0.87 z=0.00 len=1.00 dot=0.50 0°→60° 0 lat=0.0 / x=1.00 y=0.00 z=0.00 len=1.00 1 lat=15.0 / x=0.97 y=0.26 z=0.00 len=1.00 2 lat=30.0 / x=0.87 y=0.50 z=0.00 len=1.00 3 lat=45.0 / x=0.71 y=0.71 z=0.00 len=1.00 4 lat=60.0 / x=0.50 y=0.87 z=0.00 len=1.00 dot=-0.50 0°→120° 0 lat=0.0 / x=1.00 y=0.00 z=0.00 len=1.00 1 lat=30.0 / x=0.87 y=0.50 z=0.00 len=1.00 2 lat=60.0 / x=0.50 y=0.87 z=0.00 len=1.00 3 lat=90.0 / x=0.00 y=1.00 z=0.00 len=1.00 4 lat=60.0 / x=-0.50 y=0.87 z=0.00 len=1.00
https://w.atwiki.jp/bambooflow/pages/290.html
Quaternionによる回転 GLUT (freeglut3.7) GLM 0.9.0.6 Quaternionによる回転四元数について四元数の表現 四元数の掛け算 三次元座標の四元数による表現 四元数での回転表現 c実装メモ GLMを使ったサンプルコード 四元数について 四元数の表現 四元数Qは、 Q = (t; x, y, z) と表すことができます。 このとき、tは実数部、x,y,zは虚数部です。 四元数の掛け算 A = (a; U) B = (b; V) AB = (ab - U・V; aV + bU + U×V) ただし、「・」は内積、「×」は外積を表します。 三次元座標の四元数による表現 たとえばx,y,zで示された座標を四元数で表現すると、 P = (0; x,y,z) となります。このとき実数部はとりあえず0にしておきます。 四元数での回転表現 原点を中心とした回転軸を(α,γ,β)としたとき、回転をθとした四元数は、 Q = (cos(θ/2); αsin(θ/2), βsin(θ/2), γsin(θ/2) R = (cos(θ/2);-αsin(θ/2),-βsin(θ/2),-γsin(θ/2) となります。 このとき、RはQの共役四元数といいます。 回転の実行は、 RPQ = (0; x,y,z) #x,y,zが回転した結果 Pに対してRとQを挟み込むことで座標Pに対する任意の回転座標が得られます。 c実装メモ ////////////////////////////////////////////// // クォータニオンの積 r - p x q static void qmul(double r[], const double p[], const double q[]) { r[0] = p[0] * q[0] - p[1] * q[1] - p[2] * q[2] - p[3] * q[3]; r[1] = p[0] * q[1] + p[1] * q[0] + p[2] * q[3] - p[3] * q[2]; r[2] = p[0] * q[2] - p[1] * q[3] + p[2] * q[0] + p[3] * q[1]; r[3] = p[0] * q[3] + p[1] * q[2] - p[2] * q[1] + p[3] * q[0]; } ///////////////////////////////////////////// // 回転の変換行列 r - クォータニオン q static void qrot(double r[], double q[]){ double x2 = q[1] * q[1] * 2.0; double y2 = q[2] * q[2] * 2.0; double z2 = q[3] * q[3] * 2.0; double xy = q[1] * q[2] * 2.0; double yz = q[2] * q[3] * 2.0; double zx = q[3] * q[1] * 2.0; double xw = q[1] * q[0] * 2.0; double yw = q[2] * q[0] * 2.0; double zw = q[3] * q[0] * 2.0; r[ 0] = 1.0 - y2 - z2; r[ 1] = xy + zw; r[ 2] = zx - yw; r[ 4] = xy - zw; r[ 5] = 1.0 - z2 - x2; r[ 6] = yz + xw; r[ 8] = zx + yw; r[ 9] = yz - xw; r[10] = 1.0 - x2 - y2; r[ 3] = r[ 7] = r[11] = r[12] = r[13] = r[14] = 0.0; r[15] = 1.0; } GLMを使ったサンプルコード GLMを使うことで簡単に記述できます。 マウスでくるくる。。 #include math.h #include GL/glut.h #include glm/glm.hpp #include glm/gtc/type_ptr.hpp #include glm/gtc/quaternion.hpp static glm vec4 red = glm vec4( 0.8, 0.2, 0.2, 1.0 ); // 物体の色 static glm vec4 lightPos = glm vec4( 3.0, 4.0, 5.0, 1.0 ); // 光源の位置 static glm vec3 eyePos(0.0, 0.0, 10.0); // 視点 static glm vec3 ctrPos(0.0, 0.0, 0.0); // 目標点 static glm dvec2 s; // 係数 static glm ivec2 st_pos; // マウスクリック位置 static glm quat cq(1.0, 0.0, 0.0, 0.0); // 回転初期値 (クォータニオン) static glm quat tq; // ドラッグ中の回転 (クォータニオン) static glm mat4 rt; // 回転の変換行列 void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt( eyePos.x, eyePos.y, eyePos.z, ctrPos.x, ctrPos.y, ctrPos.z, 0.0, 1.0, 0.0 ); glLightfv(GL_LIGHT0, GL_POSITION, glm value_ptr(lightPos)); glPushMatrix(); { glEnable(GL_LIGHTING); glMaterialfv(GL_FRONT, GL_DIFFUSE, glm value_ptr(red)); glMultMatrixf(glm value_ptr(rt)); // 回転 glutSolidTeapot(1.5); } glPopMatrix(); glutSwapBuffers(); } void resize(int w, int h) { // ドラッグ用係数 - ウィンドウサイズに依存 s.x = 1.0 / (double)w; s.y = 1.0 / (double)h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); } void idle(void) { glutPostRedisplay(); } void mouse(int button, int state, int x, int y) { switch (button) { case GLUT_LEFT_BUTTON switch (state) { case GLUT_DOWN st_pos = glm ivec2( x, y ); glutIdleFunc(idle); break; case GLUT_UP glutIdleFunc(0); cq = tq; // 回転保持 break; default break; } break; default break; } } void motion(int x, int y) { static const double scale = (2.0 * M_PI); glm dvec2 d; double a; d.x = double(x - st_pos.x) * s.x; d.y = double(y - st_pos.y) * s.y; a = glm length(d); if (a != 0.0) { double ar = a * scale * 0.5; double as = sin(ar) / a; glm quat dq(cos(ar), as*d.y, as*d.x, 0.0); tq = glm cross(dq, cq); // 回転合成 rt = glm mat4_cast(tq); // Quotanion- 回転の変換行列 } } void init(void) { glClearColor(0.2, 0.2, 0.2, 1.0); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glCullFace(GL_FRONT); rt = glm mat4_cast(cq); // 回転行列初期化 } int main(int argc, char *argv[]) { glutInit( argc, argv); glutInitWindowSize(600, 400); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("glm quatanion test"); glutDisplayFunc(display); glutReshapeFunc(resize); glutMouseFunc(mouse); glutMotionFunc(motion); init(); glutMainLoop(); return 0; }
https://w.atwiki.jp/liicaq2wiki/pages/28.html
第4ステージ。ここからは非常にテクニックを使うため、難易度がこれまでより高くなる。 凡人での攻略も難しくなるため、遠投やジャンパー、怪力らへんがあると気が楽かも。 ステージ一覧 ↑TERTIARY QUATERNARY 1 QUATERNARY 2 QUATERNARY 3 QUATERNARY 4 ←ZETA 12 QUATERNARY 5 QUATERNARY 6 QUATERNARY 7 QUATERNARY 8 GAMMA 5→ QUATERNARY 9 QUATERNARY 10 QUATERNARY 11 QUATERNARY 12 QUATERNARY 13 QUATERNARY 14 QUATERNARY 15 QUATERNARY 16 ↓QUINARY
https://w.atwiki.jp/liicaq2wiki/pages/47.html
後半第2ステージ。 無重力オブジェクトも登場する。非常に難しい。 ステージ一覧 ↑裏QUINARY 裏QUATERNARY 16 裏QUATERNARY 15 裏QUATERNARY 14 裏QUATERNARY 13 裏QUATERNARY 12 裏QUATERNARY 11 裏QUATERNARY 10 裏QUATERNARY 9 裏ZETA 16→ 裏QUATERNARY 8 裏QUATERNARY 7 裏QUATERNARY 6 裏QUATERNARY 5 ←裏GAMMA 16 裏QUATERNARY 4 裏QUATERNARY 3 裏QUATERNARY 2 裏QUATERNARY 1 ↓裏TERTIARY
https://w.atwiki.jp/dominions4/pages/32.html
概要 Marverniは、Druidと宗教的な執政官によって導かれる部族的な首長制の国です。 部族間には長い戦争と内紛の歴史がありますが、最近の情勢は1つの目的の追求のために部族を纏め上げました。 もっとも著名な部族は、Marverni、Ambibate、Eponi、Carnuteです。 小さな部族であるとしても、Sequaniは多くのDruidを擁するために影響力を持ちます。 Marverni族の鍛冶屋はチェインメイルの発明者と言われており、部族の貴族の大半はこれを用います。 卑しい生まれの戦士らは、胸を露にして戦います。 Ambibateはその戦闘技能において知られています。 Eponi貴族は馬に乗って戦い、この国が利用できる唯一の騎兵です。 Carnute族は、Druidが毎年集まる神聖なるCarnutesの森を守ります。 Carnuteの戦士は、傷つくと狂戦士の怒りに落ちます。 猪はMarverniの国における神聖なシンボルです。 種族 人間 軍事 軽装・中装歩兵、中装騎兵 魔法 地、星、緑、水 聖職者 平均的。生贄の儀式を実行可能 要塞技術 レベル1(Fortress) 初期宝石 地2、星3、緑1 魔法土地 Carnutes 指揮官 名称 コスト 制限 雇用条件 解説 Marverni Scout 25g,2r 要塞 偵察兵:槍のみを持つやや安価な偵察兵。役割は他国のものと変わらない Marverni Chieftain 50g,17r 要塞 指揮官:基本的な指揮官。統率に優れ、指揮下の部隊すべての士気を上げる。指揮上限60 Ambibate Chieftain 55g,17r 要塞 指揮官:やや戦闘技能が高い指揮官。直接戦わせるつもりがなければとくに必要はない。指揮上限60 Carnute Chieftain 60g,15r 要塞 指揮官:狂戦士の指揮官。事故死の率が高いが、森林のサバイバル能力は利点になり得る。指揮上限60 Eponi Chieftain 100g,18r 要塞 指揮官:騎乗した指揮官。騎兵の迅速な行軍に役立ち、単純な指揮能力を見ても優秀。指揮上限80 Vergobret 65g,1r 要塞 聖職者:レベル1聖職者。指揮能力に優れている。指揮上限80。老齢。 Sequani Stargazer 45g,1r 要塞 魔術師:星魔法を使う魔術師。悪性イベントを低確率で阻止する。マップ移動力1 Gutuater 135g,1r 要塞 聖職者:レベル1聖職者。緑を中心とした魔法スキルも持つ Druid 175g,1r 要塞 聖職者:レベル1聖職者。地、星を中心とした魔法スキルも持つ。指揮上限40。マップ移動力1 Boar Lord 90g,15r 要塞 指揮官:狂戦士のSacred指揮官。戦闘力に優れ、適切な装備があれば直接戦闘での活躍を期待できる。指揮上限40 Elder Druid 340g,3r 2ターン雇用 要塞 聖職者:レベル2聖職者。地と星を中心とした高い魔法スキルも持つ。指揮上限40。老齢。マップ移動力1 兵士 名称 コスト 制限 雇用条件 解説 Marverni Horn Blower 20g,5r 要塞 角笛兵:角笛の音色で同部隊の味方の士気を向上させる兵。戦闘力は乏しい Marverni Slinger 8g,3r 要塞 投石兵:盾も装備した安価な射撃兵。防具を欠く相手にはそれなりに強い Marverni Javelineer 8g,5r 要塞 手槍兵:槍と手槍、盾を持つ兵。鎧兜を持たないため攻撃には耐えられない Marverni Bare Chested Warrior 8g,9r 要塞 軽歩兵:長剣と手槍、盾を持つ軽歩兵。兜は持つが鎧がなく、士気にも問題あり Marverni Noble Warrior 11g,17r 要塞 歩兵:長剣と盾を持つ歩兵。手槍はないが真っ当な防具を装備し、戦闘技能も高め Ambibate Bare Chested Warrior 10g,8r 要塞 軽歩兵:長剣と盾を持つ軽歩兵。戦闘技能は高めだが鎧がないので消耗しがち Ambibate Noble Warrior 14g,17r 要塞 歩兵:長剣と盾を持つ精鋭歩兵。高い戦闘技能と無難な武装を持つ Carnute Bare Chested Warrior 12g,6r 要塞 軽歩兵:斧と盾を持つ狂戦士。消耗は早いが攻撃面では強力。森林のサバイバル能力あり Carnute Noble Warrior 16g,15r 要塞 歩兵:斧と盾を持つ精鋭狂戦士。攻撃寄りだが真っ当な防具のおかげで瞬殺はされにくい。森林のサバイバル能力あり Eponi Knight 30g,18r 要塞 騎兵:長剣と手槍、盾を持つ騎兵。突撃ボーナスが無いが、無難な戦闘力を持つ Boar Warrior 30g,15r 要塞 歩兵:Sacred。斧と盾を持つ狂戦士。優れた戦闘力を持ち、護衛にも適している 地方守備隊 種別 指揮官 兵士 備考 地上下位 Marverni Chieftain Marverni Slinger 10 Marverni Javelineer 10 Marverni Bare Chested Warrior 10 地上上位 Vergobret Marverni Noble Warrior 10 魔法技能 条件 名称 固定 変動 備考 要塞 Vergobret 1 Sacred Old Age 要塞 Sequani Stargazer 1 要塞 Gutuater 11 +1 100% Sacred 要塞 Druid 111 +1 100% Sacred 首都 Elder Druid 222 +1 100% +1 100% +1 10% Sacred Old Age 固有魔法 領域 使用 名称 主属性 副属性 宝石 解説 Conjuration Lv3 儀式 Sounder of Boars 2 20 敵を蹂躙する神聖なる猪Great Boarを20体召喚します Conjuration Lv5 儀式 Monster Boar 3 10 指定した州にMonster Boarを潜伏させ、不安度を増加させます Conjuration Lv5 儀式 Contact Boar of Carnutes 1 1 7 知的で神聖な大猪Great Boar of Carnutesを召喚します Alteration Lv6 儀式 Iron Pigs 3 1 10 敵を蹂躙する神聖なる鋼鉄の猪Iron Boarを7体召喚します ※Iron Pigsは固有魔法ではありませんが、他国が使用した際とは結果が異なります 前作からの変更点 Druidの魔力が低下、コストも同様に低下した 以前のDruidと同等の性能を持つElder Druidが首都専用で雇用可能になった コメント 名前 コメント