共用方式為


觸控與執行

Windows Phone 議案和 3D 視圖

Charles Petzold

下載代碼示例

Charles Petzold
Windows Phone 7.1 引入的新議案類是一個好的工具,對於程式師需要知道如何電話面向在三維的空間。運動類將資訊從感應器 (加速度計、 磁強計和陀螺儀) 相結合和也來平滑資料並使其可方便的形式。

當 Windows Phone 程式瞭解的電話在 3D 空間中的定位時,電話可以進入一個 3D 世界提供一個入口網站。這項設施有應用程式映射、 虛擬實境、 增強的現實,當然,遊戲,但可能還有些應用程式,有沒有未受孕。這絕對是你要像你編碼的技能一樣行使你的想像力的領域。

運動資料

我想要只專注于獲取電話,而不是速度或加速度,這也可從運動類的方向。感應器提供的 MotionReading 結構,和方向的資訊是可用的態度屬性中。"態度"一詞來自飛行動力學,它指示在 3D 空間中的一架飛機的方向 — — 從海拔高度的不同,這是地球以上的高度。這個詞有時也用於向量幾何。

這個態度屬性是類型 AttitudeReading,另一種結構,用於定義描述三維方向的五個屬性:

  • 偏航角的浮點類型,以弧度表示的角
  • 浮點類型,以弧度表示的角的音調
  • 輥的浮點類型,以弧度表示的角
  • 新華社中定義的類型矩陣,4 × 4 矩陣類型的 RotationMatrix
  • 四元數的類型四元數,新華社在定義的類型

偏航,音調和卷也飛行動力學中使用的術語和他們正在即通常所指的歐拉角。偏航指示羅盤方向平面的鼻子所面臨的諸多,因此飛機轉右或左,偏航更改。隨著鼻子攀爬的間距更改或向下俯衝。左和右平面銀行作為卷的更改。直觀顯示這些公約電話,它有助於想像到你前面電話和到你後面的三個標準按鈕的頂部的"飛天"你像魔毯在手機上坐上這款手機的螢幕。

一個叫做 YawPitchRoll 包含在可下載的代碼,這篇文章的小程式可能也有助於直觀顯示這些角度。(像這篇文章中的所有程式,它需要向 Microsoft.Devices.Sensors 和 Microsoft.Xna.Framework 的程式集的引用。)如中所示圖 1,該程式顯示的值轉換為度,這三個角度,它還象徵著它們的值以圖形方式。


圖 1 YawPitchRoll 顯示

指向北像一個指南針,簡單線條顯示偏航而瀝青和卷都顯示為似乎滾向地球的固體球。當電話坐在了螢幕和手機指向北方的頂部水準表上時,所有三個角度有零值。

如你向上和向下傾斜手機的頂部,您可以從 90 ° 更改間距,當手機-90 ° 到直立時手機的頂部向下指。同樣,您可以更改卷從 90 °-90 ° 到倒騰的左、 右的電話。

當電話顯示朝下,南偏航角點。攤位就值範圍從 90 ° 到 180 °,和到-180 °-90 °。在 YawPitchRoll 程式中,這些值是空心的紅色-概述的球的象徵。值的卷繼續採取從 90 度到-90 ° 的值。

旋轉角度

雖然我們花費我們整個的生活在一個三維的宇宙,我們很多人掌握很窮直觀的三維旋轉。因此,直觀顯示和使用在 3D 空間中旋轉,頗具挑戰性。偏航,攤位和輥似乎充分說明您在 3D 空間中旋轉,但他們變成尷尬實際程式設計中。

程式師更喜歡使用替代的方式來描述 3D 旋轉:

  • 一個單一的角度描述圍繞 3D 向量 (軸/角度旋轉) 旋轉
  • 旋轉矩陣 (全 3D 矩陣變換的子集)
  • 四元數,複雜平面的 2D 旋轉 3D 類比

這些表單可全部之間轉換對方,因為我演示中的章節 7 及 8 條"3D 程式設計 Windows 的"我的書 (微軟出版社,2008年)。四元數是從一個方向順利遷移到另一種特別有用,因為它適合線性插值。

運動類提供 3D 旋轉旋轉矩陣和四元數,但我會只專注的 AttitudeReading 結構的 RotationMatrix 屬性。這是新華社矩陣值,這是一個標準的 4 × 4 變換矩陣,但該矩陣表示只旋轉。它具有無縮放和沒有翻譯。M14、 較老的 M24、 M34、 M41、 M42 和 M43 欄位是所有 0,且 M44 欄位為 1。

當使用此旋轉矩陣,角度的改變將非常有用。此列中的前一部分中,描述如何從加速度計和指南針感應器可用的三維向量是相對於 3D 坐標系強加于地理的電話。不過,在處理時的旋轉矩陣,您真的需要直觀顯示兩個不同 3D 坐標系,另一個用於手機和其他地球:

  • 這款手機的 3D 的座標系統中積極 Y 指向頂部的 (在縱向模式),電話 X 點右和積極正面 Z 出來螢幕。
  • 在地球的三維座標系統中,積極 Y 點往北,積極 X 點東和來自于大地的正 Z。

當電話坐在了螢幕的水準表面上和北指向頂部,RotationMatrix 的值是恒等矩陣。否則,它描述了地球旋轉與手機中,是相反的方式描述的歐拉角的旋轉。

要說明這點,我寫了一個叫做 MotionMatrix 的小程式。顯示 (所示圖 2) 僅包含數位值: 偏航,攤位及登記冊的價值觀,全矩陣和旋轉的軸/角形式表示的 3 × 3 旋轉矩陣子集。

The MotionMatrix Display
圖 2 MotionMatrix 顯示

當你第一次開始玩這個程式時,你立即的直覺可能是電話的方向,使所有歐拉角均為零。不過,倒在底部的軸向量都瘋掉了,因為幾乎沒有旋轉,因此軸值可以為幾乎任何東西。簡單的輪換平靜顯示。中的截圖圖 2 顯示頂部的手機指向北方,但升高約 45 °。這是的螺距值的報告,以及軸/角度旋轉顯示 46 ° 非常密切值。

但請注意,旋轉軸: 大約是 (– 1,0,0),這是座標軸指向左邊的電話。新華社軸/角度旋轉遵守右手: 指向你的右手的拇指軸的方向 (那是,左邊的電話在這種情況下)。曲線的你的手指然後顯示正旋轉的方向。這意味著旋轉對面俯仰角度。它告訴我們電話必須是旋轉-45 °,地球的對齊。

MotionMatrix 和新華社

它似乎合理的利用從運動類的旋轉矩陣用於查看 3D 物件的電話。但不正常的做法是 — — 凡 3D 物件的旋轉與顯示,或許用滑鼠或手指 — — 這裡會相對於 3D 物件旋轉了顯示幕 (從概念上講,反正)。

這個實驗,我從 archive3d 下載古董電話的 3D 模型。淨的 Web 網站 (特別是 bit.ly/GSNTi3),然後轉換為使用轉換器工具從歐特克的新華社友好 FBX 格式的 3DS 格式。創建顯示逐步更好的方法顯示此物件的四個 Visual Studio 專案。(其實,我就很有點說錯和後來才創建這些四個專案,以掩蓋這一事實 !)為了減少您的原始程式碼下載時間,所有四個專案引用相同的 3D 模型檔。

四個專案的第一個被稱為 View3DPhonePlain,這是剛才的靜態視圖的物件 ; 圖 3 顯示相關的代碼。此程式將載入在模型中,定義了一個世界轉換,縮放的模型下很多,並且定義了一個簡單的相機。(顯然多餘的欄位變數指定將使感不久。)

圖 3 View3DPhonePlain 程式

 

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    Model model;
    Matrix scaleMatrix, worldMatrix, lookatMatrix,
           viewMatrix, projectionMatrix;
    ...
    protected override void LoadContent()
    {
        model = this.Content.Load<Model>(“Phone Retro Caesar N170910”);
        foreach (ModelMesh mesh in model.Meshes)
            foreach (BasicEffect effect in mesh.Effects)
                effect.EnableDefaultLighting();
        // World matrix
        scaleMatrix = Matrix.CreateScale(0.0001f);
        worldMatrix = scaleMatrix;
        // View matrix
        lookatMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 10f),
                                                       Vector3.Zero,
                                                       Vector3.Up);
        viewMatrix = lookatMatrix;
        // Projection matrix
        float aspectRatio = 
            graphics.GraphicsDevice.Viewport.AspectRatio;
        projectionMatrix =
            Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
                                                aspectRatio,
                                                1f, 100.0f);
    }
    ...
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        model.Draw(worldMatrix, viewMatrix, projectionMatrix);
        base.Draw(gameTime);
    }
}

在 3D 圖形系統中像新華社,模型受到一系列的矩陣轉換到顯示的路上。世界變換應用第一,而且這江鎮在 3D 空間中的模型。相機是應用於連續兩次轉換的組合: 查看變換占的位置和方向的相機,而投影變換處理透視效果,還會將剪輯的所有座標都標準化。

圖 4 模型在新華社的外觀的顯示預設景觀模式,和它很多我們或許可以預期。

The View3DPhonePlain Display
圖 4 View3DPhonePlain 顯示

下一步是名為 View3DPhoneReoriented 的專案。我想要切換到縱向模式,以便在新華社內使用的三維座標都相同,使用的感應器的三維座標系統。這是一個簡單的問題,將幾個語句添加到遊戲衍生的建構函式:

 

graphics.IsFullScreen = true;
   graphics.PreferredBackBufferWidth = 480;
   graphics.PreferredBackBufferHeight = 800;

我也想要重新置放在手機本身。如前所述,運動類所提供的 3D 旋轉矩陣是恒等矩陣時電話正坐在了螢幕的表和北指向頂部。3D 電話要顯示在該位置有電話時並未想怎樣?我想要找電話的頂部,如果從上面看所以我只是添加的世界變換繞 X 軸旋轉:

 

worldMatrix *= Matrix.CreateRotationX(MathHelper.PiOver2);

結果如 [圖 5] 所示。

The View3DPhone­Reoriented Display
圖 5 View3DPhone­調整顯示的方向

相機看起來有點太接近該物件在這一點上,但這並沒有打擾我,因為我知道當我成立為法團的旋轉矩陣,我會能夠旋轉的電話要在視圖中得到這一切一點。(3D 光線和陰影的敏銳檢視器可能會注意到的方法,我使用的,但讓我天真 traipse 沿著這條路第一概念存在缺陷,然後我要修理東西。

現在讓我們把從運動類的旋轉矩陣。

從概念上講,3D 物件應似乎仍停留在空間中,固定和行動電話應允許您查看物件從不同的方向。當然,經驗不像"現實生活"因為你永遠不能行動電話要看物件。物件始終是有研究顯示,但在 3D 空間中顯示的方向為您提供了不同的意見,它。

要實現此效果,我們需要適用物件實現地球的座標系統中,此物件的概念上存在從手機的坐標系旋轉矩陣。

我們應該能夠達到這種效果只需通過在世界變換的計算中包括從運動類的 RotationMatrix 物件。View3DPhoneWorldMotion 專案執行此操作。它包括在其建構函式中創建動作感應器、 啟動它在 OnActivated 重寫並停止它在 OnDeactivated 重寫的代碼。我然後移動計算的世界變換到更新改寫,如中所示圖 6

圖 6 中 View3DPhoneWorldMotion 的更新替代

 

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
      ButtonState.Pressed)
        this.Exit();
    worldMatrix = scaleMatrix * 
      Matrix.CreateRotationX(MathHelper.PiOver2);
    if (motion != null && motion.IsDataValid)
        worldMatrix *= motion.CurrentValue.Attitude.RotationMatrix;
    base.Update(gameTime);
}

在此程式中,當您在 3D 空間中移動手機的定位您查看 3D 物件從所有不同的方向。 其效果是非常順利和 — — 我必須承認 — — 非常酷。

移旋轉

然而,越多我演奏了與此版本的程式,就越覺得出事了。

通過對世界變換應用的旋轉矩陣,3D 物件有效地旋轉與相機,不僅與光源。 在某些情況下,這將是正確的。 例如,如果要實現一個觸摸介面,所以你可以轉身的 3D 圖像用你的手指,在世界變換應用旋轉矩陣將適當。

但對此程式範例很大的不同。 我想要電話顯示要像,相對於 3D 物件,將移動,這意味著此物件應保持固定與光源的移動相機。 從動作感應器的旋轉矩陣需要應用於視圖轉換,而不是世界變換。

最後版本的程式 — — 稱為 View3DPhone­CameraMotion — — 回復原始版本的世界變換的計算:

worldMatrix = scaleMatrix;

即使應用初始旋轉是個錯誤,因為它暗示光即將從電話中,而不從上面。 新的更新方法所示圖 7

圖 7 中 View3DPhoneCameraMotion 的更新替代

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
      ButtonState.Pressed)
        this.Exit();
    if (motion != null && motion.IsDataValid)
        viewMatrix = Matrix.CreateRotationX(MathHelper.PiOver2) *
                        motion.CurrentValue.Attitude.RotationMatrix *
                        lookatMatrix;
    else
        viewMatrix = Matrix.CreateRotationX(MathHelper.PiOver2) *
                        lookatMatrix;
    base.Update(gameTime);
}

 

你真的需要試用此程式在電話中得到充分的效果,但中的圖像圖 8 顯示了一個可能的視圖。

One View in View3DPhoneCameraMotion
圖 8 個視圖中 View3DPhoneCameraMotion

Charles Petzold 是 MSDN 雜誌長期貢獻和 Windows 8 的當前正在更新他的經典著作"程式設計 Windows"(微軟出版社,1998年)。 他的網站是 charlespetzold.com

由於有關檢討這篇文章是以下技術專家: Donn Morse