Koordinat tiga dimensi ke konversi koordinat layar
ringkasan
Ini mengubah koordinat dalam ruang 3D menjadi koordinat di layar dan menampilkan nama di lokasi model. Dalam sampel, kamera diputar untuk memudahkan melihat bahwa namanya mengikuti model.
Lingkungan operasi
Prasyarat
Versi XNA yang Didukung |
|
Platform yang Didukung |
|
Versi Vertex Shader yang Diperlukan Windows | 2.0 |
Versi Pixel Shader yang Diperlukan Windows | 2.0 |
Lingkungan operasi
balei-balei |
|
zat
Mengonversi koordinat 3D ke koordinat layar
Jika Anda ingin menampilkan nama di atas kepala karakter, seperti dalam game 3D, perlu untuk menghitung koordinat layar di mana karakter harus ditampilkan dari posisi spasial tiga dimensi karakter.
Ini mungkin tampak seperti perhitungan yang sulit, tetapi pada kenyataannya, data simpul poligon diperoleh dengan cara yang sama seperti rumus yang digunakan untuk mengubah data simpul poligon dari koordinat 3D ke koordinat layar, sehingga tidak diperlukan pengetahuan baru.
Ada juga metode yang mudah dihitung, sehingga Anda tidak perlu menulis kode tambahan apa pun.
kebun
Dalam sampel, tiga model ditampilkan, jadi kami mendefinisikan Model dan Vektor[3], yang merupakan tiga informasi posisi. Ini juga mendefinisikan sudut rotasi otomatis untuk kamera sehingga gerakannya mudah dipahami.
<summary>
モデル
</summary>
private Model model = null;
<summary>
位置の配列
</summary>
private Vector3[] positions = new Vector3[3];
<summary>
カメラの水平回転角度
</summary>
private float theta = 0.0f;
Proses pembaruan
Sudut rotasi untuk rotasi otomatis kamera diperoleh dari waktu permainan yang telah berlalu.
// カメラの水平角度を自動更新
this.theta = (float)gameTime.TotalGameTime.TotalSeconds / 2.0f;
Pra-Gambar
Setelah menggambar sprite, buffer kedalaman mungkin dinonaktifkan, jadi atur "DepthStencilState.Default" untuk mengaktifkan penilaian gambar berdasarkan nilai kedalaman.
Dengan mengalikan matriks rotasi sumbu Y dengan matriks tampilan yang telah Anda buat, Anda dapat memutar posisi kamera di sekitar titik yang menarik. Perhatikan urutan di mana matriks dikalikan.
// Zバッファを有効にする
this.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
// ビューマトリックスに回転を合成算出
Matrix rotatedView = Matrix.CreateRotationY(this.theta) * this.view;
Dapatkan Viewport
Viewport menyediakan metode untuk mengonversi dari koordinat spasial 3D ke koordinat layar, jadi dapatkan dari GraphicsDevice.
// ビューポート取得
Viewport viewport = this.GraphicsDevice.Viewport;
Perhitungan koordinat layar dari koordinat 3D
Menemukan koordinat layar dari koordinat ruang 3D semudah menggunakan metode Viewport.Project.
Tentukan posisi spasial 3D sumber sebagai argumen pertama, matriks proyeksi sebagai argumen kedua, dan matriks tampilan sebagai argumen ketiga. Kemudian, Anda bisa mendapatkan koordinat di layar sebagai nilai yang dikembalikan.
Setelah itu, jika Anda mengekstrak nilai X dan Y dari Vector3, Anda dapat menggunakan posisi tampilan teks. (Z adalah posisi kedalaman)
// 3次元座標からスクリーンの座標算出
Vector3 v3 = viewport.Project(this.positions[i],
this.projection,
rotatedView,
Matrix.Identity);
Vector2 screenPosition = new Vector2(v3.X, v3.Y);
// テキスト描画
this.spriteBatch.DrawString(this.font, "Model " + (i + 1).ToString(),
screenPosition, Color.White);
Viewport.Project
Metode
Memproyeksikan vektor 3D dari ruang objek ke ruang layar.
sumber | Vektor3 | Vektor koordinat spasial 3D untuk proyeksi ke koordinat layar |
Proyeksi | Matriks | Matriks proyektif |
melihat | Matriks | Lihat Matriks |
dunia | Matriks | Menentukan transformasi pertama yang akan dilakukan |
Nilai Pengembalian | Vektor3 | Mendapatkan vektor pada ruang layar |
Semua Kode
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif
namespace TransformToScreen
{
<summary>
ゲームメインクラス
</summary>
public class GameMain : Microsoft.Xna.Framework.Game
{
<summary>
グラフィックデバイス管理クラス
</summary>
private GraphicsDeviceManager graphics = null;
<summary>
スプライトのバッチ化クラス
</summary>
private SpriteBatch spriteBatch = null;
<summary>
スプライトでテキストを描画するためのフォント
</summary>
private SpriteFont font = null;
<summary>
モデル
</summary>
private Model model = null;
<summary>
位置の配列
</summary>
private Vector3[] positions = new Vector3[3];
<summary>
カメラの水平回転角度
</summary>
private float theta = 0.0f;
<summary>
ビューマトリックス
</summary>
private Matrix view = Matrix.Identity;
<summary>
プロジェクションマトリックス
</summary>
private Matrix projection = Matrix.Identity;
<summary>
GameMain コンストラクタ
</summary>
public GameMain()
{
// グラフィックデバイス管理クラスの作成
this.graphics = new GraphicsDeviceManager(this);
// ゲームコンテンツのルートディレクトリを設定
this.Content.RootDirectory = "Content";
#if WINDOWS_PHONE
// Windows Phone のデフォルトのフレームレートは 30 FPS
this.TargetElapsedTime = TimeSpan.FromTicks(333333);
// バックバッファサイズの設定
this.graphics.PreferredBackBufferWidth = 480;
this.graphics.PreferredBackBufferHeight = 800;
// フルスクリーン表示
this.graphics.IsFullScreen = true;
#endif
}
<summary>
ゲームが始まる前の初期化処理を行うメソッド
グラフィック以外のデータの読み込み、コンポーネントの初期化を行う
</summary>
protected override void Initialize()
{
// 位置をランダムに設定
Random rand = new Random();
for (int i = 0; i < this.positions.Length; i++)
{
this.positions[i] =
new Vector3((float)(rand.NextDouble() - 0.5) * 10.0f,
0.0f,
(float)(rand.NextDouble() - 0.5) * 10.0f);
}
// ビューマトリックス
this.view = Matrix.CreateLookAt(new Vector3(0.0f, 10.0f, 20.0f),
Vector3.Zero,
Vector3.Up);
// プロジェクションマトリックス
this.projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45.0f),
(float)this.GraphicsDevice.Viewport.Width /
(float)this.GraphicsDevice.Viewport.Height,
1.0f,
100.0f
);
// コンポーネントの初期化などを行います
base.Initialize();
}
<summary>
ゲームが始まるときに一回だけ呼ばれ
すべてのゲームコンテンツを読み込みます
</summary>
protected override void LoadContent()
{
// テクスチャーを描画するためのスプライトバッチクラスを作成します
this.spriteBatch = new SpriteBatch(this.GraphicsDevice);
// フォントをコンテンツパイプラインから読み込む
this.font = this.Content.Load<SpriteFont>("Font");
// モデルを作成
this.model = this.Content.Load<Model>("Model");
// ライトとプロジェクションはあらかじめ設定しておく
foreach (ModelMesh mesh in this.model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
// デフォルトのライト適用
effect.EnableDefaultLighting();
// プロジェクションマトリックスをあらかじめ設定
effect.Projection = this.projection;
}
}
}
<summary>
ゲームが終了するときに一回だけ呼ばれ
すべてのゲームコンテンツをアンロードします
</summary>
protected override void UnloadContent()
{
// TODO: ContentManager で管理されていないコンテンツを
// ここでアンロードしてください
}
<summary>
描画以外のデータ更新等の処理を行うメソッド
主に入力処理、衝突判定などの物理計算、オーディオの再生など
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Update(GameTime gameTime)
{
// Xbox 360 コントローラ、Windows Phone の BACK ボタンを押したときに
// ゲームを終了させます
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
// カメラの水平角度を自動更新
this.theta = (float)gameTime.TotalGameTime.TotalSeconds / 2.0f;
// 登録された GameComponent を更新する
base.Update(gameTime);
}
<summary>
描画処理を行うメソッド
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Draw(GameTime gameTime)
{
// 画面を指定した色でクリアします
this.GraphicsDevice.Clear(Color.CornflowerBlue);
// Zバッファを有効にする
this.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
// ビューマトリックスに回転を合成算出
Matrix rotatedView = Matrix.CreateRotationY(this.theta) * this.view;
for (int i = 0; i < this.positions.Length; i++)
{
foreach (ModelMesh mesh in this.model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
// ビューマトリックス
effect.View = rotatedView;
// モデルの位置設定
effect.World = Matrix.CreateTranslation(this.positions[i]);
}
// モデルを描画
mesh.Draw();
}
}
// ビューポート取得
Viewport viewport = this.GraphicsDevice.Viewport;
// スプライトの描画準備
this.spriteBatch.Begin();
// 各モデルの位置にテキストを描画
for (int i = 0; i < this.positions.Length; i++)
{
// 3次元座標からスクリーンの座標算出
Vector3 v3 = viewport.Project(this.positions[i],
this.projection,
rotatedView,
Matrix.Identity);
Vector2 screenPosition = new Vector2(v3.X, v3.Y);
// テキスト描画
this.spriteBatch.DrawString(this.font, "Model " + (i + 1).ToString(),
screenPosition, Color.White);
}
// スプライトの一括描画
this.spriteBatch.End();
// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);
}
}
}