Отображение 3D-прямоугольника на 2D-экран - PullRequest
2 голосов
/ 22 апреля 2011

Я искал ТАК, но я просто не могу понять это. Другие вопросы не помогли, или я их не понял.

Проблема в том, что у меня есть куча точек на трехмерном изображении. Точки для прямоугольника, который не выглядит как прямоугольник с точки зрения 3D-камеры из-за перспективы. Задача состоит в том, чтобы отобразить точки из этого прямоугольника на экран. Я видел несколько способов, которые некоторые называют «преобразованиями четырехугольника», но большинство из них предназначены для отображения двухмерного четырехугольника на другой. Но у меня есть координаты X, Y и Z прямоугольника в реальном мире, поэтому я ищу более простые способы. Кто-нибудь знает какой-либо практический алгоритм или способ сделать это?

Если это поможет, моя 3d-камера на самом деле является устройством Kinect с промежуточным ПО OpenNI и NITE, и я использую WPF.

Заранее спасибо.

редактирование: Я также нашел страницу 3D-проекции в Википедии, в которой использовались углы и косинусы, но это кажется трудным способом (поиск углов в трехмерном изображении), и я не уверен, является ли это реальным решением или нет.

Ответы [ 5 ]

2 голосов
/ 22 апреля 2011

См. Этот код , чтобы получить матрицу проекции для данной камеры WPF:

private static Matrix3D GetProjectionMatrix(OrthographicCamera camera, double aspectRatio)
{ 
    // This math is identical to what you find documented for
    // D3DXMatrixOrthoRH with the exception that in WPF only
    // the camera's width is specified.  Height is calculated
    // from width and the aspect ratio.
    double w = camera.Width;
    double h = w / aspectRatio;
    double zn = camera.NearPlaneDistance;
    double zf = camera.FarPlaneDistance;
    double m33 = 1 / (zn - zf);
    double m43 = zn * m33;
    return new Matrix3D(
        2 / w, 0, 0, 0,
        0, 2 / h, 0, 0,
        0, 0, m33, 0,
        0, 0, m43, 1);
}

private static Matrix3D GetProjectionMatrix(PerspectiveCamera camera, double aspectRatio)
{ 
    // This math is identical to what you find documented for
    // D3DXMatrixPerspectiveFovRH with the exception that in
    // WPF the camera's horizontal rather the vertical
    // field-of-view is specified.
    double hFoV = MathUtils.DegreesToRadians(camera.FieldOfView);
    double zn = camera.NearPlaneDistance;
    double zf = camera.FarPlaneDistance;
    double xScale = 1 / Math.Tan(hFoV / 2);
    double yScale = aspectRatio * xScale;
    double m33 = (zf == double.PositiveInfinity) ? -1 : (zf / (zn - zf));
    double m43 = zn * m33;
    return new Matrix3D(
        xScale, 0, 0, 0,
        0, yScale, 0, 0,
        0, 0, m33, -1,
        0, 0, m43, 0);
}

/// <summary>
///     Computes the effective projection matrix for the given
///     camera.
/// </summary>
public static Matrix3D GetProjectionMatrix(Camera camera, double aspectRatio)
{
    if (camera == null)
    {
        throw new ArgumentNullException("camera");
    }
    PerspectiveCamera perspectiveCamera = camera as PerspectiveCamera;
    if (perspectiveCamera != null)
    {
        return GetProjectionMatrix(perspectiveCamera, aspectRatio);
    }
    OrthographicCamera orthographicCamera = camera as OrthographicCamera;
    if (orthographicCamera != null)
    {
        return GetProjectionMatrix(orthographicCamera, aspectRatio);
    }
    MatrixCamera matrixCamera = camera as MatrixCamera;
    if (matrixCamera != null)
    {
        return matrixCamera.ProjectionMatrix;
    }
    throw new ArgumentException(String.Format("Unsupported camera type '{0}'.", camera.GetType().FullName), "camera");
}
2 голосов
/ 22 апреля 2011

Возможно, вы захотите проверить матрицы проекций

Вот так любой 3D растеризатор "сглаживает" 3D-объемы на 2D-экране.

1 голос
/ 30 августа 2011

Я нашел это .Использует прямую математику вместо матриц.

Это называется перспективной проекцией для преобразования из 3D-вершины в 2D-экранную вершину.Я использовал это, чтобы помочь мне с моей 3D-программой, которую я сделал.

HorizontalFactor = ScreenWidth / Tan(PI / 4)
VerticalFactor = ScreenHeight / Tan(PI / 4)

ScreenX = ((X * HorizontalFactor) / Y) + HalfWidth
ScreenY = ((Z * VerticalFactor) / Y) + HalfHeight

Надеюсь, что это может помочь.Я думаю, что вы ищете.Извините за форматирование (новое здесь)

1 голос
/ 22 апреля 2011

Вы могли бы сделать простую ортографическую проекцию (я думаю с точки зрения трассировки лучей, так что это может не относиться к тому, что вы делаете):

enter image description here

Кодинтуитивно понятен:

for y in image.height:
  for x in image.width:
    ray = new Ray(x, 0, z, Vector(0, 1, 0)) # Pointing forward
    intersection = prism.intersection(ray) # Since you aren't shading, you can check only for intersections.

    image.setPixel(x, y, intersection) # Returns black and white image of prism mapped to plane

Вы просто снимаете векторы с направлением (0, 1, 0) прямо в космос и записываете, какие из них попали.

0 голосов
/ 22 апреля 2011

Отображение точек в трехмерном мире на двухмерный экран является частью работы фреймворков, таких как OpenGL и Direct3d. Это называется растеризацией, как сказал Хендель. Возможно, вы могли бы использовать Direct3d?

...