نمایش چند ضلعی های مثلثی

صفحه به روز شده :
تاریخ ایجاد صفحه :

خلاصه

چند ضلعی های مثلثی را در فضای سه بعدی نمایش می دهد.

3角形ポリゴンの表示

محیط عملیاتی

پیش نیازها

نسخه های XNA پشتیبانی شده
  • 4.0
پلتفرم های پشتیبانی شده
  • ویندوز (XP SP2 یا بالاتر، ویستا، 7)
  • ایکس باکس 360
  • ویندوز فون 7
نسخه Vertex Shader مورد نیاز ویندوز 2.0
ویندوز نسخه Pixel Shader مورد نیاز است 2.0

محیط عملیاتی

بستر
  • ویندوز 7
  • ایکس باکس 360
  • شبیه ساز ویندوز فون 7

ماده

چند ضلعی چیست؟

چند ضلعی چهره ای است که توسط چندین تعاریف راس ایجاد می شود. به طور کلی، چند ضلعی یک وجه مثلثی شکل است که از سه راس تشکیل شده است. و مثلثات کوچکترین واحد چند ضلعی است. برخی از نرم افزارهای مدل سازی ممکن است چند ضلعی ها را به صورت چهار ضلعی یا چند ضلعی نمایش دهند، اما در نهایت به چند ضلعی های مثلثی تجزیه می شوند.

مدل نمایش داده شده در بازی ها با ترکیب چندین مورد از این چند ضلعی مثلثی شکل می گیرد.

最小単位のポリゴン

چند ضلعی ها توسط رئوس تشکیل می شوند. رئوس می توانند داده هایی مانند موقعیت و رنگ داشته باشند. این نمونه همچنین از داده های "موقعیت" و "رنگ" ساخته شده است.

ポリゴンと頂点

رنگ صورت در این مثال به طور منظم توسط رنگ و فاصله تعیین شده برای هر راس درون یابی می شود، اما می توانید آزادانه آن را با برنامه سایه زن خود تغییر دهید (اطلاعات بیشتر در مورد برنامه های سایه زن در زمان دیگر).

تعاریف داده Vertex

برای نمایش یک چند ضلعی، "داده های راس" مورد نیاز است و برنامه نویس باید تصمیم بگیرد که چه عناصری را در آن راس بگنجاند. هنگام ترسیم یک چند ضلعی، باید به دستگاه، که موتور ترسیم است، بگویید که چند ضلعی را با چه داده های راس ترسیم کنید. برای انجام این کار، یک کلاس "VertexDeclaration" ایجاد کنید و "Vertex Data Definition" را تنظیم کنید.

با این حال، با شروع XNA Game Studio 4.0، این راه اندازی ساده شده است و برای این نکته نیازی به آماده سازی کلاس VertexDeclaration ندارید. (این به این دلیل است که اطلاعات تعریف از قبل در داده های راس ارائه شده توسط چارچوب تعبیه شده است.)

داده های راس

من نوشتم که داده های راس برای ترسیم چند ضلعی ها مورد نیاز است، اما ابتدا باید تصمیم بگیریم که چه نوع داده ای را می خواهیم داشته باشیم. در این مورد، ما از داده های "موقعیت" و "رنگ" استفاده خواهیم کرد. هنگامی که تصمیم گرفتید چه داده هایی را می خواهید داشته باشید، باید ساختاری برای نگهداری آن داده ها ایجاد کنید. شما تا حدودی آزادی دارید که تصمیم بگیرید داده راس چیست، اما داده های راس رایج قبلا در چارچوب XNA تعریف شده است، بنابراین نمونه از آن استفاده می کند.

داده های راس با "موقعیت" و "رنگ" به عنوان ساختار "VertexPositionColor" تعریف می شوند. از آنجایی که چندین رأس برای تشکیل یک چند ضلعی مورد نیاز است، آن را به عنوان یک آرایه اعلام می کنیم.

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

اثر

در XNA، هنگامی که یک چند ضلعی می کشید، باید یک برنامه سایه زن جداگانه بنویسید تا تصمیم بگیرید که چگونه آن را ترسیم کنید. برای انجام این کار، یک فایل افکت جداگانه ایجاد کنید، یک برنامه بنویسید، آن را به عنوان یک کلاس افکت بارگذاری کنید و برنامه سایه زن را اجرا کنید.

با این حال، اگر نیازی به ترسیم چند ضلعی مثلثی ساده مانند این یا جلوه های طراحی پیچیده ندارید، می تواند یک کار بسیار دست و پا گیر باشد.

به همین دلیل، XNA افکت های توسعه یافته ای را تعریف می کند که به شما امکان می دهد موارد مورد نیاز را به عنوان ویژگی ها تنظیم کنید تا مجبور نباشید یک برنامه سایه زن برای طراحی اولیه بنویسید. این کلاس "BasicEffect" است. از آنجایی که هدف این مقاله ترسیم چند ضلعی است، از "BasicEffect" استفاده می کنیم که برای ترسیم آن تلاش زیادی نمی کند.

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

در زمان دیگری بیشتر در مورد افکت ها و BasicEffects صحبت خواهم کرد.

به هر حال، ویندوز فون 7 به شما اجازه نمی دهد از جلوه های خود استفاده کنید، فقط آنهایی که در چارچوب هایی مانند BasicEffect تعبیه شده اند.

ایجاد یک تعریف داده راس

تا XNA Framework 3.1، شما باید به صراحت آنها را به صورت برنامه نویسی ایجاد می کردید، اما با شروع با 4.0، اطلاعات راس داخلی چارچوب قبلا در اطلاعات راس به عنوان "IVertexType.VertexDeclaration" گنجانده شده است، بنابراین ما از آن استفاده خواهیم کرد.

ایجاد افکت ها

یک کلاس BasicEffect ایجاد کنید. ویژگی BasicEffect.VertexColorEnabled را روی true تنظیم کنید تا رنگ های راس حفظ شود.

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

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

BasicEffect سازنده

یک نمونه از کلاس افکت "BasicEffect" ایجاد کنید که رنگ، بافت و نورپردازی راس را با استفاده از Shader Model 2.0 انجام می دهد.

دستگاه دستگاه گرافیکی GraphicsDevice را برای ایجاد افکت مشخص می کند

مشاهده ماتریس و ماتریس پروجکشن

BasicEffect را روی یک ماتریس view و یک ماتریس پروجکشن تنظیم کنید. برای توضیح مفهومی هر کدام، به پیوندهای زیر مراجعه کنید.

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

برای ایجاد ماتریس نما، از روش "Matrix.CreateLookAt" استفاده کنید.

آرگومان اول موقعیت دوربین را مشخص می کند، آرگومان دوم نقطه مورد علاقه دوربین را مشخص می کند و آرگومان سوم جهت رو به بالا دوربین را مشخص می کند.

در این حالت ، تنظیم شده است که از موقعیت (0 ، 0 ، 15) به مبدا نگاه کند.

Matrix.CreateLookAt روش

یک ماتریس نما ایجاد کنید.

موقعیت دوربین بردار3 موقعیت دوربین
cameraTarget بردار3 نقطه مورد علاقه دوربین
cameraUpVector بردار3 جهت رو به بالا دوربین

برای ایجاد یک ماتریس پروجکشن، از روش "Matrix.CreatePerspectiveFieldOfView" استفاده کنید.

اولین استدلال زاویه دید در رادیان است. در نمونه، واحد درجه با استفاده از روش "MathHelper.ToRadians" به رادیان تبدیل می شود. برای کسب اطلاعات بیشتر در مورد رادیان و مدرک به رادیان و مدرک مراجعه کنید.

آرگومان دوم نسبت تصویر (نسبت ابعاد) را مشخص می کند. به طور معمول، مقداری را برای View Width ÷ Height تعیین می کنید. در نمونه از عرض و ارتفاع تنظیم شده برای نمای دستگاه محاسبه می شود.

آرگومان سوم موقعیت برش رو به جلو را مشخص می کند و آرگومان چهارم موقعیت برش رو به عقب را مشخص می کند.

Matrix.CreatePerspectiveFieldOfView روش

یک ماتریس طرح پرسپکتیو بر اساس تنظیمات فیلد دید ایجاد می کند.

fieldOfView شناور زاویه دید. مشخص شده در واحدهای رادیان.
نسبت ابعاد شناور نسبت تصویر (نسبت ابعاد). به طور معمول، مقداری را برای "View Width ÷ Height" تعیین می کنید
nearPlaneDistance شناور موقعیت گیره رو به جلو. اشیاء جلوی این موقعیت ترسیم نمی شوند.
farPlaneDistance شناور موقعیت گیره عقب. اشیاء فراتر از این موقعیت ترسیم نمی شوند.

ایجاد داده Vertex

سه داده راس ایجاد کنید. ابتدا یک آرایه ایجاد می کنیم و هر راس را ایجاد می کنیم.

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

برای ایجاد داده های راس، "موقعیت راس" و "رنگ راس" را در سازنده "VertexPositionColor" مشخص کنید.

VertexPositionColor سازنده

یک نمونه از ساختار "VertexPositionColor" با داده های موقعیت و رنگ راس ایجاد کنید.

موقعیت بردار3 موقعیت راس
رنگ رنگ رنگ راس

موقعیت رئوس را روی محدوده ای که از دوربین دیده می شود تنظیم کنید. همچنین، آرایش راس را روی "جهت عقربه های ساعت (در جهت عقربه های ساعت)" تنظیم کنید. اگر آن را روی "خلاف جهت عقربه های ساعت" تنظیم کنید، چند ضلعی قابل مشاهده نخواهد بود. برای توضیح این موضوع، به مشخص کردن چهره های یک چند ضلعی برای ترسیم مراجعه کنید.

ترسیم چند ضلعی ها

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

دو نوع افکت وجود دارد که "تکنیک" و "مسیر" نامیده می شوند که از طریق آنها برنامه طراحی واقعی را اجرا می کنید. از آنجایی که می تواند چندین مسیر در یک افکت وجود داشته باشد، سعی می کنم آنها را بارها و بارها در foreach فراخوانی کنم. با این حال، در BasicEffect، یک تکنیک و یک مسیر وجود دارد، بنابراین می توانید ایندکس مسیر را مستقیما مشخص کنید، اما توضیحات بالا تمیزتر خواهد بود زیرا می توانید آن را جایگزین جلوه های دیگر کنید.

قبل از شروع نقاشی واقعی، روش "EffectPass.Apply" را برای شروع پاس فراخوانی کنید. با فراخوانی این روش ، پارامترهای افکت مورد استفاده این بار به دستگاه گرافیکی اعمال می شود.

هنگامی که مسیر را شروع کردید، چند ضلعی را با روش "GraphicsDevice.DrawUserPrimitives" بکشید.

اولین استدلال نوع ابتدایی را مشخص می کند که باید ترسیم شود. در این حالت ، ما یک چند ضلعی مثلثی ترسیم می کنیم ، بنابراین "PrimitiveType.TriangleList" را مشخص کنید.

آرگومان دوم داده های راس ایجاد شده را مشخص می کند.

آرگومان سوم راس را مشخص می کند که باید از آن ترسیم شود. به طور معمول، این 0 است.

آرگومان چهارم تعداد ابتدایی هایی را که باید ترسیم شود مشخص می کند. در این مورد، فقط یک چند ضلعی مثلثی وجود دارد، بنابراین 1 را مشخص کنید. توجه داشته باشید که تعداد رئوس نیست.

GraphicsDevice.DrawUserPrimitives روش

ترسیم اولیه ها بر اساس داده های راس ارائه شده توسط کاربر.

T بدون محدودیت ساختارهای داده Vertex
نوع ابتدایی نوع اولیه نوع ابتدایی برای ترسیم
vertexData T[] آرایه ای از داده های راس برای ترسیم
راس افست هوشمند تعداد داده های راس مورد استفاده برای ترسیم را مشخص کنید
شمارش ابتدایی هوشمند تعداد ابتدایی ها برای ترسیم.

این برای برنامه طراحی است. اگر واقعا آن را اجرا کنید و یک مثلث نمایش داده شود، کارتان تمام است.

همه کدها

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