来自欧拉角的 3D 法线/观察向量

发布于 2024-12-04 18:37:26 字数 1113 浏览 1 评论 0原文

我正在开发一个类似 JavaScript/Canvas 3D FPS 的引擎,并且迫切需要一个法线向量(或者如果你愿意的话可以查看向量)来进行近平面和远平面裁剪。我有 x 轴和 y 轴旋转角度,并且当时只用其中一个就可以轻松完成,但我就是不知道如何获得它们......我们的

想法是使用这个向量要计算相机前面的点,近剪裁平面和远剪裁平面也必须可以由常量定义,因此必须对向量进行归一化,我希望仅使用角度就可以将此向量长度设置为 1 而无需归一化,但这不是问题。

我没有任何滚动(绕 z 轴旋转),所以它更容易。

我的数学计算如下:

zNear = 200; // near plane at an arbitrary 200 "points" away from camera position

// normal calculated with only y rotation angle (vertical axis)
normal = {
    x: Math.sin(rotation.y),
    y: 0,
    z: Math.cos(rotation.y)};

然后通过点积测试从平面到该点的向量,在 3D 空间中剪切一个点。

nearPlane = {
    x: position.x+normal.x*zNear,
    y: position.y+normal.y*zNear,
    z: position.z+normal.z*zNear};

// test a point at x, y, z against the near clipping plane
if(
    (nearPlane.x-x)*normal.x+
    (nearPlane.y-y)*normal.y+
    (nearPlane.z-z)*normal.z < 0
)
{
    return;
}

// then project the 3D point to screen

当一个点位于玩家后面时,它的投影坐标会反转(x=-x,y=-y),所以没有任何意义了,这就是我试图删除它们的原因。

在此处输入图像描述

我想要那个绿色箭头,但是是 3D 的。

I'm working on a JavaScript/Canvas 3D FPS-like engine and desperately need a normal vector (or look-at vector if you will) for near and far plane clipping. I have the x and y axis rotation angles and am able to do it easily with only one of them at the time, but I just can't figure out how to get both of them...

The idea is to use this vector it to calculate a point in front of the camera, the near and far clipping planes must also be definable by constants so the vector has to be normalized, I hoped that with only the angles it would be possible to get this vector length to 1 without normalizing, but that's not the problem.

I don't have any roll (rotation around z axis) so it's that much easier.

My math looks like this:

zNear = 200; // near plane at an arbitrary 200 "points" away from camera position

// normal calculated with only y rotation angle (vertical axis)
normal = {
    x: Math.sin(rotation.y),
    y: 0,
    z: Math.cos(rotation.y)};

Then clip a point in 3D space by testing the vector from the plane to it by means of a dot product.

nearPlane = {
    x: position.x+normal.x*zNear,
    y: position.y+normal.y*zNear,
    z: position.z+normal.z*zNear};

// test a point at x, y, z against the near clipping plane
if(
    (nearPlane.x-x)*normal.x+
    (nearPlane.y-y)*normal.y+
    (nearPlane.z-z)*normal.z < 0
)
{
    return;
}

// then project the 3D point to screen

When a point is behind the player its projection coordinates are reversed (x=-x, y=-y) so nothing makes sense any more, that's why I'm trying to remove them.

enter image description here

I want that green arrow there, but in 3D.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

此刻的回忆 2024-12-11 18:37:26

经过一番密集的大脑处理后,我发现

  1. 我原来的观察向量是 (0, 0, 1)
  2. z 旋转角度(滚动)始终为 0
  3. Wikipedia 不起作用

通过在 (0, 0, 1) 向量上应用完整旋转矩阵并考虑到 rz = 0我得到的解决方案是:

normal = {
    x: Math.cos(camera.rotation.x)*Math.sin(camera.rotation.y),
    y: -Math.sin(camera.rotation.x),
    z: Math.cos(camera.rotation.y)*Math.cos(camera.rotation.x)};

现在一切都很完美。错误在于仅使用 x 和 y 旋转矩阵,而没有考虑所有角度的 rz = 0,这稍微改变了矩阵。

After some intensive brain processing I figured out that

  1. My original look-at vector was (0, 0, 1)
  2. The z-rotation angle (roll) was always 0
  3. There was no reason for the rotation matrix found on Wikipedia not to work

By applying the full rotation matrix on the (0, 0, 1) vector and taking in account that rz = 0 the solution I got was:

normal = {
    x: Math.cos(camera.rotation.x)*Math.sin(camera.rotation.y),
    y: -Math.sin(camera.rotation.x),
    z: Math.cos(camera.rotation.y)*Math.cos(camera.rotation.x)};

And now everything works perfectly. The error was using only the x and y rotation matrices without taking in account rz = 0 for all angles which changed the matrix a little.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文