Сопоставление 3D-объекта с изображением камеры для дополненной реальности

Я работаю над простым движком AR, и у меня возникла проблема с сопоставлением трехмерного объекта с изображением камеры. Для лучшего понимания я проиллюстрировал это картинкой. Точки A и B находятся в трехмерном пространстве. Точки C и D даны на плоскости текстуры. Расстояние до самолета от камеры известно. Я знаю, как получить координаты Anear, Bnear, Afar, Bfar, Cnear, Dnear, Cfar и Dfar. Проблема в том, как найти точки A 'и B' в трехмерном пространстве, например вектор d == d 'и точки Anear == Cnear и Bnear == Dnear (проекция трехмерных точек на экран должна иметь одинаковые координаты) Может ли кто-нибудь помочь мне с математикой здесь или, по крайней мере, указать мне, где искать ответ?

PS. Похоже, мое описание проблемы недостаточно четкое, чтобы выразить это другими словами: у меня есть пара точек в трехмерном пространстве и пара точек на плоскости текстуры (изображение с веб-камеры). Мне нужно разместить точки в трехмерном пространстве на правильном расстоянии от камеры, чтобы после преобразования перспективы они накладывались на точки на плоскости текстуры. Необходимо сохранить пространственное соотношение трехмерных точек. На чертеже визуальным решением являются точки A 'и B'. Пунктирная линия показывает перспективное преобразование (где они нанесены на ближнюю плоскость в том же месте, что и точки C и D).

иллюстрация проблемы


person Chris    schedule 20.07.2020    source источник
comment
хорошо, какова концепция A' и B'? Насколько я понимаю из ваших рисунков, они могут быть расположены где угодно на линии между Cnear и C ....   -  person derHugo    schedule 20.07.2020
comment
@derHugo - Спасибо за комментарий. Я добавил дополнительные пояснения в тексте вопроса. Точки не могут быть где-либо на пунктирных линиях, потому что тогда длина или направление вектора d изменится (пространственное соотношение между точками A и B).   -  person Chris    schedule 20.07.2020


Ответы (2)


Так что если я правильно понимаю

данные точки в мировом пространстве

  • A
  • B
  • C
  • D

также известно расстояние d и косвенно исходное положение Camera.position и направление Camera.transform.forward.

Искали

  • A'
  • B'

Насколько я понимаю, вы можете найти первую точку A', найдя точку пересечения линии (origin = A, direction = camera forward) и линии (origin = camera.position, direction = Camera.position - ›C).

Точно так же и вторая точка B', найдя точку пересечения линии (origin = B, direction = camera.forward) и линии (origin = camera.position, direction = Camera.position - ›D).

Unity предлагает несколько специальных Math3d, которые здесь могут помочь, например:

//Calculate the intersection point of two lines. Returns true if lines intersect, otherwise false.
//Note that in 3d, two lines do not intersect most of the time. So if the two lines are not in the 
//same plane, use ClosestPointsOnTwoLines() instead.
public static bool LineLineIntersection(out Vector3 intersection, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2)
{
    Vector3 lineVec3 = linePoint2 - linePoint1;
    Vector3 crossVec1and2 = Vector3.Cross(lineVec1, lineVec2);
    Vector3 crossVec3and2 = Vector3.Cross(lineVec3, lineVec2);

    float planarFactor = Vector3.Dot(lineVec3, crossVec1and2);

    //is coplanar, and not parrallel
    if(Mathf.Abs(planarFactor) < 0.0001f && crossVec1and2.sqrMagnitude > 0.0001f)
    {
        float s = Vector3.Dot(crossVec3and2, crossVec1and2) / crossVec1and2.sqrMagnitude;
        intersection = linePoint1 + (lineVec1 * s);
        return true;
    }
    else
    {
        intersection = Vector3.zero;
        return false;
    }
}

Так что вы, вероятно, могли бы сделать что-то вроде

public static bool TryFindPoints(Vector3 cameraOrigin, Vector3 cameraForward, Vector3 A, Vector3 B, Vector3 C, Vector3 D, out Vector3 AMapped, out Vector3 BMapped)
{
    AMapped = default;
    BMapped = default;

    if(LineLineIntersection(out AMapped, A, cameraForward, cameraOrigin, C - cameraOrigin))
    {
        if(LineLineIntersection(out BMapped, B, cameraForward, cameraOrigin, D - cameraOrigin))
        {
            return true;
        }
    }

    return false;
}

а затем используйте его как

if(TryFindPoints(Camera.transform.position, Camera.transform.forward, A, B, C, D, out var aMapped, out var bMapped))
{
    // do something with aMapped and bMapped
}
else
{
    Debug.Log("It was mathematically impossible to find valid points");
}

Примечание. Набрано на смартфоне, но я надеюсь, что идея прояснится

person derHugo    schedule 20.07.2020
comment
Спасибо. Это довольно близко к тому, что мне нужно! - person Chris; 22.07.2020

Учитывая K положение камеры и X = A 'и Y = B'

var angleK = Vector3.Angle(C-K,D-K);
var angleB = Vector3.Angle(D-K, A-B);
var XK = Mathf.Sin(angleB)*(Vector3.Distance(A,B))/Mathf.Sin(angleK);
var X= K+(C-K).normalized*XK;
var Y= B + X - A;
person pi-di-tredipi    schedule 20.07.2020