我需要在场景中加载几个STL文件,其中一些文件具有反转/翻转面。这可以使用双面材料轻松固定(视觉上),但我尝试的是可视化错误的面,将材质指数从蓝色切换为红色。
如果我理解,镜像/翻转/反转面是顺时针而不是逆时针绘制的。但我们是在谈论构成面孔的三个向量吗?如果是这样,绕线顺序是face.a,face.b和face.c设置的顺序?或者我是否应该比较面部索引值以了解面部的绘制顺序?
我设置了一个JSFiddle来解决这个问题:这个STL模型有10个面,其中3个被反转或翻转。使用FaceNormalsHelper,您可以看到这3个普通助手指向模型的内部,而不是指向外部。我尝试了6种不同的方法来检查它,其中一些是从computeFaceNormals()的代码中提取的,没有运气。我还检查了FaceNormalsHelper以查看它是如何工作的,但它只是在法线方向上从面心中绘制一条线,但它无论是指向内部还是外部都无法计算。
(注意:为了从一种方法更改为另一种方法,您必须在脚本开头更改变量。方法1手动覆盖这三个面材料索引,只是为了可视化错误的方法(作为所有其他方法的验证)没有其他人得到好的结果..但方法2和3真的非常接近它,虽然不知何故其他两个面被检测为翻转。我想知道面角是否与此有关)
编辑:@manthrax建议的方法完美,比较每个面的边缘与所有其他面。如果以相同的方式绘制边缘(例如:面1边缘a-b匹配面2边缘a-b而不是b-a),则翻转。基本上,如果一个面有两个或多个标记为翻转的边缘,我们可以说整个面都被翻转了。检查JSFiddle以查看它是否正常工作。
function paintFlippedFaces(faceCheck){
for(var x=0; x<Object.keys(faceCheck).length; x++){
var flipCounter = 0;
if(faceCheck[x]['a-b']) flipCounter++;
if(faceCheck[x]['b-c']) flipCounter++;
if(faceCheck[x]['c-a']) flipCounter++;
console.log("face " + x + " has " +flipCounter+ " flipped edges" );
if(flipCounter >= 2){
geometry.faces[x].materialIndex = 1;
//geometry.faces.elementsNeedUpdate = true;
}
}
}
首先,“翻转”的面孔是完全主观的。您需要决定一些参数。对于凸体对象,存在非主观定义。例如,面部法线,其中一个面部顶点点缀,是> 0。
对于非凸体对象,您可以根据顶点的缠绕顺序进行一些猜测,以及任何2条边是否包含相同的顺序,这意味着您有1个正面和1个背面三角形共享边。 (这些三角形中的哪一个被翻转,但在非凸形情况下不一定可以识别。)
首先,你必须在你的几何体上使用.mergeVertices,以便在面上共享顶点...我认为stl为每个三角形定义了唯一的顶点,所以没有两个面共享的“边缘”的概念。
然后你可以循环遍历每个面......基本上任何2个共享相同2个顶点的边缘应该具有对立排序,或者面对面彼此相对。
因此,如果2个面具有像3,2和2,3那样的边,则它们都面向相同的方向..并且面是一致的。
如果两个不同的面都具有3,2和3,2的边缘,那么它们面向相反的方向,并且您可以将两个面标记为可能被翻转。被标记最多次的面是可能实际翻转的面。
这些是我能想到的最好的猜测测试来确定内部/外部,但这是一个棘手的问题。
Blender有一些“重新计算法线”方法,用于重新计算“内部”/“外部”,我认为这些方法基于类似的原理运作...所以你也可以看看那些。