Search code examples
javascript3dwebglbabylonjs

Imported meshes can't be picked deterministically


I've got grid of cylinder meshes created simply by

var tile = BABYLON.MeshBuilder.CreateCylinder("tile-" + i, { tessellation: 6, height: 0.1 }, scene);

then I have following event callback

window.addEventListener("click", function (evt) {
    // try to pick an object
    var pickResult = scene.pick(evt.clientX, evt.clientY);
    if (pickResult.pickedMesh != null){
         alert(pickResult.pickedMesh.name)
});

Then mouse-click on one of tiles raises message box with correct tile name.

When I add some new meshes (3D model inside .babylon file) by

var house;
BABYLON.SceneLoader.ImportMesh("", "../Content/"
                              , "house.babylon"
                              , scene
                              , function (newMeshes) 
                                { house = newMeshes[0]; });

For better imagination it's texture of house created from four different meshes which is placed over grid of cylinder tiles.

It's displayed fine but when mouse-click it too much often behave as it would totally ignore there is such a mesh and so pickResult.pickedMesh is either null or pickResult.pickedMesh.name points to tile underlaying my imported mesh in point I've clicked.

Just approximately 5% of mesh area corresponds properly to mouse-clicks (let's say in middle of roof, in middle of walls).

I've tried playing with setting some virtual (hidden) house.parent mesh for that which would not be created by importing meshes but seems as dead end.

Are you aware about some way how enforce that scene.pick(evt.clientX, evt.clientY); would respect mesh hierarchy and would consider all visible parts of overlaying texture?

Just for completeness I'm working with middle part of this 3D model (removed left and right house from that).

EDIT: Demo on BabylonJS playground


Solution

  • you could try change

    var pickResult = scene.pick(evt.clientX, evt.clientY);
    

    to

    var pickResult = scene.pick(scene.pointerX, scene.pointerY);
    

    as evt corresponds to whole page.