عرض المربعات باستخدام مخازن الفهرس المؤقتة

تحديث الصفحة :
تاريخ إنشاء الصفحة :

ملخص

أستخدم الكثير من المضلعات لإنشاء صندوق. عند القيام بذلك ، يتم استخدام مخزن مؤقت للفهرس لتقليل كمية البيانات في بيانات الرأس.

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

بيئة التشغيل

المتطلبات المسبقه

إصدارات XNA المدعومة
  • 4.0
المنصات المدعومة
  • ويندوز (إكس بي SP2 أو في وقت لاحق ، فيستا ، 7)
  • إكس بوكس 360
  • ويندوز فون 7
ويندوز المطلوبة قمة الإصدار شادر 2.0
ويندوز المطلوبة بكسل شادر الإصدار 2.0

بيئة التشغيل

رصيف
  • ويندوز 7
  • إكس بوكس 360
  • ويندوز فون 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 []" ، ولكن يمكن أن يكون أيضا "قصيرا []" (2 بايت). في بعض الحالات ، يتم إنشاء صفيف باستخدام "int" (4 بايت) ، ولكن يتم استخدام هذا عندما يتجاوز عدد الرؤوس "65535". إذا لم يتجاوز عدد الرؤوس هذا الرقم مطلقا ، فقم بإنشاء صفيف من بيانات 2 بايت لتقليل استهلاك الذاكرة.

خلق

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

إنشاء مخازن الرأس. في الأصل ، من الضروري إنشاء 36 رأسا ، ولكن باستخدام مخزن مؤقت للفهرس ، ما عليك سوى إنشاء 8 رؤوس.

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

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

إنشاء مخازن الفهرس. تحدد الوسيطة الثانية عدد بتات مؤشر الرأس المراد كتابته. نظرا لأن فهرس واحد هو 2 بايت ، حدد "IndexElementSize.SixteenBits".

الوسيطة الثالثة هي عدد الفهارس. في هذه الحالة ، سنرسم 12 مضلعا ، لذا حدد 36 ، وهو عدد رؤوس × مضلعات المضلعات الثلاثية. بالطبع ، لا توجد مشكلة إذا حددت عدد العناصر في صفيف الفهرس كما هو ، ولكن هذه المرة يتم فصل الأرقام عن قصد من أجل الوضوح.

نظرا لأننا أنشأنا بالفعل مجموعة من مؤشرات الرأس مع الحقول ، فسنكتبها بطريقة "IndexBuffer.SetData".

IndexBuffer منشئ

إنشاء مثيل من فئة IndexBuffer التي تدير الفهرس الذي يشير إلى بيانات الرأس.

الرسومياتالجهاز الرسومياتالجهاز يحدد GraphicsDevice لربطه بالمخزن المؤقت للفهرس.
indexElementSize إندكس إليمنتسيزي حجم مؤشر قمة واحدة. حدد "SixteenBits" ل 2 بايت ، "ThirtyTwoBits" ل 4 بايت ، وحدد BufferUsage.None.
الفهرسالكونت الباحث يحدد عدد الفهارس.
استخدام التخزين المؤقت استخدام المخزن المؤقت للفهرس. حدد BufferUsage.None ما لم يكن خلاف ذلك.

IndexBuffer.SetData أسلوب

انسخ صفيف مؤشرات الرأس إلى المخزن المؤقت للفهرس.

T نوع القيمة نوع صفيف فهرس قمة الرأس
بيانات T صفيف فهرس قمة الرأس للنسخ

رسم

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

إذا كنت تريد استخدام مخزن مؤقت للفهرس، فقم بتعيين المخزن المؤقت للفهرس على الجهاز قبل رسم المضلع.

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

إذا كنت تستخدم المخازن المؤقتة للفهرس والرأس، استخدم الأسلوب "GraphicsDevice.DrawIndexedPrimitives" لرسم المضلعات.

الوسيطة الرابعة هي عدد الرؤوس التي تم إنشاؤها. في العينة ، يتم تحديد "8" لأنه تتم مشاركة بيانات 8 رؤوس.

تحدد الوسيطة السادسة عدد الأوليات. إنه "12" لأنه يرسم 12 مضلعا مثلثا.

بالنسبة للمعلمات الرقمية الأخرى ، 0 جيد.

GraphicsDevice.DrawIndexedPrimitives أسلوب

يرسم بدائيا بناء على مؤشر الرأس المحدد والمخزن المؤقت للرأس.

النوع البدائي النوع البدائي يحدد البدائية للرسم.
baseVertex الباحث الإزاحة المراد إضافتها إلى كل فهرس قمة في المخزن المؤقت للفهرس. على سبيل المثال، عندما يشير فهرس الرأس الأول إلى بيانات الرأس 2، إذا تم تحديد "1" في هذه الوسيطة، فسيشير فهرس الرأس الأول إلى بيانات الرأس 3.
مينفيرتكس إندكس الباحث الحد الأدنى لمؤشر قمة الرأس المستخدم في المكالمة. على سبيل المثال ، يزيد minVertexIndex من 1 من فهرس بيانات قمة الرأس بمقدار 1 (لا يزيد من عدد المخازن المؤقتة ، لذلك لا يمكن تحديد العنصر الأخير من بيانات الرأس). إذا كان مؤشر الرأس يشير إلى بيانات الرأس الثانية ، فسيشير إلى بيانات الرأس الأولى.
عدد القمم الباحث عدد بيانات قمة الرأس المستخدمة.
ستارت إندكس الباحث إزاحة البداية لمؤشر الرأس. على سبيل المثال، إذا قمت بتحديد TriangleList باعتباره النوع البدائي، حدد "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);
        }
    }
}