3차원 그래픽 개요
Windows Presentation Foundation (WPF)의 3-D 기능을 사용하여 개발자는 태그 및 프로시저 코드 모두를 통해 3차원 그래픽을 그리고 변환하며 이러한 그래픽에 애니메이션 효과를 줄 수 있습니다. 개발자는 2-D 및 3-D 그래픽을 결합하여 다양한 컨트롤을 만들거나, 복잡한 데이터 표시를 제공하거나, 응용 프로그램 인터페이스의 사용자 경험을 개선할 수 있습니다. WPF의 3-D 지원은 모든 기능을 갖춘 게임 개발 플랫폼을 제공하기 위한 것은 아닙니다. 이 항목에서는 WPF 그래픽 시스템의 3-D 기능에 대해 간략하게 설명합니다.
이 항목에는 다음 단원이 포함되어 있습니다.
- 2차원 컨테이너의 3차원
- 3차원 좌표 공간
- 카메라 및 프로젝션
- 모델 및 망상 조직 기본 도형
- 모델에 재질 적용
- 장면 비추기
- 모델 변환
- 모델에 애니메이션 효과 주기
- 창에 3차원 콘텐츠 추가
- 관련 항목
2차원 컨테이너의 3차원
WPF의 3-D 그래픽 콘텐츠는 2차원 요소 구조에 참여할 수 있는 요소인 Viewport3D에 캡슐화됩니다. 그래픽 시스템에서는 Viewport3D를 WPF의 다른 많은 요소처럼 2차원 시각적 요소로 처리합니다. Viewport3D는 3차원 장면을 보여 주는 창(뷰포트)으로 작동합니다. 보다 정확히 말해 이는 3-D 장면이 나타나는 표면입니다.
기존 2-D 응용 프로그램에서는 표나 캔버스와 같은 다른 컨테이너 요소를 사용하듯이 Viewport3D를 사용합니다. Viewport3D와 다른 2-D 그리기 개체를 같은 장면 그래프에서 사용할 수 있지만 Viewport3D 내에서 2-D 및 3-D 개체를 상호 침투할 수는 없습니다. 이 항목에서는 Viewport3D 내에서 3-D 그래픽을 그리는 방법에 중점을 두어 설명합니다.
3차원 좌표 공간
2-D 그래픽의 WPF 좌표계 원점은 렌더링 영역(일반적으로 화면)의 왼쪽 위에서 시작됩니다. 2-D 시스템에서 x축의 양수 값은 오른쪽으로 진행되고 y축의 양수 값은 아래로 진행됩니다. 그러나 3-D 좌표계에서 원점은 렌더링 영역의 중앙에서 시작됩니다. 여기서 x축의 양수 값은 오른쪽으로 진행되고 y축의 양수 값은 위로 진행되며 z축의 양수 값은 원점에서 뷰어를 향해 바깥쪽으로 진행됩니다.
기존의 2차원 및 3차원 좌표계 표현
이러한 축으로 정의되는 공간은 WPF의 3-D 개체에 대한 고정된 참조 프레임입니다. 이 공간에서 모델을 빌드하고 이를 보기 위한 조명과 카메라를 만들 때는 변환 적용 시 각 모델에 대해 만드는 로컬 참조 프레임을 이 고정된 참조 프레임 또는 "전역 공간"과 구분하면 유용합니다. 또한 전역 공간의 개체는 조명 및 카메라 설정에 따라 완전히 다르게 보이거나 전혀 보이지 않을 수 있지만 카메라의 위치는 전역 공간에서 개체의 위치를 변경하지 않습니다.
카메라 및 프로젝션
2-D에서 작업을 수행하는 개발자는 2차원 화면에서 그리기 기본 도형을 배치하는 작업에 익숙할 것입니다. 3-D 장면을 만들 경우 실제로는 3-D 개체의 2-D 표현을 만드는 것임을 기억해야 합니다. 3-D 장면은 보는 이의 시점에 따라 다르게 보이므로 시점을 지정해야 합니다. Camera 클래스를 사용하면 3-D 장면에 대한 이러한 시점을 지정할 수 있습니다.
2-D 표면에서 3-D 장면이 표시되는 방법은 장면을 보기 표면에 대한 프로젝션으로 기술하여 이해할 수도 있습니다. ProjectionCamera를 사용하면 다른 프로젝션 및 해당 속성을 지정하여 보는 이가 3-D 모델을 보는 방법을 변경할 수 있습니다. PerspectiveCamera는 장면에 원급법을 적용하는 프로젝션을 지정합니다. 즉, PerspectiveCamera는 소실점 원근감을 제공합니다. 장면 좌표 공간에서의 카메라 위치, 카메라의 방향 및 뷰 필드, 장면의 "위쪽" 방향을 정의하는 벡터를 지정할 수 있습니다. 다음 다이어그램에서는 PerspectiveCamera의 프로젝션을 보여 줍니다.
ProjectionCamera의 NearPlaneDistance 및 FarPlaneDistance 속성은 카메라 프로젝션의 범위를 제한합니다. 카메라는 장면의 어느 위치에든 배치될 수 있으므로 카메라가 모델 내 또는 모델에 매우 가깝게 배치될 수 있으며 이로 인해 개체를 제대로 구별하기가 어려워집니다. NearPlaneDistance를 사용하면 개체를 그릴 수 없는 카메라로부터의 최소 거리를 지정할 수 있습니다. 반대로 FarPlaneDistance를 사용하면 개체를 그릴 수 없는 카메라로부터의 거리를 지정하여 너무 멀어서 인식할 수 없는 개체가 장면에 포함되지 않도록 만들 수 있습니다.
카메라 위치
OrthographicCamera는 3-D 모델의 직교 프로젝션을 2-D 시각적 표면으로 지정합니다. 다른 카메라와 마찬가지로 이는 위치, 보기 방향 및 "위쪽" 방향을 지정합니다. 그러나 PerspectiveCamera와는 달리 OrthographicCamera는 원근 포어쇼트닝(foreshortening)을 포함하지 않는 프로젝션을 설명합니다. 즉, OrthographicCamera는 면이 카메라의 특정 지점에서 만나는 것이 아니라 평행한 보기 상자를 기술합니다. 다음 그림에서는 동일한 모델을 PerspectiveCamera 및 OrthographicCamera를 사용하여 보여 줍니다.
원근 및 직교 프로젝션
다음 코드에서는 일반적인 카메라 설정을 보여 줍니다.
' Defines the camera used to view the 3D object. In order to view the 3D object,
' the camera must be positioned and pointed such that the object is within view
' of the camera.
Dim myPCamera As New PerspectiveCamera()
' Specify where in the 3D scene the camera is.
myPCamera.Position = New Point3D(0, 0, 2)
' Specify the direction that the camera is pointing.
myPCamera.LookDirection = New Vector3D(0, 0, -1)
' Define camera's horizontal field of view in degrees.
myPCamera.FieldOfView = 60
' Asign the camera to the viewport
myViewport3D.Camera = myPCamera
// Defines the camera used to view the 3D object. In order to view the 3D object,
// the camera must be positioned and pointed such that the object is within view
// of the camera.
PerspectiveCamera myPCamera = new PerspectiveCamera();
// Specify where in the 3D scene the camera is.
myPCamera.Position = new Point3D(0, 0, 2);
// Specify the direction that the camera is pointing.
myPCamera.LookDirection = new Vector3D(0, 0, -1);
// Define camera's horizontal field of view in degrees.
myPCamera.FieldOfView = 60;
// Asign the camera to the viewport
myViewport3D.Camera = myPCamera;
모델 및 망상 조직 기본 도형
Model3D는 일반 3-D 개체를 나타내는 추상 기본 클래스입니다. 3-D 장면을 빌드하려면 볼 개체와 Model3D에서 파생된 장면 그래프를 구성하는 개체가 있어야 합니다. 현재 WPF에서는 GeometryModel3D를 사용하여 기하 도형을 모델링할 수 있습니다. 이 모델의 Geometry 속성은 망상 조직 기본 도형을 사용합니다.
모델을 빌드하려면 먼저 기본 도형 또는 망상 조직을 빌드합니다. 3-D 기본 도형은 단일 3-D 엔터티를 구성하는 꼭지점 컬렉션입니다. 대부분의 3-D 시스템은 가장 간단한 닫힌 그림, 즉 세 개의 꼭지점으로 정의되는 삼각형을 기반으로 모델링되는 기본 요소를 제공합니다. 삼각형의 세 점은 같은 평면에 있으므로 망상 조직이라는 보다 복잡한 도형을 모델링하기 위해 계속해서 삼각형을 추가할 수 있습니다.
WPF 3-D 시스템은 현재 모든 기하 도형을 지정할 수 있는 MeshGeometry3D 클래스를 제공합니다. 구 및 입방체와 같은 미리 정의된 3-D 기본 도형은 현재 지원되지 않습니다. 먼저 삼각형의 꼭지점 목록을 해당 Positions 속성으로 지정하여 MeshGeometry3D를 만듭니다. 각 꼭지점은 Point3D로 지정됩니다. Extensible Application Markup Language (XAML)에서는 이 속성을 각 꼭지점의 좌표를 나타내는 세 숫자가 그룹화된 목록으로 지정합니다. 해당 기하 도형에 따라 망상 조직은 여러 개의 삼각형으로 구성될 수 있고 그 중 일부는 같은 모퉁이(꼭지점)를 공유할 수 있습니다. 망상 조직을 올바르게 그리려면 어떤 삼각형에 어떤 꼭지점이 공유되는지에 대한 정보를 WPF에 제공해야 합니다. 이 정보는 TriangleIndices 속성을 통해 삼각형 인덱스 목록을 지정하여 제공합니다. 이 목록은 Positions 목록에 지정된 점이 삼각형을 결정하는 순서를 지정합니다.
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="-1 -1 0 1 -1 0 -1 1 0 1 1 0"
Normals="0 0 1 0 0 1 0 0 1 0 0 1"
TextureCoordinates="0 1 1 1 0 0 1 0 "
TriangleIndices="0 1 2 1 3 2" />
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<!-- Translate the plane. -->
<GeometryModel3D.Transform>
<TranslateTransform3D
OffsetX="2" OffsetY="0" OffsetZ="-1" >
</TranslateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
앞의 예에서 Positions 목록은 8개의 꼭지점을 지정하여 입방형 망상 조직을 정의합니다. TriangleIndices 속성은 인덱스 세 개로 구성된 12개 그룹 목록을 지정합니다. 목록의 각 숫자는 Positions 목록으로의 오프셋을 나타냅니다. 예를 들어 Positions 목록으로 지정된 첫 세 개의 꼭지점은 (1,1,0), (0,1,0), (0,0,0)입니다. TriangleIndices 목록으로 지정된 첫 세 개의 인덱스는 0, 2, 1이며 각각 Positions 목록의 첫 번째, 세 번째, 두 번째 점에 해당합니다. 그 결과 입방형 모델을 구성하는 첫 번째 삼각형은 (1,1,0)에서 (0,1,0) 및 (0,0,0)으로 이어지고 나머지 11개의 삼각형도 이와 비슷하게 결정됩니다.
Normals 및 TextureCoordinates 속성 값을 지정하여 계속해서 모델을 정의할 수 있습니다. 모델의 표면을 렌더링하려면 그래픽 시스템에 임의의 삼각형에서 해당 표면이 어느 방향을 바라보고 있는지에 대한 정보가 필요합니다. 그래픽 시스템은 이 정보를 사용하여 모델에 대한 조명 계산을 수행할 수 있습니다. 즉, 광원쪽 표면이 광원 반대쪽 표면보다 밝게 나타납니다. WPF에서 위치 좌표를 사용하여 기본 법선 벡터를 결정할 수 있지만 다른 법선 벡터를 지정하여 곡선 표면에 근접한 모양을 만들 수도 있습니다.
TextureCoordinates 속성은 질감이 그려지는 방법을 결정하는 좌표를 망상 조직의 꼭지점에 매핑하는 방법을 그래픽 시스템에 알려주는 Point 컬렉션을 지정합니다. TextureCoordinates는 0과 1을 포함하는 사이 값으로 지정됩니다. Normals 속성과 마찬가지로 그래픽 시스템은 기본 질감 좌표를 계산할 수 있지만 다른 질감 좌표를 선택하여 반복 패턴의 일부를 포함하는 등의 질감 매핑을 제어할 수도 있습니다. 질감 좌표에 대한 자세한 내용은 다음 항목 또는 관리되는 Direct3D SDK를 참조하십시오.
다음 예제에서는 입방형 모델의 한 면을 프로시저 코드로 만드는 방법을 보여 줍니다. 입방체 전체를 단일 GeometryModel3D로 그릴 수 있지만 이 예제에서는 나중에 각 면에 별도의 질감을 적용하기 위해 입방체 면을 고유한 모델로 그립니다.
Private side1Plane As New MeshGeometry3D()
MeshGeometry3D side1Plane = new MeshGeometry3D();
side1Plane.Positions.Add(New Point3D(-0.5, -0.5, -0.5))
side1Plane.Positions.Add(New Point3D(-0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, 0.5, -0.5))
side1Plane.Positions.Add(New Point3D(0.5, -0.5, -0.5))
side1Plane.Positions.Add(New Point3D(-0.5, -0.5, -0.5))
side1Plane.TriangleIndices.Add(0)
side1Plane.TriangleIndices.Add(1)
side1Plane.TriangleIndices.Add(2)
side1Plane.TriangleIndices.Add(3)
side1Plane.TriangleIndices.Add(4)
side1Plane.TriangleIndices.Add(5)
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.Normals.Add(New Vector3D(0, 0, -1))
side1Plane.TextureCoordinates.Add(New Point(1, 0))
side1Plane.TextureCoordinates.Add(New Point(1, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 1))
side1Plane.TextureCoordinates.Add(New Point(0, 0))
side1Plane.TextureCoordinates.Add(New Point(1, 0))
side1Plane.Positions.Add(new Point3D(-0.5, -0.5, -0.5));
side1Plane.Positions.Add(new Point3D(-0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, 0.5, -0.5));
side1Plane.Positions.Add(new Point3D(0.5, -0.5, -0.5));
side1Plane.Positions.Add(new Point3D(-0.5, -0.5, -0.5));
side1Plane.TriangleIndices.Add(0);
side1Plane.TriangleIndices.Add(1);
side1Plane.TriangleIndices.Add(2);
side1Plane.TriangleIndices.Add(3);
side1Plane.TriangleIndices.Add(4);
side1Plane.TriangleIndices.Add(5);
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.Normals.Add(new Vector3D(0, 0, -1));
side1Plane.TextureCoordinates.Add(new Point(1, 0));
side1Plane.TextureCoordinates.Add(new Point(1, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 1));
side1Plane.TextureCoordinates.Add(new Point(0, 0));
side1Plane.TextureCoordinates.Add(new Point(1, 0));
모델에 재질 적용
망상 조직이 3차원 개체로 보이도록 만들려면 조명을 비추고 카메라로 프로젝션할 수 있도록 해당 꼭지점과 삼각형으로 정의된 표면에 질감을 적용해야 합니다. 2-D에서는 Brush 클래스를 사용하여 색, 패턴, 그라데이션 또는 기타 시각적 콘텐츠를 화면 영역에 적용합니다. 그러나 3-D 개체의 모양은 이 개체에 적용된 색 또는 패턴뿐만 아니라 모델에 조명을 비춘 결과로 결정됩니다. 실제 개체는 표면의 특성에 따라 빛을 다르게 반사합니다. 광택이 나거나 빛나는 표면은 거칠거나 윤기 없는 표면과 다르게 보이며 어떤 개체는 빛을 흡수하는 것처럼 보이는 반면 다른 개체는 빛이 납니다. 2-D 개체에 적용할 수 있는 것과 같은 브러시를 모두 3-D 개체에 적용할 수 있지만 직접 적용할 수는 없습니다.
모델의 표면 특성을 정의하기 위해 WPF에서는 Material 추상 클래스를 사용합니다. Material의 실제적인 서브클래스는 모델 표면의 일부 모양 특성을 결정하며 이들 각각은 SolidColorBrush, TileBrush 또는 VisualBrush를 전달할 수 있는 Brush 속성도 제공합니다.
DiffuseMaterial은 확산 조명이 적용된 것처럼 브러시가 모델에 적용되도록 지정합니다. DiffuseMaterial을 사용하면 브러시를 2-D 모델에 직접 사용하는 것과 가장 비슷한 효과를 내며 모델의 표면은 빛나는 것처럼 빛을 반사하지 않습니다.
SpecularMaterial은 모델의 표면이 하이라이트를 반사할 수 있는 딱딱하거나 빛나는 표면인 것처럼 브러시가 모델에 적용되도록 지정합니다. SpecularPower 속성 값을 지정하여 질감에 이러한 반사 특성 또는 "빛나는 효과"가 표현되는 정도를 설정할 수 있습니다.
EmissiveMaterial을 사용하면 모델이 브러시 색과 동일한 조명을 내보내는 것처럼 질감이 적용되도록 지정할 수 있습니다. 이로 인해 모델이 조명으로 변경되는 것은 아니며 모델은 DiffuseMaterial 또는 SpecularMaterial을 사용하여 질감을 표현할 때와는 다른 방식으로 그림자 지정에 참여합니다.
성능 개선을 위해 GeometryModel3D의 뒷면(카메라에서 볼 때 모델의 반대편에 있어 시야에 들어오지 않는 면)은 장면에서 컬링됩니다. 평면과 같이 모델의 뒷면에 적용할 Material을 지정하려면 모델의 BackMaterial 속성을 설정합니다.
빛이 나거나 반사되는 효과와 같은 일부 표면 특성을 얻으려면 모델에 여러 개의 서로 다른 브러시를 연속으로 적용해야 할 수 있습니다. MaterialGroup 클래스를 사용하여 여러 재질을 적용하고 다시 사용할 수 있습니다. MaterialGroup의 자식이 맨 먼저 적용되어 여러 렌더링 패스에서 지속됩니다.
다음 코드 예제에서는 브러시로 그리기 및 단색을 3-D 모델에 적용하는 방법을 보여 줍니다.
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<DrawingBrush x:Key="patternBrush" Viewport="0,0,0.1,0.1" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Geometry="M0,0.1 L0.1,0 1,0.9, 0.9,1z"
Brush="Gray" />
<GeometryDrawing Geometry="M0.9,0 L1,0.1 0.1,1 0,0.9z"
Brush="Gray" />
<GeometryDrawing Geometry="M0.25,0.25 L0.5,0.125 0.75,0.25 0.5,0.5z"
Brush="#FFFF00" />
<GeometryDrawing Geometry="M0.25,0.75 L0.5,0.875 0.75,0.75 0.5,0.5z"
Brush="Black" />
<GeometryDrawing Geometry="M0.25,0.75 L0.125,0.5 0.25,0.25 0.5,0.5z"
Brush="#FF0000" />
<GeometryDrawing Geometry="M0.75,0.25 L0.875,0.5 0.75,0.75 0.5,0.5z"
Brush="MediumBlue" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
Dim side5Material As New DiffuseMaterial(CType(Application.Current.Resources("patternBrush"), Brush))
DiffuseMaterial side5Material = new DiffuseMaterial((Brush)Application.Current.Resources["patternBrush"]);
장면 비추기
3-D 그래픽의 조명은 실제 조명의 역할을 합니다. 즉, 표면이 보이도록 만듭니다. 보다 정확히 말해 조명은 프로젝션에 포함될 장면의 부분을 결정합니다. WPF의 조명 개체는 다양한 조명 및 그림자 효과를 만들며 다양한 실제 조명의 동작을 기반으로 모델링됩니다. 장면에 하나 이상의 조명을 포함하지 않으면 모델이 보이지 않습니다.
다음 조명은 기본 클래스 Light에서 파생된 것입니다.
AmbientLight: 위치나 방향에 관계없이 모든 개체를 균등하게 비추는 앰비언트 조명을 제공합니다.
DirectionalLight: 광원이 멀리 떨어져 있는 것처럼 비춥니다. 방향성 조명은 Direction이 Vector3D로 지정되지만 위치는 지정되지 않습니다.
PointLight: 광원이 가까이 있는 것처럼 비춥니다. 점 조명은 지정된 위치가 있으며 해당 위치에서 조명을 비춥니다. 장면의 개체는 조명과 관련된 해당 위치 및 거리에 따라 비춰집니다. PointLightBase는 모델에 조명이 비춰지는 최대 거리를 결정하는 Range 속성을 노출합니다. 점 조명은 거리에 따라 조명의 강도가 감소되는 방식을 결정하는 감쇠 속성도 노출합니다. 조명 감쇠에 대해 상수, 선형 또는 정방형 보간을 지정할 수 있습니다.
SpotLight: PointLight에서 상속합니다. 스폿 조명은 점 조명과 유사하게 비추며 위치와 방향이 모두 지정됩니다. 스폿 조명은 InnerConeAngle 및 OuterConeAngle 속성을 각도로 지정하여 원뿔 모양 영역에 조명을 비춥니다.
조명은 Model3D 개체이므로 위치, 색, 방향 및 범위와 같은 조명 속성을 변환하고 해당 속성에 애니메이션 효과를 줄 수 있습니다.
<ModelVisual3D.Content>
<AmbientLight Color="#333333" />
</ModelVisual3D.Content>
Private myDirLight As New DirectionalLight()
DirectionalLight myDirLight = new DirectionalLight();
myDirLight.Color = Colors.White
myDirLight.Direction = New Vector3D(-3, -4, -5)
myDirLight.Color = Colors.White;
myDirLight.Direction = new Vector3D(-3, -4, -5);
modelGroup.Children.Add(myDirLight)
modelGroup.Children.Add(myDirLight);
모델 변환
모델을 만들 때 모델에는 장면에서의 특정 위치가 지정됩니다. 장면에서 이러한 모델을 이동하거나, 회전하거나, 크기를 변경하기 위해 모델 자체를 정의하는 꼭지점을 변경하는 것은 비효율적입니다. 대신 2-D에서와 같이 모델에 변환을 적용합니다.
각 모델 개체에는 모델을 이동하고, 방향을 다시 지정하고, 크기를 조정할 수 있는 Transform 속성이 있습니다. 변환을 적용할 때는 변환에 의해 지정된 벡터 또는 값이 무엇이든 실제적으로 모델의 모든 점을 오프셋하게 됩니다. 즉, 모델이 정의된 좌표 공간("모델 공간")은 변환하지만 장면 전체("전역 공간")의 좌표계에서 모델의 기하 도형을 구성하는 값은 변경하지 않습니다.
모델 변환에 대한 자세한 내용은 3차원 변환 개요를 참조하십시오.
모델에 애니메이션 효과 주기
WPF 3-D 구현은 2-D 그래픽과 동일한 타이밍 및 애니메이션 시스템에 참여합니다. 즉, 3차원 장면에 애니메이션 효과를 주려면 해당 모델의 속성에 애니메이션 효과를 줍니다. 기본 도형의 속성에 직접 애니메이션 효과를 줄 수도 있지만 일반적으로 모델의 위치나 모양을 변경하는 변환에 애니메이션 효과를 주는 것이 보다 쉽습니다. 변환은 개별 모델뿐만 아니라 Model3DGroup 개체에도 적용될 수 있으므로 Model3DGroup의 자식에 한 애니메이션 집합을 적용하고 자식 개체 그룹에는 또 다른 애니메이션 집합을 적용할 수 있습니다. 장면의 조명 속성에 애니메이션 효과를 주어 다양한 시각적 효과를 얻을 수도 있습니다. 마지막으로 카메라 위치 또는 뷰 필드에 애니메이션 효과를 주어 프로젝션 자체에 애니메이션 효과를 줄 수 있습니다. WPF 타이밍 및 애니메이션 시스템에 대한 자세한 내용은 애니메이션 개요, Storyboard 개요 및 Freezable 개체 개요 항목을 참조하십시오.
WPF에서 개체에 애니메이션 효과를 주려면 시간 표시 막대를 만들고 애니메이션(시간이 지남에 따른 일부 속성 값의 변경)을 정의한 다음 애니메이션을 적용할 속성을 지정합니다. 3-D 장면의 모든 개체는 Viewport3D의 자식이므로 장면에 적용하려는 모든 애니메이션에 사용되는 속성은 Viewport3D의 속성입니다.
모델이 제자리에서 비틀거리는 것처럼 보이게 만들려는 경우 모델에 RotateTransform3D를 적용하고 한 벡터에서 다른 벡터로의 회전 축에 애니메이션 효과를 줄 수 있습니다. 다음 코드 예제에서는 RotateTransform3D가 TransformGroup이 있는 모델에 적용된 여러 변환 중 하나라는 가정 하에 변환의 Rotation3D에 대한 Axis 속성에 Vector3DAnimation을 적용하는 방법을 보여 줍니다.
'Define a rotation
Dim myRotateTransform As New RotateTransform3D(New AxisAngleRotation3D(New Vector3D(0, 1, 0), 1))
//Define a rotation
RotateTransform3D myRotateTransform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 1));
Dim myVectorAnimation As New Vector3DAnimation(New Vector3D(-1, -1, -1), New Duration(TimeSpan.FromMilliseconds(5000)))
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever
Vector3DAnimation myVectorAnimation = new Vector3DAnimation(new Vector3D(-1, -1, -1), new Duration(TimeSpan.FromMilliseconds(5000)));
myVectorAnimation.RepeatBehavior = RepeatBehavior.Forever;
myRotateTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AxisProperty, myVectorAnimation)
myRotateTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AxisProperty, myVectorAnimation);
'Add transformation to the model
cube1TransformGroup.Children.Add(myRotateTransform)
//Add transformation to the model
cube1TransformGroup.Children.Add(myRotateTransform);
창에 3차원 콘텐츠 추가
장면을 렌더링하려면 Model3DGroup에 모델과 조명을 추가한 다음 Model3DGroup을 ModelVisual3D의 Content로 설정합니다. Viewport3D의 Children 컬렉션에 ModelVisual3D를 추가합니다. 해당 Camera 속성을 설정하여 Viewport3D에 카메라를 추가합니다.
마지막으로 창에 Viewport3D를 추가합니다. Viewport3D가 캔버스와 같은 레이아웃 요소의 콘텐츠로 포함될 경우에는 FrameworkElement에서 상속된 해당 Height 및 Width 속성을 설정하여 Viewport3D의 크기를 지정합니다.
<UserControl x:Class="HostingWpfUserControlInWf.UserControl1"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
>
<Grid>
<!-- Place a Label control at the top of the view. -->
<Label
HorizontalAlignment="Center"
TextBlock.TextAlignment="Center"
FontSize="20"
Foreground="Red"
Content="Model: Cone"/>
<!-- Viewport3D is the rendering surface. -->
<Viewport3D Name="myViewport" >
<!-- Add a camera. -->
<Viewport3D.Camera>
<PerspectiveCamera
FarPlaneDistance="20"
LookDirection="0,0,1"
UpDirection="0,1,0"
NearPlaneDistance="1"
Position="0,0,-3"
FieldOfView="45" />
</Viewport3D.Camera>
<!-- Add models. -->
<Viewport3D.Children>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup >
<Model3DGroup.Children>
<!-- Lights, MeshGeometry3D and DiffuseMaterial objects are added to the ModelVisual3D. -->
<DirectionalLight Color="#FFFFFFFF" Direction="3,-4,5" />
<!-- Define a red cone. -->
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="0.293893 -0.5 0.404509 0.475528 -0.5 0.154509 0 0.5 0 0.475528 -0.5 0.154509 0 0.5 0 0 0.5 0 0.475528 -0.5 0.154509 0.475528 -0.5 -0.154509 0 0.5 0 0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0 0.475528 -0.5 -0.154509 0.293893 -0.5 -0.404509 0 0.5 0 0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0 0.293893 -0.5 -0.404509 0 -0.5 -0.5 0 0.5 0 0 -0.5 -0.5 0 0.5 0 0 0.5 0 0 -0.5 -0.5 -0.293893 -0.5 -0.404509 0 0.5 0 -0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0 -0.293893 -0.5 -0.404509 -0.475528 -0.5 -0.154509 0 0.5 0 -0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0 -0.475528 -0.5 -0.154509 -0.475528 -0.5 0.154509 0 0.5 0 -0.475528 -0.5 0.154509 0 0.5 0 0 0.5 0 -0.475528 -0.5 0.154509 -0.293892 -0.5 0.404509 0 0.5 0 -0.293892 -0.5 0.404509 0 0.5 0 0 0.5 0 -0.293892 -0.5 0.404509 0 -0.5 0.5 0 0.5 0 0 -0.5 0.5 0 0.5 0 0 0.5 0 0 -0.5 0.5 0.293893 -0.5 0.404509 0 0.5 0 0.293893 -0.5 0.404509 0 0.5 0 0 0.5 0 "
Normals="0.7236065,0.4472139,0.5257313 0.2763934,0.4472138,0.8506507 0.5308242,0.4294462,0.7306172 0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925 0.5308242,0.4294462,0.7306172 0.2763934,0.4472138,0.8506507 -0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925 -0.2763934,0.4472138,0.8506507 -0.5308242,0.4294462,0.7306172 0,0.4294458,0.9030925 -0.2763934,0.4472138,0.8506507 -0.7236065,0.4472139,0.5257313 -0.5308242,0.4294462,0.7306172 -0.7236065,0.4472139,0.5257313 -0.858892,0.429446,0.279071 -0.5308242,0.4294462,0.7306172 -0.7236065,0.4472139,0.5257313 -0.8944269,0.4472139,0 -0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.858892,0.429446,-0.279071 -0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.7236065,0.4472139,-0.5257313 -0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.5308242,0.4294462,-0.7306172 -0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.2763934,0.4472138,-0.8506507 -0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0,0.4294458,-0.9030925 -0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0.2763934,0.4472138,-0.8506507 0,0.4294458,-0.9030925 0.2763934,0.4472138,-0.8506507 0.5308249,0.4294459,-0.7306169 0,0.4294458,-0.9030925 0.2763934,0.4472138,-0.8506507 0.7236068,0.4472141,-0.5257306 0.5308249,0.4294459,-0.7306169 0.7236068,0.4472141,-0.5257306 0.8588922,0.4294461,-0.27907 0.5308249,0.4294459,-0.7306169 0.7236068,0.4472141,-0.5257306 0.8944269,0.4472139,0 0.8588922,0.4294461,-0.27907 0.8944269,0.4472139,0 0.858892,0.429446,0.279071 0.8588922,0.4294461,-0.27907 0.8944269,0.4472139,0 0.7236065,0.4472139,0.5257313 0.858892,0.429446,0.279071 0.7236065,0.4472139,0.5257313 0.5308242,0.4294462,0.7306172 0.858892,0.429446,0.279071 " TriangleIndices="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 " />
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush
Color="Red"
Opacity="1.0"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
</GeometryModel3D>
</Model3DGroup.Children>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
</Viewport3D>
</Grid>
</UserControl>