Visualització de polígons triangulars

Pàgina actualitzada :
Data de creació de la pàgina :

resum

Mostra polígons triangulars en l'espai 3D.

3角形ポリゴンの表示

Entorn operatiu

Prerequisits

Versions XNA compatibles
  • 4.0
Plataformes compatibles
  • Windows (XP SP2 o posterior, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Versió del shader de vèrtex necessària per al Windows 2.0
Versió de Pixel Shader necessària per a Windows 2.0

Entorn operatiu

plataforma
  • Windows 7
  • Xbox 360
  • Emulador de Windows Phone 7

substància

Què és un polígon?

Un polígon és una cara generada per múltiples definicions de vèrtexs. En general, un polígon és una cara triangular formada per tres vèrtexs. I el trígon és la unitat més petita del polígon. Alguns programes de modelatge poden mostrar polígons com a quadrilàters o poligonals, però aquests finalment es descompondran en polígons triangulars.

El model que es mostra en els jocs es forma combinant múltiples d'aquests polígons triangulars.

最小単位のポリゴン

Els polígons estan formats per vèrtexs. Els vèrtexs poden tenir dades com la posició i el color. Aquesta mostra també es fa a partir de dades de "posició" i "color".

ポリゴンと頂点

El color de la cara en aquest exemple està perfectament interpolat pel color i la distància establerts per a cada vèrtex, però podeu canviar-lo lliurement amb el vostre propi programa de shader (més sobre els programes de shader en un altre moment).

Definicions de dades de vèrtex

Per mostrar un polígon, es requereixen "dades de vèrtex" i el programador ha de decidir quins elements incloure en aquest vèrtex. Quan dibuixeu un polígon, heu de dir al dispositiu, que és el motor de dibuix, amb quines dades de vèrtex dibuixar el polígon. Per fer-ho, creeu una classe "VertexDeclaration" i establiu la "Definició de dades de vèrtex".

Tanmateix, a partir de l'XNA Game Studio 4.0, aquesta configuració s'ha simplificat i no cal que prepareu una classe VertexDeclaration per a aquest consell. (Això es deu al fet que la informació de la definició ja està incrustada a les dades de vèrtex proporcionades pel marc).

Dades de vèrtex

Vaig escriure que les dades de vèrtex són necessàries per dibuixar polígons, però primer hem de decidir quin tipus de dades volem tenir. En aquest cas, utilitzarem dades de "posició" i "color". Un cop hàgiu decidit quines dades voleu tenir, heu de crear una estructura per contenir aquestes dades. Teniu certa llibertat per decidir quines són les dades de vèrtex, però les dades de vèrtex d'ús comú ja estan definides al marc XNA, de manera que l'exemple les utilitza.

Les dades de vèrtex amb "position" i "color" es defineixen com una estructura "VertexPositionColor". Com que es necessiten diversos vèrtexs per formar un polígon, el declarem com una matriu.

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

efecte

A XNA, quan dibuixeu un polígon, heu d'escriure un programa de shader separat per decidir com dibuixar-lo. Per fer-ho, creeu un fitxer d'efectes separat, escriviu un programa, carregueu-lo com a classe d'efecte i executeu el programa shader.

Tanmateix, si no necessiteu dibuixar polígons triangulars senzills com aquest o efectes de dibuix complexos, pot ser una tasca molt complicada.

Per aquest motiu, XNA defineix efectes estesos que us permeten establir els elements necessaris com a propietats perquè no hàgiu d'escriure un programa de shader per al dibuix bàsic. Aquesta és la classe "BasicEffect". Com que el propòsit d'aquest article és dibuixar polígons, utilitzarem "BasicEffect" que no requereix gaire esforç per dibuixar.

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

Parlaré més sobre efectes i BasicEffects en un altre moment.

Per cert, Windows Phone 7 no us permet utilitzar els vostres propis efectes, només els integrats en marcs com BasicEffect.

Crear una definició de dades de vèrtex

Fins a XNA Framework 3.1, havíeu de crear-los explícitament mitjançant programació, però a partir de la 4.0, la informació de vèrtex integrada del marc ja està inclosa a la informació del vèrtex com a "IVertexType.VertexDeclaration", així que l'utilitzarem.

Creació d'efectes

Creeu una classe BasicEffect. Definiu la propietat BasicEffect.VertexColorEnabled com a true per mantenir els colors dels vèrtexs.

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

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

BasicEffect constructor

Creeu una instància de la classe d'efectes "BasicEffect" que realitzi el color, la textura i la il·luminació dels vèrtexs utilitzant Shader Model 2.0.

dispositiu Dispositius gràfics Especifica el dispositiu gràfic per crear l'efecte

Veure matriu i matriu de projecció

Definiu BasicEffect en una matriu de visualització i una matriu de projecció. Per a una explicació conceptual de cadascun, vegeu els enllaços següents.

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

Per generar una matriu de visualització, utilitzeu el mètode "Matrix.CreateLookAt".

El primer argument especifica la posició de la càmera, el segon argument especifica el punt d'interès de la càmera i el tercer argument especifica la direcció cap amunt de la càmera.

En aquest cas, s'estableix per mirar l'origen des de la posició (0, 0, 15).

Matrix.CreateLookAt mètode

Creeu una matriu de visualització.

càmeraPosició Vector3 Posició de la càmera
càmeraObjectiu Vector3 Punt d'interès de la càmera
càmeraVector amunt Vector3 Direcció ascendent de la càmera

Per generar una matriu de projecció, utilitzeu el mètode "Matrix.CreatePerspectiveFieldOfView".

El primer argument és l'angle de visió en radiants. A la mostra, la unitat de grau es converteix en radià mitjançant el mètode "MathHelper.ToRadians". Per obtenir més informació sobre el radià i el grau, vegeu Radià i grau.

El segon argument especifica la relació d'aspecte (relació d'aspecte). Normalment, especifiqueu un valor per a Amplada ÷ Alçada de la vista. A la mostra, es calcula a partir de l'amplada i l'alçada establertes per a la finestra gràfica del dispositiu.

El tercer argument especifica la posició de retallada cap endavant i el quart argument especifica la posició de retallada cap enrere.

Matrix.CreatePerspectiveFieldOfView mètode

Crea una matriu de projecció en perspectiva basada en la configuració del camp de visualització.

fieldOfView flotar Angle de visió. Especificat en unitats radianes.
aspectRatio flotar Relació d'aspecte (relació d'aspecte). Normalment, especifiqueu un valor per a "Amplada ÷ alçada de la vista"
nearPlaneDistance flotar Posició del clip cap endavant. Els objectes davant d'aquesta posició no es dibuixen.
farPlaneDistance flotar Posició del clip posterior. Els objectes més enllà d'aquesta posició no es dibuixen.

Creació de dades de vèrtex

Creeu tres dades de vèrtex. Primer, crearem una matriu i crearem cada vèrtex.

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

Per crear dades de vèrtex, especifiqueu la "posició del vèrtex" i el "color del vèrtex" al constructor de "VertexPositionColor".

VertexPositionColor constructor

Creeu una instància de l'estructura "VertexPositionColor" amb les dades de vèrtex de posició i color.

posició Vector3 Posició del vèrtex
color Color Color del vèrtex

Establiu la posició dels vèrtexs al rang que es pot veure des de la càmera. A més, establiu la disposició dels vèrtexs en "sentit horari (en sentit horari)". Si l'establiu en sentit "antihorari", el polígon no serà visible. Per a una explicació d'això, vegeu Especificació de les cares d'un polígon a dibuixar.

Dibuix de polígons

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

Hi ha dos tipus d'efectes, anomenats "tècniques" i "camins", a través dels quals executeu el programa de dibuix real. Com que hi pot haver diversos camins en un sol efecte, intento cridar-los repetidament a foreach. Tanmateix, a BasicEffect, hi ha una tècnica i un camí, de manera que podeu especificar l'índex del camí directament, però la descripció anterior serà més neta perquè podeu substituir-la per altres efectes.

Abans d'iniciar el dibuix real, crideu al mètode "EffectPass.Apply" per iniciar la passada. En cridar a aquest mètode, els paràmetres de l'efecte que s'utilitzarà aquesta vegada s'apliquen al dispositiu gràfic.

Un cop hàgiu iniciat el camí, dibuixeu el polígon amb el mètode "GraphicsDevice.DrawUserPrimitives".

El primer argument especifica el tipus de primitiu que s'ha de dibuixar. En aquest cas, dibuixarem un polígon triangular, així que especifiqueu "PrimitiveType.TriangleList".

El segon argument especifica les dades de vèrtex creades.

El tercer argument especifica el vèrtex a dibuixar. Normalment, això és 0.

El quart argument especifica el nombre de primitives a dibuixar. En aquest cas, només hi ha un polígon triangular, així que especifiqueu 1. Tingueu en compte que no és el nombre de vèrtexs.

GraphicsDevice.DrawUserPrimitives mètode

Dibuixa primitives basades en dades de vèrtex proporcionades per l'usuari.

T Sense límit Estructures de dades de vèrtex
primitiveType Tipus primitiu El tipus de primitiu per dibuixar
vertexData T[] Una matriu de dades de vèrtex per dibuixar
vèrtexDesplaçament Int Especifiqueu el nombre de dades de vèrtex que s'utilitzaran per dibuixar
primitiveCount Int El nombre de primitives a dibuixar.

Això és tot per al programa de dibuix. Si realment l'executeu i es mostra un triangle, ja heu acabat.

Tots els codis

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