Dreieckige Polygone anzeigen

Diese Seite wurde aktualisiert :
Erstellungsdatum der Seite :

Zusammenfassung

Es zeigt dreieckige Polygone im 3D-Raum an.

3角形ポリゴンの表示

Betriebsumgebung

Voraussetzungen

Unterstützte XNA-Versionen
  • 4.0
Unterstützte Plattformen
  • Windows (XP SP2 oder höher, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Erforderliche Vertex-Shader-Version für Windows 2.0
Erforderliche Pixel-Shader-Version für Windows 2.0

Betriebsumgebung

Bahnsteig
  • Windows 7
  • Xbox 360
  • Windows Phone 7-Emulator

Substanz

Was ist ein Polygon?

Ein Polygon ist eine Fläche, die durch mehrere Scheitelpunktdefinitionen generiert wird. Im Allgemeinen ist ein Polygon eine dreieckige Fläche, die aus drei Eckpunkten besteht. Und das Trigon ist die kleinste Einheit des Polygons. Einige Modellierungssoftware kann Polygone als viereckig oder polygonal anzeigen, aber diese werden schließlich in dreieckige Polygone zerlegt.

Das in Spielen angezeigte Modell wird durch die Kombination mehrerer dieser dreieckigen Polygone gebildet.

最小単位のポリゴン

Polygone werden durch Eckpunkte gebildet. Scheitelpunkte können Daten wie Position und Farbe enthalten. Diese Stichprobe wird ebenfalls aus "Positions"- und "Farb"-Daten erstellt.

ポリゴンと頂点

Die Farbe der Fläche in diesem Beispiel wird sauber durch die Farbe und den Abstand interpoliert, die für jeden Scheitelpunkt festgelegt sind, aber Sie können sie mit Ihrem eigenen Shader-Programm frei ändern (mehr zu Shader-Programmen ein anderes Mal).

Definitionen von Vertex-Daten

Um ein Polygon anzuzeigen, sind "Vertex-Daten" erforderlich, und der Programmierer muss entscheiden, welche Elemente in diesen Vertex aufgenommen werden sollen. Beim Zeichnen eines Polygons müssen Sie dem Gerät, das die Zeichen-Engine ist, mitteilen, mit welchen Vertex-Daten das Polygon gezeichnet werden soll. Erstellen Sie dazu eine "VertexDeclaration"-Klasse und setzen Sie die "Vertex Data Definition".

Ab XNA Game Studio 4.0 wurde dieses Setup jedoch vereinfacht, und Sie müssen keine VertexDeclaration-Klasse für diesen Tipp vorbereiten. (Dies liegt daran, dass die Definitionsinformationen bereits in die vom Framework bereitgestellten Vertexdaten eingebettet sind.)

Vertex-Daten

Ich habe geschrieben, dass Vertex-Daten erforderlich sind, um Polygone zu zeichnen, aber zuerst müssen wir entscheiden, welche Art von Daten wir haben möchten. In diesem Fall verwenden wir die Daten "Position" und "Farbe". Sobald Sie sich entschieden haben, welche Daten Sie haben möchten, müssen Sie eine Struktur erstellen, in der diese Daten gespeichert werden. Sie haben eine gewisse Freiheit zu entscheiden, was Vertexdaten sind, aber die häufig verwendeten Vertexdaten sind bereits in XNA Framework definiert, sodass sie im Beispiel verwendet werden.

Vertex-Daten mit "position" und "color" werden als "VertexPositionColor"-Struktur definiert. Da mehrere Eckpunkte benötigt werden, um ein Polygon zu bilden, deklarieren wir es als Array.

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

Effekt

Wenn Sie in XNA ein Polygon zeichnen, müssen Sie ein separates Shader-Programm schreiben, um zu entscheiden, wie es gezeichnet werden soll. Erstellen Sie dazu eine separate Effektdatei, schreiben Sie ein Programm, laden Sie es als Effektklasse und führen Sie das Shaderprogramm aus.

Wenn Sie jedoch keine einfachen dreieckigen Polygone wie dieses oder komplexe Zeicheneffekte zeichnen müssen, kann dies eine sehr umständliche Aufgabe sein.

Aus diesem Grund definiert XNA erweiterte Effekte, mit denen Sie die erforderlichen Elemente als Eigenschaften festlegen können, sodass Sie kein Shaderprogramm für das grundlegende Zeichnen schreiben müssen. Das ist die "BasicEffect"-Klasse. Da der Zweck dieses Artikels darin besteht, Polygone zu zeichnen, werden wir "BasicEffect" verwenden, das nicht viel Aufwand zum Zeichnen erfordert.

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

Ich werde zu einem anderen Zeitpunkt mehr über Effekte und BasicEffects sprechen.

Übrigens: Windows Phone 7 erlaubt es Ihnen nicht, eigene Effekte zu verwenden, sondern nur solche, die in Frameworks wie BasicEffect integriert sind.

Erstellen einer Vertex-Datendefinition

Bis zum XNA Framework 3.1 mussten Sie sie explizit programmgesteuert erstellen, aber ab 4.0 sind die integrierten Vertexinformationen des Frameworks bereits als "IVertexType.VertexDeclaration" in den Vertexinformationen enthalten, sodass wir sie verwenden werden.

Erstellen von Effekten

Erstellen Sie eine BasicEffect-Klasse. Legen Sie die BasicEffect.VertexColorEnabled-Eigenschaft auf true fest, um die Scheitelpunktfarben beizubehalten.

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

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

BasicEffect Konstruktor

Erstellen Sie eine Instanz der Effektklasse "BasicEffect", die mithilfe des Shadermodells 2.0 Scheitelpunktfarbe, Textur und Beleuchtung ausführt.

Gerät Grafikgerät Gibt das GraphicsDevice zum Erstellen des Effekts an

Ansichtsmatrix und Projektionsmatrix

Legen Sie BasicEffect auf eine Ansichtsmatrix und eine Projektionsmatrix fest. Eine konzeptionelle Erläuterung der einzelnen Informationen finden Sie unter den unten stehenden Links.

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

Verwenden Sie zum Generieren einer Ansichtsmatrix die "Matrix.CreateLookAt"-Methode.

Das erste Argument gibt die Position der Kamera an, das zweite Argument gibt den Point of Interest der Kamera an und das dritte Argument gibt die Aufwärtsrichtung der Kamera an.

In diesem Fall ist es so eingestellt, dass der Ursprung von der Position (0, 0, 15) aus betrachtet wird.

Matrix.CreateLookAt Methode

Erstellen Sie eine Ansichtsmatrix.

cameraPosition Vektor3 Kameraposition
cameraZiel Vektor3 Kamera Sehenswürdigkeit
cameraUpVector Vektor3 Aufwärtsrichtung der Kamera

Verwenden Sie zum Generieren einer Projektionsmatrix die "Matrix.CreatePerspectiveFieldOfView"-Methode.

Das erste Argument ist der Betrachtungswinkel im Bogenmaß. In der Stichprobe wird die Gradeinheit mithilfe der Methode "MathHelper.ToRadians" in das Bogenmaß konvertiert. Weitere Informationen zu Bogenmaß und Grad finden Sie unter Bogenmaß und Grad.

Das zweite Argument gibt das Seitenverhältnis (Seitenverhältnis) an. In der Regel geben Sie einen Wert für Ansichtsbreite ÷ -höhe an. Im Beispiel wird sie aus der Breite und Höhe berechnet, die für den Viewport des Geräts festgelegt sind.

Das dritte Argument gibt die Position des Clippens nach vorne an, und das vierte Argument gibt die Position des Clippings nach hinten an.

Matrix.CreatePerspectiveFieldOfView Methode

Erstellt eine perspektivische Projektionsmatrix basierend auf den Einstellungen des Ansichtsfelds.

fieldOfView schweben Betrachtungswinkel. Angegeben in Bogenmaßeinheiten.
AspektVerhältnis schweben Seitenverhältnis (Seitenverhältnis). Normalerweise geben Sie einen Wert für "Ansichtsbreite ÷ -höhe" an
nearPlaneDistance schweben Clip-Position nach vorne. Objekte, die sich vor dieser Position befinden, werden nicht gezeichnet.
farPlaneDistance schweben Position des hinteren Clips. Objekte, die über diese Position hinausgehen, werden nicht gezeichnet.

Erstellen von Vertex-Daten

Erstellen Sie drei Vertex-Daten. Zuerst erstellen wir ein Array und erstellen jeden Scheitelpunkt.

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

Um Vertex-Daten zu erstellen, geben Sie die "Vertex-Position" und die "Vertex-Farbe" im Konstruktor von "VertexPositionColor" an.

VertexPositionColor Konstruktor

Erstellen Sie eine Instanz der Struktur "VertexPositionColor" mit den Positions- und Farbvertexdaten.

Position Vektor3 Position des Scheitelpunkts
Farbe Farbe Vertex-Farbe

Legen Sie die Position der Scheitelpunkte auf den Bereich fest, der von der Kamera aus sichtbar ist. Legen Sie außerdem die Scheitelpunktanordnung auf "im Uhrzeigersinn (Uhrzeigersinn)" fest. Wenn Sie es auf "gegen den Uhrzeigersinn" einstellen, ist das Polygon nicht sichtbar. Eine Erläuterung hierzu finden Sie unter Festlegen der Flächen eines zu zeichnenden Polygons.

Zeichnen von Polygonen

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

Es gibt zwei Arten von Effekten, die als "Techniken" und "Pfade" bezeichnet werden und über die Sie das eigentliche Zeichenprogramm ausführen. Da es mehrere Wege in einem einzigen Effekt geben kann, versuche ich, sie immer wieder im Voraus aufzurufen. In BasicEffect gibt es jedoch eine Technik und einen Pfad, so dass Sie den Index des Pfads direkt angeben können, aber die obige Beschreibung ist sauberer, da Sie sie durch andere Effekte ersetzen können.

Rufen Sie vor dem Starten der eigentlichen Zeichnung die Methode "EffectPass.Apply" auf, um den Durchlauf zu starten. Durch den Aufruf dieser Methode werden die Parameter des Effekts, der diesmal verwendet werden soll, auf das Grafikgerät angewendet.

Nachdem Sie den Pfad gestartet haben, zeichnen Sie das Polygon mit der Methode "GraphicsDevice.DrawUserPrimitives".

Das erste Argument gibt den Typ des zu zeichnenden Grundkörpers an. In diesem Fall zeichnen wir ein dreieckiges Polygon, also geben Sie "PrimitiveType.TriangleList" an.

Das zweite Argument gibt die erstellten Vertexdaten an.

Das dritte Argument gibt den Scheitelpunkt an, aus dem gezeichnet werden soll. Normalerweise ist dies 0.

Das vierte Argument gibt die Anzahl der zu zeichnenden Grundkörper an. In diesem Fall gibt es nur ein dreieckiges Polygon, geben Sie also 1 an. Beachten Sie, dass es sich nicht um die Anzahl der Eckpunkte handelt.

GraphicsDevice.DrawUserPrimitives Methode

Zeichnet Grundkörper basierend auf den vom Benutzer bereitgestellten Scheitelpunktdaten.

T Keine Begrenzung Vertex-Datenstrukturen
primitiver Typ Primitiver Typ Der Typ des zu zeichnenden Grundkörpers
vertex-Daten T[] Ein Array von Vertexdaten, die gezeichnet werden sollen
vertexOffset Int Geben Sie die Anzahl der Scheitelpunktdaten an, die zum Zeichnen verwendet werden sollen
primitiveCount Int Die Anzahl der zu zeichnenden Grundkörper.

Das war's dann auch schon mit dem Zeichenprogramm. Wenn Sie es tatsächlich ausführen und ein Dreieck angezeigt wird, sind Sie fertig.

Alle Codes

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