C# Programming

Image3D マルチタッチ・アプリケーション

最近、スレートPCという、タッチパネルを搭載したPCが発売されています。特徴は、キーボードやマウスが無いかわりに、マルチ・タッチ入力が可能になっています。このようなマルチタッチ・アプリケーションの簡単な作り方について説明します。

前回は、首都高の交通情報を表示するアプリケーションを作成しましたが、今回は「魔法少女まどか☆マギカ」のキュウべぇと、ソウルジェムを3Dモデリングして、それをスレートPCで動かしてみます。

Visual Studioマルチタッチ・アプリケーションの概要

このアプリケーションの作成は次の手順になります。

全体の流れは次の通りです。

  1. ZAM 3D で3Dオブジェクトをモデリングする。

  2. Microsoft Expression Blend で、タッチ機能、スムースな移動を実装する。

  3. Visual Studio 2010 で必要な機能を実装する。

Image1.ZAM 3D による、3Dモデリング

ZAM 3D とは、erain より発売されてる、3D XAML を生成することができるツールです。残念ながら日本語バージョンはありませんが、非常に簡単に 3D XAML を作成することができます。さらに、その 3D XAML を Visual Studio の形式で Export できますので、簡単に 3D アプリケーションを作成することができます。

ここでは、簡単にキュウべぇを作ってみます。しかし、モデリングを言葉で説明するのはほとんど不可能なので、モデリングの様子をビデオにとりましたので、そちらをご覧になってください。

ニコニコ動画 キュウべえを 3D モデリングして、スレートPCで動かしてみた

Image2.Expression Blend で、タッチ機能、スムースな移動を実装する。

次に、Expression Blend で、タッチ機能、スムースな移動を実装します。ZAM 3D でモデリングしたプロジェクトを Expression Blend でタッチアプリケー

  1. Expression Blend 4.0 でプロジェクトを開きます。

  2. .NET Framework 4.0 を選択します。

  3. Canvas に、[アセット]→[ビヘイビアー]→[TranslateZoomRotateBehavior]を追加します。このTranslateZoomRotateBehaviorだけで、Canvas を指でタッチして、移動、ズーム、回転ができるようになります。

  4. Canvas に、[アセット]→[ビヘイビアー]→[FluidMoveBehavior]を追加します。このFluidMoveBehaviorを追加するだけで、Canvas の移動や回転に慣性(イナーシャ)が追加されます。

 生成されるコートは、次の通りです。

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:c="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 中略>
<Canvas x:Name="ZAM3DCanvas" ClipToBounds="true" Width="400" Height="300">

<i:Interaction.Behaviors>
  <ei:TranslateZoomRotateBehavior/>
  <ei:FluidMoveBehavior/>
</i:Interaction.Behaviors>

Web画面3.Visual Studio 2010 での実装

ここまででまったくコーディング・ゼロでできてしまいます。

この状態では、FluidMoveBehaviorにより、Canvas の移動や回転に慣性(イナーシャ)が追加されていますので、たとえば、左方向に移動させると、そのままの勢いでずっと左に動いて行ってしまいます。この時の、イナーシャ(慣性)の減衰係数は0です。つまり、宇宙空間のように摩擦がない状態になり、一度慣性が付くと、そのまま動き続けます。

慣性(イナーシャ)に減衰させるには、次のように ManipukationInertiaStarting イベントで、減衰係数をセットしてください。

 private void ZAM3DCanvas_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e)
{
// イナーシャの減衰係数
e.TranslationBehavior.DesiredDeceleration = 0.0001;
e.RotationBehavior.DesiredDeceleration = 0.0001;
e.ExpansionBehavior.DesiredDeceleration = 0.0001;

e.Handled = true;
}

減衰がない場合や、減衰が弱い場合には、一度移動の慣性が発生すると、Canvas が移動を続け、スクリーンの外まで移動してしまいますCanvas が表示エリアの外部に移動してしまうと、Canvas に触ることができなくなり、表示位置を元に戻すことができなくなってしまいます。

このような場合には、ManipulationDeltaイベントでCanvas がどの位置に移動されるのか計算し、親ウィンドウの外に出てしまう場合には、マニピュレーションを停止してあげる必要があります。それが次のコードになります。

 private void ZAM3DCanvas_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
// Get the Rectangle and its RenderTransform matrix.
Canvas canvasToMove = (Canvas)e.OriginalSource;
Matrix canvasMatrix = ((MatrixTransform)canvasToMove.RenderTransform).Matrix;

// Rotate the Rectangle.
canvasMatrix.RotateAt(e.DeltaManipulation.Rotation,
e.ManipulationOrigin.X,
e.ManipulationOrigin.Y);

// Resize the Rectangle. Keep it square
// so use only the X value of Scale.
canvasMatrix.ScaleAt(e.DeltaManipulation.Scale.X,
e.DeltaManipulation.Scale.Y,
e.ManipulationOrigin.X,
e.ManipulationOrigin.Y);

// Move the Rectangle.
canvasMatrix.Translate(e.DeltaManipulation.Translation.X,
e.DeltaManipulation.Translation.Y);

// Apply the changes to the Rectangle.
canvasToMove.RenderTransform = new MatrixTransform(canvasMatrix);

Rect containingRect =
new Rect(((FrameworkElement)e.ManipulationContainer).RenderSize);

Rect shapeBounds =
canvasToMove.RenderTransform.TransformBounds(
new Rect(canvasToMove.RenderSize));

// Check if the rectangle is completely in the window.
// If it is not and intertia is occuring, stop the manipulation.
if (e.IsInertial && !containingRect.Contains(shapeBounds))
{
e.Complete();
}

e.Handled = true;
}

なお、この例では、Canvas そのものを TranslateZoomRotate するだけで、3D Object そのものを回転したり、移動したりするものではありません。3D Object そのものを回転したり、移動する方法に関しては、初音ミク XAML 化計画 を参照してください。

Web画面4.タッチアプリケーションで注意すべきこと・・・

せっかくキュウべぇが動くようになったので、もう少し頑張って、ソウルジェムをモデリングしてみました。キュウべぇはどちらかというとシンプルなプリミティブで構成していますが、ソウルジェムのほうが複雑です。デモ用の SoulGem.exe をスレートPCで実行してもらえばわかると思いますが、かなり重いです。

スレートPCでは、Atom などの非力なCPUを使っているものが多いと思いますので、CPUパワーはそれほど高くないことを前提にしたほうがいいです。このため、あまり複雑な 3D モデリングは避けたほうがいいです。

一応、比較のために、SoulGem.exe を用意してみましたので、比較してみてください。 

なお、次のコードは、CPU Processor Timeに従って、SoulGem のマテリアルの色を青から黒に変化させるコードです。

using System;
using System.Windows;
using System.Windows.Media.Media3D;
using System.Windows.Media;
using System.Diagnostics;
using System.Windows.Threading;
using System.Windows.Input;
using System.Windows.Controls;

public partial class Window1 : System.Windows.Window
{

PerformanceCounter pc = new PerformanceCounter();
DispatcherTimer timer = new DispatcherTimer();

MaterialGroup[] mg = new MaterialGroup[17];
DiffuseMaterial[] d = new DiffuseMaterial[17];

private void Window_Loaded(object sender, RoutedEventArgs e)
{
pc.CategoryName = "Processor";
pc.CounterName = "% Processor Time";
pc.InstanceName = "_Total";
ColorConverter cc = new ColorConverter();

SpecularMaterial shine = new SpecularMaterial(new SolidColorBrush(Colors.White), 1.0d);
shine.SpecularPower = 40;

for(int i = 0; i < 16; i++)
{
string c = String.Format("{0:X2}", i * 15);
string c2 = String.Format("{0:X2}", i * 2);
string col = "#" + "00" + "00" + c;
SolidColorBrush br = new SolidColorBrush((Color)(ColorConverter.ConvertFromString(col)));
br.Opacity = 0.8;
d[i] = new DiffuseMaterial(br);

mg[i] = new MaterialGroup();
mg[i].Children.Add(d[i]);
mg[i].Children.Add(shine);
}

timer.Interval = new TimeSpan(0, 0, 1);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}

void timer_Tick(object sender, EventArgs e)
{
int v = 100 - (int)this.pc.NextValue();

int delta = 100 / 16;

this.GemOutterOR299GR300.Material = mg[v / delta];
}

...

}
 

また、これ以外のタッチアプリケーションを開発するうえでの注意事項としては、“Windows Slate/Windows 7/マルチタッチ対応アプリケーション開発者会議”レポート にわかりやすく書いてあるので、参考にしてください。

Web画面5.ソフト

Touch-QB-Bin.zip 152KB キュウべぇのタッチアプリケーションデモ用コード

キュウべぇに似てないとか、SoulGem のモデリングでオブジェクトがずれていたりしますが、デモ用ということでご容赦を・・・

SoulGem-Bin.zip 131KB ソウルジェムのタッチアプリケーションデモ用コード

ソウルジェムは、Atom クラスのスレートPCでは、ソウルジェムの頂点数が多すぎて、処理が非常に重くなっています。

 

Web画面6.ソースコード

Touch-QB.zip 1.2MB キュウべぇのタッチアプリケーション デモ用コード (Visual Studio 2010 用プロジェクト一式)

SoulGem.zip 0.98MB ソウルジェムのタッチアプリケーション デモ用コード (Visual Studio 2010 用プロジェクト一式)

Web画面7.まとめ

以上のように、非常に簡単にマルチタッチ・アプリケーションを実装することができます。ぜひ、試してみてはいかがでしょうか。