@@ -607,28 +607,63 @@ class SculptMesh {
607607 _updateVerticesNormal ( iVerts ) {
608608
609609 const nAr = this . _normalsXYZ ;
610+ const vAr = this . _verticesXYZ ;
611+ const fAr = this . _facesABCD ;
610612 const faceNormals = this . _faceNormals ;
611613 const ringFaces = this . _vertRingFace ;
612614 const full = iVerts === undefined ;
613615 const nbVerts = full ? this . _nbVertices : iVerts . length ;
614616
617+ // MWSELR: weight = sin(angle) / (|e1| * |e2|)
618+ // Since sin(angle) = |cross(e1,e2)| / (|e1|*|e2|),
619+ // weight = |cross(e1,e2)| / (|e1|^2 * |e2|^2)
620+
615621 for ( let i = 0 ; i < nbVerts ; ++ i ) {
616622
617623 const ind = full ? i : iVerts [ i ] ;
618624 const vrf = ringFaces [ ind ] ;
625+ const ind3 = ind * 3 ;
626+ const vx = vAr [ ind3 ] , vy = vAr [ ind3 + 1 ] , vz = vAr [ ind3 + 2 ] ;
619627 let nx = 0 , ny = 0 , nz = 0 ;
628+
620629 for ( let j = 0 , l = vrf . length ; j < l ; ++ j ) {
621630
622- const id = vrf [ j ] * 3 ;
623- nx += faceNormals [ id ] ;
624- ny += faceNormals [ id + 1 ] ;
625- nz += faceNormals [ id + 2 ] ;
631+ const fId = vrf [ j ] * 4 ;
632+ const iv1 = fAr [ fId ] , iv2 = fAr [ fId + 1 ] , iv3 = fAr [ fId + 2 ] ;
633+
634+ // Find the two other vertices of this face
635+ let ov1 , ov2 ;
636+ if ( iv1 === ind ) { ov1 = iv2 ; ov2 = iv3 ; }
637+ else if ( iv2 === ind ) { ov1 = iv3 ; ov2 = iv1 ; }
638+ else { ov1 = iv1 ; ov2 = iv2 ; }
639+
640+ const o1 = ov1 * 3 , o2 = ov2 * 3 ;
641+ const e1x = vAr [ o1 ] - vx , e1y = vAr [ o1 + 1 ] - vy , e1z = vAr [ o1 + 2 ] - vz ;
642+ const e2x = vAr [ o2 ] - vx , e2y = vAr [ o2 + 1 ] - vy , e2z = vAr [ o2 + 2 ] - vz ;
643+
644+ const len1sq = e1x * e1x + e1y * e1y + e1z * e1z ;
645+ const len2sq = e2x * e2x + e2y * e2y + e2z * e2z ;
646+ const denom = len1sq * len2sq ;
647+ if ( denom === 0 ) continue ;
648+
649+ // cross(e1, e2) magnitude = sin(angle) * |e1| * |e2|
650+ const cx = e1y * e2z - e1z * e2y ;
651+ const cy = e1z * e2x - e1x * e2z ;
652+ const cz = e1x * e2y - e1y * e2x ;
653+ const sinArea = Math . sqrt ( cx * cx + cy * cy + cz * cz ) ;
654+
655+ // weight = sinArea / (|e1|^2 * |e2|^2) = sin(angle) / (|e1| * |e2|)
656+ const w = sinArea / denom ;
657+
658+ const fnId = vrf [ j ] * 3 ;
659+ nx += faceNormals [ fnId ] * w ;
660+ ny += faceNormals [ fnId + 1 ] * w ;
661+ nz += faceNormals [ fnId + 2 ] * w ;
626662
627663 }
628664
629665 let len = Math . sqrt ( nx * nx + ny * ny + nz * nz ) ;
630666 if ( len > 0 ) len = 1.0 / len ;
631- const ind3 = ind * 3 ;
632667 nAr [ ind3 ] = nx * len ;
633668 nAr [ ind3 + 1 ] = ny * len ;
634669 nAr [ ind3 + 2 ] = nz * len ;
0 commit comments