fix ball taper render in indexed mode

This commit is contained in:
Stewart Allen 2025-12-12 22:26:58 -05:00
commit d5cda790c0
8 changed files with 38 additions and 31 deletions

View file

@ -73,7 +73,7 @@ function prepareSlices(callback, scale = 1, offset = 0) {
let totalProgress; let totalProgress;
api.widgets.opacity(COLOR.slicing_opacity); api.widgets.setOpacity(COLOR.slicing_opacity);
let segtimes = {}, let segtimes = {},
segNumber = 0, segNumber = 0,
@ -325,12 +325,10 @@ function preparePreview(callback, scale = 1, offset = 0) {
event.emit('preview.begin', pMode); event.emit('preview.begin', pMode);
if (isCam) { if (isCam) {
api.widgets.opacity(isDark ? COLOR.cam_preview_opacity_dark : COLOR.cam_preview_opacity); api.widgets.setOpacity(isDark ? COLOR.cam_preview_opacity_dark : COLOR.cam_preview_opacity);
api.widgets.each(widget => { api.widgets.setColor(COLOR.cam_preview);
widget.setColor(COLOR.cam_preview);
});
} else if (offset === 0) { } else if (offset === 0) {
api.widgets.opacity(COLOR.preview_opacity); api.widgets.setOpacity(COLOR.preview_opacity);
} }
let mark = Date.now(), let mark = Date.now(),
@ -374,7 +372,7 @@ function preparePreview(callback, scale = 1, offset = 0) {
show.progress(0); show.progress(0);
if (!isCam) { if (!isCam) {
api.widgets.opacity(0); api.widgets.setOpacity(0);
} }
if (output.length) { if (output.length) {
@ -463,7 +461,7 @@ function parseCode(code, type) {
event.emit("code.load", {code, type}); event.emit("code.load", {code, type});
view.set_preview(); view.set_preview();
widgets.opacity(0); widgets.setOpacity(0);
client.parse({code, type, settings}, progress => { client.parse({code, type, settings}, progress => {
show.progress(progress, "parsing"); show.progress(progress, "parsing");

View file

@ -361,7 +361,7 @@ function updateSliderMax(set) {
function hideSlices() { function hideSlices() {
STACKS.clear(); STACKS.clear();
api.widgets.opacity(COLOR.model_opacity); api.widgets.setOpacity(COLOR.model_opacity);
api.widgets.each(function(widget) { api.widgets.each(function(widget) {
widget.setWireframe(false); widget.setWireframe(false);
}); });
@ -804,7 +804,7 @@ function setViewMode(mode) {
updateSpeeds(); updateSpeeds();
setVisibleLayer(); setVisibleLayer();
setWidgetVisibility(true); setWidgetVisibility(true);
api.widgets.opacity(1); api.widgets.setOpacity(1);
api.view.edges(api.local.getBoolean('model.edges')); api.view.edges(api.local.getBoolean('model.edges'));
break; break;
case VIEWS.SLICE: case VIEWS.SLICE:

View file

@ -82,7 +82,7 @@ function meshes() {
return out; return out;
} }
function opacity(value) { function setOpacity(value) {
api.widgets.each(w => w.setOpacity(value)); api.widgets.each(w => w.setOpacity(value));
api.space.update(); api.space.update();
} }
@ -103,16 +103,18 @@ export const widgets = {
meshes, meshes,
rename, rename,
replace, replace,
opacity, opacity(o) { setOpacity(o); console.trace('opacity() deprecated') },
annotate, annotate,
setIndexed, setIndexed,
setAxisIndex, setAxisIndex,
all() { return WIDGETS.slice() }, setColor(c,s) { api.widgets.each(widget => widget.setColor(c,undefined,s) )},
add(w) { return WIDGETS.push(w) }, setOpacity,
remove(w) { return WIDGETS.remove(w) }, all() { return WIDGETS.slice() },
filter(fn) { return WIDGETS = WIDGETS.filter(fn) }, add(w) { return WIDGETS.push(w) },
count() { return WIDGETS.length }, remove(w) { return WIDGETS.remove(w) },
each(fn) { WIDGETS.slice().forEach(widget => fn(widget)) }, filter(fn) { return WIDGETS = WIDGETS.filter(fn) },
for(fn) { widgets.each(fn) }, count() { return WIDGETS.length },
forid(id) { return WIDGETS.filter(w => w.id === id)[0] } each(fn) { WIDGETS.slice().forEach(widget => fn(widget)) },
for(fn) { widgets.each(fn) },
forid(id) { return WIDGETS.filter(w => w.id === id)[0] }
}; };

View file

@ -288,15 +288,15 @@ function toolUpdate(toolid, send) {
.add(sphere(frad, 20).translate(0, 0, -(tlen - frad * 2) / 2)) .add(sphere(frad, 20).translate(0, 0, -(tlen - frad * 2) / 2))
.add(cylinder(slen, srad, srad, 20, true).translate(0, 0, flen / 2)); .add(cylinder(slen, srad, srad, 20, true).translate(0, 0, flen / 2));
} else if (tool.isTaperBall()) { } else if (tool.isTaperBall()) {
const trad = Math.max(tool.tipDiameter() / 2, 0.001); const { b, r } = tool.getBallTaperParams();
const brad = trad; // ball radius equals tip radius // taper length excludes most of ball
const taperLen = flen - brad; // taper length excludes ball const taperLen = flen - b;
// shaft at top // shaft at top
mesh = cylinder(slen, srad, srad, 20, true).translate(0, 0, slen / 2) mesh = cylinder(slen, srad, srad, 20, true).translate(0, 0, slen / 2)
// taper cone in middle // taper cone in middle
.add(cylinder(taperLen, trad, frad, 20, true).translate(0, 0, -taperLen / 2)) .add(cylinder(taperLen, b, frad, 20, true).translate(0, 0, -taperLen / 2))
// ball at bottom // exposed ball at bottom
.add(sphere(brad, 20).translate(0, 0, -(taperLen + brad))); .add(sphere(r, 20).translate(0, 0, -taperLen));
} else if (tool.isTaperMill()) { } else if (tool.isTaperMill()) {
const trad = Math.max(tool.tipDiameter() / 2, 0.001); const trad = Math.max(tool.tipDiameter() / 2, 0.001);
mesh = cylinder(slen, srad, srad, 20, true).translate(0, 0, slen / 2) mesh = cylinder(slen, srad, srad, 20, true).translate(0, 0, slen / 2)

View file

@ -111,6 +111,8 @@ Object.assign(client, {
color: 0x888888, color: 0x888888,
side: THREE.DoubleSide side: THREE.DoubleSide
}); });
api.widgets.setColor(0x0055aa);
api.widgets.setOpacity(0.5);
client.send("animate_setup2", { settings }, ondone); client.send("animate_setup2", { settings }, ondone);
}, },

View file

@ -963,7 +963,7 @@ function validateTools(tools) {
function animate() { function animate() {
env.isAnimate = true; env.isAnimate = true;
api.widgets.opacity(env.isParsed ? 0 : 0.75); api.widgets.setOpacity(env.isParsed ? 0 : 0.75);
api.hide.slider(); api.hide.slider();
STACKS.clear(); STACKS.clear();
animFn().animate(api); animFn().animate(api);

View file

@ -132,7 +132,7 @@ class OpArea extends CamOp {
if (mode === 'clear') { if (mode === 'clear') {
let zMov = flatOff ?? 0; let zMov = flatOff ?? 0;
let zs = flats ? let zs = flats ?
flats.filter(z => z <= zTop && z >= zBottom).map(v => v + (zMov ?? 0)) : flats.filter(z => z <= zTop && z >= zBottom).map(v => v + zMov) :
down ? base_util.lerp(zTop, zBottom, down) : [ bounds.min.z ]; down ? base_util.lerp(zTop, zBottom, down) : [ bounds.min.z ];
let zroc = 0; let zroc = 0;
let zinc = 1 / zs.length; let zinc = 1 / zs.length;

View file

@ -78,6 +78,13 @@ class Tool {
return calcTaperAngle((flute_diam - taper_tip) / 2, flute_len); return calcTaperAngle((flute_diam - taper_tip) / 2, flute_len);
} }
getBallTaperParams() {
let a = this.getTaperAngle() * DEG2RAD,
r = (this.tipDiameter()/2) * (1 + Math.sin(a)) / Math.cos(a),
b = r * Math.cos(a);
return { a, r, b };
}
shaftLength() { shaftLength() {
return this.unitScale() * this.tool.shaft_len; return this.unitScale() * this.tool.shaft_len;
} }
@ -152,9 +159,7 @@ class Tool {
toolOffset = [], toolOffset = [],
maxo = -Infinity, maxo = -Infinity,
// ball taper magic // ball taper magic
a = this.getTaperAngle() * DEG2RAD, { b, r } = this.getBallTaperParams(),
r = (tip_dia/2) * (1 + Math.sin(a)) / Math.cos(a),
b = r * Math.cos(a),
pix_b = b / resolution, pix_b = b / resolution,
pix_r = r / resolution; pix_r = r / resolution;