Skip to content

Picking for GLTF isn't working correctly #2678

@AnthonyGlt

Description

@AnthonyGlt

When using the picking on a gtlf, we don't get any result.
This is the case when the background color is left at the default value (#000000 <- black)

view.mainLoop.gfxEngine.renderer.setClearColor(

Your Environment

branch master

Context

When calling view.pickObjectsAt(event, 0, gtlfObj);, the return value is always empty.
Even though i'm clicking on the object.
It works if I set the background color to a different value, using view.mainLoop.gfxEngine.renderer.setClearColor(...)

Steps to Reproduce

  1. Don't call view.mainLoop.gfxEngine.renderer.setClearColor()
  2. Import GLTF
  3. Enable Picking on the gltf by click with a radius >= 0
  4. Click and see that no value is returned

Expected Behavior

Return the gltf object

Actual Behavior

Nothing is returned

Possible Cause/Fix/Solution

When calling view.pickObjectsAt() for a gltf with a radius >= 0, we go directly to Picking.js pickObjectsAt
In this method, we render a circular zone to a buffer and reads the pixel colors back based on the 3d object (gltf). BUT it always returns RGB values closed to 0 and then we compare those values with the background color view.mainLoop.gfxEngine.renderer.getClearColor(clearColor); which is, by default, black. So the picking area is considered as being part of the background because they are both black ...

The issue is that when we read the pixels colors values from the rendering, we shouldn't not get the color black. Currently, I think we get this wrong values because in the rendering, we are missing a light, so the scene is just black...

To correct this, we could either create a temporary scene containing only the object and a light and use it for the render.
Or just render the full scene and not only the object.

IMO the second option is the way to go

Reprod Script

<html>
    <head>
        <title>Itowns - Instancing</title>

        <script type="importmap">
        {
            "imports": {
                "itowns": "../dist/itowns.js",
                "three": "https://unpkg.com/three@0.182.0/build/three.module.js",
                "three/addons/": "https://unpkg.com/three@0.182.0/examples/jsm/"
            }
        }
        </script>
        <meta charset="UTF-8" />
        <link rel="stylesheet" type="text/css" href="css/example.css" />

        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    </head>
    <body>
        <div id="description">
            <p>
                <b>
                    Render a large number of objects with the same geometry<br/>
                    by importing your 3D models
                </b>
            </p>
        </div>
        <div id="viewerDiv" class="viewer"></div>
        <script type="module">

            import * as THREE from 'three';
            import * as itowns from 'itowns';

            // Define initial camera position
            var placement = {
                coord: new itowns.Coordinates("EPSG:4326", -0.57918, 44.837789),
                range: 1000,
                tilt: 45,
            };

            // `viewerDiv` will contain iTowns' rendering area (`<canvas>`)
            var viewerDiv = document.getElementById("viewerDiv");

            // Instanciate iTowns GlobeView*
            var view = new itowns.GlobeView(viewerDiv, placement);
            // view.mainLoop.gfxEngine.renderer.setClearColor(0x999999);


            var ambLight = new THREE.AmbientLight(0xffffff, 0.2);
            view.scene.add(ambLight);

            // Add one imagery layer to the scene
            itowns.Fetcher.json("./layers/JSONLayers/Ortho.json").then(
                function _(config) {
                    config.source = new itowns.WMTSSource(config.source);
                    var layer = new itowns.ColorLayer("Ortho", config);
                    view.addLayer(layer).then(
                    );
                }
            );


            var parentObj = new THREE.Group();
            var parentParentObj = new THREE.Group();

            // Load a glTF resource
            var gltfLoader = new itowns.iGLTFLoader();
            gltfLoader.load(
                // resource URL
                // "https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/models/lampadaire/scene.gltf",
                "https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/models/tree/tree.glb",
                // "./bim.glb",

                // called when the resource is loaded
                (gltf) => {
                    var model = gltf.scene;

                    // Position the model at the placement coordinates
                    model.position.copy(placement.coord.as(view.referenceCrs).toVector3());

                    // Apply rotation and scale
                    model.rotateX(Math.PI / 2.0);
                    model.position.z += 2; // Offset from ground
                    model.scale.set(10, 10, 10);

                    // Update model matrix
                    model.updateMatrixWorld(true);

                    // Add the model directly to the scene
                    // view.scene.add(model);

                    parentObj.add(model);
                    parentParentObj.add(parentObj);
                    view.scene.add(parentParentObj);

                    // Notify view to render the changes
                    view.notifyChange();
                },

                // called while loading is progressing
                () => {
                },

                // called when loading has errors
                (error) => {
                    // eslint-disable-next-line no-console
                    console.log("An error happened :");
                    // eslint-disable-next-line no-console
                    console.log(error);
                }
            );
            function clickHandler(event) {
                var pick = view.pickObjectsAt(event, 0, parentParentObj);

                // for (const p of pick) {
                    console.info('Selected point ' + pick);
                // }
            }
            view.domElement.addEventListener('click', clickHandler);



            window.view = view;
            window.itowns = itowns;
            window.THREE = THREE;

        </script>
    </body>
</html>

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions