Работая на собственном образце Vuforia UWP для VuMarks, я пытался реализовать функциональность на собственном образце Android Dominoes (оба они могут быть найдены Вот). В частности, возможность нажать на экран и получить координаты в целевом пространстве VuMark.
Вот мой код:
void VuMarkRenderer::OnScreenTapped(Point* pos, double logicalWidth, double logicalHeight) {
// normalize coordinates
float x = pos->X / logicalWidth;
float y = pos->Y / logicalHeight;
// normalized device coordinates
Vuforia::Vec4F ndcNear(x, y, -1.0f, 1.0f); // pn near plane
Vuforia::Vec4F ndcFar(x, y, 1.0f, 1.0f); // on far plane
// to eye coordinates (i.e. multiplay with inverse projection matrix)
auto nearPlanePoint = AppMathUtils::Vec4FTransform(ndcNear, m_currentInverseProjection);
auto farPlanePoint = AppMathUtils::Vec4FTransform(ndcFar, m_currentInverseProjection);
// normalize
nearPlanePoint = AppMathUtils::Vec4FDiv(nearPlanePoint, nearPlanePoint.data[3]);
farPlanePoint = AppMathUtils::Vec4FDiv(farPlanePoint, farPlanePoint.data[3]);
// to object (world) coordinates
Vuforia::Vec4F nearWorld = AppMathUtils::Vec4FTransform(nearPlanePoint, m_currentInverseModelView);
Vuforia::Vec4F farWorld = AppMathUtils::Vec4FTransform(farPlanePoint, m_currentInverseModelView);
// set up line (--> ray cast)
Vuforia::Vec3F lineStart(
nearWorld.data[0],
nearWorld.data[1],
nearWorld.data[2]);
Vuforia::Vec3F lineEnd(
farWorld.data[0],
farWorld.data[1],
farWorld.data[2]);
// intersect with VuMark plane
auto lineDir = AppMathUtils::Vec3FSub(lineEnd, lineStart);
lineDir = AppMathUtils::Vec3FDiv(lineDir, lineDir.data[2]);
Vuforia::Vec3F vuMarkPlaneCenter(0, 0, 0);
auto planeDir = AppMathUtils::Vec3FSub(vuMarkPlaneCenter, lineStart);
Vuforia::Vec3F vuMarkPlaneNormal(0, 0, 1);
float n = AppMathUtils::Vec3FDot(vuMarkPlaneNormal, planeDir);
float d = AppMathUtils::Vec3FDot(vuMarkPlaneNormal, lineDir);
if (fabs(d) < 0.00001) { // i.e. line is parallel to plane
m_vuMarkView->UpdateDebugOutput("No intersection");
return;
}
float dist = n / d;
Vuforia::Vec3F offset = AppMathUtils::Vec3FScale(lineDir, dist);
auto intersection = AppMathUtils::Vec3FAdd(lineStart, offset);
}
logicalWidth а также logicalHeight являются страницами UWP ActualWidth а также ActualHeight respecively.
Вот где я получаю m_currentInverseProjection от:
[...]
// Calculate the DX Projection matrix using the current Vuforia state
auto projectionMatrix = Vuforia::Tool::convertPerspectiveProjection2GLMatrix(
m_renderingPrimitives->getProjectionMatrix(Vuforia::VIEW_SINGULAR, state.getCameraCalibration()),
m_near,
m_far);
XMFLOAT4X4 dxProjection;
memcpy(dxProjection.m, projectionMatrix.data, sizeof(float) * 16);
XMStoreFloat4x4(&dxProjection, XMMatrixTranspose(XMLoadFloat4x4(&dxProjection)));
XMMATRIX xmProjection = XMLoadFloat4x4(&dxProjection);
bool gotVuMark = false;
for (size_t v = 0; v < viewList.getNumViews(); v++)
{
Vuforia::VIEW viewId = viewList.getView(static_cast<int>(v));
// Apply the appropriate eye adjustment to the raw projection matrix, and assign to the global variable
Vuforia::Matrix44F eyeAdjustment44F = Vuforia::Tool::convert2GLMatrix(
m_renderingPrimitives->getEyeDisplayAdjustmentMatrix(viewId));
// get current inverse projection matrix
Vuforia::Matrix44F currentProjection;
AppMathUtils::multiplyMatrix(projectionMatrix, eyeAdjustment44F, currentProjection);
m_currentInverseProjection = AppMathUtils::Matrix44FInverse(currentProjection);
[...]
И вот m_currentInverseModelView:
[...]
// Set up the modelview matrix
auto poseGL = Vuforia::Tool::convertPose2GLMatrix(result->getPose());
// save the current inverse model-view matrix
m_currentInverseModelView = AppMathUtils::Matrix44FInverse(poseGL);
[...]
Функции из AppMathUtils просто копируются и вставляются из двух примеров проектов.
Тем не менее, результаты полностью отключены. Я почти уверен, что что-то неправильно понимаю в разных системах координат, но совершенно не могу понять, что это такое …
У кого-нибудь есть идеи, что я делаю не так? Буду признателен за любую помощь!
РЕДАКТИРОВАТЬ
я забыл упомянуть Эта статья (раздел «Пространство экрана до целевого пространства»), в котором изначально указывалось на образец Dominoes и который я пытался адаптировать.
Задача ещё не решена.
Других решений пока нет …