Graphics/DirectX

Direct X - 12. 마우스로 카메라 시점 움직이기

MOLOKINI 2014. 6. 9. 00:07
카메라를 움직이는 부분의 공식이나 방법은 11강과 같고,,
단지 키보드에서 마우스만을 사용한다는 점이 바뀌었다



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 _vertexBuffer = null;

        private Texture _texture = null;

        private float _lensPosTheta = 270.0f;
        private float _lensPosPhi = 0.0f;

        private Point _oldMousePoint = Point.Empty;

        public bool InitializeApplication(MainForm topLevelForm)
        {
            // 폼의 참조를 보관 유지
            this._form = topLevelForm;

            PresentParameters pp = new PresentParameters();
            pp.Windowed = true;
            pp.SwapEffect = SwapEffect.Discard;
            pp.EnableAutoDepthStencil = true;
            pp.AutoDepthStencilFormat = DepthFormat.D16;

            topLevelForm.MouseMove += new MouseEventHandler(this.form_MouseMove);

            try
            {
                // Direct3D 디바이스 작성
                this.CreateDevice(topLevelForm, pp);
                // 폰트의 작성
                this.CreateFont();

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

            this.SettingCamera();
            this.MyFace();

            this._device.RenderState.Lighting = false;
            this._device.RenderState.CullMode = Cull.None;

            return true;
        }

        /// <summary>
        /// 메인 루프 처리
        /// </summary>
        public void MainLoop()
        {
            float radius = 10.0f;
            float theta = Geometry.DegreeToRadian(this._lensPosTheta);
            float phi = Geometry.DegreeToRadian(this._lensPosPhi);
            Vector3 lensPosition = new Vector3((float)(radius * Math.Cos(theta) * Math.Cos(phi)), 
                (float)(radius * Math.Sin(phi)), (float)(radius * Math.Sin(theta) * Math.Cos(phi)));
            
            this.SettingCamera(lensPosition);           
            
            // 화면을 단색(파랑색)으로 클리어
            this._device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkBlue, 1.0f, 0);

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

            this.RenderMyFace();
                        
            // 좌표 x=0 y=0 의 위치에 흰색으로 출력
            this._font.DrawText(null, "카메라 돌려보기", 0, 0, 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;

                if (this._lensPosPhi >= 90.0f)
                {
                    this._lensPosPhi = 89.9999f;
                }
                else if (this._lensPosTheta <= -90.0f)
                {
                    this._lensPosPhi = -89.9999f;
                }
            }
            this._oldMousePoint = e.Location;
        }

        /// <summary>
        /// 자원의 파기
        /// </summary>
        public void Dispose()
        {
            if (this._texture != null)
            {
                this._texture.Dispose();
            }
            // 정점 버퍼를 해제
            if (this._vertexBuffer != null)
            {
                this._vertexBuffer.Dispose();
            }

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

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


        private Point _oldMousePoint = Point.Empty;
마우스의 이동량을 저장하기 위한 변수 선언


            topLevelForm.MouseMove += new MouseEventHandler(this.form_MouseMove);
키보드처럼 마우스의 이동 이벤트 핸들러 작성
이 외에도 마우스를 클릭했을때의 이벤트, 뗐을때의 이벤트 핸들러가 있는데, 여기서는 이동만


        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;

                if (this._lensPosPhi >= 90.0f)
                {
                    this._lensPosPhi = 89.9999f;
                }
                else if (this._lensPosTheta <= -90.0f)
                {
                    this._lensPosPhi = -89.9999f;
                }
            }
            this._oldMousePoint = e.Location;
        }
마우스가 이동할때마다 이 메서드가 호출된다
마우스의 왼쪽 버튼이 눌리는지는, MouseEventArgs.Button의 상태를 통해 알 수 있다
MouseButtons.Left면 마우스의 왼쪽 버튼이 눌러지는것
다음은, 클릭 이전의 마우스의 위치와 현재의 마우스위치를 뺀 값으로 회전량을 결정
파이는 전과같이 한계점을 두고
앞의 값과 비교하기 위해 현재 마우스의 위치를 마지막으로 기록한다

소스를 보면 알겠지만, 마우스를 클릭해서 움직여야한다!


끗^^