Math 将三维面绘制为二维面
我有三维网格,我想画每个面二维形状 我的想法是: 每一张脸 1.正常接触面部 2.从法向量获取旋转矩阵 3.将每个顶点与旋转矩阵相乘,以获得“类似2d”平面中的顶点 4.从变换的顶点获取2个坐标 我不知道这是否是最好的方法,所以欢迎任何建议 现在我正试图从法向量得到一个旋转矩阵, 我该怎么做 更新: 以下是我需要的直观说明: 目前我有四头肌,但没有问题 将它们转换为三角形 我想旋转一个面的顶点,这样 其中一个维度变平 我还需要存储人脸的原始三维旋转。 我想那将是面部的反向旋转 正常 我想我有点迷路了:) 这是我使用的一个基本原型: 我所做的就是获取当前对象,访问第一个面,获取法线,获取顶点,计算旋转矩阵,将其反转,然后将其乘以每个顶点。 最后我编写了一个简单的输出 以下是我手动将所有顶点旋转30度的默认平面的输出:Math 将三维面绘制为二维面,math,opengl,3d,vector,matrix,Math,Opengl,3d,Vector,Matrix,我有三维网格,我想画每个面二维形状 我的想法是: 每一张脸 1.正常接触面部 2.从法向量获取旋转矩阵 3.将每个顶点与旋转矩阵相乘,以获得“类似2d”平面中的顶点 4.从变换的顶点获取2个坐标 我不知道这是否是最好的方法,所以欢迎任何建议 现在我正试图从法向量得到一个旋转矩阵, 我该怎么做 更新: 以下是我需要的直观说明: 目前我有四头肌,但没有问题 将它们转换为三角形 我想旋转一个面的顶点,这样 其中一个维度变平 我还需要存储人脸的原始三维旋转。 我想那将是面部的反向旋转 正常 我想我有点
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