【问题标题】:three.js maintaining creases when smooth shading custom geometrythree.js 在平滑着色自定义几何图形时保持折痕
【发布时间】:2015-01-19 06:16:32
【问题描述】:

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

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

    }

}

}

谁能提供一种折痕检测策略,这样我就可以制作出带有锐利边缘的光滑形状吗? 提前致谢!

【问题讨论】:

  • 在构建几何体时,请考虑在硬边上复制顶点。

标签: three.js vertex-attributes


【解决方案1】:

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!

【讨论】:

  • 我从我在这里找到的答案中了解到,主要由 WestLangley 和他直接提供的答案,复制边缘是解决问题的关键。我想我成功地复制了边缘并在此基础上绘制了新面孔。以这种方式构建的立方体(如和 IndexedFaceSet)看起来仍然完全平滑。然而,内置的 Cube 或 Box 几何形状看起来完全一样。我希望内置几何图形可以在合理的情况下呈现锐利的边缘。我很困惑他们不是。
猜你喜欢
  • 2013-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 2012-10-12
  • 1970-01-01
  • 2017-03-28
相关资源
最近更新 更多