cedric pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=82504d9d77f761f2575f63095459011eba02a594
commit 82504d9d77f761f2575f63095459011eba02a594 Author: se.osadchy <se.osad...@samsung.com> Date: Mon Dec 7 16:12:56 2015 -0800 evas: recognize duplicated data structure with eina_quternion and ector. Summary: Move data structure and functionality to eina_quaternion from evas_vec4. Reviewers: raster, Hermet, cedric Subscribers: jpeg, Oleksander Differential Revision: https://phab.enlightenment.org/D3327 Signed-off-by: Cedric BAIL <ced...@osg.samsung.com> --- src/lib/eina/eina_quaternion.c | 121 ++++++++ src/lib/eina/eina_quaternion.h | 124 +++++++++ src/lib/evas/#Evas_# | 1 + src/lib/evas/canvas/evas_canvas3d_camera.c | 2 +- src/lib/evas/canvas/evas_canvas3d_node.c | 12 +- src/lib/evas/include/evas_3d_utils.h | 355 ++++-------------------- src/lib/evas/include/evas_private.h | 4 +- src/modules/evas/engines/gl_common/evas_gl_3d.c | 4 +- src/tests/eina/eina_test_quaternion.c | 43 +++ src/tests/evas/evas_test_matrix.c | 4 +- 10 files changed, 354 insertions(+), 316 deletions(-) diff --git a/src/lib/eina/eina_quaternion.c b/src/lib/eina/eina_quaternion.c index 3c26845..73649c0 100644 --- a/src/lib/eina/eina_quaternion.c +++ b/src/lib/eina/eina_quaternion.c @@ -984,3 +984,124 @@ eina_quaternion_matrix4_to(Eina_Matrix4 *m, m->wz = tmp.wz; m->ww = tmp.ww; } + +EAPI void +eina_quaternion_inverse(Eina_Quaternion *out, const Eina_Quaternion *q) +{ + double norm = (q->x * q->x) + (q->y * q->y) + (q->z * q->z) + (q->w * q->w); + + if (norm > 0.0) + { + double inv_norm = 1.0 / norm; + out->x = -q->x * inv_norm; + out->y = -q->y * inv_norm; + out->z = -q->z * inv_norm; + out->w = q->w * inv_norm; + } + else + { + out->x = 0.0; + out->y = 0.0; + out->z = 0.0; + out->w = 0.0; + } +} + +EAPI void +eina_quaternion_array_set(Eina_Quaternion *dst, const double *v) +{ + dst->x = v[0]; + dst->y = v[1]; + dst->z = v[2]; + dst->w = v[3]; +} + +EAPI void +eina_quaternion_copy(Eina_Quaternion *dst, const Eina_Quaternion *src) +{ + dst->x = src->x; + dst->y = src->y; + dst->z = src->z; + dst->w = src->w; +} + +EAPI void +eina_quaternion_homogeneous_regulate(Eina_Quaternion *out, const Eina_Quaternion *v) +{ + if (v->w != 0.0) + { + double scale = 1.0 / v->w; + + out->x = v->x * scale; + out->y = v->y * scale; + out->z = v->z * scale; + out->w = 1.0; + } +} + +EAPI void +eina_quaternion_subtract(Eina_Quaternion *out, const Eina_Quaternion *a, const Eina_Quaternion *b) +{ + out->x = a->x - b->x; + out->y = a->y - b->y; + out->z = a->z - b->z; + out->w = a->w - b->w; +} + +EAPI double +eina_quaternion_length_get(const Eina_Quaternion *v) +{ + return (double)sqrt((double)((v->x * v->x) + (v->y * v->y) + + (v->z * v->z) + (v->w * v->w))); +} + +EAPI double +eina_quaternion_length_square_get(const Eina_Quaternion *v) +{ + return (v->x * v->x) + (v->y * v->y) + (v->z * v->z) + (v->w * v->w); +} + +EAPI double +eina_quaternion_distance_get(const Eina_Quaternion *a, const Eina_Quaternion *b) +{ + Eina_Quaternion v; + + eina_quaternion_subtract(&v, a, b); + return eina_quaternion_length_get(&v); +} + +EAPI double +eina_quaternion_distance_square_get(const Eina_Quaternion *a, const Eina_Quaternion *b) +{ + Eina_Quaternion v; + + eina_quaternion_subtract(&v, a, b); + return eina_quaternion_length_square_get(&v); +} + +EAPI void +eina_quaternion_transform(Eina_Quaternion *out, const Eina_Quaternion *v, const Eina_Matrix4 *m) +{ + Eina_Quaternion tmp; + + if (eina_matrix4_type_get(m) & EINA_MATRIX_TYPE_IDENTITY) + { + eina_quaternion_copy(out, v); + return; + } + + tmp.x = (m->xx * v->x) + (m->yx * v->y) + (m->zx * v->z) + (m->wx * v->w); + tmp.y = (m->xy * v->x) + (m->yy * v->y) + (m->zy * v->z) + (m->wy * v->w); + tmp.z = (m->xz * v->x) + (m->yz * v->y) + (m->zz * v->z) + (m->wz * v->w); + tmp.w = (m->xw * v->x) + (m->yw * v->y) + (m->zw * v->z) + (m->ww * v->w); + + eina_quaternion_copy(out, &tmp); +} + +EAPI double +eina_quaternion_angle_plains(Eina_Quaternion *a, Eina_Quaternion *b) +{ + return (double) ((a->x * b->x) + (a->y * b->y) + (a->z * b->z)) / ((sqrt((a->x * a->x) + + (a->y * a->y) + (a->z * a->z))) * (sqrt((b->x * b->x) + (b->y * b->y) + + (b->z * b->z)))); +} diff --git a/src/lib/eina/eina_quaternion.h b/src/lib/eina/eina_quaternion.h index df66589..9606036 100644 --- a/src/lib/eina/eina_quaternion.h +++ b/src/lib/eina/eina_quaternion.h @@ -141,5 +141,129 @@ EAPI void eina_quaternion_matrix4_to(Eina_Matrix4 *m, const Eina_Point_3D *translation, const Eina_Point_3D *scale, const Eina_Point_3D *skew); /**< @since 1.16 */ +/** + * @brief Compute the inverse of the given quaternion. + * + * @param out The quaternion to inverse. + * @param q The quaternion matrix. + * + * This function inverse the quaternion @p q and stores the result in + * @p out. + * + * @since 1.17 + */ +EAPI void eina_quaternion_inverse(Eina_Quaternion *out, const Eina_Quaternion *q); + +/** + * @brief Set array to quaternion. + * + * @param dst The result quaternion + * @param v The the array[4] for set + * + * Set to quaternion first 4 elements from array + * + * @since 1.17 + */ +EAPI void eina_quaternion_array_set(Eina_Quaternion *dst, const double *v); + +/** + * @brief Copy quternion. + * + * @param dst The quaternion copy + * @param src The quaternion for copy. + * + * @since 1.17 + */ +EAPI void eina_quaternion_copy(Eina_Quaternion *dst, + const Eina_Quaternion *src); + +/** + * @brief Homogeneous quaternion + * + * @param out The resulting quaternion + * @param v The given quaternion + * + * @since 1.17 + */ +EAPI void eina_quaternion_homogeneous_regulate(Eina_Quaternion *out, + const Eina_Quaternion *v); + +/** + * @brief Subtract two quaternions + * + * @param out The resulting quaternion + * @param a The first member of the subtract + * @param b The second member of the subtract + * + * @since 1.17 + */ +EAPI void eina_quaternion_subtract(Eina_Quaternion *out, const Eina_Quaternion *a, + const Eina_Quaternion *b); + +/** + * @brief Return the length of the given quaternion. + * + * @param v The quaternion. + * @return The length. + * + * @since 1.17 + */ +EAPI double eina_quaternion_length_get(const Eina_Quaternion *v); + +/** + * @brief Return the length in square of the given quaternion. + * + * @param v The quaternion. + * @return The length in square. + * + * @since 1.17 + */ +EAPI double eina_quaternion_length_square_get(const Eina_Quaternion *v); + +/** + * @brief Return the distance between of two quaternions. + * + * @param a The first quaternion. + * @param b The second quaternion. + * @return The distance. + * + * @since 1.17 + */ +EAPI double eina_quaternion_distance_get(const Eina_Quaternion *a, + const Eina_Quaternion *b); +/** + * @brief Return the distance in square between of two quaternions. + * + * @param a The first quaternion. + * @param b The second quaternion. + * @return The distance in square. + * + * @since 1.17 + */ +EAPI double eina_quaternion_distance_square_get(const Eina_Quaternion *a, + const Eina_Quaternion *b); + +/** + * @brief Transform quaternion. + * + * @param out The result quaternion. + * @param v The quaternion for transform. + * @param m The matrix for transform. + * + * @since 1.17 + */ +EAPI void eina_quaternion_transform(Eina_Quaternion *out, const Eina_Quaternion *v, + const Eina_Matrix4 *m); + +/** + * @brief Return the angle plains between of two quaternions. + * + * @param a The first quaternion. + * @param b The second quaternion. + * @return The angle. + * + * @since 1.17 + */ +EAPI double eina_quaternion_angle_plains(Eina_Quaternion *a, Eina_Quaternion *b); #endif diff --git a/src/lib/evas/#Evas_# b/src/lib/evas/#Evas_# new file mode 100644 index 0000000..96d80cd --- /dev/null +++ b/src/lib/evas/#Evas_# @@ -0,0 +1 @@ +C \ No newline at end of file diff --git a/src/lib/evas/canvas/evas_canvas3d_camera.c b/src/lib/evas/canvas/evas_canvas3d_camera.c index ffec051..9f874e2 100644 --- a/src/lib/evas/canvas/evas_canvas3d_camera.c +++ b/src/lib/evas/canvas/evas_canvas3d_camera.c @@ -160,7 +160,7 @@ EOLIAN static Eina_Bool _evas_canvas3d_camera_node_visible_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Camera_Data *pd, Evas_Canvas3D_Node *camera_node, Evas_Canvas3D_Node *node, Evas_Canvas3D_Frustum_Mode key) { Eina_Matrix4 matrix_vp; - Evas_Vec4 planes[6]; + Eina_Quaternion planes[6]; Evas_Canvas3D_Node_Data *pd_node = eo_data_scope_get(node, EVAS_CANVAS3D_NODE_CLASS); Evas_Canvas3D_Node_Data *pd_camera = eo_data_scope_get(camera_node, EVAS_CANVAS3D_NODE_CLASS); Evas_Vec3 central_point; diff --git a/src/lib/evas/canvas/evas_canvas3d_node.c b/src/lib/evas/canvas/evas_canvas3d_node.c index cbfbb84..4f0c02e 100644 --- a/src/lib/evas/canvas/evas_canvas3d_node.c +++ b/src/lib/evas/canvas/evas_canvas3d_node.c @@ -241,13 +241,13 @@ _node_transform_update(Evas_Canvas3D_Node *node, void *data EINA_UNUSED) { Evas_Canvas3D_Node_Data *pdparent = eo_data_scope_get(pd->parent, MY_CLASS); const Evas_Vec3 *scale_parent = &pdparent->scale_world; - const Evas_Vec4 *orientation_parent = &pdparent->orientation_world; + const Eina_Quaternion *orientation_parent = &pdparent->orientation_world; /* Orienatation */ if (pd->orientation_inherit) { - evas_vec4_quaternion_multiply(&pd->orientation_world, - orientation_parent, &pd->orientation); + eina_quaternion_mul(&pd->orientation_world, + orientation_parent, &pd->orientation); } else { @@ -383,7 +383,7 @@ _node_item_update(Evas_Canvas3D_Node *node, void *data EINA_UNUSED) } static void -_rotate_vertices(Evas_Vec4* orientation, int vertex_count, Evas_Vec3* vertex_position) +_rotate_vertices(Eina_Quaternion* orientation, int vertex_count, Evas_Vec3* vertex_position) { int i; if (orientation->x || orientation->y || orientation->z) @@ -1148,11 +1148,11 @@ _evas_canvas3d_node_constructor(Eo *obj, Evas_Canvas3D_Node_Data *pd, Evas_Canva eo_do(obj, evas_canvas3d_object_type_set(EVAS_CANVAS3D_OBJECT_TYPE_NODE)); evas_vec3_set(&pd->position, 0.0, 0.0, 0.0); - evas_vec4_set(&pd->orientation, 0.0, 0.0, 0.0, 1.0); + eina_quaternion_set(&pd->orientation, 0.0, 0.0, 0.0, 1.0); evas_vec3_set(&pd->scale, 1.0, 1.0, 1.0); evas_vec3_set(&pd->position_world, 0.0, 0.0, 0.0); - evas_vec4_set(&pd->orientation_world, 0.0, 0.0, 0.0, 1.0); + eina_quaternion_set(&pd->orientation_world, 0.0, 0.0, 0.0, 1.0); evas_vec3_set(&pd->scale_world, 1.0, 1.0, 1.0); pd->position_inherit = EINA_TRUE; diff --git a/src/lib/evas/include/evas_3d_utils.h b/src/lib/evas/include/evas_3d_utils.h index f3d4ed0..319c599 100644 --- a/src/lib/evas/include/evas_3d_utils.h +++ b/src/lib/evas/include/evas_3d_utils.h @@ -15,7 +15,6 @@ typedef struct _Evas_Color Evas_Color; typedef struct _Evas_Vec2 Evas_Vec2; typedef struct _Evas_Vec3 Evas_Vec3; -typedef struct _Evas_Vec4 Evas_Vec4; typedef struct _Evas_Box2 Evas_Box2; typedef struct _Evas_Box3 Evas_Box3; typedef struct _Evas_Line3 Evas_Line3; @@ -44,14 +43,6 @@ struct _Evas_Vec3 Evas_Real z; }; -struct _Evas_Vec4 -{ - Evas_Real x; - Evas_Real y; - Evas_Real z; - Evas_Real w; -}; - struct _Evas_Box2 { Evas_Vec2 p0; @@ -400,7 +391,7 @@ evas_vec3_homogeneous_direction_transform(Evas_Vec3 *out, const Evas_Vec3 *v, co } static inline void -evas_vec3_quaternion_rotate(Evas_Vec3 *out, const Evas_Vec3 *v, const Evas_Vec4 *q) +evas_vec3_quaternion_rotate(Evas_Vec3 *out, const Evas_Vec3 *v, const Eina_Quaternion *q) { Evas_Vec3 uv, uuv; Evas_Vec3 axis; @@ -434,152 +425,8 @@ evas_vec3_orthogonal_projection_on_plain(Evas_Vec3 *out, const Evas_Vec3 *v, con return; } -/* 4D vector */ -static inline void -evas_vec4_set(Evas_Vec4 *dst, Evas_Real x, Evas_Real y, Evas_Real z, Evas_Real w) -{ - dst->x = x; - dst->y = y; - dst->z = z; - dst->w = w; -} - -static inline void -evas_vec4_array_set(Evas_Vec4 *dst, const Evas_Real *v) -{ - dst->x = v[0]; - dst->y = v[1]; - dst->z = v[2]; - dst->w = v[3]; -} - -static inline void -evas_vec4_copy(Evas_Vec4 *dst, const Evas_Vec4 *src) -{ - dst->x = src->x; - dst->y = src->y; - dst->z = src->z; - dst->w = src->w; -} - -static inline void -evas_vec4_homogeneous_regulate(Evas_Vec4 *out, const Evas_Vec4 *v) -{ - if (v->w != 0.0) - { - Evas_Real scale = 1.0 / v->w; - - out->x = v->x * scale; - out->y = v->y * scale; - out->z = v->z * scale; - out->w = 1.0; - } -} - -static inline void -evas_vec4_negate(Evas_Vec4 *out, const Evas_Vec4 *v) -{ - out->x = -v->x; - out->y = -v->y; - out->z = -v->z; - out->w = -v->w; -} - static inline void -evas_vec4_add(Evas_Vec4 *out, const Evas_Vec4 *a, const Evas_Vec4 *b) -{ - out->x = a->x + b->x; - out->y = a->y + b->y; - out->z = a->z + b->z; - out->w = a->w + b->w; -} - -static inline void -evas_vec4_subtract(Evas_Vec4 *out, const Evas_Vec4 *a, const Evas_Vec4 *b) -{ - out->x = a->x - b->x; - out->y = a->y - b->y; - out->z = a->z - b->z; - out->w = a->w - b->w; -} - -static inline void -evas_vec4_scale(Evas_Vec4 *out, const Evas_Vec4 *v, Evas_Real scale) -{ - out->x = scale * v->x; - out->y = scale * v->y; - out->z = scale * v->z; - out->w = scale * v->w; -} - -static inline void -evas_vec4_multiply(Evas_Vec4 *out, const Evas_Vec4 *a, const Evas_Vec4 *b) -{ - out->x = a->x * b->x; - out->y = a->y * b->y; - out->z = a->z * b->z; - out->w = a->w * b->w; -} - -static inline Evas_Real -evas_vec4_length_get(const Evas_Vec4 *v) -{ - return (Evas_Real)sqrt((double)((v->x * v->x) + (v->y * v->y) + - (v->z * v->z) + (v->w + v->w))); -} - -static inline Evas_Real -evas_vec4_length_square_get(const Evas_Vec4 *v) -{ - return (v->x * v->x) + (v->y * v->y) + (v->z * v->z) + (v->w * v->w); -} - -static inline Evas_Real -evas_vec4_distance_get(const Evas_Vec4 *a, const Evas_Vec4 *b) -{ - Evas_Vec4 v; - - evas_vec4_subtract(&v, a, b); - return evas_vec4_length_get(&v); -} - -static inline Evas_Real -evas_vec4_distance_square_get(const Evas_Vec4 *a, const Evas_Vec4 *b) -{ - Evas_Vec4 v; - - evas_vec4_subtract(&v, a, b); - return evas_vec4_length_square_get(&v); -} - -static inline void -evas_vec4_normalize(Evas_Vec4 *out, const Evas_Vec4 *v) -{ - /* Assume "v" is not a zero vector */ - evas_vec4_scale(out, v, 1.0 / evas_vec4_length_get(v)); -} - -static inline void -evas_vec4_transform(Evas_Vec4 *out, const Evas_Vec4 *v, const Eina_Matrix4 *m) -{ - Evas_Vec4 tmp; - - if (eina_matrix4_type_get(m) == EINA_MATRIX_TYPE_IDENTITY) - { - evas_vec4_copy(out, v); - return; - } - - tmp.x = (m->xx * v->x) + (m->yx * v->y) + (m->zx * v->z) + (m->wx * v->w); - tmp.y = (m->xy * v->x) + (m->yy * v->y) + (m->zy * v->z) + (m->wy * v->w); - tmp.z = (m->xz * v->x) + (m->yz * v->y) + (m->zz * v->z) + (m->wz * v->w); - tmp.w = (m->xw * v->x) + (m->yw * v->y) + (m->zw * v->z) + (m->ww * v->w); - - evas_vec4_copy(out, &tmp); -} - -static inline void -evas_vec4_plain_by_points(Evas_Vec4 *out, const Evas_Vec3 *a, const Evas_Vec3 *b, const Evas_Vec3 *c) +evas_vec3_plain_by_points(Eina_Quaternion *out, const Evas_Vec3 *a, const Evas_Vec3 *b, const Evas_Vec3 *c) { out->x = (b->y - a->y) * (c->z - a->z) - (b->z - a->z) * (c->y - a->y); out->y = -(b->x - a->x) * (c->z - a->z) + (b->z - a->z) * (c->x - a->x); @@ -589,16 +436,8 @@ evas_vec4_plain_by_points(Evas_Vec4 *out, const Evas_Vec3 *a, const Evas_Vec3 *b (-a->z) * ((b->x - a->x) * (c->y - a->y) - (b->y - a->y) * (c->x - a->x)); } -static inline Evas_Real -evas_vec4_angle_plains(Evas_Vec4 *a, Evas_Vec4 *b) -{ - return (Evas_Real) ((a->x * b->x) + (a->y * b->y) + (a->z * b->z)) / ((sqrt((a->x * a->x) + - (a->y * a->y) + (a->z * a->z))) * (sqrt((b->x * b->x) + (b->y * b->y) + - (b->z * b->z)))); -} - static inline void -evas_vec3_homogeneous_position_set(Evas_Vec3 *out, const Evas_Vec4 *v) +evas_vec3_homogeneous_position_set(Evas_Vec3 *out, const Eina_Quaternion *v) { /* Assume "v" is a positional vector. (v->w != 0.0) */ Evas_Real h = 1.0 / v->w; @@ -609,7 +448,7 @@ evas_vec3_homogeneous_position_set(Evas_Vec3 *out, const Evas_Vec4 *v) } static inline void -evas_vec3_homogeneous_direction_set(Evas_Vec3 *out, const Evas_Vec4 *v) +evas_vec3_homogeneous_direction_set(Evas_Vec3 *out, const Eina_Quaternion *v) { /* Assume "v" is a directional vector. (v->w == 0.0) */ out->x = v->x; @@ -707,24 +546,6 @@ evas_triangle3_if_equivalent(Evas_Triangle3 *a, Evas_Triangle3 *b) } static inline void -evas_vec4_homogeneous_position_set(Evas_Vec4 *out, const Evas_Vec3 *v) -{ - out->x = v->x; - out->y = v->y; - out->z = v->z; - out->w = 1.0; -} - -static inline void -evas_vec4_homogeneous_direction_set(Evas_Vec4 *out, const Evas_Vec3 *v) -{ - out->x = v->x; - out->y = v->y; - out->z = v->z; - out->w = 0.0; -} - -static inline void evas_mat4_look_at_set(Eina_Matrix4 *m, const Evas_Vec3 *pos, const Evas_Vec3 *center, const Evas_Vec3 *up) { @@ -841,16 +662,16 @@ evas_box3_transform(Evas_Box3 *out EINA_UNUSED, const Evas_Box3 *box EINA_UNUSED } static inline void -evas_mat4_position_get(const Eina_Matrix4 *matrix, Evas_Vec4 *position) +evas_mat4_position_get(const Eina_Matrix4 *matrix, Eina_Quaternion *position) { - Evas_Vec4 pos; + Eina_Quaternion pos; pos.x = 0.0; pos.y = 0.0; pos.z = 0.0; pos.w = 1.0; - evas_vec4_transform(position, &pos, matrix); + eina_quaternion_transform(position, &pos, matrix); } static inline void @@ -858,14 +679,14 @@ evas_mat4_direction_get(const Eina_Matrix4 *matrix, Evas_Vec3 *direction) { /* TODO: Check correctness. */ - Evas_Vec4 dir; + Eina_Quaternion dir; dir.x = 0.0; dir.y = 0.0; dir.z = 1.0; dir.w = 1.0; - evas_vec4_transform(&dir, &dir, matrix); + eina_quaternion_transform(&dir, &dir, matrix); direction->x = dir.x; direction->y = dir.y; @@ -873,84 +694,12 @@ evas_mat4_direction_get(const Eina_Matrix4 *matrix, Evas_Vec3 *direction) } static inline void -evas_vec4_quaternion_multiply(Evas_Vec4 *out, const Evas_Vec4 *a, const Evas_Vec4 *b) -{ - Evas_Vec4 r; - - r.x = (a->w * b->x) + (a->x * b->w) + (a->y * b->z) - (a->z * b->y); - r.y = (a->w * b->y) - (a->x * b->z) + (a->y * b->w) + (a->z * b->x); - r.z = (a->w * b->z) + (a->x * b->y) - (a->y * b->x) + (a->z * b->w); - r.w = (a->w * b->w) - (a->x * b->x) - (a->y * b->y) - (a->z * b->z); - - *out = r; -} - -static inline void -evas_vec4_quaternion_inverse(Evas_Vec4 *out, const Evas_Vec4 *q) -{ - Evas_Real norm = (q->x * q->x) + (q->y * q->y) + (q->z * q->z) + (q->w * q->w); - - if (norm > 0.0) - { - Evas_Real inv_norm = 1.0 / norm; - out->x = -q->x * inv_norm; - out->y = -q->y * inv_norm; - out->z = -q->z * inv_norm; - out->w = q->w * inv_norm; - } - else - { - out->x = 0.0; - out->y = 0.0; - out->z = 0.0; - out->w = 0.0; - } -} - -static inline void -evas_vec4_quaternion_rotation_matrix_get(const Evas_Vec4 *q, Eina_Matrix3 *mat) -{ - Evas_Real x, y, z; - Evas_Real xx, xy, xz; - Evas_Real yy, yz; - Evas_Real zz; - Evas_Real wx, wy, wz; - - x = 2.0 * q->x; - y = 2.0 * q->y; - z = 2.0 * q->z; - - xx = q->x * x; - xy = q->x * y; - xz = q->x * z; - - yy = q->y * y; - yz = q->y * z; - - zz = q->z * z; - - wx = q->w * x; - wy = q->w * y; - wz = q->w * z; - - mat->xx = 1.0 - yy - zz; - mat->xy = xy + wz; - mat->xz = xz - wy; - mat->yx = xy - wz; - mat->yy = 1.0 - xx - zz; - mat->yz = yz + wx; - mat->zx = xz + wy; - mat->zy = yz - wx; - mat->zz = 1.0 - xx - yy; -} - -static inline void evas_mat4_build(Eina_Matrix4 *out, - const Evas_Vec3 *position, const Evas_Vec4 *orientation, const Evas_Vec3 *scale) + const Evas_Vec3 *position, const Eina_Quaternion *orientation, const Evas_Vec3 *scale) { Eina_Matrix3 rot; - evas_vec4_quaternion_rotation_matrix_get(orientation, &rot); + eina_quaternion_rotation_matrix3_get(&rot, orientation); out->xx = scale->x * rot.xx; out->xy = scale->x * rot.xy; @@ -975,9 +724,9 @@ evas_mat4_build(Eina_Matrix4 *out, static inline void evas_mat4_inverse_build(Eina_Matrix4 *out, const Evas_Vec3 *position, - const Evas_Vec4 *orientation, const Evas_Vec3 *scale) + const Eina_Quaternion *orientation, const Evas_Vec3 *scale) { - Evas_Vec4 inv_rotation; + Eina_Quaternion inv_rotation; Evas_Vec3 inv_scale; Evas_Vec3 inv_translate; @@ -987,7 +736,7 @@ evas_mat4_inverse_build(Eina_Matrix4 *out, const Evas_Vec3 *position, evas_vec3_set(&inv_scale, 1.0 / scale->x, 1.0 / scale->y, 1.0 / scale->z); /* Inverse rotation. */ - evas_vec4_quaternion_inverse(&inv_rotation, orientation); + eina_quaternion_inverse(&inv_rotation, orientation); /* Inverse translation. */ evas_vec3_negate(&inv_translate, position); @@ -995,7 +744,7 @@ evas_mat4_inverse_build(Eina_Matrix4 *out, const Evas_Vec3 *position, evas_vec3_multiply(&inv_translate, &inv_translate, &inv_scale); /* Get 3x3 rotation matrix. */ - evas_vec4_quaternion_rotation_matrix_get(&inv_rotation, &rot); + eina_quaternion_rotation_matrix3_get(&rot, &inv_rotation); out->xx = inv_scale.x * rot.xx; out->xy = inv_scale.x * rot.xy; @@ -1040,7 +789,7 @@ static inline void evas_ray3_init(Evas_Ray3 *ray, Evas_Real x, Evas_Real y, const Eina_Matrix4 *mvp) { Eina_Matrix4 mat; - Evas_Vec4 dnear, dfar; + Eina_Quaternion dnear, dfar; memset(&mat, 0, sizeof (mat)); @@ -1054,7 +803,7 @@ evas_ray3_init(Evas_Ray3 *ray, Evas_Real x, Evas_Real y, const Eina_Matrix4 *mvp dnear.z = -1.0; dnear.w = 1.0; - evas_vec4_transform(&dnear, &dnear, &mat); + eina_quaternion_transform(&dnear, &dnear, &mat); dnear.w = 1.0 / dnear.w; dnear.x *= dnear.w; @@ -1069,7 +818,7 @@ evas_ray3_init(Evas_Ray3 *ray, Evas_Real x, Evas_Real y, const Eina_Matrix4 *mvp dfar.z = 1.0; dfar.w = 1.0; - evas_vec4_transform(&dfar, &dfar, &mat); + eina_quaternion_transform(&dfar, &dfar, &mat); dfar.w = 1.0 / dfar.w; dfar.x *= dfar.w; @@ -1297,7 +1046,7 @@ evas_sphere_empty_set(Evas_Sphere *dst) } static inline void -evas_plane_normalize(Evas_Vec4 *plane) +evas_plane_normalize(Eina_Quaternion *plane) { Evas_Vec3 tmp; Evas_Real length; @@ -1310,7 +1059,7 @@ evas_plane_normalize(Evas_Vec4 *plane) } static inline Eina_Bool -evas_intersection_line_of_two_planes(Evas_Line3 *line, Evas_Vec4 *plane1, Evas_Vec4 *plane2) +evas_intersection_line_of_two_planes(Evas_Line3 *line, Eina_Quaternion *plane1, Eina_Quaternion *plane2) { //TODO:parallel case Evas_Vec3 planes3D[2]; @@ -1343,13 +1092,13 @@ evas_intersection_line_of_two_planes(Evas_Line3 *line, Evas_Vec4 *plane1, Evas_V } static inline Eina_Bool -evas_intersection_point_of_three_planes(Evas_Vec3 *point, Evas_Vec4 *plane1, Evas_Vec4 *plane2, Evas_Vec4 *plane3) +evas_intersection_point_of_three_planes(Evas_Vec3 *point, Eina_Quaternion *plane1, Eina_Quaternion *plane2, Eina_Quaternion *plane3) { //TODO:parallel case int i; Evas_Real delta, deltax, deltay, deltaz; Evas_Real matrix_to_det[3][3]; - Evas_Vec4 planes[3]; + Eina_Quaternion planes[3]; planes[0] = *plane1; planes[1] = *plane2; @@ -1387,7 +1136,7 @@ evas_intersection_point_of_three_planes(Evas_Vec3 *point, Evas_Vec4 *plane1, Eva } static inline Evas_Real -evas_point_plane_distance(Evas_Vec3 *point, Evas_Vec4 *plane) +evas_point_plane_distance(Evas_Vec3 *point, Eina_Quaternion *plane) { return plane->x * point->x + plane->y * point->y + plane->z * point->z + plane->w; } @@ -1404,7 +1153,7 @@ evas_point_line_distance(Evas_Vec3 *point, Evas_Line3 *line) } static inline Eina_Bool -evas_is_sphere_in_frustum(Evas_Sphere *bsphere, Evas_Vec4 *planes) +evas_is_sphere_in_frustum(Evas_Sphere *bsphere, Eina_Quaternion *planes) { int i; Evas_Line3 line; @@ -1450,7 +1199,7 @@ evas_is_sphere_in_frustum(Evas_Sphere *bsphere, Evas_Vec4 *planes) } static inline Eina_Bool -evas_is_point_in_frustum(Evas_Vec3 *point, Evas_Vec4 *planes) +evas_is_point_in_frustum(Evas_Vec3 *point, Eina_Quaternion *planes) { int i; for (i = 0; i < 6; i++) @@ -1459,7 +1208,7 @@ evas_is_point_in_frustum(Evas_Vec3 *point, Evas_Vec4 *planes) } static inline Eina_Bool -evas_is_box_in_frustum(Evas_Box3 *box, Evas_Vec4 *planes) +evas_is_box_in_frustum(Evas_Box3 *box, Eina_Quaternion *planes) { int i; for (i = 0; i < 6; i++) @@ -1487,31 +1236,31 @@ evas_is_box_in_frustum(Evas_Box3 *box, Evas_Vec4 *planes) } static inline void -evas_frustum_calculate(Evas_Vec4 *planes, Eina_Matrix4 *matrix_vp) +evas_frustum_calculate(Eina_Quaternion *planes, Eina_Matrix4 *matrix_vp) { int i; - evas_vec4_set(&planes[0], matrix_vp->xw - matrix_vp->xx, + eina_quaternion_set(&planes[0], matrix_vp->xw - matrix_vp->xx, matrix_vp->yw - matrix_vp->yx, matrix_vp->zw - matrix_vp->zx, matrix_vp->ww - matrix_vp->wx); - evas_vec4_set(&planes[1], matrix_vp->xw - matrix_vp->xx, + eina_quaternion_set(&planes[1], matrix_vp->xw - matrix_vp->xx, matrix_vp->yw - matrix_vp->yx, matrix_vp->zw - matrix_vp->zx, matrix_vp->ww - matrix_vp->wx); - evas_vec4_set(&planes[2], matrix_vp->xw - matrix_vp->xx, + eina_quaternion_set(&planes[2], matrix_vp->xw - matrix_vp->xx, matrix_vp->yw - matrix_vp->yx, matrix_vp->zw - matrix_vp->zx, matrix_vp->ww - matrix_vp->wx); - evas_vec4_set(&planes[3], matrix_vp->xw - matrix_vp->xx, + eina_quaternion_set(&planes[3], matrix_vp->xw - matrix_vp->xx, matrix_vp->yw - matrix_vp->yx, matrix_vp->zw - matrix_vp->zx, matrix_vp->ww - matrix_vp->wx); - evas_vec4_set(&planes[4], matrix_vp->xw - matrix_vp->xx, + eina_quaternion_set(&planes[4], matrix_vp->xw - matrix_vp->xx, matrix_vp->yw - matrix_vp->yx, matrix_vp->zw - matrix_vp->zx, matrix_vp->ww - matrix_vp->wx); - evas_vec4_set(&planes[5], matrix_vp->xw - matrix_vp->xx, + eina_quaternion_set(&planes[5], matrix_vp->xw - matrix_vp->xx, matrix_vp->yw - matrix_vp->yx, matrix_vp->zw - matrix_vp->zx, matrix_vp->ww - matrix_vp->wx); @@ -1618,7 +1367,7 @@ convex_hull_first_tr_get(float *data, int count, int stride) Evas_Vec3 triangle2, triangle2_candidate; Evas_Vec3 triangle3, triangle3_candidate; Evas_Vec3 first, second, complanar1, complanar2, candidate; - Evas_Vec4 normal_a, normal_b; + Eina_Quaternion normal_a, normal_b; Evas_Real cos = 0.0, new_cos = 0.0, tan = 0.0, new_tan = 0.0, cos_2d = 0.0, new_cos_2d = 0.0; int first_num = 0, second_num = 0; @@ -1715,10 +1464,10 @@ convex_hull_first_tr_get(float *data, int count, int stride) evas_vec3_set(&complanar1, triangle1.x + 1, triangle1.y, triangle1.z); evas_vec3_set(&complanar2, triangle1.x, triangle1.y + 1, triangle1.z); - evas_vec4_plain_by_points(&normal_a, &triangle1, &complanar1, &complanar2); + evas_vec3_plain_by_points(&normal_a, &triangle1, &complanar1, &complanar2); if (normal_a.z < 0) - evas_vec4_scale(&normal_a, &normal_a, -1); + eina_quaternion_scale(&normal_a, &normal_a, -1); evas_vec3_set(&triangle3, data[0], data[1], data[2]); @@ -1730,12 +1479,12 @@ convex_hull_first_tr_get(float *data, int count, int stride) if ((i != first_num) && (i != second_num)) { evas_vec3_set(&candidate, data[j], data[j + 1], data[j + 2]); - evas_vec4_plain_by_points(&normal_b, &triangle1, &candidate, &triangle2); + evas_vec3_plain_by_points(&normal_b, &triangle1, &candidate, &triangle2); if (normal_b.z < 0) - evas_vec4_scale(&normal_b, &normal_b, -1); + eina_quaternion_scale(&normal_b, &normal_b, -1); - new_cos = evas_vec4_angle_plains(&normal_a, &normal_b); + new_cos = eina_quaternion_angle_plains(&normal_a, &normal_b); if (new_cos > cos + FLT_EPSILON) { @@ -1772,7 +1521,7 @@ evas_convex_hull_get(float *data, int count, int stride, Eina_Inarray *vertex, Evas_Vec3 *next = NULL, *best = NULL, *next_2d = NULL, *el_vec3 = NULL; Evas_Vec3 tmp1, tmp2; - Evas_Vec4 normal_a, normal_b; + Eina_Quaternion normal_a, normal_b; Eina_Array arr_elems; Eina_Array arr_triangles; @@ -1842,8 +1591,8 @@ evas_convex_hull_get(float *data, int count, int stride, Eina_Inarray *vertex, /* something like the dihedral angle between the triangles is a determining factor in searching the necessary points */ - evas_vec4_plain_by_points(&normal_a, &elem->p0, &elem->p1, &elem->p2); - evas_vec4_plain_by_points(&normal_b, &elem->p0, &elem->p1, next); + evas_vec3_plain_by_points(&normal_a, &elem->p0, &elem->p1, &elem->p2); + evas_vec3_plain_by_points(&normal_b, &elem->p0, &elem->p1, next); /* MIN_DIFF because vertices that belong to plain shouldn't be included */ if (fabs(normal_a.x * data[j] + normal_a.y * data[j + 1] + normal_a.z * data[j + 2] + normal_a.w) < MIN_DIFF) @@ -1860,11 +1609,11 @@ evas_convex_hull_get(float *data, int count, int stride, Eina_Inarray *vertex, else { if (normal_a.x * data[j] + normal_a.y * data[j+1] + normal_a.z * data[j+2] + normal_a.w < 0) - evas_vec4_scale(&normal_a, &normal_a, -1); + eina_quaternion_scale(&normal_a, &normal_a, -1); if (normal_b.x * elem->p2.x + normal_b.y * elem->p2.y + normal_b.z * elem->p2.z + normal_b.w < 0) - evas_vec4_scale(&normal_b, &normal_b, -1); + eina_quaternion_scale(&normal_b, &normal_b, -1); - new_cos = evas_vec4_angle_plains(&normal_a, &normal_b); + new_cos = eina_quaternion_angle_plains(&normal_a, &normal_b); } /* MIN_DIFF is more useful for dihedral angles apparently */ @@ -1911,7 +1660,7 @@ evas_convex_hull_get(float *data, int count, int stride, Eina_Inarray *vertex, { Evas_Vec3 angle_from, angle_to; next_2d = eina_array_data_get(&arr_candidates, 0); - evas_vec4_plain_by_points(&normal_b, &elem->p1, &elem->p0, next_2d); + evas_vec3_plain_by_points(&normal_b, &elem->p1, &elem->p0, next_2d); if (normal_b.x * elem->p2.x + normal_b.y * elem->p2.y + normal_b.z * elem->p2.z + normal_b.w > 0) { @@ -1959,8 +1708,8 @@ evas_convex_hull_get(float *data, int count, int stride, Eina_Inarray *vertex, { evas_vec3_subtract(&angle_to, next_2d, &elem->p0); - evas_vec4_plain_by_points(&normal_a, &elem->p0, &elem->p1, &elem->p2); - evas_vec4_plain_by_points(&normal_b, &elem->p0, &elem->p1, next_2d); + evas_vec3_plain_by_points(&normal_a, &elem->p0, &elem->p1, &elem->p2); + evas_vec3_plain_by_points(&normal_b, &elem->p0, &elem->p1, next_2d); if ((normal_a.x * normal_b.x <= 0) && (normal_a.y * normal_b.y <= 0) && (normal_a.z * normal_b.z <= 0)) { new_cos = evas_vec3_dot_product(&angle_from, &angle_to) / @@ -1983,7 +1732,7 @@ evas_convex_hull_get(float *data, int count, int stride, Eina_Inarray *vertex, else best = eina_array_data_get(&arr_candidates, 0); - evas_vec4_plain_by_points(&normal_b, &elem->p0, &elem->p1, best); + evas_vec3_plain_by_points(&normal_b, &elem->p0, &elem->p1, best); if_two = 0; first_exist_twice = 0; @@ -2172,7 +1921,7 @@ evas_tangent_space_get(float *data, float *tex_data, float *normal_data, unsigne Evas_Triangle3 triangle; Evas_Vec2 tex1, tex2, tex3; Evas_Vec3 big_tangent, little_tangent, normal; - Evas_Vec4 *plain = NULL; + Eina_Quaternion *plain = NULL; int i, j, k, l, m, found_index = 0; int indexes[3]; @@ -2241,9 +1990,9 @@ evas_tangent_space_get(float *data, float *tex_data, float *normal_data, unsigne evas_vec3_set(&triangle.p2, data[indexes[2] * stride], data[indexes[2] * stride + 1], data[indexes[2] * stride + 2]); if (plain) free(plain); - plain = malloc(sizeof(Evas_Vec4)); + plain = malloc(sizeof(Eina_Quaternion)); - evas_vec4_plain_by_points(plain, &triangle.p0, &triangle.p1, &triangle.p2); + evas_vec3_plain_by_points(plain, &triangle.p0, &triangle.p1, &triangle.p2); tex1.x = tex_data[indexes[0] * tex_stride]; tex1.y = tex_data[indexes[0] * tex_stride + 1]; tex2.x = tex_data[indexes[1] * tex_stride]; diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 4bb7c75..5ef176f 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -248,11 +248,11 @@ struct _Evas_Canvas3D_Node Evas_Canvas3D_Node *billboard_target; Evas_Vec3 position; - Evas_Vec4 orientation; + Eina_Quaternion orientation; Evas_Vec3 scale; Evas_Vec3 position_world; - Evas_Vec4 orientation_world; + Eina_Quaternion orientation_world; Evas_Vec3 scale_world; Evas_Box3 aabb; diff --git a/src/modules/evas/engines/gl_common/evas_gl_3d.c b/src/modules/evas/engines/gl_common/evas_gl_3d.c index 4cb6887..798a3b5 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_3d.c +++ b/src/modules/evas/engines/gl_common/evas_gl_3d.c @@ -1180,7 +1180,7 @@ void _shadowmap_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_Canvas3D_Light_Data *pd = eo_data_scope_get(pd_light_node->data.light.light, EVAS_CANVAS3D_LIGHT_CLASS); - Evas_Vec4 planes[6]; + Eina_Quaternion planes[6]; eina_matrix4_multiply(&matrix_vp, &pd->projection, matrix_light_eye); evas_frustum_calculate(planes, &matrix_vp); @@ -1230,7 +1230,7 @@ _scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_Canvas3D_Scen Eina_Matrix4 matrix_light_eye, matrix_vp;; Evas_Canvas3D_Light_Data *ld = NULL; Evas_Canvas3D_Node_Data *pd_light_node; - Evas_Vec4 planes[6]; + Eina_Quaternion planes[6]; /* Get eye matrix. */ Evas_Canvas3D_Node_Data *pd_camera_node = eo_data_scope_get(data->camera_node, EVAS_CANVAS3D_NODE_CLASS); diff --git a/src/tests/eina/eina_test_quaternion.c b/src/tests/eina/eina_test_quaternion.c index da97dea..901eac9 100644 --- a/src/tests/eina/eina_test_quaternion.c +++ b/src/tests/eina/eina_test_quaternion.c @@ -473,6 +473,48 @@ START_TEST(eina_test_quaternion_rotate) } END_TEST +START_TEST(eina_test_quaternion_operations) +{ + Eina_Quaternion in = {2, 2, 1, 1}; + Eina_Quaternion in2 = {5, 5, 5, 5}; + Eina_Quaternion out; + const double v[] = {0, 1, 2, 3}; + double angle; + + eina_init(); + + eina_quaternion_inverse(&out, &in); + fail_if((out.x + 0.2 > DBL_EPSILON) || (out.y + 0.2 > DBL_EPSILON) || + (out.z + 0.1 > DBL_EPSILON) || (out.w - 0.1 > DBL_EPSILON)); + + eina_quaternion_array_set(&out, v); + fail_if((out.x != 0) || (out.y != 1) || + (out.z != 2) || (out.w != 3)); + + eina_quaternion_copy(&out, &in); + fail_if((out.x != 2) || (out.y != 2) || + (out.z != 1) || (out.w != 1)); + + eina_quaternion_homogeneous_regulate(&out, &in2); + fail_if((out.x != 1) || (out.y != 1) || + (out.z != 1) || (out.w != 1)); + + eina_quaternion_subtract(&out, &in2, &in); + fail_if((out.x != 3) || (out.y != 3) || + (out.z != 4) || (out.w != 4)); + + fail_if(eina_quaternion_length_get(&in2) != 10); + fail_if(eina_quaternion_length_square_get(&in) != 10); + fail_if((eina_quaternion_distance_get(&in2, &in) - sqrt(50)) > DBL_EPSILON); + fail_if(eina_quaternion_distance_square_get(&in2, &in) != 50); + + angle = eina_quaternion_angle_plains(&in, &in2); + fail_if(angle - 0.963 > DBL_EPSILON); + + eina_shutdown(); +} +END_TEST + void eina_test_quaternion(TCase *tc) { @@ -492,4 +534,5 @@ eina_test_quaternion(TCase *tc) tcase_add_test(tc, eina_test_quaternion_lerp); tcase_add_test(tc, eina_test_quaternion_f16p16_rotate_matrix); tcase_add_test(tc, eina_test_quaternion_rotate); + tcase_add_test(tc, eina_test_quaternion_operations); } diff --git a/src/tests/evas/evas_test_matrix.c b/src/tests/evas/evas_test_matrix.c index 26e8b02..7f1d7e6 100644 --- a/src/tests/evas/evas_test_matrix.c +++ b/src/tests/evas/evas_test_matrix.c @@ -16,12 +16,12 @@ START_TEST(evas_matrix) { Evas_Vec3 position; - Evas_Vec4 orientation; + Eina_Quaternion orientation; Evas_Vec3 scale; Eina_Matrix4 mat; evas_vec3_set(&position, 5.0, 3.0, 2.0); - evas_vec4_set(&orientation, 30.0, 1.0, 0.0, 0.0); + eina_quaternion_set(&orientation, 30.0, 1.0, 0.0, 0.0); evas_vec3_set(&scale, 1.0, 2.0, 1.0); evas_mat4_build(&mat, &position, &orientation, &scale); --