■ 3차원 지구본 사용하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


MainWindow.xaml

 

 

<Window x:Class="TestProject.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Width="800"

    Height="600"

    Title="3차원 지구본 사용하기"

    Loaded="Window_Loaded"

    KeyDown="Window_KeyDown">

    <Grid>

        <Viewport3D Name="viewport3D" />

    </Grid>

</Window>

 

 

MainWindow.xaml.cs

 

 

using System;

using System.Windows;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Media.Media3D;

 

namespace TestProject

{

    /// <summary>

    /// 메인 윈도우

    /// </summary>

    public partial class MainWindow : Window

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 모델 그룹

        /// </summary>

        private Model3DGroup modelGroup = new Model3DGroup();

 

        /// <summary>

        /// 카메라

        /// </summary>

        private PerspectiveCamera camera;

 

        /// <summary>

        /// 카메라 파이

        /// </summary>

        private double cameraPhi = Math.PI / 6.0;

 

        /// <summary>

        /// 카메라 세타

        /// </summary>

        private double cameraTheta = Math.PI / 6.0;

 

        /// <summary>

        /// 카메라 R

        /// </summary>

        private double cameraR = 3.0;

 

        /// <summary>

        /// 카메라 델타 파이

        /// </summary>

        private const double CAMERA_DELTA_PHI = 0.1;

 

        /// <summary>

        /// 카메라 델타 세타

        /// </summary>

        private const double CAMERA_DELTA_THETA = 0.1;

 

        /// <summary>

        /// 카메라 델타 R

        /// </summary>

        private const double CAMERA_DELTA_R = 0.1;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainWindow()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainWindow()

        {

            InitializeComponent();

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 윈도우 로드시 처리하기 - Window_Loaded(sender, e)

 

        /// <summary>

        /// 윈도우 로드시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Window_Loaded(object sender, RoutedEventArgs e)

        {

            this.camera = new PerspectiveCamera();

 

            this.camera.FieldOfView = 60;

 

            this.viewport3D.Camera = this.camera;

 

            SetCameraPosition();

 

            DefineLight();

 

            DefineModel(this.modelGroup);

 

            ModelVisual3D modelVisual = new ModelVisual3D();

 

            modelVisual.Content = this.modelGroup;

 

            this.viewport3D.Children.Add(modelVisual);

        }

 

        #endregion

        #region 윈도우 키 DOWN 처리하기 - Window_KeyDown(sender, e)

 

        /// <summary>

        /// 윈도우 키 DOWN 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Window_KeyDown(object sender, KeyEventArgs e)

        {

            switch(e.Key)

            {

                case Key.Up :

 

                    this.cameraPhi += CAMERA_DELTA_PHI;

 

                    if(this.cameraPhi > Math.PI / 2.0)

                    {

                        this.cameraPhi = Math.PI / 2.0;

                    }

 

                    break;

 

                case Key.Down :

 

                    this.cameraPhi -= CAMERA_DELTA_PHI;

 

                    if(this.cameraPhi < -Math.PI / 2.0)

                    {

                        this.cameraPhi = -Math.PI / 2.0;

                    }

 

                    break;

 

                case Key.Left :

 

                    this.cameraTheta += CAMERA_DELTA_THETA;

 

                    break;

 

                case Key.Right :

 

                    this.cameraTheta -= CAMERA_DELTA_THETA;

 

                    break;

 

                case Key.Add     :

                case Key.OemPlus :

 

                    this.cameraR -= CAMERA_DELTA_R;

 

                    if(this.cameraR < CAMERA_DELTA_R)

                    {

                        this.cameraR = CAMERA_DELTA_R;

                    }

 

                    break;

 

                case Key.Subtract :

                case Key.OemMinus :

 

                    this.cameraR += CAMERA_DELTA_R;

 

                    break;

            }

 

            SetCameraPosition();

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 카메라 위치 설정하기 - SetCameraPosition()

 

        /// <summary>

        /// 카메라 위치 설정하기

        /// </summary>

        private void SetCameraPosition()

        {

            double y   = this.cameraR * Math.Sin(this.cameraPhi);

            double hyp = this.cameraR * Math.Cos(this.cameraPhi);

            double x   = hyp * Math.Cos(this.cameraTheta);

            double z   = hyp * Math.Sin(this.cameraTheta);

 

            this.camera.Position = new Point3D(x, y, z);

 

            this.camera.LookDirection = new Vector3D(-x, -y, -z);

 

            this.camera.UpDirection = new Vector3D(0, 1, 0);

        }

 

        #endregion

        #region 조명 정의하기 - DefineLight()

 

        /// <summary>

        /// 조명 정의하기

        /// </summary>

        private void DefineLight()

        {

            AmbientLight ambientLight = new AmbientLight(Colors.Gray);

 

            DirectionalLight directionalLight = new DirectionalLight(Colors.Gray, new Vector3D(-1.0, -3.0, -2.0));

 

            this.modelGroup.Children.Add(ambientLight);

 

            this.modelGroup.Children.Add(directionalLight);

        }

 

        #endregion

        #region 구체 생성하기 - CreateSphere(modelGroup, sphereMesh, sphereMaterial, radius, centerX, centerY, centerZ,

            phiCount, thetaCount)

 

        /// <summary>

        /// 구체 생성하기

        /// </summary>

        /// <param name="modelGroup">모델 그룹</param>

        /// <param name="sphereMesh">구체 메시</param>

        /// <param name="sphereMaterial">구체 재료</param>

        /// <param name="radius">반지름</param>

        /// <param name="centerX">중심 X 좌표</param>

        /// <param name="centerY">중심 Y 좌표</param>

        /// <param name="centerZ">중심 Z 좌표</param>

        /// <param name="phiCount">파이 카운트</param>

        /// <param name="thetaCount">세타 카운트</param>

        private void CreateSphere(Model3DGroup modelGroup, ref MeshGeometry3D sphereMesh, Material sphereMaterial, double radius,

            double centerX, double centerY, double centerZ, int phiCount, int thetaCount)

        {

            if(sphereMesh == null)

            {

                sphereMesh = new MeshGeometry3D();

 

                GeometryModel3D newModel = new GeometryModel3D(sphereMesh, sphereMaterial);

 

                modelGroup.Children.Add(newModel);

            }

 

            double deltaPhi   = Math.PI / phiCount;

            double deltaTheta = 2 * Math.PI / thetaCount;

 

            int positionCount = sphereMesh.Positions.Count;

 

            double halfPI = Math.PI / 2;

 

            for(int p = 0; p <= phiCount; p++)

            {

                double r1 = radius * Math.Cos(halfPI);

                double y1 = radius * Math.Sin(halfPI);

 

                double theta = 0;

 

                for(int t = 0; t <= thetaCount; t++)

                {

                    sphereMesh.Positions.Add

                    (

                        new Point3D

                        (

                            centerX +  r1 * Math.Cos(theta),

                            centerY +  y1,

                            centerZ + -r1 * Math.Sin(theta)

                        )

                    );

 

                    sphereMesh.TextureCoordinates.Add

                    (

                        new Point

                        (

                            (double)t / thetaCount,

                            (double)p / phiCount

                        )

                    );

 

                    theta += deltaTheta;

                }

 

                halfPI -= deltaPhi;

            }

 

            int i1;

            int i2;

            int i3;

            int i4;

 

            for(int p = 0; p <= phiCount - 1; p++)

            {

                i1 = p  * (thetaCount + 1);

                i2 = i1 + (thetaCount + 1);

 

                for(int t = 0; t <= thetaCount - 1; t++)

                {

                    i3 = i1 + 1;

                    i4 = i2 + 1;

 

                    sphereMesh.TriangleIndices.Add(positionCount + i1);

                    sphereMesh.TriangleIndices.Add(positionCount + i2);

                    sphereMesh.TriangleIndices.Add(positionCount + i4);

 

                    sphereMesh.TriangleIndices.Add(positionCount + i1);

                    sphereMesh.TriangleIndices.Add(positionCount + i4);

                    sphereMesh.TriangleIndices.Add(positionCount + i3);

 

                    i1 += 1;

                    i2 += 1;

                }

            }

        }

 

        #endregion

        #region 모델 정의하기 - DefineModel(modelGroup)

 

        /// <summary>

        /// 모델 정의하기

        /// </summary>

        /// <param name="modelGroup">모델 그룹</param>

        private void DefineModel(Model3DGroup modelGroup)

        {

            Model3DGroup globeModel = new Model3DGroup();

 

            modelGroup.Children.Add(globeModel);

 

            ImageBrush globeBrush = new ImageBrush(new BitmapImage(new Uri("pack://application:,,,/world.jpg")));

 

            Material globeMaterial = new DiffuseMaterial(globeBrush);

 

            MeshGeometry3D globeMesh = null;

 

            CreateSphere(globeModel, ref globeMesh, globeMaterial, 1, 0, 0, 0, 100, 150);

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요