在 React 中通过 Three.js 加载 gltf 文件时出现语法错误

SyntaxError when loading a gltf-file via Three.js in React

我正在尝试将 3D 模型实施到网站中。当我用网站上的 3D 模型尝试它时,一切正常,但是当我用我自己的模型尝试它时,我得到这个控制台错误: SyntaxError: "JSON.parse: unexpected character at line 1 column 1 of the JSON data"

我在 React 中编程并使用 three.js 将模型实现为 gltf 文件。

import ReactDOM from "react-dom";
import * as THREE from "three";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

class App extends Component {
    componentDidMount() {
        var scene = new THREE.Scene();

        var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

        //Camera fixieren
        camera.position.set(0,12,20);

        var renderer = new THREE.WebGLRenderer();
        renderer.setClearColor("#e5e5e5");
        renderer.setSize(window.innerWidth, window.innerHeight);

        //automatische Fensteranpassung
        window.addEventListener('resize', () => {
            renderer.setSize( window.innerWidth, window.innerHeight );
            camera.aspect = window.innerWidth / window.innerHeight;

            camera.updateProjectionMatrix();
        })
        document.body.appendChild( renderer.domElement );
        // use ref as a mount point of the Three.js scene instead of the document.body
        this.mount.appendChild( renderer.domElement );



        var light = new THREE.AmbientLight(0xffffff);
        scene.add(light);

        var hlight = new THREE.PointLight(0xffffff, 1, 100);
        light.position.set(50,50,50);
        scene.add(hlight);

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


        function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
            const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
            const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
            const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
            // compute a unit vector that points in the direction the camera is now
            // in the xz plane from the center of the box
            const direction = (new THREE.Vector3())
                .subVectors(camera.position, boxCenter)
                .multiply(new THREE.Vector3(1, 0, 1))
                .normalize();

            // move the camera to a position distance units way from the center
            // in whatever direction the camera was from the center already
            camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));

            // pick some near and far values for the frustum that
            // will contain the box.
            camera.near = boxSize / 100;
            camera.far = boxSize * 100;

            camera.updateProjectionMatrix();

            // point the camera to look at the center of the box
            camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
        }


        //GLTFLoader
        const gltfLoader = new GLTFLoader();
        gltfLoader.load('prototype/public/test.gltf', (gltf) => {
            const root = gltf.scene;
            scene.add(root);

            // compute the box that contains all the stuff
            // from root and below
            const box = new THREE.Box3().setFromObject(root);

            const boxSize = box.getSize(new THREE.Vector3()).length();
            const boxCenter = box.getCenter(new THREE.Vector3());

            // set the camera to frame the box
            frameArea(boxSize * 0.5, boxSize, boxCenter, camera);

            // update the Trackball controls to handle the new size
            controls.maxDistance = boxSize * 10;
            controls.target.copy(boxCenter);
            controls.update();
        });





        //Objektloader der net funzt -- leere Seite wird angezeigt
        /*
        loader.load('public/test.obj', function ( obj ){

            var box = new THREE.Box3().setFromObject(obj);
            var center = new THREE.Vector3();
            box.getCenter(center);
            obj.position.sub(center);

            scene.add(obj);
        })*/


        //Objektloader der net funzt -- leere Seite wird angezeigt
        /*var mtlLoader = new MTLLoader();
        mtlLoader.load("/public/TechnicLEGO_CAR_1.mtl", function(materials){

            materials.preload();

            var objLoader = new OBJLoader();
            objLoader.setMaterials(materials);

            objLoader.load("/public/TechnicLEGO_CAR_1.obj", function(mesh){
                const ab = new THREE.Box3().setFromObject(mesh);
                const center = ab.getCenter( new THREE.Vector3());

                mesh.position.x += (mesh.position.x - center.x);
                mesh.position.y += (mesh.position.y - center.y);
                mesh.position.z += (mesh.position.z - center.z);

                scene.add(mesh);


            });
        });*/


        //Würfel
        /*
        var geometry = new THREE.BoxGeometry( 1, 1, 1 );
        //var material = new THREE.MeshBasicMaterial( { color: 0xff00ff } );
        var material = new THREE.MeshNormalMaterial();
        var cube = new THREE.Mesh( geometry, material );
        scene.add( cube );*/


        var animate = function () {
            requestAnimationFrame( animate );
            //cube.rotation.x += 0.01;
            //cube.rotation.y += 0.01;
            renderer.render( scene, camera );
        };
        animate();
    }


    //muss so bleiben, da rendern sonst nix wird
    render() {
        return (
            <div ref={ref => (this.mount = ref)} />
        )
    }
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

这是我要加载的 gltf:https://drive.google.com/drive/folders/1mZhyYRBmN8FVac9d3c2T1dN1TpUXPM5Q?usp=sharing

如您所见,我也尝试过使用 .obj-Files,但这也行不通。

希望smb能帮帮我:)

您的文件在 three.js editor 中加载得很好。所以这个问题很可能不是 GLTFLoader 的问题,而是您的网络服务器的问题。错误信息

JSON.parse: unexpected character at line 1 column 1 of the JSON data

通常在 glTF 清单文件未作为 JSON 时弹出。我建议您在从后端请求 glTF 资产时使用浏览器的开发人员工具来确保正确的 HTTP 响应。

我遇到了类似的问题,看起来 parcel 没有将静态文件复制到 dist 文件夹。你可以安装 parcel-plugin-static-files-copy and declare static files as guided in README of that package in this link parcel-plugin-static-files-copy。然后文件将加载成功