3D マルチタッチ・アプリケーション
最近、スレートPCという、タッチパネルを搭載したPCが発売されています。特徴は、キーボードやマウスが無いかわりに、マルチ・タッチ入力が可能になっています。このようなマルチタッチ・アプリケーションの簡単な作り方について説明します。
前回は、首都高の交通情報を表示するアプリケーションを作成しましたが、今回は「魔法少女まどか☆マギカ」のキュウべぇと、ソウルジェムを3Dモデリングして、それをスレートPCで動かしてみます。
マルチタッチ・アプリケーションの概要
このアプリケーションの作成は次の手順になります。
全体の流れは次の通りです。
-
ZAM 3D で3Dオブジェクトをモデリングする。
-
Microsoft Expression Blend で、タッチ機能、スムースな移動を実装する。
-
Visual Studio 2010 で必要な機能を実装する。
1.ZAM
3D による、3Dモデリング
ZAM 3D とは、erain
より発売されてる、3D XAML
を生成することができるツールです。残念ながら日本語バージョンはありませんが、非常に簡単に 3D XAML
を作成することができます。さらに、その 3D XAML を Visual Studio の形式で
Export できますので、簡単に 3D アプリケーションを作成することができます。
ここでは、簡単にキュウべぇを作ってみます。しかし、モデリングを言葉で説明するのはほとんど不可能なので、モデリングの様子をビデオにとりましたので、そちらをご覧になってください。
ニコニコ動画 キュウべえを 3D モデリングして、スレートPCで動かしてみた
2.Expression
Blend で、タッチ機能、スムースな移動を実装する。
次に、Expression Blend で、タッチ機能、スムースな移動を実装します。ZAM 3D
でモデリングしたプロジェクトを Expression Blend でタッチアプリケー
-
Expression Blend 4.0 でプロジェクトを開きます。
-
.NET Framework 4.0 を選択します。
-
Canvas
に、[アセット]→[ビヘイビアー]→[TranslateZoomRotateBehavior]を追加します。このTranslateZoomRotateBehaviorだけで、Canvas
を指でタッチして、移動、ズーム、回転ができるようになります。
-
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>
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 化計画 を参照してください。
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/マルチタッチ対応アプリケーション開発者会議”レポート
にわかりやすく書いてあるので、参考にしてください。
5.ソフト
Touch-QB-Bin.zip
152KB キュウべぇのタッチアプリケーションデモ用コード
キュウべぇに似てないとか、SoulGem
のモデリングでオブジェクトがずれていたりしますが、デモ用ということでご容赦を・・・
SoulGem-Bin.zip 131KB
ソウルジェムのタッチアプリケーションデモ用コード
ソウルジェムは、Atom
クラスのスレートPCでは、ソウルジェムの頂点数が多すぎて、処理が非常に重くなっています。
6.ソースコード
Touch-QB.zip
1.2MB キュウべぇのタッチアプリケーション デモ用コード (Visual Studio 2010
用プロジェクト一式)
SoulGem.zip 0.98MB ソウルジェムのタッチアプリケーション デモ用コード (Visual Studio 2010
用プロジェクト一式)
7.まとめ
以上のように、非常に簡単にマルチタッチ・アプリケーションを実装することができます。ぜひ、試してみてはいかがでしょうか。