Reputation: 33
I'm developing a 2d viewer of CAD drawings using the three.js library and for this project I need to be able to click the objects in the scene to do some operations.
Using orthographic camera the three.js raycasting is not precise as I expect.
Here the code and a fiddle that shows exactly what I mean https://jsfiddle.net/toriphes/a0o7td1u/
var camera, scene, renderer, square, raycaster;
init();
animate();
function init() {
output = document.getElementById('output');
raycaster = new THREE.Raycaster();
// Renderer.
renderer = new THREE.WebGLRenderer();
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
var aspect = window.innerWidth / window.innerHeight;
var d = 20;
camera = new THREE.OrthographicCamera(-window.innerWidth / 2, window.innerWidth / 2, window.innerHeight / 2, -window.innerHeight / 2, 1, 1000);
camera.position.z = 10;
camera.position.x = 25;
camera.position.y = 25;
camera.zoom = 10
camera.updateProjectionMatrix()
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableRotate = false
controls.target.x = camera.position.x;
controls.target.y = camera.position.y;
controls.update();
// Create scene.
scene = new THREE.Scene();
var points = [
new THREE.Vector2(10, 10),
new THREE.Vector2(40, 10),
new THREE.Vector2(40, 40),
new THREE.Vector2(10, 40),
new THREE.Vector2(10, 10)
]
var shape = new THREE.Shape(points);
var geometry = new THREE.Geometry().setFromPoints(points);
var square = new THREE.Line(geometry, new THREE.LineBasicMaterial({
color: 0xFF0000
}));
scene.add(square)
document.addEventListener('mousemove', findIntersections, false);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function updateMousePosition(event) {
return new THREE.Vector3(
(event.clientX - renderer.domElement.offsetLeft) /
renderer.domElement.clientWidth *
2 -
1,
-(
(event.clientY - renderer.domElement.offsetTop) /
renderer.domElement.clientHeight
) *
2 +
1,
0
);
}
function findIntersections(e) {
var mouseposition = updateMousePosition(e);
raycaster.setFromCamera(mouseposition, camera);
const intersects = raycaster.intersectObjects(scene.children);
output.innerHTML = intersects.length > 0 ?
'Intersect: TRUE' :
'Intersect: FALSE';
}
If you pass the mouse near the red square you can see that the intersection trigger before hovering the edge.
What am I doing wrong?
Upvotes: 3
Views: 1497
Reputation: 210908
The intersection detection of lines depends on the .linePrecision
property of the Raycaster
.
e.g.
raycaster.linePrecision = 0.1;
const intersects = raycaster.intersectObjects(scene.children);
The parameter has to be set dependent on the scale of the scene. The value of 0.1 is an empirical value, which gives good results for your example. Sadly there is not further information provided in the documentation (perhaps I've overlooked something, but I didn't find one).
Upvotes: 3