trip.three
Version:
Three.js addon for Trip
93 lines (84 loc) • 2.48 kB
JavaScript
;
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;
}
};