Показване на триъгълни многоъгълници

Страницата се актуализира :
Дата на създаване на страница :

резюме

Той показва триъгълни многоъгълници в 3D пространство.

3角形ポリゴンの表示

Работна среда

Предпоставки

Поддържани версии на XNA
  • 4.0
Поддържани платформи
  • Windows (XP SP2 или по-нова версия, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Необходима версия на Vertex Shader за Windows 2.0
Необходима версия на пикселния шейдър за Windows 2.0

Работна среда

платформа
  • Windows 7
  • Xbox 360
  • Емулатор на Windows Phone 7

вещество

Какво е многоъгълник?

Многоъгълникът е лице, което се генерира от множество дефиниции на върхове. Като цяло многоъгълникът е триъгълно лице, състоящо се от три върха. А триъгълникът е най-малката единица от многоъгълника. Някои софтуери за моделиране могат да показват многоъгълници като четириъгълници или многоъгълни, но те в крайна сметка ще бъдат разложени на триъгълни многоъгълници.

Моделът, показан в игрите, се формира чрез комбиниране на множество от тези триъгълни многоъгълници.

最小単位のポリゴン

Многоъгълниците са образувани от върхове. Върховете могат да имат данни като позиция и цвят. Тази проба също е направена от данни за "позиция" и "цвят".

ポリゴンと頂点

Цветът на лицето в този пример е добре интерполиран от цвета и разстоянието, зададени за всеки връх, но можете свободно да го промените със собствена шейдърна програма (повече за шейдърните програми друг път).

Дефиниции на върхови данни

За да се покаже многоъгълник, са необходими "върхови данни" и програмистът трябва да реши какви елементи да включи в този връх. Когато чертаете многоъгълник, трябва да кажете на устройството, което е машината за рисуване, с какви върхове данни да начертае многоъгълника. За да направите това, създайте клас "VertexDeclaration" и задайте "Vertex Data Definition".

Въпреки това, започвайки с XNA Game Studio 4.0, тази настройка е опростена и не е необходимо да подготвяте клас VertexDeclaration за този съвет. (Това е така, защото информацията за дефиницията вече е вградена в данните за върховете, предоставени от рамката.)

Върхови данни

Писах, че данните за върховете са необходими за чертане на многоъгълници, но първо трябва да решим какъв вид данни искаме да имаме. В този случай ще използваме данни за "позиция" и "цвят". След като решите какви данни искате да имате, трябва да създадете структура, която да съхранява тези данни. Имате известна свобода да решите какви са върховите данни, но често използваните данни за върховете вече са дефинирани в XNA Framework, така че извадката ги използва.

Данните за върховете с "позиция" и "цвят" се дефинират като структура "VertexPositionColor". Тъй като за образуването на многоъгълник са необходими множество върхове, ние го декларираме като масив.

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

ефект

В XNA, когато рисувате многоъгълник, трябва да напишете отделна шейдърна програма, за да решите как да го нарисувате. За да направите това, създайте отделен файл с ефекти, напишете програма, заредете я като клас ефекти и стартирайте програмата шейдър.

Въпреки това, ако не е необходимо да рисувате прости триъгълни многоъгълници като този или сложни ефекти на рисуване, това може да бъде много тромава задача.

Поради тази причина XNA дефинира разширени ефекти, които ви позволяват да зададете необходимите елементи като свойства, така че да не се налага да пишете шейдърна програма за основно рисуване. Това е класът "BasicEffect". Тъй като целта на тази статия е да начертаем многоъгълници, ще използваме "BasicEffect", който не изисква много усилия за рисуване.

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

Ще говоря повече за ефектите и BasicEffects друг път.

Между другото, Windows Phone 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 на матрица на изглед и матрица на проекция. За концептуално обяснение на всеки вижте връзките по-долу.

// ビューマトリックスをあらかじめ設定 ((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 метод

Създайте матрица на изгледи.

cameraPosition Вектор3 Позиция на камерата
cameraTarget Вектор3 Интересна точка на камерата
cameraUpVector Вектор3 Посока нагоре на камерата

За да генерирате проекционна матрица, използвайте метода "Matrix.CreatePerspectiveFieldOfView".

Първият аргумент е ъгълът на видимост в радиани. В извадката градусната единица се преобразува в радиан с помощта на метода "MathHelper.ToRadians". За повече информация относно радиана и градуса вижте Радиан и градус.

Вторият аргумент определя съотношението на страните (съотношението). Обикновено задавате стойност за Ширина ÷ височина на изгледа. В извадката се изчислява от ширината и височината, зададени за прозореца за изглед на устройството.

Третият аргумент указва позицията на изрязване напред, а четвъртият аргумент указва позицията на изрязване назад.

Matrix.CreatePerspectiveFieldOfView метод

Създава матрица за прожектиране на перспектива въз основа на настройките на полето за изглед.

fieldOfView плавам Ъгъл на гледане. Зададени в радиански единици.
aspectRatio плавам Съотношение на страните (съотношение). Обикновено задавате стойност за "Ширина ÷ височина на изглед"
nearPlaneDistance плавам Позиция на щипката напред. Обектите пред тази позиция не се рисуват.
farPlaneDistance плавам Позиция на задната скоба. Обекти извън това положение не се рисуват.

Създаване на вертексови данни

Създайте данни за три върха. Първо ще създадем масив и ще създадем всеки връх.

// 頂点データを作成する
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 Без ограничение Върхови структури от данни
primitiveType Примитивен тип Типът примитив за рисуване
vertexData T[] Масив от върхови данни за рисуване
vertexOffset int Задайте броя на данните за върховете, които да се използват за чертане
primitiveCount int Броят на примитивите за рисуване.

Това е всичко за програмата за рисуване. Ако действително го изпълните и се покаже триъгълник, сте готови.

Всички кодове

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