使对象3d查找其他矢量,但冻结Three.js中的z轴

时间:2019-06-30 15:18:20

标签: javascript three.js

如何使用object1.lookat(object2)函数但冻结z旋转?在Three.js中

我在字段i中有一些对象,我希望它们始终面对一个新对象2。该对象2可以自由移动。但是,对象1的z旋转必须始终保持相同。 lookat()的问题在于每个轴都会旋转。还有另一种方法吗?

1 个答案:

答案 0 :(得分:0)

您的意思是不要在X中旋转吗? lookAt已经不在Z轴上旋转

// Three.js - Responsive
// from https://threejsfundamentals.org/threejs/threejs-responsive.html

  'use strict';

/* global THREE */

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});

  const fov = 75;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 250;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.set(20, 10, 20);

  const controls = new THREE.OrbitControls(camera, canvas);
  controls.target.set(0, 0, 0);
  controls.update();
  
  const scene = new THREE.Scene();
  scene.background = new THREE.Color('white');

  function addLight(...pos) {
    const color = 0xFFFFFF;
    const intensity = 1;
    const light = new THREE.DirectionalLight(color, intensity);
    light.position.set(...pos);
    scene.add(light);
  }
  addLight(-1, 2, 4);
  addLight( 1, 2, 2);

  
  const shape = new THREE.Shape();
  shape.moveTo(-1, -1);
  shape.lineTo( 0, -1);
  shape.lineTo( 0, -2);
  shape.lineTo( 2,  0);
  shape.lineTo( 0,  2);
  shape.lineTo( 0,  1);
  shape.lineTo(-1,  1);
  const extrudeSettings = {
    depth: 1,
    bevelEnabled: false,
  };
  const geometry = new THREE.ExtrudeBufferGeometry(shape, extrudeSettings);
  geometry.applyMatrix(new THREE.Matrix4().makeRotationY(Math.PI * -0.5));

  const arrows = [];
  const spread = 5;
  for (let z = -3; z <= 3 ; ++z) {
    for (let x = -3; x <= 3; ++x) {
      const material = new THREE.MeshPhongMaterial({
        color: new THREE.Color().setHSL(Math.abs(Math.atan2(x, z)) / Math.PI, 1, 0.5),
      });
      const mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);
      arrows.push(mesh);
      mesh.position.set(x * spread, 0, z * spread);
    }
  }

  const geometry2 = new THREE.SphereBufferGeometry();
  const sphere = new THREE.Mesh(geometry2, new THREE.MeshPhongMaterial({color:'red'}));
  const base = new THREE.Object3D();
  scene.add(base)
  base.position.y = 10;
  const base2 = new THREE.Object3D();
  base.add(base2);
  base2.position.z = 15;
  const base3 = new THREE.Object3D();
  base2.add(base3);
  base3.position.z = 5;
  base3.add(sphere);
  sphere.position.y = 5;

  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(time) {
    time *= 0.001;

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }

    base.rotation.y = time;
    base2.rotation.y = time * 0.77;
    base3.rotation.z = time * 2.33;
    
    const temp = new THREE.Vector3();
    for (const arrow of arrows) {
      sphere.getWorldPosition(temp);
      arrow.lookAt(temp);
    }

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();
body { margin: 0; }
#c { width: 100vw; height: 100vh; display: block; }
<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/js/controls/OrbitControls.js"></script>

也许您是说不以X旋转?在这种情况下,获取目标在临时Vector3中的位置,然后设置Y,使其与您要瞄准的物体的y匹配,然后调用lookAt。

// Three.js - Responsive
// from https://threejsfundamentals.org/threejs/threejs-responsive.html

  'use strict';

/* global THREE */

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});

  const fov = 75;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 250;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.set(20, 10, 20);

  const controls = new THREE.OrbitControls(camera, canvas);
  controls.target.set(0, 0, 0);
  controls.update();
  
  const scene = new THREE.Scene();
  scene.background = new THREE.Color('white');

  function addLight(...pos) {
    const color = 0xFFFFFF;
    const intensity = 1;
    const light = new THREE.DirectionalLight(color, intensity);
    light.position.set(...pos);
    scene.add(light);
  }
  addLight(-1, 2, 4);
  addLight( 1, 2, 2);

  
  const shape = new THREE.Shape();
  shape.moveTo(-1, -1);
  shape.lineTo( 0, -1);
  shape.lineTo( 0, -2);
  shape.lineTo( 2,  0);
  shape.lineTo( 0,  2);
  shape.lineTo( 0,  1);
  shape.lineTo(-1,  1);
  const extrudeSettings = {
    depth: 1,
    bevelEnabled: false,
  };
  const geometry = new THREE.ExtrudeBufferGeometry(shape, extrudeSettings);
  geometry.applyMatrix(new THREE.Matrix4().makeRotationY(Math.PI * -0.5));

  const arrows = [];
  const spread = 5;
  for (let z = -3; z <= 3 ; ++z) {
    for (let x = -3; x <= 3; ++x) {
      const material = new THREE.MeshPhongMaterial({
        color: new THREE.Color().setHSL(Math.abs(Math.atan2(x, z)) / Math.PI, 1, 0.5),
      });
      const mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);
      arrows.push(mesh);
      mesh.position.set(x * spread, 0, z * spread);
    }
  }

  const geometry2 = new THREE.SphereBufferGeometry();
  const sphere = new THREE.Mesh(geometry2, new THREE.MeshPhongMaterial({color:'red'}));
  const base = new THREE.Object3D();
  scene.add(base)
  base.position.y = 10;
  const base2 = new THREE.Object3D();
  base.add(base2);
  base2.position.z = 15;
  const base3 = new THREE.Object3D();
  base2.add(base3);
  base3.position.z = 5;
  base3.add(sphere);
  sphere.position.y = 5;

  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(time) {
    time *= 0.001;

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }

    base.rotation.y = time;
    base2.rotation.y = time * 0.77;
    base3.rotation.z = time * 2.33;
    
    const temp = new THREE.Vector3();
    for (const arrow of arrows) {
      sphere.getWorldPosition(temp);
      temp.y = arrow.position.y
      arrow.lookAt(temp);
    }

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();
body { margin: 0; }
#c { width: 100vw; height: 100vh; display: block; }
<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/js/controls/OrbitControls.js"></script>