fix focus, bounding box calc, edge edit

This commit is contained in:
Stewart Allen 2025-06-15 11:50:30 -04:00
commit 9c85187923
6 changed files with 24 additions and 64 deletions

View file

@ -230,7 +230,7 @@ function space_init(data) {
case 'KeyQ':
return api.settings();
case 'KeyI':
return shiftKey ? api.tool.invert() : api.file.import();
return api.file.import();
case 'KeyX':
return api.file.export();
case 'KeyD':
@ -251,8 +251,10 @@ function space_init(data) {
return;
case 'KeyV':
return shiftKey ? selection.show() : selection.focus();
case 'KeyR':
return estop(evt, api.tool.rename());
case 'KeyN':
return shiftKey ? estop(evt, api.tool.rename()) : api.normals();
return shiftKey ? api.tool.invert() : api.normals();
case 'KeyW':
return api.wireframe();
case 'KeyG':
@ -371,7 +373,7 @@ function space_init(data) {
let obj = int?.object;
if (obj) api.selection.drag({ start: int.object });
if (obj) obj.sketch_item?.sketch.drag({ start: int.object });
return event?.shiftKey ? undefined : api.objects(selection.count() ? true : false);
return event?.altKey ? undefined : api.objects(selection.count() ? true : false);
});
// called two ways:
@ -490,7 +492,6 @@ function space_init(data) {
function load_files(files) {
log(`loading file...`);
let api = api;
let has_image = false;
let has_svg = false;
let has_gbr = false;

View file

@ -1526,14 +1526,14 @@ const api = {
}
},
// @param object {THREE.Object3D | THREE.Object3D[] | Point}
// @param object {MeshObject | MeshObject[]}
focus(object) {
let { center } = object.center ? object : meshUtil.bounds(object);
let { center } = meshUtil.bounds(object);
// when no valid objects supplied, set origin
if (isNaN(center.x * center.y * center.z)) {
center = { x: 0, y: 0, z: 0 };
}
let { normal } = object;
let { normal } = object.object;
let left, up;
if (normal) {
let { x, y, z } = normal;

View file

@ -510,6 +510,7 @@ function ui_build() {
menu_item('Flip Normals', tool.invert, ['bi-shift','I']),
menu_item('Triangulate', tool.triangulate, ['bi-shift','T']),
menu_item('To Sketch', tool.toSketch),
hr(),
menu_item('Analyze', tool.analyze),
menu_item('Flatten', tool.flatten),
menu_item('Clean', tool.clean),

View file

@ -8,7 +8,7 @@
import { THREE, Line2, LineSegmentsGeometry, LineSegments2, LineGeometry, LineMaterial } from '../ext/three.js';
import { space as motoSpace } from '../moto/space.js';
import { newPoint } from '../geo/point.js';
import { api as meshApi } from './api.js';
import { api } from './api.js';
const { Vector3, Group } = THREE;
@ -44,7 +44,7 @@ function cmp(v1, v2) {
// points equal if all axis values are within tolerance of each other
function eq(p1, p2) {
return
return true &&
cmp(p1.x, p2.x) &&
cmp(p1.y, p2.y) &&
cmp(p1.z, p2.z);
@ -61,8 +61,6 @@ const edges = {
return;
}
let { api } = meshApi;
isActive = true;
selected.length = 0;
obj.visible = false;
@ -71,7 +69,7 @@ const edges = {
// enable temp mode
let state = edges.state = { obj };
let models = state.models = api.selection.models();
let models = state.models = api.model.list();
let meshes = models.map(m => m.mesh);
// find closest facet edge to hover location
@ -105,7 +103,7 @@ const edges = {
space.scene.remove(edges.selected);
space.mouse.onHover(undefined);
isActive = edges.state = undefined;
meshApi.api.selection.update();
api.selection.update();
},
async add() {

View file

@ -86,7 +86,7 @@ class MeshObject {
}
focus() {
api.focus(this.object);
api.focus(this);
return this;
}

View file

@ -69,26 +69,25 @@ const util = {
// @param object {THREE.Object3D | THREE.Object3D[] | MeshObject | MeshObject[]}
// @returns bounds modified for moto.space
bounds(object) {
// console.log({ bounds: object });
let box = new Box3();
if (Array.isArray(object)) {
for (let o of object) {
util.box3expand(box, o instanceof meshObject ? o.object : o);
box.union(o.bounds);
}
} else if (object) {
util.box3expand(box, object instanceof meshObject ? object.object : object);
} else {
return box;
box.union(object.bounds);
}
let bnd = {
min: {
x: box.min.x,
y: box.min.z,
z: box.min.y
},
y: box.min.y,
z: box.min.z
},
max: {
x: box.max.x,
y: box.max.z,
z: box.max.y
y: box.max.y,
z: box.max.z
}
};
bnd.size = bnd.dim = {
@ -97,52 +96,13 @@ const util = {
z: bnd.max.z - bnd.min.z
};
bnd.center = bnd.mid = {
x: (bnd.max.x + bnd.min.x) / 2,
x: (bnd.max.x + bnd.min.x) / 2,
y: -(bnd.max.y + bnd.min.y) / 2,
z: (bnd.max.z + bnd.min.z) / 2
z: (bnd.max.z + bnd.min.z) / 2
};
return bnd;
},
// bounding box workaround adapted from:
// https://discourse.threejs.org/t/bounding-box-bigger-than-concave-object-extrudegeometry/26073/2
// https://discourse.threejs.org/t/invalid-bounds-generated-for-some-orientations/33205
box3expand(box3, object) {
if (object._no_bounds) {
return;
}
let geometry = object.geometry;
object.updateWorldMatrix(geometry ? true : false, false);
if (geometry) {
let matrix = object.matrixWorld;
let bkey = [matrix.elements.map(v => v.round(5))].join(',')
let cached = boundsCache[object.id];
// geometry._model_invalid set on model.reload(), usually after a split
if (!cached || cached.bkey !== bkey || geometry._model_invalid) {
let position = geometry.attributes.position.clone();
position.applyMatrix4(new Matrix4().extractRotation(matrix));
let bounds = new Box3().setFromBufferAttribute(position);
// let scale = new Vector3().setFromMatrixScale(matrix);
// bounds.min.multiply(scale);
// bounds.max.multiply(scale);
cached = boundsCache[object.id] = { bkey, bounds };
geometry._model_invalid = undefined;
}
let bt = cached.bounds.clone();
let m4 = new Matrix4();
m4.setPosition(new Vector3().setFromMatrixPosition(object.matrixWorld));
bt.applyMatrix4(m4);
box3.union(bt);
}
let children = object.children;
for (let i = 0, l = children.length; i < l; i++) {
util.box3expand(box3, children[i]);
}
},
// extract object fields into an array with optional rounding
extract(object, opt = {}) {
let field = opt.fields || ['x', 'y', 'z'];