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') {
entries[k] = loader.parse(state.byId[k])
if (entries[k].userData.inverted) {
flipBufferGeometryNormals(entries[k].geometry)
}
}
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 bspB = CSG.fromMesh(m2)
m1.visible = false
@ -275,18 +275,51 @@ export class Scene {
mesh.add(vertices)
sc.obj3d.add(mesh)
if (!refresh) {
sc.obj3d.add(mesh)
this.store.dispatch({
type: 'set-entry-visibility', obj: {
[m1.name]: false,
[m2.name]: false,
[mesh.name]: true,
}
})
this.store.dispatch({
type: 'set-entry-visibility', obj: {
[m1.name]: false,
[m2.name]: false,
[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++) {
const obj = this.obj3d.children[i + j]
obj.geometry.dispose()
obj.material.dispose()
// obj.geometry.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)
}
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 = []
}

View File

@ -1,8 +1,15 @@
import { color } from './shared'
export async function setCoincident() {
let selection = await this.awaitSelection({ point: 2 }, { point: 1, line: 1 })
if (selection == null) return;
export async function setCoincident(sel) {
let selection
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')) {
this.constraints.set(++this.c_id,
[

View File

@ -1,6 +1,6 @@
import * as THREE from '../node_modules/three/src/Three';
import { color } from './shared'
export function extrude(sketch, depth) {
export function extrude(sketch, depth, refresh=false) {
let constraints = sketch.constraints;
let linkedObjs = sketch.linkedObjs;
@ -10,7 +10,7 @@ export function extrude(sketch, depth) {
let v2s = []
function findPair(node) {
console.log(node.name,'xx')
// console.log(node.name, 'xx')
if (node.userData.construction) return;
visited.add(node)
let linkedObj = linkedObjs.get(node.userData.l_id)
@ -43,7 +43,7 @@ export function extrude(sketch, depth) {
)
]
if (d == children[2]) {
console.log('pair found')
// console.log('pair found')
};
findTouching(d)
@ -51,19 +51,19 @@ export function extrude(sketch, depth) {
function findTouching(node) {
console.log(node.name,'yy')
// console.log(node.name, 'yy')
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
for (let c of constraints.get(t)[2]) {
if (c == -1) continue;
const d = children[objIdx.get(c)]
if (d == node) continue;
if (d == children[2]) {
console.log('loop found')
// console.log('loop found')
} else {
// 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 extrudeSettings = { depth: Math.abs(depth), bevelEnabled: false };
@ -88,27 +88,9 @@ export function extrude(sketch, depth) {
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 = 'm' + sketch.obj3d.name.slice(1)
// mesh.name = 'e' + sketch.obj3d.name.slice(1)
mesh.userData.type = 'mesh'
mesh.userData.featureInfo = [sketch.obj3d.name, depth]
mesh.layers.enable(1)
@ -119,12 +101,6 @@ export function extrude(sketch, depth) {
mesh.add(vertices)
mesh.matrixAutoUpdate = false;
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) {
this.activeSketch = null
sketch.deactivate()
if (this.activeSketch == sketch) {
sketch.deactivate()
}
this.render()
} else {
return mesh
}
// this.clearSelection()
this.render()
}
export function flipBufferGeometryNormals(geometry) {
//https://stackoverflow.com/a/54496265
const tempXYZ = [0, 0, 0];

View File

@ -1,20 +1,15 @@
export class DepTree {
constructor(obj) {
if (obj) {
this.order = { ...obj.order }
this.byId = { ...obj.byId }
this.allIds = [...obj.allIds]
this.order = { ...obj.order }
this.byId = { ...obj.byId }
this.allIds = [...obj.allIds]
this.tree = {}
for (let k in obj.tree) {
this.tree[k] = { ...obj.tree[k] }
}
} else {
this.tree = {}
this.order = {}
this.allIds = []
this.tree = {}
for (let k in obj.tree) {
this.tree[k] = { ...obj.tree[k] }
}
}
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
deletedObj.traverse((obj)=>{
deletedObj.traverse((obj) => {
if (obj.geometry) obj.geometry.dispose()
if (obj.material) obj.material.dispose()
})
@ -95,6 +90,9 @@ export class DepTree {
}
return this
}
}
@ -103,7 +101,7 @@ export class DepTree {
// const dt = new DepTree()
// dt.addParent('r1')
// dt.addParent('r2')
// dt.addChild('r3', 'r1', 'r2')
// dt.addChild('r3', 'r1', 'r2')s
// dt.addParent('r4')
// dt.addChild('r5', 'r4', 'r3')
// dt.addChild('r6', 'r1', 'r5')
@ -128,3 +126,6 @@ export class DepTree {
// allIds: [ 'r1', 'r2', 'r3', 'r4', 'r8' ]
// }

View File

@ -22,21 +22,28 @@ export const Dialog = ({ dialog, setDialog }) => {
}, [])
const extrude = () => {
let sketch
if (sc.activeSketch) {
sc.extrude(sc.activeSketch, ref.current.value)
setDialog(null)
sketch = sc.activeSketch
} else if (sc.selected.length === 1 && sc.selected[0].userData.type == 'sketch') {
sc.extrude(treeEntriesById[sc.selected[0].name], ref.current.value)
setDialog(null)
sketch = treeEntriesById[sc.selected[0].name]
} else {
console.log('invalid selection')
return
}
setDialog(null)
sc.extrude(sketch, ref.current.value)
sc.render()
forceUpdate()
}
const [_, forceUpdate] = useReducer(x => x + 1, 0);
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} />
<Icon.Flip className="btn w-auto h-full p-2"
onClick={() => ref.current.value *= -1}

View File

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

View File

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

View File

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

View File

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

View File

@ -30,16 +30,15 @@ tangent // done to the best of my ability
extrude dialogue / 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
hover not clearing sometimes in sketch
dim tags are not clearing
auto update extrude
loopfind especially arc
file save, stl export