Visualizzazione di poligoni triangolari

Pagina aggiornata :
Data di creazione della pagina :

sommario

Visualizza poligoni triangolari nello spazio 3D.

3角形ポリゴンの表示

Ambiente operativo

Prerequisiti

Versioni XNA supportate
  • 4.0
Piattaforme supportate
  • Windows (XP SP2 o successivo, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Versione Vertex Shader richiesta da Windows 2.0
Versione Pixel Shader richiesta da Windows 2.0

Ambiente operativo

piattaforma
  • finestre 7
  • Xbox 360
  • Emulatore di Windows Phone 7

sostanza

Che cos'è un poligono?

Un poligono è una faccia generata da più definizioni di vertici. In generale, un poligono è una faccia triangolare composta da tre vertici. E il trigono è l'unità più piccola del poligono. Alcuni software di modellazione possono visualizzare i poligoni come quadrilateri o poligonali, ma questi alla fine verranno scomposti in poligoni triangolari.

Il modello visualizzato nei giochi è formato dalla combinazione di più di questi poligoni triangolari.

最小単位のポリゴン

I poligoni sono formati da vertici. I vertici possono contenere dati quali la posizione e il colore. Questo campione è costituito anche da dati di "posizione" e "colore".

ポリゴンと頂点

Il colore del viso in questo esempio è interpolato in modo ordinato dal colore e dalla distanza impostati per ogni vertice, ma puoi cambiarlo liberamente con il tuo programma shader (maggiori informazioni sui programmi shader un'altra volta).

Definizioni dei dati dei vertici

Per visualizzare un poligono, sono necessari "dati di vertice" e il programmatore deve decidere quali elementi includere in quel vertice. Quando si disegna un poligono, è necessario indicare al dispositivo, che è il motore di disegno, con quali dati di vertice disegnare il poligono. A tale scopo, creare una classe "VertexDeclaration" e impostare la "Vertex Data Definition".

Tuttavia, a partire da XNA Game Studio 4.0, questa configurazione è stata semplificata e non è necessario preparare una classe VertexDeclaration per questo suggerimento. Ciò è dovuto al fatto che le informazioni sulla definizione sono già incorporate nei dati dei vertici forniti dal framework.

Dati dei vertici

Ho scritto che i dati dei vertici sono necessari per disegnare i poligoni, ma prima dobbiamo decidere che tipo di dati vogliamo avere. In questo caso, utilizzeremo i dati di "posizione" e "colore". Una volta decisi quali dati si desidera avere, è necessario creare una struttura per conservare tali dati. Si dispone di una certa libertà per decidere quali sono i dati dei vertici, ma i dati dei vertici di uso comune sono già definiti in XNA Framework, quindi l'esempio li utilizza.

I dati dei vertici con "position" e "color" sono definiti come una struttura "VertexPositionColor". Poiché sono necessari più vertici per formare un poligono, lo dichiariamo come un array.

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

effetto

In XNA, quando si disegna un poligono, è necessario scrivere un programma shader separato per decidere come disegnarlo. A tale scopo, creare un file di effetti separato, scrivere un programma, caricarlo come classe di effetti ed eseguire il programma shader.

Tuttavia, se non hai bisogno di disegnare semplici poligoni triangolari come questo o effetti di disegno complessi, può essere un compito molto ingombrante.

Per questo motivo, XNA definisce effetti estesi che consentono di impostare gli elementi necessari come proprietà in modo da non dover scrivere un programma shader per il disegno di base. Questa è la classe "BasicEffect". Poiché lo scopo di questo articolo è disegnare poligoni, utilizzeremo "BasicEffect" che non richiede molto sforzo per disegnare.

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

Parlerò di più degli effetti e dei BasicEffects in un altro momento.

A proposito, Windows Phone 7 non ti consente di utilizzare i tuoi effetti, solo quelli integrati in framework come BasicEffect.

Creare una definizione di dati dei vertici

Fino a XNA Framework 3.1, era necessario crearli in modo esplicito a livello di codice, ma a partire dalla versione 4.0, le informazioni sui vertici incorporate del framework sono già incluse nelle informazioni sui vertici come "IVertexType.VertexDeclaration", quindi verranno utilizzate.

Creazione di effetti

Creare una classe BasicEffect. Impostare la proprietà BasicEffect.VertexColorEnabled su true per mantenere i colori dei vertici.

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

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

BasicEffect costruttore

Creare un'istanza della classe di effetti "BasicEffect" che esegue il colore dei vertici, la trama e l'illuminazione utilizzando il modello shader 2.0.

dispositivo Dispositivo grafico Specifica l'oggetto GraphicsDevice per la creazione dell'effetto

Visualizza matrice e matrice di proiezione

Impostare BasicEffect su una matrice di visualizzazione e una matrice di proiezione. Per una spiegazione concettuale di ciascuno, vedere i link sottostanti.

// ビューマトリックスをあらかじめ設定 ((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 generare una matrice di visualizzazione, utilizzare il metodo "Matrix.CreateLookAt".

Il primo argomento specifica la posizione della fotocamera, il secondo il punto di interesse della fotocamera e il terzo argomento specifica la direzione verso l'alto della fotocamera.

In questo caso, è impostato per guardare l'origine dalla posizione (0, 0, 15).

Matrix.CreateLookAt metodo

Creare una matrice di visualizzazione.

cameraPosition Vettoriale3 Posizione della telecamera
cameraTarget Vettoriale3 Punto di interesse della fotocamera
cameraUpVector Vettoriale3 Direzione verso l'alto della fotocamera

Per generare una matrice di proiezione, utilizzare il metodo "Matrix.CreatePerspectiveFieldOfView".

Il primo argomento è l'angolo di visione in radianti. Nell'esempio, l'unità di grado viene convertita in radiante utilizzando il metodo "MathHelper.ToRadians". Per ulteriori informazioni su Radiante e Grado, vedere Radiante e Grado.

Il secondo argomento specifica le proporzioni (proporzioni). In genere, si specifica un valore per Larghezza vista ÷ Altezza. Nell'esempio, viene calcolato in base alla larghezza e all'altezza impostate per il riquadro di visualizzazione del dispositivo.

Il terzo argomento specifica la posizione di ritaglio in avanti e il quarto argomento specifica la posizione di ritaglio all'indietro.

Matrix.CreatePerspectiveFieldOfView metodo

Crea una matrice di proiezione prospettica in base alle impostazioni del campo visivo.

campoDiVista galleggiare Angolo di visione. Specificato in unità radianti.
aspectRatio galleggiare Proporzioni (proporzioni). Normalmente, si specifica un valore per "Larghezza ÷ altezza della vista"
nearPlaneDistance galleggiare Posizione della clip in avanti. Gli oggetti che si trovano davanti a questa posizione non vengono disegnati.
farPlaneDistance galleggiare Posizione clip posteriore. Gli oggetti oltre questa posizione non vengono disegnati.

Creazione di dati vertice

Creare tre dati dei vertici. Innanzitutto, creeremo un array e creeremo ogni vertice.

// 頂点データを作成する
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 creare i dati dei vertici, specificare la "posizione del vertice" e il "colore del vertice" nel costruttore di "VertexPositionColor".

VertexPositionColor costruttore

Creare un'istanza della struttura "VertexPositionColor" con i dati relativi alla posizione e al colore dei vertici.

posizione Vettoriale3 Posizione vertice
Colore Colore Colore vertice

Impostare la posizione dei vertici sull'intervallo visibile dalla fotocamera. Inoltre, impostare la disposizione dei vertici su "in senso orario (in senso orario)". Se lo imposti su "in senso antiorario", il poligono non sarà visibile. Per una spiegazione di ciò, vedere Specifica delle facce di un poligono da disegnare.

Disegno di poligoni

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

Esistono due tipi di effetti, chiamati "tecniche" e "percorsi", attraverso i quali si esegue il programma di disegno vero e proprio. Poiché possono esserci più percorsi in un singolo effetto, provo a chiamarli ripetutamente in foreach. Tuttavia, in BasicEffect, esiste una tecnica e un percorso, quindi è possibile specificare direttamente l'indice del percorso, ma la descrizione precedente sarà più pulita perché è possibile sostituirla con altri effetti.

Prima di iniziare il disegno vero e proprio, chiamare il metodo "EffectPass.Apply" per avviare il passaggio. Chiamando questo metodo, i parametri dell'effetto da utilizzare questa volta vengono applicati al dispositivo grafico.

Una volta avviato il percorso, disegna il poligono con il metodo "GraphicsDevice.DrawUserPrimitives".

Il primo argomento specifica il tipo di primitiva da disegnare. In questo caso, disegneremo un poligono triangolare, quindi specificare "PrimitiveType.TriangleList".

Il secondo argomento specifica i dati dei vertici creati.

Il terzo argomento specifica il vertice da cui attingere. Normalmente, questo valore è 0.

Il quarto argomento specifica il numero di primitive da disegnare. In questo caso, c'è un solo poligono triangolare, quindi specifica 1. Si noti che non è il numero di vertici.

GraphicsDevice.DrawUserPrimitives metodo

Disegna primitive in base ai dati dei vertici forniti dall'utente.

T Nessun limite Strutture dati dei vertici
primitiveType Tipo primitivo Il tipo di primitiva da disegnare
dati dei vertici T[] Una matrice di dati dei vertici da disegnare
vertexOffset Int Specificare il numero di dati dei vertici da utilizzare per il disegno
primitiveCount Int Numero di primitive da disegnare.

Questo è tutto per il programma di disegno. Se lo esegui effettivamente e viene visualizzato un triangolo, hai finito.

Tutti i codici

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