xeokit / xeokit-sdk

Open source JavaScript SDK for viewing high-detail, full-precision 3D BIM and AEC models in the Web browser.
https://xeokit.io
Other
738 stars 291 forks source link

IfcSpace elements with 0 opacity are not pickable even if pickable=true #1372

Closed hamza-hajji closed 9 months ago

hamza-hajji commented 9 months ago

Describe the bug Version: 2.5.2-beta-22 Setting an IfcSpace's opacity to 0 seems to make it unpickable with Scene#pick

To Reproduce Steps to reproduce the behavior:

  1. Go to https://xeokit.github.io/xeokit-sdk/examples/buildings/#xkt_vbo_Schependomlaan
  2. Make its IfcSpace elements have opacity 0

const sceneModel = xktLoader.load({ id: "myModel", src: "../../assets/models/xkt/v8/ifc/Schependomlaan.ifc.xkt", saoEnabled: true, edges: false, dtxEnabled: true, pickSurfacePrecisionEnabled: true, objectDefaults: { // This model has opaque windows / spaces; make them transparent IfcPlate: { opacity: 0.3, // These are used as windows in this model - make transparent }, IfcWindow: { opacity: 0.4, }, IfcSpace: { opacity: 0, }, }, });

3. Pick elements on mousemove

viewer.scene.input.on("mousemove", (coords) => { const hit = viewer.scene.pick({ canvasPos: coords, pickSurface: true, });

console.log("Hit?", hit); if (hit && hit.entity) { hit.entity.selected = true; hit.entity.opacity = 0.5; } });



5. Turn off some elements from the tree to be able to see the IfcSpaces

It continuously get a null pick no matter how much I hover

If I make the opacity 0.1, it works as expected

![image](https://github.com/xeokit/xeokit-sdk/assets/26790341/6dfe4e69-08cc-4d82-8ec2-1aa64461effc)

**Expected behavior**
In previous versions 2.4.X, even elements with opacity=0, the pick works

**Screenshots**

![image](https://github.com/xeokit/xeokit-sdk/assets/26790341/c93cfaa9-3333-444b-8329-e41e1069c68e)
paireks commented 9 months ago

Hey :)

I couldn't really reproduced it on the current 2.5.2-beta-22 (or I don't get it :)). It gets "null" only when the mouse is pointing on nothing. But IfcSpace on opacity 0.0 looks like it's reporting what it hits.

https://github.com/xeokit/xeokit-sdk/assets/47977819/c54131f7-b22e-4bbb-baa2-ded9558c7ff8

Let me know if I can't see something :)

hamza-hajji commented 9 months ago

Hi @paireks. Thanks a lot for looking into this. It looks like it's reprduced only when we set IfcSpaces specifcally to be pickable afterwards. Here's a screencast of the reproduction of the issue Here's the code I use:

const ifcSpaces = viewer.metaScene.metaObjectsByType.IfcSpace;
const ifcSpaceIds = ifcSpaces ? Object.keys(ifcSpaces) : [""];
viewer.scene.setObjectsPickable(ifcSpaceIds, true);
xeolabs commented 9 months ago

I'll take a look in the next couple of days also (travelling at the moment)

hamza-hajji commented 9 months ago

@xeolabs any news on this?

xeolabs commented 9 months ago

@hamza-hajji news will appear here as soon as this issue is resolved.

xeolabs commented 9 months ago

Seems to work OK for me in @xeokit/xeokit-sdk 2.5.2-beta-23

Screencast from 26.02.2024 11:25:04.webm

This is my JS:

 import {
        Viewer,
        XKTLoaderPlugin,
        NavCubePlugin,
        TreeViewPlugin,
        FastNavPlugin
    } from "../../dist/xeokit-sdk.min.es.js";

    const viewer = new Viewer({
        canvasId: "myCanvas",
        transparent: true,
        saoEnabled: true
    });

    viewer.scene.camera.eye = [14.915582703146043, 14.396781491179095, 5.431098754133695];
    viewer.scene.camera.look = [6.599999999999998, 8.34099990051474, -4.159999575600315];
    viewer.scene.camera.up = [-0.2820584034861215, 0.9025563895259413, -0.3253229483893775];

    new NavCubePlugin(viewer, {
        canvasId: "myNavCubeCanvas",
        visible: true,
        size: 250,
        alignment: "bottomRight",
        bottomMargin: 100,
        rightMargin: 10
    });

    new TreeViewPlugin(viewer, {
        containerElement: document.getElementById("treeViewContainer"),
        hierarchy: "types",
        autoExpandDepth: 1
    });

    new FastNavPlugin(viewer, {
        hideEdges: true,
        hideSAO: true,
        hideColorTexture: false,
        hidePBR: false,
        hideTransparentObjects: false,
        scaleCanvasResolution: false,
        scaleCanvasResolutionFactor: 0.5,
        delayBeforeRestore: true,
        delayBeforeRestoreSeconds: 0.4
    });

    const xktLoader = new XKTLoaderPlugin(viewer);

    const sceneModel = xktLoader.load({
        id: "myModel",
        src: "../../assets/models/xkt/v8/ifc/Schependomlaan.ifc.xkt",
        saoEnabled: true,
        edges: false,
        dtxEnabled: true,
        objectDefaults: { // This model has opaque windows / spaces; make them transparent
            "IfcPlate": {
                opacity: 0.3 // These are used as windows in this model - make transparent
            },
            "IfcWindow": {
                opacity: 0.4
            },
            IfcSpace: {
                opacity: 0,
            }
        }
    });

    sceneModel.on("loaded", () => {
        viewer.cameraFlight.jumpTo(sceneModel);

        const ifcSpaces = viewer.metaScene.metaObjectsByType.IfcSpace;
        const ifcSpaceIds = ifcSpaces ? Object.keys(ifcSpaces) : [""];
        viewer.scene.setObjectsPickable(ifcSpaceIds, true);
    });

    const t0 = performance.now();
    document.getElementById("time").innerHTML = "Loading model...";
    sceneModel.on("loaded", function () {
        const t1 = performance.now();
        document.getElementById("time").innerHTML = "Model loaded in " + Math.floor(t1 - t0) / 1000.0 + " seconds<br>Objects: " + sceneModel.numEntities;
    });

    window.viewer = viewer;

    viewer.scene.input.on("mousemove", (coords) => {
        const hit = viewer.scene.pick({
            canvasPos: coords,
            pickSurface: true,
        });

        console.log("Hit?", hit);
        if (hit && hit.entity) {

            console.log("Hit = yes");

            hit.entity.selected = true;
            hit.entity.opacity = 0.5;
        }
    });
hamza-hajji commented 9 months ago

Interesting, your example works on 2.5.2-beta-8 as well. But when I comment out hit.entity.opacity = 0.5; it gives null hits.

viewer.scene.input.on("mousemove", (coords) => {
  const hit = viewer.scene.pick({
    canvasPos: coords,
    pickSurface: true,
  });

  console.log("Hit?", hit);
  if (hit && hit.entity) {
    console.log("Hit = yes");

    hit.entity.selected = true;
    // hit.entity.opacity = 0.5;
  }
});

NB: In version 2.4.2-beta-49, even with the commented out line // hit.entity.opacity = 0.5; I have the desired behavior, it's picked even at opacity 0

image