728x90
반응형
728x170
▶ SphereModelVisual3D.cs
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;
namespace TestProject
{
/// <summary>
/// 구체 모델 비주얼 3D
/// </summary>
public class SphereModelVisual3D : ModelVisual3D
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region Field
/// <summary>
/// 재료 속성
/// </summary>
public static readonly DependencyProperty MaterialProperty = GeometryModel3D.MaterialProperty.AddOwner
(
typeof(SphereModelVisual3D),
new PropertyMetadata(MaterialPropertyChangedCallback)
);
/// <summary>
/// 후면 재료 속성
/// </summary>
public static readonly DependencyProperty BackMaterialProperty = GeometryModel3D.BackMaterialProperty.AddOwner
(
typeof(SphereModelVisual3D),
new PropertyMetadata(MaterialPropertyChangedCallback)
);
/// <summary>
/// 중심점 속성
/// </summary>
public static readonly DependencyProperty CenterPointProperty = DependencyProperty.Register
(
"CenterPoint",
typeof(Point3D),
typeof(SphereModelVisual3D),
new PropertyMetadata
(
new Point3D(),
PropertyChangedCallback
)
);
/// <summary>
/// 반경 속성
/// </summary>
public static readonly DependencyProperty RadiusProperty = DependencyProperty.Register
(
"Radius",
typeof(double),
typeof(SphereModelVisual3D),
new PropertyMetadata
(
1.0,
PropertyChangedCallback
)
);
/// <summary>
/// 슬라이스 수 속성
/// </summary>
public static readonly DependencyProperty SliceCountProperty = DependencyProperty.Register
(
"SliceCount",
typeof(int),
typeof(SphereModelVisual3D),
new PropertyMetadata
(
32,
PropertyChangedCallback
)
);
/// <summary>
/// 스택 수 속성
/// </summary>
public static readonly DependencyProperty StackCountProperty = DependencyProperty.Register
(
"StackCount",
typeof(int),
typeof(SphereModelVisual3D),
new PropertyMetadata
(
16,
PropertyChangedCallback
)
);
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Instance
//////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 도형 모델 3D
/// </summary>
private GeometryModel3D geometryModel3D;
/// <summary>
/// 메쉬 도형 3D
/// </summary>
private MeshGeometry3D meshGeometry3D;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 재료 - Material
/// <summary>
/// 재료
/// </summary>
public Material Material
{
set
{
SetValue(MaterialProperty, value);
}
get
{
return (Material)GetValue(MaterialProperty);
}
}
#endregion
#region 후면 재료 - BackMaterial
/// <summary>
/// 후면 재료
/// </summary>
public Material BackMaterial
{
set
{
SetValue(BackMaterialProperty, value);
}
get
{
return (Material)GetValue(BackMaterialProperty);
}
}
#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
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - SphereModelVisual3D()
/// <summary>
/// 생성자
/// </summary>
public SphereModelVisual3D()
{
this.geometryModel3D = new GeometryModel3D();
this.meshGeometry3D = new MeshGeometry3D();
this.geometryModel3D.Geometry = this.meshGeometry3D;
Content = this.geometryModel3D;
PropertyChanged(new DependencyPropertyChangedEventArgs());
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region 재료 속성 변경시 콜백 처리하기 - MaterialPropertyChangedCallback(d, e)
/// <summary>
/// 재료 속성 변경시 콜백 처리하기
/// </summary>
/// <param name="d">의존 객체</param>
/// <param name="e">이벤트 인자</param>
private static void MaterialPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as SphereModelVisual3D).MaterialPropertyChanged(e);
}
#endregion
#region 속성 변경시 콜백 처리하기 - PropertyChangedCallback(d, e)
/// <summary>
/// 속성 변경시 콜백 처리하기
/// </summary>
/// <param name="d">의존 객체</param>
/// <param name="e">이벤트 인자</param>
private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as SphereModelVisual3D).PropertyChanged(e);
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Instance
//////////////////////////////////////////////////////////////////////////////// Private
#region 재료 속성 변경시 처리하기 - MaterialPropertyChanged(e)
/// <summary>
/// 재료 속성 변경시 처리하기
/// </summary>
/// <param name="e">이벤트 인자</param>
private void MaterialPropertyChanged(DependencyPropertyChangedEventArgs e)
{
if(e.Property == MaterialProperty)
{
this.geometryModel3D.Material = e.NewValue as Material;
}
else if(e.Property == BackMaterialProperty)
{
this.geometryModel3D.BackMaterial = e.NewValue as Material;
}
}
#endregion
#region 속성 변경시 처리하기 - PropertyChanged(e)
/// <summary>
/// 속성 변경시 처리하기
/// </summary>
/// <param name="e">이벤트 인자</param>
private void PropertyChanged(DependencyPropertyChangedEventArgs e)
{
Point3DCollection vertexCollection = this.meshGeometry3D.Positions;
Vector3DCollection normalCollection = this.meshGeometry3D.Normals;
Int32Collection indexCollection = this.meshGeometry3D.TriangleIndices;
PointCollection textureCollection = this.meshGeometry3D.TextureCoordinates;
this.meshGeometry3D.Positions = null;
this.meshGeometry3D.Normals = null;
this.meshGeometry3D.TriangleIndices = null;
this.meshGeometry3D.TextureCoordinates = null;
vertexCollection.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 normal = new Vector3D(x, y, z);
normalCollection.Add(normal);
vertexCollection.Add(normal + 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);
}
}
}
this.meshGeometry3D.TextureCoordinates = textureCollection;
this.meshGeometry3D.TriangleIndices = indexCollection;
this.meshGeometry3D.Normals = normalCollection;
this.meshGeometry3D.Positions = vertexCollection;
}
#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="ModelVisual3D 클래스 상속하기"
FontFamily="나눔고딕코딩"
FontSize="16">
<Viewport3D>
<local:SphereModelVisual3D
SliceCount="72"
StackCount="36">
<local:SphereModelVisual3D.Material>
<DiffuseMaterial Brush="RoyalBlue" />
</local:SphereModelVisual3D.Material>
<local:SphereModelVisual3D.Transform>
<ScaleTransform3D x:Name="scaleTransform3D" />
</local:SphereModelVisual3D.Transform>
</local:SphereModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<AmbientLight Color="#404040" />
<DirectionalLight
Color="#C0C0C0"
Direction="2 -3 -1" />
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<Viewport3D.Camera>
<PerspectiveCamera
Position="4 4 4"
LookDirection="-1 -1 -1"
UpDirection="0 1 0"
FieldOfView="45" />
</Viewport3D.Camera>
</Viewport3D>
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard TargetName="scaleTransform3D">
<DoubleAnimation
Storyboard.TargetProperty="ScaleX"
From="0.5"
To="2"
Duration="0:0:3"
AutoReverse="True"
RepeatBehavior="Forever" />
<DoubleAnimation
Storyboard.TargetProperty="ScaleY"
From="0.5"
To="2"
Duration="0:0:5"
AutoReverse="True"
RepeatBehavior="Forever" />
<DoubleAnimation
Storyboard.TargetProperty="ScaleZ"
From="0.5"
To="2"
Duration="0:0:7"
AutoReverse="True"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
</Window>
728x90
반응형
그리드형(광고전용)
'C# > WPF' 카테고리의 다른 글
[C#/WPF] WindowInteropHelper 클래스 : Handle 속성을 사용해 윈도우 핸들 구하기 (0) | 2020.05.20 |
---|---|
[C#/WPF] Application 클래스 : Shutdown 메소드를 사용해 애플리케이션 종료하기 (0) | 2020.02.29 |
[C#/WPF] MeshGeometry3D 클래스 : 구체 애니메이션 만들기 (0) | 2019.09.08 |
[C#/WPF] NAUDIO 라이브러리를 사용해 음악 재생하기 (0) | 2019.09.08 |
[C#/WPF] MeshGeometry3D 클래스 : 수레바퀴 만들기 (0) | 2019.09.02 |
[C#/WPF] object 객체에서 XAML 구하기 (0) | 2019.09.01 |
[C#/WPF] MeshGeometry3D 클래스 : 리소스 사용하기 (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 |
댓글을 달아 주세요