0

i have tried a lot of ways to go around this topic, before asking and now i really have no clue how to accomplish object picking with gpu on a gltf loaded file, so im hoping for any help that i can get :(

I've loaded a huge GLTF file, with a lot of little objects in it, due to the file count its not possible to achieve a good fps, if i just add them to the scene, so i have managed to achieve 60fps merging the gltfs children into chunks, but when i try to implement the webgl_interactive_cubes_gpu example, but it doesn't seem to be working for me, I always get the same object when im clicking.

To debug i have tried rendering the pickingScene and everything seems to be in place, graphically speaking, but when it comes to picking it doesnt seem to be working as i expected, unless im doing something wrong.

Raycast picking is not a suitable option for me as there are a lot of objects and adding renderin them would kill the fps. (55k objects);

Below is the code once the gltf is loaded:

var child = gltf.scene.children[i];
                    var childGeomCopy = child.geometry.clone();
                    childGeomCopy.translate(geomPosition.x, geomPosition.y, geomPosition.z);
                    childGeomCopy.scale(child.scale.x * Scalar, child.scale.y * Scalar, child.scale.z * Scalar);
                    childGeomCopy.computeBoundingBox();
                    childGeomCopy.computeBoundingSphere();
                    childGeomCopy.applyMatrix(new THREE.Matrix4());

                    geometriesPicking.push(childGeomCopy);

                    var individualObj = new THREE.Mesh(childGeomCopy, IndividualObjMat);
                    individualObj.name = "individual_" + child.name;

                    pickingData[childCounter] = {
                        object: individualObj,
                        position: individualObj.position.clone(),
                        rotation: individualObj.rotation.clone(),
                        scale: individualObj.scale.clone()
                    };
                    childCounter++;

Edit:

gltf.scene.traverse(function (child) {
                    //console.log(child.type);
                    if (child.isMesh) {
                        let geometry = child.geometry.clone();

                        let position = new THREE.Vector3();
                        position.x = child.position.x;
                        position.y = child.position.y;
                        position.z = child.position.z;

                        let rotation = new THREE.Euler();
                        rotation.x = child.rotation.x;
                        rotation.y = child.rotation.y;
                        rotation.z = child.rotation.z;

                        let scale = new THREE.Vector3();
                        scale.x = child.scale.x;
                        scale.y = child.scale.y;
                        scale.z = child.scale.z;

                        quaternion.setFromEuler(rotation);
                        matrix.compose(position.multiplyScalar(Scalar), quaternion, scale.multiplyScalar(Scalar));
                        geometry.applyMatrix(matrix);

                        applyVertexColors(geometry, color.setHex(Math.random() * 0xffffff));
                        geometriesDrawn.push(geometry);

                        geometry = geometry.clone();
                        applyVertexColors(geometry, color.setHex(childCounter));
                        geometriesPicking.push(geometry);

                        pickingData[childCounter] = {
                            object: new THREE.Mesh(geometry.clone(), new THREE.MeshBasicMaterial({ color: 0xffff00, blending: THREE.AdditiveBlending, transparent: true, opacity: 0.8 })),
                            id: childCounter,
                            position: position,
                            rotation: rotation,
                            scale: scale
                        };
                        childCounter++;
                        //console.log("%c [childCounter] :", "", childCounter);
                    }
                });

... var pickingGeom = THREE.BufferGeometryUtils.mergeBufferGeometries(geometriesPicking); pickingGeom.rotateX(THREE.Math.degToRad(90)); pickingScene.add(new THREE.Mesh(pickingGeom, pickingMaterial));

Then on my MouseUp function I call pick(mouse*) and pass in the mouse* information:

function pick(mouse) {
camera.setViewOffset(renderer.domElement.width, renderer.domElement.height, mouse.x * window.devicePixelRatio | 0, mouse.y * window.devicePixelRatio | 0, 1, 1);
renderer.setRenderTarget(pickingTexture);
renderer.render(pickingScene, camera);
camera.clearViewOffset();
var pixelBuffer = new Uint8Array(4);
renderer.readRenderTargetPixels(pickingTexture, 0, 0, 1, 1, pixelBuffer);
var id = (pixelBuffer[0] << 16) | (pixelBuffer[1] << 8) | (pixelBuffer[2]);
var data = pickingData[id];

if (data) {
    console.log(data.object.name, ":", data.position); // Always return the same object
}}
nosh247
  • 13
  • 5
  • Where is your code generating vertex colors with the object ids? if you look at [this sample](https://github.com/mrdoob/three.js/blob/master/examples/webgl_interactive_cubes_gpu.html) you'll see for one it's a static scene, it creates one giant geometry to pick from with vertex colors that map to object ids. – gman Oct 31 '19 at 12:46
  • @gman hey thanks for your response, i managed to make it work with individual objects from the gltf that i am loading. Could you help me understand how if rendering potree pointcloud over the model be affecting the picking of the objects? Because when i try it on the example it works, but when i try it on top of a pointcloud with potree running it always outputs the index 0 when i log "data", Im thinking that maybe i need to turn off the potree engine alltogether to make this work as it changes the SetRenderTarget. Is there a way to create a view "setViewOffset" from the camera? – nosh247 Oct 31 '19 at 17:22

0 Answers0