如何在 ThreeJS 中围绕其中心旋转一个组?

How to rotate a group in ThreeJS around its center?

我正在尝试使用 ThreeJS 构建一个有效的 Rubikscube。现在我在 旋转侧面时遇到问题。 目前,我正在将 较小的立方体 添加到 Rubikscube 并像这样创建它:

const rubikscube = new THREE.Group();
for (var i = 0; i < 27; i++) {
  // 3x3x3 (0,0,0) is on the top left corner
  var cube = createPartOfCube(i, scene);
  cube.name = i;
  cube.position.x = (i % 3) * gap;
  cube.position.y = Math.floor(i / 9) * gap;
  cube.position.z = (Math.floor(i / 3) % 3) * gap;
  rubikscube.add(cube);
}
scene.add(rubikscube);

这一切 工作正常 直到我尝试 旋转 ,例如 侧。我 select 右侧的棋子并将它们添加到 自己的组 中。现在,当我尝试旋转组时,it's rotating around the x axes。这是我想用来移动一侧的方法(忽略 bool 和 eval 部分,它只是为了获得正确的部分):

  function move(direction) {
    var bool = moves[direction];

    var pivot = new THREE.Group();
    pivot.updateMatrixWorld();

    for (var i = 0; i < 27; i++) {
      if (eval(format(bool, i))) {
        pivot.add(scene.getObjectByName(i));
      }
    }
    scene.add(pivot);
    animateMove(pivot);
  }

并为其制作动画:

  function animateMove(pivot) {
    requestAnimationFrame(() => {
      animateMove(pivot);
    });
    // missing part
    renderer.render(scene, camera);
  }

我尝试过的:

我尝试了不同的方法,以正确的方式旋转它,但没有任何效果,移动立方体也不是正确的答案。

我试过的一件事是 ,但是当我尝试以这种方式旋转它时,侧面只是 移动了 ,所以它仍然是 绕 x 轴旋转.

最小可重现示例

function main() {
  const scene = new THREE.Scene();
  const renderer = new THREE.WebGLRenderer();
  const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  const gap = 1.1;

  scene.add(new THREE.AxesHelper(100));
  scene.background = new THREE.Color('white');

  camera.position.z = 5;

  renderer.setSize(window.innerWidth, window.innerHeight);

  const rubikscube = new THREE.Group();
  for (var i = 0; i < 27; i++) {
    // 3x3x3 (0,0,0) is on the top left corner
    var cube = createPartOfCube(i, scene);
    cube.name = i;
    cube.position.x = (i % 3) * gap;
    cube.position.y = Math.floor(i / 9) * gap;
    cube.position.z = (Math.floor(i / 3) % 3) * gap;
    rubikscube.add(cube);
  }

  scene.add(rubikscube);
  animate();
}

function animate() {
  requestAnimationFrame(animate);
  const controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.target.set(1, 1, 1);
  controls.update();

  var movingIds = [2, 5, 8, 11, 14, 17, 20, 23, 26]; // IDs of the pieces needed to rotate
  var group = new THREE.Group();
  movingIds.forEach((i) => {
    group.add(scene.getObjectByName(i));
  });

  scene.add(group);
  animateMove(group);
}

function animateMove(group) {
  requestAnimationFrame(() => {
    animateMove(group);
  });
  group.rotation.x = 2; // Wrong part I need help with
  renderer.render(scene, camera);
}

function createPartOfCube() {
  var geometry = new THREE.BoxGeometry(1, 1, 1);
  var material = new THREE.MeshBasicMaterial({ color: 'black' });
  var cube = new THREE.Mesh(geometry, material);
  return cube;
}
main();

我希望有人理解我的问题并帮助我解决它。谢谢!

所有旋转都围绕对象的原点进行。因此,如果您的对象的位置是 (0, 0, 0),那么这将是枢轴点。

我建议您将每个立方体块嵌套到一个 THREE.Group() 中,这样您就可以将所有 27 个块的轴心点保持在 (0, 0, 0)。然后你可以将其组内的每个棋子移动到所需的位置:

const geom = new THREE.BoxGeometry(1, 1, 1);
const Piece = new THREE.Mesh(geom, mat);
const Group = new THREE.Group();

// Nest Piece inside of its Group
Group.add(Piece);

// Parent Group position is at (0, 0, 0)
// Inner piece position is at (-1, -1, -1)
Piece.position.set(-1, -1, -1);

// Now we can apply rotations to the parent group 
// and the child will maintain its distance from the center
Group.rotation.set(Math.PI / 2, 0, 0);

您需要为 X,Y,Z[-1, 0, +1] 的所有值重复此操作。那是 3^3 = 27 件。