Hi,
I am trying to employ quaternion-based rotation to a positional light, with no luck, and was hoping some of you would help me figuring out whether the math I've used is wrong or the programming has bugs.
The problem I'm having is I simply can't perform any rotations.
All comments/suggestions will be greatly appreciated!
I am calculating the direction vector has follows:
Vector4f rx(::g_axis_X, _dx), ry(::g_axis_Y, _dy), rz(::g_axis_Z, _dz);
Vector3f v(::g_vector_down);
rx.Mul(ry, rx); // rx * ry (result into rx)
rx.Mul(rz, rx); // rx * rz (result into rx)
rx.Mul(v, v); // rx * v (result into v)
// set light direction
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, v);
Other relevant bits of code follow.
template <typename T> Vector4
// Converts degrees to radians
static inline T Vector4<T>::DegreesToRadians(T degrees) throw()
{ return(degrees * T(M_PI) / T(180)); }
// Construct from an axis and a rotation angle.
// NOTE: Vector-in must already be normalized.
Vector4<T>::Vector4(const Vector3<T>& axis, T degrees) throw()
{
FromAxisAngle(axis, degrees);
}
// Assign new quaternion from an axis and an angle in degrees.
// NOTE: Vector-in *MUST ALREADY BE* normalized.
void Vector4<T>::FromAxisAngle(const Vector3<T>& axis, T degrees) throw()
{
T sinAngle;
degrees = DegreesToRadians(degrees) * T(0.5);
sinAngle = sin(degrees);
_x = axis._x * sinAngle; _y = axis._y * sinAngle;
_z = axis._z * sinAngle; _w = cos(degrees);
}
// Calculates the inverse of the quaternion and stores it
// in another quaternion object.
void Vector4<T>::InvertTo(Vector4<T>& quat) const throw()
{
T len = T(1) / (_x*_x + _y*_y + _z*_z + _w*_w);
quat._x = _x*-len; quat._y = _y*-len; quat._z = _z*-len; quat._w = _w*len;
}
// Multiply by a quaternion and store in given quaternion object.
Vector4<T>& Vector4<T>::Mul(const Vector4<T>& mulQuat,
Vector4<T>& outQuat) const throw()
{
Vector3<T> vec1(*this), vec2(mulQuat), cross;
outQuat._w = ((_w * mulQuat._w) - (vec1.Dot(vec2)));
vec1.Cross(vec2, cross);
vec1._x *= mulQuat._w; vec1._y *= mulQuat._w; vec1._z *= mulQuat._w;
vec2._x *= _w; vec2._y *= _w; vec2._z *= _w;
outQuat._x = (vec1._x + vec2._x + cross._x);
outQuat._y = (vec1._y + vec2._y + cross._y);
outQuat._z = (vec1._z + vec2._z + cross._z);
return(outQuat);
}
// Multiply by a vector and store result in given vector object.
Vector3<T>& Vector4<T>::Mul(const Vector3<T>& mulVector,
Vector3<T>& outVector) const throw()
{
Vector4<T> vectorQuat(mulVector), inverseQuat, resultQuat;
InvertTo(inverseQuat);
vectorQuat.Mul(inverseQuat, resultQuat);
this->Mul(resultQuat, resultQuat);
outVector._x = resultQuat._x;
outVector._y = resultQuat._y;
outVector._z = resultQuat._z;
return(outVector);
}
template <typename T> Vector3
// Copy-constructor.
Vector3(const Vector3<T>& oV) throw()
: _x(oV._x), _y(oV._y), _z(oV._z) {}
// Calculates cross between this vector and another. Stores
// result in another vector object.
Vector3<T>& Vector3<T>::Cross(const Vector3<T>& vector, Vector3<T>& cross) const throw()
{
cross._x = (_y * vector._z) - (vector._z * _y);
cross._y = (_z * vector._x) - (vector._x * _z);
cross._z = (_x * vector._y) - (vector._y * _x);
return(cross);
}
// Calculates dot between this vector and another.
// Does *NOT* calculate the angle in radians between the two vectors.
inline T Vector3<T>::Dot(const Vector3<T>& vector) const throw()
{
return(_x*vector._x + _y*vector._y + _z*vector._z);
}
Global vectors/axes
CDECL const Vector3f g_vector_down(0.f, -1.f, 0.f);
CDECL const Vector3f g_axis_X(1.f, 0.f, 0.f);
CDECL const Vector3f g_axis_Y(0.f, 1.f, 0.f);
CDECL const Vector3f g_axis_Z(0.f, 0.f, 1.f);
[Edited by - 0v3rloader on April 17, 2007 9:56:23 AM]