我通过在新的THREE.Geometry()中添加顶点和面来创建自定义网格,然后在其上运行computeFaceNormals()和computeVertexNormals()来平滑渲染(我使用的是MeshPhongMaterial)。没有computevertexnormals,我的网格物体的一部分看起来是条纹的。问题在于,r69中包含的stock 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();
}
}
}
}
任何人都可以提供一种折痕检测策略,这样我可以得到带有一些尖锐边缘的平滑形状吗?提前致谢!
WestLangley在上面的评论中是正确的。为了获得我想要的锐利边缘,我在构造几何图形时仅复制了“折痕”上的顶点。然后,我使用了THREE.Geometry()原型中包含的标准computeVertexNormals()函数。
我当时正在使用自制的“阁楼”功能构造几何体:基本上是遍历一系列形状(使用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!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句