What's wrong with this turn to face algorithm?
Posted
by
Chan
on Game Development
See other posts from Game Development
or by Chan
Published on 2012-11-04T02:11:58Z
Indexed on
2012/11/04
5:24 UTC
Read the original article
Hit count: 340
I implement a torpedo object that chases a rotating planet. Specifically, it will turn toward the planet each update. Initially my implement was:
void move() {
vector3<float> to_target = target - get_position();
to_target.normalize();
position += (to_target * speed);
}
which works perfectly for torpedo that is a solid sphere. Now my torpedo is actually a model, which has a forward vector, so using this method looks odd because it doesn't actually turn toward but jump toward. So I revised it a bit to get,
double get_rotation_angle(vector3<float> u, vector3<float> v) const {
u.normalize();
v.normalize();
double cosine_theta = u.dot(v);
// domain of arccosine is [-1, 1]
if (cosine_theta > 1) {
cosine_theta = 1;
}
if (cosine_theta < -1) {
cosine_theta = -1;
}
return math3d::to_degree(acos(cosine_theta));
}
vector3<float> get_rotation_axis(vector3<float> u, vector3<float> v) const {
u.normalize();
v.normalize();
// fix linear case
if (u == v || u == -v) {
v[0] += 0.05;
v[1] += 0.0;
v[2] += 0.05;
v.normalize();
}
vector3<float> axis = u.cross(v);
return axis.normal();
}
void turn_to_face() {
vector3<float> to_target = (target - position);
vector3<float> axis = get_rotation_axis(get_forward(), to_target);
double angle = get_rotation_angle(get_forward(), to_target);
double distance = math3d::distance(position, target);
gl_matrix_mode(GL_MODELVIEW);
gl_push_matrix(); {
gl_load_identity();
gl_translate_f(position.get_x(), position.get_y(), position.get_z());
gl_rotate_f(angle, axis.get_x(), axis.get_y(), axis.get_z());
gl_get_float_v(GL_MODELVIEW_MATRIX, OM);
} gl_pop_matrix();
move();
}
void move() {
vector3<float> to_target = target - get_position();
to_target.normalize();
position += (get_forward() * speed);
}
The logic is simple, I find the rotation axis by cross product, the angle to rotate by dot product, then turn toward the target position each update. Unfortunately, it looks extremely odds since the rotation happens too fast that it always turns back and forth. The forward vector for torpedo is from the ModelView
matrix, the third column A
:
MODELVIEW MATRIX
--------------------------------------------------
R U A T
--------------------------------------------------
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
--------------------------------------------------
Any suggestion or idea would be greatly appreciated.
© Game Development or respective owner