从加载GLTF中提取全局顶点位置的问题

从 gltf 文件中提取顶点和面索引,这样我就能把它们作为碰撞网格输入物理引擎。大多数 gltf 文件都能正常工作,但有些文件就不行了。调试时我重建了一个新的网格,这样问题就显现出来了。

以下是要重现的代码:

复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Debug Mesh Reconstruction</title>
    <script type="importmap">
{
  "imports": {
    "three": "https://cdn.jsdelivr.net/npm/three@v0.183.0/build/three.module.js",
    "three/addons/": "https://cdn.jsdelivr.net/npm/three@v0.183.0/examples/jsm/"
  }
}
</script>
</head>

<body style="margin:0; overflow:hidden;">
    <script type="module">
        import * as THREE from 'three';
        import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
        import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

        const scene = new THREE.Scene();

        const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.1, 1000);
        camera.position.set(2, 2, 2);

        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(innerWidth, innerHeight);
        document.body.appendChild(renderer.domElement);

        const controls = new OrbitControls(camera, renderer.domElement);

        const loader = new GLTFLoader();
        loader.load('Menger Sponge.glb', gltf => {
            const original = gltf.scene;
            scene.add(original);

            const originalData = [];

            original.updateWorldMatrix(true, true);
            original.traverse(child => {
                if (!child.isMesh) return;

                child.material = new THREE.MeshNormalMaterial()

                const geom = child.geometry;
                const posAttr = geom.attributes.position;
                const indexAttr = geom.index;

                const worldMatrix = child.matrixWorld;
                const v = new THREE.Vector3();

                const vertices = new Float32Array(posAttr.count * 3);
                for (let i = 0; i < posAttr.count; i++) {
                    v.fromBufferAttribute(posAttr, i).applyMatrix4(worldMatrix);
                    vertices[i * 3 + 0] = v.x;
                    vertices[i * 3 + 1] = v.y;
                    vertices[i * 3 + 2] = v.z;
                }
                const faces = new Uint16Array(indexAttr.array);

                originalData.push({ vertices, faces });
            });

            const reconstructed = new THREE.Group();
            for (const data of originalData) {
                const geometry = new THREE.BufferGeometry();
                geometry.setAttribute('position', new THREE.BufferAttribute(data.vertices, 3));
                geometry.setIndex(new THREE.BufferAttribute(data.faces, 1));
                geometry.computeVertexNormals();

                const mesh = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial());
                reconstructed.add(mesh);
            }
            scene.add(reconstructed);
            reconstructed.position.x = 3
        });

        function animate() {
            requestAnimationFrame(animate);
            controls.update();
            renderer.render(scene, camera);
        }
        animate();
    </script>
</body>

</html>

具体情况如下:

左边是原件,右边是重建版。

相关推荐
AI视觉网奇1 天前
latex公式渲染
arcgis
进击的雷神3 天前
蓝湖 MCP 快速上手手册(Claude + Codex)
arcgis·skill·蓝湖·mcp
非科班Java出身GISer3 天前
ArcGIS JS 基础教程(4):地图中心点定位(指定经纬度/地址)
arcgis·arcgis js定位·arcgis js地址定位·arcgis js参数定位·arcgis js复合定位
GIS地信小匠4 天前
(32)ArcGIS Pro WGS84坐标系:投影选择逻辑与实操设置
arcgis·空间分析·数据处理·gis教程·arcgls pro
玩大数据的龙威5 天前
农经权二轮延包—付费软件插件与免费软件插件汇总
python·arcgis
墨黎芜5 天前
ArcGIS从入门到精通——地图符号、注记的初步使用
学习·arcgis·信息可视化
GIS地信小匠6 天前
(31)ArcGIS Pro 定义投影与批量投影:矢量数据坐标转换工具实操
arcgis·空间分析·数据处理·gis教程·arcgls pro
非科班Java出身GISer7 天前
ArcGIS JS 基础教程(3):地图缩放、平移、旋转(基础交互)
arcgis·arcgis js地图交互·arcgis js缩放·arcgis js平移·arcgis js旋转·arcgis js基础交互
城数派7 天前
2025年我国省市县三级的平均坡度数据(Excel\Shp格式)
arcgis·信息可视化·数据分析·excel
装疯迷窍_A8 天前
以举证方位线生成工具为例,分享如何在Arcgis中创建Python工具箱(含源码)
开发语言·python·arcgis·变更调查·举证照片