[SOLVED] Entity Picking only working from two sides


#1

Hi, so I followed the tutorial for entity picking and made a script that generates a few boxes which can then be highlighted by hovering the mouse over them. So far so good, everything works fine as long as I’m looking at the boxes from the front or back (Positive or negative Z-Axis) but if I look at them from the side (Positive or negative X-Axis) they are basically selected inverted. So when I then point the mouse at the one furthest from the camera, the one closest to it highlights and so for all following.

I’m using the script from the tutorial with a few adjustments to what the console Warnings said to change (as some things were deprecated or parameters changed)

MyPickingScript.prototype.onHover = function (event) {
    var canvas = this.app.graphicsDevice.canvas;
    var canvasWidth = parseInt(canvas.clientWidth, 10);
    var canvasHeight = parseInt(canvas.clientHeight, 10);

    var camera = this.cameraEntity.camera; //cameraEntity is an attribute to which I assigned the camera entity
    var scene = this.app.scene;
    var picker = this.picker;  //this picker is declared in the init-function as following: 
                                           //this.picker = new pc.Picker(this.app, 1024, 1024);

    this.app.renderNextFrame = true;
    picker.prepare(camera, scene, scene.layers.getLayerByName("AllowPicking"));

    // Map the mouse coordinates into picker coordinates and
    // query the selection
    var selected = picker.getSelection(
        Math.floor(event.x * (picker.width / canvasWidth)),
        picker.height - Math.floor(event.y * (picker.height / canvasHeight)));

    if (selected.length > 0 && selected[0].node) {
        // Get the graph node used by the selected mesh instance
        var entity = selected[0].node;

        // Bubble up the hierarchy until we find an actual Entity
        while (!(entity instanceof pc.Entity) && entity !== null) {
            entity = entity.getParent();
        }
        if (entity.getParent() == this.entity) {
            this.entity.children.forEach((c)=>{
                if(c instanceof pc.Entity)c.model.meshInstances[0].material = this.colliderMat.resource;});
            entity.model.meshInstances[0].material = this.colliderMat_hover.resource;
        }
    }
};


#2

Can you share the project link please if possible?


#3

Hi, I couldn’t share the project itself, but I reproduced the issue in the following public project: https://playcanvas.com/project/601190/overview/entity-picking-issue


#4

Very odd :confused:

Do you need this specific type of entity picking or could you use an alternative method such as the simple shapes shown here in the meantime https://developer.playcanvas.com/en/tutorials/simple-shape-raycasting/


#5

Thanks for the reply - I thought that Entity Picking was the only way to detect a clicked entity without enabling Physics but I can see that the example you linked doesn’t utilise physics either.
Is there any performance advantages/disadvantages using the RayCasting from that example in comparison to Entity Picking?


#6

Entity picking using the picker has a cost to it as it stalls the renderer IIRC. It is far more accurate for custom shaped meshes though.

The raycasting from the example is pretty cheap performance wise but only handles primitive shapes.


#7

In that case it should probably be even more effective for my case as I’m only looking to pick boxes - Thanks a lot!

If possible, it would be really nice if this info could be added to this page:
https://developer.playcanvas.com/en/tutorials/entity-picking/


#8

As a side note, I think I fixed your example too. I think the y position of when getSelection is used is inverted. See this fork and see if it works for you: https://playcanvas.com/project/601195/overview/entity-picking-issue-from-forums

Edit: Not 100% sure why this happens as the original tutorial works the way it is currently. Maybe @will can shed some light on this?


#9

Aweseome - yes that does fix the issue.
That bit was copied from the linked tutorial from my last reply.
There it states:

// query the selection
    var selected = picker.getSelection({
        x: Math.floor(event.x * (picker.width / canvasWidth)),
        y: picker.height - Math.floor(event.y * (picker.height / canvasHeight))
    });

But that tutorial needs an update either way as some of the syntax has changed.


#10

The bit that confuses me is that tutorial works as is so I’m not sure what the difference is between the two projects that causes the inversion :confused:


#11

Could it be the deprecated declaration as Picker.getSelection used to expect an object as parameter? I mean I really don’t know but maybe something changed in the class itself as for example that the class code now automatically does the inversion of the y-axis and maybe before one had to do it ‘manually’ ?


#12

Ah, that does ring a bell. You are right, looking at the source code, the inversion is done in the getSelection function when not using an object. Good spot. https://github.com/playcanvas/engine/blob/master/src/scene/pick.js