filter shadow slivers on high poly models, add W ghost/wire hotkeys

This commit is contained in:
Stewart Allen 2025-12-27 19:11:55 -05:00
commit c3638262d0
5 changed files with 36 additions and 17 deletions

View file

@ -481,7 +481,11 @@ export function union(polys, minarea, all, opt = {}) {
}
for (i=0; i<out.length; i++) {
if (out[i]) uset.push(out[i]);
if (out[i]) {
if (!minarea || out[i].area() >= minarea) {
uset.push(out[i]);
}
}
}
opt.changes = length(uset) - lpre;

View file

@ -258,6 +258,7 @@ class KeyboardControl {
switch (evt.key) {
// case 'g': return this.#api.group.merge();
// case 'u': return this.#api.group.split();
case 'w': return $('render-edges').onclick();
}
}
@ -366,9 +367,6 @@ class KeyboardControl {
case this.#cca('o'): // tools
this.#api.show.tools();
break;
case this.#cca('c'): // local devices
this.#api.show.local();
break;
case this.#cca('v'): // toggle single slice view mode
if (this.#api.view.get() === this.#VIEWS.ARRANGE) {
this.#api.space.set_focus(this.#selection.widgets());
@ -399,6 +397,12 @@ class KeyboardControl {
this.#api.view.set(this.#VIEWS.ARRANGE);
}
break;
case this.#cca('w'): // set ghost
$('render-ghost').onclick();
break;
case this.#cca('W'): // set wireframe
$('render-wire').onclick();
break;
default:
this.#onUnhandledKey(evt);
handled = false;

View file

@ -112,7 +112,7 @@ function setVisibleLayer(h, l) {
* @param {number} [opacity] - Optional wireframe opacity
*/
function setWireframe(bool, color, opacity) {
api.widgets.each(function(w) { w.setWireframe(bool, color, opacity) });
api.widgets.each((w) => { w.setWireframe(bool, color, opacity) });
space.update();
}
@ -303,19 +303,19 @@ function updateStats(add) {
}
export const visuals = {
set_progress: setProgress,
set_wireframe: setWireframe,
set_edges: setEdges,
unit_scale: unitScale,
update_speeds: updateSpeeds,
update_slider: updateSlider,
update_slider_max: updateSliderMax,
update_stack_labels: updateStackLabelState,
update_stats: updateStats,
show_slices: showSlices,
hide_slices: hideSlices,
show_slider: showSlider,
hide_slider: hideSlider,
set_edges: setEdges,
set_progress: setProgress,
set_visible_layer: setVisibleLayer,
set_widget_visibility: setWidgetVisibility
set_widget_visibility: setWidgetVisibility,
set_wireframe: setWireframe,
show_slices: showSlices,
show_slider: showSlider,
unit_scale: unitScale,
update_slider_max: updateSliderMax,
update_slider: updateSlider,
update_speeds: updateSpeeds,
update_stack_labels: updateStackLabelState,
update_stats: updateStats
};

View file

@ -703,7 +703,18 @@ class Widget {
let minZabove = Math.min(Infinity, ...zover);
let shadow = this.#computeShadowAt(z - 0.005, minZabove);
if (minZabove < Infinity) {
shadow = POLY.union([...shadow, ...shadows[minZabove]], 0.001, true, { wasm: false });
shadow = POLY.union([...shadow, ...shadows[minZabove]], 0, true, { wasm: false });
// cull interior sliver voids
for (let poly of shadow) {
if (poly.inner) {
poly.inner = poly.inner.filter(inr => {
let A = inr.area();
let P = inr.perimeter();
let R = (2 * A / P);
return R > 0.05;
});
}
}
}
return shadows[z] = POLY.setZ(shadow, z);
}

View file

@ -105,9 +105,9 @@ export const widgets = {
replace,
opacity(o) { setOpacity(o); console.trace('opacity() deprecated') },
annotate,
setIndexed,
setAxisIndex,
setColor(c,s) { api.widgets.each(widget => widget.setColor(c,undefined,s) )},
setIndexed,
setOpacity,
all() { return WIDGETS.slice() },
add(w) { return WIDGETS.push(w) },