UNPKG

leapjs-plugins

Version:
388 lines (358 loc) 13.6 kB
//CoffeeScript generated from main/bone-hand/leap.bone-hand.coffee (function() { var HandMesh, THREE, armTopAndBottomRotation, baseBoneRotation, boneColor, boneHandLost, boneRadius, boneScale, initScene, jointColor, jointRadius, jointScale, material, onHand, scope; scope = null; THREE = typeof require !== 'undefined' ? require('three') : window.THREE; initScene = function(targetEl, scale) { var camera, far, height, near, renderer, width; scope.scene = new THREE.Scene(); scope.rendererOps || (scope.rendererOps = {}); if (scope.rendererOps.alpha === void 0) { scope.rendererOps.alpha = true; } scope.renderer = renderer = new THREE.WebGLRenderer(scope.rendererOps); width = scope.width || window.innerWidth; height = scope.height || window.innerHeight; renderer.setClearColor(0x000000, 0); renderer.setSize(width, height); renderer.domElement.className = "leap-boneHand"; renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; targetEl.appendChild(renderer.domElement); near = 1; far = 10000; if (scale) { near *= scale; far *= scale; } scope.camera = camera = new THREE.PerspectiveCamera(45, width / height, near, far); camera.position.set(0, 300, 500); camera.lookAt(new THREE.Vector3(0, 160, 0)); scope.scene.add(camera); if (!scope.width && !scope.height) { window.addEventListener('resize', function() { width = window.innerWidth; height = window.innerHeight; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height); return renderer.render(scope.scene, camera); }, false); } scope.render || (scope.render = function(timestamp) { return renderer.render(scope.scene, scope.camera); }); return scope.render(); }; baseBoneRotation = null; jointColor = null; boneColor = null; boneScale = null; jointScale = null; boneRadius = null; jointRadius = null; material = null; armTopAndBottomRotation = null; HandMesh = (function() { HandMesh.unusedHandMeshes = []; HandMesh.get = function() { var handMesh; if (HandMesh.unusedHandMeshes.length === 0) { handMesh = HandMesh.create(); } handMesh = HandMesh.unusedHandMeshes.pop(); handMesh.show(); return handMesh; }; HandMesh.prototype.replace = function() { this.hide(); return HandMesh.unusedHandMeshes.push(this); }; HandMesh.create = function() { var mesh; mesh = new HandMesh; mesh.setVisibility(false); HandMesh.unusedHandMeshes.push(mesh); if (HandMesh.onMeshCreated) { HandMesh.onMeshCreated(mesh); } return mesh; }; function HandMesh() { var boneCount, finger, i, j, mesh, _i, _j, _k, _l; material = !isNaN(scope.opacity) ? new THREE.MeshPhongMaterial({ fog: false, transparent: true, opacity: scope.opacity }) : new THREE.MeshPhongMaterial({ fog: false }); boneRadius = 40 * boneScale; jointRadius = 40 * jointScale; this.fingerMeshes = []; for (i = _i = 0; _i < 5; i = ++_i) { finger = []; boneCount = i === 0 ? 3 : 4; for (j = _j = 0; 0 <= boneCount ? _j < boneCount : _j > boneCount; j = 0 <= boneCount ? ++_j : --_j) { mesh = new THREE.Mesh(new THREE.SphereGeometry(jointRadius, 32, 32), material.clone()); mesh.name = "hand-bone-" + j; mesh.material.color.copy(jointColor); mesh.renderOrder = ((i * 9) + (2 * j)) / 36; mesh.castShadow = true; scope.scene.add(mesh); finger.push(mesh); mesh = new THREE.Mesh(new THREE.CylinderGeometry(boneRadius, boneRadius, 40, 32), material.clone()); mesh.name = "hand-joint-" + j; mesh.material.color.copy(boneColor); mesh.renderOrder = ((i * 9) + (2 * j) + 1) / 36; mesh.castShadow = true; scope.scene.add(mesh); finger.push(mesh); } mesh = new THREE.Mesh(new THREE.SphereGeometry(jointRadius, 32, 32), material.clone()); mesh.material.color.copy(jointColor); mesh.castShadow = true; scope.scene.add(mesh); finger.push(mesh); this.fingerMeshes.push(finger); } if (scope.arm) { this.armMesh = new THREE.Object3D; this.armBones = []; this.armSpheres = []; for (i = _k = 0; _k <= 3; i = ++_k) { this.armBones.push(new THREE.Mesh(new THREE.CylinderGeometry(boneRadius, boneRadius, (i < 2 ? 1000 : 100), 32), material.clone())); this.armBones[i].material.color.copy(boneColor); this.armBones[i].castShadow = true; this.armBones[i].name = "ArmBone" + i; if (i > 1) { this.armBones[i].quaternion.multiply(armTopAndBottomRotation); } this.armMesh.add(this.armBones[i]); } this.armSpheres = []; for (i = _l = 0; _l <= 3; i = ++_l) { this.armSpheres.push(new THREE.Mesh(new THREE.SphereGeometry(jointRadius, 32, 32), material.clone())); this.armSpheres[i].material.color.copy(jointColor); this.armSpheres[i].castShadow = true; this.armSpheres[i].name = "ArmSphere" + i; this.armMesh.add(this.armSpheres[i]); } scope.scene.add(this.armMesh); } } HandMesh.prototype.traverse = function(callback) { var i, mesh, _i, _j, _len, _ref; for (i = _i = 0; _i < 5; i = ++_i) { _ref = this.fingerMeshes[i]; for (_j = 0, _len = _ref.length; _j < _len; _j++) { mesh = _ref[_j]; callback(mesh); } } return this.armMesh && this.armMesh.traverse(callback); }; HandMesh.prototype.scaleTo = function(hand) { var armLenScale, armWidthScale, baseScale, bone, boneXOffset, finger, fingerBoneLengthScale, halfArmLength, i, j, mesh, _i, _j; baseScale = hand.middleFinger.proximal.length / this.fingerMeshes[2][1].geometry.parameters.height; for (i = _i = 0; _i < 5; i = ++_i) { finger = hand.fingers[i]; j = 0; while (true) { if (j === this.fingerMeshes[i].length - 1) { mesh = this.fingerMeshes[i][j]; mesh.scale.set(baseScale, baseScale, baseScale); break; } bone = finger.bones[3 - (j / 2)]; mesh = this.fingerMeshes[i][j]; mesh.scale.set(baseScale, baseScale, baseScale); j++; mesh = this.fingerMeshes[i][j]; fingerBoneLengthScale = bone.length / mesh.geometry.parameters.height; mesh.scale.set(baseScale, fingerBoneLengthScale, baseScale); j++; } } if (scope.arm) { armLenScale = hand.arm.length / (this.armBones[0].geometry.parameters.height + this.armBones[0].geometry.parameters.radiusTop); armWidthScale = hand.arm.width / (this.armBones[2].geometry.parameters.height + this.armBones[2].geometry.parameters.radiusTop); for (i = _j = 0; _j <= 3; i = ++_j) { this.armBones[i].scale.set(baseScale, (i < 2 ? armLenScale : armWidthScale), baseScale); this.armSpheres[i].scale.set(baseScale, baseScale, baseScale); } boneXOffset = (hand.arm.width / 2) * 0.85; halfArmLength = hand.arm.length / 2; this.armBones[0].position.setX(boneXOffset); this.armBones[1].position.setX(-boneXOffset); this.armBones[2].position.setY(halfArmLength); this.armBones[3].position.setY(-halfArmLength); this.armSpheres[0].position.set(-boneXOffset, halfArmLength, 0); this.armSpheres[1].position.set(boneXOffset, halfArmLength, 0); this.armSpheres[2].position.set(boneXOffset, -halfArmLength, 0); this.armSpheres[3].position.set(-boneXOffset, -halfArmLength, 0); } return this; }; HandMesh.prototype.formTo = function(hand) { var bone, finger, i, j, mesh, _i; for (i = _i = 0; _i < 5; i = ++_i) { finger = hand.fingers[i]; j = 0; while (true) { if (j === this.fingerMeshes[i].length - 1) { mesh = this.fingerMeshes[i][j]; mesh.position.fromArray(bone.prevJoint); break; } bone = finger.bones[3 - (j / 2)]; mesh = this.fingerMeshes[i][j]; mesh.position.fromArray(bone.nextJoint); ++j; mesh = this.fingerMeshes[i][j]; mesh.position.fromArray(bone.center()); mesh.setRotationFromMatrix((new THREE.Matrix4).fromArray(bone.matrix())); mesh.quaternion.multiply(baseBoneRotation); ++j; } } if (this.armMesh) { this.armMesh.position.fromArray(hand.arm.center()); this.armMesh.setRotationFromMatrix((new THREE.Matrix4).fromArray(hand.arm.matrix())); this.armMesh.quaternion.multiply(baseBoneRotation); } return this; }; HandMesh.prototype.setVisibility = function(visible) { var i, j, _i, _j, _results; for (i = _i = 0; _i < 5; i = ++_i) { j = 0; while (true) { this.fingerMeshes[i][j].visible = visible; ++j; if (j === this.fingerMeshes[i].length) { break; } } } if (scope.arm) { _results = []; for (i = _j = 0; _j <= 3; i = ++_j) { this.armBones[i].visible = visible; _results.push(this.armSpheres[i].visible = visible); } return _results; } }; HandMesh.prototype.show = function() { return this.setVisibility(true); }; HandMesh.prototype.hide = function() { return this.setVisibility(false); }; return HandMesh; })(); onHand = function(hand) { var handMesh; if (!scope.scene) { return; } handMesh = hand.data('handMesh'); if (!handMesh) { handMesh = HandMesh.get().scaleTo(hand); hand.data('handMesh', handMesh); if (HandMesh.onMeshUsed) { HandMesh.onMeshUsed(handMesh); } } return handMesh.formTo(hand); }; boneHandLost = function(hand) { var handMesh; handMesh = hand.data('handMesh'); if (handMesh) { handMesh.replace(); } return handMesh = hand.data('handMesh', null); }; Leap.plugin('boneHand', function(options) { var controller, scale; if (options == null) { options = {}; } scope = options; controller = this; jointColor = (new THREE.Color).setHex(0x5daa00); boneColor = (new THREE.Color).setHex(0xffffff); scope.boneScale && (boneScale = scope.boneScale); scope.jointScale && (jointScale = scope.jointScale); scope.boneColor && (boneColor = scope.boneColor); scope.jointColor && (jointColor = scope.jointColor); scope.HandMesh = HandMesh; scope.addShadowCamera = function() { scope.light = new THREE.SpotLight(0xffffff, 1); scope.light.castShadow = true; scope.light.shadow.mapSize.width = 1024; scope.light.shadow.mapSize.height = 1024; scope.light.shadow.camera.near = 0.5 / 0.001; scope.light.shadow.camera.far = 3 / 0.001; scope.light.position.set(0, 1000, 1000); scope.light.target.position.set(0, 0, -1000); scope.camera.add(scope.light.target); scope.camera.add(scope.light); if (controller.plugins.transform) { if (controller.plugins.transform.getScale()) { scope.light.shadowCameraNear *= controller.plugins.transform.scale.x; scope.light.shadowCameraFar *= controller.plugins.transform.scale.x; scope.light.target.position.multiply(controller.plugins.transform.scale); scope.light.position.multiply(controller.plugins.transform.scale); } if (controller.plugins.transform.vr === true) { scope.camera.position.set(0, 0, 0); } if (controller.plugins.transform.vr === 'desktop') { return scope.camera.position.set(0, 0.15, 0.3); } } }; baseBoneRotation = (new THREE.Quaternion).setFromEuler(new THREE.Euler(Math.PI / 2, 0, 0)); boneScale = 1 / 6; jointScale = 1 / 5; boneRadius = null; jointRadius = null; material = null; armTopAndBottomRotation = (new THREE.Quaternion).setFromEuler(new THREE.Euler(0, 0, Math.PI / 2)); HandMesh.onMeshCreated = function(mesh) { return controller.emit('handMeshCreated', mesh); }; HandMesh.onMeshUsed = function(mesh) { return controller.emit('handMeshUsed', mesh); }; this.use('handEntry'); this.use('handHold'); if (scope.scene === void 0) { console.assert(scope.targetEl); if (this.plugins.transform && this.plugins.transform.getScale()) { scale = this.plugins.transform.scale.x; } initScene(scope.targetEl, scale); scope.addShadowCamera(); } if (scope.scene) { HandMesh.create(); HandMesh.create(); if (Leap.version.major === 0 && Leap.version.minor < 7 && Leap.version.dot < 4) { console.warn("BoneHand default scene render requires LeapJS > 0.6.3. You're running have " + Leap.version.full); } this.on('frameEnd', function(timestamp) { if (scope.render) { return scope.render(timestamp); } }); } this.on('handLost', boneHandLost); return { hand: onHand }; }); }).call(this);