math - 将 3d 面绘制为 2d

标签 math opengl 3d vector matrix

我有 3d 网格,我想为每个面绘制 2d 形状。

我想到的是:
每张脸
1.访问人脸正常
2.从法向量中得到一个旋转矩阵
3. 将每个顶点与旋转矩阵相乘,得到“2d like”平面中的顶点
4.从变换后的顶点获取2个坐标

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

目前我正在尝试从法线向量中获取旋转矩阵,
我该怎么做?

更新:

这是我需要的视觉解释:

3d to 2d

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

我想旋转一个面的顶点,这样
其中一个尺寸变平了。

我还需要存储面部的原始 3d 旋转。
我想那将是面部的反向旋转
普通的。

我想我在太空中有点迷失了:)

这是我使用 Processing 制作的基本原型(prototype):

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];
  PVector   nr = PVector.add(n,new PVector());//clone normal

  float rx = degrees(acos(n.dot(x)));//angle between normal and x axis
  float ry = degrees(acos(n.dot(y)));//angle between normal and y axis
  float rz = degrees(acos(n.dot(z)));//angle between normal and z axis

  PMatrix3D r = new PMatrix3D();
  //is this ok, or should I drop the builtin function, and add 
  //the rotations manually
  r.rotateX(rx);
  r.rotateY(ry);
  r.rotateZ(rz);

  print("original: ");println(face);
  for(int i = 0 ; i < 4; i++){
    PVector rv = new PVector();
    PVector rn = new PVector();
    r.mult(face[i],rv);
    r.mult(nr,rn);
    face2d[i] = PVector.add(face[i],rv);
  }
  print("rotated: ");println(face2d);
  //draw
  float scale = 100.0;
  translate(width * .5,height * .5);//move to centre, Processing has 0,0 = Top,Lef
  beginShape(QUADS);
  for(int i = 0 ; i < 4; i++){
   vertex(face2d[i].x * scale,face2d[i].y * scale,face2d[i].z * scale);
  }
  endShape();
  line(0,0,0,nr.x*scale,nr.y*scale,nr.z*scale);

  //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 = new PMatrix3D(x2+(1-x2)*c,  n.x*n.y*(1-c)-n.z*s,  n.x*n.z*(1-c)+n.y*s,  0,
                              n.x*n.y*(1-c)+n.z*s,y2+(1-y2)*c,n.y*n.z*(1-c)-n.x*s,0,
                              n.x*n.y*(1-c)-n.y*s,n.x*n.z*(1-c)+n.x*s,z2-(1-z2)*c,0,
                              0,0,0,1);
}

更新

对不起,如果我变得烦人,但我似乎不明白。

这是使用Blender的一点python的 API:
import Blender
from Blender import *
import math
from math import sin,cos,radians,degrees

def getRotMatrix(n):
    c = cos(0)
    s = sin(0)
    x2 = n.x*n.x
    y2 = n.y*n.y
    z2 = n.z*n.z
    l1 = x2+(1-x2)*c, n.x*n.y*(1-c)+n.z*s, n.x*n.y*(1-c)-n.y*s
    l2 = n.x*n.y*(1-c)-n.z*s,y2+(1-y2)*c,n.x*n.z*(1-c)+n.x*s
    l3 = n.x*n.z*(1-c)+n.y*s,n.y*n.z*(1-c)-n.x*s,z2-(1-z2)*c
    m = Mathutils.Matrix(l1,l2,l3)
    return m

scn = Scene.GetCurrent()
ob = scn.objects.active.getData(mesh=True)#access mesh

out = ob.name+'\n'
#face0
f = ob.faces[0]
n = f.v[0].no
out += 'face: ' + str(f)+'\n'
out += 'normal: ' + str(n)+'\n'

m = getRotMatrix(n)
m.invert()

rvs = []
for v in range(0,len(f.v)):
    out += 'original vertex'+str(v)+': ' + str(f.v[v].co) + '\n'
    rvs.append(m*f.v[v].co)

out += '\n'
for v in range(0,len(rvs)):
    out += 'original vertex'+str(v)+': ' + str(rvs[v]) + '\n'

f = open('out.txt','w')
f.write(out)
f.close

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

这是我手动将所有顶点旋转 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 网格的第一张脸:
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. Blender 的矩阵支持 * 运算符 2. 在 Blender 的坐标系中 Z 点向上。它看起来像一个右手系统,在 X 上旋转了 90 度。

谢谢

最佳答案

这在我看来是合理的。以下是如何获得 rotation matrix from normal vector .法线是向量。角度为 0。您可能需要反向旋转。

你的网格是三角形的吗?我假设它是。如果是这样,您可以在没有旋转矩阵的情况下执行此操作。设人脸点为A,B,C .取面部的任意两个顶点,例如 AB .沿向量 AB 定义 x 轴. A0,0 . B0,|AB| . C可以使用 AC 之间的角度从三角函数中确定和 AB (通过使用点积得到)和长度 |AC| .

关于math - 将 3d 面绘制为 2d,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3269806/

相关文章:

python - python中的谐波级数

python - vpython绘制半球

css - 使用 css 在 3d 透视中创建一个圆 Angular 矩形

java - 用于具有 2D 逻辑的 3D 游戏的 Libgdx scene2d?

opengl - (GLSL)同时从不同角度渲染多个 channel

ruby - ruby 中的算术

javascript - 在 JavaScript 中计算两个或三个数字的 LCM

iphone - CGFloat的乘除法和精度损失

c++ - Opengl - 实例化属性

c++ - 为什么重启原语需要发送十六进制索引? OpenGL