three.js在平滑着色自定义几何体时保持折痕

时间:2014-11-21 06:46:31

标签: three.js vertex-attributes

我通过向新的THREE.Geometry()添加顶点和面来创建自定义网格,然后在其上运行computeFaceNormals()和computeVertexNormals()以平滑渲染(我使用MeshPhongMaterial)。没有computevertexnormals,我的网格的一部分看起来是条纹的。问题是r69中包含的库存computeVertexNormals()忽略了锐边。它是一个优雅的功能,通过平均周围的面来建立每个顶点的法线。然而,它平均边缘的法线需要保持锐利的外观。对另一个question with the same topic提出了一些有希望的评论但是没有发布任何代码来解决保持边缘锐利的问题。

我试图修改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();
        }

    }

}

}

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

1 个答案:

答案 0 :(得分:0)

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

我正在用自制的阁楼建造我的几何形状。 function:基本上迭代一组形状(使用i)并在它们的顶点之间创建B样条(使用j),然后从B-Splines构造一个网格。修复是测试每个形状的每个顶点的角度。如果它的角度大于给定的阈值(我使用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!