From a0f056670422d4ca9140f874080b11eb05310b88 Mon Sep 17 00:00:00 2001 From: howard Date: Thu, 15 Apr 2021 17:05:40 -0700 Subject: [PATCH] trying to add edges back for debug --- dist/solver.wasm | Bin 139393 -> 139397 bytes src/Scene.js | 57 ++++++++++++++------ src/Sketch.js | 27 ++++++---- src/drawDimension.js | 6 +-- src/extrude.js | 125 ++++++++++++++++++++++++++++++++++++++++--- src/mouseEvents.js | 13 +++-- src/react/app.css | 20 ++++++- src/react/app.jsx | 5 +- src/react/dialog.jsx | 17 ++++-- src/react/navBar.jsx | 21 ++------ src/react/reducer.js | 2 +- src/shared.js | 2 +- todo.txt | 21 +++++--- wasm/solver.c | 6 ++- 14 files changed, 244 insertions(+), 78 deletions(-) diff --git a/dist/solver.wasm b/dist/solver.wasm index a4a67f0bbfed73c230ba5b6bc4e031f3117b8f94..29d812888bf5304c08512051866c19c5f973130a 100755 GIT binary patch delta 9737 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 diff --git a/src/Scene.js b/src/Scene.js index f06ea0f..da467c9 100644 --- a/src/Scene.js +++ b/src/Scene.js @@ -6,7 +6,7 @@ import { TrackballControls } from '../lib/trackball' import { Sketch } from './Sketch' import Stats from '../lib/stats.module.js'; -import { extrude } from './extrude' +import { extrude, flipBufferGeometryNormals } from './extrude' import { onHover, onPick } from './mouseEvents'; import { _vec2, _vec3, color, awaitSelection, ptObj, setHover } from './shared' @@ -26,9 +26,19 @@ const eq = (a1, a2) => { window.loader = new THREE.ObjectLoader(); window.id = 0 +window.sid = 1 +window.mid = 1 + + +const pointMaterial = new THREE.PointsMaterial({ + color: color.selpoint, + size: 4, +}) export class Scene { constructor(store) { + this.sid = 1 + this.mid = 1 this.store = store; this.canvas = document.querySelector('#c'); @@ -63,10 +73,14 @@ export class Scene { for (let i = 0; i < 4; i++) { - const freePt = ptObj() + const freePt = new THREE.Points( + new THREE.BufferGeometry().setAttribute('position', + new THREE.Float32BufferAttribute(3, 3) + ), + pointMaterial.clone() + ) + freePt.matrixAutoUpdate = false - freePt.material.size = 4 - freePt.material.color.set(color.selpoint) freePt.visible = false freePt.depthTest = false freePt.userData.type = 'selpoint' @@ -160,37 +174,49 @@ export class Scene { saveState() { localStorage.setItem( - 'sv', JSON.stringify([id, this.store.getState()]) + 'sv2', JSON.stringify([id, this.sid, this.mid, this.store.getState().treeEntries]) ) } loadState() { //uglyyy - const [curid, state] = JSON.parse( - localStorage.getItem('sv') + const [curid, cursid, curmid, state] = JSON.parse( + localStorage.getItem('sv2') ) window.id = curid + this.sid = cursid + this.mid = curmid - const entries = state.treeEntries.byId + const entries = state.byId for (let k in entries) { if (k[0] == 's') { entries[k].obj3d = loader.parse(entries[k].obj3d) this.obj3d.add(entries[k].obj3d) - entries[k] = new Sketch(this, state.treeEntries.byId[k]) + entries[k] = new Sketch(this, state.byId[k]) entries[k].obj3d.addEventListener('change', this.render) // !! took 3 hours to realize - } else if (k[0] == 'm') { + } 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]) + + } else { + entries[k] = loader.parse(state.byId[k]) - entries[k] = loader.parse(state.treeEntries.byId[k]) - // console.log(entries[k]) this.obj3d.add(entries[k]) } } this.store.dispatch({ type: 'restore-state', state }) + return state } clearSelection() { @@ -244,8 +270,9 @@ export class Scene { let mesh = CSG.toMesh(bspResult, m1.matrix, m1.material) mesh.userData.type = 'mesh' + mesh.userData.featureInfo = [m1.name, m2.name, op] - mesh.name = `(${m1.name}${opChar}${m2.name})` + mesh.name = `(${m1.name} ${opChar} ${m2.name})` mesh.layers.enable(1) const vertices = new THREE.Points(mesh.geometry, new THREE.PointsMaterial({ size: 0 })); @@ -288,7 +315,7 @@ function render() { this.renderer.render(this.obj3d, this.camera); if (this.activeSketch) { - dims = this.activeSketch.obj3d.children[1].children + dims = this.activeSketch.dimGroup.children matrix = this.activeSketch.obj3d.matrix for (idx = 1; idx < dims.length; idx += 2) { @@ -347,7 +374,7 @@ async function addSketch() { } window.sc = new Scene(store) -// sc.loadState() +sc.loadState() // sc.camera.layers.enable(1) // rc.layers.set(1) \ No newline at end of file diff --git a/src/Sketch.js b/src/Sketch.js index 09fcece..bece5c6 100644 --- a/src/Sketch.js +++ b/src/Sketch.js @@ -5,7 +5,7 @@ import * as THREE from '../node_modules/three/src/Three'; import { _vec2, _vec3, raycaster, awaitSelection, ptObj, setHover } from './shared' import { drawOnClick1, drawOnClick2, drawPreClick2, drawOnClick3, drawPreClick3, drawClear, drawPoint } from './drawEvents' -import { onHover, onDrag, onPick, onRelease} from './mouseEvents' +import { onHover, onDrag, onPick, onRelease } from './mouseEvents' import { setCoincident, setOrdinate, setTangent } from './constraintEvents' import { get3PtArc } from './drawArc' import { replacer, reviver } from './utils' @@ -37,7 +37,7 @@ class Sketch { if (preload === undefined) { this.obj3d = new THREE.Group() - this.obj3d.name = "s" + id++ + this.obj3d.name = "s" + scene.sid++ this.obj3d.userData.type = "sketch" this.obj3d.matrixAutoUpdate = false; @@ -50,8 +50,10 @@ class Sketch { this.c_id = 1; this.obj3d.add(new THREE.Group()); - this.obj3d.add(new THREE.Group()); - this.obj3d.add(new THREE.Group()); + + this.geomStartIdx = this.obj3d.children.length + this.obj3d.userData.geomStartIdx = this.geomStartIdx + this.dimGroup = this.obj3d.children[this.geomStartIdx - 1] this.labels = [] @@ -80,6 +82,8 @@ class Sketch { this.constraints = JSON.parse(preload.constraints, reviver) this.c_id = preload.c_id; + this.geomStartIdx = this.obj3d.userData.geomStartIdx + this.dimGroup = this.obj3d.children[this.geomStartIdx - 1] this.updatePointsBuffer() this.updateOtherBuffers() @@ -385,13 +389,14 @@ class Sketch { updateBoundingSpheres() { - for (let x = 3; x < this.obj3d.children.length; x++) { // geometry boundign spheres + + for (let x = this.geomStartIdx; x < this.obj3d.children.length; x++) { // geometry boundign spheres const obj = this.obj3d.children[x] obj.geometry.computeBoundingSphere() } - for (let x = 0; x < this.obj3d.children[1].children.length; x++) { // dimension bounding sphere - const obj = this.obj3d.children[1].children[x] + for (let x = 0; x < this.dimGroup.children.length; x++) { // dimension bounding sphere + const obj = this.dimGroup.children[x] obj.geometry.computeBoundingSphere() } } @@ -432,16 +437,16 @@ class Sketch { Module["_solver"]( this.obj3d.children.length, pts_buffer, this.constraints.size, constraints_buffer, - this.linkedObjs.size, links_buffer) + this.linkedObjs.size, links_buffer, + this.geomStartIdx + ) /* - loop to update all the children that are points - - why +6? we skip first two triplets because it refers to a non-geometry children - we also sneak in updating lines children as well, by checking when ptsBuf[ptr] is NaN */ - for (let i = 3, ptr = (pts_buffer >> 2) + 9; i < this.obj3d.children.length; i += 1, ptr += 3) { - // for (let i = 0, ptr = (pts_buffer >> 2) + 3; i < this.obj3d.children.length; i += 1, ptr += 3) { + for (let i = this.geomStartIdx, ptr = (pts_buffer >> 2) + this.geomStartIdx * 3; i < this.obj3d.children.length; i += 1, ptr += 3) { const pos = this.obj3d.children[i].geometry.attributes.position; if (isNaN(Module.HEAPF32[ptr])) { diff --git a/src/drawDimension.js b/src/drawDimension.js index 5d357f0..ea7b5fe 100644 --- a/src/drawDimension.js +++ b/src/drawDimension.js @@ -92,7 +92,7 @@ export async function drawDimension() { line.layers.enable(2) point.layers.enable(2) - this.obj3d.children[1].add(line).add(point) + this.dimGroup.add(line).add(point) const onMove = this._onMoveDimension(point, line) point.label = document.createElement('div'); point.label.textContent = dimVal.toFixed(3); @@ -138,7 +138,7 @@ export async function drawDimension() { } else { - this.obj3d.children[1].children.splice(this.obj3d.children[1].length - 2, 2).forEach( + this.dimGroup.children.splice(this.dimGroup.length - 2, 2).forEach( e => { e.geometry.dispose() e.material.dispose() @@ -209,7 +209,7 @@ export function _onMoveDimension(point, line) { export function setDimLines() { const restoreLabels = this.labelContainer.childElementCount == 0; - const dims = this.obj3d.children[1].children + const dims = this.dimGroup.children let point, dist; for (let i = 0; i < dims.length; i += 2) { if (restoreLabels) { diff --git a/src/extrude.js b/src/extrude.js index 9c68abf..665c5ec 100644 --- a/src/extrude.js +++ b/src/extrude.js @@ -1,7 +1,7 @@ import * as THREE from '../node_modules/three/src/Three'; -import { color} from './shared' +import { color } from './shared' export function extrude(sketch, depth) { - console.log(sketch,'here') + console.log(sketch, 'here') let constraints = sketch.constraints; let linkedObjs = sketch.linkedObjs; @@ -68,20 +68,43 @@ export function extrude(sketch, depth) { findPair(children[4]) //??? need fixing const shape = new THREE.Shape(v2s); + // const extrudeSettings = { depth: Math.abs(depth), bevelEnabled: false }; const extrudeSettings = { depth, bevelEnabled: false }; const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); // const material = new THREE.MeshLambertMaterial({ - const material = new THREE.MeshPhongMaterial({ - color: color.mesh, - emissive: color.emissive, - }); + // const material = new THREE.MeshPhongMaterial({ + // color: color.mesh, + // emissive: color.emissive, + // }); - const mesh = new THREE.Mesh(geometry, material) - mesh.name = 'm' + id++ + // const mesh = new THREE.Mesh(geometry, material) + + // const material = new THREE.MeshPhongMaterial({ + // color: color.mesh, + // }); + // const wireframe = new THREE.EdgesGeometry( geometry ); + // const mesh = new THREE.LineSegments( wireframe ); + // // mesh.material.depthTest = false; + // // mesh.material.opacity = 0.25; + // // mesh.material.transparent = true; + // mesh.material.transparent = false; + + 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) const vertices = new THREE.Points(mesh.geometry, new THREE.PointsMaterial({ size: 0 })); @@ -89,13 +112,27 @@ export function extrude(sketch, depth) { vertices.layers.enable(1) mesh.add(vertices) + + + + + + + mesh.matrixAutoUpdate = false; mesh.matrix.multiply(sketch.obj3d.matrix) + if (depth < 0) { + flipBufferGeometryNormals(mesh.geometry) + mesh.userData.inverted = true + } + + this.obj3d.add(mesh) this.store.dispatch({ type: 'rx-extrusion', mesh, sketchId: sketch.obj3d.name }) + // sketch.userData if (this.activeSketch == sketch) { this.activeSketch = null sketch.deactivate() @@ -107,3 +144,75 @@ export function extrude(sketch, depth) { + + + +export function flipBufferGeometryNormals(geometry) { + //https://stackoverflow.com/a/54496265 + const tempXYZ = [0, 0, 0]; + + // flip normals + for (let i = 0; i < geometry.attributes.normal.array.length / 9; i++) { + // cache a coordinates + tempXYZ[0] = geometry.attributes.normal.array[i * 9]; + tempXYZ[1] = geometry.attributes.normal.array[i * 9 + 1]; + tempXYZ[2] = geometry.attributes.normal.array[i * 9 + 2]; + + // overwrite a with c + geometry.attributes.normal.array[i * 9] = + geometry.attributes.normal.array[i * 9 + 6]; + geometry.attributes.normal.array[i * 9 + 1] = + geometry.attributes.normal.array[i * 9 + 7]; + geometry.attributes.normal.array[i * 9 + 2] = + geometry.attributes.normal.array[i * 9 + 8]; + + // overwrite c with stored a values + geometry.attributes.normal.array[i * 9 + 6] = tempXYZ[0]; + geometry.attributes.normal.array[i * 9 + 7] = tempXYZ[1]; + geometry.attributes.normal.array[i * 9 + 8] = tempXYZ[2]; + } + + // change face winding order + for (let i = 0; i < geometry.attributes.position.array.length / 9; i++) { + // cache a coordinates + tempXYZ[0] = geometry.attributes.position.array[i * 9]; + tempXYZ[1] = geometry.attributes.position.array[i * 9 + 1]; + tempXYZ[2] = geometry.attributes.position.array[i * 9 + 2]; + + // overwrite a with c + geometry.attributes.position.array[i * 9] = + geometry.attributes.position.array[i * 9 + 6]; + geometry.attributes.position.array[i * 9 + 1] = + geometry.attributes.position.array[i * 9 + 7]; + geometry.attributes.position.array[i * 9 + 2] = + geometry.attributes.position.array[i * 9 + 8]; + + // overwrite c with stored a values + geometry.attributes.position.array[i * 9 + 6] = tempXYZ[0]; + geometry.attributes.position.array[i * 9 + 7] = tempXYZ[1]; + geometry.attributes.position.array[i * 9 + 8] = tempXYZ[2]; + } + + // flip UV coordinates + for (let i = 0; i < geometry.attributes.uv.array.length / 6; i++) { + // cache a coordinates + tempXYZ[0] = geometry.attributes.uv.array[i * 6]; + tempXYZ[1] = geometry.attributes.uv.array[i * 6 + 1]; + + // overwrite a with c + geometry.attributes.uv.array[i * 6] = + geometry.attributes.uv.array[i * 6 + 4]; + geometry.attributes.uv.array[i * 6 + 1] = + geometry.attributes.uv.array[i * 6 + 5]; + + // overwrite c with stored a values + geometry.attributes.uv.array[i * 6 + 4] = tempXYZ[0]; + geometry.attributes.uv.array[i * 6 + 5] = tempXYZ[1]; + } + + geometry.attributes.normal.needsUpdate = true; + geometry.attributes.position.needsUpdate = true; + geometry.attributes.uv.needsUpdate = true; +} + + diff --git a/src/mouseEvents.js b/src/mouseEvents.js index 45a2e04..213c8d0 100644 --- a/src/mouseEvents.js +++ b/src/mouseEvents.js @@ -24,7 +24,7 @@ export function onHover(e) { } else { // raycaster.layers.set(0) raycaster.layers.set(2) - hoverPts = raycaster.intersectObjects([...this.obj3d.children[1].children, ...this.obj3d.children]) + hoverPts = raycaster.intersectObjects([...this.dimGroup.children, ...this.obj3d.children]) } @@ -171,27 +171,26 @@ export function onPick(e) { switch (obj.userData.type) { case 'dimension': - const idx = this.obj3d.children[1].children.indexOf(this.hovered[0]) + const idx = this.dimGroup.children.indexOf(this.hovered[0]) if (idx % 2) { // we only allow tag point (odd idx) to be dragged this.onDragDim = this._onMoveDimension( - this.obj3d.children[1].children[idx], - this.obj3d.children[1].children[idx - 1], + this.dimGroup.children[idx], + this.dimGroup.children[idx - 1], ) this.canvas.addEventListener('pointermove', this.onDragDim); this.canvas.addEventListener('pointerup', () => { - onDimMoveEnd(this.obj3d.children[1].children[idx]) + onDimMoveEnd(this.dimGroup.children[idx]) this.onRelease() }) } - draggedLabel = this.obj3d.children[1].children[idx].label + draggedLabel = this.dimGroup.children[idx].label draggedLabel.style.zIndex = -1; break; case 'point': this.canvas.addEventListener('pointermove', this.onDrag); this.canvas.addEventListener('pointerup', () => { - // onDimMoveEnd(this.obj3d.children[1].children[idx]) this.onRelease() }) break; diff --git a/src/react/app.css b/src/react/app.css index 0326244..0569650 100644 --- a/src/react/app.css +++ b/src/react/app.css @@ -86,4 +86,22 @@ body { border: solid 6px transparent; border-bottom-color: white; border-top: none; -} \ No newline at end of file +} + +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +/* Firefox */ +input[type=number] { + -moz-appearance: textfield; + border:none; + background-color:transparent; + outline: none; + text-align:right; +} + +/* input:focus[type=number] { */ +/* } */ diff --git a/src/react/app.jsx b/src/react/app.jsx index 2c84bc1..95afbdd 100644 --- a/src/react/app.jsx +++ b/src/react/app.jsx @@ -26,7 +26,10 @@ const preloadedState = { } // const store = createStore(reducer, preloadedState, applyMiddleware(logger)) + + const store = createStore(reducer, {}, applyMiddleware(logger)) +// const store = createStore(reducer, sc.loadState(), applyMiddleware(logger)) const App = ({ store }) => { const [dialog, setDialog] = useState() @@ -34,7 +37,7 @@ const App = ({ store }) => { return - + }; diff --git a/src/react/dialog.jsx b/src/react/dialog.jsx index f21dbb8..404e0ce 100644 --- a/src/react/dialog.jsx +++ b/src/react/dialog.jsx @@ -9,8 +9,8 @@ import { GiVerticalFlip } from 'react-icons/gi' import * as Icon from "./icons"; -export const Dialog = ({ dd }) => { - if (!dd) return null +export const Dialog = ({ dialog, setDialog }) => { + if (!dialog) return null const dispatch = useDispatch() const treeEntriesById = useSelector(state => state.treeEntries.byId) @@ -24,8 +24,10 @@ export const Dialog = ({ dd }) => { const extrude = () => { if (sc.activeSketch) { sc.extrude(sc.activeSketch, ref.current.value) + setDialog(null) } else if (sc.selected.length === 1 && sc.selected[0].userData.type == 'sketch') { sc.extrude(treeEntriesById[sc.selected[0].name], ref.current.value) + setDialog(null) } else { console.log('invalid selection') } @@ -36,11 +38,16 @@ export const Dialog = ({ dd }) => { return
+ ref.current.value *= -1} + /> - - + /> + setDialog(null)} + />
} diff --git a/src/react/navBar.jsx b/src/react/navBar.jsx index d06935b..a665bd5 100644 --- a/src/react/navBar.jsx +++ b/src/react/navBar.jsx @@ -4,15 +4,13 @@ import React, { useEffect, useReducer } from 'react'; import { useDispatch, useSelector } from 'react-redux' -import { FaCube, FaEdit } from 'react-icons/fa' -import { BsBoxArrowUp } from 'react-icons/bs' +import { FaEdit } from 'react-icons/fa' import { MdDone, MdSave, MdFolder } from 'react-icons/md' import * as Icon from "./icons"; -export const NavBar = ({setDialog}) => { +export const NavBar = ({ setDialog }) => { const dispatch = useDispatch() - const treeEntriesById = useSelector(state => state.treeEntries.byId) const activeSketchId = useSelector(state => state.treeEntries.activeSketchId) @@ -24,16 +22,7 @@ export const NavBar = ({setDialog}) => { sc.render() forceUpdate() } - const extrude = () => { - setDialog('dd') - // if (sc.activeSketch) { - // sc.extrude(sc.activeSketch) - // } else if (sc.selected.length === 1 && sc.selected[0].userData.type == 'sketch') { - // sc.extrude(treeEntriesById[sc.selected[0].name]) - // } else { - // console.log('invalid selection') - // } - } + const extrude = () => { setDialog(true) } const addSketch = () => { sc.addSketch() @@ -59,12 +48,10 @@ export const NavBar = ({setDialog}) => { const btnz = [ [MdDone, () => { - // treeEntriesById[activeSketchId].deactivate() - // dispatch({ type: 'update-descendents', sketch}) sc.activeSketch.deactivate() + // dispatch({ type: 'update-descendents', sketch}) sc.render() forceUpdate() - // sc.activeDim = this.activeSketch.obj3d.children[1].children }, 'Finish'], [Icon.Extrude, extrude, 'Extrude [e]'], [Icon.Dimension, () => sc.activeSketch.command('d'), 'Dimension [d]'], diff --git a/src/react/reducer.js b/src/react/reducer.js index 36fd3af..dd96053 100644 --- a/src/react/reducer.js +++ b/src/react/reducer.js @@ -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 } }, diff --git a/src/shared.js b/src/shared.js index 696f1da..a94afce 100644 --- a/src/shared.js +++ b/src/shared.js @@ -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 } diff --git a/todo.txt b/todo.txt index 7dc3a7f..e45f9e0 100644 --- a/todo.txt +++ b/todo.txt @@ -25,30 +25,35 @@ constraint angle // done button panel cleanup // done 3 pt arc // done tangent // done to the best of my ability +-boolean highlights when hovering over parent why? because they share the same material +- should unselect after boolean see above + +extrude dialogue / done +better default ent names / done + -unable to delete arc -hover not clearing sometimes +hover not clearing sometimes in sketch dim tags are not clearing -should unselect after boolean - auto update extrude -extrude dialogue loopfind especially arc file save, stl export - -better default ent names +add cancle soft button for line arc reattach sketch auto snap constraint labels,equal parallel + + +tree relation tool tip tree ent renaming @@ -60,6 +65,10 @@ hover state for sketch await selection 3 point arc implementation +saerch tree for loop finding // need dev effor + +dep tree for biuidling design treee + diff --git a/wasm/solver.c b/wasm/solver.c index 22ce85a..465e520 100644 --- a/wasm/solver.c +++ b/wasm/solver.c @@ -33,7 +33,7 @@ static void *CheckMalloc(size_t n) * entities and constraints. *---------------------------------------------------------------------------*/ -int solver(int nPts, float *p_ptr, int nConst, float *c_ptr, int nLinks, float *l_ptr) +int solver(int nPts, float *p_ptr, int nConst, float *c_ptr, int nLinks, float *l_ptr, int geomStartIdx) { // printf("first %i \n", (int)*(l_ptr + 1)); Slvs_hGroup g; @@ -111,7 +111,9 @@ int solver(int nPts, float *p_ptr, int nConst, float *c_ptr, int nLinks, float * SLVS_C_POINTS_COINCIDENT, 200, -1, - 101, 3, -1, -1); + 101, geomStartIdx, -1, -1); + + // it's 2 + nConst because c_id at this point is 2 for (; c_id < 2 + nConst; c_id++, c_ptr += 6) { sys.constraint[sys.constraints++] = Slvs_MakeConstraint(