2013-12-26 23:56:30 -08:00
|
|
|
#ifndef EVAS_PRIVATE_H
|
|
|
|
# error You shall not include this header directly
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <math.h>
|
2014-06-05 11:50:42 -07:00
|
|
|
#include <float.h>
|
2013-12-26 23:56:30 -08:00
|
|
|
|
|
|
|
#define DEGREE_TO_RADIAN(x) (((x) * M_PI) / 180.0)
|
|
|
|
#define EVAS_MATRIX_IS_IDENTITY 0x00000001
|
2015-07-03 17:39:08 -07:00
|
|
|
#define MIN_DIFF 0.00000000001
|
|
|
|
|
2014-04-25 05:34:55 -07:00
|
|
|
typedef struct _Evas_Color Evas_Color;
|
|
|
|
typedef struct _Evas_Box2 Evas_Box2;
|
|
|
|
typedef struct _Evas_Box3 Evas_Box3;
|
2014-11-30 21:26:28 -08:00
|
|
|
typedef struct _Evas_Line3 Evas_Line3;
|
2014-04-25 05:34:55 -07:00
|
|
|
typedef struct _Evas_Triangle3 Evas_Triangle3;
|
|
|
|
typedef struct _Evas_Ray3 Evas_Ray3;
|
2014-11-30 21:26:28 -08:00
|
|
|
typedef struct _Evas_Sphere Evas_Sphere;
|
2014-04-25 05:34:55 -07:00
|
|
|
|
|
|
|
struct _Evas_Color
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
|
|
|
Evas_Real r;
|
|
|
|
Evas_Real g;
|
|
|
|
Evas_Real b;
|
|
|
|
Evas_Real a;
|
2014-04-25 05:34:55 -07:00
|
|
|
};
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2014-04-25 05:34:55 -07:00
|
|
|
struct _Evas_Box2
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector2 p0;
|
|
|
|
Eina_Vector2 p1;
|
2014-04-25 05:34:55 -07:00
|
|
|
};
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2014-04-25 05:34:55 -07:00
|
|
|
struct _Evas_Box3
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 p0;
|
|
|
|
Eina_Vector3 p1;
|
2014-04-25 05:34:55 -07:00
|
|
|
};
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2014-11-30 21:26:28 -08:00
|
|
|
struct _Evas_Line3
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 point;
|
|
|
|
Eina_Vector3 direction;
|
2014-11-30 21:26:28 -08:00
|
|
|
};
|
|
|
|
|
2014-04-25 05:34:55 -07:00
|
|
|
struct _Evas_Triangle3
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 p0;
|
|
|
|
Eina_Vector3 p1;
|
|
|
|
Eina_Vector3 p2;
|
2014-04-25 05:34:55 -07:00
|
|
|
};
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2014-04-25 05:34:55 -07:00
|
|
|
struct _Evas_Ray3
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 org;
|
|
|
|
Eina_Vector3 dir;
|
2014-04-25 05:34:55 -07:00
|
|
|
};
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2014-11-30 21:26:28 -08:00
|
|
|
struct _Evas_Sphere
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 center;
|
2014-11-30 21:26:28 -08:00
|
|
|
Evas_Real radius;
|
|
|
|
};
|
|
|
|
|
2015-07-03 17:39:08 -07:00
|
|
|
static inline void
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_triangle3_set(Evas_Triangle3 *v, Eina_Vector3 *a, Eina_Vector3 *b, Eina_Vector3 *c)
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_copy(&v->p0, a);
|
|
|
|
eina_vector3_copy(&v->p1, b);
|
|
|
|
eina_vector3_copy(&v->p2, c);
|
2015-07-03 17:39:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
evas_triangle3_is_line(Evas_Triangle3 *v)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
if (eina_vector3_equivalent(&v->p0, &v->p1) ||
|
|
|
|
eina_vector3_equivalent(&v->p0, &v->p2) ||
|
|
|
|
eina_vector3_equivalent(&v->p1, &v->p2))
|
2015-07-03 17:39:08 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2016-02-16 21:26:40 -08:00
|
|
|
convex_hull_triangle3_not_first_edje(Evas_Triangle3 *v, Eina_Vector3 *a, Eina_Vector3 *b)
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2017-01-06 09:57:46 -08:00
|
|
|
if ((EINA_DBL_EQ(v->p1.x, a->x) && EINA_DBL_EQ(v->p1.y, a->y) && EINA_DBL_EQ(v->p1.z, a->z)) &&
|
|
|
|
(EINA_DBL_EQ(v->p2.x, b->x) && EINA_DBL_EQ(v->p2.y, b->y) && EINA_DBL_EQ(v->p2.z, b->z)))
|
2015-07-03 17:39:08 -07:00
|
|
|
return EINA_TRUE;
|
2017-01-06 09:57:46 -08:00
|
|
|
else if ((EINA_DBL_EQ(v->p2.x, a->x) && EINA_DBL_EQ(v->p2.y, a->y) && EINA_DBL_EQ(v->p2.z, a->z)) &&
|
|
|
|
(EINA_DBL_EQ(v->p1.x, b->x) && EINA_DBL_EQ(v->p1.y, b->y) && EINA_DBL_EQ(v->p1.z, b->z)))
|
2015-07-03 17:39:08 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2016-02-16 21:26:40 -08:00
|
|
|
convex_hull_triangle3_first_edje(Evas_Triangle3 *v, Eina_Vector3 *a, Eina_Vector3 *b)
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2017-01-06 09:57:46 -08:00
|
|
|
if ((!EINA_FLT_EQ(v->p0.x, a->x) && !EINA_FLT_EQ(v->p0.y, a->y) &&
|
|
|
|
!EINA_FLT_EQ(v->p0.z, a->z)) && (!EINA_FLT_EQ(v->p1.x, b->x) &&
|
|
|
|
!EINA_FLT_EQ(v->p1.y, b->y) && !EINA_FLT_EQ(v->p1.z, b->z)))
|
2015-07-03 17:39:08 -07:00
|
|
|
return EINA_TRUE;
|
2017-01-06 09:57:46 -08:00
|
|
|
else if ((!EINA_FLT_EQ(v->p1.x, a->x) && !EINA_FLT_EQ(v->p1.y, a->y) &&
|
|
|
|
!EINA_FLT_EQ(v->p1.z, a->z)) && (!EINA_FLT_EQ(v->p0.x, b->x) &&
|
|
|
|
!EINA_FLT_EQ(v->p0.y, b->y) && !EINA_FLT_EQ(v->p0.z, b->z)))
|
2015-07-03 17:39:08 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2016-02-16 21:26:40 -08:00
|
|
|
convex_hull_triangle3_first_point(Evas_Triangle3 *v, Eina_Vector3 *a)
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2017-01-06 09:57:46 -08:00
|
|
|
return (EINA_DBL_EQ(v->p0.x, a->x) && EINA_DBL_EQ(v->p0.y, a->y) && EINA_DBL_EQ(v->p0.z, a->z));
|
2015-07-03 17:39:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_equivalent_as_triangle(Eina_Vector3 *v0, Eina_Vector3 *v1, Eina_Vector3 *v2,
|
|
|
|
Eina_Vector3 *w0, Eina_Vector3 *w1, Eina_Vector3 *w2)
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2017-01-06 09:57:46 -08:00
|
|
|
if ((EINA_DBL_EQ(v0->x, w0->x) && EINA_DBL_EQ(v0->y, w0->y) && EINA_DBL_EQ(v0->z, w0->z)) &&
|
|
|
|
(EINA_DBL_EQ(v1->x, w1->x) && EINA_DBL_EQ(v1->y, w1->y) && EINA_DBL_EQ(v1->z, w1->z)) &&
|
|
|
|
(EINA_DBL_EQ(v2->x, w2->x) && EINA_DBL_EQ(v2->y, w2->y) && EINA_DBL_EQ(v2->z, w2->z)))
|
2015-07-03 17:39:08 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_triangle3_equivalent(Evas_Triangle3 *a, Evas_Triangle3 *b)
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
|
|
|
/* to compare two triangles there are six permutations
|
|
|
|
to test because vertices are unordered */
|
2016-02-16 21:26:40 -08:00
|
|
|
if (eina_vector3_equivalent_as_triangle(&a->p0, &a->p1, &a->p2, &b->p0, &b->p1, &b->p2) ||
|
|
|
|
eina_vector3_equivalent_as_triangle(&a->p0, &a->p1, &a->p2, &b->p0, &b->p2, &b->p1) ||
|
|
|
|
eina_vector3_equivalent_as_triangle(&a->p0, &a->p1, &a->p2, &b->p1, &b->p0, &b->p2) ||
|
|
|
|
eina_vector3_equivalent_as_triangle(&a->p0, &a->p1, &a->p2, &b->p1, &b->p2, &b->p0) ||
|
|
|
|
eina_vector3_equivalent_as_triangle(&a->p0, &a->p1, &a->p2, &b->p2, &b->p0, &b->p1) ||
|
|
|
|
eina_vector3_equivalent_as_triangle(&a->p0, &a->p1, &a->p2, &b->p2, &b->p1, &b->p0))
|
2015-07-03 17:39:08 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2013-12-26 23:56:30 -08:00
|
|
|
static inline void
|
2015-11-09 14:37:42 -08:00
|
|
|
evas_mat4_look_at_set(Eina_Matrix4 *m,
|
2016-02-16 21:26:40 -08:00
|
|
|
const Eina_Vector3 *pos, const Eina_Vector3 *center, const Eina_Vector3 *up)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 x, y, z;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&z, pos, center);
|
|
|
|
eina_vector3_normalize(&z, &z);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_cross_product(&x, up, &z);
|
|
|
|
eina_vector3_normalize(&x, &x);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_cross_product(&y, &z, &x);
|
|
|
|
eina_vector3_normalize(&y, &y);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
m->xx = x.x;
|
|
|
|
m->xy = y.x;
|
|
|
|
m->xz = z.x;
|
|
|
|
m->xw = 0.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
m->yx = x.y;
|
|
|
|
m->yy = y.y;
|
|
|
|
m->yz = z.y;
|
|
|
|
m->yw = 0.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
m->zx = x.z;
|
|
|
|
m->zy = y.z;
|
|
|
|
m->zz = z.z;
|
|
|
|
m->zw = 0.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
m->wx = -eina_vector3_dot_product(&x, pos);
|
|
|
|
m->wy = -eina_vector3_dot_product(&y, pos);
|
|
|
|
m->wz = -eina_vector3_dot_product(&z, pos);
|
2015-11-09 14:37:42 -08:00
|
|
|
m->ww = 1.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2015-11-09 14:37:42 -08:00
|
|
|
evas_mat4_frustum_set(Eina_Matrix4 *m,
|
2013-12-26 23:56:30 -08:00
|
|
|
Evas_Real left, Evas_Real right, Evas_Real bottom, Evas_Real top,
|
2014-04-25 07:16:46 -07:00
|
|
|
Evas_Real dnear, Evas_Real dfar)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
|
|
|
Evas_Real w = right - left;
|
|
|
|
Evas_Real h = top - bottom;
|
2014-04-25 07:16:46 -07:00
|
|
|
Evas_Real depth = dnear - dfar;
|
|
|
|
Evas_Real near_2 = 2.0f * dnear;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
m->xx = near_2 / w;
|
|
|
|
m->xy = 0.0f;
|
|
|
|
m->xz = 0.0f;
|
|
|
|
m->xw = 0.0f;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
m->yx = 0.0f;
|
|
|
|
m->yy = near_2 / h;
|
|
|
|
m->yz = 0.0f;
|
|
|
|
m->yw = 0.0f;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
m->zx = (right + left) / w;
|
|
|
|
m->zy = (top + bottom) / h;
|
|
|
|
m->zz = (dfar + dnear) / depth;
|
|
|
|
m->zw = -1.0f;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
m->wx = 0.0f;
|
|
|
|
m->wy = 0.0f;
|
|
|
|
m->wz = near_2 * dfar / depth;
|
|
|
|
m->ww = 0.0f;
|
2013-12-26 23:56:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2014-04-16 00:31:14 -07:00
|
|
|
evas_box2_set(Evas_Box2 *box, Evas_Real x0, Evas_Real y0, Evas_Real x1,
|
|
|
|
Evas_Real y1)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
|
|
|
box->p0.x = x0;
|
|
|
|
box->p0.y = y0;
|
|
|
|
box->p1.x = x1;
|
|
|
|
box->p1.y = y1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2014-04-16 00:31:14 -07:00
|
|
|
evas_box3_set(Evas_Box3 *box, Evas_Real x0, Evas_Real y0, Evas_Real z0,
|
|
|
|
Evas_Real x1, Evas_Real y1, Evas_Real z1)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
|
|
|
box->p0.x = x0;
|
|
|
|
box->p0.y = y0;
|
|
|
|
box->p0.z = z0;
|
|
|
|
box->p1.x = x1;
|
|
|
|
box->p1.y = y1;
|
|
|
|
box->p1.z = z1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
evas_box3_empty_set(Evas_Box3 *box)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&box->p0, 0.0, 0.0, 0.0);
|
|
|
|
eina_vector3_set(&box->p1, 0.0, 0.0, 0.0);
|
2013-12-26 23:56:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
evas_box3_copy(Evas_Box3 *dst, const Evas_Box3 *src)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_copy(&dst->p0, &src->p0);
|
|
|
|
eina_vector3_copy(&dst->p1, &src->p1);
|
2013-12-26 23:56:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
evas_box3_union(Evas_Box3 *out, const Evas_Box3 *a, const Evas_Box3 *b)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&out->p0, MIN(a->p0.x, b->p0.x), MIN(a->p0.y, b->p0.y), MIN(a->p0.z, b->p0.z));
|
|
|
|
eina_vector3_set(&out->p1, MAX(a->p1.x, b->p1.x), MAX(a->p1.y, b->p1.y), MAX(a->p1.z, b->p1.z));
|
2013-12-26 23:56:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2015-11-09 14:37:42 -08:00
|
|
|
evas_box3_transform(Evas_Box3 *out EINA_UNUSED, const Evas_Box3 *box EINA_UNUSED, const Eina_Matrix4 *mat EINA_UNUSED)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
|
|
|
/* TODO: */
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2015-12-07 16:12:56 -08:00
|
|
|
evas_mat4_position_get(const Eina_Matrix4 *matrix, Eina_Quaternion *position)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
2015-12-07 16:12:56 -08:00
|
|
|
Eina_Quaternion pos;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
|
|
|
pos.x = 0.0;
|
|
|
|
pos.y = 0.0;
|
|
|
|
pos.z = 0.0;
|
|
|
|
pos.w = 1.0;
|
|
|
|
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_transform(position, &pos, matrix);
|
2013-12-26 23:56:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_mat4_direction_get(const Eina_Matrix4 *matrix, Eina_Vector3 *direction)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
|
|
|
/* TODO: Check correctness. */
|
|
|
|
|
2015-12-07 16:12:56 -08:00
|
|
|
Eina_Quaternion dir;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
|
|
|
dir.x = 0.0;
|
|
|
|
dir.y = 0.0;
|
|
|
|
dir.z = 1.0;
|
|
|
|
dir.w = 1.0;
|
|
|
|
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_transform(&dir, &dir, matrix);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
|
|
|
direction->x = dir.x;
|
|
|
|
direction->y = dir.y;
|
|
|
|
direction->z = dir.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2015-11-09 14:37:42 -08:00
|
|
|
evas_mat4_build(Eina_Matrix4 *out,
|
2016-02-16 21:26:40 -08:00
|
|
|
const Eina_Vector3 *position, const Eina_Quaternion *orientation, const Eina_Vector3 *scale)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
2015-11-09 14:37:42 -08:00
|
|
|
Eina_Matrix3 rot;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_rotation_matrix3_get(&rot, orientation);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
out->xx = scale->x * rot.xx;
|
2015-12-02 14:14:17 -08:00
|
|
|
out->xy = scale->x * rot.xy;
|
|
|
|
out->xz = scale->x * rot.xz;
|
2015-11-09 14:37:42 -08:00
|
|
|
out->xw = 0.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-12-02 14:14:17 -08:00
|
|
|
out->yx = scale->y * rot.yx;
|
2015-11-09 14:37:42 -08:00
|
|
|
out->yy = scale->y * rot.yy;
|
2015-12-02 14:14:17 -08:00
|
|
|
out->yz = scale->y * rot.yz;
|
2015-11-09 14:37:42 -08:00
|
|
|
out->yw = 0.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-12-02 14:14:17 -08:00
|
|
|
out->zx = scale->z * rot.zx;
|
|
|
|
out->zy = scale->z * rot.zy;
|
2015-11-09 14:37:42 -08:00
|
|
|
out->zz = scale->z * rot.zz;
|
|
|
|
out->zw = 0.0;
|
2015-02-05 02:16:57 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
out->wx = position->x;
|
|
|
|
out->wy = position->y;
|
|
|
|
out->wz = position->z;
|
|
|
|
out->ww = 1.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_mat4_inverse_build(Eina_Matrix4 *out, const Eina_Vector3 *position,
|
|
|
|
const Eina_Quaternion *orientation, const Eina_Vector3 *scale)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
2015-12-07 16:12:56 -08:00
|
|
|
Eina_Quaternion inv_rotation;
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 inv_scale;
|
|
|
|
Eina_Vector3 inv_translate;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
Eina_Matrix3 rot;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
|
|
|
/* Inverse scale. */
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&inv_scale, 1.0 / scale->x, 1.0 / scale->y, 1.0 / scale->z);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
|
|
|
/* Inverse rotation. */
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_inverse(&inv_rotation, orientation);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
|
|
|
/* Inverse translation. */
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_negate(&inv_translate, position);
|
|
|
|
eina_vector3_quaternion_rotate(&inv_translate, &inv_translate, &inv_rotation);
|
|
|
|
eina_vector3_multiply(&inv_translate, &inv_translate, &inv_scale);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
|
|
|
/* Get 3x3 rotation matrix. */
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_rotation_matrix3_get(&rot, &inv_rotation);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
out->xx = inv_scale.x * rot.xx;
|
2015-12-02 14:14:17 -08:00
|
|
|
out->xy = inv_scale.x * rot.xy;
|
|
|
|
out->xz = inv_scale.x * rot.xz;
|
2015-11-09 14:37:42 -08:00
|
|
|
out->xw = 0.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-12-02 14:14:17 -08:00
|
|
|
out->yx = inv_scale.y * rot.yx;
|
2015-11-09 14:37:42 -08:00
|
|
|
out->yy = inv_scale.y * rot.yy;
|
2015-12-02 14:14:17 -08:00
|
|
|
out->yz = inv_scale.y * rot.yz;
|
2015-11-09 14:37:42 -08:00
|
|
|
out->yw = 0.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-12-02 14:14:17 -08:00
|
|
|
out->zx = inv_scale.z * rot.zx;
|
|
|
|
out->zy = inv_scale.z * rot.zy;
|
2015-11-09 14:37:42 -08:00
|
|
|
out->zz = inv_scale.z * rot.zz;
|
|
|
|
out->zw = 0.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-11-09 14:37:42 -08:00
|
|
|
out->wx = inv_translate.x;
|
|
|
|
out->wy = inv_translate.y;
|
|
|
|
out->wz = inv_translate.z;
|
|
|
|
out->ww = 1.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
evas_color_set(Evas_Color *color, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
|
|
|
|
{
|
|
|
|
color->r = r;
|
|
|
|
color->g = g;
|
|
|
|
color->b = b;
|
|
|
|
color->a = a;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
evas_color_blend(Evas_Color *dst, const Evas_Color *c0, const Evas_Color *c1, Evas_Real w)
|
|
|
|
{
|
|
|
|
dst->r = c0->r * w + c1->r * (1.0 - w);
|
|
|
|
dst->g = c0->g * w + c1->g * (1.0 - w);
|
|
|
|
dst->b = c0->b * w + c1->b * (1.0 - w);
|
|
|
|
dst->a = c0->a * w + c1->a * (1.0 - w);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2015-11-09 14:37:42 -08:00
|
|
|
evas_ray3_init(Evas_Ray3 *ray, Evas_Real x, Evas_Real y, const Eina_Matrix4 *mvp)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
2015-11-09 14:37:42 -08:00
|
|
|
Eina_Matrix4 mat;
|
2015-12-07 16:12:56 -08:00
|
|
|
Eina_Quaternion dnear, dfar;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2014-04-25 05:34:55 -07:00
|
|
|
memset(&mat, 0, sizeof (mat));
|
|
|
|
|
2014-04-16 00:31:14 -07:00
|
|
|
/* Get the matrix which transforms from normalized device coordinate to
|
|
|
|
modeling coodrinate. */
|
2015-11-09 14:37:42 -08:00
|
|
|
eina_matrix4_inverse(&mat, mvp);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
|
|
|
/* Transform near point. */
|
2014-04-25 07:16:46 -07:00
|
|
|
dnear.x = x;
|
|
|
|
dnear.y = y;
|
|
|
|
dnear.z = -1.0;
|
|
|
|
dnear.w = 1.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_transform(&dnear, &dnear, &mat);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2014-04-25 07:16:46 -07:00
|
|
|
dnear.w = 1.0 / dnear.w;
|
|
|
|
dnear.x *= dnear.w;
|
|
|
|
dnear.y *= dnear.w;
|
|
|
|
dnear.z *= dnear.w;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&ray->org, dnear.x, dnear.y, dnear.z);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
|
|
|
/* Transform far point. */
|
2014-04-25 07:16:46 -07:00
|
|
|
dfar.x = x;
|
|
|
|
dfar.y = y;
|
|
|
|
dfar.z = 1.0;
|
|
|
|
dfar.w = 1.0;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_transform(&dfar, &dfar, &mat);
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2014-04-25 07:16:46 -07:00
|
|
|
dfar.w = 1.0 / dfar.w;
|
|
|
|
dfar.x *= dfar.w;
|
|
|
|
dfar.y *= dfar.w;
|
|
|
|
dfar.z *= dfar.w;
|
2013-12-26 23:56:30 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&ray->dir, dfar.x - dnear.x, dfar.y - dnear.y, dfar.z - dnear.z);
|
2013-12-26 23:56:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_box2_intersect_2d(const Evas_Box2 *box, const Eina_Vector2 *org, const Eina_Vector2 *dir)
|
2013-12-26 23:56:30 -08:00
|
|
|
{
|
2014-06-05 11:50:42 -07:00
|
|
|
Evas_Real t1, t2, t_near = FLT_MIN, t_far = FLT_MAX;
|
|
|
|
/* ray intersects box if its begins in */
|
|
|
|
if ((org->x >= box->p0.x) && (org->x <= box->p1.x) &&
|
|
|
|
(org->y >= box->p0.y) && (org->y <= box->p1.y))
|
|
|
|
{
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
/* minmax algorithm of ray and box intersection */
|
2017-01-06 09:57:46 -08:00
|
|
|
if (!EINA_DBL_EQ(dir->x, 0.0) && !EINA_DBL_EQ(dir->y, 0.0))
|
2014-06-05 11:50:42 -07:00
|
|
|
{
|
|
|
|
t1 = (box->p0.x - org->x) / dir->x;
|
|
|
|
t2 = (box->p1.x - org->x) / dir->x;
|
|
|
|
|
|
|
|
if (t1 > t2)
|
|
|
|
{
|
|
|
|
Evas_Real tmp = t1;
|
|
|
|
t1 = t2;
|
|
|
|
t2 = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t1 > t_near) t_near = t1;
|
|
|
|
if (t2 < t_far) t_far = t2;
|
|
|
|
|
|
|
|
if (t_far < 0.0f)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
t1 = (box->p0.y - org->y) / dir->y;
|
|
|
|
t2 = (box->p1.y - org->y) / dir->y;
|
|
|
|
|
|
|
|
if (t1 > t2)
|
|
|
|
{
|
|
|
|
Evas_Real tmp = t1;
|
|
|
|
t1 = t2;
|
|
|
|
t2 = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t1 > t_near) t_near = t1;
|
|
|
|
if (t2 < t_far) t_far = t2;
|
|
|
|
|
|
|
|
if ((t_near > t_far) || (t_far < 0.0f))
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
/* case when ray is parallel to one of axes */
|
2017-01-06 09:57:46 -08:00
|
|
|
else if (EINA_DBL_EQ(dir->x, 0.0))
|
2014-06-05 11:50:42 -07:00
|
|
|
{
|
|
|
|
if ((org->x < box->p0.x) && (org->x > box->p1.x))
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
else if (org->y < box->p0.y && org->y > box->p1.y)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
2013-12-26 23:56:30 -08:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
2014-01-05 22:10:59 -08:00
|
|
|
|
2014-11-30 21:26:28 -08:00
|
|
|
static inline Evas_Real
|
|
|
|
evas_determinant_3D(Evas_Real matrix[3][3])
|
|
|
|
{
|
|
|
|
return (matrix[0][0] * matrix[1][1] * matrix[2][2]) +
|
|
|
|
(matrix[0][1] * matrix[1][2] * matrix[2][0]) +
|
|
|
|
(matrix[0][2] * matrix[1][0] * matrix[2][1]) -
|
|
|
|
(matrix[0][2] * matrix[1][1] * matrix[2][0]) -
|
|
|
|
(matrix[0][1] * matrix[1][0] * matrix[2][2]) -
|
|
|
|
(matrix[0][0] * matrix[1][2] * matrix[2][1]);
|
|
|
|
}
|
|
|
|
|
2014-06-05 11:50:42 -07:00
|
|
|
static inline Eina_Bool
|
|
|
|
evas_box3_ray3_intersect(const Evas_Box3 *box, const Evas_Ray3 *ray)
|
|
|
|
{
|
|
|
|
Evas_Real t1, t2, t_near = FLT_MIN, t_far = FLT_MAX;
|
|
|
|
Evas_Box2 box2;
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector2 org2;
|
|
|
|
Eina_Vector2 dir2;
|
2014-06-05 11:50:42 -07:00
|
|
|
Eina_Bool intersect = EINA_FALSE;
|
|
|
|
|
|
|
|
/* ray intersects box if its begins in */
|
|
|
|
if ((ray->org.x >= box->p0.x) && (ray->org.x <= box->p1.x) &&
|
|
|
|
(ray->org.y >= box->p0.y) && (ray->org.y <= box->p1.y) &&
|
|
|
|
(ray->org.z >= box->p0.z) && (ray->org.z <= box->p1.z))
|
|
|
|
{
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
/* minmax algorithm of ray and box intersection */
|
2017-01-06 09:57:46 -08:00
|
|
|
if (!EINA_DBL_EQ(ray->dir.x, 0.0) && !EINA_DBL_EQ(ray->dir.y, 0.0) && !EINA_DBL_EQ(ray->dir.z, 0.0))
|
2014-06-05 11:50:42 -07:00
|
|
|
{
|
|
|
|
t1 = (box->p0.x - ray->org.x) / ray->dir.x;
|
|
|
|
t2 = (box->p1.x - ray->org.x) / ray->dir.x;
|
|
|
|
|
|
|
|
if (t1 > t2)
|
|
|
|
{
|
|
|
|
Evas_Real tmp = t1;
|
|
|
|
t1 = t2;
|
|
|
|
t2 = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t1 > t_near) t_near = t1;
|
|
|
|
if (t2 < t_far) t_far = t2;
|
|
|
|
|
|
|
|
if (t_far < 0.0f)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
t1 = (box->p0.y - ray->org.y) / ray->dir.y;
|
|
|
|
t2 = (box->p1.y - ray->org.y) / ray->dir.y;
|
|
|
|
|
|
|
|
if (t1 > t2)
|
|
|
|
{
|
|
|
|
Evas_Real tmp = t1;
|
|
|
|
t1 = t2;
|
|
|
|
t2 = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t1 > t_near) t_near = t1;
|
|
|
|
if (t2 < t_far) t_far = t2;
|
|
|
|
|
|
|
|
if ((t_near > t_far) || (t_far < 0.0f))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
t1 = (box->p0.z - ray->org.z) / ray->dir.z;
|
|
|
|
t2 = (box->p1.z - ray->org.z) / ray->dir.z;
|
|
|
|
|
|
|
|
if (t1 > t2)
|
|
|
|
{
|
|
|
|
Evas_Real tmp = t1;
|
|
|
|
t1 = t2;
|
|
|
|
t2 = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t1 > t_near) t_near = t1;
|
|
|
|
if (t2 < t_far) t_far = t2;
|
|
|
|
|
|
|
|
if ((t_near > t_far) || (t_far < 0.0f))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
intersect = EINA_TRUE;
|
|
|
|
}
|
|
|
|
/* case when ray is parallel to one of axes */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* use two-dimensional version here */
|
2017-01-06 09:57:46 -08:00
|
|
|
if (EINA_DBL_EQ(ray->dir.x, 0.0))
|
2014-06-05 11:50:42 -07:00
|
|
|
{
|
|
|
|
if ((ray->org.x < box->p0.x) || (ray->org.x > box->p1.x))
|
|
|
|
return EINA_FALSE;
|
|
|
|
else
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector2_set(&org2, ray->org.y, ray->org.z);
|
|
|
|
eina_vector2_set(&dir2, ray->dir.y, ray->dir.z);
|
2014-06-05 11:50:42 -07:00
|
|
|
evas_box2_set(&box2, box->p0.y, box->p0.z, box->p1.y, box->p1.z);
|
|
|
|
intersect = evas_box2_intersect_2d(&box2, &org2, &dir2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:57:46 -08:00
|
|
|
if (EINA_DBL_EQ(ray->dir.y, 0.0))
|
2014-06-05 11:50:42 -07:00
|
|
|
{
|
|
|
|
if ((ray->org.y < box->p0.y) || (ray->org.y > box->p1.y))
|
|
|
|
return EINA_FALSE;
|
|
|
|
else
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector2_set(&org2, ray->org.x, ray->org.z);
|
|
|
|
eina_vector2_set(&dir2, ray->dir.x, ray->dir.z);
|
2014-06-05 11:50:42 -07:00
|
|
|
evas_box2_set(&box2, box->p0.x, box->p0.z, box->p1.x, box->p1.z);
|
|
|
|
intersect = evas_box2_intersect_2d(&box2, &org2, &dir2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:57:46 -08:00
|
|
|
if (EINA_DBL_EQ(ray->dir.z, 0.0))
|
2014-06-05 11:50:42 -07:00
|
|
|
{
|
|
|
|
if (ray->org.z < box->p0.z || ray->org.z > box->p1.z)
|
|
|
|
return EINA_FALSE;
|
|
|
|
else
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector2_set(&org2, ray->org.x, ray->org.y);
|
|
|
|
eina_vector2_set(&dir2, ray->dir.x, ray->dir.y);
|
2014-06-05 11:50:42 -07:00
|
|
|
evas_box2_set(&box2, box->p0.x, box->p0.y, box->p1.x, box->p1.y);
|
|
|
|
intersect = evas_box2_intersect_2d(&box2, &org2, &dir2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return intersect;
|
|
|
|
}
|
|
|
|
|
2014-01-05 22:10:59 -08:00
|
|
|
static inline Evas_Real
|
|
|
|
evas_reciprocal_sqrt(Evas_Real x)
|
|
|
|
{
|
2014-01-07 00:39:23 -08:00
|
|
|
union {
|
|
|
|
float f;
|
|
|
|
long i;
|
|
|
|
} u;
|
|
|
|
|
|
|
|
u.f = x;
|
|
|
|
u.i = 0x5f3759df - (u.i >> 1);
|
|
|
|
return u.f * (1.5f - u.f * u.f * x * 0.5f);
|
2014-01-05 22:10:59 -08:00
|
|
|
}
|
2014-11-30 21:26:28 -08:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
evas_build_sphere(const Evas_Box3 *box, Evas_Sphere *sphere)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 tmp;
|
2014-11-30 21:26:28 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&sphere->center, (0.5 * (box->p0.x + box->p1.x)), (0.5 * (box->p0.y + box->p1.y)), (0.5 * (box->p0.z + box->p1.z)));
|
|
|
|
eina_vector3_set(&tmp, sphere->center.x - box->p0.x, sphere->center.y - box->p0.y, sphere->center.z - box->p0.z);
|
2014-11-30 21:26:28 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
sphere->radius = sqrtf(eina_vector3_dot_product(&tmp, &tmp));
|
2014-11-30 21:26:28 -08:00
|
|
|
}
|
|
|
|
|
2015-02-17 06:33:05 -08:00
|
|
|
static inline void
|
|
|
|
evas_sphere_empty_set(Evas_Sphere *dst)
|
|
|
|
{
|
|
|
|
dst->radius = 0;
|
|
|
|
dst->center.x = 0;
|
|
|
|
dst->center.y = 0;
|
|
|
|
dst->center.z = 0;
|
|
|
|
}
|
|
|
|
|
2014-11-30 21:26:28 -08:00
|
|
|
static inline void
|
2015-12-07 16:12:56 -08:00
|
|
|
evas_plane_normalize(Eina_Quaternion *plane)
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 tmp;
|
2014-11-30 21:26:28 -08:00
|
|
|
Evas_Real length;
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&tmp, plane->x, plane->y, plane->z);
|
|
|
|
length = eina_vector3_length_get(&tmp);
|
2014-11-30 21:26:28 -08:00
|
|
|
plane->x = plane->x / length;
|
|
|
|
plane->y = plane->y / length;
|
|
|
|
plane->z = plane->z / length;
|
|
|
|
plane->w = plane->w / length;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_intersection_line_of_two_plains(Evas_Line3 *line, Eina_Quaternion *plane1, Eina_Quaternion *plane2)
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
|
|
|
//TODO:parallel case
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 planes3D[2];
|
2014-11-30 21:26:28 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&planes3D[0], plane1->x, plane1->y, plane1->z);
|
|
|
|
eina_vector3_set(&planes3D[1], plane2->x, plane2->y, plane2->z);
|
2014-11-30 21:26:28 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_cross_product(&line->direction, &planes3D[0], &planes3D[1]);
|
2014-11-30 21:26:28 -08:00
|
|
|
|
|
|
|
#define SOLVE_EQUATION(x, y, z) \
|
|
|
|
line->point.x = 0; \
|
|
|
|
line->point.y = (plane2->w * plane1->z - plane1->w * plane2->z) / line->direction.x; \
|
|
|
|
line->point.z = (plane2->y * plane1->w - plane1->y * plane2->w) / line->direction.x;
|
|
|
|
|
2017-01-06 09:57:46 -08:00
|
|
|
if (!EINA_DBL_EQ(line->direction.x, 0.0) && !EINA_DBL_EQ(plane1->z, 0.0))
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
|
|
|
SOLVE_EQUATION(x, y, z)
|
|
|
|
}
|
2017-01-06 09:57:46 -08:00
|
|
|
else if (!EINA_DBL_EQ(line->direction.y, 0.0) && !EINA_DBL_EQ(plane1->x, 0.0))
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
|
|
|
SOLVE_EQUATION(y, z, x)
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SOLVE_EQUATION(z, x, y)
|
|
|
|
}
|
|
|
|
#undef SOLVE_EQUATION
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_intersection_point_of_three_plains(Eina_Vector3 *point, Eina_Quaternion *plane1, Eina_Quaternion *plane2, Eina_Quaternion *plane3)
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
|
|
|
//TODO:parallel case
|
|
|
|
int i;
|
|
|
|
Evas_Real delta, deltax, deltay, deltaz;
|
|
|
|
Evas_Real matrix_to_det[3][3];
|
2015-12-07 16:12:56 -08:00
|
|
|
Eina_Quaternion planes[3];
|
2014-11-30 21:26:28 -08:00
|
|
|
|
|
|
|
planes[0] = *plane1;
|
|
|
|
planes[1] = *plane2;
|
|
|
|
planes[2] = *plane3;
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
matrix_to_det[0][i] = planes[i].x;
|
|
|
|
matrix_to_det[1][i] = planes[i].y;
|
|
|
|
matrix_to_det[2][i] = planes[i].z;
|
|
|
|
}
|
|
|
|
delta = evas_determinant_3D(matrix_to_det);
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
matrix_to_det[0][i] = planes[i].w;
|
|
|
|
deltax = evas_determinant_3D(matrix_to_det);
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
matrix_to_det[0][i] = planes[i].x;
|
|
|
|
matrix_to_det[1][i] = planes[i].w;
|
|
|
|
}
|
|
|
|
deltay = evas_determinant_3D(matrix_to_det);
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
matrix_to_det[1][i] = planes[i].y;
|
|
|
|
matrix_to_det[2][i] = planes[i].w;
|
|
|
|
}
|
|
|
|
deltaz = evas_determinant_3D(matrix_to_det);
|
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(point, -deltax/delta, -deltay/delta, -deltaz/delta);
|
2014-11-30 21:26:28 -08:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Evas_Real
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_point_plane_distance(Eina_Vector3 *point, Eina_Quaternion *plane)
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
|
|
|
return plane->x * point->x + plane->y * point->y + plane->z * point->z + plane->w;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Evas_Real
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_point_line_distance(Eina_Vector3 *point, Evas_Line3 *line)
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 temp, sub;
|
2014-11-30 21:26:28 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&sub, point, &line->point);
|
|
|
|
eina_vector3_cross_product(&temp, &sub, &line->direction);
|
2014-11-30 21:26:28 -08:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
return eina_vector3_length_get(&temp) / eina_vector3_length_get(&line->direction);
|
2014-11-30 21:26:28 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2015-12-07 16:12:56 -08:00
|
|
|
evas_is_sphere_in_frustum(Evas_Sphere *bsphere, Eina_Quaternion *planes)
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
Evas_Line3 line;
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 point, sub;
|
2014-11-30 21:26:28 -08:00
|
|
|
Evas_Real distances[6] = {0};
|
2016-02-16 21:26:40 -08:00
|
|
|
int intersected_plains[3];
|
|
|
|
int intersected_plains_count = 0;
|
2014-11-30 21:26:28 -08:00
|
|
|
|
|
|
|
for (i = 0; i < 6; i++)
|
2015-02-05 06:06:10 -08:00
|
|
|
distances[i] = evas_point_plane_distance(&bsphere->center, &planes[i]);
|
2014-11-30 21:26:28 -08:00
|
|
|
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
if (distances[i] <= -bsphere->radius)
|
|
|
|
{
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
else if (distances[i] <= 0)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
intersected_plains[intersected_plains_count] = i;
|
|
|
|
intersected_plains_count++;
|
2014-11-30 21:26:28 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
switch (intersected_plains_count)
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
2015-02-05 06:06:10 -08:00
|
|
|
case 2:
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_intersection_line_of_two_plains(&line,
|
|
|
|
&planes[intersected_plains[0]],
|
|
|
|
&planes[intersected_plains[1]]);
|
2015-02-05 06:06:10 -08:00
|
|
|
return (evas_point_line_distance(&bsphere->center, &line) <
|
|
|
|
bsphere->radius) ? EINA_TRUE : EINA_FALSE;
|
|
|
|
case 3:
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_intersection_point_of_three_plains(&point,
|
|
|
|
&planes[intersected_plains[0]],
|
|
|
|
&planes[intersected_plains[1]],
|
|
|
|
&planes[intersected_plains[2]]);
|
|
|
|
eina_vector3_subtract(&sub, &point, &bsphere->center);
|
|
|
|
return (eina_vector3_length_get(&sub) < bsphere->radius) ? EINA_TRUE : EINA_FALSE;
|
2015-02-05 06:06:10 -08:00
|
|
|
default:
|
|
|
|
return EINA_TRUE;
|
2014-11-30 21:26:28 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2016-02-16 21:26:40 -08:00
|
|
|
evas_is_point_in_frustum(Eina_Vector3 *point, Eina_Quaternion *planes)
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
if (evas_point_plane_distance(point, &planes[i]) <= 0) return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2015-12-07 16:12:56 -08:00
|
|
|
evas_is_box_in_frustum(Evas_Box3 *box, Eina_Quaternion *planes)
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
if (planes[i].x * box->p0.x + planes[i].y * box->p0.y + planes[i].z * box->p0.z + planes[i].w > 0)
|
|
|
|
continue;
|
|
|
|
if (planes[i].x * box->p1.x + planes[i].y * box->p0.y + planes[i].z * box->p0.z + planes[i].w > 0)
|
|
|
|
continue;
|
|
|
|
if (planes[i].x * box->p1.x + planes[i].y * box->p1.y + planes[i].z * box->p0.z + planes[i].w > 0)
|
|
|
|
continue;
|
|
|
|
if (planes[i].x * box->p0.x + planes[i].y * box->p1.y + planes[i].z * box->p0.z + planes[i].w > 0)
|
|
|
|
continue;
|
|
|
|
if (planes[i].x * box->p0.x + planes[i].y * box->p0.y + planes[i].z * box->p1.z + planes[i].w > 0)
|
|
|
|
continue;
|
|
|
|
if (planes[i].x * box->p1.x + planes[i].y * box->p0.y + planes[i].z * box->p1.z + planes[i].w > 0)
|
|
|
|
continue;
|
|
|
|
if (planes[i].x * box->p1.x + planes[i].y * box->p1.y + planes[i].z * box->p1.z + planes[i].w > 0)
|
|
|
|
continue;
|
|
|
|
if (planes[i].x * box->p0.x + planes[i].y * box->p1.y + planes[i].z * box->p1.z + planes[i].w > 0)
|
|
|
|
continue;
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2015-12-07 16:12:56 -08:00
|
|
|
evas_frustum_calculate(Eina_Quaternion *planes, Eina_Matrix4 *matrix_vp)
|
2014-11-30 21:26:28 -08:00
|
|
|
{
|
|
|
|
int i;
|
2015-11-09 14:37:42 -08:00
|
|
|
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_set(&planes[0], matrix_vp->xw - matrix_vp->xx,
|
2015-11-09 14:37:42 -08:00
|
|
|
matrix_vp->yw - matrix_vp->yx,
|
|
|
|
matrix_vp->zw - matrix_vp->zx,
|
|
|
|
matrix_vp->ww - matrix_vp->wx);
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_set(&planes[1], matrix_vp->xw - matrix_vp->xx,
|
2015-11-09 14:37:42 -08:00
|
|
|
matrix_vp->yw - matrix_vp->yx,
|
|
|
|
matrix_vp->zw - matrix_vp->zx,
|
|
|
|
matrix_vp->ww - matrix_vp->wx);
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_set(&planes[2], matrix_vp->xw - matrix_vp->xx,
|
2015-11-09 14:37:42 -08:00
|
|
|
matrix_vp->yw - matrix_vp->yx,
|
|
|
|
matrix_vp->zw - matrix_vp->zx,
|
|
|
|
matrix_vp->ww - matrix_vp->wx);
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_set(&planes[3], matrix_vp->xw - matrix_vp->xx,
|
2015-11-09 14:37:42 -08:00
|
|
|
matrix_vp->yw - matrix_vp->yx,
|
|
|
|
matrix_vp->zw - matrix_vp->zx,
|
|
|
|
matrix_vp->ww - matrix_vp->wx);
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_set(&planes[4], matrix_vp->xw - matrix_vp->xx,
|
2015-11-09 14:37:42 -08:00
|
|
|
matrix_vp->yw - matrix_vp->yx,
|
|
|
|
matrix_vp->zw - matrix_vp->zx,
|
|
|
|
matrix_vp->ww - matrix_vp->wx);
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_set(&planes[5], matrix_vp->xw - matrix_vp->xx,
|
2015-11-09 14:37:42 -08:00
|
|
|
matrix_vp->yw - matrix_vp->yx,
|
|
|
|
matrix_vp->zw - matrix_vp->zx,
|
|
|
|
matrix_vp->ww - matrix_vp->wx);
|
|
|
|
|
2014-11-30 21:26:28 -08:00
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
evas_plane_normalize(&planes[i]);
|
|
|
|
}
|
|
|
|
}
|
2015-02-18 12:43:23 -08:00
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
box_intersection_box(Evas_Box3 *v1, Evas_Box3 *v2)
|
|
|
|
{
|
|
|
|
if ((v1->p1.x < v2->p0.x) || (v1->p0.x > v2->p1.x)
|
|
|
|
|| (v1->p1.y < v2->p0.y) || (v1->p0.y > v2->p1.y)
|
|
|
|
|| (v1->p1.z < v2->p0.z) || (v1->p0.z > v2->p1.z))
|
|
|
|
return EINA_FALSE;
|
|
|
|
else
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2015-07-29 13:24:02 -07:00
|
|
|
static inline void
|
2016-02-16 21:26:40 -08:00
|
|
|
tangent_new_basis(Eina_Vector3 *out, Evas_Triangle3 *triangle,
|
|
|
|
Eina_Vector2 *a, Eina_Vector2 *b, Eina_Vector2 *c)
|
2015-07-29 13:24:02 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector2 new1, new2;
|
|
|
|
Eina_Vector3 old1, old2;
|
|
|
|
eina_vector3_set(out, 0, 0, 0);
|
2015-07-29 13:24:02 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector2_subtract(&new1, b, a);
|
|
|
|
eina_vector2_subtract(&new2, c, a);
|
|
|
|
eina_vector3_subtract(&old1, &(triangle->p1), &(triangle->p0));
|
|
|
|
eina_vector3_subtract(&old2, &(triangle->p2), &(triangle->p0));
|
2015-07-29 13:24:02 -07:00
|
|
|
|
|
|
|
|
|
|
|
/* calculation of new basis(in system coordinates of texturing) by solution of system of equations */
|
2017-01-06 09:57:46 -08:00
|
|
|
if (!EINA_DBL_EQ(new2.y, 0.0))
|
2015-07-29 13:24:02 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_scale(&old2, &old2, (new1.y / new2.y));
|
|
|
|
eina_vector2_scale(&new2, &new2, (new1.y / new2.y));
|
2015-07-29 13:24:02 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector2_subtract(&new1, &new1, &new2);
|
|
|
|
eina_vector3_subtract(&old1, &old1, &old2);
|
2015-07-29 13:24:02 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_scale(out, &old1, 1 / new1.x);
|
2015-07-29 13:24:02 -07:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:57:46 -08:00
|
|
|
else if (!EINA_DBL_EQ(new1.y, 0.0))
|
2015-07-29 13:24:02 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_scale(&old1, &old1, (new2.y / new1.y));
|
|
|
|
eina_vector2_scale(&new1, &new1, (new2.y / new1.y));
|
2015-07-29 13:24:02 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector2_subtract(&new2, &new2, &new1);
|
|
|
|
eina_vector3_subtract(&old2, &old2, &old1);
|
2015-07-29 13:24:02 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_scale(out, &old2, 1 / new2.x);
|
2015-07-29 13:24:02 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-07-03 17:39:08 -07:00
|
|
|
static inline void
|
2015-11-09 14:29:44 -08:00
|
|
|
convex_hull_vertex_set(Evas_Triangle3 *el, unsigned short int *vertex_count, float **vertex,
|
2015-07-03 17:39:08 -07:00
|
|
|
unsigned short int **index, unsigned int k, int *leader, int coord)
|
|
|
|
{
|
|
|
|
int color_coords, normal_coords;
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 vect = {0, 0, 0};
|
2015-07-03 17:39:08 -07:00
|
|
|
switch (coord)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
vect = el->p0;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
vect = el->p1;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
vect = el->p2;
|
|
|
|
break;
|
|
|
|
}
|
2016-01-08 15:32:47 -08:00
|
|
|
|
2015-07-03 17:39:08 -07:00
|
|
|
(*vertex_count)++;
|
|
|
|
*vertex = (float*) realloc(*vertex, (10 * (*vertex_count)) * sizeof(float));
|
|
|
|
|
|
|
|
(*vertex)[10 * (*vertex_count) - 10] = vect.x;
|
|
|
|
(*vertex)[10 * (*vertex_count) - 9] = vect.y;
|
|
|
|
(*vertex)[10 * (*vertex_count) - 8] = vect.z;
|
2017-04-24 05:25:22 -07:00
|
|
|
/* set alpha channel */
|
2015-07-03 17:39:08 -07:00
|
|
|
(*vertex)[10 * (*vertex_count) - 1] = 1.0;
|
|
|
|
/* set color */
|
|
|
|
for (color_coords = 2; color_coords < 5; color_coords++)
|
|
|
|
(*vertex)[10 * (*vertex_count) - color_coords] = (float) rand() / RAND_MAX;
|
|
|
|
/* set normal coords */
|
|
|
|
for (normal_coords = 5; normal_coords < 8; normal_coords++)
|
|
|
|
(*vertex)[10 * (*vertex_count) - normal_coords] = 1.0;
|
|
|
|
(*index)[3 * k + coord] = *leader;
|
|
|
|
(*leader)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Evas_Triangle3
|
|
|
|
convex_hull_first_tr_get(float *data, int count, int stride)
|
|
|
|
{
|
|
|
|
Evas_Triangle3 out;
|
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 triangle1;
|
|
|
|
Eina_Vector3 triangle2, triangle2_candidate;
|
|
|
|
Eina_Vector3 triangle3, triangle3_candidate;
|
|
|
|
Eina_Vector3 first, diagonal, complanar1, complanar2, candidate;
|
2015-12-07 16:12:56 -08:00
|
|
|
Eina_Quaternion normal_a, normal_b;
|
2015-07-03 17:39:08 -07:00
|
|
|
|
2016-01-04 14:50:42 -08:00
|
|
|
Evas_Real cos = 0.0, new_cos = 0.0, sin = 0.0, new_sin = 0.0, cos_2d = 0.0, new_cos_2d = 0.0;
|
|
|
|
int first_num = 0;
|
2015-07-03 17:39:08 -07:00
|
|
|
int i = 0, j = 0;
|
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle1, data[0], data[1], data[2]);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
for (i = 1, j = stride; i < count; i++, j += stride)
|
|
|
|
{
|
|
|
|
if ((triangle1.z > data[j + 2]) ||
|
2017-01-06 09:57:46 -08:00
|
|
|
((EINA_FLT_EQ(triangle1.z, data[j + 2])) && (triangle1.y > data[j + 1])) ||
|
|
|
|
((EINA_FLT_EQ(triangle1.z, data[j + 2])) && (EINA_FLT_EQ(triangle1.y, data[j + 1])) && (triangle1.x > data[j])))
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle1, data[j], data[j + 1], data[j + 2]);
|
2015-07-03 17:39:08 -07:00
|
|
|
first_num = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (first_num)
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle2, data[0], data[1], data[2]);
|
2015-07-03 17:39:08 -07:00
|
|
|
else
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle2, data[3], data[4], data[5]);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&diagonal, &triangle2, &triangle1);
|
|
|
|
sin = fabs(triangle2.z - triangle1.z) / eina_vector3_length_get(&diagonal);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
#define COMPARE_ANGLES(trigonom, triangle, previous, big, little) \
|
|
|
|
if (little > big + FLT_EPSILON) \
|
|
|
|
{ \
|
|
|
|
trigonom = new_##trigonom; \
|
|
|
|
cos_2d = new_cos_2d; \
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle, data[j], data[j + 1], data[j + 2]); \
|
2015-07-03 17:39:08 -07:00
|
|
|
} \
|
2017-01-06 09:57:46 -08:00
|
|
|
else if(!EINA_FLT_EQ(little, big) && \
|
2016-02-16 21:26:40 -08:00
|
|
|
(eina_vector3_distance_get(&triangle##_candidate, &previous) > \
|
|
|
|
eina_vector3_distance_get(&triangle, &previous))) \
|
2015-07-03 17:39:08 -07:00
|
|
|
{ \
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle, data[j], data[j + 1], data[j + 2]); \
|
2015-07-03 17:39:08 -07:00
|
|
|
}
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&complanar1, 1, 0, 0);
|
2015-07-03 17:39:08 -07:00
|
|
|
for (i = 0, j = 0; i < count; i++, j += stride)
|
|
|
|
{
|
2017-01-06 09:57:46 -08:00
|
|
|
if (EINA_FLT_EQ(data[j], triangle1.x) ||
|
|
|
|
EINA_FLT_EQ(data[j + 1], triangle1.y) ||
|
|
|
|
EINA_FLT_EQ(data[j + 2], triangle1.z))
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle2_candidate, data[j], data[j + 1], data[j + 2]);
|
|
|
|
eina_vector3_subtract(&diagonal, &triangle2_candidate, &triangle1);
|
|
|
|
new_sin = fabs(data[j + 2] - triangle1.z) / eina_vector3_length_get(&diagonal);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
2016-01-04 14:50:42 -08:00
|
|
|
if (sin > new_sin + FLT_EPSILON)
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-01-04 14:50:42 -08:00
|
|
|
sin = new_sin;
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle2, data[j], data[j + 1], data[j + 2]);
|
|
|
|
eina_vector3_subtract(&diagonal, &triangle2, &triangle1);
|
|
|
|
cos_2d = eina_vector3_angle_get(&complanar1, &diagonal);
|
2015-07-03 17:39:08 -07:00
|
|
|
}
|
2017-01-06 09:57:46 -08:00
|
|
|
else if (!EINA_FLT_EQ(sin, new_sin))
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&diagonal, &triangle2_candidate, &triangle1);
|
|
|
|
new_cos_2d = eina_vector3_angle_get(&complanar1, &diagonal);
|
2016-01-04 14:50:42 -08:00
|
|
|
|
|
|
|
COMPARE_ANGLES(cos, triangle2, triangle1, cos_2d, new_cos_2d)
|
2015-07-03 17:39:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&complanar1, triangle1.x + 1, triangle1.y, triangle1.z);
|
|
|
|
eina_vector3_set(&complanar2, triangle1.x, triangle1.y + 1, triangle1.z);
|
|
|
|
eina_vector3_plane_by_points(&normal_a, &triangle1, &complanar1, &complanar2);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
if (normal_a.z < 0)
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_scale(&normal_a, &normal_a, -1);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle3, data[0], data[1], data[2]);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
cos = -1.0;
|
|
|
|
cos_2d = 1.0;
|
|
|
|
|
|
|
|
for (i = 0, j = 0; i < count; i++, j += stride)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&candidate, data[j], data[j + 1], data[j + 2]);
|
2016-01-04 14:50:42 -08:00
|
|
|
|
2017-01-06 09:57:46 -08:00
|
|
|
if ((EINA_FLT_EQ(data[j], triangle1.x) ||
|
|
|
|
EINA_FLT_EQ(data[j + 1], triangle1.y) ||
|
|
|
|
EINA_FLT_EQ(data[j + 2], triangle1.z)) &&
|
|
|
|
(EINA_FLT_EQ(data[j], triangle2.x) ||
|
|
|
|
EINA_FLT_EQ(data[j + 1], triangle2.y) ||
|
|
|
|
EINA_FLT_EQ(data[j + 2], triangle2.z)))
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_plane_by_points(&normal_b, &triangle1, &candidate, &triangle2);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
if (normal_b.z < 0)
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_scale(&normal_b, &normal_b, -1);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
2015-12-07 16:12:56 -08:00
|
|
|
new_cos = eina_quaternion_angle_plains(&normal_a, &normal_b);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
if (new_cos > cos + FLT_EPSILON)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle3_candidate, data[j], data[j + 1], data[j + 2]);
|
|
|
|
eina_vector3_subtract(&first, &triangle2, &triangle1);
|
|
|
|
eina_vector3_subtract(&diagonal, &triangle3, &triangle1);
|
2015-07-03 17:39:08 -07:00
|
|
|
cos = new_cos;
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle3, data[j], data[j + 1], data[j + 2]);
|
|
|
|
cos_2d = eina_vector3_angle_get(&diagonal, &first);
|
2015-07-03 17:39:08 -07:00
|
|
|
}
|
2017-01-06 09:57:46 -08:00
|
|
|
else if (!EINA_FLT_EQ(new_cos, cos))
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle3_candidate, data[j], data[j + 1], data[j + 2]);
|
|
|
|
eina_vector3_subtract(&first, &triangle1, &triangle2);
|
|
|
|
eina_vector3_subtract(&diagonal, &triangle3_candidate, &triangle2);
|
|
|
|
new_cos_2d = eina_vector3_angle_get(&first, &diagonal);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
2016-01-04 14:50:42 -08:00
|
|
|
COMPARE_ANGLES(cos, triangle3, triangle2, new_cos_2d, cos_2d)
|
2015-07-03 17:39:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
evas_triangle3_set(&out, &triangle1, &triangle2, &triangle3);
|
|
|
|
|
|
|
|
#undef COMPARE_ANGLES
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2015-11-09 14:29:44 -08:00
|
|
|
evas_convex_hull_get(float *data, int count, int stride, Eina_Inarray *vertex,
|
|
|
|
Eina_Inarray *index)
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
|
|
|
Evas_Triangle3 first_elem, second_elem, *third_elem = NULL, *el = NULL;
|
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 *next = NULL, *best = NULL, *next_2d = NULL, *el_vec3 = NULL;
|
|
|
|
Eina_Vector3 tmp1, tmp2;
|
2015-12-07 16:12:56 -08:00
|
|
|
Eina_Quaternion normal_a, normal_b;
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
Eina_Array arr_elems;
|
|
|
|
Eina_Array arr_triangles;
|
|
|
|
Eina_Array arr_candidates;
|
|
|
|
Eina_Array arr_ch;
|
|
|
|
Eina_Array_Iterator iterator;
|
|
|
|
|
|
|
|
Evas_Real cos = 0.0, new_cos = 0.0, cos_2d = 0.0;
|
|
|
|
float *found_vertex = NULL;
|
|
|
|
int i = 0, j = 0, new_stride = 0, leader = 0;
|
|
|
|
int if_two = 0, first_exist_twice = 0, second_exist_twice = 0;
|
|
|
|
unsigned int k = 0;
|
2015-11-09 14:29:44 -08:00
|
|
|
unsigned short int *found_index = NULL, index_count, vertex_count = 0;
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
Eina_Bool exist1 = EINA_FALSE, pushed;
|
|
|
|
Eina_Bool equivalent_triangle = EINA_FALSE, triangle_chain = EINA_FALSE;
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Bool on_plane = EINA_FALSE, right = EINA_FALSE;
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
eina_array_step_set(&arr_elems, sizeof(Eina_Array), 1);
|
|
|
|
eina_array_step_set(&arr_triangles, sizeof(Eina_Array), 1);
|
|
|
|
eina_array_step_set(&arr_candidates, sizeof(Eina_Array), 1);
|
|
|
|
eina_array_step_set(&arr_ch, sizeof(Eina_Array), 1);
|
|
|
|
|
|
|
|
/* Finding of first triangle in convex hull */
|
|
|
|
first_elem = convex_hull_first_tr_get(data, count, stride);
|
|
|
|
|
|
|
|
eina_array_push(&arr_triangles, &first_elem);
|
|
|
|
eina_array_push(&arr_elems, &first_elem);
|
|
|
|
|
|
|
|
evas_triangle3_set(&second_elem, &first_elem.p1, &first_elem.p2, &first_elem.p0);
|
|
|
|
eina_array_push(&arr_elems, &second_elem);
|
|
|
|
eina_array_push(&arr_triangles, &second_elem);
|
|
|
|
|
|
|
|
third_elem = malloc(sizeof(Evas_Triangle3));
|
|
|
|
evas_triangle3_set(third_elem, &first_elem.p2, &first_elem.p0, &first_elem.p1);
|
|
|
|
eina_array_push(&arr_elems, third_elem);
|
|
|
|
eina_array_push(&arr_triangles, third_elem);
|
|
|
|
eina_array_push(&arr_ch, third_elem);
|
|
|
|
|
|
|
|
el = eina_array_data_get(&arr_elems, 0);
|
|
|
|
|
|
|
|
/* arr_ellems is an array of triangles, in fact it is a queue of edjes
|
|
|
|
because vertices in triangles are ordered, every edje in this queue
|
|
|
|
should have a conjugate edje in some other triangle */
|
|
|
|
while (eina_array_count(&arr_elems) > 0)
|
|
|
|
{
|
|
|
|
Evas_Triangle3 *new_elem1 = NULL, *new_elem2 = NULL;
|
|
|
|
|
|
|
|
Evas_Triangle3 *elem = eina_array_pop(&arr_elems);
|
|
|
|
|
|
|
|
cos = -1.0;
|
|
|
|
|
|
|
|
/* searching of next triangle in convex hull as given conjugate edje
|
|
|
|
and one new vertex, all vertices should be checked */
|
|
|
|
for (i = 0, j = 0; i < count; i++, j += stride)
|
|
|
|
{
|
2017-01-06 09:57:46 -08:00
|
|
|
if ((EINA_FLT_EQ(elem->p0.x, data[j]) || EINA_FLT_EQ(elem->p0.y, data[j + 1]) ||
|
|
|
|
EINA_FLT_EQ(elem->p0.z, data[j + 2])) && (EINA_FLT_EQ(elem->p1.x, data[j]) ||
|
|
|
|
EINA_FLT_EQ(elem->p1.y, data[j + 1]) || EINA_FLT_EQ(elem->p1.z, data[j + 2])) &&
|
|
|
|
(EINA_FLT_EQ(elem->p2.x, data[j]) || EINA_FLT_EQ(elem->p2.y, data[j + 1]) ||
|
|
|
|
EINA_FLT_EQ(elem->p2.z, data[j + 2])))
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
next = malloc(sizeof(Eina_Vector3));
|
|
|
|
eina_vector3_set(next, data[j], data[j + 1], data[j + 2]);
|
2015-07-03 17:39:08 -07:00
|
|
|
pushed = EINA_FALSE;
|
|
|
|
|
|
|
|
/* something like the dihedral angle between the triangles
|
|
|
|
is a determining factor in searching the necessary points */
|
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_plane_by_points(&normal_a, &elem->p0, &elem->p1, &elem->p2);
|
|
|
|
eina_vector3_plane_by_points(&normal_b, &elem->p0, &elem->p1, next);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
|
|
|
/* based on the construction of triangles, parallel but not collinear normal
|
|
|
|
means that the triangles overlap, which is the worst case */
|
|
|
|
if ((normal_a.x * normal_b.x <= 0) && (normal_a.y * normal_b.y <= 0) && (normal_a.z * normal_b.z <= 0) &&
|
|
|
|
((fabs(normal_a.x) > DBL_EPSILON) || (fabs(normal_a.y) > DBL_EPSILON) || (fabs(normal_a.z) > DBL_EPSILON)) &&
|
|
|
|
((fabs(normal_b.x) > DBL_EPSILON) || (fabs(normal_b.y) > DBL_EPSILON) || (fabs(normal_b.z) > DBL_EPSILON)))
|
|
|
|
new_cos = 1.0;
|
|
|
|
else new_cos = -1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (normal_a.x * data[j] + normal_a.y * data[j+1] + normal_a.z * data[j+2] + normal_a.w < 0)
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_scale(&normal_a, &normal_a, -1);
|
2015-07-03 17:39:08 -07:00
|
|
|
if (normal_b.x * elem->p2.x + normal_b.y * elem->p2.y + normal_b.z * elem->p2.z + normal_b.w < 0)
|
2015-12-07 16:12:56 -08:00
|
|
|
eina_quaternion_scale(&normal_b, &normal_b, -1);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
2015-12-07 16:12:56 -08:00
|
|
|
new_cos = eina_quaternion_angle_plains(&normal_a, &normal_b);
|
2015-07-03 17:39:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* MIN_DIFF is more useful for dihedral angles apparently */
|
|
|
|
if (new_cos > cos + MIN_DIFF)
|
|
|
|
{
|
|
|
|
cos = new_cos;
|
|
|
|
EINA_ARRAY_ITER_NEXT(&arr_candidates, k, el_vec3, iterator)
|
|
|
|
free(el_vec3);
|
|
|
|
|
|
|
|
/* Vertex gets into arr_candidates if the corresponding cosine is the maximum */
|
|
|
|
eina_array_flush(&arr_candidates);
|
|
|
|
eina_array_step_set(&arr_candidates, sizeof(Eina_Array), 1);
|
|
|
|
eina_array_push(&arr_candidates, next);
|
|
|
|
pushed = EINA_TRUE;
|
|
|
|
}
|
|
|
|
else if (fabs(new_cos - cos) < MIN_DIFF)
|
|
|
|
{
|
|
|
|
exist1 = EINA_FALSE;
|
|
|
|
|
|
|
|
for (k = 0; (k < eina_array_count(&arr_candidates)) && !exist1; k++)
|
|
|
|
{
|
|
|
|
next_2d = eina_array_data_get(&arr_candidates, k);
|
2016-02-16 21:26:40 -08:00
|
|
|
exist1 = eina_vector3_equivalent(next, next_2d);
|
2015-07-03 17:39:08 -07:00
|
|
|
}
|
|
|
|
if (!exist1)
|
|
|
|
{
|
|
|
|
eina_array_push(&arr_candidates, next);
|
|
|
|
pushed = EINA_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pushed)
|
|
|
|
free(next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
on_plane = EINA_FALSE;
|
2015-07-03 17:39:08 -07:00
|
|
|
right = EINA_FALSE;
|
|
|
|
|
2015-11-22 23:18:51 -08:00
|
|
|
/* The case when several points are found, is discussed below.
|
2015-07-03 17:39:08 -07:00
|
|
|
This case is interesting because the convex hull in the
|
|
|
|
two-dimensional subspace should be filled further */
|
2017-01-06 09:57:46 -08:00
|
|
|
if ((!EINA_FLT_EQ(cos, 1.0)) && (1 < eina_array_count(&arr_candidates)))
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 angle_from, angle_to;
|
2015-07-03 17:39:08 -07:00
|
|
|
next_2d = eina_array_data_get(&arr_candidates, 0);
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_plane_by_points(&normal_b, &elem->p1, &elem->p0, next_2d);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
if (normal_b.x * elem->p2.x + normal_b.y * elem->p2.y + normal_b.z * elem->p2.z + normal_b.w > 0)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&angle_from, &elem->p0, &elem->p1);
|
2015-07-03 17:39:08 -07:00
|
|
|
right = EINA_TRUE;
|
|
|
|
}
|
|
|
|
else
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&angle_from, &elem->p1, &elem->p0);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
cos_2d = -1.0;
|
|
|
|
|
|
|
|
EINA_ARRAY_ITER_NEXT(&arr_candidates, k, next_2d, iterator)
|
|
|
|
{
|
|
|
|
/* Selection of the required vertex occurs on the basis of a specific angle */
|
|
|
|
if (right)
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&angle_to, next_2d, &elem->p0);
|
2015-07-03 17:39:08 -07:00
|
|
|
else
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&angle_to, next_2d, &elem->p1);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
new_cos = eina_vector3_dot_product(&angle_from, &angle_to) /
|
|
|
|
(eina_vector3_length_get(&angle_from) * eina_vector3_length_get(&angle_to));
|
2015-07-03 17:39:08 -07:00
|
|
|
if (new_cos > cos_2d + FLT_EPSILON)
|
|
|
|
{
|
|
|
|
cos_2d = new_cos;
|
|
|
|
best = eina_array_data_get(&arr_candidates, k);
|
|
|
|
}
|
2017-01-06 09:57:46 -08:00
|
|
|
else if (!EINA_FLT_EQ(new_cos, cos_2d))
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
if ((right && (eina_vector3_distance_get(best, &elem->p0) < eina_vector3_length_get(&angle_from))) ||
|
|
|
|
(!right && (eina_vector3_distance_get(best, &elem->p1) < eina_vector3_length_get(&angle_from))))
|
2015-07-03 17:39:08 -07:00
|
|
|
best = eina_array_data_get(&arr_candidates, k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This event will take place after the previous,
|
|
|
|
in fact, choice of first triangle in a new two-dimensional
|
|
|
|
convex hull allows to fill it fan counterclockwise when viewed from the inside */
|
2017-01-06 09:57:46 -08:00
|
|
|
else if ((EINA_FLT_EQ(cos, 1.0)) && (1 < eina_array_count(&arr_candidates)))
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 angle_from, angle_to;
|
|
|
|
eina_vector3_subtract(&angle_from, &elem->p0, &elem->p1);
|
2015-07-03 17:39:08 -07:00
|
|
|
cos_2d = -1.0;
|
|
|
|
EINA_ARRAY_ITER_NEXT(&arr_candidates, k, next_2d, iterator)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&angle_to, next_2d, &elem->p0);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_plane_by_points(&normal_a, &elem->p0, &elem->p1, &elem->p2);
|
|
|
|
eina_vector3_plane_by_points(&normal_b, &elem->p0, &elem->p1, next_2d);
|
2015-07-03 17:39:08 -07:00
|
|
|
if ((normal_a.x * normal_b.x <= 0) && (normal_a.y * normal_b.y <= 0) && (normal_a.z * normal_b.z <= 0))
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
new_cos = eina_vector3_dot_product(&angle_from, &angle_to) /
|
|
|
|
(eina_vector3_length_get(&angle_from) * eina_vector3_length_get(&angle_to));
|
2015-07-03 17:39:08 -07:00
|
|
|
if (new_cos > cos_2d + FLT_EPSILON)
|
|
|
|
{
|
|
|
|
cos_2d = new_cos;
|
|
|
|
best = eina_array_data_get(&arr_candidates, k);
|
|
|
|
}
|
2017-01-06 09:57:46 -08:00
|
|
|
else if (!EINA_FLT_EQ(new_cos, cos_2d))
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
if (eina_vector3_distance_get(best, &elem->p0) < eina_vector3_length_get(&angle_to))
|
2015-07-03 17:39:08 -07:00
|
|
|
best = eina_array_data_get(&arr_candidates, k);
|
|
|
|
}
|
2016-02-16 21:26:40 -08:00
|
|
|
on_plane = EINA_TRUE;
|
2015-07-03 17:39:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
best = eina_array_data_get(&arr_candidates, 0);
|
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_plane_by_points(&normal_b, &elem->p0, &elem->p1, best);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
if_two = 0;
|
|
|
|
first_exist_twice = 0;
|
|
|
|
second_exist_twice = 0;
|
|
|
|
equivalent_triangle = EINA_FALSE;
|
|
|
|
triangle_chain = EINA_FALSE;
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_copy(&tmp1, &elem->p0);
|
|
|
|
eina_vector3_copy(&tmp2, &elem->p1);
|
2015-07-03 17:39:08 -07:00
|
|
|
new_elem1 = malloc(sizeof(Evas_Triangle3));
|
|
|
|
evas_triangle3_set(new_elem1, best, &tmp1, &tmp2);
|
|
|
|
pushed = EINA_FALSE;
|
|
|
|
|
|
|
|
/* verification that the edje has not been found previously */
|
|
|
|
EINA_ARRAY_ITER_NEXT(&arr_triangles, k, el, iterator)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
if (convex_hull_triangle3_first_edje(el, &elem->p0, &elem->p1))
|
2015-07-03 17:39:08 -07:00
|
|
|
if_two++;
|
2016-02-16 21:26:40 -08:00
|
|
|
if (evas_triangle3_equivalent(el, new_elem1))
|
2015-07-03 17:39:08 -07:00
|
|
|
equivalent_triangle++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EINA_ARRAY_ITER_NEXT(&arr_triangles, k, el, iterator)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
if ((k > 2) && (convex_hull_triangle3_not_first_edje(el, &elem->p0, best) ||
|
|
|
|
convex_hull_triangle3_not_first_edje(el, &elem->p1, best)))
|
2015-07-03 17:39:08 -07:00
|
|
|
triangle_chain = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* There is a specific order according to which the edjes are entered in arr_elems */
|
2016-02-16 21:26:40 -08:00
|
|
|
if (!on_plane && !right)
|
2015-07-03 17:39:08 -07:00
|
|
|
{
|
|
|
|
if ((!equivalent_triangle) && (!second_exist_twice) && (!triangle_chain) && (if_two < 2))
|
|
|
|
{
|
|
|
|
new_elem2 = malloc(sizeof(Evas_Triangle3));
|
|
|
|
evas_triangle3_set(new_elem2, best, &tmp2, &tmp1);
|
|
|
|
eina_array_push(&arr_elems, new_elem2);
|
|
|
|
|
|
|
|
/* triangles whose edges have been found should be entered into the arr_triangles
|
|
|
|
to optimize the algorithm */
|
|
|
|
if ((first_exist_twice < 2) && (second_exist_twice < 2))
|
|
|
|
eina_array_push(&arr_triangles, eina_array_data_get(&arr_elems, eina_array_count(&arr_elems) - 1));
|
|
|
|
}
|
|
|
|
if ((!equivalent_triangle) && (!first_exist_twice) && (!triangle_chain) && (if_two < 2))
|
|
|
|
{
|
|
|
|
eina_array_push(&arr_elems, new_elem1);
|
|
|
|
if ((first_exist_twice < 2) && (second_exist_twice < 2))
|
|
|
|
{
|
|
|
|
pushed = EINA_TRUE;
|
|
|
|
|
|
|
|
/* eina_ch is the resultant vector of all triangles in convex hull */
|
|
|
|
eina_array_push(&arr_ch, eina_array_data_get(&arr_elems, eina_array_count(&arr_elems) - 1));
|
|
|
|
eina_array_push(&arr_triangles, eina_array_data_get(&arr_elems, eina_array_count(&arr_elems) - 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((!equivalent_triangle) && (!first_exist_twice) && (!triangle_chain) && (if_two < 2))
|
|
|
|
{
|
|
|
|
eina_array_push(&arr_elems, new_elem1);
|
|
|
|
if ((first_exist_twice < 2) && (second_exist_twice < 2))
|
|
|
|
{
|
|
|
|
pushed = EINA_TRUE;
|
|
|
|
eina_array_push(&arr_ch, eina_array_data_get(&arr_elems, eina_array_count(&arr_elems) - 1));
|
|
|
|
eina_array_push(&arr_triangles, eina_array_data_get(&arr_elems, eina_array_count(&arr_elems) - 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((!equivalent_triangle) && (!second_exist_twice) && (!triangle_chain) && (if_two < 2))
|
|
|
|
{
|
|
|
|
new_elem2 = malloc(sizeof(Evas_Triangle3));
|
|
|
|
evas_triangle3_set(new_elem2, best, &tmp2, &tmp1);
|
|
|
|
eina_array_push(&arr_elems, new_elem2);
|
|
|
|
|
|
|
|
if ((first_exist_twice < 2) && (second_exist_twice < 2))
|
|
|
|
eina_array_push(&arr_triangles, eina_array_data_get(&arr_elems, eina_array_count(&arr_elems)-1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!pushed)
|
|
|
|
free (new_elem1);
|
|
|
|
}
|
|
|
|
|
2015-11-09 14:29:44 -08:00
|
|
|
index_count = 3 * eina_array_count(&arr_ch);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
found_vertex = (float*) malloc(10 * sizeof(float));
|
2015-11-09 14:29:44 -08:00
|
|
|
found_index = (unsigned short int*) malloc(index_count * sizeof(unsigned short int));
|
2015-07-03 17:39:08 -07:00
|
|
|
j = 0;
|
|
|
|
|
2016-12-19 16:28:43 -08:00
|
|
|
#define CHECK_AND_SET_VERTEX(coord) \
|
|
|
|
exist1 = EINA_FALSE; \
|
|
|
|
for (i = 0, new_stride = 0; (i < vertex_count) && !exist1; i++, new_stride += 10) \
|
|
|
|
{ \
|
2017-01-06 09:57:46 -08:00
|
|
|
if ((k > 0) && !EINA_FLT_EQ(el->p##coord.x, found_vertex[new_stride]) && \
|
|
|
|
!EINA_FLT_EQ(el->p##coord.y, found_vertex[new_stride + 1]) && \
|
|
|
|
!EINA_FLT_EQ(el->p##coord.z, found_vertex[new_stride + 2])) \
|
2016-12-19 16:28:43 -08:00
|
|
|
{ \
|
|
|
|
exist1 = EINA_TRUE; \
|
|
|
|
found_index[3 * k + coord] = i; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
if (!exist1) \
|
|
|
|
convex_hull_vertex_set(el, &vertex_count, &found_vertex, \
|
|
|
|
&found_index, k, &leader, coord);
|
2015-07-03 17:39:08 -07:00
|
|
|
|
|
|
|
EINA_ARRAY_ITER_NEXT(&arr_ch, k, el, iterator)
|
|
|
|
{
|
|
|
|
CHECK_AND_SET_VERTEX(0)
|
|
|
|
CHECK_AND_SET_VERTEX(1)
|
|
|
|
CHECK_AND_SET_VERTEX(2)
|
|
|
|
|
|
|
|
j += 30;
|
|
|
|
}
|
|
|
|
|
2015-11-09 14:29:44 -08:00
|
|
|
for (i = 0; i < 10 * (vertex_count); i++)
|
|
|
|
eina_inarray_push(vertex, &found_vertex[i]);
|
|
|
|
|
|
|
|
for (i = 0; i < index_count; i++)
|
|
|
|
eina_inarray_push(index, &found_index[i]);
|
|
|
|
|
2015-07-03 17:39:08 -07:00
|
|
|
free(found_vertex);
|
|
|
|
|
|
|
|
free(found_index);
|
|
|
|
|
|
|
|
EINA_ARRAY_ITER_NEXT(&arr_triangles, k, el, iterator)
|
|
|
|
{
|
|
|
|
if (k > 2)
|
|
|
|
free(el);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(third_elem);
|
|
|
|
|
|
|
|
EINA_ARRAY_ITER_NEXT(&arr_candidates, k, el_vec3, iterator)
|
|
|
|
free(el_vec3);
|
|
|
|
|
|
|
|
eina_array_flush(&arr_candidates);
|
|
|
|
eina_array_flush(&arr_ch);
|
|
|
|
eina_array_flush(&arr_elems);
|
|
|
|
eina_array_flush(&arr_triangles);
|
|
|
|
|
|
|
|
#undef CHECK_AND_SET_VERTEX
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2015-07-29 13:24:02 -07:00
|
|
|
|
|
|
|
static inline void
|
2016-02-16 21:26:40 -08:00
|
|
|
tangent_space_weighted_sum(Eina_Vector3 *big_t, Eina_Vector3 *little_t,
|
2015-07-29 13:24:02 -07:00
|
|
|
Evas_Real *big_angle, Evas_Real little_angle)
|
|
|
|
{
|
|
|
|
/* one way to calculate tangent in vertex that is found in many triangles */
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_scale(big_t, big_t, *big_angle / (*big_angle + little_angle));
|
|
|
|
eina_vector3_scale(little_t, little_t, little_angle / (*big_angle + little_angle));
|
|
|
|
eina_vector3_add(big_t, big_t, little_t);
|
2015-07-29 13:24:02 -07:00
|
|
|
*big_angle += little_angle;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline Evas_Real
|
2016-02-16 21:26:40 -08:00
|
|
|
tangent_space_triangle_angle_get(Eina_Vector3 *first, Eina_Vector3 *second, Eina_Vector3 *third)
|
2015-07-29 13:24:02 -07:00
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 a, b, c;
|
2015-07-29 13:24:02 -07:00
|
|
|
Evas_Real cos, arccos;
|
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&a, second, third);
|
|
|
|
eina_vector3_subtract(&b, third, first);
|
|
|
|
eina_vector3_subtract(&c, first, second);
|
2015-07-29 13:24:02 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
cos = -(eina_vector3_length_square_get(&a) - eina_vector3_length_square_get(&b) -
|
|
|
|
eina_vector3_length_square_get(&c)) / (2 * eina_vector3_length_get(&b) *
|
|
|
|
eina_vector3_length_get(&c));
|
2015-07-29 13:24:02 -07:00
|
|
|
arccos = acos(cos);
|
|
|
|
|
|
|
|
return arccos;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
evas_tangent_space_get(float *data, float *tex_data, float *normal_data, unsigned short int *index, int vertex_count,
|
|
|
|
int index_count, int stride, int tex_stride, int normal_stride, float **tangent)
|
|
|
|
{
|
|
|
|
Eina_Bool if_not_primitive = EINA_FALSE;
|
|
|
|
Evas_Real big_angle, little_angle;
|
|
|
|
Evas_Triangle3 triangle;
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector2 tex1, tex2, tex3;
|
|
|
|
Eina_Vector3 big_tangent, little_tangent, normal;
|
2015-12-07 16:12:56 -08:00
|
|
|
Eina_Quaternion *plain = NULL;
|
2015-08-05 03:12:24 -07:00
|
|
|
int i, j, k, l, m, found_index = 0;
|
2015-07-29 13:24:02 -07:00
|
|
|
int indexes[3];
|
|
|
|
|
|
|
|
if (!tex_data)
|
|
|
|
{
|
|
|
|
ERR("Impossible to calculate tangent space, texture coordinates not found %d %s", __LINE__, __FILE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(*tangent))
|
|
|
|
{
|
|
|
|
ERR("Failed to allocate memory %d %s", __LINE__, __FILE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
float *tmp_tangent = (float*) malloc((3 * vertex_count) * sizeof(float));
|
|
|
|
if (tmp_tangent == NULL)
|
|
|
|
{
|
|
|
|
ERR("Failed to allocate memory %d %s", __LINE__, __FILE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index_count == 0)
|
|
|
|
{
|
|
|
|
if_not_primitive = EINA_TRUE;
|
|
|
|
index_count = vertex_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0, j = 0, k = 0; i < vertex_count; i++, j += stride, k += normal_stride)
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&big_tangent, 0.0, 0.0, 0.0);
|
2015-07-29 13:24:02 -07:00
|
|
|
big_angle = 0.0;
|
|
|
|
for (l = 0, m = 0; l < vertex_count; l++, m += stride)
|
|
|
|
{
|
|
|
|
/* tangent for vertex is calculating in each triangle in which the vertex is found */
|
|
|
|
if ((fabs(data[j] - data[m]) < FLT_EPSILON) &&
|
|
|
|
(fabs(data[j + 1] - data[m + 1]) < FLT_EPSILON) &&
|
|
|
|
(fabs(data[j + 2] - data[m + 2]) < FLT_EPSILON) &&
|
2017-01-06 09:57:46 -08:00
|
|
|
((m == j) || ((!EINA_FLT_EQ(tex_data[i * tex_stride], 0.0)) &&
|
|
|
|
!EINA_FLT_EQ(tex_data[i * tex_stride + 1], 0.0) &&
|
|
|
|
!EINA_FLT_EQ(tex_data[i * tex_stride], 1.0) &&
|
|
|
|
!EINA_FLT_EQ(tex_data[i * tex_stride + 1], 1.0))))
|
2015-07-29 13:24:02 -07:00
|
|
|
{
|
|
|
|
found_index = l;
|
|
|
|
for (k = 0; k < index_count; k += 3)
|
|
|
|
{
|
|
|
|
/* there is no index count and indexes , for models that are not a primitive,
|
|
|
|
so we use the vertex count and an ordered array instead of them */
|
|
|
|
if (if_not_primitive)
|
|
|
|
{
|
|
|
|
indexes[0] = k;
|
|
|
|
indexes[1] = k + 1;
|
|
|
|
indexes[2] = k + 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
indexes[0] = index[k];
|
|
|
|
indexes[1] = index[k + 1];
|
|
|
|
indexes[2] = index[k + 2];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((found_index == indexes[0]) ||
|
|
|
|
(found_index == indexes[1]) ||
|
|
|
|
(found_index == indexes[2]))
|
|
|
|
{
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&triangle.p0, data[indexes[0] * stride], data[indexes[0] * stride + 1], data[indexes[0] * stride + 2]);
|
|
|
|
eina_vector3_set(&triangle.p1, data[indexes[1] * stride], data[indexes[1] * stride + 1], data[indexes[1] * stride + 2]);
|
|
|
|
eina_vector3_set(&triangle.p2, data[indexes[2] * stride], data[indexes[2] * stride + 1], data[indexes[2] * stride + 2]);
|
2015-07-29 13:24:02 -07:00
|
|
|
if (plain)
|
|
|
|
free(plain);
|
2015-12-07 16:12:56 -08:00
|
|
|
plain = malloc(sizeof(Eina_Quaternion));
|
2015-07-29 13:24:02 -07:00
|
|
|
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_plane_by_points(plain, &triangle.p0, &triangle.p1, &triangle.p2);
|
2015-07-29 13:24:02 -07:00
|
|
|
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];
|
|
|
|
tex2.y = tex_data[indexes[1] * tex_stride + 1];
|
|
|
|
tex3.x = tex_data[indexes[2] * tex_stride];
|
|
|
|
tex3.y = tex_data[indexes[2] * tex_stride + 1];
|
|
|
|
|
|
|
|
/* calculate the tangent */
|
|
|
|
tangent_new_basis(&little_tangent, &triangle,
|
|
|
|
&tex1, &tex2, &tex3);
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_normalize(&little_tangent, &little_tangent);
|
2015-07-29 13:24:02 -07:00
|
|
|
|
|
|
|
/* founding the angle in triangle in founded vertex */
|
|
|
|
if (found_index == indexes[0])
|
|
|
|
little_angle = tangent_space_triangle_angle_get(&triangle.p0, &triangle.p1, &triangle.p2);
|
|
|
|
|
|
|
|
else if (found_index == indexes[1])
|
|
|
|
little_angle = tangent_space_triangle_angle_get(&triangle.p1, &triangle.p0, &triangle.p2);
|
|
|
|
|
|
|
|
else
|
|
|
|
little_angle = tangent_space_triangle_angle_get(&triangle.p2, &triangle.p0, &triangle.p1);
|
|
|
|
|
|
|
|
if (evas_triangle3_is_line(&triangle))
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&big_tangent, 1.0, 0.0, 0.0);
|
2015-07-29 13:24:02 -07:00
|
|
|
|
|
|
|
else
|
|
|
|
tangent_space_weighted_sum(&big_tangent, &little_tangent, &big_angle, little_angle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_set(&normal, normal_data[j], normal_data[j + 1], normal_data[j + 2]);
|
|
|
|
eina_vector3_orthogonal_projection_on_plane(&big_tangent, &big_tangent, &normal);
|
|
|
|
eina_vector3_normalize(&big_tangent, &big_tangent);
|
2015-07-29 13:24:02 -07:00
|
|
|
tmp_tangent[i * 3] = big_tangent.x;
|
|
|
|
tmp_tangent[i * 3 + 1] = big_tangent.y;
|
|
|
|
tmp_tangent[i * 3 + 2] = big_tangent.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(*tangent, tmp_tangent, (3 * vertex_count) * sizeof(float));
|
|
|
|
free(tmp_tangent);
|
2015-10-19 11:00:22 -07:00
|
|
|
free(plain);
|
2015-07-29 13:24:02 -07:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2016-02-12 11:58:04 -08:00
|
|
|
|
|
|
|
static inline void
|
2016-02-16 21:26:40 -08:00
|
|
|
calculate_box(Evas_Box3 *box3, int vertex_count, Eina_Vector3 *vertex_position)
|
2016-02-12 11:58:04 -08:00
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
float vxmin, vymin, vzmin, vxmax, vymax, vzmax;
|
|
|
|
|
|
|
|
vxmax = vxmin = vertex_position[0].x;
|
|
|
|
vymax = vymin = vertex_position[0].y;
|
|
|
|
vzmax = vzmin = vertex_position[0].z;
|
|
|
|
|
|
|
|
for (i = 1; i < vertex_count; ++i)
|
|
|
|
{
|
|
|
|
if (vxmin > vertex_position[i].x) vxmin = vertex_position[i].x;
|
|
|
|
if (vxmax < vertex_position[i].x) vxmax = vertex_position[i].x;
|
|
|
|
if (vymin > vertex_position[i].y) vymin = vertex_position[i].y;
|
|
|
|
if (vymax < vertex_position[i].y) vymax = vertex_position[i].y;
|
|
|
|
if (vzmin > vertex_position[i].z) vzmin = vertex_position[i].z;
|
|
|
|
if (vzmax < vertex_position[i].z) vzmax = vertex_position[i].z;
|
|
|
|
}
|
|
|
|
evas_box3_set(box3, vxmin, vymin, vzmin, vxmax, vymax, vzmax);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2016-02-16 21:26:40 -08:00
|
|
|
calculate_sphere(Evas_Sphere *sphere, int vertex_count, Eina_Vector3 *vertex_position)
|
2016-02-12 11:58:04 -08:00
|
|
|
{
|
|
|
|
float radius = 0.0001f;
|
2016-02-16 21:26:40 -08:00
|
|
|
Eina_Vector3 center, pos, diff;
|
2016-02-12 11:58:04 -08:00
|
|
|
float len, alpha, alpha2;
|
|
|
|
int i, k;
|
|
|
|
|
|
|
|
// shuffle array for averaging algorithms error
|
|
|
|
for (i = 0; i < vertex_count; i++)
|
|
|
|
{
|
|
|
|
k = i + rand()%(vertex_count-i);
|
|
|
|
pos = vertex_position[i];
|
|
|
|
vertex_position[i] = vertex_position[k];
|
|
|
|
vertex_position[k] = pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
center = vertex_position[0];
|
|
|
|
|
|
|
|
for (k = 0; k < 2; k++)
|
|
|
|
{
|
|
|
|
for (i = 0; i < vertex_count; ++i)
|
|
|
|
{
|
|
|
|
pos = vertex_position[i];
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&diff, &pos, ¢er);
|
|
|
|
len = eina_vector3_length_get(&diff);
|
2016-02-12 11:58:04 -08:00
|
|
|
if (len > radius)
|
|
|
|
{
|
|
|
|
alpha = len / radius;
|
|
|
|
alpha2 = alpha * alpha;
|
|
|
|
radius = 0.5f * (alpha + 1 / alpha) * radius;
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_scale(&pos, &pos, 1 - 1 / alpha2);
|
|
|
|
eina_vector3_scale(¢er, ¢er, (1 + 1 / alpha2));
|
|
|
|
eina_vector3_add(¢er, ¢er, &pos);
|
|
|
|
eina_vector3_scale(¢er, ¢er, 0.5f);
|
2016-02-12 11:58:04 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < vertex_count; ++i)
|
|
|
|
{
|
|
|
|
pos = vertex_position[i];
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_subtract(&diff, &pos, ¢er);
|
|
|
|
len = eina_vector3_length_get(&diff);
|
2016-02-12 11:58:04 -08:00
|
|
|
|
|
|
|
if (len > radius)
|
|
|
|
{
|
|
|
|
radius = (radius + len) / 2.0f;
|
2016-02-16 21:26:40 -08:00
|
|
|
eina_vector3_scale(&diff, &diff, (len - radius) / len);
|
|
|
|
eina_vector3_add(¢er, ¢er, &diff);
|
2016-02-12 11:58:04 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sphere->radius = radius;
|
|
|
|
sphere->center = center;
|
|
|
|
}
|