0 ~ 5 のインデックスが付けられた一連の正方形マーカーがあります。これらのマーカーは、親からのオフセットと一連の回転 (x、y、z) によって表されます。親は別のマーカー (0-5) です。たとえば、マーカー 0 をルート マーカーとして、1 を 0 の子としてオフセット (x:10,y:0,z:5) と回転 (x:0.5,y:0.1,z:0) で指定できます。 2 は 1 の子、3 は 0 の子などです。
ベース マーカーからマーカーの相対的な 3D 位置を見つけるには、オフセットと回転から形成された変換行列をチェーンするだけです。
プロセスの 2 番目のステップは、カメラ ビューからこれらのマーカーを検出することです。ARToolkit に似た ALVAR マーカー トラッカーを使用してこれを行いました。XNAマトリックス形式で検出された各マーカーのカメラ変換マトリックスにアクセスできるラッパーを使用しています(これは、ラッパーを介してOpenGL形式から修正されます)。
検出されたマーカー モデルが、定義したモデルとどの程度一致するかをテストしたいと考えています。これを行うには、検出されたマーカーの 1 つを「ベース」マーカーとして選択し、これから定義されたマーカー モデルを再投影します。
XNA を使用したコードは次のとおりです。
最初に、0 (ルート) マーカーからの「ベース」マーカーの相対的な変換を見つけます。
Matrix globalTransformToPerform=Matrix.Identity;
//Find the markerIDTOBAse on
int mibo = 0;
foreach (Bone b in model.bones)
{
foreach (Marker m in b.markers)
{
if (mibo != markerIDToBaseOn)
{
mibo++;
continue;
}
else
{
//Chain Marker transform
Matrix markerTransform =
Matrix.CreateRotationZ(m.z) *
Matrix.CreateRotationX(m.x) *
Matrix.CreateRotationY(m.y) *
Matrix.CreateTranslation(m.offset);
//Add bone transform
markerTransform *= Matrix.CreateRotationZ(MathHelper.ToRadians(b.z)) *
Matrix.CreateRotationX(MathHelper.ToRadians(b.x)) *
Matrix.CreateRotationY(MathHelper.ToRadians(b.y)) *
Matrix.CreateTranslation(b.Offset);
//Chain parents transforms
Bone parent = b.parent;
while (parent != null)
{
Matrix parentLocalTransform = Matrix.CreateRotationZ(MathHelper.ToRadians(parent.z)) *
Matrix.CreateRotationX(MathHelper.ToRadians(parent.x)) *
Matrix.CreateRotationY(MathHelper.ToRadians(parent.y)) *
Matrix.CreateTranslation(parent.Offset);
markerTransform *= parentLocalTransform;
parent = parent.parent;
}
globalTransformToPerform = markerTransform;
mibo++;
}
}
}
ここで、各マーカーの各コーナーについて、「ベース」マーカーに基づいて、画面上で予想される 2D 投影位置を見つけます。
foreach (Bone b in model.bones)
{
foreach (Marker m in b.markers)
{
//foreach of the corners...
for (int i = 0; i < 4; i++)
{
Matrix cornerTransform = Matrix.CreateTranslation(Global.cornerModel[i]);
//Chain Marker transform
Matrix markerTransform = cornerTransform *
Matrix.CreateRotationZ(m.z) *
Matrix.CreateRotationX(m.x) *
Matrix.CreateRotationY(m.y) *
Matrix.CreateTranslation(m.offset);
//Add bone transform
markerTransform *= Matrix.CreateRotationZ(MathHelper.ToRadians(b.z)) *
Matrix.CreateRotationX(MathHelper.ToRadians(b.x)) *
Matrix.CreateRotationY(MathHelper.ToRadians(b.y)) *
Matrix.CreateTranslation(b.Offset);
//Chain parents transforms
Bone parent = b.parent;
while (parent != null)
{
Matrix parentLocalTransform = Matrix.CreateRotationZ(MathHelper.ToRadians(parent.z))* Matrix.CreateRotationX(MathHelper.ToRadians(parent.x)) *
Matrix.CreateRotationY(MathHelper.ToRadians(parent.y)) *
Matrix.CreateTranslation(parent.Offset);
markerTransform *= parentLocalTransform;
parent = parent.parent;
}
//Find 3D position
Vector3 location = (markerTransform).Translation;
//Now project
Vector3 v = viewPort.Project(location * scalingFactor, projectionMatrix, Matrix.CreateLookAt(new Vector3(0, 0, 3), Vector3.Zero, Vector3.Up), worldTransform*globalTransformToPerform);
Vector2 res = new Vector2(v.X, v.Y);
//Store result
cornersToRet.Add(res);
}
}
}
問題は、マーカーが期待どおりに表示されないことです。私が試したこと:
- ラッパーは正しく動作します。これはテスト済みです
- モデルは正しいです。XNA を使用してこれを画面に描画しましたが、期待どおりです。
- 上記のコードと同じ変換を使用して、モデルを画面に描画しました。
これを実行すると、次のようになります。
緑は、スクリーンに投影されたマーカー トラッカーによって検出されたマーカーです。赤は、「ベース」マーカーに基づくモデルのマーカー コーナーです。
モデルは以下です。
実験: 1. 0 はベース マーカーです。これは、ベースからの変換が同じであるため機能します。
- 1 はベース マーカーです。これは正しくありません。
これを解決するための助けがあれば大歓迎です