evas: Evas_3D - add evas_box3_ray3_intersect and evas_box2_intersect_2d functions.

Summary: First function is used for intersection of ray and parallelepiped, the second one - for intersection of ray and rectangle in two-dimensional case.

@feature

Reviewers: Hermet, cedric, raster

CC: cedric

Differential Revision: https://phab.enlightenment.org/D956

Signed-off-by: Cedric BAIL <c.bail@partner.samsung.com>
This commit is contained in:
perepelits.m 2014-06-05 20:50:42 +02:00 committed by Cedric BAIL
parent 700f4396e1
commit e5905f3f74
1 changed files with 169 additions and 2 deletions

View File

@ -3,6 +3,7 @@
#endif
#include <math.h>
#include <float.h>
#define DEGREE_TO_RADIAN(x) (((x) * M_PI) / 180.0)
#define EVAS_MATRIX_IS_IDENTITY 0x00000001
@ -1537,12 +1538,178 @@ evas_ray3_init(Evas_Ray3 *ray, Evas_Real x, Evas_Real y, const Evas_Mat4 *mvp)
}
static inline Eina_Bool
evas_box3_ray3_intersect(const Evas_Box3 *box EINA_UNUSED, const Evas_Ray3 *ray EINA_UNUSED)
evas_box2_intersect_2d(const Evas_Box2 *box, const Evas_Vec2 *org, const Evas_Vec2 *dir)
{
/* TODO: */
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 */
if ((dir->x != 0.0f) && (dir->y != 0.0f))
{
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 */
else if (dir->x == 0.0f)
{
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;
return EINA_TRUE;
}
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;
Evas_Vec2 org2;
Evas_Vec2 dir2;
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 */
if ((ray->dir.x != 0.0f) && (ray->dir.y != 0.0f) && (ray->dir.z != 0.0f))
{
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 */
if (ray->dir.x == 0.0f)
{
if ((ray->org.x < box->p0.x) || (ray->org.x > box->p1.x))
return EINA_FALSE;
else
{
evas_vec2_set(&org2, ray->org.y, ray->org.z);
evas_vec2_set(&dir2, ray->dir.y, ray->dir.z);
evas_box2_set(&box2, box->p0.y, box->p0.z, box->p1.y, box->p1.z);
intersect = evas_box2_intersect_2d(&box2, &org2, &dir2);
}
}
if (ray->dir.y == 0.0f)
{
if ((ray->org.y < box->p0.y) || (ray->org.y > box->p1.y))
return EINA_FALSE;
else
{
evas_vec2_set(&org2, ray->org.x, ray->org.z);
evas_vec2_set(&dir2, ray->dir.x, ray->dir.z);
evas_box2_set(&box2, box->p0.x, box->p0.z, box->p1.x, box->p1.z);
intersect = evas_box2_intersect_2d(&box2, &org2, &dir2);
}
}
if (ray->dir.z == 0.0f)
{
if (ray->org.z < box->p0.z || ray->org.z > box->p1.z)
return EINA_FALSE;
else
{
evas_vec2_set(&org2, ray->org.x, ray->org.y);
evas_vec2_set(&dir2, ray->dir.x, ray->dir.y);
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;
}
static inline Evas_Real
evas_reciprocal_sqrt(Evas_Real x)
{