Graphics/DirectX

Direct X - 18. 모델 확대와 축소

MOLOKINI 2014. 6. 9. 00:36

이 모델 확대와 축소를 이용하면,, 폭발하는듯한 애니메이션을 만드는데 응용이 가능하다




using System;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Windows.Forms;
using System.Drawing;

namespace MDXSample
{
    /// <summary>
    /// 메인 샘플 클래스
    /// </summary>
    public partial class MainSample : IDisposable
    {
        /// <summary>
        /// 정점 버퍼
        /// </summary>
        /// 
        private VertexBuffer _xyzLineBuffer = null;

        private Vector3 _scale = new Vector3(1.0f, 1.0f, 1.0f);

        public bool InitializeApplication(MainForm topLevelForm)
        {
            // 폼의 참조를 보관 유지
            this._form = topLevelForm;
            PresentParameters pp = new PresentParameters();
            try
            {
                // Direct3D 디바이스 작성
                this.CreateDevice(topLevelForm, pp);
                // 폰트의 작성
                this.CreateFont();

            }
            catch (DirectXException ex)
            {
                // 예외 발생
                MessageBox.Show(ex.ToString(), "에러", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            LoadXfile("01.x");  // 라이트까지 세팅되어있다.
            createXYZLine();

            this._device.RenderState.NormalizeNormals = true;

            return true;
        }

        /// <summary>
        /// 메인 루프 처리
        /// </summary>
        public void MainLoop()
        {       
            this.SettingCamera();

            if (this._keys[(int)Keys.Left])
            {
                this._scale.X /= 1.01f;
            }
            if (this._keys[(int)Keys.Right])
            {
                this._scale.X *= 1.01f;
            }
            if (this._keys[(int)Keys.Up])
            {
                this._scale.Y /= 1.01f;
            }
            if (this._keys[(int)Keys.Down])
            {
                this._scale.Y *= 1.01f;
            }
                        
            // 화면을 단색(파랑색)으로 클리어
            this._device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkBlue, 1.0f, 0);

            // 「BeginScene」와「EndScene」의 사이에 화면에 출력할 내용을 코딩
            this._device.BeginScene();

            this.RenderXYZ();           

            this._device.RenderState.Lighting = true;
            this._device.SetTransform(TransformType.World, Matrix.Scaling(this._scale));

            this.RenderMesh();

            this._font.DrawText(null, "θ:" + this._lensPosTheta, 0, 0, Color.White);
            this._font.DrawText(null, "φ:" + this._lensPosPhi, 0, 12, Color.White);
            this._font.DrawText(null, "마우스 위치:" + this._oldMousePoint, 0, 24, Color.White);
            
            // 화면출력은 여기까지
            this._device.EndScene();

            // 실제의 디스플레이에 출력
            this._device.Present();
        }

        private void form_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this._lensPosTheta -= e.Location.X - this._oldMousePoint.X;
                this._lensPosPhi += e.Location.Y - this._oldMousePoint.Y;
            }
            this._oldMousePoint = e.Location;
        }

        /// <summary>
        /// 자원의 파기
        /// </summary>
        public void Dispose()
        {
            if (this._textures != null)
            {
                foreach (Texture i in this._textures)
                {
                    if (i != null)
                    {
                        i.Dispose();
                    }
                }
            }

            if (this._mesh != null)
            {
                this._mesh.Dispose();
            }

            // 폰트 자원을 해제
            if (this._font != null)
            {
                this._font.Dispose();
            }

            // Direct3D 디바이스의 자원 해제
            if (this._device != null)
            {
                this._device.Dispose();
            }
        }
    }
}


        private Vector3 _scale = new Vector3(1.0f, 1.0f, 1.0f);
XYZ방향으로 모델을 확대하기 위해, Vector3 파라미터를 준비한다.
확대축소의 값은 원형의 배율이니 1.0으로 초기화한다. Vector3.Empty로 지정해버리면 모델이 표시가 되지 않으니 주의해주세요


            this._device.RenderState.NormalizeNormals = true;
모델을 확대하면 법선의 계산이 바뀌니까 좌표변화 이후 법선을 정규화하도록 지정한다.


            if (this._keys[(int)Keys.Left])
            {
                this._scale.X /= 1.01f;
            }
            if (this._keys[(int)Keys.Right])
            {
                this._scale.X *= 1.01f;
            }
            if (this._keys[(int)Keys.Up])
            {
                this._scale.Y /= 1.01f;
            }
            if (this._keys[(int)Keys.Down])
            {
                this._scale.Y *= 1.01f;
            }
모델의 확대와 축소가 자연스럽게 보이도록, 원래의 값에 1.01을 곱하거나 나누고있어요
더하거나 빼면 커지고작아지는게 무지하게 빨라져요


            this._device.RenderState.Lighting = true;
            this._device.SetTransform(TransformType.World, Matrix.Scaling(this._scale));

            this.RenderMesh();
이번 확대 축소에 사용되는 메서드는 Matrix.Scaling
값을 세트한 Vector3을 건네주면 그대로 확대 축소합니다
메쉬그리고하는건 17강이랑 똑같으니까 생각안나면 17강을 참고하세요


Matrix.Scaling 메서드 동작방법
Matrix.Scaling은 건네받은 값을 아래와 같은 매트릭스로 변환하고 있습니다


사실 이것만봐서는 잘 모르겠죠?

그럼 다각형을 이용해서 설명해볼테니 이해해봅시다



이번에는 다각형의 배율을(1.5, 1.0, 2.0)으로 합니다.

이 그림 역시 Y축에서 아래를 내려다 본 그림


위 그림의 0번 정점을 먼저 계산해봅시다


나머지 정점은 다음과 같은 결과가 나온다

0번 정점 : (-1.5, 0, 2)

1번 정점 : (3, 0, 2)

2번 정점 : (-1.5, 0, -2)

3번 정점 : (3, 0, -2)


요로코롬 된다는거죠