Prikaz polj z medpomnilniki indeksa

Stran posodobljena :
Datum ustvarjanja strani :

Povzetek

Za ustvarjanje škatle uporabljam veliko poligonov. Pri tem se indeksni medpomnilnik uporablja za zmanjšanje količine podatkov v podatkih točke.

インデックスバッファを使用したボックスの表示

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

O škatli

Škatla je sestavljena iz šestih ploskev, od katerih je ena sestavljena iz dveh trikotnih mnogokotnikov. To pomeni, da je skupno število trikotnih mnogokotnikov "2×6 = 12". Poleg tega, ker ima trikotni mnogokotnik tri točke, je vsota točk "12×3 = 36". Zato je pri ustvarjanju samo z »VertexBuffer« mogoče prikazati kot polje, če se odločite za informacije o položaju tako, da je 36 podatkov v obliki polja in ga napišete. (24 jih je potrebnih za TriangleStrip)

Ampak predstavljajte si škatlo. Vogali škatle so 8 kosov. Osem bi moralo biti dovolj za informacije o lokaciji. Ker se število podatkov o točkah povečuje, pritiska na pomnilnik. Da bi to nekako zmanjšali, uporabljamo "IndexBuffer".

Potrebujete samo 8 informacij o položaju, vendar vedno potrebujete 36 točk za mnogokotnik. Zato je namen uporabe »IndexBuffer« skupna raba 8 podatkov o točkah.

四角形ポリゴン

polje

/// <summary>
/// インデックスバッファ
/// </summary>
private IndexBuffer indexBuffer = null;

/// <summary>
/// インデックスバッファの各頂点番号配列
/// </summary>
private static readonly Int16[] vertexIndices = new Int16[] {
    2, 0, 1, // 1枚目のポリゴン
    1, 3, 2, // 2枚目のポリゴン
    4, 0, 2, // 3枚目のポリゴン
    2, 6, 4, // 4枚目のポリゴン
    5, 1, 0, // 5枚目のポリゴン
    0, 4, 5, // 6枚目のポリゴン
    7, 3, 1, // 7枚目のポリゴン
    1, 5, 7, // 8枚目のポリゴン
    6, 2, 3, // 9枚目のポリゴン
    3, 7, 6, // 10枚目のポリゴン
    4, 6, 7, // 11枚目のポリゴン
    7, 5, 4  // 12枚目のポリゴン
};

Polje je deklarirano kot »IndexBuffer«, vendar je pod njim vnaprej ustvarjena »polja številk točk«. Ta matrika rezervira matriko za 36 točk, vendar je pomen vsakega števila število podatkov o točkah osmih točk, ki jih uporablja vsak trikotnik. Če natančno pogledate, lahko vidite, da so podatki v notranjosti zapisani z indeksom med "0 ~ 7". To je enostavno videti v komentarjih.

Mimogrede, vrsta matrike je »Int16 []«, lahko pa je tudi »kratka []« (2 bajta). V nekaterih primerih je matrika ustvarjena z »int« (4 bajti), vendar se to uporabi, ko število točk presega »65535«. Če število točk nikoli ne preseže tega števila, ustvarite matriko 2-bajtnih podatkov, da zmanjšate porabo pomnilnika.

ustvarjanje

// 頂点の数
int vertexCount = 8;

// 頂点バッファ作成
this.vertexBuffer = new VertexBuffer(this.GraphicsDevice,
    typeof(VertexPositionColor), vertexCount, BufferUsage.None);

// 頂点データを作成する
VertexPositionColor[] vertives = new VertexPositionColor[vertexCount];

vertives[0] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, -2.0f), Color.Yellow);
vertives[1] = new VertexPositionColor(new Vector3(2.0f, 2.0f, -2.0f), Color.Gray);
vertives[2] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, 2.0f), Color.Purple);
vertives[3] = new VertexPositionColor(new Vector3(2.0f, 2.0f, 2.0f), Color.Red);
vertives[4] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, -2.0f), Color.SkyBlue);
vertives[5] = new VertexPositionColor(new Vector3(2.0f, -2.0f, -2.0f), Color.Orange);
vertives[6] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, 2.0f), Color.Green);
vertives[7] = new VertexPositionColor(new Vector3(2.0f, -2.0f, 2.0f), Color.Blue);

// 頂点データを頂点バッファに書き込む
this.vertexBuffer.SetData(vertives);

Ustvarjanje medpomnilnikov točk. Prvotno je bilo potrebno ustvariti 36 točk, vendar z uporabo indeksnega medpomnilnika morate ustvariti le 8 točk.

// インデックスバッファを作成
this.indexBuffer = new IndexBuffer(this.GraphicsDevice,
    IndexElementSize.SixteenBits, 3 * 12, BufferUsage.None);

// 頂点インデックスを書き込む
this.indexBuffer.SetData(vertexIndices);

Ustvarjanje indeksnih medpomnilnikov. Drugi argument določa število bitov indeksa točk, ki jih je treba zapisati. Ker je en indeks 2 bajta, določite »IndexElementSize.SixteenBits«.

Tretji argument je število indeksov. V tem primeru bomo narisali 12 poligonov, zato določite 36, kar je število točk × poligonov trikotnih mnogokotnikov. Seveda ni težav, če določite število elementov v indeksni matriki, kot je, toda tokrat so številke namerno ločene zaradi jasnosti.

Ker smo že ustvarili niz indeksov točk s polji, jih bomo napisali z metodo »IndexBuffer.SetData«.

IndexBuffer gradbenik

Ustvari primerek razreda IndexBuffer, ki upravlja indeks, ki se sklicuje na podatke točk.

grafikaNaprava Grafična naprava Določa GraphicsDevice, ki ga je treba povezati z medpomnilnikom indeksa.
indexElementSize Velikost elementa indeksa Velikost indeksa ene točke. Določite »SixteenBits« za 2 bajta, »ThirtyTwoBits« za 4 bajte in določite BufferUsage.None.
Število indeksov Int Določa število kazal.
navada Uporaba medpomnilnika Uporaba medpomnilnika indeksa. Določite BufferUsage.None, razen če ni drugače.

IndexBuffer.SetData metoda

Kopirajte matriko indeksov točk v medpomnilnik indeksa.

T Vrsta vrednosti Vrsta polja indeksa točk
podatki T Indeksna matrika točk za kopiranje

risba

// インデックスバッファをセット
this.GraphicsDevice.Indices = this.indexBuffer;

Če želite uporabiti indeksni medpomnilnik, nastavite indeksni medpomnilnik v napravi, preden narišete mnogokotnik.

// インデックスを使用してポリゴンを描画する
this.GraphicsDevice.DrawIndexedPrimitives(
    PrimitiveType.TriangleList,
    0,
    0,
    8,
    0,
    12
);

Če uporabljate medpomnilnike indeksa in vrhov, uporabite metodo »GraphicsDevice.DrawIndexedPrimitives« za risanje mnogokotnikov.

Četrti argument je število ustvarjenih točk. V vzorcu je »8« določeno, ker je v skupni rabi 8 podatkov o točkah.

Šesti argument določa število primitivov. To je "12", ker nariše 12 trikotnih mnogokotnikov.

Za druge številske parametre je 0 v redu.

GraphicsDevice.DrawIndexedPrimitives metoda

Nariše primitiv na podlagi določenega indeksa točk in medpomnilnika točk.

primitivni tip Primitivni tip Določa primitiv za risanje.
baseVertex Int Odmik, ki se doda vsakemu indeksu točk v medpomnilniku indeksa. Če je na primer prvi indeks točk kaže na podatke o točkah 2, če je v tem argumentu določeno »1«, bo prvi indeks točk kazal na podatke o točkah 3.
minVertexIndeks Int Najmanjši indeks točk točke, uporabljene v klicu. Na primer, minVertexIndex 1 poveča indeks podatkov o točkah za 1 (ne poveča števila medpomnilnikov, zato zadnjega elementa podatkov o točkah ni mogoče določiti). Če indeks točk kaže na podatke o drugi točki, bo kazal na podatke o prvi točki.
numVertices Int Število uporabljenih podatkov o točkah.
začetni indeks Int Začetni odmik indeksa točke. Če na primer določite TriangleList kot primitiveType, določite »3, 6, 9,...«, da preskočite mnogokotnike, ki začnejo risati. Če določite vrednost, ki ni število, deljeno s 3, se bo model strnil. (Ker so vsi indeksi izklopljeni)
primitiveCount Int Število primitivov, ki jih je treba narisati. Največja vrednost, ki jo je mogoče določiti, je »Število indeksov točk÷ Število točk primitivov - startIndex«

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

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

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

        /// <summary>
        /// 頂点バッファ
        /// </summary>
        private VertexBuffer vertexBuffer = null;

        /// <summary>
        /// インデックスバッファ
        /// </summary>
        private IndexBuffer indexBuffer = null;

        /// <summary>
        /// インデックスバッファの各頂点番号配列
        /// </summary>
        private static readonly Int16[] vertexIndices = new Int16[] {
            2, 0, 1, // 1枚目のポリゴン
            1, 3, 2, // 2枚目のポリゴン
            4, 0, 2, // 3枚目のポリゴン
            2, 6, 4, // 4枚目のポリゴン
            5, 1, 0, // 5枚目のポリゴン
            0, 4, 5, // 6枚目のポリゴン
            7, 3, 1, // 7枚目のポリゴン
            1, 5, 7, // 8枚目のポリゴン
            6, 2, 3, // 9枚目のポリゴン
            3, 7, 6, // 10枚目のポリゴン
            4, 6, 7, // 11枚目のポリゴン
            7, 5, 4  // 12枚目のポリゴン
        };


        /// <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;

            // ビューマトリックスをあらかじめ設定 ((10, 10, 10) から原点を見る)
            this.basicEffect.View = Matrix.CreateLookAt(
                    new Vector3(10.0f, 10.0f, 10.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
                );

            // 頂点の数
            int vertexCount = 8;

            // 頂点バッファ作成
            this.vertexBuffer = new VertexBuffer(this.GraphicsDevice,
                typeof(VertexPositionColor), vertexCount, BufferUsage.None);

            // 頂点データを作成する
            VertexPositionColor[] vertives = new VertexPositionColor[vertexCount];

            vertives[0] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, -2.0f), Color.Yellow);
            vertives[1] = new VertexPositionColor(new Vector3(2.0f, 2.0f, -2.0f), Color.Gray);
            vertives[2] = new VertexPositionColor(new Vector3(-2.0f, 2.0f, 2.0f), Color.Purple);
            vertives[3] = new VertexPositionColor(new Vector3(2.0f, 2.0f, 2.0f), Color.Red);
            vertives[4] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, -2.0f), Color.SkyBlue);
            vertives[5] = new VertexPositionColor(new Vector3(2.0f, -2.0f, -2.0f), Color.Orange);
            vertives[6] = new VertexPositionColor(new Vector3(-2.0f, -2.0f, 2.0f), Color.Green);
            vertives[7] = new VertexPositionColor(new Vector3(2.0f, -2.0f, 2.0f), Color.Blue);

            // 頂点データを頂点バッファに書き込む
            this.vertexBuffer.SetData(vertives);

            // インデックスバッファを作成
            this.indexBuffer = new IndexBuffer(this.GraphicsDevice,
                IndexElementSize.SixteenBits, 3 * 12, BufferUsage.None);

            // 頂点インデックスを書き込む
            this.indexBuffer.SetData(vertexIndices);
        }

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

            // 描画に使用する頂点バッファをセット
            this.GraphicsDevice.SetVertexBuffer(this.vertexBuffer);

            // インデックスバッファをセット
            this.GraphicsDevice.Indices = this.indexBuffer;

            // パスの数だけ繰り替えし描画 (といっても BasicEffect は通常1回)
            foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
            {
                // パスの開始
                pass.Apply();
                
                // インデックスを使用してポリゴンを描画する
                this.GraphicsDevice.DrawIndexedPrimitives(
                    PrimitiveType.TriangleList,
                    0,
                    0,
                    8,
                    0,
                    12
                );
            }

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