Εμφάνιση πλαισίων με χρήση buffer ευρετηρίου

Σελίδα ενημέρωση :
Ημερομηνία δημιουργίας σελίδας :

περίληψη

Χρησιμοποιώ πολλά πολύγωνα για να δημιουργήσω ένα κουτί. Με αυτόν τον τρόπο, χρησιμοποιείται ένα buffer ευρετηρίου για τη μείωση της ποσότητας δεδομένων στα δεδομένα κορυφής.

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

Περιβάλλον λειτουργίας

Προϋποθέσεις

Υποστηριζόμενες εκδόσεις XNA
  • 4.0
Υποστηριζόμενες πλατφόρμες
  • Windows (XP SP2 ή νεότερη έκδοση, Vista, 7)
  • Κονσόλα Xbox 360
  • Windows Phone 7
Windows Απαιτούμενη έκδοση σκίασης Vertex 2.0
Απαιτούμενη έκδοση Pixel Shader των Windows 2.0

Περιβάλλον λειτουργίας

πλατφόρμα
  • Τα Windows 7
  • Κονσόλα Xbox 360
  • Εξομοιωτής Windows Phone 7

ουσία

Σχετικά με το κουτί

Το κουτί αποτελείται από έξι όψεις, μία από τις οποίες αποτελείται από δύο τριγωνικά πολύγωνα. Αυτό σημαίνει ότι ο συνολικός αριθμός τριγωνικών πολυγώνων είναι "2×6 = 12". Επιπλέον, δεδομένου ότι το τριγωνικό πολύγωνο έχει τρεις κορυφές, το σύνολο των κορυφών είναι "12×3 = 36". Επομένως, όταν δημιουργείτε μόνο με το "VertexBuffer", είναι δυνατό να το εμφανίσετε ως πλαίσιο εάν αποφασίσετε τις πληροφορίες θέσης έτσι ώστε 36 κομμάτια δεδομένων να έχουν σχήμα κουτιού και να το γράψετε. (24 απαιτούνται για το TriangleStrip)

Αλλά φανταστείτε ένα κουτί. Οι γωνίες του κουτιού είναι 8 κομμάτια. Οκτώ θα πρέπει να είναι αρκετά για πληροφορίες τοποθεσίας. Καθώς ο αριθμός των δεδομένων κορυφής αυξάνεται, ασκεί πίεση στη μνήμη. Για να το μειώσουμε με κάποιο τρόπο, χρησιμοποιούμε το "IndexBuffer".

Χρειάζεστε μόνο 8 πληροφορίες θέσης, αλλά χρειάζεστε πάντα 36 κορυφές για ένα πολύγωνο. Επομένως, ο σκοπός της χρήσης του "IndexBuffer" είναι η κοινή χρήση δεδομένων κορυφής 8.

四角形ポリゴン

αγρός

/// <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枚目のポリゴン
};

Το πεδίο δηλώνεται ως "IndexBuffer", αλλά ένας "πίνακας αριθμών κορυφής" δημιουργείται εκ των προτέρων κάτω από αυτό. Αυτός ο πίνακας δεσμεύει έναν πίνακα για 36 κορυφές, αλλά η έννοια κάθε αριθμού είναι πόσα δεδομένα κορυφής από τα οκτώ δεδομένα κορυφής χρησιμοποιεί κάθε τρίγωνο πολύγωνο. Αν κοιτάξετε προσεκτικά, μπορείτε να δείτε ότι τα δεδομένα μέσα είναι γραμμένα με δείκτη μεταξύ "0 ~ 7". Είναι εύκολο να το δείτε στα σχόλια.

Παρεμπιπτόντως, ο τύπος του πίνακα είναι "Int16[]", αλλά μπορεί επίσης να είναι "short[]" (2 byte). Σε ορισμένες περιπτώσεις, δημιουργείται ένας πίνακας με "int" (4 byte), αλλά αυτό χρησιμοποιείται όταν ο αριθμός των κορυφών υπερβαίνει το "65535". Εάν ο αριθμός των κορυφών δεν υπερβαίνει ποτέ αυτόν τον αριθμό, δημιουργήστε έναν πίνακα δεδομένων 2 byte για να μειώσετε την κατανάλωση μνήμης.

δημιουργία

// 頂点の数
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);

Δημιουργία buffer κορυφής. Αρχικά, είναι απαραίτητο να δημιουργήσετε 36 κορυφές, αλλά χρησιμοποιώντας ένα buffer ευρετηρίου, χρειάζεται μόνο να δημιουργήσετε 8 κορυφές.

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

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

Δημιουργία buffer ευρετηρίου. Το δεύτερο όρισμα καθορίζει τον αριθμό των bit του ευρετηρίου κορυφής που θα γραφτεί. Δεδομένου ότι ένα ευρετήριο είναι 2 byte, καθορίστε "IndexElementSize.SixteenBits".

Το τρίτο όρισμα είναι ο αριθμός των ευρετηρίων. Σε αυτή την περίπτωση, θα σχεδιάσουμε 12 πολύγωνα, οπότε καθορίστε 36, που είναι ο αριθμός των κορυφών × των πολυγώνων των τριγωνικών πολυγώνων. Φυσικά, δεν υπάρχει πρόβλημα εάν καθορίσετε τον αριθμό των στοιχείων στον πίνακα ευρετηρίου ως έχει, αλλά αυτή τη φορά οι αριθμοί διαχωρίζονται σκόπιμα για λόγους σαφήνειας.

Δεδομένου ότι έχουμε ήδη δημιουργήσει μια σειρά δεικτών κορυφής με πεδία, θα τα γράψουμε με τη μέθοδο "IndexBuffer.SetData".

IndexBuffer κατασκευαστής

Δημιουργεί μια παρουσία της κλάσης IndexBuffer που διαχειρίζεται το ευρετήριο που αναφέρεται στα δεδομένα κορυφής.

γραφικάΣυσκευή ΓραφικάΣυσκευή Καθορίζει το GraphicsDevice που θα συσχετιστεί με το buffer ευρετηρίου.
indexElementSize IndexElementSize Το μέγεθος ενός δείκτη κορυφής. Καθορίστε "SixteenBits" για 2 byte, "ThirtyTwoBits" για 4 byte και καθορίστε BufferUsage.None.
indexCount ιντ Καθορίζει τον αριθμό των ευρετηρίων.
χρήση Χρήση buffer Χρήση buffer ευρετηρίου. Καθορίστε BufferUsage.None, εκτός αν υπάρχει διαφορετικά.

IndexBuffer.SetData μέθοδος

Αντιγράψτε τον πίνακα δεικτών κορυφής στο buffer ευρετηρίου.

T Τύπος τιμής Τύπος πίνακα ευρετηρίου κορυφής
δεδομένα T Πίνακας ευρετηρίου κορυφής για αντιγραφή

σχέδιο

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

Εάν θέλετε να χρησιμοποιήσετε ένα buffer ευρετηρίου, ορίστε το buffer ευρετηρίου στη συσκευή πριν σχεδιάσετε το πολύγωνο.

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

Εάν χρησιμοποιείτε buffer ευρετηρίου και κορυφής, χρησιμοποιήστε τη μέθοδο "GraphicsDevice.DrawIndexedPrimitives" για να σχεδιάσετε πολύγωνα.

Το τέταρτο όρισμα είναι ο αριθμός των κορυφών που δημιουργήθηκαν. Στο δείγμα, καθορίζεται το "8" επειδή μοιράζονται δεδομένα κορυφής 8.

Το έκτο όρισμα καθορίζει τον αριθμό των πρωτόγονων. Είναι "12" επειδή σχεδιάζει 12 τριγωνικά πολύγωνα.

Για άλλες αριθμητικές παραμέτρους, το 0 είναι εντάξει.

GraphicsDevice.DrawIndexedPrimitives μέθοδος

Σχεδιάζει ένα πρωτόγονο με βάση τον καθορισμένο δείκτη κορυφής και το buffer κορυφής.

πρωτόγονοςΤύπος Πρωτόγονος τύπος Καθορίζει το πρωτόγονο σχέδιο που θα σχεδιαστεί.
βάσηVertex ιντ Η μετατόπιση που θα προστεθεί σε κάθε δείκτη κορυφής στο buffer ευρετηρίου. Για παράδειγμα, όταν ο πρώτος δείκτης κορυφής οδηγεί σε δεδομένα κορυφής 2, εάν καθορίζεται "1" σε αυτό το όρισμα, ο πρώτος δείκτης κορυφής θα οδηγεί σε δεδομένα κορυφής 3.
minΔείκτης Vertex ιντ Ο ελάχιστος δείκτης κορυφής της κορυφής που χρησιμοποιείται στην κλήση. Για παράδειγμα, ένα minVertexIndex 1 αυξάνει τον δείκτη των δεδομένων κορυφής κατά 1 (δεν αυξάνει τον αριθμό των buffers, επομένως το τελευταίο στοιχείο των δεδομένων κορυφής δεν μπορεί να καθοριστεί). Εάν ο δείκτης κορυφής οδηγεί στα δεδομένα δεύτερης κορυφής, θα υποδεικνύει τα πρώτα δεδομένα κορυφής.
numΚορυφές ιντ Ο αριθμός των δεδομένων κορυφής που χρησιμοποιήθηκαν.
startIndex ιντ Η αρχική μετατόπιση του δείκτη κορυφής. Για παράδειγμα, εάν ορίσετε το TriangleList ως primitiveType, καθορίστε "3, 6, 9,..." για να παραλείψετε τα πολύγωνα που αρχίζουν να σχεδιάζουν. Εάν καθορίσετε μια τιμή διαφορετική από τον αριθμό που διαιρείται με το 3, το μοντέλο θα συμπτυχθεί. (Επειδή όλα τα ευρετήρια είναι απενεργοποιημένα)
πρωτόγονοςΚόμης ιντ Ο αριθμός των πρωτόγονων για να σχεδιάσετε. Η μέγιστη τιμή που μπορεί να καθοριστεί είναι "Αριθμός δεικτών κορυφής÷ Αριθμός κορυφών πρωτόγονων - startIndex"

Όλοι οι κωδικοί

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