[SOLVED] Tweening the rotation of a camera

Hey all, bit of a weird issue here.

I appear to be having an issue tweening a PerspectiveCamera’s y rotation (using tween.js). It works to some degree, but when rotations are between 90deg and 270deg, they appear mirrored and don’t match.

A bit of a background - I’ve designed a level in blender, and import it using GLTFLoader - all working fine. In this blender level, I have a series of cone shapes that define a position and direction for a camera to tween a long and rotate along.

blender_2019-01-08_17-52-19

The camera tweens from position to position (works perfectly fine) and simultaneously rotates based on the cones rotations (semi-working).

In the above screenshot, once it gets to the 5th and 6th cone, the rotations are offset. Cone 5’s y rotation is 270deg and Cone 6 is 226deg.

If I output the rotation of the camera after it finished tweening, it is almost 90 degrees offset from the rotation of cone 6.

I did a bit of testing, look at the screenshot below

As you can see, the arrowhelpers I create every update work fine until it hits 90 degrees, and works fine again after 270. You can observe that if the arrow helpers were flipped for those two, the would match the direction of the cone.

If I console log the rotations of the broken cones, they have minus rotations and sometimes up to 360 degrees or more too much. The others are fine and stay in positive values. All cones in blender have positive rotations between 0 and 360, no more or less.

What is causing the camera’s rotation to mess up in that range?
Sadly I’m unable to upload a test build due to NDA :frowning: any help is very muchly appreciated!

Live example:
http://davidpuetter.com/games/threejs-test/
Click on the game to start the tween. Once it’s done, press Q to view it from overhead. You can see in the top right one, the lines didn’t match.

Code available here:

Sorry for very messy code, this was stripped out of a project thats under NDA.

1 Like

/cc:

I added an example & source code to the bottom of the OP.

Anyone? :frowning:

Would you be a bit helpful to say, where is that piece of code with tweening?

Ah of course, sorry!

In scenes/GameScene.js:

Positions and rotations are put in an array in createCameraTweens() lines 93-105
The rotation tween is created in createCameraTweens() line 121-129.

Tweens are started in nextCameraGroup() line 183 & 184

Any ideas?

Anyone?

Changing the rotation.y value of the last cone in the first screenshot to -node.rotation.y * -Math.PI yields correct results but this does not work for all cones obviously.

I tried an approach where I have an array of THREE.Vector4() (x, y, z, rotation) with .onUpdate() function in tweens and seems it works okay. Thus, instead of two tweens per move from one point to another, I have just one.

https://jsfiddle.net/prisoner849/L2vo4srd/

Your fiddle doesn’t seem to work :sweat_smile:

That’s why I prefer codepen.io :slight_smile: For unknown reason the fiddle didn’t save the progress.
I’ve restored it, try again :slight_smile:

Thank you so far for your help! Much appreciated :slight_smile:
Your example does look good and appears to be working, however I adopted your method and my demo still seems to break on the same cones;

That leads me to believe that it might be an issue with the glTF importer/blender Exporter? I also tried completely deleting those two cones and copying one of the ones that did work, with the same result as above.

And I just observed that if I rotate the last three cones in the same direction as the previous ones (anti-clockwise), this works perfectly fine.

//edit - code;

parseGroups() {
		for (let i = 0; i < this.world.camerapaths.length; i++) {
			for (let j = 0; j < this.world.camerapaths[i].length; j++) {
				const node = this.world.camerapaths[i][j];
				this._tweenVectorArray.push(new THREE.Vector4(node.position.x, node.position.y, node.position.z, node.rotation.y))
			}
		}		
	}

	createCameraTweens() {
		this.parseGroups();

		for (let i = 0; i < this._tweenVectorArray.length - 1; i++) {
			let t = new TWEEN.Tween(this._tweenVectorArray[i], this.tweens)
				.to(this._tweenVectorArray[i + 1].clone(), 1000)
				.onUpdate((val) => {
					common.camera.position.copy(val)
					common.camera.rotation.y = val.w;
					this.stage.add(new THREE.ArrowHelper(common.camera.getWorldDirection(new THREE.Vector3()), common.camera.position, 2, 0xFF0000));
				})
				.easing(TWEEN.Easing.Linear.None);

			this._cameraTweenGroups.push(t);
		}
	}

Just out of curiousity, in those “wrong” objects, are vertices in geometries have the same coordinates as in the “correct” objects?

Possibly? The geometry was a single cone facing upwards, which I rotated 90 degrees on its Y axis and then applied its transform in blender, which in theoretically should have applied all the new vertex positions. The blend file is in the github repo if you want to take a look!

However, I dont think its an issue with the vertices of the cone geometry, because if I try to offset the ‘wrong’ cones in blender, the camera rotation offset isn’t the same. I.e. if the cone was facing towards 0, and the camera faced towards -30, and I rotate the cone by 90, the camera doesn’t necessarily face towards 60, it could be more or less than -30.

Still hoping for a saving grace :stuck_out_tongue: I’m out of ideas for it. I’ll try exporting the level in a different format, see if GLTF import/export is causing it.

Any chance to share a gltf model?

It’s in assets/3d/ of the Github repo :slight_smile: Blend file, too

Have you tried to load you gltf model to https://gltf-viewer.donmccurdy.com/ ?

Yup, looks exactly as it should. Same in blender and the viewer.

Whew, few months later and I attempted to fix this again - it was a really simple fix.

Seems like it was gimbal-locking despite only tweening on one axis. Simply tweening the cameras quaternion to the quaternion of the node fixed it and now it works flawlessly!

1 Like