방식 1-1. 두 벡터의 Radian값을 구하고
1-2. 두 벡터의 외적을 구해 나온 값을 Axis의 x, y, z를 기준으로
1-3. 쿼터니언 공식에 대입
inline void __Quaternion::RotationSetFromVectorAToVectorB(const __Vector3& vA, const __Vector3& vB) { //vA와 vB의 사이각을 구한다. float fRadian = acosf(vA.Dot(vB) / (vA.Magnitude() * vB.Magnitude())); //완전히 정반대벡터이면 외적 축을 구할수 없기때문에 보정한다. __Vector3 vA2(vA); if(D3DX_PI - fRadian < 0.0005f) vA2 += 0.0005f; //vA와 vB에 직교하는 벡터를 구한다.(cross) __Vector3 vCross; vCross.Cross(vA2, vB); vCross.Normalize(); //vCross를 기준으로 fRadian만큼 회전하는 행렬을 만든다. this->RotationAxis(vCross, fRadian); } inline void __Quaternion::RotationAxis(const __Vector3& v, float fRadian) { //D3DXQuaternionRotationAxis(this, &v, fRadian); this->RotationAxis(v.x, v.y, v.z, fRadian); } inline void __Quaternion::RotationAxis(float fX, float fY, float fZ, float fRadian) { float fTheta = sinf(fRadian/2.0f); x = fX * fTheta; y = fY * fTheta; z = fZ * fTheta; w = cosf(fRadian/2.0f); }
위 공식을 더 간단화 하면 아래와 같다./// 벡터 v0에서 v1까지 호를 그리는 회전 사원수 /// 주의: v0, v1는 단위 벡터 void quatRotationArc(quat* p, const vec3& v0, const vec3& v1) { vec3 c; cross(&c, v0, v1); // 외적값으로 나온 c 벡터 real s = sqrtf((1.0f+dot(v0,v1))*2.0f); // 중요.. // 외적 결과를 쿼터니언의 Axis값으로 산출
p->x = c.x/s; p->y = c.y/s; p->z = c.z/s; p->w = s/2.0f; }
댓글
댓글 쓰기