用Raycaster设置位置后,THREE.js更新对象矩阵

时间:2019-02-05 13:39:09

标签: javascript three.js

我在three.js场景中遇到FPS相机控件的问题。我正在使用Raycaster来确定摄影机组的位置,基于它与沿Y轴的场景相交(如果您愿意,则为穷人的重力),然后应用用户输入来移动。摄像头组的位置会不断重置为每帧的相交位置,从本质上将您粘在该点上。

我假设这是一个updateMatrix()问题,或者是某个地方Vector3通过引用传递,但是对于我一生,我似乎无法全力以赴。我需要一些帮助...我希望这段代码很清楚,可以帮助您理解问题:

renderer.setAnimationLoop((event) => {

    if (clock.running) {

        update();

        renderer.render(scene,character.view);

    }

});

clock.start();


// 


const update = () => {


   // velocity


   const velocity = new THREE.Vector3();

   velocity.x = input.controller.direction.x;
   velocity.z = input.controller.direction.y;

   velocity.clampLength(0,1);

   if (velocity.z < 0) {

      velocity.z *= 1.4;

   }


   // gravity


   if (scene.gravity.length() > 0) {

      const origin = new THREE.Vector3().copy(character.view.position);
      const direction = new THREE.Vector3().copy(scene.gravity).normalize();

      const intersection = new THREE.Raycaster(origin,direction).intersectObjects(scene.collision).shift();

      if (intersection) {

         character.group.position.copy(intersection.point);

         character.group.updateMatrix();

      }

   }


   // rotation


   const rotation = new THREE.Euler();

   rotation.x = input.controller.rotation.y;
   rotation.y = input.controller.rotation.x;

   character.group.rotation.set(0,rotation.y,0);
   character.view.rotation.set(rotation.x,0,0);


   // velocity.applyEuler(rotation);


   const quaternion = new THREE.Quaternion();

   character.group.getWorldQuaternion(quaternion);

   velocity.applyQuaternion(quaternion);


   // collision


   const origin = new THREE.Vector3().setFromMatrixPosition(character.view.matrixWorld);
   const direction = new THREE.Vector3().copy(velocity).normalize();

   const raycaster = new THREE.Raycaster(origin,direction);

   for (const intersection of raycaster.intersectObjects(scene.collision)) {

      if (intersection.distance < 0.5) {


         // face normals ignore object quaternions


         const normal = new THREE.Vector3().copy(intersection.face.normal);
         const matrix = new THREE.Matrix4().extractRotation(intersection.object.matrixWorld);

         normal.applyMatrix4(matrix);


         // normal


         normal.multiplyScalar(velocity.clone().dot(normal));

         velocity.sub(normal);

      }

   }


   // step


   const delta = 0.001 / clock.getDelta();

   velocity.multiplyScalar(delta);


   // apply


   character.group.position.add(velocity);

}

摄像机的设置与PointerLockControls帮助器非常相似,该摄像机是用于偏航和俯仰的“组对象”的子级。控制器输入是在其他地方定义的,因为它可以来自鼠标或游戏手柄,但是它返回归一化的值。

更准确地说,引起问题的部分在这里:

   // gravity


   if (scene.gravity.length() > 0) {

      const origin = new THREE.Vector3().copy(character.view.position);
      const direction = new THREE.Vector3().copy(scene.gravity).normalize();

      const intersection = new THREE.Raycaster(origin,direction).intersectObjects(scene.collision).shift();

      if (intersection) {

         character.group.position.copy(intersection.point);

         character.group.updateMatrix();

      }

   }

例如,如果我注释掉character.group.position.copy(intersection.point);,则相机会像预期的那样移动(当然,它正在飞行),但是否则它将移动一帧的距离,然后重置为下一个帧。

我尝试了所有方式的updateMatrix(),updateMatrixWorld(),updateProjectionMatrix()和Object.matrixWorldNeedsUpdate = true,但遗憾的是。

我很抱歉使用代码的复制/粘贴而不是使用可测试的案例。谢谢您的宝贵时间。

1 个答案:

答案 0 :(得分:0)

圣牛,我觉得很蠢... const origin = new THREE.Vector3().copy(character.view.position);返回本地空间坐标,当然它会重置为原点!

const origin = new THREE.Vector3().setFromMatrixPosition(character.view.matrixWorld);替换它会给我正确的结果

那里有一堂课,关于呆呆地凝视代码太久了。我希望至少这个问题有一天能对某个人有所帮助。