1

How can I have an ThreeJS object rotate on an axis that is at angle.

Like from this codepen I made, the left square rotates on its center and moved up when you click on the "rotate up" button.

I want the left cure rotate along the red axis in the image attached and move along on that axis when click on the "Rotate 45 degree" button. I can make up move along the axis, but the rotation is wrong. How can I make the cute rotate along the red axis?

****EDIT:

enter image description here

PS: Sorry I cannot get the snippet working here. Please use the codepen link for the demo. https://codepen.io/eforblue/pen/MWpYggY

var upTl = gsap.timeline();
var degreeTl = gsap.timeline();

var width = window.innerWidth;
var height = window.innerHeight;

var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);

var scene = new THREE.Scene();

var cubeGeometry = new THREE.CubeGeometry(100, 100, 100);
var cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
scene.add(cube);


var cube2 = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube2.position.set(200, 200, 0);
cube2.rotation.z = 45;
scene.add(cube2);

var camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 10000);
camera.position.set(0, 500, 3000);
camera.lookAt(cube.position);

scene.add(camera);

var skyboxGeometry = new THREE.CubeGeometry(100, 100, 100);
var skyboxMaterial = new THREE.MeshBasicMaterial({ color: 0x000000, side: THREE.BackSide });
var skybox = new THREE.Mesh(skyboxGeometry, skyboxMaterial);


var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(0, 300, 200);

scene.add(pointLight);

var clock = new THREE.Clock();

function render() {
        requestAnimationFrame(render);
        
        // cube.rotation.y -= clock.getDelta();
        
        renderer.render(scene, camera);
}

render();

$('.up').on('click', () => {
  console.log('click')
     upTl.to( cube.rotation, 1, { y: Math.PI * 3 }, 0 )
     .to( cube.position, 1, { y: cube.position.y + 400 }, 0 )    
})

$('.degree').on('click', () => {
  degreeTl.to( cube2.rotation, 1, { y: Math.PI * 3 }, 0 )
     .to( cube2.position, 1, { x: cube2.position.x + 300, y:cube2.position.y + 300 }, 0 )    
});
canvas {
        position: fixed;
        top: 0;
        left: 0;
}

button {
  position:relative;
  z-index: 99;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.1/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="./main.js"></script>
<button class="up">rotate up</button>
<button class="degree">rotate 45deg</button>
Yang Zeng
  • 71
  • 1
  • 6

1 Answers1

0

In your case it's easier to use quaternions to rotate around your red axis, you can use the following function and define your rotation axis in the "axis" parameter.

static rotateAroundWorldAxis(mesh, point, axis, angle) {
     const q = new Quaternion();
     q.setFromAxisAngle(axis, angle);
     mesh.applyQuaternion(q);
     mesh.position.sub(point);
     mesh.position.applyQuaternion(q);
     mesh.position.add(point);
    return mesh;
}
houssk
  • 146
  • 1
  • 7