| 223 | const dot = triNrmX[t]*triNrmX[other] + triNrmY[t]*triNrmY[other] + triNrmZ[t]*triNrmZ[other]; |
| 224 | if (dot < sharpEdgeCos) { frozenVert[u] = 1; frozenVert[v] = 1; } |
| 225 | } |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | // Preserve-untextured (beta): freeze every vertex of an excluded face so |
| 230 | // collapses can neither move nor remove untextured geometry (fillets, fine |
| 231 | // CAD detail). excludeWeight is constant across a face's three vertices |
| 232 | // (see subdivision.js toNonIndexed), so testing the first corner suffices. |
| 233 | // Rejections land in rejectStats.frozen like sharp-edge freezes. |
| 234 | if (opts.preserveExcluded) { |
| 235 | const ew = geometry.attributes.excludeWeight; |
| 236 | if (ew) { |