Using three.js, and adapting instructions from West Langley\'s post provided here: Three.js: Adding and Removing Children of Rotated Objects, I set up a WebGL scene to whic
This is an old post but the sake of search engines here are my thoughts about this
Looking at the code for THREE.SceneUtils.attach() it appears to me that the code assumes the object that you want to attach is parented to the scene object. This makes it problematic to work with when your objects are actually nested further down in the scene graph. To address this problem I wrote this function
function reparentObject3D(subject, newParent)
{
subject.matrix.copy(subject.matrixWorld);
subject.applyMatrix(new THREE.Matrix4().getInverse(newParent.matrixWorld));
newParent.add(subject);
}
This allows you to reparent an object from any level of the scene graph to any other level in the scene graph. This dispenses with the need to "Detach" objects. You just reparent them to the scene if thats what you need
your line of code
THREE.SceneUtils.detach(cubeMesh[i], scene, parentCube);
should be
THREE.SceneUtils.detach(cubeMesh[i], parentCube, scene);
I have done a demo with your example, and what I believe should be te correct approach.
HTML
<body>
<button onclick="attachChild();">attach</button>
<button onclick="detachChild();">dettach</button>
</body>
JavaScript
var camera, scene, renderer;
var geometry, material1, material2;
var parentCube;
var cubeMesh = [];
var cameraControls;
var attached = true;
window.onload = function() {
init();
animate();
}
function init() {
camera = new THREE.PerspectiveCamera(75, 2, 1, 10000);
camera.position.z = 400;
camera.position.y = 100;
scene = new THREE.Scene();
geometry = new THREE.BoxGeometry(200, 200, 200);
material1 = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true });
//Create parentCube mesh
parentCube = new THREE.Mesh(new THREE.CubeGeometry(100, 100, 100, 1, 1, 1), material1);
scene.add(parentCube);
//...create materials for the child cubes....
material2 = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
//create child cube mesh
cubeMesh[0] = new THREE.Mesh(new THREE.CubeGeometry(100, 100, 100, 1, 1, 1), material2);
cubeMesh[1] = new THREE.Mesh(new THREE.CubeGeometry(100, 100, 100, 1, 1, 1), material2);
cubeMesh[2] = new THREE.Mesh(new THREE.CubeGeometry(100, 100, 100, 1, 1, 1), material2);
cubeMesh[3] = new THREE.Mesh(new THREE.CubeGeometry(100, 100, 100, 1, 1, 1), material2);
//--> Set child cube world positions before the attachment to parentCube mesh
cubeMesh[0].position.set(100,100,0);
cubeMesh[1].position.set(-100,100,0);
cubeMesh[2].position.set(-100,-100,0);
cubeMesh[3].position.set(100,-100,0);
//Add child cubes to the scene
for (var i = 0; i < 4; i++)
parentCube.add(cubeMesh[i]);
//translate parentCube
parentCube.position.set(0,50,0);
renderer = new THREE.CanvasRenderer();
renderer.setSize(600, 300);
document.body.appendChild(renderer.domElement);
// CONTROLS
cameraControls = new THREE.OrbitControls(camera);
cameraControls.addEventListener( 'change', render );
}
function animate() {
cameraControls.update();
requestAnimationFrame(animate);
parentCube.rotation.z += 0.01;
render ();
}
function render () {
renderer.render(scene, camera);
}
function attachChild () {
if (attached) {
alert ("already attached");
} else {
for (var i = 0; i < 4; i++)
THREE.SceneUtils.attach(cubeMesh[i], scene, parentCube);
attached = true;
}
}
function detachChild () {
if ( ! attached) {
alert ("not attached");
} else {
for (var i = 0; i < 4; i++)
THREE.SceneUtils.detach(cubeMesh[i], parentCube, scene);
attached = false;
}
}
Notice specially that I add the children directly to the parent (not the scene), and that I consider them attached from the beginning. After that, detaching and reattaching them works as expected
How could this be used for a Rubik's cube simulation ?
I would just create all the cubes added to the scene.
Then, to perform a move, you have to
SceneUtils.attach/detach has been deprecated since r105 . One should use Object3D's attach() method directly
// parent the cube to parentCube
parentCube.attach(cubeMesh[i]);
// parent it to the scene
scene.attach(cubeMesh[i])
Remark : detach()
doesn't exist anymore
three.js r.123