Evas: 3D: evas_3d_node_look_at_set() bug fix

This commit is contained in:
Taekyun Kim 2014-01-06 15:10:59 +09:00 committed by ChunEon Park
parent 44a9f924ee
commit fc6cdaaa9d
2 changed files with 56 additions and 7 deletions

View File

@ -965,16 +965,51 @@ evas_3d_node_look_at_set(Evas_3D_Node *node,
evas_vec3_cross_product(&y, &z, &x);
evas_vec3_normalize(&y, &y);
Evas_Real w = sqrt(1.0 + x.x + y.y + z.z);
/* Below matrix to quaternion conversion code taken from
* http://fabiensanglard.net/doom3_documentation/37726-293748.pdf
* When any license issue occurs, use ken shoemake's algorithm instead.
*/
node->orientation.w = 0.5 * w;
if (x.x + y.y + z.z > 0.0)
{
Evas_Real t = x.x + y.y + z.z + 1.0;
Evas_Real s = evas_reciprocal_sqrt(t) * 0.5;
w = 0.5 / w;
node->orientation.w = s * t;
node->orientation.z = (x.y - y.x) * s;
node->orientation.y = (z.x - x.z) * s;
node->orientation.x = (y.z - z.y) * s;
}
else if (x.x > y.y && x.x > z.z)
{
Evas_Real t = x.x - y.y - z.z + 1.0;
Evas_Real s = evas_reciprocal_sqrt(t) * 0.5;
/* Inverse the axis. */
node->orientation.x = (y.z - z.y) * w;
node->orientation.y = (z.x - x.z) * w;
node->orientation.z = (x.y - y.x) * w;
node->orientation.x = s * t;
node->orientation.y = (x.y + y.x) * s;
node->orientation.z = (z.x + x.z) * s;
node->orientation.w = (y.z - z.y) * s;
}
else if (y.y > z.z)
{
Evas_Real t = -x.x + y.y - z.z + 1.0;
Evas_Real s = evas_reciprocal_sqrt(t) * 0.5;
node->orientation.y = s * t;
node->orientation.x = (x.y + y.x) * s;
node->orientation.w = (z.x - x.z) * s;
node->orientation.z = (y.z + z.y) * s;
}
else
{
Evas_Real t = -x.x - y.y + z.z + 1.0;
Evas_Real s = evas_reciprocal_sqrt(t) * 0.5;
node->orientation.z = s * t;
node->orientation.w = (x.y - y.x) * s;
node->orientation.x = (z.x + x.z) * s;
node->orientation.y = (y.z + z.y) * s;
}
evas_3d_object_change(&node->base, EVAS_3D_STATE_NODE_TRANSFORM, NULL);
}

View File

@ -1524,3 +1524,17 @@ evas_box3_ray3_intersect(const Evas_Box3 *box EINA_UNUSED, const Evas_Ray3 *ray
/* TODO: */
return EINA_TRUE;
}
static inline Evas_Real
evas_reciprocal_sqrt(Evas_Real x)
{
long i;
float y, r;
y = x * 0.5f;
i = *(long *)(&x);
i = 0x5f3759df - (i >> 1);
r = *(float *)(&i);
r = r * (1.5f - r * r * y);
return r;
}