Wpf3DのHelix-Toolkitを使ってみる

がっつり描画する3DエンジンのようなものではなくGUIよりのライブラリとして[Helix 3D Toolkit](https://github.com/helix-toolkit/helix-toolkit.github.io/blob/master/demos/index.md)というのを見つけたのだけど、どうなのかということであります。スクリーンショットを見るとなかなか多機能そうな感じ。

# Cloneしてビルドしてみる
とりあえず<https://github.com/helix-toolkit/helix-toolkit>からclone。
Source/HelixToolkit.Wpf.slnで実験。問題なく動く。

![MvvmManipulatorDemo](https://qiita-image-store.s3.amazonaws.com/0/59664/3f5ee8d8-5778-2efe-ae4b-8bbc9b79bdca.png)

なんかWpfらしく3D側のマニピュレーターもバインディングできてドラッグ操作できるぞ。これはいいものなのではないか。

```xml:xaml抜粋
        <ht:HelixViewport3D Grid.Column="1"  Background="{ht:LinearGradientBrush Gray, White}"   ShowCameraInfo="True"
                            >
            <ht:HelixViewport3D.DefaultCamera>
                <PerspectiveCamera Position="-20 -40 20" LookDirection="17 34 -17" UpDirection="0 0 1"/>
            </ht:HelixViewport3D.DefaultCamera>
            <ht:SunLight/>
            <ht:GridLinesVisual3D/>
            <ht:BindableTranslateManipulator Direction="1 0 0"  Length="5" Diameter="1" Color="Black" 
                                     Value="{Binding TranslateValue}"
                                     TargetTransform="{Binding ElementName=sphere1, Path=Transform}"/>

            <ht:BindableRotateManipulator Position="20 15 0"  Diameter="10" InnerDiameter="7" Axis="0 1 0" Color="Green"
                                  Value="{Binding RotateValue}"  
                                  TargetTransform="{Binding ElementName=cube1, Path=Transform}"/>            
            <ht:SphereVisual3D x:Name="sphere1" Radius="1" Fill="Gold" />
            <ht:ArrowVisual3D Origin="15 10 0"  Point1="15 10 0" Point2="19 10 0"   x:Name="cube1"  Fill="Gold"/> 

        </ht:HelixViewport3D>
```

# 自分で使ってみる
チュートリアル記事的なものは見当たらないですな。ExamplesのSimpleDemoを新規プロジェクトで再現してみる。

##新規プロジェクトをWpfアプリケーションで開始
![ss05.png](https://qiita-image-store.s3.amazonaws.com/0/59664/12addee8-fb71-90e5-6f24-c4a2a713277e.png)

##nugetでHelixToolkit.Wpfをインストール
![ss06.png](https://qiita-image-store.s3.amazonaws.com/0/59664/9c0c04c6-4f04-d1ea-1f26-688d20e97f1d.png)

```txt:ネームスペースを追加
        xmlns:ht="clr-namespace:HelixToolkit.Wpf;assembly=HelixToolkit.Wpf"
```

##Viewport追加

```xml:xaml
<Window x:Class="HelixToolkitSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ht="clr-namespace:HelixToolkit.Wpf;assembly=HelixToolkit.Wpf"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <!-- The HelixViewport3D supports camera manipulation, and can be used just like the Viewport3D -->
        <ht:HelixViewport3D>


        </ht:HelixViewport3D>
    </Grid>
</Window>
```

ここで一回動作確認。
真っ白な空間の右下に視点カーソルが出てくる。ビューを右ドラッグで方向を変えられる。
![ss07.png](https://qiita-image-store.s3.amazonaws.com/0/59664/49e7ac08-82e0-88bd-563f-e453cb4db263.png)

##Grid追加

```xml:HelixViewport3Dの中
            <HelixToolkit:GridLinesVisual3D Width="8" Length="8" MinorDistance="1" MajorDistance="1" Thickness="0.01"/>
```

#モデル追加

## xaml
```xml:HelixViewport3Dの中
 <ModelVisual3D Content="{Binding Model}"/>       
```

忘れていたがこれはWpf3Dらしい。

## ViewModel
SimpleDemoのMainViewModel.csを頂いてくる。

```csharp:ExampleBrowser.MainViewModel

namespace ExampleBrowser
{
    using System.Windows.Media;
    using System.Windows.Media.Media3D;

    using HelixToolkit.Wpf;

    /// <summary>
    /// Provides a ViewModel for the Main window.
    /// </summary>
    public class MainViewModel
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="MainViewModel"/> class.
        /// </summary>
        public MainViewModel()
        {
            // Create a model group
            var modelGroup = new Model3DGroup();

            // Create a mesh builder and add a box to it
            var meshBuilder = new MeshBuilder(false, false);
            meshBuilder.AddBox(new Point3D(0, 0, 1), 1, 2, 0.5);
            meshBuilder.AddBox(new Rect3D(0, 0, 1.2, 0.5, 1, 0.4));

            // Create a mesh from the builder (and freeze it)
            var mesh = meshBuilder.ToMesh(true);

            // Create some materials
            var greenMaterial = MaterialHelper.CreateMaterial(Colors.Green);
            var redMaterial = MaterialHelper.CreateMaterial(Colors.Red);
            var blueMaterial = MaterialHelper.CreateMaterial(Colors.Blue);
            var insideMaterial = MaterialHelper.CreateMaterial(Colors.Yellow);

            // Add 3 models to the group (using the same mesh, that's why we had to freeze it)
            modelGroup.Children.Add(new GeometryModel3D { Geometry = mesh, Material = greenMaterial, BackMaterial = insideMaterial });
            modelGroup.Children.Add(new GeometryModel3D { Geometry = mesh, Transform = new TranslateTransform3D(-2, 0, 0), Material = redMaterial, BackMaterial = insideMaterial });
            modelGroup.Children.Add(new GeometryModel3D { Geometry = mesh, Transform = new TranslateTransform3D(2, 0, 0), Material = blueMaterial, BackMaterial = insideMaterial });

            // Set the property, which will be bound to the Content property of the ModelVisual3D (see MainWindow.xaml)
            this.Model = modelGroup;
        }

        /// <summary>
        /// Gets or sets the model.
        /// </summary>
        /// <value>The model.</value>
        public Model3D Model { get; set; }
    }
}
```

```xml
<Window x:Class="HelixToolkitSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ht="clr-namespace:HelixToolkit.Wpf;assembly=HelixToolkit.Wpf"
        xmlns:ex="clr-namespace:ExampleBrowser"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <ex:MainViewModel />
    </Window.DataContext>
    <Grid>
        <!-- The HelixViewport3D supports camera manipulation, and can be used just like the Viewport3D -->
        <ht:HelixViewport3D>

            <ht:GridLinesVisual3D Width="8" Length="8" MinorDistance="1" MajorDistance="1" Thickness="0.01"/>

            <ModelVisual3D Content="{Binding Model}"/>            
            
        </ht:HelixViewport3D>
    </Grid>
</Window>
```

黒い物体が・・・

![ss08.png](https://qiita-image-store.s3.amazonaws.com/0/59664/14ee5357-e0cc-b4fb-b8a2-eb399bd317ee.png)

わざと光源を追加してなかったからですな。

## 光源追加

```xml:HelixViewport3Dの中
            <ht:SunLight/>
```
## ZoomExtentsWhenLoaded

```xml
        <ht:HelixViewport3D Grid.Column="1" ZoomExtentsWhenLoaded="True">
```

自動でおさまりがいいところまでズームする機能。

![ss09.png](https://qiita-image-store.s3.amazonaws.com/0/59664/0ca704a5-6397-d3dc-5135-0b50ede14d04.png)

Helix-Toolkit使いやすいんでないか。
Kinectとかの実験アプリにちょうどよい気がする。

次回は自前のモデルローダーかなぁ。