Lock multiple Three.js meshes in relation to one another

573 views Asked by At

I've been struggling to figure out how to lock two sibling meshes in a scene, so that when I rotate them their relationship to each other remains fixed.

I know this can be done using a dummy Object3D or by adding one object to the other, but I need to use Physijs, and want both meshes to respond to collisions and other physics in the scene.

This is a simplified example, but I would love to know how to get the upper sphere/cylinder pair to behave exactly like the lower pair in the following code (the lower pair have a parent/child relationship, while the upper meshes are both added directly to the scene):

$(document).ready
(
    function()
    {
        var renderer,scene,camera,globe,globe2,disc,disc2,params;

        params = { rotation: {x:0,y:0,z:0}};

        var init = function()
        {
            scene = new THREE.Scene();

            camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
            camera.position.z = 100;
            scene.add(camera);

            renderer = new THREE.WebGLRenderer({antialias:true});
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);

            // create a mesh with models geometry and material
            globe = new THREE.Mesh(new THREE.SphereGeometry(5, 32, 32), new THREE.MeshNormalMaterial({color: 0xff3300,transparent:false, opacity: 1}));
            THREE.GeometryUtils.center( globe.geometry );
            scene.add(globe);

            disc = new THREE.Mesh(new THREE.CylinderGeometry( 5, 5, 1, 32), new THREE.MeshNormalMaterial());
            disc.position.y = 5;
            scene.add(disc);

            globe2 = new THREE.Mesh(new THREE.SphereGeometry(5, 32, 32), new THREE.MeshNormalMaterial({color: 0xff3300,transparent:false, opacity: 1}));
            THREE.GeometryUtils.center( globe2.geometry );
            globe2.position.y = -20;
            scene.add(globe2);

            disc2 = new THREE.Mesh(new THREE.CylinderGeometry( 5, 5, 1, 32), new THREE.MeshNormalMaterial());
            disc2.position.y = 5;
            globe2.add(disc2);

            controls = new dat.GUI();
            controls.add( params.rotation, 'x', -180, 180 );
            controls.add( params.rotation, 'y', -180, 180 );
            controls.add( params.rotation, 'z', -180, 180 );
            //controls.close();
        }

        var rotateAroundWorldAxis = function( object, axis, radians ) 
        { 
            rotWorldMatrix = new THREE.Matrix4();
            rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);
            rotWorldMatrix.multiplySelf(object.matrix);
            object.matrix = rotWorldMatrix;
            object.rotation.setEulerFromRotationMatrix(object.matrix, object.order);
        }

        var animate = function()
        {
            requestAnimationFrame(render);
            render();
        }

        var render = function()
        {
            requestAnimationFrame(render);

            globe.rotation.set( params.rotation.x*Math.PI/180,params.rotation.y*Math.PI/180,params.rotation.z*Math.PI/180)
                disc.rotation.copy(globe.rotation);

            globe2.rotation.set( params.rotation.x*Math.PI/180,params.rotation.y*Math.PI/180,params.rotation.z*Math.PI/180)

            renderer.render(scene,camera);
        }

        init();
        animate();
    }
);

Fiddle here: http://jsfiddle.net/lostnation/9pd0kpwo/30/

1

There are 1 answers

0
AudioBubble On

Unfortunatly, when adding compound meshes (parent/child relationship meshes) to a scene, their children are finalized and can't be changed after (Physijs). This surely must be the same thing in THREE.

Do you know about Physijs __dirtyRotation? You have to set this flag to true before you can change any actual Physijs mesh rotation. Using the same algorithm, you can do the same thing as if you were only using THREE. Just make sure the shapes are not added to each other.