gpt4 book ai didi

c# - 基本渲染 3D 透视投影到带摄像头的 2D 屏幕(不带 opengl)

转载 作者:IT老高 更新时间:2023-10-28 21:21:00 26 4
gpt4 key购买 nike

假设我有一个如下所示的数据结构:

Camera {
double x, y, z

/** ideally the camera angle is positioned to aim at the 0,0,0 point */
double angleX, angleY, angleZ;
}

SomePointIn3DSpace {
double x, y, z
}

ScreenData {
/** Convert from some point 3d space to 2d space, end up with x, y */
int x_screenPositionOfPt, y_screenPositionOfPt

double zFar = 100;

int width=640, height=480
}

...

如果没有屏幕剪辑或其他任何东西,我将如何计算给定空间中某个 3d 点的某个点的屏幕 x,y 位置。我想将该 3d 点投影到 2d 屏幕上。
Camera.x = 0
Camera.y = 10;
Camera.z = -10;


/** ideally, I want the camera to point at the ground at 3d space 0,0,0 */
Camera.angleX = ???;
Camera.angleY = ????
Camera.angleZ = ????;

SomePointIn3DSpace.x = 5;
SomePointIn3DSpace.y = 5;
SomePointIn3DSpace.z = 5;

ScreenData.x 和 y 是空间中 3d 点的屏幕 x 位置。我如何计算这些值?

我可以使用这里找到的方程,但我不明白屏幕宽度/高度是如何起作用的。另外,我在 wiki 条目中不明白观看者的位置与相机位置的关系。

http://en.wikipedia.org/wiki/3D_projection

最佳答案

“完成的方式”是使用同构变换和坐标。你在空间中取一个点,然后:

  • 使用模型矩阵将其相对于相机定位。
  • 使用投影矩阵以正交或透视方式投影它。
  • 应用视口(viewport)变形将其放置在屏幕上。

  • 这变得非常模糊,但我会尝试涵盖重要的部分,并将其中的一些留给您。我假设您了解矩阵数学的基础知识:)。

    齐次 vector 、点、变换

    在 3D 中,齐次点将是 [x, y, z, 1] 形式的列矩阵。最后一个组件是“w”,一个缩放因子,对于 vector 来说,它是 0:这会导致你无法转换 vector ,这在数学上是正确的。我们不会去那里,我们在讨论要点。

    齐次变换是 4x4 矩阵,使用它们是因为它们允许将转换表示为矩阵乘法,而不是加法,这对您的视频卡来说既好又快。也很方便,因为我们可以通过将它们相乘来表示连续的变换。我们通过执行transformation * point 对点进行变换。

    有 3 个主要的齐次变换:
  • Translation,
  • Rotation,
  • Scaling.

  • 还有其他值得探索的,特别是“观察”转换。但是,我只想提供一个简短的列表和一些链接。应用于点的移动、缩放和旋转的连续应用统称为模型变换矩阵,并将它们放置在场景中,相对于相机。重要的是要意识到我们所做的类似于在相机周围移动物体,而不是相反。

    正交和透视

    要将世界坐标转换为屏幕坐标,您首先要使用投影矩阵,通常有两种形式:
  • 正交,常用于 2D 和 CAD。
  • 视角,适用于游戏和 3D 环境。

  • 正交投影矩阵的构造如下:

    An orthographic projection matrix, courtesy of Wikipedia.

    其中参数包括:
  • 顶部 :可见空间上边缘的 Y 坐标。
  • 底部 :可见空间下边缘的 Y 坐标。
  • :可见空间左边缘的X坐标。
  • :可见空间右边缘的 X 坐标。

  • 我认为这很简单。您建立的是一个将出现在屏幕上的空间区域,您可以对其进行剪辑。这里很简单,因为可见空间区域是一个矩形。透视剪裁更复杂,因为出现在屏幕或观看体积上的区域是 frustrum .

    如果您对透视投影的维基百科有困难,这是构建合适矩阵的代码, courtesy of geeks3D
    void BuildPerspProjMat(float *m, float fov, float aspect,
    float znear, float zfar)
    {
    float xymax = znear * tan(fov * PI_OVER_360);
    float ymin = -xymax;
    float xmin = -xymax;

    float width = xymax - xmin;
    float height = xymax - ymin;

    float depth = zfar - znear;
    float q = -(zfar + znear) / depth;
    float qn = -2 * (zfar * znear) / depth;

    float w = 2 * znear / width;
    w = w / aspect;
    float h = 2 * znear / height;

    m[0] = w;
    m[1] = 0;
    m[2] = 0;
    m[3] = 0;

    m[4] = 0;
    m[5] = h;
    m[6] = 0;
    m[7] = 0;

    m[8] = 0;
    m[9] = 0;
    m[10] = q;
    m[11] = -1;

    m[12] = 0;
    m[13] = 0;
    m[14] = qn;
    m[15] = 0;
    }

    变量是:
  • fov : 视野,pi/4 弧度是一个很好的值。
  • 方面 : 高宽比。
  • znear, zfar : 用于剪辑,我会忽略这些。

  • 生成的矩阵是列主矩阵,在上面的代码中索引如下:
    0   4   8  12
    1 5 9 13
    2 6 10 14
    3 7 11 15

    视口(viewport)变换,屏幕坐标

    这两种变换都需要另一个矩阵矩阵来将事物置于屏幕坐标中,称为视口(viewport)变换。 That's described here, I won't cover it (it's dead simple) .

    因此,对于点 p,我们将:
  • 执行模型变换矩阵 * p,得到 pm。
  • 执行投影矩阵 * pm,得到 pp.
  • 根据观看量剪辑 pp。
  • 执行视口(viewport)变换矩阵 * pp,结果是 ps: 屏幕上的点。

  • 摘要

    我希望能涵盖大部分内容。上面有漏洞,有些地方含糊不清,有什么问题可以在下面留言。这个主题通常值得一整章教科书,我已经尽我所能提炼这个过程,希望对你有利!

    我在上面链接到了这个,但我强烈建议你阅读这个,并下载二进制文件。这是一个很好的工具,可以进一步了解这些转换以及它如何在屏幕上获得点数:

    http://www.songho.ca/opengl/gl_transform.html

    就实际工作而言,您需要为齐次变换实现一个 4x4 矩阵类以及一个齐次点类,您可以将其与它相乘以应用变换(请记住,[x, y, z, 1])。您需要按照上述和链接中的说明生成转换。一旦你理解了程序,这并不是那么困难。祝你好运:)。

    关于c# - 基本渲染 3D 透视投影到带摄像头的 2D 屏幕(不带 opengl),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8633034/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com