Skip to content

Commit

Permalink
matrix_init_look_at: Handle corner cases better
Browse files Browse the repository at this point in the history
graphene_matrix_init_look_at() currently breaks badly in the case
where the given point is either the same as the eye, or in "up" direction
from the eye.

The exact definition of look_at() kinda breaks down in this situation,
but this is the behaviour three.js uses, and its better than nothing.
  • Loading branch information
alexlarsson authored and ebassi committed Jun 15, 2020
1 parent 2f1b44a commit e5f8e9c
Showing 1 changed file with 30 additions and 3 deletions.
33 changes: 30 additions & 3 deletions include/graphene-simd4x4f.h
Original file line number Diff line number Diff line change
Expand Up @@ -601,11 +601,38 @@ graphene_simd4x4f_init_look_at (graphene_simd4x4f_t *m,
graphene_simd4f_t center,
graphene_simd4f_t up)
{
const graphene_simd4f_t z_axis = graphene_simd4f_normalize3 (graphene_simd4f_sub (center, eye));
const graphene_simd4f_t x_axis = graphene_simd4f_normalize3 (graphene_simd4f_cross3 (z_axis, up));
const graphene_simd4f_t y_axis = graphene_simd4f_cross3 (x_axis, z_axis);
const graphene_simd4f_t direction = graphene_simd4f_sub (center, eye);
graphene_simd4f_t cross;
graphene_simd4f_t z_axis;
graphene_simd4f_t x_axis;
graphene_simd4f_t y_axis;
float eye_v[4];

if (graphene_simd4f_get_x (graphene_simd4f_dot3 (direction, direction)) < FLT_EPSILON)
/* eye and center are in the same position */
z_axis = graphene_simd4f_init (0, 0, 1, 0);
else
z_axis = graphene_simd4f_normalize3 (direction);

cross = graphene_simd4f_cross3 (z_axis, up);
if (graphene_simd4f_get_x (graphene_simd4f_dot3 (cross, cross)) < FLT_EPSILON)
{
graphene_simd4f_t tweak_z;

/* up and z_axis are parallel */
if (fabs (graphene_simd4f_get_z (up) - 1.0) < FLT_EPSILON)
tweak_z = graphene_simd4f_init (0.0001f, 0, 0, 0);
else
tweak_z = graphene_simd4f_init (0, 0, 0.0001f, 0);

z_axis = graphene_simd4f_add (z_axis, tweak_z);
z_axis = graphene_simd4f_normalize3 (z_axis);
cross = graphene_simd4f_cross3 (z_axis, up);
}

x_axis = graphene_simd4f_normalize3 (cross);
y_axis = graphene_simd4f_cross3 (x_axis, z_axis);

graphene_simd4f_dup_4f (eye, eye_v);

m->x = x_axis;
Expand Down

0 comments on commit e5f8e9c

Please sign in to comment.