首页 > 解决方案 > GPU 拾取加载的 GLTF 对象

问题描述

在询问之前,我已经尝试了很多方法来解决这个话题,现在我真的不知道如何在 gltf 加载的文件上使用 gpu 完成对象拾取,所以我希望能得到任何帮助:(

我已经加载了一个巨大的 GLTF 文件,其中有很多小对象,由于文件数量,如果我只是将它们添加到场景中,它不可能实现良好的 fps,所以我设法实现了 60fps 合并gltfs 孩子成块,但是当我尝试实现 webgl_interactive_cubes_gpu 示例时,但它似乎对我不起作用,我点击时总是得到相同的对象。

为了调试,我尝试渲染 PickingScene 并且一切似乎都到位,从图形上讲,但是当涉及到挑选时,它似乎并没有像我预期的那样工作,除非我做错了什么。

Raycast 拾取对我来说不是一个合适的选择,因为有很多对象并且在其中添加渲染会杀死 fps。(55k 个对象);

以下是加载gltf后的代码:

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++;

编辑:

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 PickGeom = THREE.BufferGeometryUtils.mergeBufferGeometries(geometriesPicking); PickGeom.rotateX(THREE.Math.degToRad(90)); PickingScene.add(new THREE.Mesh(pickingGeom, PickingMaterial));

然后在我的 MouseUp 函数中调用 pick(mouse*) 并传入 mouse* 信息:

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
}}

标签: javascriptthree.jsgpumouse-picking

解决方案


推荐阅读