UNPKG

trip.three

Version:
93 lines (84 loc) 2.48 kB
'use strict'; var THREE = require('three'); var toWorldPosition = require('./toWorldPosition'); var decimalAdjust = require('./decimalAdjust'); var rayFromWorldAndCamera = require('./rayFromWorldAndCamera'); function findClosestMesh(scene, meshes, position) { var camera = scene.camera; var worldPos = toWorldPosition(scene.width, scene.height, camera, position); var ray = rayFromWorldAndCamera(worldPos, camera); var raycaster = new THREE.Raycaster(ray.origin, ray.direction); var intersects = raycaster.intersectObjects(meshes); if (intersects.length) { var sorted = intersects.sort(function (a, b) { if (a.distance < b.distance) { return -1; } else if (a.distance > b.distance) { return 1; } else { return 0; } }); return { distance: sorted[0].distance, mesh: sorted[0].object, position: sorted[0].point }; } else { return undefined; } } function collectViewsAndMeshes(scene, viewFilter) { var viewsAndMeshes = scene.views.reduce(function (acc, view) { if (view.noEvents) { return acc; } var meshes = []; if (viewFilter(view)) { view.sceneObject.traverseVisible(function (obj) { if (obj instanceof THREE.Mesh) { meshes.push(obj); } }); } if (meshes.length) { acc.push({ view: view, meshes: meshes }); } return acc; }, []); return viewsAndMeshes; } module.exports = function (scene, screenPos, viewFilter) { if (!viewFilter) { viewFilter = function viewFilter() { return true; }; } var viewsAndMeshes = collectViewsAndMeshes(scene, viewFilter); var viewLookup = viewsAndMeshes.reduce(function (acc, viewAndMeshes) { var view = viewAndMeshes.view; viewAndMeshes.meshes.reduce(function (acc, mesh) { acc[mesh.id] = view; return acc; }, acc); return acc; }, {}); var allMeshes = viewsAndMeshes.reduce(function (acc, viewAndMeshes) { acc = acc.concat(viewAndMeshes.meshes); return acc; }, []); var closest = findClosestMesh(scene, allMeshes, screenPos); if (closest !== undefined) { return { distance: closest.distance, position: new THREE.Vector3(decimalAdjust(closest.position.x, -3), decimalAdjust(closest.position.y, -3), decimalAdjust(closest.position.z, -3)), view: viewLookup[closest.mesh.id], mesh: closest.mesh }; } else { return undefined; } };