Animating rotation of object based on new pivot in Three.js

Viewed 97

I want to do this in Three.JS:

Animation

I did the spiral and downward movement, but I don't do the knocking motion.

var planeGeometry = new THREE.PlaneGeometry(10,10);
var planeMaterial = new THREE.MeshBasicMaterial({color: 0x828282, wireframe: false, side: THREE.DoubleSide});
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.rotation.x = 1.0 * THREE.Math.degToRad(90);
scene.add(planeMesh);

var cylinderGeometry = new THREE.CylinderGeometry(0.2, 0.2, 14);
var cylinderMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, wireframe: false});
var cylinderMesh = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
cylinderMesh.position.set(0,7,0);
scene.add(cylinderMesh);


groupDown = new THREE.Group();
groupSpiral = new THREE.Group();
groupKnock = new THREE.Group();

var woodPeckerGeometry = new THREE.BoxGeometry(1,3,2);
var woodPeckerMaterial = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: false});
var woodPeckerMesh = new THREE.Mesh(woodPeckerGeometry , woodPeckerMaterial );
groupDown.add(woodPeckerMesh );
groupDown.position.set(0, 10, 2);

groupSpiral.add(groupDown)

groupKnock.add(groupSpiral)

scene.add(groupKnock);

and the render function:

var render = function () {
    groupDown.position.y -= 0.03;
    if(groupDown.position.y < 1.6) {
        groupDown.position.y = 13;
    }
    groupSpiral.rotation.y += 0.03;
};

So the question is that how can I do knocking motion?

1 Answers

You could increase the groupDown rotation on the z axis like you did with its position and the "woodpecker" would start to knock on the cylinder. The problem with this is that the pivot for the rotation is at the center of the box.

To fix this, you can add the "woodpecker" to a group (i.e. pivotGroup), set its position up relative to its height on this new group and treat pivotGroup as the new object for animation. This way, the box would rotate from its base.

See the complete example below.

var camera, scene, renderer, groupSpiral, groupDown, groupKnock;

function init() {

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 10, 10000);
    camera.position.z = 30;
    camera.position.y = 24;
    camera.rotation.x = -0.55;

    scene.add(camera);

    var planeGeometry = new THREE.PlaneGeometry(10, 10);
    var planeMaterial = new THREE.MeshBasicMaterial({color: 0x828282, wireframe: false, side: THREE.DoubleSide});
    var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
    planeMesh.rotation.x = 1.0 * THREE.Math.degToRad(90);
    planeMesh.rotation.z = 1.0 * THREE.Math.degToRad(45);
    scene.add(planeMesh);

    var cylinderGeometry = new THREE.CylinderGeometry(0.3, 0.3, 14);
    var cylinderMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, wireframe: false});
    var cylinderMesh = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
    cylinderMesh.position.y = 7;
    scene.add(cylinderMesh);

    var coneGeometry = new THREE.ConeGeometry(0.3, 1, 32);
    var coneMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: false});
    var coneMesh = new THREE.Mesh(coneGeometry, coneMaterial);
    coneMesh.position.set(1, 1.8, 0);
    coneMesh.rotation.z = Math.PI / -2;

    groupDown = new THREE.Group();
    groupSpiral = new THREE.Group();
    groupKnock = new THREE.Group();

    var woodPeckerGeometry = new THREE.BoxGeometry(1, 3, 1.5);
    var woodPeckerMaterial = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: false});
    var woodPeckerMesh = new THREE.Mesh(woodPeckerGeometry, woodPeckerMaterial);

    woodPeckerMesh.position.set(0, 1, 0);
    woodPeckerMesh.rotation.set(0, 0, Math.PI);
    groupKnock.add(coneMesh);
    groupKnock.add(woodPeckerMesh);

    groupDown.add(groupKnock);
    groupDown.position.set(0, 12, 1.5);
    groupDown.rotation.y = Math.PI / 2;
    groupSpiral.add(groupDown)

    scene.add(groupSpiral);

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

}

function animate() {

    requestAnimationFrame(animate);
    render();

}

function render() {

    groupDown.position.y -= 0.03;
    if(groupDown.position.y < 1.6) {
        groupDown.position.y = 12;
    }
    groupSpiral.rotation.y += 0.03;

    groupKnock.rotation.z += 0.035;
    if(groupKnock.rotation.z > Math.PI/6) {
        groupKnock.rotation.z = 0;
    }

    renderer.render(scene, camera);

}

$(document).ready(function() {
    init();
    animate();
});
* {
  padding: 0;
  margin: 0;
  overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Related