我有一组从 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 位置,您只需链接由偏移和旋转形成的变换矩阵。
该过程的第二步是从摄像机视图中检测这些标记。我使用类似于 ARToolkit 的 ALVAR 标记跟踪器完成了这项工作。我正在使用一个包装器,它允许我以 XNA 矩阵格式访问每个检测到的标记的相机变换矩阵(这是通过包装器从 OpenGL 格式更正的)。
我想测试检测到的标记模型与我定义的模型的匹配程度。为此,我选择一个检测到的标记作为“基础”标记,并从中重新投影出定义的标记模型。
使用 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 是基础标记。这是不正确的。
任何解决此问题的帮助将不胜感激