ThreeJS:如何用汽车网格替换立方体网格?

ThreeJS: How to replace a cube mesh with a car mesh?

我开发了一个在一个轴上移动的 3D 立方体来模拟加速度计传感器。 目前,我有一个玩具车的 .obj 和 .mtl,我打算将其添加到场景中(),但是当我删除 BoxGeometry 3D 立方体并将其替换为汽车网格我一直遇到这些错误:

我也收到此错误,指出未定义 obj,即使我在全局范围内定义了它,我仍然遇到同样的问题:

我检查了本地存在的库和其他功能,但我看不出问题出在哪里。

以下是我加载汽车模型的方式:

const scene = new THREE.Scene();

    var loader = new THREE.OBJMTLLoader();
    loader.load('https://jyunming-chen.github.io/tutsplus/models/toycar.obj', 'https://jyunming-chen.github.io/tutsplus/models/toycar.mtl',
      function (vehicle) {
        toycar = vehicle;
        toycar.rotateY(-10.99);
        scene.add(toycar);
      });

这是我的完整 .HTML 代码和 js 实现:

这是 hoq 现在的样子:

这就是我的目标:

这是我当前的代码:

<html>

<head>
  <meta charset="UTF-8">
  <script src="./three.min.js"></script>
  <script src="./require.js" type="text/javascript"></script>
  <script src="./OrbitControls.js"></script>
    <script src="./KeyboardState.js"></script>
    <script src="./MTLLoader.js"></script>
    <script src="./OBJMTLLoader.js"></script>
  <script type="module"> import * as THREE from "./three.module.js"</script>
</head>

<body>
  <canvas id="canvas" width="1000" height="600" style="border:1px solid #000000;"></canvas>

</body>
<script>

  let sensorValue = 0;
  let sensorAddr = 0;
  var toycar;
  StartRetrieveLiveData();

  function main() {
    const canvas = document.querySelector('#canvas');
    const accelPanel = document.querySelector('#accelPanel');
    const renderer = new THREE.WebGLRenderer({  alpha: true, canvas });
    renderer.setClearColor( 0x626d73, 1 ); 
    var context = canvas.getContext("2d");
    var width = window.innerWidth;
    var height = window.innerHeight;

    const fov = 70;
    const aspect = 2;
    const near = 20;
    const far = 500;
    const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);

    camera.position.set(0, 50, 1.5);
    camera.up.set(0, 0, 1);
    camera.lookAt(0, 0, 0);

    const scene = new THREE.Scene();

    // var loader = new THREE.OBJMTLLoader();
    // loader.load('https://jyunming-chen.github.io/tutsplus/models/toycar.obj', 'https://jyunming-chen.github.io/tutsplus/models/toycar.mtl',
    //   function (vehicle) {
    //     toycar = vehicle;
    //     toycar.rotateY(-10.99);
    //     scene.add(toycar);
    //   });

    // An array of objects who's rotation to update
    const objects = [];
    const radius = 3;
    const widthSegments = 3;
    const heightSegments = 3;
    const sphereGeometry = new THREE.BoxGeometry(radius, widthSegments, heightSegments);
    const sunMaterial = new THREE.MeshBasicMaterial({ color: "green", wireframe: false });
    const object = new THREE.Mesh(sphereGeometry, sunMaterial);

    var cubeAxis = new THREE.AxesHelper(10);
    object.add(cubeAxis);

    object.scale.set(2, 2, 2);
    scene.add(object);
    objects.push(object);

    function resizeRendererToDisplaySize(renderer) {
      const canvas = renderer.domElement;
      const width = canvas.clientWidth;
      const height = canvas.clientHeight;
      const needResize = canvas.width !== width || canvas.height !== height;
      if (needResize) {
        renderer.setSize(width, height, false);
      }
      return needResize;
    }

    function render() {

      if (resizeRendererToDisplaySize(renderer)) {
        const canvas = renderer.domElement;
        camera.aspect = canvas.clientWidth / canvas.clientHeight;
        camera.updateProjectionMatrix();
      }
 
      objects.forEach((obj) => {
        sensorValueIndex = ((sensorValue / 16384) * 10);
        obj.position.z = ((sensorValue / 16384) * 20);
        console.log("AccX: ",sensorValueIndex);

        // // Here I take accelerometerX and pass them to the 3D model
        // if (sensorAddr === 1) {
          
        // }
        
      });

      renderer.render(scene, camera);
      
      requestAnimationFrame(render);
    }
    requestAnimationFrame(render);
  }

  function onMsg(event) {
    // console.log(`[message] Data received from server: ${event.data}`);
    // console.log("event.data = " + JSON.parse(event.data));

    var received_msg = event.data;
    var obj = JSON.parse(JSON.parse(received_msg));

    if (obj !== null) {

      if (
        obj.hasOwnProperty("DataMapChangedObjectsAddressValue") &&
        obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"] !==
        undefined
      ) {
        sensorAddr =
          obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"];
        sensorValue =
          obj["DataMapChangedObjectsAddressValue"][0]["Value"];

        // if (sensorAddr === 1) {
        //   sensorValueIndex = (sensorValue / 16384) * 500;
        // }
      }
    }
  }

  function onOpen(e) {
    console.log("SSE connected");
  }

  function onError(e) {
    // console.log(`[error] ${error.message}`);
    if (e.eventPhase == EventSource.CLOSED) this.source.close();
    if (e.target.readyState == EventSource.CLOSED) {
      console.log("SSE Disconnected");
    } else if (e.target.readyState == EventSource.CONNECTING) {
      console.log("SSE Connecting ...");
    }
  }

  function StartRetrieveLiveData() {
    if (!!window.EventSource) {
      this.source = new EventSource("/sse");
    } else {
      console.log("Your browser doesn't support SSE");
    }

    this.source.addEventListener("message", e => this.onMsg(e));

    this.source.addEventListener("open", e => this.onOpen(e), false);

    this.source.addEventListener("error", e => this.onError(e), false);

    // Add here (only mozilla)
    main();
    // Add here

  }

</script>

</html>

请注意,当我使用 public 服务器时,一切正常,但我使用远程服务器(实际服务器)时出现这些错误,并且整个事情没有按预期工作。

希望有解决方案。

我解决了这个问题,所以我要回答这个问题。

首先,应该删除 document.querySelector('#canvas') 以避免创建两个 canvas,因为我正在调用 .这是一个愚蠢的错误,但我终于找到了。

其次,摄像头位置偏了,并没有真正指向汽车,所以屏幕上什么也没有显示。我调整了 X、Y 和 Z 轴上的 camera.position 以使其正确。

我在仔细调试代码时发现了很多其他愚蠢的错误,我还不是这门语言的专家,所以这些错误对我来说是一种学习经验。

最终的工作代码如下:

  let sensorValue = 0;
  var toycar;
  StartRetrieveLiveData();
  var scene, renderer, camera;
  var controls, keyboard = new KeyboardState();
  var toycar;

  function init() {
    var width = window.innerWidth;
    var height = window.innerHeight;

    renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    renderer.setClearColor(0x626d73, 1);
    renderer.setSize(width, height);
    document.body.appendChild(renderer.domElement);

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(10, width / height, 1, 10000);
    camera.position.y = -150;
    camera.lookAt(new THREE.Vector3(0, 0, 0));

    var loader = new THREE.OBJMTLLoader();
    loader.load('./toycar.obj', './toycar.mtl',
      function (object) {
        toycar = object;
        toycar.rotateZ(10.99); //toycar.rotateZ(-10.99);
        scene.add(toycar);
      });

    var gridXZ = new THREE.GridHelper(350000, 10000);
    gridXZ.setColors(new THREE.Color(0xff0000), new THREE.Color(0xffffff));
    scene.add(gridXZ);

    var pointLight = new THREE.PointLight(0xffffff);
    pointLight.position.set(350, 20, 5);
    scene.add(pointLight);

    var ambientLight = new THREE.AmbientLight(0x111111);
    scene.add(ambientLight);
  }

  function animate() {
    var angle = 0;
    var speed = 0;
    var pos   = new THREE.Vector3(0, 0, 0);
    var clock = new THREE.Clock();
    var dt = clock.getDelta();
    var dir = new THREE.Vector3(1, 0, 0);
    dir.multiplyScalar(dt * speed);
    dir.applyAxisAngle(new THREE.Vector3(0, 0, 0), 10);
    pos.add(dir);

    if (toycar != undefined) {
      sensorValueIndex = ((sensorValue / 16384) * 50);
      toycar.scale.set(0.1, 0.1, 0.1);
      toycar.position.x = sensorValueIndex;
      toycar.position.y = 0;
      toycar.position.z = 0;
      toycar.rotation.x = (angle + Math.PI);
    }

    requestAnimationFrame(animate);
    renderer.render(scene, camera);
  }

  function onMsg(event) {    
    var received_msg = event.data;
    var obj = JSON.parse(JSON.parse(received_msg));

    if (obj !== null) {

      if (
        obj.hasOwnProperty("DataMapChangedObjectsAddressValue") &&
        obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"] !==
        undefined
      ) {
        let sensorAddr =
          obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"];
        sensorValue =
          obj["DataMapChangedObjectsAddressValue"][0]["Value"];

        if (sensorAddr === 1) {
          sensorValueIndex = (sensorValue / 16384) * 10;
          console.log(sensorValueIndex);
        }
      }
    }
  }