Click here to Skip to main content
15,890,123 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I don't know if this is an appropriate place for topics like this, but I'll give it a try. I'm building a framework for my WebGL project and at the moment I have a problem with a function which will rotate an object towards a target vector with a given angular speed. In Unity engine it's called rotateTowards(), and since I'm coding my framework from a scratch, I'm basing on my observations about how this function works. Lately I have abandoned an idea about interpolating two quaternions in this function using nLERP method, because an angular speed seems to be far more suitable factor. The function seems to be almost working - it works well only when there is no roll or pitch angle in the camera rotation involved, otherwise it makes strange curves and sets the final position after ridiculously long time. I suspect it may have something to do with me methodology of searching the shortest path of rotation between two vectors (which bases on an angle between them and a rotation axis calculated from their cross product). I've been trying to fix this for a long time, but without any success. What I also opt for is to restrict the rotation only to pitch and yaw axises (so no roll would be involved). My very first idea about how to do this was to convert the rotation to an Euler angles vector, nullify roll angle and convert it back to quaternion, but doing so will introduce Gimbal Lock problem, which is incongruous in this case. The code of this function below:
JavaScript
rotateTowards: function(vecTarget, angularSpeed) {
	// If is on the same position
	if (this.position.isEqual(vecTarget)) {
		return;
	}

	var vecStart = this.rotation.getForwardVector();
	// Add vectors instead of subdividing them because the camera is facing -Z direction
	vecTarget.addSelf(this.position);
	vecTarget.normalize();
	var angleLeft = Math.acos(vecStart.dot(vecTarget));

	// If already rotated towards the target
	if (Math.areScalarsSimilar(angleLeft, 0)) {
		return;
	}
	// If vectors are opposite
	else if (Math.areScalarsSimilar(angleLeft, Math.PI)) {
		// Turn around up-axis a bit
		this.rotation.multiply(this.tempQuat.axisToQuaternion(angularSpeed * deltaT, upVec()));
	}
	// If vectors casually differs
	else {
		var rotAxis = vecStart.cross(vecTarget);

		// If able to make another full rotation step
		if (angleLeft > angularSpeed * deltaT) {
			this.rotation.multiply(this.tempQuat.axisToQuaternion(angularSpeed * deltaT, rotAxis));
		}
		// If the angle left is smaller than the angular speed
		else {
			// Set the final rotation
			this.rotation.multiply(this.tempQuat.axisToQuaternion(angleLeft, rotAxis));
		}
	}

	MVMatrix.setRotation(this.rotation.quaternionToMatrix());
},

Save the world, and give me a hint what is wrong with this code / my notion about this function ^^
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900