arpo
arpo

Reputation: 1889

Rotating a 3d vector in THREE.js on two axes

Sorry for posting possible duplicate.

I have two 3d vectors:

center ( 0, 0, 0 )

orb ( 0, 0, 100 )

I want to rotate the orb-vector around the center-vector on both X and the Y axes. What I'm trying to achieve is the make and object always be in view of the camera in the direction it's facing.

I've tried this but with no luck.

var vector = new THREE.Vector3( 0, 0, 100 );
vector.applyAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI * 0.5 );
vector.applyAxisAngle( new THREE.Vector3( 1, 0, 0 ), Math.PI * 0.5 );
orbBall.position.copy(vector);

Upvotes: 1

Views: 1552

Answers (2)

arpo
arpo

Reputation: 1889

After digging around this issue I realise that it's quite advanced mathematics. Check out this lecture about quaternions if you're interested:

https://www.youtube.com/watch?v=mHVwd8gYLnI

So I used @bjorke suggestins and used a dummy object, and it works well.

var container, scene, camera, renderer, controls, stats;
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;

scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set(100, 100, 400);
camera.lookAt(scene.position);
scene.add(camera);

renderer = new THREE.WebGLRenderer( {antialias:true} );
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container = document.getElementById( 'ThreeJS' );
container.appendChild( renderer.domElement );

var light = new THREE.DirectionalLight(0xffffff); //new THREE.PointLight(0xffffff);
light.position.set( 30, 80, -15 );
scene.add(light);


var boxGeo = new THREE.BoxGeometry( 10, 10, 10);
var axes = new THREE.AxisHelper(1000);
scene.add( axes );

var cameraObj = new THREE.Mesh(boxGeo, new THREE.MeshLambertMaterial( {color: 0x888800}));
scene.add(cameraObj);

var orbSpace = new THREE.Object3D();
scene.add(orbSpace);
var orbBall = new THREE.Mesh(boxGeo, new THREE.MeshLambertMaterial( {color: 0x880088}));
orbBall.position.set(0, 0, cameraObj.position.z + 100);
orbSpace.add(orbBall);

animate();

var camX = 0.3;
var camY = 0;
function animate() {

    requestAnimationFrame( animate );

    camY += 0.02;
    if (camY >= 2) camY = 0;

    cameraObj.rotation.x = Math.PI * document.querySelector('#volume').value;
    cameraObj.rotation.y = Math.PI * camY;
    orbSpace.position.copy(cameraObj.position);
    orbSpace.rotation.copy(cameraObj.rotation)


    renderer.render( scene, camera );

}

Here's a codepen about how it works:

http://codepen.io/arpo/pen/RrpMJJ

You can update the X angle in the uper right corner

Upvotes: 0

bjorke
bjorke

Reputation: 3305

"What I'm trying to achieve is the make and object always be in view of the camera in the direction it's facing."

If you are simply trying to ensure that orbBall always faces the camera, and both orbBall and the camera are part of the THREE scene then you can just use lookAt like so:

orbBall.lookAt(camera.position);

if you need to align a particular side of orbBall you can use a null dummy Object3D to do it, by adding the dummy node to the scene and orbBall to the dummy, in something like this:

dummy = new THREE.Object3D();
scene.add(camera); // "camera" is defined however
scene.add(dummy);
dummy.add(orbBall); // "orbBall" is created as usual
// ... not to align dummy+orbBall
dummy.lookAt(camera.position);
// ...and you can just rotate orbBall around "inside" dummy, just once,
///       to face however you like

Upvotes: 1

Related Questions