Visualización de polígonos triangulares

Actualización de la página :
Fecha de creación de la página :

resumen

Muestra polígonos triangulares en el espacio 3D.

3角形ポリゴンの表示

Entorno operativo

Prerrequisitos

Versiones de XNA compatibles
  • 4.0
Plataformas compatibles
  • Windows (XP SP2 o posterior, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Versión del sombreador de vértices requerida para Windows 2.0
Versión de Pixel Shader requerida para Windows 2.0

Entorno operativo

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

sustancia

¿Qué es un polígono?

Un polígono es una cara generada por varias definiciones de vértices. En general, un polígono es una cara triangular que consta de tres vértices. Y el trígono es la unidad más pequeña del polígono. Algunos programas de modelado pueden mostrar polígonos como cuadriláteros o poligonales, pero estos eventualmente se descompondrán en polígonos triangulares.

El modelo que se muestra en los juegos se forma combinando varios de estos polígonos triangulares.

最小単位のポリゴン

Los polígonos están formados por vértices. Los vértices pueden tener datos como la posición y el color. Este ejemplo también se realiza a partir de datos de "posición" y "color".

ポリゴンと頂点

El color de la cara en este ejemplo está perfectamente interpolado por el color y la distancia establecidos para cada vértice, pero puede cambiarlo libremente con su propio programa de sombreado (más sobre los programas de sombreado en otro momento).

Definiciones de datos de vértices

Para mostrar un polígono, se requieren "datos de vértice" y el programador debe decidir qué elementos incluir en ese vértice. Al dibujar un polígono, debe decirle al dispositivo, que es el motor de dibujo, con qué datos de vértice dibujar el polígono. Para ello, cree una clase "VertexDeclaration" y establezca la "Definición de datos de vértice".

Sin embargo, a partir de XNA Game Studio 4.0, esta configuración se ha simplificado y no es necesario preparar una clase VertexDeclaration para esta sugerencia. (Esto se debe a que la información de definición ya está incrustada en los datos de vértice proporcionados por el marco).

Datos de vértice

Escribí que los datos de vértices son necesarios para dibujar polígonos, pero primero tenemos que decidir qué tipo de datos queremos tener. En este caso, utilizaremos los datos de "posición" y "color". Una vez que haya decidido qué datos desea tener, debe crear una estructura para contener esos datos. Tiene cierta libertad para decidir qué son los datos de vértice, pero los datos de vértice que se usan habitualmente ya están definidos en XNA Framework, por lo que el ejemplo los usa.

Los datos de vértice con "posición" y "color" se definen como una estructura "VertexPositionColor". Dado que se necesitan múltiples vértices para formar un polígono, lo declaramos como una matriz.

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

efecto

En XNA, cuando se dibuja un polígono, hay que escribir un programa de sombreado independiente para decidir cómo dibujarlo. Para hacer esto, cree un archivo de efectos separado, escriba un programa, cárguelo como una clase de efecto y ejecute el programa de sombreado.

Sin embargo, si no necesitas dibujar polígonos triangulares simples como este, o efectos de dibujo complejos, puede ser una tarea muy engorrosa.

Por este motivo, XNA define efectos extendidos que permiten establecer los elementos necesarios como propiedades para que no tenga que escribir un programa de sombreado para el dibujo básico. Esa es la clase "BasicEffect". Dado que el propósito de este artículo es dibujar polígonos, usaremos "BasicEffect" que no requiere mucho esfuerzo para dibujar.

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

Hablaré más sobre los efectos y BasicEffects en otro momento.

Por cierto, Windows Phone 7 no te permite usar tus propios efectos, solo aquellos integrados en frameworks como BasicEffect.

Creación de una definición de datos de vértice

Hasta XNA Framework 3.1, había que crearlos explícitamente mediante programación, pero a partir de la versión 4.0, la información de vértice integrada del marco ya está incluida en la información de vértice como "IVertexType.VertexDeclaration", por lo que la usaremos.

Creación de efectos

Cree una clase BasicEffect. Establezca la propiedad BasicEffect.VertexColorEnabled en true para mantener los colores de los vértices.

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

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

BasicEffect constructor

Cree una instancia de la clase de efecto "BasicEffect" que realice el color, la textura y la iluminación de los vértices mediante Shader Model 2.0.

dispositivo Dispositivo gráfico Especifica el GraphicsDevice para crear el efecto

Matriz de vista y matriz de proyección

Establezca BasicEffect en una matriz de vista y una matriz de proyección. Para obtener una explicación conceptual de cada uno, consulte los enlaces a continuación.

// ビューマトリックスをあらかじめ設定 ((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 generar una matriz de vista, utilice el método "Matrix.CreateLookAt".

El primer argumento especifica la posición de la cámara, el segundo argumento especifica el punto de interés de la cámara y el tercer argumento especifica la dirección ascendente de la cámara.

En este caso, se establece para mirar el origen desde la posición (0, 0, 15).

Matrix.CreateLookAt método

Cree una matriz de vista.

cameraPosition Vector3 Posición de la cámara
cameraTarget Vector3 Punto de interés de la cámara
cameraUpVector Vector3 Dirección ascendente de la cámara

Para generar una matriz de proyección, utilice el método "Matrix.CreatePerspectiveFieldOfView".

El primer argumento es el ángulo de visión en radianes. En el ejemplo, la unidad de grado se convierte a radianes mediante el método "MathHelper.ToRadians". Para obtener más información sobre Radian y Degree, consulte Radian y Degree.

El segundo argumento especifica la relación de aspecto (relación de aspecto). Normalmente, se especifica un valor para Anchura ÷ Altura de vista. En el ejemplo, se calcula a partir de la anchura y la altura establecidas para la ventanilla del dispositivo.

El tercer argumento especifica la posición de recorte hacia adelante y el cuarto argumento especifica la posición de recorte hacia atrás.

Matrix.CreatePerspectiveFieldOfView método

Crea una matriz de proyección en perspectiva basada en la configuración del campo de vista.

fieldOfView flotar Ángulo. Especificado en unidades de radianes.
aspectRatio flotar Relación de aspecto (relación de aspecto). Normalmente, se especifica un valor para "Anchura ÷ altura de vista"
nearPlaneDistance flotar Posición del clip hacia adelante. Los objetos que se encuentran delante de esta posición no se dibujan.
farPlaneDistance flotar Posición del clip trasero. Los objetos que se encuentran más allá de esta posición no se dibujan.

Creación de datos de vértices

Cree tres datos de vértice. Primero, crearemos una matriz y crearemos 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 crear datos de vértice, especifique la "posición del vértice" y el "color del vértice" en el constructor de "VertexPositionColor".

VertexPositionColor constructor

Cree una instancia de la estructura "VertexPositionColor" con los datos de posición y color de los vértices.

posición Vector3 Posición del vértice
Color Color Color del vértice

Establezca la posición de los vértices en el rango que se puede ver desde la cámara. Además, establezca la disposición de los vértices en "el sentido de las agujas del reloj (en el sentido de las agujas del reloj)". Si lo configura en "sentido contrario a las agujas del reloj", el polígono no será visible. Para obtener una explicación de esto, consulte Especificación de las caras de un polígono para dibujar.

Dibujo de 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);

Hay dos tipos de efectos, llamados "técnicas" y "trazados", a través de los cuales se ejecuta el programa de dibujo real. Dado que puede haber múltiples caminos en un solo efecto, trato de llamarlos repetidamente en foreach. Sin embargo, en BasicEffect, hay una técnica y un trazado, por lo que puede especificar el índice del trazado directamente, pero la descripción anterior será más limpia porque puede sustituirla por otros efectos.

Antes de iniciar el dibujo real, llame al método "EffectPass.Apply" para iniciar el pase. Al llamar a este método, los parámetros del efecto que se utilizará esta vez se aplican al dispositivo gráfico.

Una vez que haya iniciado la ruta, dibuje el polígono con el método "GraphicsDevice.DrawUserPrimitives".

El primer argumento especifica el tipo de primitiva que se va a dibujar. En este caso, dibujaremos un polígono triangular, así que especifica "PrimitiveType.TriangleList".

El segundo argumento especifica los datos de vértice creados.

El tercer argumento especifica el vértice del que se va a extraer. Normalmente, es 0.

El cuarto argumento especifica el número de primitivas que se van a dibujar. En este caso, solo hay un polígono triangular, por lo que debe especificar 1. Tenga en cuenta que no es el número de vértices.

GraphicsDevice.DrawUserPrimitives método

Dibuja primitivas en función de los datos de vértice proporcionados por el usuario.

T Sin límite Estructuras de datos de vértices
primitiveType PrimitiveType (Tipo primitivo) El tipo de primitiva que se va a dibujar
vérticeData T[] Una matriz de datos de vértices para dibujar
vérticeDesplazamiento Int Especifique el número de datos de vértice que se utilizarán para dibujar
primitiveCount Int El número de primitivas que se van a dibujar.

Eso es todo para el programa de dibujo. Si realmente lo ejecutas y se muestra un triángulo, ya está.

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