Camera transition with rotation - three.js

I got a question about camera object. I'm trying to make a transition between cameras and I got it partially working. Camera is moving well but it does not rotate correct. I suppose my code does not calculate lookAtVector right but I cannot find information how to do it correct.
Here is the code I'm using:
var new_position = new_camera.position.clone();
var new_rotation = new_camera.rotation.clone();
var new_quaternion = new_camera.quaternion.clone();
camera.rotation.clone(new_rotation);
camera.quaternion.clone(new_quaternion);
newlookAtVector = new THREE.Vector3(0, 0, -1);
newlookAtVector.applyEuler(new_rotation, new_camera.eulerOrder);
new TWEEN.Tween( camera.position ).to( {
x: new_position.x,
y: new_position.y,
z: new_position.z}, 600 ).onUpdate(function () {
camera.lookAt(newlookAtVector);
}).onComplete(function () {
camera.lookAt(newlookAtVector);
}).easing( TWEEN.Easing.Sinusoidal.Out).start();
Thank you!

Related

Animate 'real' translateZ property

Hi guys so I am looking for a way to animate translateZ ( i use gsap also but doesn't have to be gsap but probably prefered as the rest of my animations use it).
What i'm trying to do.....
so I am trying to have my character face the enemy character on a collision then rotate the player to the opposite rotation of the enemy so its basically facing the opposite way to the enemy character so the player can be repelled backwards when its hit from the enemy...
Where im up to....
so I have managed to do it all basically and it works just fine but without animation:
const dirToPlayer = this._FindPlayer();
const controlObject = object;
const controlObject2 = this._target;
const _R = controlObject.quaternion.clone();
const m = new THREE.Matrix4();
m.lookAt(
new THREE.Vector3(0, 0, 0),
dirToPlayer.negate(),
new THREE.Vector3(0, 1, 0));
_R.setFromRotationMatrix(m);
controlObject.quaternion.copy(_R);
// console.log(dir);
controlObject.translateZ( -10 );
now im not strong in three nor gsap
so here's what i did to try and animate translateZ:
let position = new THREE.Vector3();
object.getWorldPosition(position);
position.add(new THREE.Vector3(0, 0, -10));
gsap.to(object.position, {
duration: 0.6, z: position.z,
onUpdate: function() {
},
});
the above will work but only goes along the positive z axis so sometimes it gets pushed forwards rather than back ...
So what i really need is to animate the TRUE translateZ property any idea's?
thanks
this seems to work:
var ten = {value: 0};
gsap.to((object.translateZ(ten.value), ten), {
duration: 0.6, value: -10,
onUpdate: function() {
object.translateZ(ten.value);
},
});
console.log(object.translateZ(ten.value));

Tween camera target in three.js

I have this code that works well:
function onMouseMove( event ) {
window.onmousedown = function() {
var canvasPosition = renderer.domElement.getBoundingClientRect();
var mouseX = event.clientX - canvasPosition.left;
var mouseY = event.clientY - canvasPosition.top;
var mouseVector = new THREE.Vector3 (
2 * (mouseX / window.innerWidth) - 1,
1 - 2 * (mouseY / window.innerHeight), 1);
mouseVector.unproject( camera );
var dir = mouseVector.sub( camera.position ).normalize();
var distance = - camera.position.z / dir.z;
var pos = camera.position.clone().add( dir.multiplyScalar( distance ) );
camera.getWorldDirection();
camera.lookAt( pos );
// camera.updateMatrixWorld(true);
console.log(mouseVector);
console.log(mouseX);
console.log(mouseY);
// render();
}
}
But I would like to smooth the movement. So I found the following code from the tween example, but not sure how to use it. In the above code, I get current camera lookat from one place, one format, and put the new camera look at in camera.lookat in a different format - neither of which seem to be standard x,y,z.
In the below code, the tween would have me change an properties (x,y,z) on a single item. which the unprojecting and normalizing of the camera do not accommodate:
new TWEEN.Tween( intersects[ 0 ].object.position )
.to( {
x: Math.random() * 800 - 400,
y: Math.random() * 800 - 400,
z: Math.random() * 800 - 400
}, 2000 )
.easing( TWEEN.Easing.Elastic.Out)
.start();
If there is a breakdown or something I can read, or actually work out problems to understand, I'd be grateful. I've read camera tutorials and matrix tutorials over and over for years, but my brain just can't comprehend it.
I've been digging around here quite a bit, but nothing addresses a camera tween - at least for a valid version of threejs
Thank you!
I recommend you get acquainted with linear interpolation, or more commonly known as "lerp". The THREE.Vector3 class has a lerp function that you could use to interpolate between a starting point and an ending point:
var camPos = new THREE.Vector3(0, 0, 0); // Holds current camera position
var targetPos = new THREE.Vector3(10, 10, -10);// Target position
var origin = new THREE.Vector3(0, 0, 0); // Optional origin
function animate(){
// Interpolate camPos toward targetPos
camPos.lerp(targetPos, 0.05);
// Apply new camPos to your camera
camera.position.copy(camPos);
// (Optional) have camera look at the origin after it's been moved
camera.lookAt(origin);
// render();
}
In the above example, your animate() function is called once per frame, and the camera will travel 5% towards targetPos per frame.
If you change targetPos, the camera will animate towards its new target value.
I recommend you first get acquainted with lerping before you start bringing in third-party libraries like TWEEN.js or others.
just for smoothing the movement, this might already help you:
// keep this outside of the event-handler
var lookAtPosition = new THREE.Vector3();
var lookAtTween = new TWEEN.Tween(lookAtPosition);
// as lookAt is not a property we can assign to we need to
// call it every time the tween was updated:
lookAtTween.onUpdate(function() {
camera.lookAt(lookAtPosition);
});
window.onmousedown = function() {
// do your thing to compute pos
// instead of `camera.lookAt(pos)`, do this:
lookAtTween
.stop() // just in case it's still animating
.to(pos, 500) // set destination and duration
.start(); // start the tween
};

Three.js store camera rotation and apply to camera dolly

I'm developing a VR app and I'm attempting to store the current camera viewing angle with
THREE.Utils = {
cameraLookDir: function(camera) {
var vector = new THREE.Vector3(0, 0, -1);
vector.applyEuler(camera.rotation, camera.eulerOrder);
return vector;
}
};
var dir = THREE.Utils.cameraLookDir(camera);
var defaults = {
x:dir.x,
y:dir.y,
z:dir.z,
fov: camera.fov
};
I'm then attempting to apply this to a dolly which I use to pre-set the camera viewing angle for using with VRControls
The dolly is constructed as
dolly = new THREE.PerspectiveCamera();
dolly.position.set( 0, 0, 0 );
scene.add( dolly );
dolly.add( camera );
and I try and apply the angle so the camera is facing the same way
dolly.rotation.x = defaults.x;
dolly.rotation.y = defaults.y;
dolly.rotation.z = defaults.z;
This isn't' really working, and I'm not really sure how to go about getting the camera to face the same way as it's saved values.
Any clues on how to go about this?

camera to face selected plane three.js

i have 600 planes being added to a scene in random x,y,z positions, each plane is clickable. when clicked i animate to the selected plane. All works but i am struggling for the camera to face the selected plane / or make sure the plane is centred in the view. I have tried getting the direction vector of the clicked item but not sure how make sure the camera is always a set distance away. here is the function and below a link to the test. Any ideas? Many thanks
http://adigitalengagement.co.uk/webauth_stickies/plane/
function toObj(obj) {
var lookAtVector = new THREE.Vector3(0, 0, 1);
lookAtVector.applyQuaternion(obj.quaternion);
console.log(lookAtVector);
var rotateTween = new TWEEN.Tween(controls.target)
.to({
x: obj.position.x,
y: obj.position.y,
z: obj.position.z
}, 4000)
.interpolation(TWEEN.Interpolation.CatmullRom)
.easing(TWEEN.Easing.Quintic.InOut)
.start();
var goTween = new TWEEN.Tween(camera.position)
.to({
x: obj.position.x,
y: obj.position.y,
z: obj.position.z + 10
}, 4000)
.interpolation(TWEEN.Interpolation.CatmullRom)
.easing(TWEEN.Easing.Quintic.InOut);
goTween.start();
goTween.onComplete(function() {
console.log('done!');
});
}
I'm sure there can be a better solution, but this one can be a starting point based on this SO answer.
I've changed your toObj() function and added a global variable:
var lookAtVector = new THREE.Vector3(0,0,0);
...
function toObj(obj) {
var normalMatrix = new THREE.Matrix3().getNormalMatrix( obj.matrixWorld );
var worldNormal = new THREE.Vector3(0,0,1).applyMatrix3( normalMatrix ).normalize();
var camPosition = new THREE.Vector3().copy(obj.position).add(worldNormal.multiplyScalar(100));
var rotateTween = new TWEEN.Tween(lookAtVector)
.to({
x: obj.position.x,
y: obj.position.y,
z: obj.position.z
}, 4000)
.easing(TWEEN.Easing.Quadratic.InOut)
.onUpdate(function(){
camera.lookAt(lookAtVector);
})
.onComplete(function(){
lookAtVector.copy(obj.position);
})
.start();
var goTween = new TWEEN.Tween(camera.position)
.to(camPosition, 4000)
.easing(TWEEN.Easing.Quadratic.InOut)
.start();
}
jsfiddle example

Tween camera to coordinates but preserve camera angle in three.js

I've seen a couple of questions on stack overflow about this but none resolve my issue.
For my first project in Three.Js I'm trying to create a tree and have the camera zoom in on specific nodes. I have the following code:
var selectedObject = fourthParent;
camera.target = selectedObject;
var tween = new TWEEN.Tween(camera.position).to({
x: selectedObject.position.x,
y: selectedObject.position.y,
z: 5
},1000).easing(TWEEN.Easing.Linear.None).onUpdate(function () {
camera.lookAt(camera.target);
}).onComplete(function () {
camera.lookAt(selectedObject.position);
}).start();
var tween = new TWEEN.Tween(camera.target).to({
x: selectedObject.position.x,
y: selectedObject.position.y,
z: 0
}).easing(TWEEN.Easing.Linear.None).onUpdate(function () {
}).onComplete(function () {
camera.lookAt(selectedObject.position);
}).start();
This moves the camera correctly but right at the end of the animation it changes the camera angle. I'm not changing the angle in my code so I have no idea why it is changing. Can anyone help?
Thanks,
Joe
Here is the working code:
updateControls = false;
var selectedObject = fourthParent;
camera.target = selectedObject;
var tween = new TWEEN.Tween(camera.position).to({
x: selectedObject.position.x,
y: selectedObject.position.y,
z: 20
},1000).easing(TWEEN.Easing.Linear.None).onComplete(function () {
controls.target0.set(selectedObject.position.x, selectedObject.position.y, selectedObject.position.z);
controls.position0.set(selectedObject.position.x, selectedObject.position.y, 20);
controls.reset();
updateControls = true;
}).start();
var tween = new TWEEN.Tween(camera.target).to({
x: selectedObject.position.x,
y: selectedObject.position.y,
z: 20
}).easing(TWEEN.Easing.Linear.None).start();
// Render loop
var render = function () {
requestAnimationFrame(render);
TWEEN.update();
renderer.render(scene, camera);
if (updateControls) {
controls.update();
}
};
By calling camera.lookAt() you're changing the camera angle.
You should just remove every instance of that code.

Resources