如何在墙上旋转 3D 三角形平面? [英] How to rotate a 3D tringle flat against the wall?

查看:25
本文介绍了如何在墙上旋转 3D 三角形平面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

使用这个 2D 三角形,我正在做一些矢量计算.

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

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

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.

这是我正在使用的代码.
我不知道如何反转旋转.

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

输入

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 平面对齐.

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;

推荐答案

使用 平面方程.然后,确定一个 quaternion 表示 垂直于 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.

一个向量可以被四元数旋转,方法是从向量中创建一个四元数,其中 'w' = 0:

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)

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

要旋转q2,

rv = q2 * q * q2 ^ -1

rv = q2 * q * q2 ^ -1

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

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

要再次旋转回来,请使用

To rotate back again, use

q2 ^ -1 * rv * q

q2 ^ -1 * rv * q

其中 q2 ^ -1 是 q2 的逆或共轭.

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

编辑 2

C++ 代码的应用程序,但这里是我的 Vector3d 和 Quaternion 类的工作方式(简化):

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;
  }
};

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

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);

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

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);

这篇关于如何在墙上旋转 3D 三角形平面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆