首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

MDX 3D 旋轉實作(二):球面座標與向量叉積的滑鼠軌跡旋轉算法

     編輯:關於.NET

前言:算法來源與啟發

3D 旋轉算法並非原創,參考學術論文與開源專案整理而成。關鍵在於理解滑鼠在視口上的移動對應球面軌跡,而非平面直線。

核心幾何模型:半球面軌跡

滑鼠點擊視口邊緣拖曳,對應半球面上從 A 點到 B 點的圓弧軌跡。旋轉軸為平面 OAB 的法向量,旋轉角為向量 OA、OB 的夾角。

半球面軌跡示意

數學公式

  • 旋轉軸(法向量):n = OA × OB(向量叉積)
  • 旋轉角:α = acos( (OA·OB) / (|OA|·|OB|) )(向量內積)
  • 實務上常取 α * 2,使滑鼠從左邊緣拖至右邊緣即完成繞 Y 軸 360° 旋轉。

關鍵問題:螢幕座標到球面向量的映射

視口中心為球心,半徑 R = min(Width, Height)/2。滑鼠點 (x, y) 相對中心向量 (dx, dy)。

分兩種情況:

  • 點在球面投影內:dx² + dy² ≤ R²,Z = √(R² - dx² - dy²),向量單位化。
  • 點在球面投影外:Z = 0,向量投影至球面赤道平面並單位化(避免 NaN)。

座標映射示意

完整核心代碼解析

float radius = Math.Min(this.Width, this.Height) / 2f;

// 前一次滑鼠向量
Vector3 pre = new Vector3(_posLast.X - radius, _posLast.Y - radius, 0);
float sq = radius*radius - pre.X*pre.X - pre.Y*pre.Y;
if (sq <= 0) {
    pre.Z = 0;
    pre = Vector3.Normalize(new Vector3(pre.X, pre.Y, 0));
} else {
    pre.Z = (float)Math.Sqrt(sq);
    pre = Vector3.Normalize(pre);
}

// 當前滑鼠向量
Vector3 cur = new Vector3(e.X - radius, e.Y - radius, 0);
sq = radius*radius - cur.X*cur.X - cur.Y*cur.Y;
if (sq <= 0) {
    cur.Z = 0;
    cur = Vector3.Normalize(new Vector3(cur.X, cur.Y, 0));
} else {
    cur.Z = (float)Math.Sqrt(sq);
    cur = Vector3.Normalize(cur);
}

if (pre == cur) return;

// 旋轉軸與角度
Vector3 axis = Vector3.Cross(pre, cur);
float angle = (float)Math.Acos(Vector3.Dot(pre, cur) / (pre.Length() * cur.Length()));

// 累積旋轉矩陣(右乘)
_matrixRotation.Multiply(Matrix.RotationAxis(axis, angle * 2));

關鍵細節避坑指南

  1. 向量相等/極小時的退化:pre == cur 直接返回,否則 Cross 產生零向量導致後續旋轉失效。
  2. 矩陣累乘順序:必須 右乘(_matrixRotation *= newRotation),保證每次旋轉基於當前姿態疊加。
  3. 角度倍率:angle * 2 為經驗值,可依手感調整。

結語

技術如層紙,捅破前神秘,捅破後清晰。掌握球面映射與向量運算,即可實現直觀流暢的 3D 視圖旋轉控制。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved