■ MeshGeometry3D 클래스 : 리소스 사용하기

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


TestProject.zip


SphereMeshGenerator.cs

 

 

using System;

using System.Windows;

using System.Windows.Markup;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Media.Media3D;

 

namespace TestProject

{

    /// <summary>

    /// 구체 메쉬 생성자

    /// </summary>

    [RuntimeNameProperty("Name")]

    public class SphereMeshGenerator : Animatable

    {

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

        ////////////////////////////////////////////////////////////////////////////////////////// Static

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

 

        #region Field

 

        /// <summary>

        /// 도형 키

        /// </summary>

        private static readonly DependencyPropertyKey GeometryKey = DependencyProperty.RegisterReadOnly

        (

            "Geometry",

            typeof(MeshGeometry3D),

            typeof(SphereMeshGenerator),

            new PropertyMetadata(new MeshGeometry3D())

        );

 

        #endregion

 

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

 

        #region Field

 

        /// <summary>

        /// 명칭 속성

        /// </summary>

        public static readonly DependencyProperty NameProperty = DependencyProperty.Register

        (

            "Name",

            typeof(string),

            typeof(SphereMeshGenerator)

        );

 

        /// <summary>

        /// 중심점 속성

        /// </summary>

        public static readonly DependencyProperty CenterPointProperty = DependencyProperty.Register

        (

            "CenterPoint",

            typeof(Point3D),

            typeof(SphereMeshGenerator),

            new PropertyMetadata(new Point3D(), PropertyChangedCallback)

        );

 

        /// <summary>

        /// 반경 속성

        /// </summary>

        public static readonly DependencyProperty RadiusProperty = DependencyProperty.Register

        (

            "Radius",

            typeof(double),

            typeof(SphereMeshGenerator),

            new PropertyMetadata(1.0, PropertyChangedCallback)

        );

 

        /// <summary>

        /// 슬라이스 수 속성

        /// </summary>

        public static readonly DependencyProperty SliceCountProperty = DependencyProperty.Register

        (

            "SliceCount",

            typeof(int),

            typeof(SphereMeshGenerator),

            new PropertyMetadata(32, PropertyChangedCallback)

        );

 

        /// <summary>

        /// 스택 수 속성

        /// </summary>

        public static readonly DependencyProperty StackCountProperty = DependencyProperty.Register

        (

            "StackCount",

            typeof(int),

            typeof(SphereMeshGenerator),

            new PropertyMetadata(16, PropertyChangedCallback)

        );

 

        /// <summary>

        /// 도형 속성

        /// </summary>

        public static readonly DependencyProperty GeometryProperty = GeometryKey.DependencyProperty;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

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

 

        #region 명칭 - Name

 

        /// <summary>

        /// 명칭

        /// </summary>

        public string Name

        {

            set

            {

                SetValue(NameProperty, value);

            }

            get

            {

                return (string)GetValue(NameProperty);

            }

        }

 

        #endregion

        #region 중심점 - CenterPoint

 

        /// <summary>

        /// 중심점

        /// </summary>

        public Point3D CenterPoint

        {

            set

            {

                SetValue(CenterPointProperty, value);

            }

            get

            {

                return (Point3D)GetValue(CenterPointProperty);

            }

        }

 

        #endregion

        #region 반경 - Radius

 

        /// <summary>

        /// 반경

        /// </summary>

        public double Radius

        {

            set

            {

                SetValue(RadiusProperty, value);

            }

            get

            {

                return (double)GetValue(RadiusProperty);

            }

        }

 

        #endregion

        #region 슬라이스 수 - SliceCount

 

        /// <summary>

        /// 슬라이스 수

        /// </summary>

        public int SliceCount

        {

            set

            {

                SetValue(SliceCountProperty, value);

            }

            get

            {

                return (int)GetValue(SliceCountProperty);

            }

        }

 

        #endregion

        #region 스택 수 - StackCount

 

        /// <summary>

        /// 스택 수

        /// </summary>

        public int StackCount

        {

            set

            {

                SetValue(StackCountProperty, value);

            }

            get

            {

                return (int)GetValue(StackCountProperty);

            }

        }

 

        #endregion

        #region 도형 - Geometry

 

        /// <summary>

        /// 도형

        /// </summary>

        public MeshGeometry3D Geometry

        {

            protected set

            {

                SetValue(GeometryKey, value);

            }

            get

            {

                return (MeshGeometry3D)GetValue(GeometryProperty);

            }

        }

 

        #endregion

 

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

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

 

        #region 생성자 - SphereMeshGenerator()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public SphereMeshGenerator()

        {

            Geometry = Geometry.Clone();

 

            PropertyChanged(new DependencyPropertyChangedEventArgs());

        }

 

        #endregion

 

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

        ////////////////////////////////////////////////////////////////////////////////////////// Static

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

 

        #region 속성 변경시 콜백 처리하기 - PropertyChangedCallback(d, e)

 

        /// <summary>

        /// 속성 변경시 콜백 처리하기

        /// </summary>

        /// <param name="d">의존 객체</param>

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

        private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            (d as SphereMeshGenerator).PropertyChanged(e);

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

        //////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 인스턴스 생성하기 (CORE) - CreateInstanceCore()

 

        /// <summary>

        /// 인스턴스 생성하기 (CORE)

        /// </summary>

        /// <returns>Freezable 객체</returns>

        protected override Freezable CreateInstanceCore()

        {

            return new SphereMeshGenerator();

        }

 

        #endregion

 

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

 

        #region 속성 변경시 처리하기 - PropertyChanged(e)

 

        /// <summary>

        /// 속성 변경시 처리하기

        /// </summary>

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

        private void PropertyChanged(DependencyPropertyChangedEventArgs e)

        {

            MeshGeometry3D mesh = Geometry;

 

            Point3DCollection  positionCollection = mesh.Positions;

            Vector3DCollection normalCollection   = mesh.Normals;

            Int32Collection    indexCollection    = mesh.TriangleIndices;

            PointCollection    textureCollection  = mesh.TextureCoordinates;

 

            mesh.Positions          = null;

            mesh.Normals            = null;

            mesh.TriangleIndices    = null;

            mesh.TextureCoordinates = null;

 

            positionCollection.Clear();

            normalCollection.Clear();

            indexCollection.Clear();

            textureCollection.Clear();

 

            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 normalVector = new Vector3D(x, y, z);

 

                    normalCollection.Add(normalVector);

 

                    positionCollection.Add(normalVector + CenterPoint);

 

                    textureCollection.Add(new Point((double)slice / SliceCount, (double)stack / StackCount));

                }

            }

 

            for(int stack = 0; stack < StackCount; stack++)

            {

                int top    = (stack + 0) * (SliceCount + 1);

                int bottom = (stack + 1) * (SliceCount + 1);

 

                for(int slice = 0; slice < SliceCount; slice++)

                {

                    if(stack != 0)

                    {

                        indexCollection.Add(top    + slice    );

                        indexCollection.Add(bottom + slice    );

                        indexCollection.Add(top    + slice + 1);

                    }

 

                    if(stack != StackCount - 1)

                    {

                        indexCollection.Add(top    + slice + 1);

                        indexCollection.Add(bottom + slice    );

                        indexCollection.Add(bottom + slice + 1);

                    }

                }

            }

 

            mesh.TextureCoordinates = textureCollection;

            mesh.TriangleIndices    = indexCollection;

            mesh.Normals            = normalCollection;

            mesh.Positions          = positionCollection;

        }

 

        #endregion

    }

}

 

 

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"

    xmlns:local="clr-namespace:TestProject"

    Width="800"

    Height="600"

    Title="MeshGeometry3D 클래스 : 리소스 사용하기"

    FontFamily="나눔고딕코딩"

    FontSize="16">

    <Window.Resources>

        <local:SphereMeshGenerator x:Key="SphereMeshGeneratorKey1"

            x:Name="sphereMeshGenerator1"

            CenterPoint="-0.25 0 0" />

        <local:SphereMeshGenerator x:Key="SphereMeshGeneratorKey2"

            x:Name="sphereMeshGenerator2"

            CenterPoint="0.25 0 0" />

    </Window.Resources>

    <Viewport3D>

        <ModelVisual3D>

            <ModelVisual3D.Content>

                <Model3DGroup>

                    <GeometryModel3D Geometry="{Binding Source={StaticResource SphereMeshGeneratorKey1}, Path=Geometry}">

                        <GeometryModel3D.Material>

                            <DiffuseMaterial Brush="RoyalBlue" />

                        </GeometryModel3D.Material>

                    </GeometryModel3D>

                    <GeometryModel3D Geometry="{Binding Source={StaticResource SphereMeshGeneratorKey2}, Path=Geometry}">

                        <GeometryModel3D.Material>

                            <DiffuseMaterial Brush="Red" />

                        </GeometryModel3D.Material>

                    </GeometryModel3D>

                    <AmbientLight Color="#404040" />

                    <DirectionalLight

                        Color="#c0c0c0"

                        Direction="2 -3 -1" />

                </Model3DGroup>

            </ModelVisual3D.Content>

        </ModelVisual3D>

        <Viewport3D.Camera>

            <PerspectiveCamera

                Position="0 0 4"

                LookDirection="0 0 -1"

                UpDirection="0 1 0"

                FieldOfView="45" />

        </Viewport3D.Camera>

    </Viewport3D>

    <Window.Triggers>

        <EventTrigger RoutedEvent="Window.Loaded">

            <BeginStoryboard>

                <Storyboard>

                    <DoubleAnimation

                        Storyboard.TargetName="sphereMeshGenerator1"

                        Storyboard.TargetProperty="Radius"

                        From="0"

                        To="0.5"

                        Duration="0:0:3"

                        AutoReverse="True"

                        RepeatBehavior="Forever" />

                    <DoubleAnimation

                        Storyboard.TargetName="sphereMeshGenerator2"

                        Storyboard.TargetProperty="Radius"

                        From="0.5"

                        To="0"

                        Duration="0:0:3"

                        AutoReverse="True"

                        RepeatBehavior="Forever" />

                </Storyboard>

            </BeginStoryboard>

        </EventTrigger>

    </Window.Triggers>

</Window>

 

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

※ 리소스에서 Name 또는 x:Name 속성의 사용이 닷넷 프레임워크 3.5 버전까지만 에러없이 실행된다.

Posted by 사용자 icodebroker

댓글을 달아 주세요