如何将 3D 三角形旋转到靠墙平放?

发布于 2024-09-19 07:57:02 字数 1201 浏览 5 评论 0 原文

我正在处理 3D 网格数据,其中有很多 3D 三角形,我需要旋转它们以消除 Z 值,将其转换为 2D 三角形。

我正在用这个二维三角形进行一些向量计算。

完成工作后,我需要将其旋转回原始角度,以便旧点返回到其原始位置,以重新适合 3D 网格。


编辑:这是我正在使用的代码。
我不知道如何反转旋转。

输入

var p1:Object, p2:Object, p3:Object;

查找面法线

var norm:Object = calcNormal(p1,p2,p3);

根据法线查找旋转角度

sinteta = -norm.y / Math.sqrt(norm.x * norm.x + norm.y * norm.y);
costeta = norm.x / Math.sqrt(norm.x * norm.x + norm.y * norm.y);
sinfi = -Math.sqrt(norm.x * norm.x + norm.y * norm.y);
cosfi = norm.z;

绕 Z 旋转,然后绕 Y 旋转以与 z 平面对齐。

lx = costeta * cosfi;
ly = -sinteta * cosfi;
lz = sinfi;

mx = sinteta;
my = costeta;
mz = 0;

nx = -sinfi * costeta;
ny = sinfi * sinteta;
nz = cosfi;

var np1:Object = {};
np1.x=p1.x*lx + p1.y*ly + p1.z*lz;
np1.y=p1.x*mx + p1.y*my + p1.z*mz;
np1.z=p1.x*nx + p1.y*ny + p1.z*nz;

var np2:Object = {};
np2.x=p2.x*lx + p2.y*ly + p2.z*lz;
np2.y=p2.x*mx + p2.y*my + p2.z*mz;
np2.z=p2.x*nx + p2.y*ny + p2.z*nz;

var np3:Object = {};
np3.x=p3.x*lx + p3.y*ly + p3.z*lz;
np3.y=p3.x*mx + p3.y*my + p3.z*mz;
np3.z=p3.x*nx + p3.y*ny + p3.z*nz;

I'm working with 3D mesh data, where I have lots of 3D triangles which I need to rotate to eliminate the Z value, converting it to a 2D triangle.

With this 2D triangle I'm doing some vector calculations.

After I'm done with my work I need to rotate it back to the original angle such that the old points return back to their original positions, to fit back into the 3D mesh.


Edit: This is the code I'm using.
I can't figure out how to reverse the rotation.

Inputs

var p1:Object, p2:Object, p3:Object;

Find face normal

var norm:Object = calcNormal(p1,p2,p3);

Find rotation angles based on normal

sinteta = -norm.y / Math.sqrt(norm.x * norm.x + norm.y * norm.y);
costeta = norm.x / Math.sqrt(norm.x * norm.x + norm.y * norm.y);
sinfi = -Math.sqrt(norm.x * norm.x + norm.y * norm.y);
cosfi = norm.z;

Rotate around Z and then Y to align to the z plane.

lx = costeta * cosfi;
ly = -sinteta * cosfi;
lz = sinfi;

mx = sinteta;
my = costeta;
mz = 0;

nx = -sinfi * costeta;
ny = sinfi * sinteta;
nz = cosfi;

var np1:Object = {};
np1.x=p1.x*lx + p1.y*ly + p1.z*lz;
np1.y=p1.x*mx + p1.y*my + p1.z*mz;
np1.z=p1.x*nx + p1.y*ny + p1.z*nz;

var np2:Object = {};
np2.x=p2.x*lx + p2.y*ly + p2.z*lz;
np2.y=p2.x*mx + p2.y*my + p2.z*mz;
np2.z=p2.x*nx + p2.y*ny + p2.z*nz;

var np3:Object = {};
np3.x=p3.x*lx + p3.y*ly + p3.z*lz;
np3.y=p3.x*mx + p3.y*my + p3.z*mz;
np3.z=p3.x*nx + p3.y*ny + p3.z*nz;

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

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

发布评论

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

评论(2

傲世九天 2024-09-26 07:57:02

使用平面方程确定平面的法线。然后,确定一个代表 四元数 www.gamedev.net/community/forums/topic.asp?topic_id=429507" rel="nofollow noreferrer">垂直于 z 轴。旋转多边形,完成工作,然后将其旋转回来。

通过从 'w' = 0 的向量创建四元数,可以将向量旋转四元数:

v = (x, y, z)
q = (w=0, x, y, z)

旋转 q2,

rv = q2 * q * q2 ^ -1

要将 rv 转换为点,请删除 w(即 0)。

要再次旋转回来,请使用

q2 ^ -1 * rv * q,

其中 q2 ^ -1 是 q2 的倒数或共轭。

编辑 2

适用于 C++ 代码,但这是我的 Vector3d 和四元数类的工作方式(简化):

class Vector3d {
  //...
  double x, y, z;
  //...
  // functions here e.g. dot (dot product), cross (cross product)
};

class Quaternion {
  //...
  double w, x, y, z;
  //...
  Quaternion inverse() const { // also equal to conjugate for unit quaternions
    return Quaternion (w, -x, -y, -z);
  }

  static Quaternion align(const Vector3d v1, const Vector3d v2) {
    Vector3d bisector = (v1 + v2).normalize();
    double cosHalfAngle = v1.dot(bisector);
    Vector3d cross;

    if(cosHalfAngle == 0.0) {
      cross = v1.cross(bisector);
    } else {
      cross = v1.cross(Vector3d(v2.z, v2.x, v2.y)).normalize();
    }

    return Quaternion(cosHalfAngle, cross.x, cross.y, cross.z);
  }

  Quaternion operator *(const Quaternion &q) const {
    Quaternion r;

    r.w = w * q.w - x * q.x - y * q.y - z * q.z;
    r.x = w * q.x + x * q.w + y * q.z - z * q.y;
    r.y = w * q.y + y * q.w + z * q.x - x * q.z;
    r.z = w * q.z + z * q.w + x * q.y - y * q.x;

    return r;
  }
};

因此,使用这种数学,其想法是使用“对齐”方法创建一个四元数它表示从垂直于 z 轴的平面进行的旋转(即 v1 是平面法线[标准化],v2 是 z 轴单位向量)- 我们称之为 Q。要旋转每个点 p,您将创建一个四元数 q,对于点,将其旋转 qr,然后将 q 转换回点 p2,如下所示:

q = Quaternion(0, p.x, p.y, p.z);
qr = Q * q * Q.inverse();
p2 = Vector3d(qr.x, qr.y, qr.z);

要再次将 p2 旋转回来,请执行以下操作:

q = Quaternion(0, p2.x, p2.y, p2.z);
qr = Q.inverse() * q * Q;
p = Vector3d(qr.x, qr.y, qr.z);

Determine the normal of the plane using the plane equation. Then, determine a quaternion that represents the rotation of the normal to the z axis. Rotate the polygon, do your work, and rotate it back.

A vector can be rotated by a quaternion by creating a quaternion from the vector where 'w' = 0:

v = (x, y, z)
q = (w=0, x, y, z)

To rotate by q2,

rv = q2 * q * q2 ^ -1

To convert rv to a point, drop the w (which is 0).

To rotate back again, use

q2 ^ -1 * rv * q

where q2 ^ -1 is the inverse or conjugate of q2.

EDIT 2

Appologies for the C++ code, but here is how my Vector3d and Quaternion classes work (simplified):

class Vector3d {
  //...
  double x, y, z;
  //...
  // functions here e.g. dot (dot product), cross (cross product)
};

class Quaternion {
  //...
  double w, x, y, z;
  //...
  Quaternion inverse() const { // also equal to conjugate for unit quaternions
    return Quaternion (w, -x, -y, -z);
  }

  static Quaternion align(const Vector3d v1, const Vector3d v2) {
    Vector3d bisector = (v1 + v2).normalize();
    double cosHalfAngle = v1.dot(bisector);
    Vector3d cross;

    if(cosHalfAngle == 0.0) {
      cross = v1.cross(bisector);
    } else {
      cross = v1.cross(Vector3d(v2.z, v2.x, v2.y)).normalize();
    }

    return Quaternion(cosHalfAngle, cross.x, cross.y, cross.z);
  }

  Quaternion operator *(const Quaternion &q) const {
    Quaternion r;

    r.w = w * q.w - x * q.x - y * q.y - z * q.z;
    r.x = w * q.x + x * q.w + y * q.z - z * q.y;
    r.y = w * q.y + y * q.w + z * q.x - x * q.z;
    r.z = w * q.z + z * q.w + x * q.y - y * q.x;

    return r;
  }
};

So using this kind of maths, the idea is that you create a quaterion using the 'align' method which represents a rotation from the plane normal to the z axis (i.e. v1 is plane normal [normalized], v2 is z axis unit vector) - lets call that Q. To rotate each point, p, you would create a quaternion, q, for the point, rotate it, qr, then convert q back to a point, p2, like so:

q = Quaternion(0, p.x, p.y, p.z);
qr = Q * q * Q.inverse();
p2 = Vector3d(qr.x, qr.y, qr.z);

To rotate p2 back again, do:

q = Quaternion(0, p2.x, p2.y, p2.z);
qr = Q.inverse() * q * Q;
p = Vector3d(qr.x, qr.y, qr.z);
枫林﹌晚霞¤ 2024-09-26 07:57:02

旋转三角形几乎肯定是错误的方法。如果您的目的是修改三角形,那么您应该只在其当前(3d)坐标系中执行操作。如果您的目的不是修改三角形,则无需将其旋转回来。如果您不知道如何在当前坐标系中执行所需的操作,请提出该问题。

Rotating the triangle is almost certainly the wrong approach. If your intent is to modify the triangle, then you should just perform the operations in its current (3d) coordinate system. If your intent is not to modify the triangle then you don't need to rotate it back. If you don't know how to perform the operations you want to in its current coordinate system, then ask that question.

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