첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

728x90
반응형

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="MeshGeometry3D 클래스 : 삼각측량법을 사용해 비치볼 만들기"
    FontFamily="나눔고딕코딩"
    FontSize="16">
</Window>

 

▶ MainWindow.xaml.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Media3D;

namespace TestProject
{
    /// <summary>
    /// 메인 윈도우
    /// </summary>
    public partial class MainWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainWindow()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            Viewport3D viewport3D = new Viewport3D();

            Content = viewport3D;

            MeshGeometry3D meshGeometry3D = GetSphereMeshGeometry3D(new Point3D(0, 0, 0), 1.5, 144, 72);

            meshGeometry3D.Freeze();

            Brush[] brushArray = new Brush[6]
            {
                Brushes.Red,
                Brushes.Blue,
                Brushes.Yellow,
                Brushes.Orange,
                Brushes.Green,
                Brushes.White
            };

            DrawingGroup drawingGroup = new DrawingGroup();

            for(int i = 0; i < brushArray.Length ; i++)
            {
                RectangleGeometry rectangleGeometry = new RectangleGeometry(new Rect(10 * i, 0, 10, 60));

                GeometryDrawing geometryDrawing = new GeometryDrawing(brushArray[i], null, rectangleGeometry);

                drawingGroup.Children.Add(geometryDrawing);
            }

            DrawingBrush drawingBrush = new DrawingBrush(drawingGroup);

            drawingBrush.Freeze();

            GeometryModel3D geometryModel3D = new GeometryModel3D();

            geometryModel3D.Geometry = meshGeometry3D;
            geometryModel3D.Material = new DiffuseMaterial(drawingBrush);

            ModelVisual3D modelVisual3D = new ModelVisual3D();

            modelVisual3D.Content = geometryModel3D;

            viewport3D.Children.Add(modelVisual3D);

            Model3DGroup model3DGroup = new Model3DGroup();

            model3DGroup.Children.Add
            (
                new AmbientLight
                (
                    Color.FromRgb(128, 128, 128)
                )
            );

            model3DGroup.Children.Add
            (
                new DirectionalLight
                (
                    Color.FromRgb(128, 128, 128),
                    new Vector3D(2, -3, -1)
                )
            );

            modelVisual3D = new ModelVisual3D();

            modelVisual3D.Content = model3DGroup;

            viewport3D.Children.Add(modelVisual3D);

            PerspectiveCamera perspectiveCamera = new PerspectiveCamera
            (
                new Point3D(0, 0, 8),
                new Vector3D(0, 0, -1),
                new Vector3D(0, 1, 0),
                45
            );

            viewport3D.Camera = perspectiveCamera;

            AxisAngleRotation3D axisAngleRotation3D = new AxisAngleRotation3D(new Vector3D(1, 1, 0), 0);

            RotateTransform3D rotateTransform3D = new RotateTransform3D(axisAngleRotation3D);

            geometryModel3D.Transform = rotateTransform3D;

            DoubleAnimation doubleAnimation = new DoubleAnimation(360, new Duration(TimeSpan.FromSeconds(5)));

            doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            axisAngleRotation3D.BeginAnimation(AxisAngleRotation3D.AngleProperty, doubleAnimation);
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 구 메쉬 기하학 3D 구하기 - GetSphereMeshGeometry3D(centerPoint3D, radius, sliceCount, stackCount)

        /// <summary>
        /// 구 메쉬 기하학 3D 구하기
        /// </summary>
        /// <param name="centerPoint3D">중앙 포인트 3D</param>
        /// <param name="radius">반경</param>
        /// <param name="sliceCount">슬라이스 수</param>
        /// <param name="stackCount">스택 수</param>
        /// <returns>구 메쉬 기하학 3D</returns>
        MeshGeometry3D GetSphereMeshGeometry3D(Point3D centerPoint3D, double radius, int sliceCount, int stackCount)
        {
            MeshGeometry3D meshGeometry3D = new MeshGeometry3D();

            for(int stack = 0; stack <= stackCount; stack++)
            {
                double phi   = Math.PI / 2 - stack * Math.PI / stackCount;
                double y     = radius * Math.Sin(phi);
                double scale = -radius * Math.Cos(phi);

                for(int slice = 0; slice <= sliceCount; slice++)
                {
                    double theta = slice * 2 * Math.PI / sliceCount;
                    double x     = scale * Math.Sin(theta);
                    double z     = scale * Math.Cos(theta);

                    Vector3D normal = new Vector3D(x, y, z);

                    meshGeometry3D.Normals.Add(normal);

                    meshGeometry3D.Positions.Add(normal + centerPoint3D);

                    meshGeometry3D.TextureCoordinates.Add
                    (
                        new Point
                        (
                            (double)slice / sliceCount,
                            (double)stack / stackCount
                        )
                    );
                }
            }

            for(int stack = 0; stack < stackCount; stack++)
            {
                for(int slice = 0; slice < sliceCount; slice++)
                {
                    int n = sliceCount + 1;

                    if(stack != 0)
                    {
                        meshGeometry3D.TriangleIndices.Add((stack + 0) * n + slice    );
                        meshGeometry3D.TriangleIndices.Add((stack + 1) * n + slice    );
                        meshGeometry3D.TriangleIndices.Add((stack + 0) * n + slice + 1);
                    }

                    if(stack != stackCount - 1)
                    {
                        meshGeometry3D.TriangleIndices.Add((stack + 0) * n + slice + 1);
                        meshGeometry3D.TriangleIndices.Add((stack + 1) * n + slice    );
                        meshGeometry3D.TriangleIndices.Add((stack + 1) * n + slice + 1);
                    }
                }
            }

            return meshGeometry3D;
        }

        #endregion
    }
}
728x90
반응형
Posted by 사용자 icodebroker

댓글을 달아 주세요