I created a custom mesh by adding vertices and faces to a new THREE.Geometry(), then running computeFaceNormals() and computeVertexNormals() on it to smooth out the rendering (I'm using the MeshPhongMaterial). Without computevertexnormals, parts of my mesh appear striped. The problem is that the stock computeVertexNormals() included in r69 ignores sharp edges. It's an elegant function that builds each vertex's normal by averaging the surrounding faces. However it averages the normals at edges that I need to remain sharp in appearance. There were some promising comments on another question with the same topic However no code was posted to solve the issue of keeping edges sharp.
I have attempted to modify computeVertexNormals() to add edge detection but with no luck. My attempt is based on detecting the angle between neighboring faces and only adding their normal to the average if it's within a given threshold. Here's my code:
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();
}
}
}
}
Can anybody please offer a strategy for crease detection so I can have smooth shapes with some sharp edges? Thanks in advance!