working manual refresh

master
howard 2021-04-16 16:03:30 -07:00
parent 930df2e288
commit 69b2fff6d1
11 changed files with 144 additions and 91 deletions

View File

@ -194,10 +194,10 @@ export class Scene {
} else if (k[0] == 'e') { } else if (k[0] == 'e') {
entries[k] = loader.parse(state.byId[k]) entries[k] = loader.parse(state.byId[k])
if (entries[k].userData.inverted) { if (entries[k].userData.inverted) {
flipBufferGeometryNormals(entries[k].geometry) flipBufferGeometryNormals(entries[k].geometry)
} }
this.obj3d.add(entries[k]) this.obj3d.add(entries[k])
@ -235,7 +235,7 @@ export class Scene {
} }
boolOp(m1, m2, op) { boolOp(m1, m2, op, refresh = false) {
let bspA = CSG.fromMesh(m1) let bspA = CSG.fromMesh(m1)
let bspB = CSG.fromMesh(m2) let bspB = CSG.fromMesh(m2)
m1.visible = false m1.visible = false
@ -275,18 +275,51 @@ export class Scene {
mesh.add(vertices) mesh.add(vertices)
sc.obj3d.add(mesh) if (!refresh) {
sc.obj3d.add(mesh)
this.store.dispatch({ this.store.dispatch({
type: 'set-entry-visibility', obj: { type: 'set-entry-visibility', obj: {
[m1.name]: false, [m1.name]: false,
[m2.name]: false, [m2.name]: false,
[mesh.name]: true, [mesh.name]: true,
} }
}) })
this.store.dispatch({
type: 'rx-boolean', mesh, deps: [m1.name, m2.name]
})
} else {
return mesh
}
return mesh
} }
refreshNode(id) {
let curId
let que = [id]
let idx = 0
const { byId, tree } = this.store.getState().treeEntries
while (idx < que.length) {
curId = que[idx++]
const info = byId[curId].userData.featureInfo
let newNode
if (info.length == 2) {
newNode = this.extrude(byId[info[0]], info[1], true)
} else if (info.length == 3) {
newNode = this.boolOp(byId[info[0]], byId[info[1]], info[2], true)
}
byId[curId].geometry.copy(newNode.geometry)
for (let k in tree[curId]) {
que.push(k)
}
}
}
} }

View File

@ -310,12 +310,36 @@ class Sketch {
for (let j = 0; j < link.length; j++) { for (let j = 0; j < link.length; j++) {
const obj = this.obj3d.children[i + j] const obj = this.obj3d.children[i + j]
obj.geometry.dispose() // obj.geometry.dispose()
obj.material.dispose() // obj.material.dispose()
for (let c_id of obj.userData.constraints.slice()) { // i hate js obj.traverse((ob) => {
if (ob.geometry) ob.geometry.dispose()
if (ob.material) ob.material.dispose()
})
// collect all coincident constraints to be reconnected
// after deleting this point
let arr = []
let cons
for (let c_id of obj.userData.constraints.slice()) {
// i hate js, slice is important because deleteContraints mutates constraints array
cons = this.constraints.get(c_id)
if (cons[0] == 'points_coincident') {
arr.push(cons[2][0] == obj.name ?
cons[2][1] : cons[2][0]
)
}
this.deleteConstraints(c_id) this.deleteConstraints(c_id)
} }
for (let i = 0; i < arr.length - 1; i++) {
setCoincident.call(this,[
this.obj3d.children[this.objIdx.get(arr[i])],
this.obj3d.children[this.objIdx.get(arr[i+1])]
])
}
obj.userData.constraints = [] obj.userData.constraints = []
} }

View File

@ -1,8 +1,15 @@
import { color } from './shared' import { color } from './shared'
export async function setCoincident() { export async function setCoincident(sel) {
let selection = await this.awaitSelection({ point: 2 }, { point: 1, line: 1 }) let selection
if (selection == null) return; if (sel === undefined) {
selection = await this.awaitSelection({ point: 2 }, { point: 1, line: 1 })
if (selection == null) return;
} else {
selection = sel
}
if (selection.every(e => e.userData.type == 'point')) { if (selection.every(e => e.userData.type == 'point')) {
this.constraints.set(++this.c_id, this.constraints.set(++this.c_id,
[ [

View File

@ -1,6 +1,6 @@
import * as THREE from '../node_modules/three/src/Three'; import * as THREE from '../node_modules/three/src/Three';
import { color } from './shared' import { color } from './shared'
export function extrude(sketch, depth) { export function extrude(sketch, depth, refresh=false) {
let constraints = sketch.constraints; let constraints = sketch.constraints;
let linkedObjs = sketch.linkedObjs; let linkedObjs = sketch.linkedObjs;
@ -10,7 +10,7 @@ export function extrude(sketch, depth) {
let v2s = [] let v2s = []
function findPair(node) { function findPair(node) {
console.log(node.name,'xx') // console.log(node.name, 'xx')
if (node.userData.construction) return; if (node.userData.construction) return;
visited.add(node) visited.add(node)
let linkedObj = linkedObjs.get(node.userData.l_id) let linkedObj = linkedObjs.get(node.userData.l_id)
@ -43,7 +43,7 @@ export function extrude(sketch, depth) {
) )
] ]
if (d == children[2]) { if (d == children[2]) {
console.log('pair found') // console.log('pair found')
}; };
findTouching(d) findTouching(d)
@ -51,19 +51,19 @@ export function extrude(sketch, depth) {
function findTouching(node) { function findTouching(node) {
console.log(node.name,'yy') // console.log(node.name, 'yy')
for (let t of node.userData.constraints) { for (let t of node.userData.constraints) {
console.log(constraints.get(t)[2],node.name ) // console.log(constraints.get(t)[2], node.name)
if (constraints.get(t)[0] != 'points_coincident') continue if (constraints.get(t)[0] != 'points_coincident') continue
for (let c of constraints.get(t)[2]) { for (let c of constraints.get(t)[2]) {
if (c == -1) continue; if (c == -1) continue;
const d = children[objIdx.get(c)] const d = children[objIdx.get(c)]
if (d == node) continue; if (d == node) continue;
if (d == children[2]) { if (d == children[2]) {
console.log('loop found') // console.log('loop found')
} else { } else {
// if (!visited.has(d)) { // if (!visited.has(d)) {
findPair(d) findPair(d)
// } // }
}; };
} }
@ -71,7 +71,7 @@ export function extrude(sketch, depth) {
} }
findPair(children[2]) //??? need fixing findPair(children[sketch.geomStartIdx + 1]) // ?? possibly allow user select search start point
const shape = new THREE.Shape(v2s); const shape = new THREE.Shape(v2s);
// const extrudeSettings = { depth: Math.abs(depth), bevelEnabled: false }; // const extrudeSettings = { depth: Math.abs(depth), bevelEnabled: false };
@ -88,27 +88,9 @@ export function extrude(sketch, depth) {
const mesh = new THREE.Mesh(geometry, material) const mesh = new THREE.Mesh(geometry, material)
// const material = new THREE.MeshPhongMaterial({
// color: color.mesh,
// });
// const wireframe = new THREE.WireframeGeometry( geometry );
// const mesh = new THREE.LineSegments( wireframe );
// mesh.material.depthTest = true;
// mesh.material.opacity = 0.8;
// mesh.material.transparent = true;
// const edges = new THREE.EdgesGeometry( geometry, 15 );
// edges.type = 'BufferGeometry'
// edges.parameters = undefined
// const mesh = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( { color: 0x000000 } ) );
mesh.name = 'e' + this.mid++ mesh.name = 'e' + this.mid++
// mesh.name = 'm' + sketch.obj3d.name.slice(1)
// mesh.name = 'e' + sketch.obj3d.name.slice(1)
mesh.userData.type = 'mesh' mesh.userData.type = 'mesh'
mesh.userData.featureInfo = [sketch.obj3d.name, depth] mesh.userData.featureInfo = [sketch.obj3d.name, depth]
mesh.layers.enable(1) mesh.layers.enable(1)
@ -119,12 +101,6 @@ export function extrude(sketch, depth) {
mesh.add(vertices) mesh.add(vertices)
mesh.matrixAutoUpdate = false; mesh.matrixAutoUpdate = false;
mesh.matrix.multiply(sketch.obj3d.matrix) mesh.matrix.multiply(sketch.obj3d.matrix)
@ -134,25 +110,22 @@ export function extrude(sketch, depth) {
} }
this.obj3d.add(mesh) if (!refresh) {
this.obj3d.add(mesh)
this.store.dispatch({ type: 'rx-extrusion', mesh, sketchId: sketch.obj3d.name }) this.store.dispatch({ type: 'rx-extrusion', mesh, sketchId: sketch.obj3d.name })
// sketch.userData if (this.activeSketch == sketch) {
if (this.activeSketch == sketch) { sketch.deactivate()
this.activeSketch = null }
sketch.deactivate() this.render()
} else {
return mesh
} }
// this.clearSelection()
this.render()
} }
export function flipBufferGeometryNormals(geometry) { export function flipBufferGeometryNormals(geometry) {
//https://stackoverflow.com/a/54496265 //https://stackoverflow.com/a/54496265
const tempXYZ = [0, 0, 0]; const tempXYZ = [0, 0, 0];

View File

@ -1,20 +1,15 @@
export class DepTree { export class DepTree {
constructor(obj) { constructor(obj) {
if (obj) { this.order = { ...obj.order }
this.order = { ...obj.order } this.byId = { ...obj.byId }
this.byId = { ...obj.byId } this.allIds = [...obj.allIds]
this.allIds = [...obj.allIds]
this.tree = {} this.tree = {}
for (let k in obj.tree) { for (let k in obj.tree) {
this.tree[k] = { ...obj.tree[k] } this.tree[k] = { ...obj.tree[k] }
}
} else {
this.tree = {}
this.order = {}
this.allIds = []
} }
} }
addParent(id) { addParent(id) {
@ -71,7 +66,7 @@ export class DepTree {
const deletedObj = sc.obj3d.children.splice(spliceIdx + 1, 1)[0] // first 1 elements are non geom const deletedObj = sc.obj3d.children.splice(spliceIdx + 1, 1)[0] // first 1 elements are non geom
deletedObj.traverse((obj)=>{ deletedObj.traverse((obj) => {
if (obj.geometry) obj.geometry.dispose() if (obj.geometry) obj.geometry.dispose()
if (obj.material) obj.material.dispose() if (obj.material) obj.material.dispose()
}) })
@ -95,6 +90,9 @@ export class DepTree {
} }
return this return this
} }
} }
@ -103,7 +101,7 @@ export class DepTree {
// const dt = new DepTree() // const dt = new DepTree()
// dt.addParent('r1') // dt.addParent('r1')
// dt.addParent('r2') // dt.addParent('r2')
// dt.addChild('r3', 'r1', 'r2') // dt.addChild('r3', 'r1', 'r2')s
// dt.addParent('r4') // dt.addParent('r4')
// dt.addChild('r5', 'r4', 'r3') // dt.addChild('r5', 'r4', 'r3')
// dt.addChild('r6', 'r1', 'r5') // dt.addChild('r6', 'r1', 'r5')
@ -128,3 +126,6 @@ export class DepTree {
// allIds: [ 'r1', 'r2', 'r3', 'r4', 'r8' ] // allIds: [ 'r1', 'r2', 'r3', 'r4', 'r8' ]
// } // }

View File

@ -22,21 +22,28 @@ export const Dialog = ({ dialog, setDialog }) => {
}, []) }, [])
const extrude = () => { const extrude = () => {
let sketch
if (sc.activeSketch) { if (sc.activeSketch) {
sc.extrude(sc.activeSketch, ref.current.value) sketch = sc.activeSketch
setDialog(null)
} else if (sc.selected.length === 1 && sc.selected[0].userData.type == 'sketch') { } else if (sc.selected.length === 1 && sc.selected[0].userData.type == 'sketch') {
sc.extrude(treeEntriesById[sc.selected[0].name], ref.current.value) sketch = treeEntriesById[sc.selected[0].name]
setDialog(null)
} else { } else {
console.log('invalid selection') console.log('invalid selection')
return
} }
setDialog(null)
sc.extrude(sketch, ref.current.value)
sc.render()
forceUpdate()
} }
const [_, forceUpdate] = useReducer(x => x + 1, 0); const [_, forceUpdate] = useReducer(x => x + 1, 0);
return <div className='dialog w-40 h-10 flex items-center bg-gray-700'> return <div className='dialog w-40 h-10 flex items-center bg-gray-700'>
{/* return <div className='w-40 h-full flex items-center bg-gray-700'> */}
<input className='w-1/2' type="number" {...useNumField(1)} step="0.1" ref={ref} /> <input className='w-1/2' type="number" {...useNumField(1)} step="0.1" ref={ref} />
<Icon.Flip className="btn w-auto h-full p-2" <Icon.Flip className="btn w-auto h-full p-2"
onClick={() => ref.current.value *= -1} onClick={() => ref.current.value *= -1}

View File

@ -17,8 +17,7 @@ export const NavBar = ({ setDialog }) => {
const boolOp = (code) => { const boolOp = (code) => {
if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) return if (sc.selected.length != 2 || !sc.selected.every(e => e.userData.type == 'mesh')) return
const [m1, m2] = sc.selected const [m1, m2] = sc.selected
const mesh = sc.boolOp(m1, m2, code) sc.boolOp(m1, m2, code)
dispatch({ type: 'rx-boolean', mesh, deps: [m1.name, m2.name] })
sc.render() sc.render()
forceUpdate() forceUpdate()
} }
@ -65,8 +64,7 @@ export const NavBar = ({ setDialog }) => {
const btnz2 = [ const btnz2 = [
[FaEdit, addSketch, 'Sketch [s]'] [FaEdit, addSketch, 'Sketch [s]'],
,
[Icon.Extrude, extrude, 'Extrude [e]'], [Icon.Extrude, extrude, 'Extrude [e]'],
[Icon.Union, () => boolOp('u'), 'Union'], [Icon.Union, () => boolOp('u'), 'Union'],
[Icon.Subtract, () => boolOp('s'), 'Subtract'], [Icon.Subtract, () => boolOp('s'), 'Subtract'],

View File

@ -48,7 +48,7 @@ export function treeEntries(state = defaultState, action) {
}, },
allIds: { $push: [action.mesh.name] }, allIds: { $push: [action.mesh.name] },
tree: { tree: {
[action.sketchId]: { [action.mesh.name]: { $set: true} }, [action.sketchId]: { [action.mesh.name]: { $set: true } },
[action.mesh.name]: { $set: {} } [action.mesh.name]: { $set: {} }
}, },
order: { [action.mesh.name]: { $set: state.allIds.length } }, order: { [action.mesh.name]: { $set: state.allIds.length } },

View File

@ -2,10 +2,12 @@
import React, { useReducer, useState } from 'react'; import React, { useReducer, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
import { MdVisibilityOff, MdVisibility, MdDelete } from 'react-icons/md' import { MdVisibilityOff, MdVisibility, MdDelete, MdRefresh } from 'react-icons/md'
import { FaCube, FaEdit } from 'react-icons/fa' import { FaCube, FaEdit } from 'react-icons/fa'
import { DepTree } from './depTree.mjs'
export const Tree = () => { export const Tree = () => {
const treeEntries = useSelector(state => state.treeEntries) const treeEntries = useSelector(state => state.treeEntries)
@ -26,6 +28,7 @@ const treeIcons = {
const TreeEntry = ({ entId }) => { const TreeEntry = ({ entId }) => {
const state = useSelector(state => state.treeEntries)
const treeEntries = useSelector(state => state.treeEntries.byId) const treeEntries = useSelector(state => state.treeEntries.byId)
const dispatch = useDispatch() const dispatch = useDispatch()
@ -110,6 +113,14 @@ const TreeEntry = ({ entId }) => {
e.stopPropagation() e.stopPropagation()
}} }}
/> />
<MdRefresh className='btn-green h-full w-auto p-1.5'
onClick={(e) => {
e.stopPropagation()
sc.refreshNode(entId)
sc.render()
}}
/>
{ {
visible ? visible ?

View File

@ -166,7 +166,7 @@ function setHover(obj, state, meshHover = true) {
break; break;
case 'mesh': case 'mesh':
if (meshHover) { if (meshHover) {
// obj.material.emissive.set(colObj.emissive) obj.material.emissive.set(colObj.emissive)
} else { } else {
break break
} }

View File

@ -30,16 +30,15 @@ tangent // done to the best of my ability
extrude dialogue / done extrude dialogue / done
better default ent names / done better default ent names / done
loopfind especially arc, // fixed for single looop, good enough, maybe stretch goal of selecting search start pt
dim tag delete //resolved
-unable to delete arc -unable to delete arc
hover not clearing sometimes in sketch hover not clearing sometimes in sketch
dim tags are not clearing
auto update extrude auto update extrude
loopfind especially arc
file save, stl export file save, stl export