gpt4 book ai didi

c++ - Irrlicht:根据四个角坐标在3D空间绘制2D图像

转载 作者:行者123 更新时间:2023-11-28 05:04:58 24 4
gpt4 key购买 nike

我想创建一个函数,使用 Irrlicht 引擎在空间中定位自由 float 的 2D 光栅图像。其灵感来自函数 rgl::show2d在 R 包 rgl 中。可以找到 R 中的示例实现 here .

chewie in space

输入数据应限于图像的路径和包含相应绘图矩形的四个角坐标的表格。

我用 irrlicht 实现这一点的第一个非常原始但最终失败的方法:

创建一个立方体:

ISceneNode * picturenode = scenemgr->addCubeSceneNode();

压平一侧:

picturenode->setScale(vector3df(1, 0.001, 1));

添加图像作为纹理:

picturenode->setMaterialTexture(0, driver->getTexture("path/to/image.png"));

将展平的立方体放置在四个角坐标的中心位置。我只是用一个小函数 position_calc() 计算所有三个轴上的平均坐标。

vector3df position = position_calc(rcdf); picturenode->setPosition(position);

通过计算由四个角坐标定义的平面的法线、归一化结果并尝试以某种方式将生成的 vector 转换为旋转角度来确定对象旋转。

vector3df normal = normal_calc(rcdf);
vector3df angles = (normal.normalize()).getSphericalCoordinateAngles();
picturenode->setRotation(angles);

此解决方案未产生预期结果。旋转计算错误。使用这种方法,我也无法将图像正确缩放到它的角坐标。

如何修复我的工作流程?还是有我不知道的更好的方法来使用 Irrlicht 实现此目的?


编辑:感谢@spug,我相信我快到了。我尝试实现他的方法 2,因为 quaternions已经在 Irrlicht 中可用。这是我计算旋转的方法:

#include <Rcpp.h>
#include <irrlicht.h>
#include <math.h>

using namespace Rcpp;

core::vector3df rotation_calc(DataFrame rcdf) {

NumericVector x = rcdf["x"];
NumericVector y = rcdf["y"];
NumericVector z = rcdf["z"];

// Z-axis
core::vector3df zaxis(0, 0, 1);
// resulting image's normal
core::vector3df normal = normal_calc(rcdf);

// calculate the rotation from the original image's normal (i.e. the Z-axis)
// to the resulting image's normal => quaternion P.
core::quaternion p;
p.rotationFromTo(zaxis, normal);

// take the midpoint of AB from the diagram in method 1, and rotate it with
// the quaternion P => vector U.
core::vector3df MAB(0, 0.5, 0);
core::quaternion m(MAB.X, MAB.Y, MAB.Z, 0);
core::quaternion rot = p * m * p.makeInverse();
core::vector3df u(rot.X, rot.Y, rot.Z);

// calculate the rotation from U to the midpoint of DE => quaternion Q
core::vector3df MDE(
(x(0) + x(1)) / 2,
(y(0) + y(1)) / 2,
(z(0) + z(1)) / 2
);
core::quaternion q;
q.rotationFromTo(u, MDE);

// multiply in the order Q * P, and convert to Euler angles
core::quaternion f = q * p;
core::vector3df euler;
f.toEuler(euler);

// to degrees
core::vector3df degrees(
euler.X * (180.0 / M_PI),
euler.Y * (180.0 / M_PI),
euler.Z * (180.0 / M_PI)
);

Rcout << "degrees: " << degrees.X << ", " << degrees.Y << ", " << degrees.Z << std::endl;

return degrees;
}

结果几乎正确,但在一个轴上的旋转是错误的。有没有办法解决这个问题,或者我的实现是否存在固有缺陷?

这就是现在的结果。这些点标记了预期的角点。

berries in space

最佳答案

我想到了两种方法来做到这一点;两者都不是很优雅 - Irrlicht 将我们限制在球形极点上并没有帮助。

注意。下面假设 rcdf 以原点为中心;这是为了让旋转计算更直接一些。虽然很容易修复:

  1. 计算rcdf的中心点(平移偏移量)
  2. rcdf的所有点中减去这个
  3. 执行以下程序
  4. 将偏移量加回结果点。

先决条件:缩放

这很简单;只需计算 rcdf 中的宽度和高度与原始图像的比率,然后调用 setScaling

enter image description here


方法一:矩阵求逆

为此,我们需要一个支持 3x3 矩阵的外部库,因为 Irrlicht 只有 4x4(我相信)。

我们需要求解将图像从 X-Y 旋转到 rcdf 的矩阵方程。为此,我们在每个引用系中需要 3 个点。我们可以立即将其中两个设置为图像的相邻角;第三个必须指向图像平面之外(因为我们需要所有三个维度的数据来形成一个完整的基础)——所以要计算它,只需将每个图像的法线乘以某个偏移常数(比如 1)即可。

enter image description here

(注意原始图像上的点已经缩放)

因此,要求解的方程是:

enter image description here

(使用列符号)。 Eigen 库提供了 3x3 矩阵和逆矩阵的实现。

然后将此矩阵转换为球形极角:https://www.learnopencv.com/rotation-matrix-to-euler-angles/


方法二:

要计算从方向 vector A 到 B 旋转的四元数:Finding quaternion representing the rotation from one vector to another

  1. 计算从原始图像的法线(即 Z 轴)到 rcdf 的法线 => 四元数 P.

  2. 从方法1的图中取AB中点,用四元数P旋转它(http://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/ ) => vector U

  3. 计算从UDE中点的旋转=>四元数Q

  4. 按顺序Q * P相乘,转换为欧拉角:https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

(不确定 Irrlicht 是否支持四元数)

关于c++ - Irrlicht:根据四个角坐标在3D空间绘制2D图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45052226/

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