728x90
반응형
728x170
▶ 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
}
}
728x90
▶ 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 버전까지만 에러없이 실행된다.
728x90
반응형
그리드형(광고전용)
'C# > WPF' 카테고리의 다른 글
[C#/WPF] MeshGeometry3D 클래스 : 구체 애니메이션 만들기 (0) | 2019.09.08 |
---|---|
[C#/WPF] NAUDIO 라이브러리를 사용해 음악 재생하기 (0) | 2019.09.08 |
[C#/WPF] MeshGeometry3D 클래스 : 수레바퀴 만들기 (0) | 2019.09.02 |
[C#/WPF] ModelVisual3D 클래스 상속하기 (0) | 2019.09.01 |
[C#/WPF] object 객체에서 XAML 구하기 (0) | 2019.09.01 |
[C#/WPF] MeshGeometry3D 클래스 : 리소스 사용하기 (0) | 2019.08.28 |
[C#/WPF] MeshGeometry3D 클래스 : 삼각측량법을 사용해 비치볼 만들기 (0) | 2019.08.27 |
[C#/WPF] SpecularMaterial 엘리먼트 사용하기 (0) | 2019.08.26 |
[C#/WPF] SpecularMaterial 엘리먼트 사용하기 (0) | 2019.08.26 |
[C#/WPF] DrawingBrush 엘리먼트 사용하기 (0) | 2019.08.26 |
댓글을 달아 주세요