The first step I want to realize in my camera system using Quaternion is to bulid a Quaternion according to the camera eye "look at" some a certain deriction. Just Say, we know at beginning the "front vector" of the camera points to (0,0,-1) (in right-hand coordinates system) and we let the camera look at somewhere and it points to (x,y,z). Hence we got two direction vectors for this camera, and then the question is, how to build a Quaternion ? The aim to build that Quaternion is to facilitate the future use of the camera.
I read that paper and got a little progress to build up a Quaternion. And I designed a method to do that. Untested yet. Just "Fire and Forget...". You can see it as pseudocode.
我想在我的相机系统中实现有关四元数的第一步,是根据相机看到的目标点来构建一个四元数。比如说,我们知道相机一开始是指向(0,0,1)的(右手坐标系中),然后我们把相机设置到某个朝向(x,y,z)。这样我们就得到了两个方向向量。接下来的问题就是,如何构建一个四元数? 构建此四元数的目的当然是为了方便以后相机的各种运算了。
最近我读了那篇paper ,在理解上有了一点小进展。我写了一个方法来实现此目的。未经测试还。并且是“射后不理....”. 你可以理解为是伪代码。
------------------------------------------------------------------
P.S. This code has been tested and it works well. ~
注:这段代码后来被测试过了,运行良好 ~
Qutearnion::Qutearnion(Vector3 from, Vector3 dest)
{
//1. First to normalize the two vectors
if(!from.IsNormalized()) {
from.Normalize();
}
if(!dest.IsNormalized()) {
dest.Normalize();
}
//2. Then get their outerproduct vector that is
// perpendicular both to the two src vectors
Vector3 axis = from.CrossProduct(dest);
//3. And get its length and normalize it to be a unit
// vector
float axis_length = axis.Normalize();
//4. Since we have such a formula:
/* if: c = a x b
/* then: |c| = |a|*|b|*sin<a,b> */
// And we also know that the two src vectors'
// length both equals to 1(they've been normalized).
// So the length of the outerproduct equals to
// sin<a,b>. And we can get the value of the angle
// by using the arcsin() function.
float sita = asin(axis_length); // calling math lib
//5. But we need to have a sense that, the angle we
// got is the one of the two possible candidates.
// That's because the result of function arcsin()
// is limited between [-PI/2, PI/2], but actually
// we always measure the angle between two vectors
// between [-2*PI, 2*PI](negative angle means a
// reverse result vector). So it exists a potential
// candidate, say, maybe actuall 150degree if we
// get a result of 30degree.
//
// The Dot Product(innerproduct) is a good way to
// help us choose the right one. Since we have such
// formula below:
// d = a * b = |a|*|b|*cos<a,b>
// Since we already knew that both a and b are unit
// vectors, the result of dot product equals to the
// function cos() for that angle, which is exactly
// the one we discussed above. So we can kickoff one
// invalided value through the polarity of the cos().
//
// If cos() is negative, we then need PI to minus the
// angle and reassign to it.
// For example, we got a result -60degree between
// two vectors, and We know that maybe it's actually
// -120degree. Then we dot producct them and find the
// innerproduct < 0. Since cos(-150degree)<0 So we hence
// kickoff the -60degree and remain -150degree, which is
// exactly we want.
float dot_product = from.DotProduct(dest);
if( dot_product<0) {
sita = PI - sita ;
}
//6.Because there is a theorem for Quaternion which says,
//If N(q) = 1, then q = [vö sin W, cos W]
//acts to rotate around unit axis vö by 2W.
// Since we knew the sita is the angle that the "from"
// vector rotates to "dest" vector. So obviously the
// Quaternion which its w equals to sita/2 can make
// "from" vector rotate to "dest" vector by sita.
sita = sita/2;
//7.Finally initialize this Quaternion.
initialize( axis*sin(sita), cos(sita) );
}