(kind)
| 3084 | // Dispose old preview material so it gets fully recreated |
| 3085 | if (previewMaterial) { |
| 3086 | previewMaterial.dispose(); |
| 3087 | previewMaterial = null; |
| 3088 | } |
| 3089 | |
| 3090 | loadGeometry(currentGeometry); |
| 3091 | |
| 3092 | // Reset displacement preview (an in-flight build used the old pose) |
| 3093 | cancelDisplacementPreviewBuild(); |
| 3094 | if (dispPreviewGeometry) { dispPreviewGeometry.dispose(); dispPreviewGeometry = null; } |
| 3095 | settings.useDisplacement = false; |
| 3096 | dispPreviewToggle.checked = false; |
| 3097 | |
| 3098 | // Deactivate tools but keep the paint (face indices are stable after rotation) |
| 3099 | exclusionTool = null; |
| 3100 | eraseMode = false; |
| 3101 | isPainting = false; |
| 3102 | exclBrushBtn.classList.remove('active'); |
| 3103 | exclBucketBtn.classList.remove('active'); |
| 3104 | exclBrushTypeRow.classList.add('hidden'); |
| 3105 | exclRadiusRow.classList.add('hidden'); |
| 3106 | exclHardnessRow.classList.add('hidden'); |
| 3107 | exclThresholdRow.classList.add('hidden'); |
| 3108 | canvas.style.cursor = ''; |
| 3109 | setHoverPreview(null); |
| 3110 | _lastHoverTriIdx = -1; |
| 3111 | |
| 3112 | // Rebuild adjacency and carry the paint onto the moved vertices |
| 3113 | const adjData = buildAdjacency(currentGeometry); |
| 3114 | triangleAdjacency = adjData.adjacency; |
| 3115 | triangleCentroids = adjData.centroids; |
| 3116 | triangleFaceNormals = adjData.faceNormals; |
| 3117 | _rebuildPaintTreeKeepingPaint(adjData); |
| 3118 | |
| 3119 | // Update edge length for new bounds |
| 3120 | const diag = Math.sqrt(currentBounds.size.x ** 2 + currentBounds.size.y ** 2 + currentBounds.size.z ** 2); |
| 3121 | const defaultEdge = Math.max(0.05, Math.min(5.0, +(diag / 300).toFixed(2))); |
| 3122 | settings.refineLength = defaultEdge; |
| 3123 | refineLenSlider.value = defaultEdge; |
| 3124 | refineLenVal.value = defaultEdge; |
| 3125 | checkResolutionWarning(); |
| 3126 | |
| 3127 | // Update mesh info |
| 3128 | const triCount = getTriangleCount(currentGeometry); |
| 3129 | const mb = ((currentGeometry.attributes.position.array.byteLength) / 1024 / 1024).toFixed(2); |
| 3130 | const sx = currentBounds.size.x.toFixed(2); |
| 3131 | const sy = currentBounds.size.y.toFixed(2); |
| 3132 | const sz = currentBounds.size.z.toFixed(2); |
| 3133 | _setMeshInfo(triCount, mb, sx, sy, sz); |
| 3134 | |
| 3135 | exportBtn.disabled = !_hasTexturedLayer(); |
| 3136 | export3mfBtn.disabled = !_hasTexturedLayer(); |
| 3137 | bakeBtn.disabled = !_hasTexturedLayer(); |
| 3138 | updateSmartResBtnState(); |
| 3139 | updatePreview(); |
| 3140 | |
| 3141 | // Rebuild the paint display with the new vertex positions (face indices unchanged) |
no test coverage detected