Threebox 和 Mapbox:为啥同一 GLTF 模型的连续实例上的纹理和形状会消失?

Posted

技术标签:

【中文标题】Threebox 和 Mapbox:为啥同一 GLTF 模型的连续实例上的纹理和形状会消失?【英文标题】:Threebox and Mapbox: Why are textures and shapes disappearing on consecutive instances of the same GLTF model?Threebox 和 Mapbox:为什么同一 GLTF 模型的连续实例上的纹理和形状会消失? 【发布时间】:2021-07-31 10:14:58 【问题描述】:

我正在使用 Mapbox-gl (2.2.0) 和出色的 Threebox (2.2.3) 插件将同一 GLTF 模型的多个实例添加到场景中。

第一个模型正确渲染,第二个模型存在于场景中,但丢失了纹理和/或形状。

可以加载不同的模型并且它们不会相互冲突,但是当每个模型的第二个和连续实例丢失纹理和/或形状时会发生相同的行为。

Two different (but similar) models, loaded twice. The first instance of each model renders correctly, the second instance does not

Mapbox 2.0 之前的版本这工作正常,所以我认为这要么是错误,要么是我误解的功能。如果能在最新版本中使用 3D 地形,那就太好了。

下面是相关的代码,直接剥离:

    let map = new mapboxgl.Map(
        style: "mapbox://styles/mapbox/satellite-v9?optimize=true",
        center: [7.059806068014609, 46.058219779837316],
        zoom: 9.848554211380023,
        pitch: 85,
        bearing: -154.1,
        container: 'map',
        antialias: true, 
        hash: true
    );

    map.on('style.load', function () 

        map.addLayer(
            id: '3D-overlay',
            type: 'custom',
            renderingMode: '3d',
            onAdd: function (map, mbxContext) 

                window.tb = new Threebox(
                    map,
                    map.getCanvas().getContext('webgl'),);

            ,

            render: function (gl, matrix) 
                tb.update();
            
        );

        addBike(1);
        addBike(2);

    );

    function addBike(num)

        var options = 
            obj: "./gltf/cyclist/scene.gltf",
            type: 'gltf',
            scale: 10,
            units: 'meters',
            rotation: x: 90, y:177, z:0,
            anchor: 'auto'
        

        tb.loadObj(options, function (model) 

            tb.add(model);

            model.setCoords([6.927566+(num/10), 45.984111 + (num/10), 4000]);

            model.traverse(function (object) 
                object.frustumCulled = false;
            );

            model.playAnimation( animation: 0, duration: 1000000000 );

            model.selected = true;

        )

    

这是一个包含文件的 github 存储库:

https://github.com/nickshreck/threebox-mapbox-gltf-issue.git

运行npm i,将一个mapbox令牌放入main.js,然后npm run dev

非常感谢

【问题讨论】:

只是检查模型,看起来是对的,所以问题可能与克隆模型(包括纹理)性能的重大改进有关。我正在认真考虑向tb.addModel 添加一个允许不克隆模型的选项。 这是一个可怕的 hack,但只需以不同的名称重新加载相同的对象即可达到预期的最终结果。 嗯...我忘了!不是那么糟糕,因为它保持了最好的性能变化(纹理克隆)而不影响动画......顺便说一句,我应该保留加载对象而不克隆的选项,在那一刻我正在努力解决严重的内存问题和我默认进行了克隆,但打开了一个任务以添加选项以避免克隆并始终完全加载。 感谢您帮助确认问题并确定可能的原因。 Threebox 令人难以置信,它为 Mapbox 开辟了一个充满可能性的世界,尤其是现在他们已经在环境中实现了 3D。我将密切关注您的更新,并再次感谢您对更大社区的帮助。谢谢你的新任务,那太好了。 不,谢谢你的报告,我什么都没做……你成功了! :-) 【参考方案1】:

感谢您以如此详细和清晰的方式报告如此棘手的问题。它帮助我发现了 Threebox 代码中的一个问题。 This issue has been resolved 向tb.loadObj 添加一个新属性,该属性现在接受clone: false。它已经在代码仓库中可用,并且很快将作为 npm 模块 v2.2.4 发布。同时你可以使用the bundle file from github。

你的函数addBike现在看起来像这样:

    function addBike(num)

        var options = 
            obj: "./gltf/cyclist/scene.gltf",
            type: 'gltf',
            scale: 10,
            units: 'meters',
            rotation: x: 90, y:177, z:0,
            anchor: 'auto',
            clone: false //objects won't be cloned
        

        tb.loadObj(options, function (model) 

            tb.add(model);

            model.setCoords([6.927566+(num/10), 45.984111 + (num/10), 4000]);

            model.traverse(function (object) 
                object.frustumCulled = false;
            );

            model.playAnimation( animation: 0, duration: 1000000000 );

            model.selected = true;

        )

    

我还建议您在 addLayer 方法之外而不是在内部声明 tb 对象。这将触发一些与真实阳光和地形图层相关的自动行为,并移除重复的灯光。

        window.tb = new Threebox(
            map,
            map.getCanvas().getContext('webgl'),
            
                realSunlight: true,
                sky: true,
                terrain: true,
                enableSelectingObjects: true,
                enableTooltips: true
            
        );

        map.on('style.load', function () 

            map.addLayer(
                id: '3D-overlay',
                type: 'custom',
                renderingMode: '3d',
                onAdd: function (map, mbxContext) 

                    addBike(3);
                    addBike(4);

                ,

                render: function (gl, matrix) 
                    tb.update();
                
            );


        );

再次感谢!

【讨论】:

顺便说一句,我在您的代码中看到了这样的导入...import Threebox from 'threebox-plugin/src/Threebox.js',老实说,我不明白它是如何工作的!我建议你像这样导入import Threebox from 'threebox-plugin'; 这很漂亮,谢谢。我已经从回购中撤出,一切都按预期工作。在过去的一年里,我完全依靠 Threebox 帮助我解决了一些难题,所以我很高兴听到我得到了一些帮助作为回报。还感谢您提供有关在外部声明 tb 对象的提示,我已采纳您的建议。还有关于进口建议! 如果您有任何问题,请随时在 repo 或此处打开问题。我会尽快提供帮助或提供解决方法 你是一个绝对的传奇。我现在正在疯狂地建造并试图找出她真正的能力,所以当我找到对你感兴趣的东西时,我会这样做!再次感谢您,请尽快发言。

以上是关于Threebox 和 Mapbox:为啥同一 GLTF 模型的连续实例上的纹理和形状会消失?的主要内容,如果未能解决你的问题,请参考以下文章

mapbox+three做3D可视化

mapbox-gl:从中心点、缩放级别和尺寸计算地图边界

如何将 Mapbox Mapmatching API 输出与 mapbox-gl-js 一起使用?

用 jsodom 和 jest 测试 react-mapbox-gl

在 Mapbox-GL-JS 中 minzoom 和 maxzoom 到底做了啥?

我可以使用传单插件和mapbox gl js吗?