trying to add edges back for debug

master
howard 2021-04-15 17:05:40 -07:00
parent dd81d67d8f
commit a0f0566704
14 changed files with 244 additions and 78 deletions

BIN
dist/solver.wasm vendored

Binary file not shown.

View File

@ -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)

View File

@ -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])) {

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;

View File

@ -87,3 +87,21 @@ body {
border-bottom-color: white;
border-top: none;
}
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] { */
/* } */

View File

@ -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 <Provider store={store}>
<NavBar setDialog={setDialog}/>
<Tree />
<Dialog dd={dialog}/>
<Dialog {...{dialog, setDialog}}/>
<ToolTip/>
</Provider>
};

View File

@ -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 <div className='dialog w-40 h-10 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}
/>
<MdDone
className="btn w-auto h-full p-2"
onClick={extrude}
className="btn w-auto h-full p-2" />
<MdClose className="btn w-auto h-full p-2" />
<Icon.Flip className="btn w-auto h-full p-2" />
/>
<MdClose className="btn w-auto h-full p-2"
onClick={() => setDialog(null)}
/>
</div>
}

View File

@ -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]'],

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

@ -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

@ -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

View File

@ -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(