한때 3D의 꽃을 뽑으라면 Texture Mapping이였다. 물론 한때다. 지금 다시 뽑으라면 Shader가 되겠지만… 여하튼 오늘 잠시 WPF 3D 쪽으로 눈을 돌리면서 WPF 3D 입문에서 다소 부족했던 부분인, Texutre Mapping 부분을 정리하기로 하겠다.
먼저 Texture Mapping을 하기 위해서는 Texture Mapping 좌표가 필요하다. 이전에 했던 부분은 Texture Mapping 좌표를 제외한 Mesh의 정점과 정점 인덱스 그리고 법선 벡터 만을 지정하였다. 이제 Texture Mapping 좌표를 지정해보는 것을 살펴보자.
우리가 지금까지 구축해 왔던 것에서 시작해보자. Mesh의 정점과 인덱스 그리고 법선 벡터를 지정해 주는 부분을 포함하는 함수가 Windows1.xaml.cs 파일 안의 Window1 클래스에 대한 CreateTriangleModel 함수였다. 이제 이것이 아래와 같이 바뀐다. 파랑색의 코드 부분이 변경이나 추가된 부분이다.
private GeometryModel3D CreateTriangleModel(Point3D p0, Point3D p1,
Point3D p2, Point p0t, Point p1t, Point p2t)
{
MeshGeometry3D mesh = new MeshGeometry3D();
mesh.Positions.Add(p0);
mesh.Positions.Add(p1);
mesh.Positions.Add(p2);
mesh.TriangleIndices.Add(0);
mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(2);
mesh.TextureCoordinates.Add(p0t);
mesh.TextureCoordinates.Add(p1t);
mesh.TextureCoordinates.Add(p2t);
Vector3D normal = CalculateNormal(p0, p1, p2);
mesh.Normals.Add(normal);
mesh.Normals.Add(normal);
mesh.Normals.Add(normal);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(@"y:/face.PNG", UriKind.RelativeOrAbsolute);
bi.EndInit();
Brush brush = new ImageBrush(bi);
Material material = new DiffuseMaterial(brush);
GeometryModel3D model = new GeometryModel3D(mesh, material);
return model;
}
Texture Mapping 좌표와 Texture Image로 사용될 그림을 재질(Material)로 지정하였다. CreateTriangleModel 함수가 변경되었으니 이 함수를 사용하는 부분도 변경되어야 하지 않겠는가? 그 부분에 대한 코드는 ClickCubeButton 함수 안이며 변경된 코드를 파란색으로 나타내면 다음과 같다.
private void ClickCubeButton(object Sender, RoutedEventArgs e)
{
if (model != null) return;
Model3DGroup cube = new Model3DGroup();
Point3D p0 = new Point3D(-1, -1, -1);
Point3D p1 = new Point3D(1, -1, -1);
Point3D p2 = new Point3D(1, -1, 1);
Point3D p3 = new Point3D(-1, -1, 1);
Point3D p4 = new Point3D(-1, 1, -1);
Point3D p5 = new Point3D(1, 1, -1);
Point3D p6 = new Point3D(1, 1, 1);
Point3D p7 = new Point3D(-1, 1, 1);
Point t00 = new Point(0, 0);
Point t01 = new Point(0, 1);
Point t10 = new Point(1, 0);
Point t11 = new Point(1, 1);
//front side triangles
cube.Children.Add(CreateTriangleModel(p3, p2, p6, t00, t10, t11));
cube.Children.Add(CreateTriangleModel(p3, p6, p7, t00, t11, t01));
//right side triangles
cube.Children.Add(CreateTriangleModel(p2, p1, p5, t00, t10, t11));
cube.Children.Add(CreateTriangleModel(p2, p5, p6, t00, t11, t01));
//back side triangles
cube.Children.Add(CreateTriangleModel(p1, p0, p4, t10, t00, t01));
cube.Children.Add(CreateTriangleModel(p1, p4, p5, t10, t01, t11));
//left side triangles
cube.Children.Add(CreateTriangleModel(p0, p3, p7, t10, t00, t01));
cube.Children.Add(CreateTriangleModel(p0, p7, p4, t10, t01, t11));
//top side triangles
cube.Children.Add(CreateTriangleModel(p7, p6, p5, t00, t10, t11));
cube.Children.Add(CreateTriangleModel(p7, p5, p4, t00, t11, t01));
//bottom side triangles
cube.Children.Add(CreateTriangleModel(p2, p3, p0, t10, t00, t01));
cube.Children.Add(CreateTriangleModel(p2, p0, p1, t10, t01, t11));
model = new ModelVisual3D();
model.Content = cube;
mainViewport.Children.Add(model);
}
Texture Mapping 좌표에 대한 설명은 이곳 OpenGL의 Texture Mapping에 대한 강좌에 동일하니 그곳을 참고하길 바란다. 그 실행 결과는 다음과 같다.
참고로 텍스쳐 이미지의 크기는 과거의 2의 자승이여야 한다는 제약이 더 이상 적용하지 않으며 동영상(AVI, 동영상 GIF 등)도 쉽게 지원하며 이미지의 경로를 http 프로토콜을 통해서도 쉽게 받아들일 수 있다.
이상으로 WPF를 이용한 간단한 3D 그래픽에 대한 글의 정리를 끝내겠다. 추후에 지속적으로 WPF에 대한 Article을 실제 업무에 적용하면서 정리하는 예가 많아지길 스스로에게 기대한다.



여기서 실제 우리가 관심을 집중시켜 코딩할 소스 파일은 Window1.xaml과 Windows1.xaml.cs이다. 확장자 XAML은 eXtansible Application Markup Language로써 개발단계에서 UI와 Data 부분을 정의할 수 있는 XML 포멧이다. UI와 Data가 아닌 실행에 관련된 로직은 확장자가 CS인 XAML 까지 포함한 동일한 파일명이다. 여기서 한가지 더 언급하면 Data의 경우 XAML 에도 넣을 수 있지만 CS 에서도 정의할 수 있다는 점이다. 여하튼 바로 이러한 UI와 Logic의 분리.. 즉, UI는 XAML 에 작성하고 로직은 CS 에 작성한다는 것이 디자이너와 개발자간의 분리된 효율적인 협업이 손쉬워졌다는 것이다. 아직 이러한 방식으로 프로젝트에서 디자이너와 협업을 해보지 않아서 모르겠지만, 적용했을시에 개발자는 편해지겠지만 디자이너는 머리가 좀 아플것같다. 디자이너가 XAML 에 익숙해져야 하는데, 이 XAML 이 꽤나 많은 내용을 담고 있기 때문인데… 이러한 문제점에 대해서 MS에서는 디자이너가 코딩보다는 미적인 감각을 더욱 잘살리길 바라는 바, XAML을 좀더 쉽게 만들 수 있는 툴을 MS에서 제공하고 있다. (참고로 XAML은 발음은 “제믈” 이다)
도구모음을 통해 해당 컨트롤을 가져다 디자인을 하든, 아니면 필자처럼 직접 xaml을 막코딩하든…. 위의 폼 구성에 대한 xaml의 내용은 다음과 같다. 참고로 여전이 WPF를 위한 VS2005의 개발환경의 지원은 완벽하지 않다.

파워포인트 2007을 이용해서 만들어 본것이다. 파워포인트의 산출물 퀄러티.. 간지가 아주 그냥 좔좔… 내가 담당하고 있는 저작툴.. 파워포인트 2007처럼 만들어봐?