在特定枢轴点旋转 [英] Rotate at specific pivot point

查看:21
本文介绍了在特定枢轴点旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试转动耳机组的一部分.它能够在我的模型中(在 Maya 中)这样做.但我似乎无法在 Threejs 中弄清楚.

I'm trying to pivot a piece of a headphone set. It's capable of doing such in my model (in Maya).. but I can't seem to figure it out in threejs.

我知道我可以通过执行以下操作来旋转对象 X Y 和 Z:

I know I can rotate my objects X Y and Z by doing something like this:

object.rotateX(THREE.Math.degToRad(degreeX));
object.rotateY(THREE.Math.degToRad(degreeY));
object.rotateZ(THREE.Math.degToRad(degreeZ));

但是如何在其余部分旋转/移动时保持枢轴点固定?所以在我的例子中,我希望耳机能够根据你在我的图片中看到的黑色螺丝左右移动.

But how do I keep the pivot point stationary while the rests rotates/moves? So in my example, I'd want the ear piece to be able to move left and right based off of the black-ish screw you see in my picture.

推荐答案

将您的模型作为另一个 THREE.Object3D 的父级,但为了便于使用 SceneUtils.attach 函数.

Parent your model to another THREE.Object3D but to make it easy use the SceneUtils.attach function.

示例:

单击然后拖动,每次单击枢轴对象都会移动到该位置,然后模型(立方体)将通过调用THREE.SceneUtils.attach(model,scene, pivot).当您松开鼠标时,使用 THREE.SceneUtils.detach(model, pivot, scene) 分离模型.

Click then drag, each time you click the pivot object will be moved to that location and then the model (the cube) will be attached to the pivot by calling THREE.SceneUtils.attach(model, scene, pivot). When you let off the mouse the model is detached using THREE.SceneUtils.detach(model, pivot, scene).

'use strict';

/* global THREE */

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

  const fov = 45;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 100;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  // make the camera look down
  camera.position.set(0, 10, 0);
  camera.up.set(0, 0, -1);
  camera.lookAt(0, 0, 0);
  
  const scene = new THREE.Scene();
  scene.background = new THREE.Color('black');

  scene.add(new THREE.GridHelper(40, 40));
     
  let model;
  {
    const cubeSize = 3;
    const cubeGeo = new THREE.BoxBufferGeometry(cubeSize, cubeSize, cubeSize);
    const cubeMat = new THREE.MeshBasicMaterial({color: 'red'});
    model = new THREE.Mesh(cubeGeo, cubeMat);
    model.position.set(.5, .5, .5);
    scene.add(model);
  }

  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();
    }
    
    renderer.render(scene, camera);
  }
  render();

  let rotate = false;
  const startPos = {x:0, y:0};
  const raycaster = new THREE.Raycaster();
  const pivot = new THREE.Object3D();  
  scene.add(pivot);
  pivot.add(new THREE.AxesHelper(.5));
  
  function setPivotPoint(e) {
    startPos.x = e.clientX;
    startPos.y = e.clientY;
    const normalizedPosition = {
      x: e.clientX / canvas.clientWidth  *  2 - 1,
      y: e.clientY / canvas.clientHeight * -2 + 1,
    };
    
    // this part is NOT important to the answer. The question
    // is how to rotate from some point. This code is picking
    // a point. Which point to pick was not part of the question
    // but to demo the solution it's important to pick a point
    
    // put the pivot where the mouse was clicked
    raycaster.setFromCamera(normalizedPosition, camera);
     
    const intersection = raycaster.intersectObjects(scene.children)[0];
    if (intersection) {
      if (rotate) {
        removeFromPivot();
      }
      pivot.position.copy(intersection.point);
      pivot.rotation.set(0,0,0);
      pivot.updateMatrixWorld();
      rotate = true;
      
      // this the important part. We're making the cube
      // a child of 'pivot' without it moving in world space
      THREE.SceneUtils.attach(model, scene, pivot);
      render();
    }
  }
  
  function rotatePivot(e) {
    e.preventDefault();
    if (rotate) {
      const dx = e.clientX - startPos.x;
      const dy = e.clientY - startPos.y;
      const maxDelta = Math.abs(dx) > Math.abs(dy) ? dx : dy;
      pivot.rotation.y = maxDelta * 0.01;
      render();
    }
  }
  
  function removeFromPivot() {
    if (rotate) {
      rotate = false;
      THREE.SceneUtils.detach(model, pivot, scene);
      window.removeEventListener('mousemove', rotatePivot);
      window.removeEventListener('mouseup', removeFromPivot);
    }
  }
  
  canvas.addEventListener('mousedown', (e) => {
    e.preventDefault();
    setPivotPoint(e);
    if (rotate) {
      window.addEventListener('mousemove', rotatePivot);
      window.addEventListener('mouseup', removeFromPivot);
    }
  });
}

main();

html, body {
  margin: 0;
  height: 100%;
}
#c {
  width: 100%;
  height: 100%;
  display: block;
}

<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r98/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r98/js/utils/SceneUtils.js"></script>

这篇关于在特定枢轴点旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆