3
votes

I want to create a 3rd person camera similiar to example. The camera should stick behind the object and rotate if the rotation difference between camera and object is too high (maybe above ten percent).

This is my actual camera code:

var targetPosition = this.getTargetPosition();
var targetRotation = this.getTargetRotation();
var tmpQuaternion = new THREE.Quaternion();
tmpQuaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), 180 * (Math['PI'] / 180));
this.camera.quaternion = targetRotation;
this.camera.position = targetPosition;
this.camera.quaternion.multiplySelf(tmpQuaternion);
this.camera.quaternion.normalize();
this.camera.updateMatrix();
this.camera.translateZ(200);
this.camera.translateY(50);

But there are several problems right now. The camera quaternion should not set directly to the target rotation. But I dont know how to calculate the difference between camera quaternion and target quaternion and use maybe this if the distance is too high:

var qm = new THREE.Quaternion();
THREE.Quaternion.slerp(targetRotation, this.camera.quaternion, qm, time);
this.camera.quaternion = qm;

The second problem is the position itself. Currently I set camera position to the object position and translate it back to view behind, but the translation should be already in target position and the camera position should be translated to the target position.

Update 1: I made an example html: http://ssachtleben.github.com/CameraProblem/

Update 2: I made some progress now. Seems like I get quaternion difference with this function:

getAxisAngle = function(quaternion1, quaternion2) {
  var tmpQuaternion = new THREE.Quaternion();
  tmpQuaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), 180 * (Math['PI'] / 180));
  var tmpRotation1 = quaternion1.clone();
  tmpRotation1.multiplySelf(tmpQuaternion);
  tmpRotation1.normalize();
  var tmpRotation2 = quaternion2.clone();
  if (tmpRotation2.w > 1) {
    tmpRotation2.normalize();
  }
  var angle1 = 2 * Math['acos'](tmpRotation1.w);
  var angle2 = 2 * Math['acos'](tmpRotation2.w);
  var diff = angle1 > angle2 ? angle1 - angle2 : angle2 - angle1;
  return diff;
};

But know I need to freeze the axis if the angle difference is too high. How can I do this?

Any help would be appreciated.

1

1 Answers

2
votes

Ok finally the camera is fixed and works as excepted:

var targetPosition = this.getTargetPosition();
var targetRotation = this.getTargetRotation();
var tmpQuaternion = new THREE.Quaternion();

tmpQuaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), 180 * (Math['PI'] / 180));
targetRotation.multiplySelf(tmpQuaternion);
targetRotation.quaternion.normalize();

var qm = new THREE.Quaternion();
THREE.Quaternion.slerp(this.camera.quaternion, targetRotation, qm, 0.07);
this.camera.quaternion = qm;
this.camera.quaternion.normalize();