Math 将三维面绘制为二维面

Math 将三维面绘制为二维面,math,opengl,3d,vector,matrix,Math,Opengl,3d,Vector,Matrix,我有三维网格,我想画每个面二维形状 我的想法是: 每一张脸 1.正常接触面部 2.从法向量获取旋转矩阵 3.将每个顶点与旋转矩阵相乘,以获得“类似2d”平面中的顶点 4.从变换的顶点获取2个坐标 我不知道这是否是最好的方法,所以欢迎任何建议 现在我正试图从法向量得到一个旋转矩阵, 我该怎么做 更新: 以下是我需要的直观说明: 目前我有四头肌,但没有问题 将它们转换为三角形 我想旋转一个面的顶点,这样 其中一个维度变平 我还需要存储人脸的原始三维旋转。 我想那将是面部的反向旋转 正常 我想我有点

我有三维网格,我想画每个面二维形状

我的想法是: 每一张脸 1.正常接触面部 2.从法向量获取旋转矩阵 3.将每个顶点与旋转矩阵相乘,以获得“类似2d”平面中的顶点 4.从变换的顶点获取2个坐标

我不知道这是否是最好的方法,所以欢迎任何建议

现在我正试图从法向量得到一个旋转矩阵, 我该怎么做

更新:

以下是我需要的直观说明:

目前我有四头肌,但没有问题 将它们转换为三角形

我想旋转一个面的顶点,这样 其中一个维度变平

我还需要存储人脸的原始三维旋转。 我想那将是面部的反向旋转 正常

我想我有点迷路了:)

这是我使用的一个基本原型:

我所做的就是获取当前对象,访问第一个面,获取法线,获取顶点,计算旋转矩阵,将其反转,然后将其乘以每个顶点。 最后我编写了一个简单的输出

以下是我手动将所有顶点旋转30度的默认平面的输出:

Plane.008
face: [MFace (0 3 2 1) 0]
normal: [0.000000, -0.499985, 0.866024](vector)
original vertex0: [1.000000, 0.866025, 0.500000](vector)
original vertex1: [-1.000000, 0.866026, 0.500000](vector)
original vertex2: [-1.000000, -0.866025, -0.500000](vector)
original vertex3: [1.000000, -0.866025, -0.500000](vector)

rotated vertex0: [1.000000, 0.866025, 1.000011](vector)
rotated vertex1: [-1.000000, 0.866026, 1.000012](vector)
rotated vertex2: [-1.000000, -0.866025, -1.000012](vector)
rotated vertex3: [1.000000, -0.866025, -1.000012](vector)
这是著名的苏珊娜网眼布的第一张脸:

Suzanne.001
face: [MFace (46 0 2 44) 0]
normal: [0.987976, -0.010102, 0.154088](vector)
original vertex0: [0.468750, 0.242188, 0.757813](vector)
original vertex1: [0.437500, 0.164063, 0.765625](vector)
original vertex2: [0.500000, 0.093750, 0.687500](vector)
original vertex3: [0.562500, 0.242188, 0.671875](vector)

rotated vertex0: [0.468750, 0.242188, -0.795592](vector)
rotated vertex1: [0.437500, 0.164063, -0.803794](vector)
rotated vertex2: [0.500000, 0.093750, -0.721774](vector)
rotated vertex3: [0.562500, 0.242188, -0.705370](vector)
来自Plane.008网格的顶点将被更改,来自Suzanne.001网格的顶点将被更改 不是。他们不应该吗?我应该期望在一个轴上得到零吗? 从法向量得到旋转矩阵后,x,y,z上的旋转是什么

注:1。搅拌机的矩阵支持*运算符2。在搅拌机的坐标系中,Z点向上。它看起来像一个右手系统,在X轴上旋转90度


谢谢,我觉得这很合理。下面是如何得到一个好的答案。法线是向量。角度是0。你可能想要反向旋转


你的网格是三角形的吗?我想是的。如果是这样,您可以在不使用旋转矩阵的情况下执行此操作。将面点设为
A、B、C
。取脸的任意两个顶点,例如
A
B
。沿矢量定义x轴
AB
<代码>A位于
0,0
<代码>B位于
0,|AB |
<通过使用
AC
AB
之间的角度(通过使用点积获得)和长度
|AC

可以从三角法确定code>C,
正确创建了m矩阵。这是与法向量对应的旋转。您可以使用此矩阵的逆矩阵来“取消旋转”点。
face2d
的法线将为
x
,即沿x轴的点。因此,提取相应的二维坐标。(这假设您的四边形近似为平面。)

我不知道您正在使用的库(处理),所以我只是假设有m.invert()的方法和一个将旋转矩阵应用于点的操作符。它们当然可以被称为其他东西。幸运的是,纯旋转矩阵的逆矩阵是它的转置,如果需要,将矩阵和向量相乘很容易手动完成

void setup(){
  size(400,400,P3D);
  background(255);
  stroke(0,0,120);
  smooth();
  fill(0,120,0);

  PVector x = new PVector(1,0,0);
  PVector y = new PVector(0,1,0);
  PVector z = new PVector(0,0,1);

  PVector n  = new PVector(0.378521084785,0.925412774086,0.0180059205741);//normal
  PVector p0 = new PVector(0.372828125954,-0.178844243288,1.35241031647);
  PVector p1 = new PVector(-1.25476706028,0.505195975304,0.412718296051);
  PVector p2 = new PVector(-0.372828245163,0.178844287992,-1.35241031647);
  PVector p3 = new PVector(1.2547672987,-0.505196034908,-0.412717700005);

  PVector[] face = {p0,p1,p2,p3};
  PVector[] face2d = new PVector[4];

  //what do I do with this ?
  float c = cos(0), s = sin(0);
  float x2 = n.x*n.x,y2 = n.y*n.y,z2 = n.z*n.z; 
  PMatrix3D m_inverse = 
      new PMatrix3D(x2+(1-x2)*c, n.x*n.y*(1-c)+n.z*s, n.x*n.y*(1-c)-n.y*s, 0,
                    n.x*n.y*(1-c)-n.z*s,y2+(1-y2)*c,n.x*n.z*(1-c)+n.x*s,   0,
                     n.x*n.z*(1-c)+n.y*s,n.y*n.z*(1-c)-n.x*s,z2-(1-z2)*c,  0,
                    0,0,0,1);

  face2d[0] = m_inverse * p0; // Assuming there's an appropriate operator*().
  face2d[1] = m_inverse * p1; 
  face2d[2] = m_inverse * p2;
  face2d[3] = m_inverse * p3;

  // print & draw as you did before...

}

对于面v0-v1-v3-v2,矢量v3-v0、v3-v2和面法线已形成旋转矩阵,可将二维面转换为三维面

矩阵表示坐标系。每行(或列,取决于符号)对应于新坐标系中的轴坐标系。三维旋转/平移矩阵可以表示为:

vx.x    vx.y    vx.z    0
vy.x    vy.y    vy.z    0
vz.x    vz.y    vz.z    0
vp.x    vp.y    vp.z    1
其中vx是坐标系的x轴、vy-y轴、vz-z轴和新系统的vp原点

假设v3-v0为y轴(第2行)、v3-v2-x轴(第1行)和法线-z轴(第3行)。从中构建矩阵。然后求逆矩阵。您将得到一个矩阵,该矩阵将三维面旋转为二维面

我有三维网格,我想画每个面二维形状


我想这比尝试从3d面获取旋转矩阵更接近您想要实现的目标。

这很容易实现:(注意:所谓“面”是指“三角形”)

  • 创建一个视图矩阵,该矩阵表示正在查看面的摄影机。
  • 使用双线性插值确定面中心
  • 确定面的法线
  • 将相机放置在与法线方向相反的部分
  • 让相机注视脸部的中心
  • 在面的任何顶点的中间方向上设置摄影机向量点
  • 将纵横比设置为1
  • 使用此数据计算视图矩阵
  • 创建正交投影矩阵。
  • 将视锥台的宽度和高度设置为足以容纳整个面(例如,面最长位置的长度)
  • 计算投影矩阵
  • 对于面的每个顶点v,将其乘以两个矩阵:v*视图*投影

  • 其结果是将3d面投影到2d空间,就好像您在看它们时完全正交,没有任何透视干扰。最终坐标将在标准化屏幕坐标中,其中(-1,-1)是左下角,(0,0)是中心,(1,1)是右上角。

    我已经阅读了wiki页面的这一部分,但无法了解如何使用信息:(.你是对的,我想我需要反向旋转。网格目前没有进行三角剖分,但可以轻松地进行三角剖分。你的方法听起来不错,这会给我一组二维三角形,但我会失去面部的三维旋转。我已经更新了我的答案,以说明我正在努力做得更好。哦,代码没有链接到il清净。在代码中,我对顶点在x、y和z轴上旋转的平面进行编码。图中显示了我试图实现的目标。在wikipedia页面,
    u
    是包含x、y和z分量的法向量(如果有
    void setup(){
      size(400,400,P3D);
      background(255);
      stroke(0,0,120);
      smooth();
      fill(0,120,0);
    
      PVector x = new PVector(1,0,0);
      PVector y = new PVector(0,1,0);
      PVector z = new PVector(0,0,1);
    
      PVector n  = new PVector(0.378521084785,0.925412774086,0.0180059205741);//normal
      PVector p0 = new PVector(0.372828125954,-0.178844243288,1.35241031647);
      PVector p1 = new PVector(-1.25476706028,0.505195975304,0.412718296051);
      PVector p2 = new PVector(-0.372828245163,0.178844287992,-1.35241031647);
      PVector p3 = new PVector(1.2547672987,-0.505196034908,-0.412717700005);
    
      PVector[] face = {p0,p1,p2,p3};
      PVector[] face2d = new PVector[4];
    
      //what do I do with this ?
      float c = cos(0), s = sin(0);
      float x2 = n.x*n.x,y2 = n.y*n.y,z2 = n.z*n.z; 
      PMatrix3D m_inverse = 
          new PMatrix3D(x2+(1-x2)*c, n.x*n.y*(1-c)+n.z*s, n.x*n.y*(1-c)-n.y*s, 0,
                        n.x*n.y*(1-c)-n.z*s,y2+(1-y2)*c,n.x*n.z*(1-c)+n.x*s,   0,
                         n.x*n.z*(1-c)+n.y*s,n.y*n.z*(1-c)-n.x*s,z2-(1-z2)*c,  0,
                        0,0,0,1);
    
      face2d[0] = m_inverse * p0; // Assuming there's an appropriate operator*().
      face2d[1] = m_inverse * p1; 
      face2d[2] = m_inverse * p2;
      face2d[3] = m_inverse * p3;
    
      // print & draw as you did before...
    
    }
    
    vx.x    vx.y    vx.z    0
    vy.x    vy.y    vy.z    0
    vz.x    vz.y    vz.z    0
    vp.x    vp.y    vp.z    1