2009年2月13日金曜日

ちょ、

足が、足がやばい・・・

クオータニオンを使って姿勢をランダムにした


クオータニオンで一様な回転を生成するには、単にその四つの係数を四次元球面上に一様に分布させれば良い(⇒これは誤り。回転軸を球面上一様分布で、回転角を一様分布で生成してクオータニオンを生成すべき。だったら、AxisAngleRoatate3Dで良かったんだな。まあ良いや。回転軸は確かに一様だし)。実際には、四つの係数を[0,1]の一様分布で生成する事を長さが1以下になるまで繰り返して、その後まずクオータニオンを作ってしまってからNormalize()を呼べば良い。

というわけで今現在のコードで、ミクさんのモデルデータは重心が原点にくるように移動させてあって、それをContentsとするVisual3DのTransformにTransform3DGroupを設定して、そのChildrenをRotateTransform3D⇒TranslateTransform3Dの順に設定し、この二つの変換を支配するQuaternionおよびPoint3Dを公開して、UpdatePose()を呼ぶと変換に反映するようにした。現在はPoint3Dのみを重力加速度に従って動かしているけれど、このデータ構造なら、オイラーの剛体方程式に従って剛体回転も容易に扱えるはず。やる気はしないけれど。

コードと実行ファイルはARWithWPFMikuEmitted.zipを詳細サイトのダウンロードページから取ってきてください。

ちなみに、この画像ではボタンの``Emit Miku!''の綴りが``Emmit Miku!''となっていて格好悪いけれど、アップしたソースでは修正してあります。

ARToolkitPlusで体感ゲームを作る予定は未定だけど準備だけ


ミクさんがマーカの位置からランダムな初速度を与えられて射出されて重力で自由落下するぞ。

ミクさんは三次元CG@七葉の4169さんのローポリなデータをお借りしています。

しかしWPFのStoryboard使わずに普通にオンフレームアニメーションにしてしまったので、プログラム的にはあまり面白くない。一連のARToolkit+WPFの実験はWPFを活かす事に主眼があるので続くかどうかは未定。

演算子とジェネリック

演算子の実装を表す型制約がないから何かやだねー、というお話。2chのC#板で出ていた。
この手の話は、C++風にダックタイピングが出来たら・・・という話にもなるのだが、そういう方針で、まあマクロのお化け的なC++のテンプレートにおけるダックタイピングとは違くてつまりは実行時に動的にメソッドを生成するという方針だけど、どなたかがExpression TreeのCompileメソッドを使うやり方を示していた。

で、それならCodeDOMでもできるじゃん、と思って書いたのがこんなコード。

class Multiplier<T>
{
public T Mult(T l, T r)
{
string nameOfT = typeof(T).FullName;
string assemblyOfT = typeof(T).Assembly.ManifestModule.FullyQualifiedName;
CompilerResults cr = null;

using (CodeDomProvider provider
= new CSharpCodeProvider(new Dictionary() { { "CompilerVersion", "v3.5" } })) {
CompilerParameters cp = new CompilerParameters() {
GenerateInMemory = true
};
cp.ReferencedAssemblies.AddRange(new string[] { "System.Core.dll", "mscorlib.dll", assemblyOfT });
string className = "Multiplier_" + nameOfT.Replace('.', '_');
string namespaceName="GenericTest";
string qualifiedClassName = namespaceName + "." + className;
string source = "namespace " +namespaceName+"{ public class " + className + "{public " + nameOfT + " Mult(" + nameOfT + " l, " + nameOfT + @" r){return l*r;}}}";

cr = provider.CompileAssemblyFromSource(cp, source);
if (cr.Errors.HasErrors) {
throw new Exception(String.Join(Environment.NewLine, cr.Errors.OfType().Select(e => e.ToString()).ToArray()));
}
Type typeOfMultiplier = cr.CompiledAssembly.GetType(qualifiedClassName);
Object multiplier = Activator.CreateInstance(typeOfMultiplier);
MethodInfo multiplierMethodMult = typeOfMultiplier.GetMethod("Mult");
return (T)multiplierMethodMult.Invoke(multiplier, new object[] { l, r });
}
}
}

その後、Nyaruruさんの詳しい記事を見つけたのでそれも投稿しておいた。Nyaruruさん(のさらに引用先)曰く、Expression Treeはセマンティクスをデータ構造として保持するからコードを構造を持った抽象的対象として扱えるのが利点で、作ってすぐさまコンパイルして動的メソッド生成のために使うなんてのは、邪道であるらしいのですが、まあCodeDOM使うとこんなに酷い事になりますよ、というお話でした。

ていうかこのコードはMult()呼ぶたびにコンパイルするのも酷いな。せめてstaticなコンストラクタでやるべきだ。