Wyświetlanie trójkątnych wielokątów

Strona zaktualizowana :
Data utworzenia strony :

streszczenie

Wyświetla trójkątne wielokąty w przestrzeni 3D.

3角形ポリゴンの表示

Środowisko pracy

Warunki wstępne

Obsługiwane wersje XNA
  • 4.0
Obsługiwane platformy
  • Windows (XP SP2 lub nowszy, Vista, 7)
  • Konsola Xbox 360
  • Telefon z systemem Windows Phone 7
Wymagana przez system Windows wersja modułu cieniującego wierzchołki 2.0
Wymagana przez system Windows wersja Pixel Shader 2.0

Środowisko pracy

podest
  • Okna 7
  • Konsola Xbox 360
  • Windows Phone 7 Emulator

substancja

Co to jest wielokąt?

Wielokąt to powierzchnia, która jest generowana przez wiele definicji wierzchołków. Ogólnie rzecz biorąc, wielokąt to trójkątna ściana składająca się z trzech wierzchołków. A trygon jest najmniejszą jednostką wielokąta. Niektóre programy do modelowania mogą wyświetlać wielokąty jako czworokątne lub wielokątne, ale ostatecznie zostaną one rozłożone na trójkątne wielokąty.

Model wyświetlany w grach jest tworzony przez połączenie wielu tych trójkątnych wielokątów.

最小単位のポリゴン

Wielokąty są tworzone przez wierzchołki. Wierzchołki mogą zawierać dane, takie jak położenie i kolor. Ta próbka jest również tworzona na podstawie danych "pozycja" i "kolor".

ポリゴンと頂点

Kolor twarzy w tym przykładzie jest starannie interpolowany przez kolor i odległość ustawione dla każdego wierzchołka, ale można go dowolnie zmieniać za pomocą własnego programu do cieniowania (więcej o programach do cieniowania innym razem).

Definicje danych wierzchołków

Aby wyświetlić wielokąt, wymagane są "dane wierzchołków", a programista musi zdecydować, jakie elementy mają się znaleźć w tym wierzchołku. Podczas rysowania wielokąta należy powiedzieć urządzeniu, które jest silnikiem rysowania, za pomocą jakich danych wierzchołków narysować wielokąt. Aby to zrobić, utwórz klasę "VertexDeclaration" i ustaw "Definicję danych wierzchołków".

Jednak począwszy od XNA Game Studio 4.0, ta konfiguracja została uproszczona i nie musisz przygotowywać klasy VertexDeclaration, aby uzyskać tę wskazówkę. (Dzieje się tak, ponieważ informacje o definicji są już osadzone w danych wierzchołków dostarczonych przez strukturę).

Dane wierzchołków

Napisałem, że dane wierzchołków są wymagane do rysowania wielokątów, ale najpierw musimy zdecydować, jakie dane chcemy mieć. W tym przypadku użyjemy danych "position" i "color". Po podjęciu decyzji, jakie dane chcesz mieć, musisz utworzyć strukturę do przechowywania tych danych. Masz pewną swobodę decydowania, co to są dane wierzchołków, ale powszechnie używane dane wierzchołków są już zdefiniowane w XNA Framework, więc próbka ich używa.

Dane wierzchołków z "position" i "color" są zdefiniowane jako struktura "VertexPositionColor". Ponieważ do utworzenia wielokąta potrzebnych jest wiele wierzchołków, deklarujemy go jako tablicę.

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

efekt

W XNA, kiedy rysujesz wielokąt, musisz napisać osobny program do cieniowania, aby zdecydować, jak go narysować. Aby to zrobić, utwórz osobny plik efektów, napisz program, załaduj go jako klasę efektów i uruchom program cieniujący.

Jeśli jednak nie musisz rysować prostych trójkątnych wielokątów, takich jak ten, ani skomplikowanych efektów rysunkowych, może to być bardzo kłopotliwe zadanie.

Z tego powodu XNA definiuje rozszerzone efekty, które pozwalają ustawić wymagane elementy jako właściwości, dzięki czemu nie trzeba pisać programu cieniującego do podstawowego rysowania. To jest klasa "BasicEffect". Ponieważ celem tego artykułu jest rysowanie wielokątów, użyjemy "BasicEffect", którego narysowanie nie wymaga dużego wysiłku.

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

Więcej o efektach i BasicEffects opowiem innym razem.

Nawiasem mówiąc, Windows Phone 7 nie pozwala na korzystanie z własnych efektów, tylko tych wbudowanych w frameworki takie jak BasicEffect.

Tworzenie definicji danych wierzchołków

Aż do XNA Framework 3.1 trzeba było jawnie tworzyć je programowo, ale począwszy od wersji 4.0, wbudowane informacje o wierzchołkach frameworka są już zawarte w informacjach o wierzchołkach jako "IVertexType.VertexDeclaration", więc będziemy ich używać.

Tworzenie efektów

Utwórz klasę BasicEffect. Ustaw właściwość BasicEffect.VertexColorEnabled na wartość true, aby zachować kolory wierzchołków.

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

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

BasicEffect konstruktor

Utwórz instancję klasy efektów "BasicEffect", która wykonuje kolor, teksturę i oświetlenie wierzchołków przy użyciu Shader Model 2.0.

urządzenie Karta graficznaUrządzenie Określa element GraphicsDevice do tworzenia efektu

Wyświetlanie macierzy i macierzy projekcji

Ustaw właściwość BasicEffect na macierz widoku i macierz projekcji. Aby zapoznać się z koncepcyjnym wyjaśnieniem każdego z nich, skorzystaj z poniższych linków.

// ビューマトリックスをあらかじめ設定 ((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
    );

Aby wygenerować macierz widoku, użyj metody "Matrix.CreateLookAt".

Pierwszy argument określa położenie kamery, drugi argument określa punkt zainteresowania kamery, a trzeci argument określa kierunek kamery w górę.

W tym przypadku jest ustawiony tak, aby patrzeć na początek układu współrzędnych z pozycji (0, 0, 15).

Matrix.CreateLookAt metoda

Utwórz macierz widoków.

cameraPosition (pozycja) kamery (cameraPosition Wektor3 Pozycja kamery
cameraTarget (docelowa kamera) Wektor3 Użyteczne miejsce kamery
kameraWektor w górę Wektor3 Kierunek kamery w górę

Aby wygenerować macierz projekcji, użyj metody "Matrix.CreatePerspectiveFieldOfView".

Pierwszym argumentem jest kąt widzenia w radianach. W przykładzie jednostka stopnia jest konwertowana na radian przy użyciu metody "MathHelper.ToRadians". Aby uzyskać więcej informacji na temat radiana i stopnia, zobacz Radian i stopień.

Drugi argument określa współczynnik proporcji (współczynnik proporcji). Zazwyczaj określa się wartość w polach Szerokość widoku ÷ Wysokość. W przykładzie jest on obliczany na podstawie szerokości i wysokości ustawionych dla rzutni urządzenia.

Trzeci argument określa pozycję przycinania do przodu, a czwarty argument określa pozycję przycinania do tyłu.

Matrix.CreatePerspectiveFieldOfView metoda

Tworzy macierz rzutowania perspektywicznego na podstawie ustawień pola widoku.

fieldOfView (pole) spławik Kąt. Określone w jednostkach radianów.
aspectRatio (współczynnik proporcji) spławik Współczynnik proporcji (współczynnik proporcji). Zwykle określa się wartość "Szerokość ÷ Wysokość widoku"
nearPlaneDistance (w pobliżuPłaszczyzna) spławik Pozycja klipsa do przodu. Obiekty znajdujące się przed tą pozycją nie są rysowane.
dalekoPłaszczyznaOdległość spławik Pozycja tylnego klipsa. Obiekty znajdujące się poza tym położeniem nie są rysowane.

Tworzenie danych wierzchołków

Utwórz trzy dane wierzchołków. Najpierw utworzymy tablicę i utworzymy każdy wierzchołek.

// 頂点データを作成する
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);

Aby utworzyć dane wierzchołków, określ "pozycję wierzchołka" i "kolor wierzchołka" w konstruktorze "VertexPositionColor".

VertexPositionColor konstruktor

Utwórz instancję struktury "VertexPositionColor" z danymi wierzchołka położenia i koloru.

pozycja Wektor3 Pozycja wierzchołka
Kolor Kolor Kolor wierzchołka

Ustaw położenie wierzchołków w zakresie, który jest widoczny z kamery. Ustaw również układ wierzchołków na "zgodnie z ruchem wskazówek zegara (zgodnie z ruchem wskazówek zegara)". Jeśli ustawisz go na "przeciwnie do ruchu wskazówek zegara", wielokąt nie będzie widoczny. Aby uzyskać wyjaśnienie tego problemu, zobacz temat Określanie powierzchni wielokąta do narysowania.

Rysowanie wielokątów

// パスの数だけ繰り替えし描画 (といっても直接作成した 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);

Istnieją dwa typy efektów, zwane "technikami" i "ścieżkami", za pomocą których uruchamia się właściwy program do rysowania. Ponieważ w jednym efekcie może być wiele ścieżek, staram się wywoływać je wielokrotnie w foreach. Jednak w BasicEffect jest jedna technika i jedna ścieżka, więc możesz określić indeks ścieżki bezpośrednio, ale powyższy opis będzie czystszy, ponieważ możesz go zastąpić innymi efektami.

Przed rozpoczęciem właściwego rysowania wywołaj metodę "EffectPass.Apply", aby rozpocząć przebieg. Wywołując tę metodę, parametry efektu, który ma być użyty tym razem, są stosowane do urządzenia graficznego.

Po uruchomieniu ścieżki narysuj wielokąt za pomocą metody "GraphicsDevice.DrawUserPrimitives".

Pierwszy argument określa typ prymitywu, który ma zostać narysowany. W tym przypadku narysujemy trójkątny wielokąt, więc określ "PrimitiveType.TriangleList".

Drugi argument określa utworzone dane wierzchołków.

Trzeci argument określa wierzchołek, z którego ma być rysowany. Zwykle jest to 0.

Czwarty argument określa liczbę prymitywów do narysowania. W tym przypadku istnieje tylko jeden trójkątny wielokąt, więc określ 1. Zauważ, że nie jest to liczba wierzchołków.

GraphicsDevice.DrawUserPrimitives metoda

Rysuje prymitywy na podstawie danych wierzchołków dostarczonych przez użytkownika.

T Bez limitu Struktury danych wierzchołków
pierwotny typ Typ pierwotny Typ prymitywu do narysowania
vertexData (dane wierzchołków) T[] Tablica danych wierzchołków do narysowania
vertexOffset (przesunięcie wierzchołka) Int Określ liczbę danych wierzchołków, które mają być używane do rysowania
primitiveCount (liczba pierwotna) Int Liczba prymitywów do narysowania.

To tyle, jeśli chodzi o program do rysowania. Jeśli faktycznie go uruchomisz i wyświetli się trójkąt, jesteś skończony.

Wszystkie kody

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