aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2019-11-10 10:14:22 +0000
committers-ol <s-ol@users.noreply.github.com>2019-11-10 10:25:38 +0000
commite956433e3b25fcc9d8a0561adee225ee7ea81745 (patch)
tree95d488a2e55618c119ce570a54573e306a1da6b4 /src
parentmovable slices (diff)
downloadleap-finger-scan-e956433e3b25fcc9d8a0561adee225ee7ea81745.tar.gz
leap-finger-scan-e956433e3b25fcc9d8a0561adee225ee7ea81745.zip
slice preview, localStorage, slice saving
Diffstat (limited to 'src')
-rw-r--r--src/index.js96
-rw-r--r--src/template.html1
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 &mdash;</b>
<key>1-5</key> track fingers &mdash;
+ <key>space</key> toggle slice data view &mdash;
<key>shift</key> rotate slice &mdash;
<key>alt</key> scale slice &mdash;
<key>S</key> export data &mdash;