()
| 3816 | } |
| 3817 | } |
| 3818 | } |
| 3819 | } |
| 3820 | const dist = Math.sqrt(minDist2); |
| 3821 | const factor = Math.min(1, dist / falloff); |
| 3822 | if (factor < 1) { |
| 3823 | falloffById[id] = applyFalloffCurve(factor); |
| 3824 | maskTypeById[id] = nearestType; |
| 3825 | } |
| 3826 | } |
| 3827 | |
| 3828 | // Write per-vertex attributes via the welded id (no re-keying pass) |
| 3829 | for (let i = 0; i < posCount; i++) { |
| 3830 | const id = vertId[i]; |
| 3831 | if (falloffById[id] >= 0) falloffArr[i] = falloffById[id]; |
| 3832 | if (maskTypeById[id] >= 0) maskTypeArr[i] = maskTypeById[id]; |
| 3833 | } |
| 3834 | |
| 3835 | if (reuseFalloff) existingFalloff.needsUpdate = true; |
| 3836 | else geometry.setAttribute('boundaryFalloffAttr', new THREE.Float32BufferAttribute(falloffArr, 1)); |
| 3837 | if (reuseType) existingType.needsUpdate = true; |
| 3838 | else geometry.setAttribute('boundaryMaskTypeAttr', new THREE.Float32BufferAttribute(maskTypeArr, 1)); |
| 3839 | } |
| 3840 | |
| 3841 | /** |
| 3842 | * Compute boundary edge segments between masked and non-masked faces and |
| 3843 | * pack them into a DataTexture for per-fragment distance queries in the |
| 3844 | * bump-only preview shader. Each edge is stored as two RGBA texels |
| 3845 | * (endpoint A xyz, endpoint B xyz). |
| 3846 | */ |
| 3847 | function computeBoundaryEdges(geometry, userMaskArr) { |
| 3848 | const posAttr = geometry.attributes.position; |
| 3849 | const posCount = posAttr.count; |
| 3850 | const triCount = posCount / 3; |
| 3851 | const falloff = settings.boundaryFalloff ?? 0; |
| 3852 | |
| 3853 | if (_boundaryEdgeTex) { _boundaryEdgeTex.dispose(); _boundaryEdgeTex = null; } |
| 3854 | _boundaryEdgeCount = 0; |
| 3855 | if (falloff <= 0) return; |
| 3856 | |
| 3857 | const faceNrmAttr = geometry.attributes.faceNormal; |
| 3858 | const faceMaskBool = new Uint8Array(triCount); |
| 3859 | for (let t = 0; t < triCount; t++) { |
| 3860 | if (userMaskArr[t * 3] < 0.5) { faceMaskBool[t] = 0; continue; } |
| 3861 | let angleMask = 1.0; |
no test coverage detected