WPF3Dという3D描画用のフレームワークがあるのですが、あまり使い勝手がよくなく、例えば球体を描画するだけでも一苦労します。
僕は3D描画のプログラムを一度も書いたことがなかったのですが、Perspectiveというライブラリを使って簡単に球体などの3D描画がWPF3Dで出来ましたので、メモしていきます。コードが長くなるので、複数回に分けてメモしたいと思います。
(WPF3Dに慣れている方は、Perspective作者様のWebサイトを参照された方が良いです)
- まずは、PerspectiveというMS-PL Licenseのライブラリをダウンロードします。
- ダウンロードしてきたライブラリを解凍し、perspective-dn4.0.slnを起動し、ビルドします。
- ビルドされたdllを自分のプロジェクトで参照して利用します。
WPFではCanvasやGridがよく使われますが、WPF3DではViewport3Dというコントロールがよく使われます。
Viewport3D上には3Dのオブジェクトを描画することができ、それに対して照明(AmbientLight, DirectionalLightクラスなど)で光を当て、カメラ(PerspectiveCameraなど)で見る(2Dに写像する)というのがWPF3Dの基本的な構成です。
Perspectiveでは球体や円筒を簡単に描画するクラスなどが用意されているのですが、これらは全てViewport3D上に描画することができます。
WPF3Dの基本も兼ねて、x,y,zの三軸を描画するサンプルコードを載せます。実行結果は次のようになります。
MainWindow.xaml.cs
using Perspective.Wpf3D.Shapes;
using System.Windows.Controls;
namespace Wpf3DSample
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
axis3DViewport.Children.Add(new XyzAxis3D() { Length = 4, Radius = 0.03 });
}
}
}
MainWindow.xaml
<Window x:Class="Wpf3DSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="500">
<Grid>
<Viewport3D Name="axis3DViewport">
<!-- Add a camera. -->
<Viewport3D.Camera>
<PerspectiveCamera FieldOfView="60"
LookDirection="-1,-1,-1"
Position="5,5,5"
UpDirection="0,1,0" />
</Viewport3D.Camera>
<!-- Add models. -->
<Viewport3D.Children>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<Model3DGroup.Children>
<!-- Lights, MeshGeometry3D and DiffuseMaterial objects are added to the ModelVisual3D. -->
<DirectionalLight Direction="-1,-1,-1" Color="#FFFFFFFF" />
</Model3DGroup.Children>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
</Viewport3D>
</Grid>
</Window>
カメラの種類を変えたり、照明を変えたりするだけでも結構面白いです。
カメラの位置がずれて、描画しているはずの3Dオブジェクトが消える(消えたように見える)ことがよくありますが、基本的にカメラのいるPositionに対して、LookDirectionが原点を向くようにしてあげれば、問題を早く特定することができます。(例えば、Position (5,5,5)に対して、LookDirection (-1,-1,-1)とする)