diff --git a/cogl/cogl-matrix.c b/cogl/cogl-matrix.c index 4ceece7d2..7941bb649 100644 --- a/cogl/cogl-matrix.c +++ b/cogl/cogl-matrix.c @@ -2051,3 +2051,65 @@ cogl_matrix_is_identity (const CoglMatrix *matrix) else return memcmp (matrix, identity, sizeof (float) * 16) == 0; } + +void +cogl_matrix_look_at (CoglMatrix *matrix, + float eye_position_x, + float eye_position_y, + float eye_position_z, + float object_x, + float object_y, + float object_z, + float world_up_x, + float world_up_y, + float world_up_z) +{ + CoglMatrix tmp; + CoglVector3 forward; + CoglVector3 side; + CoglVector3 up; + + /* Get a unit viewing direction vector */ + cogl_vector3_init (&forward, + object_x - eye_position_x, + object_y - eye_position_y, + object_z - eye_position_z); + cogl_vector3_normalize (&forward); + + cogl_vector3_init (&up, world_up_x, world_up_y, world_up_z); + + /* Take the sideways direction as being perpendicular to the viewing + * direction and the word up vector. */ + cogl_vector3_cross_product (&side, &forward, &up); + cogl_vector3_normalize (&side); + + /* Now we have unit sideways and forward-direction vectors calculate + * a new mutually perpendicular up vector. */ + cogl_vector3_cross_product (&up, &side, &forward); + + tmp.xx = side.x; + tmp.yx = side.y; + tmp.zx = side.z; + tmp.wx = 0; + + tmp.xy = up.x; + tmp.yy = up.y; + tmp.zy = up.z; + tmp.wy = 0; + + tmp.xz = -forward.x; + tmp.yz = -forward.y; + tmp.zz = -forward.z; + tmp.wz = 0; + + tmp.xw = 0; + tmp.yw = 0; + tmp.zw = 0; + tmp.ww = 1; + + cogl_matrix_translate (&tmp, -eye_position_x, -eye_position_y, -eye_position_z); + + tmp.flags = (MAT_FLAG_GENERAL_3D | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE); + + cogl_matrix_multiply (matrix, matrix, &tmp); +} diff --git a/cogl/cogl-matrix.h b/cogl/cogl-matrix.h index a2c238544..14e92a3bd 100644 --- a/cogl/cogl-matrix.h +++ b/cogl/cogl-matrix.h @@ -193,6 +193,62 @@ cogl_matrix_scale (CoglMatrix *matrix, float sy, float sz); +#define cogl_matrix_look_at cogl_matrix_look_at_EXP +/** + * cogl_matrix_look_at: + * @matrix: A 4x4 transformation matrix + * @eye_position_x: The X coordinate to look from + * @eye_position_y: The Y coordinate to look from + * @eye_position_z: The Z coordinate to look from + * @object_x: The X coordinate of the object to look at + * @object_y: The Y coordinate of the object to look at + * @object_z: The Z coordinate of the object to look at + * @world_up_x: The X component of the world's up direction vector + * @world_up_y: The Y component of the world's up direction vector + * @world_up_z: The Z component of the world's up direction vector + * + * Applies a view transform @matrix that positions the camera at + * the coordinate (@eye_position_x, @eye_position_y, @eye_position_z) + * looking towards an object at the coordinate (@object_x, @object_y, + * @object_z). The top of the camera is aligned to the given world up + * vector, which is normally simply (0, 1, 0) to map up to the + * positive direction of the y axis. + * + * Because there is a lot of missleading documentation online for + * gluLookAt regarding the up vector we want to try and be a bit + * clearer here. + * + * The up vector should simply be relative to your world coordinates + * and does not need to change as you move the eye and object + * positions. Many online sources may claim that the up vector needs + * to be perpendicular to the vector between the eye and object + * position (partly because the man page is somewhat missleading) but + * that is not necessary for this function. + * + * You should never look directly along the world-up + * vector. + * + * It is assumed you are using a typical projection matrix where + * your origin maps to the center of your viewport. + * + * Almost always when you use this function it should be the first + * transform applied to a new modelview transform + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_matrix_look_at (CoglMatrix *matrix, + float eye_position_x, + float eye_position_y, + float eye_position_z, + float object_x, + float object_y, + float object_z, + float world_up_x, + float world_up_y, + float world_up_z); + /** * cogl_matrix_frustum: * @matrix: A 4x4 transformation matrix diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt index 6c0809c69..35f4d63ef 100644 --- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt +++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt @@ -424,6 +424,7 @@ cogl_matrix_free cogl_matrix_frustum cogl_matrix_ortho cogl_matrix_perspective +cogl_matrix_look_at cogl_matrix_multiply cogl_matrix_rotate cogl_matrix_translate