代码之家  ›  专栏  ›  技术社区  ›  Robin Rodricks

如何在墙上旋转三维小摆线?

  •  0
  • Robin Rodricks  · 技术社区  · 15 年前

    我正在处理三维网格数据,我有很多三维三角形,我需要旋转它们来消除Z值,把它转换成二维三角形。

    用这个二维三角形,我在做一些向量计算。

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


    这是我正在使用的代码。
    我想不出怎么反转。

    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;
    
    2 回复  |  直到 10 年前
        1
  •  1
  •   sje397    15 年前

    plane equation . 然后,确定 quaternion 它表示 normal to the z axis

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

    v=(x,y,z)

    按q2旋转,

    rv=q2*q*q2^-1

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

    要再次旋转,请使用

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

    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);
    
        2
  •  0
  •   Andrew Beatty    15 年前

    推荐文章