diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2019-11-10 10:14:22 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2019-11-10 10:25:38 +0000 |
| commit | e956433e3b25fcc9d8a0561adee225ee7ea81745 (patch) | |
| tree | 95d488a2e55618c119ce570a54573e306a1da6b4 /src | |
| parent | movable slices (diff) | |
| download | leap-finger-scan-e956433e3b25fcc9d8a0561adee225ee7ea81745.tar.gz leap-finger-scan-e956433e3b25fcc9d8a0561adee225ee7ea81745.zip | |
slice preview, localStorage, slice saving
Diffstat (limited to 'src')
| -rw-r--r-- | src/index.js | 96 | ||||
| -rw-r--r-- | src/template.html | 1 |
2 files changed, 73 insertions, 24 deletions
diff --git a/src/index.js b/src/index.js index 7804d94..28f4dbd 100644 --- a/src/index.js +++ b/src/index.js @@ -36,9 +36,13 @@ scene.add(dirLight); const camera = new T.PerspectiveCamera(75, 1, 0.1, 1000); camera.position.set(-30, 400, 80); +let fingers; const orbit = new OrbitControls(camera, canvas); const transform = new TransformControls(camera, canvas); +transform.space = 'local'; transform.addEventListener('dragging-changed', e => { orbit.enabled = !e.value }); +transform.addEventListener('objectChange', e => fingers.forEach(finger => finger.updateSlice())); + scene.add(transform); window.onresize = () => { @@ -53,24 +57,26 @@ class Finger extends T.Group { static tipGeom = new T.SphereBufferGeometry(4, 16, 16); static trackGeom = new T.SphereBufferGeometry(2, 4, 4); static sliceMaterial = new T.MeshLambertMaterial({ color: 0xffffff, transparent: true, opacity: 0.5 }); + static trackMaterial = new T.MeshLambertMaterial({ color: 0xff0000 }); static MAX_TRACK = 1 << 10; constructor(i) { super(); const color = new T.Color().setHSL(i / 5, .8, .6); - this.meshMaterial = new T.MeshLambertMaterial({ color }); - this.lineMaterial = new T.LineBasicMaterial({ color, linewidth: 2 }); + const meshMaterial = new T.MeshLambertMaterial({ color }); + const trackMaterial = new T.MeshLambertMaterial({ color, transparent: true, opacity: 0.7 }); + const lineMaterial = new T.LineBasicMaterial({ color, linewidth: 2 }); - this.tip = new T.Mesh(Finger.tipGeom, this.meshMaterial); + this.tip = new T.Mesh(Finger.tipGeom, meshMaterial); this.add(this.tip); this.lineGeometry = new T.Geometry(); this.lineGeometry.vertices.push(new T.Vector3(), new T.Vector3(), new T.Vector3()); - this.skeleton = new T.Line(this.lineGeometry, this.lineMaterial); + this.skeleton = new T.Line(this.lineGeometry, lineMaterial); this.add(this.skeleton); - this.trackers = new T.InstancedMesh(Finger.trackGeom.clone(), this.meshMaterial.clone(), Finger.MAX_TRACK); + this.trackers = new T.InstancedMesh(Finger.trackGeom.clone(), trackMaterial, Finger.MAX_TRACK); this.add(this.trackers); this.dataPoints = []; @@ -115,6 +121,8 @@ class Finger extends T.Group { this.slice.position.copy(average); this.add(this.slice); transform.attach(this.slice); + + this.updateSlice(); } else if (transform.object === this.slice) { transform.detach(); } else { @@ -123,15 +131,25 @@ class Finger extends T.Group { } updateSlice() { - const sliceTransform = this.slice.matrixWorld.getInverse(); - const points = this.dataPoints.reduce((list, point) => { + if (!this.slice) + return; + + const sliceTransform = new T.Matrix4().getInverse(this.slice.matrixWorld); + const points = []; + this.dataPoints.map(point => { const tip = new T.Vector3(...point.tip); - tip.applyMatrix4(sliceTransform); - if (Math.abs(tip.x) <= 1 && Math.abs(tip.y) <= 1 && Math.abs(tip.z) <= 1) { + const norm = tip.clone().applyMatrix4(sliceTransform); + if (Math.abs(norm.x) <= .5 && Math.abs(norm.y) <= .5 && Math.abs(norm.z) <= .5) + points.push(tip); + }); - } - }, []); + if (this.slicedTrackers) + this.remove(this.slicedTrackers); + + this.slicedTrackers = new T.InstancedMesh(Finger.trackGeom.clone(), Finger.trackMaterial.clone(), points.length); + points.forEach((point, i) => this.slicedTrackers.setMatrixAt(i, new T.Matrix4().setPosition(point))); + this.add(this.slicedTrackers); } removeSlice() { @@ -143,6 +161,10 @@ class Finger extends T.Group { this.remove(this.slice); this.slice = null; + if (this.slicedTrackers) { + this.remove(this.slicedTrackers); + this.slicedTrackers = null; + } } update(finger) { @@ -174,15 +196,28 @@ class Finger extends T.Group { } store() { - return this.dataPoints; + return { + dataPoints: this.dataPoints, + slice: this.slice && { + position: this.slice.position.toArray(), + rotation: this.slice.rotation.toArray(), + scale: this.slice.scale.toArray(), + }, + }; } - load(dataPoints) { - for (const dp of dataPoints) { + load(data) { + for (const dp of data.dataPoints) { this.trackers.setMatrixAt(this.dataPoints.length % Finger.MAX_TRACK, new T.Matrix4().makeTranslation(...dp.tip)); this.dataPoints.push(dp); } + if (data.slice) { + this.selectSlice(); + this.slice.position.fromArray(data.slice.position); + this.slice.rotation.fromArray(data.slice.rotation); + this.slice.scale.fromArray(data.slice.scale); + } this.trackers.instanceMatrix.needsUpdate = true; } } @@ -194,20 +229,27 @@ scene.add(new T.Mesh(cube, material)); const palm = new T.Mesh(new T.BoxBufferGeometry(8, 2, 8), material); scene.add(palm); -const fingers = [0,1,2,3,4].map(i => { +fingers = [0,1,2,3,4].map(i => { const finger = new Finger(i); scene.add(finger); return finger; }); -window.F = fingers; +const restore = (str) => { + if (!str) + return; + + const data = JSON.parse(str); + data.forEach((data, i) => fingers[i].load(data)); +} + +let viewSliceOnly = false; window.onkeydown = (e) => { if (e.key === 'r') { fingers.forEach(finger => finger.clear()); - return; } else if (e.key === 's') { const data = fingers.map(finger => finger.store()); - saveAs(new Blob([JSON.stringify(data)]), 'text/json'); + saveAs(new Blob([JSON.stringify(data)]), 'finger-scan.json'); } else if (e.key === 'l') { const input = document.createElement('input'); input.type = 'file'; @@ -215,16 +257,16 @@ window.onkeydown = (e) => { input.onchange = e => { const reader = new FileReader(); - reader.onload = e => { - const data = JSON.parse(e.target.result); - data.forEach((data, i) => fingers[i].load(data)); - } + reader.onload = e => restore(e.target.result); reader.readAsText(e.target.files[0]); } } else if (e.key === 'Shift') { transform.setMode('rotate'); } else if (e.key === 'Alt') { transform.setMode('scale'); + } else if (e.key === ' ') { + viewSliceOnly = !viewSliceOnly; + fingers.forEach(finger => { finger.trackers.visible = !viewSliceOnly }); } const i = +e.key; @@ -238,9 +280,8 @@ window.onkeydown = (e) => { window.onkeyup = (e) => { const i = +e.key; - if (e.key === 'Shift' || e.key === 'Alt') { + if (e.key === 'Shift' || e.key === 'Alt') transform.setMode('translate'); - } if (i > -1 && i < 6) { e.preventDefault(); @@ -262,6 +303,13 @@ const update = (frame) => { } } +restore(localStorage.getItem('data')); +setInterval(() => { + const data = fingers.map(finger => finger.store()); + localStorage.setItem('data', JSON.stringify(data)); +}, 2000); + + const controller = Leap.loop({ frameEventName: 'animationFrame', // frameEventName: 'deviceFrame', diff --git a/src/template.html b/src/template.html index 401c9da..1868873 100644 --- a/src/template.html +++ b/src/template.html @@ -86,6 +86,7 @@ <div> <b>hotkeys —</b> <key>1-5</key> track fingers — + <key>space</key> toggle slice data view — <key>shift</key> rotate slice — <key>alt</key> scale slice — <key>S</key> export data — |
