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
694 stars 279 forks source link

Unexpected ray picking results #1531

Open g-rodigy opened 2 weeks ago

g-rodigy commented 2 weeks ago

Describe the bug In continue #1526 do some tests. First pick choose some point, other repeat from different directions.

To Reproduce

const viewer = new Viewer({
    canvasId: "myCanvas"
})

const xktLoader = new XKTLoaderPlugin(viewer);

const sceneModel = xktLoader.load({
    id: "myModel",
    src: "./xeokit-sdk/assets/models/xkt/v10/glTF-Embedded/Duplex_A_20110505.glTFEmbedded.xkt",
    edges: true,
});

function pickableObjects(status, exdludeId) {
    for (var id in viewer.scene.objects)
        viewer.scene.objects[id].pickable = status

    if (exdludeId)
        viewer.scene.objects[exdludeId].pickable = !status
}

function rayPick(origin, direction, params = {}) {
    var initOpt = {
        pickSurface: true,
        // pickSurfaceNormal: true,
        pickSurfacePrecision: true,
        origin,
        direction,
    }

    var options = Object.assign(initOpt, params)
    return viewer.scene.pick(options, new PickResult())
}

function createDirection(origin, dest) {
    return math.subVec3(dest, origin, math.vec3())
}

function createRay(originPos, directPos) {
    new Mesh(viewer.scene, {
        geometry: new ReadableGeometry(viewer.scene, {
            primitive: "lines",
            positions: [...originPos, ...directPos],
            indices: [0, 1]
        }),
        material: new PhongMaterial(viewer.scene, {
            emissive: [1, 0.3, 0.3],
            diffuse: [0, 0, 0],
            ambient: [0, 0, 0],
            lineWidth: 2
        }),
        pickable: false
    });
}

function createSphere(position, radius = 0.1) {
    new Mesh(viewer.scene, {
        geometry: new ReadableGeometry(viewer.scene, buildSphereGeometry({
            radius,
            heightSegments: 60,
            widthSegments: 60
        })),
        material: new PhongMaterial(viewer.scene, {
            diffuse: [0.1, 0, 0, 1]
        }),
        position,
        pickable: false,
        xrayed: false,
        visible: true
    });
}

viewer.scene.input.on('click', (coords) => {
    var hit = viewer.scene.pick({
        canvasPos: coords,
        pickSurfacePrecision: true,
        pickSurface: true,
        snapToEdge: true,
    }, new PickResult())

    if (!hit?.worldPos)
        return

    pickableObjects(false, hit.entity.id)

    var pyu = math.vec3(hit.worldPos),
        pyd = math.vec3(hit.worldPos),
        pxl = math.vec3(hit.worldPos),
        pxr = math.vec3(hit.worldPos),
        pzf = math.vec3(hit.worldPos),
        pzb = math.vec3(hit.worldPos)

    pyu[1] += 20
    pyd[1] -= 20
    pxl[0] -= 20
    pxr[0] += 20
    pzf[2] += 20
    pzb[2] -= 20

    var pyuDirection = createDirection(pyu, hit.worldPos)
    var pydDirection = createDirection(pyd, hit.worldPos)
    var pxlDirection = createDirection(pxl, hit.worldPos)
    var pxrDirection = createDirection(pxr, hit.worldPos)
    var pzfDirection = createDirection(pzf, hit.worldPos)
    var pzbDirection = createDirection(pzb, hit.worldPos)

    // rays
    var pyuHit = rayPick(pyu, pyuDirection)
    var pydHit = rayPick(pyd, pydDirection)
    var pxlHit = rayPick(pxl, pxlDirection)
    var pxrHit = rayPick(pxr, pxrDirection)
    var pzfHit = rayPick(pzf, pzfDirection)
    var pzbHit = rayPick(pzb, pzbDirection)

    if (pyuHit) {
        createRay(pyu, hit.worldPos)
        createSphere(pyu)
    }
    if (pydHit) {
        createRay(pyd, hit.worldPos)
        createSphere(pyd)
    }
    if (pxlHit) {
        createRay(pxl, hit.worldPos)
        createSphere(pxl)
    }
    if (pxrHit) {
        createRay(pxr, hit.worldPos)
        createSphere(pxr)
    }
    if (pzfHit) {
        createRay(pzf, hit.worldPos)
        createSphere(pzf)
    }
    if (pzbHit) {
        createRay(pzb, hit.worldPos)
        createSphere(pzb)
    }

    pickableObjects(true)
})

Expected behavior When picking same object ray pick must be the same quantity on each click point.

Screenshots

https://github.com/xeokit/xeokit-sdk/assets/30372087/c651029a-9fc8-4c05-972b-29a32d7f90ce

Desktop (please complete the following information):

Additional context xeokit-sdk v2.6.9

xeolabs commented 2 weeks ago

Hi, I'm not sure what the unexpected vs expected behavior is here - could you please describe? Thanks

g-rodigy commented 2 weeks ago

When click on model, has point designated wordPos (1). I make 6 ray picks to this point from different directions (y,-y,x,-x,z,-z) at some distance from this point. If already has point (1) and it exactly entity, expected 6 new hits (PickResult), but in even click it different quantity rays, not 6. On video rays displayed only if ray pick has hit result.