node-red-contrib-leap-motion
Version:
Node-Red nodes for leap motion
234 lines (165 loc) • 6.05 kB
HTML
<html>
<head>
<title>Bone Hands - Leap</title>
<script src="../leap-0.6.4.js"></script>
<script src="lib/leap-plugins-0.1.6.js"></script>
<script src="lib/three.js"></script>
</head>
<body>
<p>
Move Hand over Leap to see bones and bone basis.
</p>
<p>
Even without the leap, you should see a rotating blue rectangle to know that your WebGL is working.
</p>
</body>
<script>
// note: before implementing based off of this, you can instead grab the boneHand plugin
// here: js.leapmotion.com
var colors = [0xff0000, 0x00ff00, 0x0000ff];
var baseBoneRotation = (new THREE.Quaternion).setFromEuler(
new THREE.Euler(Math.PI / 2, 0, 0)
);
Leap.loop({background: true}, {
hand: function (hand) {
hand.fingers.forEach(function (finger) {
// This is the meat of the example - Positioning `the cylinders on every frame:
finger.data('boneMeshes').forEach(function(mesh, i){
var bone = finger.bones[i];
mesh.position.fromArray(bone.center());
mesh.setRotationFromMatrix(
(new THREE.Matrix4).fromArray( bone.matrix() )
);
mesh.quaternion.multiply(baseBoneRotation);
});
finger.data('jointMeshes').forEach(function(mesh, i){
var bone = finger.bones[i];
if (bone) {
mesh.position.fromArray(bone.prevJoint);
}else{
// special case for the finger tip joint sphere:
bone = finger.bones[i-1];
mesh.position.fromArray(bone.nextJoint);
}
});
});
var armMesh = hand.data('armMesh');
armMesh.position.fromArray(hand.arm.center());
armMesh.setRotationFromMatrix(
(new THREE.Matrix4).fromArray( hand.arm.matrix() )
);
armMesh.quaternion.multiply(baseBoneRotation);
armMesh.scale.x = hand.arm.width / 2;
armMesh.scale.z = hand.arm.width / 4;
renderer.render(scene, camera);
}})
// these two LeapJS plugins, handHold and handEntry are available from leapjs-plugins, included above.
// handHold provides hand.data
// handEntry provides handFound/handLost events.
.use('handHold')
.use('handEntry')
.on('handFound', function(hand){
hand.fingers.forEach(function (finger) {
var boneMeshes = [];
var jointMeshes = [];
finger.bones.forEach(function(bone) {
// create joints
// CylinderGeometry(radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded)
var boneMesh = new THREE.Mesh(
new THREE.CylinderGeometry(5, 5, bone.length),
new THREE.MeshPhongMaterial()
);
boneMesh.material.color.setHex(0xffffff);
scene.add(boneMesh);
boneMeshes.push(boneMesh);
});
for (var i = 0; i < finger.bones.length + 1; i++) {
var jointMesh = new THREE.Mesh(
new THREE.SphereGeometry(8),
new THREE.MeshPhongMaterial()
);
jointMesh.material.color.setHex(0x0088ce);
scene.add(jointMesh);
jointMeshes.push(jointMesh);
}
finger.data('boneMeshes', boneMeshes);
finger.data('jointMeshes', jointMeshes);
});
if (hand.arm){ // 2.0.3+ have arm api,
// CylinderGeometry(radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded)
var armMesh = new THREE.Mesh(
new THREE.CylinderGeometry(1, 1, hand.arm.length, 64),
new THREE.MeshPhongMaterial()
);
armMesh.material.color.setHex(0xffffff);
scene.add(armMesh);
hand.data('armMesh', armMesh);
}
})
.on('handLost', function(hand){
hand.fingers.forEach(function (finger) {
var boneMeshes = finger.data('boneMeshes');
var jointMeshes = finger.data('jointMeshes');
boneMeshes.forEach(function(mesh){
scene.remove(mesh);
});
jointMeshes.forEach(function(mesh){
scene.remove(mesh);
});
finger.data({
boneMeshes: null,
boneMeshes: null
});
});
var armMesh = hand.data('armMesh');
scene.remove(armMesh);
hand.data('armMesh', null);
renderer.render(scene, camera);
})
.connect();
// all units in mm
var initScene = function () {
window.scene = new THREE.Scene();
window.renderer = new THREE.WebGLRenderer({
alpha: true
});
window.renderer.setClearColor(0x000000, 0);
window.renderer.setSize(window.innerWidth, window.innerHeight);
window.renderer.domElement.style.position = 'fixed';
window.renderer.domElement.style.top = 0;
window.renderer.domElement.style.left = 0;
window.renderer.domElement.style.width = '100%';
window.renderer.domElement.style.height = '100%';
document.body.appendChild(window.renderer.domElement);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.position.set( 0, 0.5, 1 );
window.scene.add(directionalLight);
window.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
window.camera.position.fromArray([0, 100, 500]);
window.camera.lookAt(new THREE.Vector3(0, 160, 0));
window.addEventListener('resize', function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
}, false);
scene.add(camera);
var geometry = new THREE.CubeGeometry(30, 45, 10);
var material = new THREE.MeshPhongMaterial({color: 0x0000cc});
window.cube = new THREE.Mesh(geometry, material);
cube.position.set(0,0,0);
cube.castShadow = true;
cube.receiveShadow = true;
scene.add(cube);
renderer.render(scene, camera);
};
initScene();
var rotateCube = function(){
cube.rotation.x += 0.01;
cube.rotation.y += 0.02;
renderer.render(scene, camera);
window.requestAnimationFrame(rotateCube);
};
rotateCube();
</script>
</html>