从组中移除并单独添加到场景后,组子位置不保存

Group children position is not saved after removing from group and adding to scene individually

我正在尝试用 three.js 制作一个 rubiks 立方体模拟器,所以我现在的目标是旋转底部,然后旋转中间层。 我旋转底层切换到中间层后,底层又回到原位(旋转后的位置不保存),中间层瞬间断裂

这是我的代码:

import * as THREE from 'three'
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls';


const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

const renderer = new THREE.WebGLRenderer({canvas: document.querySelector("canvas.webgl")});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

const geometry = new THREE.BoxGeometry(1, 1, 1);
const materials = [
    new THREE.MeshBasicMaterial({color: 'white'}),
    new THREE.MeshBasicMaterial({color: 'yellow'}),
    new THREE.MeshBasicMaterial({color: 'red'}),
    new THREE.MeshBasicMaterial({color: 'darkorange'}),
    new THREE.MeshBasicMaterial({color: 'blue'}),
    new THREE.MeshBasicMaterial({color: 'green'}),
];
for(let i = 0; i < geometry.groups.length; i++)
    geometry.groups[i].materialIndex = i;

const cube = [];

for(let y = -1; y <= 1; y++){
    for(let x = -1; x <= 1; x++){
        for(let z = -1; z <= 1; z++){
            const mesh = new THREE.Mesh(geometry, materials);
            mesh.position.x = x;
            mesh.position.y = y;
            mesh.position.z = z;
            cube.push(mesh);
            scene.add(mesh);
        }
    }
}

const controls = new TrackballControls( camera, renderer.domElement );
controls.noPan = true;
controls.noZoom = true;
controls.rotateSpeed = 3;

camera.position.z = 7.5;
controls.update();

const face = new THREE.Group();
// get the bottom layer
for(let i = 0; i < 9; i++){
    scene.remove(cube[i]);
    face.add(cube[i]);
}

scene.add(face);
let moveCount = 0;
function animate() {
    requestAnimationFrame( animate );
    
    controls.update();

    if(moveCount < 1){
        if(face.rotation.y < THREE.MathUtils.degToRad(90)){
            face.rotation.y += THREE.MathUtils.degToRad(2);
        }
        else{
            changeFace();
            moveCount++;
        }
    }

    renderer.render( scene, camera );
}
function changeFace() {
    scene.add(...face.children);
    face.remove(...face.children);
    
    for(let i = 9; i < 18; i++){
        scene.remove(cube[i]);
        face.add(cube[i]);
    }
};

animate();

一张gif来说明:

当您旋转网格的 parent 时,网格的旋转不会改变。只有 parent 的旋转变化。因此,当您从 parent 中取出网格时,您将删除它继承的任何变换。

您可以使用 object.getWorldQuaternion() 将 world-space 旋转存储到四元数中,然后将它们应用于 child 网格:

let tempQuaternion = new THREE.Quaternion();

for(let i = 9; i < 18; i++){
    // Read world rotations before removal
    cube[i].getWorldQuaternion(tempQuaternion);

    // Take the cube out of the group, place directly onto scene
    scene.add(cube[i]);

    // Now we re-apply the world rotations to the cube
    cube[i].quaternion.copy(tempQuaternion);
}

请记住,一个网格一次只能有一个 parent。所以添加到组时,不需要将其从场景中移除,vice-versa.

// This line adds all children to scene, 
// and automatically removes each one from face when doing so
scene.add(...face.children);

// This line doesn't do anything because all children have already been removed
face.remove(...face.children);