Visning af trekantede polygoner

Side opdateret :
Dato for oprettelse af side :

resumé

Den viser trekantede polygoner i 3D-rum.

3角形ポリゴンの表示

Driftsmiljø

Forudsætninger

Understøttede XNA-versioner
  • 4.0
Understøttede platforme
  • Windows (XP SP2 eller nyere, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Windows påkrævet Vertex Shader-version 2.0
Windows påkrævet Pixel Shader-version 2.0

Driftsmiljø

perron
  • Windows 7
  • Xbox 360
  • Windows Phone 7-emulator

stof

Hvad er en polygon?

En polygon er en flade, der genereres af flere toppunktsdefinitioner. Generelt er en polygon en trekantet flade, der består af tre hjørner. Og trigonen er den mindste enhed i polygonen. Nogle modelleringssoftware kan vise polygoner som firkantede eller polygonale, men disse vil til sidst blive nedbrudt til trekantede polygoner.

Modellen, der vises i spil, er dannet ved at kombinere flere af disse trekantede polygoner.

最小単位のポリゴン

Polygoner dannes af hjørner. Hjørner kan have data som position og farve. Denne prøve er også lavet ud fra "position" og "farve" data.

ポリゴンと頂点

Farven på ansigtet i dette eksempel er pænt interpoleret af den farve og afstand, der er indstillet for hvert knudepunkt, men du kan frit ændre den med dit eget shader-program (mere om shader-programmer en anden gang).

Definitioner af toppunktsdata

For at vise en polygon kræves "toppunktsdata", og programmøren skal beslutte, hvilke elementer der skal inkluderes i det toppunkt. Når du tegner en polygon, skal du fortælle enheden, som er tegnemotoren, hvilke toppunktsdata du skal tegne polygonen med. Det gør du ved at oprette klassen "VertexDeclaration" og angive "Vertex Data Definition".

Men fra og med XNA Game Studio 4.0 er denne opsætning blevet forenklet, og du behøver ikke at forberede en VertexDeclaration-klasse for dette tip. (Dette skyldes, at definitionsoplysningerne allerede er indlejret i de vertex-data, der leveres af rammen.)

Data om toppunkter

Jeg skrev, at toppunktsdata er nødvendige for at tegne polygoner, men først skal vi beslutte, hvilken slags data vi vil have. I dette tilfælde bruger vi "position" og "farve" data. Når du har besluttet, hvilke data du vil have, skal du oprette en struktur til at opbevare disse data. Du har en vis frihed til at bestemme, hvad toppunktsdata er, men de almindeligt anvendte toppunktdata er allerede defineret i XNA-rammen, så eksemplet bruger dem.

Knudepunktsdata med "position" og "farve" defineres som en "VertexPositionColor"-struktur. Da der kræves flere hjørner for at danne en polygon, erklærer vi den som et array.

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

effekt

I XNA, når du tegner en polygon, skal du skrive et separat shader-program for at beslutte, hvordan du vil tegne det. For at gøre dette skal du oprette en separat effektfil, skrive et program, indlæse det som en effektklasse og køre shader-programmet.

Men hvis du ikke har brug for at tegne simple trekantede polygoner som denne eller komplekse tegneeffekter, kan det være en meget besværlig opgave.

Af denne grund definerer XNA udvidede effekter, der giver dig mulighed for at indstille de nødvendige elementer som egenskaber, så du ikke behøver at skrive et shader-program til grundlæggende tegning. Det er "BasicEffect"-klassen. Da formålet med denne artikel er at tegne polygoner, vil vi bruge "BasicEffect", der ikke kræver meget indsats at tegne.

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

Jeg vil tale mere om effekter og BasicEffects på et andet tidspunkt.

Windows Phone 7 tillader dig i øvrigt ikke at bruge dine egne effekter, kun dem, der er indbygget i rammer som BasicEffect.

Oprette en toppunktsdatadefinition

Indtil XNA Framework 3.1 skulle du eksplicit oprette dem programmatisk, men fra og med 4.0 er frameworkets indbyggede toppunktsoplysninger allerede inkluderet i toppunktsoplysningerne som "IVertexType.VertexDeclaration", så vi vil bruge det.

Oprettelse af effekter

Opret en BasicEffect-klasse. Angiv egenskaben BasicEffect.VertexColorEnabled til true for at bevare knudepunktsfarverne.

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

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

BasicEffect konstruktør

Opret en forekomst af effektklassen "BasicEffect", der udfører toppunktsfarve, tekstur og belysning ved hjælp af Shader Model 2.0.

apparat Grafikenhed Angiver den GraphicsDevice til oprettelse af effekten

Se matrix og projektionsmatrix

Indstil BasicEffect til en visningsmatrix og en projektionsmatrix. For en konceptuel forklaring af hver af dem, se linkene nedenfor.

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

Hvis du vil generere en visningsmatrix, skal du bruge metoden "Matrix.CreateLookAt".

Det første argument angiver kameraets placering, det andet argument angiver kameraets interessepunkt, og det tredje argument angiver kameraets opadgående retning.

I dette tilfælde er den indstillet til at se på oprindelsen fra positionen (0, 0, 15).

Matrix.CreateLookAt metode

Opret en visningsmatrix.

kameraPosition Vector3 Kameraets position
cameraTarget Vector3 Kamera Interessepunkt
cameraUpVector Vector3 Kameraets opadgående retning

Hvis du vil generere en projektionsmatrix, skal du bruge metoden "Matrix.CreatePerspectiveFieldOfView".

Det første argument er betragtningsvinklen i radianer. I prøven konverteres gradenheden til radian ved hjælp af "MathHelper.ToRadians"-metoden. Du kan finde flere oplysninger om radian og grad under Radian og grad.

Det andet argument angiver højde-bredde-forholdet (højde-bredde-forholdet). Typisk angiver du en værdi for Visningsbredde ÷ Højde. I eksemplet beregnes det ud fra den bredde og højde, der er indstillet for enhedens viewport.

Det tredje argument angiver den fremadrettede fritlægningsposition, og det fjerde argument angiver den bagudrettede fritlægningsposition.

Matrix.CreatePerspectiveFieldOfView metode

Opretter en perspektivprojektionsmatrix baseret på indstillingerne for visningsfeltet.

fieldOfView flyde Betragtningsvinkel. Specificeret i radianenheder.
aspektRatio flyde Billedformat (billedformat). Normalt angiver du en værdi for "Visningsbredde ÷ højde"
nearPlaneDistance flyde Fremad klipposition. Genstande foran denne position tegnes ikke.
farPlaneDistance flyde Bageste clipsposition. Genstande uden for denne position tegnes ikke.

Oprettelse af toppunktsdata

Opret tre knudepunktsdata. Først opretter vi et array og opretter hvert toppunkt.

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

Hvis du vil oprette knudepunktsdata, skal du angive "knudepunktsposition" og "knudepunktsfarve" i konstruktøren af "VertexPositionColor".

VertexPositionColor konstruktør

Opret en forekomst af strukturen "VertexPositionColor" med positions- og farvetoppunktsdata.

position Vector3 Toppunktets position
farve Farve Toppunkt farve

Indstil placeringen af hjørnerne til det område, der kan ses fra kameraet. Indstil også toppunktsarrangementet til at være "med uret (med uret)". Hvis du indstiller den til "mod uret", vil polygonen ikke være synlig. For en forklaring på dette, se Angivelse af fladerne på en polygon, der skal tegnes.

Tegning af polygoner

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

Der er to typer effekter, kaldet "teknikker" og "stier", som du kører selve tegneprogrammet igennem. Da der kan være flere stier i en enkelt effekt, prøver jeg at kalde dem gentagne gange i foreach. I BasicEffect er der dog én teknik og én sti, så du kan angive indekset for stien direkte, men ovenstående beskrivelse vil være renere, fordi du kan erstatte den med andre effekter.

Før du starter selve tegningen, skal du kalde metoden "EffectPass.Apply" for at starte gennemløbet. Ved at kalde denne metode anvendes parametrene for den effekt, der skal bruges denne gang, på grafikenheden.

Når du har startet stien, skal du tegne polygonen med metoden "GraphicsDevice.DrawUserPrimitives".

Det første argument angiver den type primitiv, der skal tegnes. I dette tilfælde vil vi tegne en trekantet polygon, så angiv "PrimitiveType.TriangleList".

Det andet argument angiver de oprettede knudepunktdata.

Det tredje argument angiver det toppunkt, der skal trækkes fra. Normalt er dette 0.

Det fjerde argument angiver antallet af primitiver, der skal tegnes. I dette tilfælde er der kun én trekantet polygon, så angiv 1. Bemærk, at det ikke er antallet af hjørner.

GraphicsDevice.DrawUserPrimitives metode

Tegner primitiver baseret på brugerleverede toppunktdata.

T Ingen grænse Vertex datastrukturer
primitiveType PrimitiveType Den type primitiv, der skal tegnes
vertexData T[] En matrix af toppunktsdata, der skal tegnes
vertexOffset Int Angiv antallet af knudepunktsdata, der skal bruges til tegning
primitiveCount Int Antallet af primitiver, der skal tegnes.

Det var alt for tegneprogrammet. Hvis du rent faktisk kører den, og der vises en trekant, er du færdig.

Alle koder

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