Prikaz trikotnih mnogokotnikov

Stran posodobljena :
Datum ustvarjanja strani :

Povzetek

Prikazuje trikotne poligone v 3D prostoru.

3角形ポリゴンの表示

Delovno okolje

Predpogoji

Podprte različice XNA
  • 4.0
Podprte platforme
  • Windows (XP SP2 ali novejši, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Zahtevana različica brilnika točk v sistemu Windows 2.0
Windows je zahteval različico Pixel Shader 2.0

Delovno okolje

peron
  • Operacijski sistem Windows 7
  • Xbox 360
  • Windows Phone 7 Emulator

snov

Kaj je mnogokotnik?

Mnogokotnik je obraz, ki ga ustvarijo več definicij točk. Na splošno je mnogokotnik trikotna ploskev, sestavljena iz treh točk. Trigon je najmanjša enota mnogokotnika. Nekatere programske opreme za modeliranje lahko prikažejo poligone kot štirikotne ali poligonalne, vendar se bodo sčasoma razgradili v trikotne mnogokotnike.

Model, prikazan v igrah, je oblikovan z združevanjem več teh trikotnih mnogokotnikov.

最小単位のポリゴン

Poligoni so sestavljeni iz točk. Točke imajo lahko podatke, kot sta položaj in barva. Ta vzorec je narejen tudi iz podatkov o »položaju« in »barvi«.

ポリゴンと頂点

Barva obraza v tem primeru je lepo interpolirana z barvo in razdaljo, ki je nastavljena za vsako točko, vendar jo lahko prosto spremenite z lastnim programom za senčenje (več o programih za senčenje drugič).

Definicije podatkov o točkah

Za prikaz mnogokotnika so potrebni "podatki o točkah" in programer se mora odločiti, katere elemente bo vključil v to točko. Pri risanju mnogokotnika morate napravi, ki je motor za risanje, povedati, s katerimi podatki o točkah naj narišejo mnogokotnik. Če želite to narediti, ustvarite razred »VertexDeclaration« in nastavite »Vertex Data Definition«.

Vendar pa je bila od XNA Game Studio 4.0 ta nastavitev poenostavljena in za ta nasvet vam ni treba pripraviti razreda VertexDeclaration. (To je zato, ker so informacije o definiciji že vgrajene v podatke o točkah, ki jih zagotavlja okvir.)

Podatki o točkah

Napisal sem, da so za risanje mnogokotnikov potrebni podatki o točkah, vendar se moramo najprej odločiti, kakšne podatke želimo imeti. V tem primeru bomo uporabili podatke o "položaju" in "barvi". Ko se odločite, katere podatke želite imeti, morate ustvariti strukturo, ki bo hranila te podatke. Imate nekaj svobode, da se odločite, kateri podatki o točkah so, vendar so pogosto uporabljeni podatki o točkah že definirani v ogrodju XNA, zato jih vzorec uporablja.

Podatki o točkah z »položajem« in »barvo« so opredeljeni kot struktura »VertexPositionColor«. Ker je za oblikovanje mnogokotnika potrebnih več točk, ga deklariramo kot matriko.

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

učinek

V XNA, ko narišete mnogokotnik, morate napisati ločen program za senčenje, da se odločite, kako ga narisati. Če želite to narediti, ustvarite ločeno datoteko z učinki, napišite program, ga naložite kot razred učinkov in zaženite program shaderja.

Če pa vam ni treba narisati preprostih trikotnih poligonov, kot je ta, ali zapletenih risalnih učinkov, je to lahko zelo okorna naloga.

Iz tega razloga XNA definira razširjene učinke, ki vam omogočajo, da zahtevane elemente nastavite kot lastnosti, tako da vam ni treba pisati programa za shader za osnovno risanje. To je razred »BasicEffect«. Ker je namen tega članka risanje poligonov, bomo uporabili "BasicEffect", ki ne zahteva veliko truda za risanje.

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

Več o učinkih in BasicEffects bom govoril drugič.

Mimogrede, Windows Phone 7 vam ne omogoča uporabe lastnih učinkov, samo tistih, ki so vgrajeni v ogrodja, kot je BasicEffect.

Ustvarjanje definicije podatkov o točkah

Do XNA Framework 3.1 ste jih morali izrecno ustvariti programsko, vendar so od 4.0 vgrajene informacije o točkah ogrodja že vključene v informacije o točkah kot »IVertexType.VertexDeclaration«, zato jih bomo uporabili.

Ustvarjanje učinkov

Ustvarite razred BasicEffect. Lastnost BasicEffect.VertexColorEnabled nastavite na true, da ohranite barve točk.

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

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

BasicEffect gradbenik

Ustvarite primerek razreda učinka »BasicEffect«, ki izvaja barvo, teksturo in osvetlitev točk z modelom Shader 2.0.

naprava Grafična naprava Določa grafično napravo za ustvarjanje učinka

Ogled matrike in projekcijske matrike

Nastavite BasicEffect na matriko pogleda in matriko projekcije. Za konceptualno razlago vsakega glej spodnje povezave.

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

Če želite ustvariti matriko pogledov, uporabite metodo »Matrix.CreateLookAt«.

Prvi argument določa položaj kamere, drugi argument določa zanimivo točko kamere, tretji argument pa določa smer kamere navzgor.

V tem primeru je nastavljen tako, da gleda izvor s položaja (0, 0, 15).

Matrix.CreateLookAt metoda

Ustvarite matriko pogledov.

Položaj kamere Vektor3 Položaj kamere
kameraCilj Vektor3 Zanimiva točka kamere
cameraUpVector Vektor3 Smer kamere navzgor

Če želite ustvariti projekcijsko matriko, uporabite metodo »Matrix.CreatePerspectiveFieldOfView«.

Prvi argument je vidni kot v radianih. V vzorcu se enota stopnje pretvori v radian z metodo »MathHelper.ToRadians«. Če želite več informacij o radianu in stopnji, glejte Radian in stopnja.

Drugi argument določa razmerje širine in višine (razmerje širine in višine). Po navadi določite vrednost za Širina pogleda ÷ Višina. V vzorcu se izračuna iz širine in višine, nastavljene za vidno polje naprave.

Tretji argument določa položaj izrezovanja naprej, četrti argument pa položaj izrezovanja nazaj.

Matrix.CreatePerspectiveFieldOfView metoda

Ustvari matriko projekcije perspektive, ki temelji na nastavitvah polja pogleda.

fieldOfView pluti Vidni kot. Določeno v radianskih enotah.
aspectRatio pluti Razmerje stranic (razmerje stranic). Običajno določite vrednost za »Širina pogleda ÷ višina«
nearPlaneDistance pluti Položaj posnetka naprej. Predmeti pred tem položajem niso narisani.
farPlaneDistance pluti Položaj zadnje sponke. Predmeti izven tega položaja niso narisani.

Ustvarjanje podatkov o točkah

Ustvarite tri podatke o točkah. Najprej bomo ustvarili matriko in ustvarili vsako točko.

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

Če želite ustvariti podatke o točkah, določite »položaj točke« in »barvo točke« v konstruktorju »VertexPositionColor«.

VertexPositionColor gradbenik

Ustvarite primerek strukture »VertexPositionColor« s podatki o položaju in barvni točki.

položaj Vektor3 Položaj vrha
barva Barva Barva vrha

Nastavite položaj točk na razpon, ki ga lahko vidite s kamere. Prav tako nastavite razporeditev točk na »v smeri urinega kazalca«. Če ga nastavite na "v nasprotni smeri urinega kazalca", poligon ne bo viden. Za razlago tega glejte Določanje ploskev mnogokotnika za risanje.

Risanje poligonov

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

Obstajata dve vrsti učinkov, imenovani »tehnike« in »poti«, skozi katere zaženete dejanski program za risanje. Ker je v enem učinku lahko več poti, jih poskušam večkrat poklicati. Vendar pa v BasicEffectu obstaja ena tehnika in ena pot, tako da lahko indeks poti določite neposredno, vendar bo zgornji opis čistejši, ker ga lahko nadomestite z drugimi učinki.

Preden začnete z dejanskim risanjem, pokličite metodo »EffectPass.Apply«, da začnete prehod. S klicanjem te metode se parametri učinka, ki ga je treba uporabiti tokrat, uporabijo za grafično napravo.

Ko začnete pot, narišite poligon z metodo »GraphicsDevice.DrawUserPrimitives«.

Prvi argument določa vrsto primitiva, ki ga je treba narisati. V tem primeru bomo narisali trikotni mnogokotnik, zato določite »PrimitiveType.TriangleList«.

Drugi argument določa ustvarjene podatke o točkah.

Tretji argument določa točko, iz katere je treba črpati. Običajno je to 0.

Četrti argument določa število primitivov, ki jih je treba narisati. V tem primeru obstaja samo en trikotni mnogokotnik, zato določite 1. Upoštevajte, da to ni število točk.

GraphicsDevice.DrawUserPrimitives metoda

Nariše primitive na podlagi uporabniških podatkov o točkah.

T Brez omejitev Podatkovne strukture točk
primitivni tip Primitivni tip Vrsta primitiva za risanje
vertexData T[] Matrika podatkov o točkah za risanje
vertexOffset Int Določite število podatkov o točkah, ki bodo uporabljeni za risanje
primitiveCount Int Število primitivov, ki jih je treba narisati.

To je vse za program risanja. Če ga dejansko zaženete in se prikaže trikotnik, ste končali.

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