Exibindo polígonos triangulares

Página atualizada :
Data de criação de página :

resumo

Ele exibe polígonos triangulares no espaço 3D.

3角形ポリゴンの表示

Ambiente operacional

Pré-requisitos

Versões do XNA suportadas
  • 4.0
Plataformas suportadas
  • Windows (XP SP2 ou posterior, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Versão do sombreador de vértice necessária para Windows 2.0
Versão do sombreador de pixel necessária para Windows 2.0

Ambiente operacional

plataforma
  • janelas 7
  • Xbox 360
  • Emulador do Windows Phone 7

substância

O que é um polígono?

Um polígono é uma face gerada por várias definições de vértice. Em geral, um polígono é uma face triangular que consiste em três vértices. E o trígono é a menor unidade do polígono. Alguns softwares de modelagem podem exibir polígonos como quadriláteros ou poligonais, mas estes serão eventualmente decompostos em polígonos triangulares.

O modelo exibido nos jogos é formado pela combinação de vários desses polígonos triangulares.

最小単位のポリゴン

Os polígonos são formados por vértices. Os vértices podem ter dados como posição e cor. Este exemplo também é feito de dados de "posição" e "cor".

ポリゴンと頂点

A cor da face neste exemplo é perfeitamente interpolada pela cor e distância definidas para cada vértice, mas você pode alterá-la livremente com seu próprio programa de sombreador (mais sobre programas de sombreador em outro momento).

Definições de dados de vértice

Para exibir um polígono, são necessários "dados de vértice" e o programador deve decidir quais elementos incluir nesse vértice. Ao desenhar um polígono, você deve informar ao dispositivo, que é o mecanismo de desenho, com quais dados de vértice desenhar o polígono. Para fazer isso, crie uma classe "VertexDeclaration" e defina a "Definição de dados de vértice".

No entanto, a partir do XNA Game Studio 4.0, essa configuração foi simplificada e você não precisa preparar uma classe VertexDeclaration para esta dica. (Isso ocorre porque as informações de definição já estão inseridas nos dados de vértice fornecidos pela estrutura.)

Dados de vértice

Escrevi que os dados de vértice são necessários para desenhar polígonos, mas primeiro temos que decidir que tipo de dados queremos ter. Nesse caso, usaremos dados de "posição" e "cor". Depois de decidir quais dados deseja ter, você precisa criar uma estrutura para armazenar esses dados. Você tem alguma liberdade para decidir o que são dados de vértice, mas os dados de vértice comumente usados já estão definidos no XNA Framework, portanto, o exemplo os usa.

Os dados de vértice com "position" e "color" são definidos como uma estrutura "VertexPositionColor". Como vários vértices são necessários para formar um polígono, nós o declaramos como uma matriz.

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

efeito

No XNA, quando você desenha um polígono, você precisa escrever um programa de sombreamento separado para decidir como desenhá-lo. Para fazer isso, crie um arquivo de efeito separado, escreva um programa, carregue-o como uma classe de efeito e execute o programa de sombreador.

No entanto, se você não precisar desenhar polígonos triangulares simples como este, ou efeitos de desenho complexos, pode ser uma tarefa muito complicada.

Por esse motivo, o XNA define efeitos estendidos que permitem definir os itens necessários como propriedades para que você não precise escrever um programa de sombreador para desenho básico. Essa é a classe "BasicEffect". Como o objetivo deste artigo é desenhar polígonos, usaremos "BasicEffect" que não exige muito esforço para desenhar.

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

Falarei mais sobre efeitos e BasicEffects em outro momento.

A propósito, o Windows Phone 7 não permite que você use seus próprios efeitos, apenas aqueles integrados a estruturas como BasicEffect.

Criar uma definição de dados de vértice

Até o XNA Framework 3.1, você tinha que criá-los explicitamente programaticamente, mas a partir do 4.0, as informações de vértice internas da estrutura já estão incluídas nas informações de vértice como "IVertexType.VertexDeclaration", portanto, vamos usá-las.

Criando efeitos

Crie uma classe BasicEffect. Defina a propriedade BasicEffect.VertexColorEnabled como true para manter as cores dos vértices.

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

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

BasicEffect construtor

Crie uma instância da classe de efeito "BasicEffect" que executa a cor, a textura e a iluminação do vértice usando o Modelo de Sombreador 2.0.

dispositivo Dispositivo gráfico Especifica o GraphicsDevice para criar o efeito

Matriz de visualização e matriz de projeção

Defina o BasicEffect como uma matriz de exibição e uma matriz de projeção. Para uma explicação conceitual de cada um, consulte os links abaixo.

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

Para gerar uma matriz de exibição, use o método "Matrix.CreateLookAt".

O primeiro argumento especifica a posição da câmera, o segundo argumento especifica o ponto de interesse da câmera e o terceiro argumento especifica a direção para cima da câmera.

Nesse caso, ele é definido para examinar a origem da posição (0, 0, 15).

Matrix.CreateLookAt método

Crie uma matriz de exibição.

posição da câmera Vetor 3 Posição da câmera
alvo da câmera Vetor 3 Ponto de interesse da câmera
cameraUpVector Vetor 3 Direção ascendente da câmera

Para gerar uma matriz de projeção, use o método "Matrix.CreatePerspectiveFieldOfView".

O primeiro argumento é o ângulo de visão em radianos. Na amostra, a unidade de grau é convertida em radiano usando o método "MathHelper.ToRadians". Para obter mais informações sobre Radiano e Grau, consulte Radiano e Grau.

O segundo argumento especifica a proporção (taxa de proporção). Normalmente, você especifica um valor para Largura ÷ Altura da Vista. No exemplo, ele é calculado a partir da largura e da altura definidas para a janela de exibição do dispositivo.

O terceiro argumento especifica a posição de recorte para frente e o quarto argumento especifica a posição de recorte para trás.

Matrix.CreatePerspectiveFieldOfView método

Cria uma matriz de projeção em perspectiva com base nas configurações do campo de exibição.

campoDevisão flutuar Ângulo de visão. Especificado em unidades radianas.
proporção de aspecto flutuar Proporção (taxa de proporção). Normalmente, você especifica um valor para "Largura ÷ altura da vista"
nearPlaneDistance flutuar Posição do clipe para frente. Os objetos na frente dessa posição não são desenhados.
farPlaneDistance flutuar Posição do clipe traseiro. Objetos além dessa posição não são desenhados.

Criando dados de vértice

Crie três dados de vértice. Primeiro, criaremos uma matriz e criaremos cada vértice.

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

Para criar dados de vértice, especifique a "posição do vértice" e a "cor do vértice" no construtor de "VertexPositionColor".

VertexPositionColor construtor

Crie uma instância da estrutura "VertexPositionColor" com os dados de vértice de posição e cor.

posição Vetor 3 Posição do vértice
Cor Cor Cor do vértice

Defina a posição dos vértices para o intervalo que pode ser visto da câmera. Além disso, defina o arranjo de vértices como "sentido horário (sentido horário)". Se você defini-lo como "sentido anti-horário", o polígono não ficará visível. Para obter uma explicação sobre isso, consulte Especificando as faces de um polígono a ser desenhado.

Desenhando polígonos

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

Existem dois tipos de efeitos, chamados de "técnicas" e "caminhos", por meio dos quais você executa o programa de desenho real. Como pode haver vários caminhos em um único efeito, tento chamá-los repetidamente em foreach. No entanto, em BasicEffect, há uma técnica e um caminho, portanto, você pode especificar o índice do caminho diretamente, mas a descrição acima será mais limpa porque você pode substituí-la por outros efeitos.

Antes de iniciar o desenho real, chame o método "EffectPass.Apply" para iniciar a passagem. Ao chamar esse método, os parâmetros do efeito a ser usado desta vez são aplicados ao dispositivo gráfico.

Depois de iniciar o caminho, desenhe o polígono com o método "GraphicsDevice.DrawUserPrimitives".

O primeiro argumento especifica o tipo de primitiva a ser desenhada. Nesse caso, desenharemos um polígono triangular, portanto, especifique "PrimitiveType.TriangleList".

O segundo argumento especifica os dados de vértice criados.

O terceiro argumento especifica o vértice do qual extrair. Normalmente, isso é 0.

O quarto argumento especifica o número de primitivas a serem desenhadas. Nesse caso, há apenas um polígono triangular, portanto, especifique 1. Observe que não é o número de vértices.

GraphicsDevice.DrawUserPrimitives método

Desenha primitivos com base em dados de vértice fornecidos pelo usuário.

T Sem limite Estruturas de dados de vértice
tipo primitivo Tipo primitivo O tipo de primitivo a ser desenhado
vertexData T[] Uma matriz de dados de vértices para desenhar
vertexOffset int Especifique o número de dados de vértice a serem usados para desenhar
primitiveCount int O número de primitivos a serem desenhados.

Isso é tudo para o programa de desenho. Se você realmente executá-lo e um triângulo for exibido, você está pronto.

Todos os códigos

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