삼각형 다각형 표시

페이지 업데이트 :
페이지 생성 날짜 :

요약

3D 공간에 삼각형 다각형을 표시합니다.

3角形ポリゴンの表示

운영 환경

필수 구성 요소

지원되는 XNA 버전
  • 4.0
지원되는 플랫폼
  • Windows(XP SP2 이상, Vista, 7)
  • 엑스박스 360
  • 윈도우 폰 7
Windows 필수 버텍스 셰이더 버전 2.0
Windows 필수 픽셀 셰이더 버전 2.0

운영 환경

플랫폼
  • 윈도우 7
  • 엑스박스 360
  • Windows Phone 7 에뮬레이터

물질

폴리곤이란 무엇입니까?

다각형은 여러 정점 정의에 의해 생성되는 면입니다. 일반적으로 다각형은 세 개의 꼭지점으로 구성된 삼각형 면입니다. 그리고 삼각형은 다각형의 가장 작은 단위입니다. 일부 모델링 소프트웨어는 다각형을 사변형 또는 다각형으로 표시할 수 있지만 결국에는 삼각형 다각형으로 분해됩니다.

게임에 표시되는 모델은 이러한 삼각형 다각형을 여러 개 결합하여 형성됩니다.

最小単位のポリゴン

다각형은 꼭짓점으로 형성됩니다. 꼭짓점에는 위치 및 색상과 같은 데이터가 있을 수 있습니다. 이 샘플은 "위치" 및 "색상" 데이터로도 만들어집니다.

ポリゴンと頂点

이 예제에서 얼굴의 색상은 각 정점에 대해 설정된 색상과 거리에 의해 깔끔하게 보간되지만 자신의 셰이더 프로그램을 사용하여 자유롭게 변경할 수 있습니다(셰이더 프로그램에 대해서는 나중에 자세히 설명).

Vertex 데이터 정의

다각형을 표시하기 위해서는 "정점 데이터"가 필요하며, 프로그래머는 해당 정점에 포함할 요소를 결정해야 합니다. 다각형을 그릴 때는 그리기 엔진인 장치에 다각형을 그릴 꼭짓점 데이터를 알려야 합니다. 이렇게 하려면 "VertexDeclaration" 클래스를 만들고 "Vertex Data Definition"을 설정합니다.

그러나 XNA Game Studio 4.0부터는 이 설정이 간소화되었으므로 이 팁에 대해 VertexDeclaration 클래스를 준비할 필요가 없습니다. (이는 정의 정보가 프레임워크에서 제공하는 꼭짓점 데이터에 이미 포함되어 있기 때문입니다.)

꼭짓점 데이터

다각형을 그리려면 정점 데이터가 필요하다고 썼지만, 먼저 어떤 종류의 데이터를 갖고 싶은지 결정해야 합니다. 이 경우 "위치" 및 "색상" 데이터를 사용합니다. 갖고 싶은 데이터를 결정한 후에는 해당 데이터를 저장할 구조를 만들어야 합니다. 꼭짓점 데이터가 무엇인지 자유롭게 결정할 수 있지만 일반적으로 사용되는 꼭지점 데이터는 XNA Framework에 이미 정의되어 있으므로 샘플에서 사용합니다.

"position" 및 "color"가 있는 꼭짓점 데이터는 "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 생성자

Shader Model 2.0을 사용하여 정점 색상, 질감 및 조명을 수행하는 효과 클래스 "BasicEffect"의 인스턴스를 만듭니다.

장치 그래픽장치 효과를 만들기 위한 GraphicsDevice를 지정합니다

View Matrix 및 Projection Matrix

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 메서드

뷰 행렬을 만듭니다.

카메라 위치 벡터3 카메라 위치
카메라타겟 벡터3 카메라 관심 지점
cameraUpVector (영문) 벡터3 카메라의 위쪽 방향

프로젝션 행렬을 생성하려면 "Matrix.CreatePerspectiveFieldOfView" 메서드를 사용합니다.

첫 번째 인수는 시야각(라디안)입니다. 샘플에서 도 단위는 "MathHelper.ToRadians" 메서드를 사용하여 라디안으로 변환됩니다. Radian 및 Degree에 대한 자세한 내용은 Radian 및 Degree를 참조하십시오.

두 번째 인수는 종횡비(종횡비)를 지정합니다. 일반적으로 View Width ÷ Height에 대한 값을 지정합니다. 샘플에서는 장치의 뷰포트에 대해 설정된 너비와 높이를 기준으로 계산됩니다.

세 번째 인수는 앞으로 클리핑 위치를 지정하고 네 번째 인수는 뒤로 클리핑 위치를 지정합니다.

Matrix.CreatePerspectiveFieldOfView 메서드

view 필드의 설정에 따라 perspective projection matrix를 생성합니다.

fieldOfView 뜨다 시야각. 라디안 단위로 지정됩니다.
종횡비 뜨다 종횡비(종횡비). 일반적으로 "View Width ÷ Height"에 대한 값을 지정합니다
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 버텍스 위치(Vertex Position)
정점 색상

정점의 위치를 카메라에서 볼 수 있는 범위로 설정합니다. 또한 정점 배열을 "시계 방향 (시계 방향)"으로 설정합니다. "시계 반대 방향"으로 설정하면 다각형이 보이지 않습니다. 이에 대한 설명은 Specifying the Faces of a Polygon to Draw를 참조하십시오.

다각형 그리기

// パスの数だけ繰り替えし描画 (といっても直接作成した 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 제한 없음 Vertex 데이터 구조
프리미티브 타입 프리미티브 타입 그릴 프리미티브의 유형입니다
vertexData T[] 그릴 꼭짓점 데이터의 배열
vertexOffset (버텍스 오프셋) 정수 그리기에 사용할 정점 데이터의 수를 지정합니다
프리미티브 카운트 정수 그릴 기본 형식의 수입니다.

드로잉 프로그램은 여기까지입니다. 실제로 실행하고 삼각형이 표시되면 완료된 것입니다.

모든 코드

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