1

我通过向新的 THREE.Geometry() 添加顶点和面来创建自定义网格,然后在其上运行 computeFaceNormals() 和 computeVertexNormals() 以平滑渲染(我使用的是 MeshPhongMaterial)。如果没有 computevertexnormals,我的部分网格会出现条纹。问题是 r69 中包含的常用 computeVertexNormals() 忽略了锐边。这是一个优雅的函数,通过平均周围的面来构建每个顶点的法线。然而,它平均了我需要在外观上保持锐利的边缘的法线。对具有相同主题的另一个问题有一些有希望的评论但是没有发布代码来解决保持边缘锐利的问题。

我试图修改 computeVertexNormals() 以添加边缘检测,但没有运气。我的尝试是基于检测相邻面之间的角度,如果它在给定阈值内,则仅将它们的法线添加到平均值中。这是我的代码:

function computeVertexNormals( object, angle_threshold, areaWeighted ) { //will compute normals if faces diverge less than given angle (in degrees)

var v, vl, f, fl, face, vertices;

angle = angle_threshold * 0.0174532925; //degrees to radians

vertices = new Array( object.vertices.length );

for ( v = 0, vl = object.vertices.length; v < vl; v ++ ) {

    vertices[ v ] = new THREE.Vector3();

}

if ( areaWeighted && areaWeighted == true) {

    // vertex normals weighted by triangle areas
    // http://www.iquilezles.org/www/articles/normals/normals.htm

    var vA, vB, vC, vD;
    var cb = new THREE.Vector3(), ab = new THREE.Vector3(),
        db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();

    for ( f = 0, fl = object.faces.length; f < fl; f ++ ) {

        face = object.faces[ f ];

        vA = object.vertices[ face.a ];
        vB = object.vertices[ face.b ];
        vC = object.vertices[ face.c ];

        cb.subVectors( vC, vB );
        ab.subVectors( vA, vB );
        cb.cross( ab );

        vertices[ face.a ].add( cb );
        vertices[ face.b ].add( cb );
        vertices[ face.c ].add( cb );

    }

} else {

    for ( f = 0, fl = object.faces.length; f < fl; f ++ ) {

        face = object.faces[ f ];

            vertices[ face.a ].add(face.normal);
            vertices[ face.b ].add( face.normal );
            vertices[ face.c ].add( face.normal );
    }

}

for ( v = 0, vl = object.vertices.length; v < vl; v ++ ) {

    vertices[ v ].normalize();

}

for ( f = 0, fl = object.faces.length; f < fl; f ++ ) {

    face = object.faces[ f ];

    //**********my modifications are all in this last section*************

    if(face.normal && face.normal != undefined){

        if(vertices[ face.a ].angleTo(face.normal) < angle_threshold){
            face.vertexNormals[ 0 ] = vertices[ face.a ].clone();
        }else{
            face.vertexNormals[ 0 ] = face.normal.clone();
        }
        if(vertices[ face.b ].angleTo(face.normal) < angle_threshold){
            face.vertexNormals[ 1 ] = vertices[ face.b ].clone();
        }else{
            face.vertexNormals[ 1 ] = face.normal.clone();
        }
        if(vertices[ face.c ].angleTo(face.normal) < angle_threshold){
            face.vertexNormals[ 2 ] = vertices[ face.c ].clone();
        }else{
            face.vertexNormals[ 2 ] = face.normal.clone();
        }

    }

}

}

任何人都可以提供折痕检测策略,这样我就可以拥有带有锐利边缘的光滑形状吗?提前致谢!

4

1 回答 1

0

WestLangley 在上面的评论中是正确的。为了获得我想要的锐利边缘,我只是在构建几何图形时复制了“折痕”上的顶点。然后我使用了 THREE.Geometry() 原型中包含的标准 computeVertexNormals() 函数。

我正在使用自制的“loft”函数构建我的几何体:基本上是遍历一组形状(使用 i)并在它们的顶点之间创建 B 样条(使用 j),然后从 B 样条构造一个网格。解决方法是测试每个形状的每个顶点的角度。如果它的角度大于给定的阈值(我使用了 70 度),我第二次添加了 B 样条,有效地复制了顶点。对不起,如果下面的代码脱离上下文有点神秘。

                    //test if vertex is on a crease
                if (j == 0) {
                    before = arrCurves[i].vertices[j].clone().sub(arrCurves[i].vertices[arrCurves[i].vertices.length-1]);
                }else{
                    before = arrCurves[i].vertices[j].clone().sub(arrCurves[i].vertices[j-1]);
                }

                if (j == arrCurves[i].vertices.length-1) {
                    after = arrCurves[i].vertices[0].clone().sub(arrCurves[i].vertices[j]);
                }else{
                    after = arrCurves[i].vertices[j+1].clone().sub(arrCurves[i].vertices[j]);
                }   

                if( before.angleTo(after) > crease_threshold ){ 
                    //here's where I'm adding the curve for a second time to make the 'crease'
                    arrSplines.push(new THREE.SplineCurve3(nurbsCurve.getPoints(resolution)));
                }

像魅力一样工作,谢谢 WestLangley!

于 2014-11-22T23:01:05.927 回答