summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTaekyun Kim <tkq.kim@samsung.com>2014-01-06 15:10:59 +0900
committerCedric BAIL <cedric.bail@samsung.com>2014-03-30 16:07:51 +0900
commitd70c3e0c556938d335487d8995a634eae9803eee (patch)
tree7f9aff61dcc120a9916b9cc193f52ae3d31e3af0
parent76e26af7400944acab4952ad68e1fadb63a49df7 (diff)
downloadefl-d70c3e0c556938d335487d8995a634eae9803eee.tar.gz
Evas: 3D: evas_3d_node_look_at_set() bug fix
-rw-r--r--src/lib/evas/canvas/evas_3d_node.c49
-rw-r--r--src/lib/evas/include/evas_3d_utils.h14
2 files changed, 56 insertions, 7 deletions
diff --git a/src/lib/evas/canvas/evas_3d_node.c b/src/lib/evas/canvas/evas_3d_node.c
index acbab4a6ab..90843ae216 100644
--- a/src/lib/evas/canvas/evas_3d_node.c
+++ b/src/lib/evas/canvas/evas_3d_node.c
@@ -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;
+
+ 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;
- w = 0.5 / 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;
- /* 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.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);
}
diff --git a/src/lib/evas/include/evas_3d_utils.h b/src/lib/evas/include/evas_3d_utils.h
index 196d3df5f5..92ae65a564 100644
--- a/src/lib/evas/include/evas_3d_utils.h
+++ b/src/lib/evas/include/evas_3d_utils.h
@@ -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;
+}