Hiển thị đa giác tam giác

Trang Cập Nhật :
Ngày tạo trang :

tóm tắt

Nó hiển thị các đa giác hình tam giác trong không gian 3D.

3角形ポリゴンの表示

Môi trường hoạt động

Điều kiện tiên quyết

Các phiên bản XNA được hỗ trợ
  • 4.0
Nền tảng được hỗ trợ
  • Windows (XP SP2 trở lên, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Phiên bản Vertex Shader bắt buộc của Windows 2.0
Phiên bản Pixel Shader bắt buộc của Windows 2.0

Môi trường hoạt động

nền tảng
  • cửa sổ 7
  • Xbox 360
  • Trình giả lập Windows Phone 7

chất

Đa giác là gì?

Đa giác là một mặt được tạo ra bởi nhiều định nghĩa đỉnh. Nói chung, đa giác là một mặt hình tam giác bao gồm ba đỉnh. Và trigon là đơn vị nhỏ nhất của đa giác. Một số phần mềm mô hình hóa có thể hiển thị đa giác dưới dạng tứ giác hoặc đa giác, nhưng cuối cùng chúng sẽ bị phân tách thành đa giác hình tam giác.

Mô hình hiển thị trong trò chơi được hình thành bằng cách kết hợp nhiều đa giác hình tam giác này.

最小単位のポリゴン

Đa giác được hình thành bởi các đỉnh. Các đỉnh có thể có dữ liệu như vị trí và màu sắc. Mẫu này cũng được làm từ dữ liệu "vị trí" và "màu".

ポリゴンと頂点

Màu sắc của khuôn mặt trong ví dụ này được nội suy gọn gàng bởi màu sắc và khoảng cách được đặt cho mỗi đỉnh, nhưng bạn có thể tự do thay đổi nó bằng chương trình đổ bóng của riêng mình (nhiều hơn về các chương trình đổ bóng vào một thời điểm khác).

Định nghĩa dữ liệu Vertex

Để hiển thị một đa giác, "dữ liệu đỉnh" là bắt buộc và lập trình viên phải quyết định những phần tử nào sẽ bao gồm trong đỉnh đó. Khi vẽ một đa giác, bạn phải cho thiết bị biết, đâu là công cụ vẽ, dữ liệu đỉnh nào để vẽ đa giác. Để thực hiện việc này, hãy tạo một lớp "VertexDeclaration" và đặt "Vertex Data Definition".

Tuy nhiên, bắt đầu với XNA Game Studio 4.0, thiết lập này đã được đơn giản hóa và bạn không cần chuẩn bị lớp VertexDeclaration cho mẹo này. (Điều này là do thông tin định nghĩa đã được nhúng trong dữ liệu đỉnh do khung cung cấp.)

Dữ liệu đỉnh

Tôi đã viết rằng dữ liệu đỉnh là cần thiết để vẽ đa giác, nhưng trước tiên chúng ta phải quyết định loại dữ liệu nào chúng ta muốn có. Trong trường hợp này, chúng tôi sẽ sử dụng dữ liệu "vị trí" và "màu". Khi bạn đã quyết định dữ liệu nào bạn muốn có, bạn cần tạo cấu trúc để giữ dữ liệu đó. Bạn có một số quyền tự do để quyết định dữ liệu đỉnh là gì, nhưng dữ liệu đỉnh thường được sử dụng đã được xác định trong XNA Framework, vì vậy mẫu sử dụng nó.

Dữ liệu đỉnh với "vị trí" và "màu" được định nghĩa là cấu trúc "VertexPositionColor". Vì cần nhiều đỉnh để tạo thành một đa giác, chúng ta khai báo nó dưới dạng một mảng.

/// <summary>
/// 頂点データリスト
/// </summary>
private VertexPositionColor[] vertices = null;

hiệu lực

Trong XNA, khi bạn vẽ một đa giác, bạn phải viết một chương trình đổ bóng riêng biệt để quyết định cách vẽ nó. Để thực hiện việc này, hãy tạo một tệp hiệu ứng riêng biệt, viết chương trình, tải nó dưới dạng lớp hiệu ứng và chạy chương trình đổ bóng.

Tuy nhiên, nếu bạn không cần vẽ các đa giác hình tam giác đơn giản như thế này, hoặc các hiệu ứng vẽ phức tạp, nó có thể là một nhiệm vụ rất cồng kềnh.

Vì lý do này, XNA định nghĩa các hiệu ứng mở rộng cho phép bạn đặt các mục cần thiết làm thuộc tính để bạn không phải viết chương trình đổ bóng cho bản vẽ cơ bản. Đó là lớp "BasicEffect". Vì mục đích của bài viết này là vẽ đa giác, chúng tôi sẽ sử dụng "BasicEffect" mà không mất nhiều công sức để vẽ.

/// <summary>
/// 基本エフェクト
/// </summary>
private BasicEffect basicEffect = null;

Tôi sẽ nói nhiều hơn về hiệu ứng và BasicEffects vào lúc khác.

Nhân tiện, Windows Phone 7 không cho phép bạn sử dụng các hiệu ứng của riêng mình, chỉ những hiệu ứng được tích hợp trong các khung như BasicEffect.

Tạo định nghĩa dữ liệu đỉnh

Cho đến XNA Framework 3.1, bạn phải tạo chúng một cách rõ ràng theo chương trình, nhưng bắt đầu với 4.0, thông tin đỉnh tích hợp của khung đã được bao gồm trong thông tin đỉnh là "IVertexType.VertexDeclaration", vì vậy chúng tôi sẽ sử dụng nó.

Tạo hiệu ứng

Tạo một lớp BasicEffect. Đặt thuộc tính BasicEffect.VertexColorEnabled thành true để giữ màu đỉnh.

// エフェクトを作成
this.basicEffect = new BasicEffect(this.GraphicsDevice);

// エフェクトで頂点カラーを有効にする
this.basicEffect.VertexColorEnabled = true;

BasicEffect Constructor

Tạo một thể hiện của lớp hiệu ứng "BasicEffect" thực hiện màu đỉnh, kết cấu và ánh sáng đỉnh bằng Shader Model 2.0.

thiết bị Đồ họaThiết bị Chỉ định GraphicsDevice để tạo hiệu ứng

Xem Ma trận và Ma trận chiếu

Đặt BasicEffect thành ma trận dạng xem và ma trận chiếu. Để biết giải thích khái niệm về từng loại, hãy xem các liên kết bên dưới.

// ビューマトリックスをあらかじめ設定 ((0, 0, 15) から原点を見る)
this.basicEffect.View = Matrix.CreateLookAt(
        new Vector3(0.0f, 0.0f, 15.0f),
        Vector3.Zero,
        Vector3.Up
    );

// プロジェクションマトリックスをあらかじめ設定
this.basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
        MathHelper.ToRadians(45.0f),
        (float)this.GraphicsDevice.Viewport.Width /
            (float)this.GraphicsDevice.Viewport.Height,
        1.0f,
        100.0f
    );

Để tạo ma trận dạng xem, hãy sử dụng phương thức "Matrix.CreateLookAt".

Đối số đầu tiên chỉ định vị trí của máy ảnh, đối số thứ hai chỉ định điểm quan tâm của máy ảnh và đối số thứ ba chỉ định hướng đi lên của máy ảnh.

Trong trường hợp này, nó được đặt để xem xét nguồn gốc từ vị trí (0, 0, 15).

Matrix.CreateLookAt phương pháp

Tạo ma trận dạng xem.

cameraVị trí Vectơ3 Vị trí máy ảnh
máy ảnhMục tiêu Vectơ3 Điểm quan tâm của máy ảnh
cameraUpVector Vectơ3 Hướng đi lên của máy ảnh

Để tạo ma trận chiếu, hãy sử dụng phương pháp "Matrix.CreatePerspectiveFieldOfView".

Lập luận đầu tiên là góc nhìn trong radian. Trong mẫu, đơn vị độ được chuyển đổi thành radian bằng phương pháp "MathHelper.ToRadians". Để biết thêm thông tin về Radian và Bằng cấp, hãy xem Radian và Bằng cấp.

Đối số thứ hai chỉ định tỷ lệ khung hình (tỷ lệ khung hình). Thông thường, bạn chỉ định một giá trị cho View Width ÷ Height. Trong mẫu, nó được tính từ chiều rộng và chiều cao được đặt cho chế độ xem của thiết bị.

Đối số thứ ba chỉ định vị trí cắt về phía trước và đối số thứ tư chỉ định vị trí cắt ngược.

Matrix.CreatePerspectiveFieldOfView phương pháp

Tạo ma trận chiếu phối cảnh dựa trên cài đặt của trường xem.

lĩnh vựcOfView nổi Góc nhìn. Được chỉ định trong đơn vị radian.
aspectRatio nổi Tỷ lệ khung hình (tỷ lệ khung hình). Thông thường, bạn chỉ định một giá trị cho "View Width ÷ Height"
nearPlaneKhoảng cách nổi Chuyển tiếp vị trí clip. Các đối tượng ở phía trước vị trí này không được vẽ.
xaMáy bayKhoảng cách nổi Vị trí kẹp phía sau. Các đối tượng ngoài vị trí này không được vẽ.

Tạo dữ liệu Vertex

Tạo dữ liệu ba đỉnh. Đầu tiên, chúng ta sẽ tạo một mảng và tạo từng đỉnh.

// 頂点データを作成する
this.vertices = new VertexPositionColor[3];

this.vertices[0] = new VertexPositionColor(new Vector3(0.0f, 3.0f, 0.0f),
                                           Color.Red);
this.vertices[1] = new VertexPositionColor(new Vector3(3.0f, -2.0f, 0.0f),
                                           Color.Blue);
this.vertices[2] = new VertexPositionColor(new Vector3(-3.0f, -2.0f, 0.0f),
                                           Color.Green);

Để tạo dữ liệu đỉnh, chỉ định "vị trí đỉnh" và "màu đỉnh" trong hàm tạo của "VertexPositionColor".

VertexPositionColor Constructor

Tạo một thể hiện của cấu trúc "VertexPositionColor" với dữ liệu đỉnh vị trí và màu.

vị trí Vectơ3 Vị trí đỉnh
màu Màu Màu đỉnh

Đặt vị trí của các đỉnh thành phạm vi có thể nhìn thấy từ máy ảnh. Ngoài ra, đặt sắp xếp đỉnh là "theo chiều kim đồng hồ (theo chiều kim đồng hồ)". Nếu bạn đặt nó thành "ngược chiều kim đồng hồ", đa giác sẽ không hiển thị. Để có lời giải thích về điều này, hãy xem Chỉ định các mặt của đa giác để vẽ.

Vẽ đa giác

// パスの数だけ繰り替えし描画 (といっても直接作成した BasicEffect は通常1回)
foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
{
    // パスの開始
    pass.Apply();

    // ポリゴンを描画する
    this.GraphicsDevice.DrawUserPrimitives(
        PrimitiveType.TriangleList,
        this.vertices,
        0,
        1
    );
}

// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);

Có hai loại hiệu ứng, được gọi là "kỹ thuật" và "đường dẫn", qua đó bạn chạy chương trình vẽ thực tế. Vì có thể có nhiều đường dẫn trong một hiệu ứng duy nhất, tôi cố gắng gọi chúng nhiều lần trong foreach. Tuy nhiên, trong BasicEffect, có một kỹ thuật và một đường dẫn, vì vậy bạn có thể chỉ định chỉ mục của đường dẫn trực tiếp, nhưng mô tả ở trên sẽ sạch hơn vì bạn có thể thay thế nó bằng các hiệu ứng khác.

Trước khi bắt đầu bản vẽ thực tế, hãy gọi phương thức "EffectPass.Apply" để bắt đầu vượt qua. Bằng cách gọi phương pháp này, các tham số của hiệu ứng được sử dụng lần này được áp dụng cho thiết bị đồ họa.

Khi bạn đã bắt đầu đường dẫn, hãy vẽ đa giác bằng phương thức "GraphicsDevice.DrawUserPrimitives".

Đối số đầu tiên chỉ định loại nguyên thủy sẽ được vẽ. Trong trường hợp này, chúng tôi sẽ vẽ một đa giác hình tam giác, vì vậy hãy chỉ định "PrimitiveType.TriangleList".

Đối số thứ hai chỉ định dữ liệu đỉnh đã tạo.

Đối số thứ ba chỉ định đỉnh để rút ra. Thông thường, đây là 0.

Đối số thứ tư chỉ định số lượng nguyên thủy để vẽ. Trong trường hợp này, chỉ có một đa giác hình tam giác, vì vậy hãy chỉ định 1. Lưu ý rằng nó không phải là số đỉnh.

GraphicsDevice.DrawUserPrimitives phương pháp

Vẽ nguyên thủy dựa trên dữ liệu đỉnh do người dùng cung cấp.

T Không giới hạn Cấu trúc dữ liệu đỉnh
nguyên thủyLoại PrimitiveType Các loại nguyên thủy để vẽ
vertexData T[] Một mảng dữ liệu đỉnh để vẽ
đỉnhBù đắp Int Chỉ định số lượng dữ liệu đỉnh sẽ được sử dụng để vẽ
nguyên thủyBá tước Int Số lượng nguyên thủy để vẽ.

Đó là nó cho chương trình vẽ. Nếu bạn thực sự chạy nó và một hình tam giác được hiển thị, bạn đã hoàn tất.

Tất cả các mã

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 DrawTriangle
{
    /// <summary>
    /// ゲームメインクラス
    /// </summary>
    public class GameMain : Microsoft.Xna.Framework.Game
    {
        /// <summary>
        /// グラフィックデバイス管理クラス
        /// </summary>
        private GraphicsDeviceManager graphics = null;

        /// <summary>
        /// スプライトのバッチ化クラス
        /// </summary>
        private SpriteBatch spriteBatch = null;

        /// <summary>
        /// 頂点データリスト
        /// </summary>
        private VertexPositionColor[] vertices = null;

        /// <summary>
        /// 基本エフェクト
        /// </summary>
        private BasicEffect basicEffect = null;


        /// <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()
        {
            // TODO: ここに初期化ロジックを書いてください

            // コンポーネントの初期化などを行います
            base.Initialize();
        }

        /// <summary>
        /// ゲームが始まるときに一回だけ呼ばれ
        /// すべてのゲームコンテンツを読み込みます
        /// </summary>
        protected override void LoadContent()
        {
            // テクスチャーを描画するためのスプライトバッチクラスを作成します
            this.spriteBatch = new SpriteBatch(this.GraphicsDevice);

            // エフェクトを作成
            this.basicEffect = new BasicEffect(this.GraphicsDevice);

            // エフェクトで頂点カラーを有効にする
            this.basicEffect.VertexColorEnabled = true;

            // ビューマトリックスをあらかじめ設定 ((0, 0, 15) から原点を見る)
            this.basicEffect.View = Matrix.CreateLookAt(
                    new Vector3(0.0f, 0.0f, 15.0f),
                    Vector3.Zero,
                    Vector3.Up
                );

            // プロジェクションマトリックスをあらかじめ設定
            this.basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.ToRadians(45.0f),
                    (float)this.GraphicsDevice.Viewport.Width /
                        (float)this.GraphicsDevice.Viewport.Height,
                    1.0f,
                    100.0f
                );

            // 頂点データを作成する
            this.vertices = new VertexPositionColor[3];

            this.vertices[0] = new VertexPositionColor(new Vector3(0.0f, 3.0f, 0.0f),
                                                       Color.Red);
            this.vertices[1] = new VertexPositionColor(new Vector3(3.0f, -2.0f, 0.0f),
                                                       Color.Blue);
            this.vertices[2] = new VertexPositionColor(new Vector3(-3.0f, -2.0f, 0.0f),
                                                       Color.Green);
        }

        /// <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();
            }

            // TODO: ここに更新処理を記述してください

            // 登録された GameComponent を更新する
            base.Update(gameTime);
        }

        /// <summary>
        /// 描画処理を行うメソッド
        /// </summary>
        /// <param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
        protected override void Draw(GameTime gameTime)
        {
            // 画面を指定した色でクリアします
            this.GraphicsDevice.Clear(Color.CornflowerBlue);

            // パスの数だけ繰り替えし描画 (といっても直接作成した BasicEffect は通常1回)
            foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
            {
                // パスの開始
                pass.Apply();

                // ポリゴンを描画する
                this.GraphicsDevice.DrawUserPrimitives(
                    PrimitiveType.TriangleList,
                    this.vertices,
                    0,
                    1
                );
            }

            // 登録された DrawableGameComponent を描画する
            base.Draw(gameTime);
        }
    }
}