7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C#Advent Calendar 2024

Day 17

【C#】3D回転入門 〜クォータニオンの理論と実装〜

Last updated at Posted at 2024-12-16

はじめに

3Dグラフィックスやゲーム開発において、物体の回転は基本的かつ重要な処理です。

前回の記事では2次元での座標変換について整理しています。

今回は3次元空間での回転、特にクォータニオンについて紹介します。

この記事で学べること

  • 3D回転の基本概念
  • クォータニオンの理論と実装
  • オイラー角との比較とジンバルロックの問題
  • 実践的なコード例と最適化手法

3D回転の基礎

従来の回転表現:オイラー角

オイラー角は3つの角度(X軸、Y軸、Z軸周りの回転)で3次元の回転を表現する方法です。

1000005354.png

直感的で理解しやすい反面、以下のような問題があります。

  • ジンバルロック:特定の角度で自由度が失われる

1000005351.png

  • 回転の順序依存性:XYZの順序が結果に影響する
  • 補間が難しい

クォータニオンとは

クォータニオンは4つの要素(w, x, y, z)を持つ数学的な概念で、3次元空間での回転を表現します。

1000005352.png

スカラー部が回転の角度を表し、ベクトル部が回転軸を含む

public struct Quaternion
{
    public double W { get; set; }  // スカラー部
    public double X { get; set; }  // ベクトル部(i成分)
    public double Y { get; set; }  // ベクトル部(j成分)
    public double Z { get; set; }  // ベクトル部(k成分)
}

クォータニオンの実装

基本的な操作

まず、回転軸と角度からクォータニオンを生成する方法を実装します。

C#
public static Quaternion FromAxisAngle(Vector3 axis, double angleInDegrees)
{
    // 単位ベクトル化
    double length = Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z);
    axis = new Vector3(
        axis.X / length,
        axis.Y / length,
        axis.Z / length
    );
    
    double angleInRadians = angleInDegrees * Math.PI / 180.0;
    double sinHalfAngle = Math.Sin(angleInRadians / 2.0);
    double cosHalfAngle = Math.Cos(angleInRadians / 2.0);
    
    return new Quaternion
    {
        W = cosHalfAngle,
        X = axis.X * sinHalfAngle,
        Y = axis.Y * sinHalfAngle,
        Z = axis.Z * sinHalfAngle
    };
}

クォータニオンの合成

2つの回転を合成する場合、クォータニオンの乗算を使用します。

1000005353.png

public static Quaternion Multiply(Quaternion q1, Quaternion q2)
{
    return new Quaternion
    {
        W = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z,
        X = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y,
        Y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X,
        Z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W
    };
}

点の回転

クォータニオンを使って点を回転させる実装

C#
public Vector3 RotatePoint(Vector3 point)
{
    // 共役クォータニオンの計算
    Quaternion conjugate = new Quaternion
    {
        W = this.W,
        X = -this.X,
        Y = -this.Y,
        Z = -this.Z
    };

    // 点をクォータニオンに変換
    Quaternion p = new Quaternion
    {
        W = 0,
        X = point.X,
        Y = point.Y,
        Z = point.Z
    };

    // 回転の適用: q * p * q'
    Quaternion rotated = Multiply(Multiply(this, p), conjugate);

    return new Vector3(rotated.X, rotated.Y, rotated.Z);
}

パフォーマンスの最適化

SIMDを活用した実装

.NET Core 3.0以降では、System.Numerics.Vector4を使用してSIMD演算を活用できます。

C#
public static Vector3 RotatePointSimd(Vector4 quaternion, Vector3 point)
{
    Vector4 p = new Vector4(point, 0);
    Vector4 q = quaternion;
    Vector4 qConjugate = new Vector4(-q.X, -q.Y, -q.Z, q.W);

    Vector4 result = Vector4.Multiply(
        Vector4.Multiply(q, p),
        qConjugate
    );

    return new Vector3(result.X, result.Y, result.Z);
}

キャッシュ効率の改善

大量の点を回転させる場合、以下のように実装することでキャッシュ効率を改善できます。

C#
public void RotatePoints(Vector3[] points, Vector3[] results)
{
    const int batchSize = 1024; // キャッシュラインに合わせたサイズ
    
    for (int i = 0; i < points.Length; i += batchSize)
    {
        int count = Math.Min(batchSize, points.Length - i);
        for (int j = 0; j < count; j++)
        {
            results[i + j] = RotatePoint(points[i + j]);
        }
    }
}

実践的な使用例

カメラの制御

カメラの視点制御にクォータニオンを使用する例

C#
public class Camera
{
    public Vector3 Position { get; set; }
    public Quaternion Rotation { get; set; }
    
    public void LookAt(Vector3 target)
    {
        Vector3 direction = Vector3.Normalize(target - Position);
        Vector3 up = new Vector3(0, 1, 0);
        
        // 前方ベクトルとアップベクトルから回転を計算
        Vector3 right = Vector3.Normalize(Vector3.Cross(up, direction));
        up = Vector3.Cross(direction, right);
        
        // 回転行列からクォータニオンを生成
        // (実装は省略)
    }
}

まとめ

クォータニオンを使用することで、以下のような利点があります。

  • ジンバルロックの回避
  • 滑らかな補間が可能
  • 数値的な安定性
  • 効率的な計算

ただし、以下の点に注意が必要です。

  • 直感的な理解が難しい
  • デバッグが複雑になりやすい
  • 正規化の重要性

補足:最新の実装テクニック(2024年版)

最新の.NETでの実装

.NET 6以降では、より効率的な数値計算が可能になっています。

.NET7/8でのベクトル演算の最適化例
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;

public static Vector3 RotatePointModern(Vector4 quaternion, Vector3 point)
{
    if (Avx.IsSupported)
    {
        // AVXを使用した高速な回転計算
        var vec = Vector256.Create(point.X, point.Y, point.Z, 0f);
        // ... AVXを使用した実装
    }
    
    // 従来の実装にフォールバック
    return RotatePoint(quaternion, point);
}

Unityでの最新の実装(2024年)

Unity 2022.3以降では、Burst CompilerとJob Systemを活用した並列処理が可能です。

Burstコンパイル対応の回転処理
using Unity.Mathematics;
using Unity.Jobs;
using Unity.Burst;

[BurstCompile]
public struct RotatePointsJob : IJobParallelFor
{
    public NativeArray<float3> Points;
    public quaternion Rotation;
    
    public void Execute(int index)
    {
        Points[index] = math.rotate(Rotation, Points[index]);
    }
}

パフォーマンスに関する最新の知見

SIMD演算の活用

  • AVX-512命令セットの利用(対応CPUの場合)
  • ハードウェアアクセラレーションの活用

メモリ最適化

メモリアライメントとSpanの活用による効率改善

最適化されたクォータニオン構造体
[StructLayout(LayoutKind.Sequential, Pack = 16)]
public struct OptimizedQuaternion
{
    public Vector4 Value;  // 16バイトアライメント
}

クラウドでの3D処理

最近のクラウドサービスでは、GPUアクセラレーションを活用した3D処理が可能になっています。

  • Azure Kinect DKのボーントラッキング
  • AWSのAmazon Sumerian(3D/AR/VR)
  • Google Cloud Platform の3Dレンダリングサービス

これらのサービスと連携する際も、クォータニオンは重要な役割を果たしています。

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?