add .dispose() for removed three geometry, update wiredge on geometry mutation

This commit is contained in:
Stewart Allen 2025-06-15 16:12:27 -04:00
commit a478f4b34b
4 changed files with 44 additions and 10 deletions

View file

@ -373,7 +373,7 @@ function space_init(data) {
let obj = int?.object; let obj = int?.object;
if (obj) api.selection.drag({ start: int.object }); if (obj) api.selection.drag({ start: int.object });
if (obj) obj.sketch_item?.sketch.drag({ start: int.object }); if (obj) obj.sketch_item?.sketch.drag({ start: int.object });
return event?.altKey ? undefined : api.objects(selection.count() ? true : false); return selection.count() ? api.objects(true) : undefined;
}); });
// called two ways: // called two ways:

View file

@ -442,6 +442,7 @@ function ui_build() {
div({ class: "menu-items" }, [ div({ class: "menu-items" }, [
menu_item('Bounds', () => { selection.boundsBox({ toggle: true }) }, 'B'), menu_item('Bounds', () => { selection.boundsBox({ toggle: true }) }, 'B'),
menu_item('Normals', () => { api.normals() }, 'N'), menu_item('Normals', () => { api.normals() }, 'N'),
hr(),
menu_item('WireEdges', () => { api.wireedges() }, 'W'), menu_item('WireEdges', () => { api.wireedges() }, 'W'),
menu_item('WireFaces', () => { api.wireframe() }, [ 'bi-shift', 'W' ]), menu_item('WireFaces', () => { api.wireframe() }, [ 'bi-shift', 'W' ]),
hr(), hr(),

View file

@ -78,6 +78,7 @@ class History {
} }
do(type, data) { do(type, data) {
console.log({ type, data });
switch (type) { switch (type) {
case 'move': { case 'move': {
let { set, dx, dy, dz } = data; let { set, dx, dy, dz } = data;

View file

@ -169,7 +169,6 @@ class MeshModel extends meshObject {
qrotate(quaternion) { qrotate(quaternion) {
this.log('model-rotate', quaternion.toArray()); this.log('model-rotate', quaternion.toArray());
this.geometry.applyQuaternion(quaternion); this.geometry.applyQuaternion(quaternion);
this.geometry._model_invalid = true;
this.updateBounds(); this.updateBounds();
} }
@ -177,7 +176,6 @@ class MeshModel extends meshObject {
if (x === 1 && y === 1 && z === 1) return; if (x === 1 && y === 1 && z === 1) return;
this.log('model-scale', ...arguments, this.bounds); this.log('model-scale', ...arguments, this.bounds);
this.geometry.scale(x, y, z); this.geometry.scale(x, y, z);
this.geometry._model_invalid = true;
this.updateBounds(); this.updateBounds();
} }
@ -185,7 +183,6 @@ class MeshModel extends meshObject {
if (!(x || y || z)) return; if (!(x || y || z)) return;
this.log('model-translate', ...arguments); this.log('model-translate', ...arguments);
this.geometry.translate(x, y, z); this.geometry.translate(x, y, z);
this.geometry._model_invalid = true;
this.updateBounds(); this.updateBounds();
} }
@ -237,8 +234,10 @@ class MeshModel extends meshObject {
// when geometry updates, recompute bounds for ray intersections // when geometry updates, recompute bounds for ray intersections
// and sync data to worker and indexed db // and sync data to worker and indexed db
updateBounds() { updateBounds() {
if (this._wire) if (this._wire) {
this._wire.geometry.attributes.position.needsUpdate = true; this._wire.geometry.attributes.position.needsUpdate = true;
this.updateWireEdges();
}
this.attributes.position.needsUpdate = true; this.attributes.position.needsUpdate = true;
this.geometry.computeBoundingBox(); this.geometry.computeBoundingBox();
this.geometry.computeBoundingSphere(); this.geometry.computeBoundingSphere();
@ -307,10 +306,12 @@ class MeshModel extends meshObject {
this.log('reload'); this.log('reload');
let was = this.wireframe(false); let was = this.wireframe(false);
let geo = this.mesh.geometry; let geo = this.mesh.geometry;
const oldGeo = geo;
geo = new BufferGeometry();
geo.setAttribute('position', new BufferAttribute(vertices, 3)); geo.setAttribute('position', new BufferAttribute(vertices, 3));
// signal util.box3expand that geometry changed
geo._model_invalid = true;
geo.computeVertexNormals(); geo.computeVertexNormals();
this.mesh.geometry = geo;
oldGeo.dispose();
// restore wireframe state // restore wireframe state
this.wireframe(was); this.wireframe(was);
// fixup normals // fixup normals
@ -443,19 +444,22 @@ class MeshModel extends meshObject {
if (bool.toggle) { if (bool.toggle) {
bool = !was; bool = !was;
} }
// no change
if (was === bool) { if (was === bool) {
return was; return was;
} }
if (was) { if (was) {
this.mesh.remove(this._wire); this.mesh.remove(this._wire);
this._wire?.geometry.dispose(); if (this._wire) {
this._wire.geometry.dispose();
this._wire.material.dispose();
}
this._wire = undefined; this._wire = undefined;
this.opacity({restore: true}); this.opacity({restore: true});
} }
if (bool && opt.edges) { if (bool && opt.edges) {
let edges = new THREE.EdgesGeometry(this.mesh.geometry, opt.edges); let edges = new THREE.EdgesGeometry(this.mesh.geometry, opt.edges);
this._wire = new THREE.LineSegments(edges, materials.wireline); this._wire = new THREE.LineSegments(edges, materials.wireline);
this._wire._edges = opt.edges;
this.mesh.add(this._wire); this.mesh.add(this._wire);
this.opacity({temp: opt.opacity || 0.15}); this.opacity({temp: opt.opacity || 0.15});
} else if (bool) { } else if (bool) {
@ -467,6 +471,15 @@ class MeshModel extends meshObject {
return was; return was;
} }
updateWireEdges() {
if (this._wire?.isLineSegments) {
const newEdges = new THREE.EdgesGeometry(this.mesh.geometry, this._wire._edges);
this._wire.geometry.dispose();
this._wire.material.dispose();
this._wire.geometry = newEdges;
}
}
normals(bool) { normals(bool) {
let was = this._norm ? true : false; let was = this._norm ? true : false;
if (bool === undefined) { if (bool === undefined) {
@ -574,6 +587,25 @@ class MeshModel extends meshObject {
this.group = undefined; this.group = undefined;
this.removed = 'pending'; this.removed = 'pending';
} else { } else {
// Clean up geometries and materials
if (this._wire) {
this._wire.geometry.dispose();
this._wire.material.dispose();
this._wire = undefined;
}
if (this._norm) {
this._norm.geometry.dispose();
this._norm.material.dispose();
this._norm = undefined;
}
if (this.mesh) {
this.mesh.geometry.dispose();
if (Array.isArray(this.mesh.material)) {
this.mesh.material.forEach(m => m.dispose());
} else {
this.mesh.material.dispose();
}
}
// manage lifecycle with worker, mesh app caches, etc // manage lifecycle with worker, mesh app caches, etc
this.destroy(); this.destroy();
// tag removed for debugging // tag removed for debugging