graphics - 确定面法线的方向是否一致?

标签 graphics 3d game-physics 3d-modelling

我是计算机图形学的新手,因此如果我的某些语言不准确或问题遗漏了一些基本内容,我深表歉意。

给定一个顶点列表和一个面列表,是否可以正确计算面法线:

v1: x_1, y_1, z_1
v2: x_2, y_2, z_2
...
v_n: x_n, y_n, z_n
f1: v1,v2,v3
f2: v4,v2,v5
...
f_m: v_j, v_k, v_l

每个 x_i, y_i , z_i 指定 3d 空间中的顶点位置(但不一定是向量)

每个 f_i 包含指定它的三个顶点的索引。

我知道您可以使用面两侧的叉积来获得法线,但该法线的方向取决于边的顺序和选择(据我所知)。

鉴于这是我拥有的唯一数据,是否可以正确确定法线的方向?或者是否有可能至少一致地确定它们? (所有法线可能都指向错误的方向?)

最佳答案

在CG中,它是通过多边形缠绕规则来完成的。这意味着所有面均已定义,因此当直接观察面上时,点按 CW(或 CCW)顺序排列。然后使用叉积将得到一致的法线。

然而,许多网格不符合缠绕规则(有些面是 CW,有些是 CCW,但并不完全相同),对于那些网格来说,这是一个问题。我知道有两种方法:

  1. 适合简单的形状(不要太凹)

    face_normalface_center-cube_center 的点积符号将告诉您法线是指向对象内部还是外部。

    dot

    if ( dot( face_normal , face_center-cube_center ) >= 0.0 ) normal_points_out
    

    您甚至可以使用面部的任何点来代替面部中心。无论如何,对于更复杂的凹面形状,这将无法正常工作。

  2. 测试面上方的点是否在内部

    只需将面的中心沿法线方向移动一段小距离(不要太大),然后测试该点是否在多边形网格内:

    displacement

    if ( !inside( face_center+0.001*face_normal ) ) normal_points_out
    

    要检查点是否在内部,您可以使用 hit test

但是,如果法线仅用于照明计算,那么它的使用通常在点积内。所以我们可以使用它的abs值来代替,这将解决所有的照明问题,无论法线面如何。例如:

output_color = face_color * abs(dot(face_normal,light_direction))

一些gfx api已经实现了这个(寻找双面 Material 或法线,打开它们通常使用abs值...)例如在OpenGL中:

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

关于graphics - 确定面法线的方向是否一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57434507/

相关文章:

opengl - 为什么人们不将四面体用于天空盒?

c++ - 解析 wavefront obj 文件格式

r - 如何导出交互式 rgl 3D 绘图以共享或发布?

python - Python 中的 3D 模型(点/线)渲染器

game-physics - 给定任意凸二维多边形计算惯性矩

Android getX/getY 交错相对/绝对坐标

math - 像 Mathematica 这样的程序是如何绘制图形的?我该如何制作这样的程序?

java - 简单的 Java 按钮显示一个圆圈

java - 在 Java 3D 中拾取形状

cocos2d-iphone - 如何使 box2d 主体沿贝塞尔曲线/圆弧路径移动