Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix graphene_box_get_center() #166

Merged
merged 5 commits into from
Aug 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 96 additions & 7 deletions src/graphene-box.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,10 @@

#include <math.h>
#include <stdio.h>
#include <string.h>

#ifdef HAVE_PTHREAD
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#endif

Expand Down Expand Up @@ -425,6 +424,60 @@ graphene_box_get_depth (const graphene_box_t *box)
return fabsf (res);
}

static inline bool
graphene_box_is_empty (const graphene_box_t *box)
{
#ifdef HAVE_ISINFF
float vmin[3], vmax[3];

graphene_simd4f_dup_3f (box->min.value, vmin);
graphene_simd4f_dup_3f (box->max.value, vmax);

return (isinff (vmin[0]) == 1 && isinff (vmin[1]) == 1 && isinff (vmin[2]) == 1) &&
(isinff (vmax[0]) == -1 && isinff (vmax[1]) == -1 && isinff (vmax[2]) == -1);
#else
graphene_simd4f_t neg_inf = graphene_simd4f_init (-INFINITY, -INFINITY, -INFINITY, 0.f);
graphene_simd4f_t pos_inf = graphene_simd4f_init (INFINITY, INFINITY, INFINITY, 0.f);

/* This is only every going to be valid for boxes that we have
* initialized ourselves, because we use the same values; the
* bitwise comparison will not hold for infinities generated by
* other operations
*/
int min_cmp = memcmp (&box->min.value, &pos_inf, sizeof (graphene_simd4f_t));
int max_cmp = memcmp (&box->max.value, &neg_inf, sizeof (graphene_simd4f_t));

return min_cmp == 0 && max_cmp == 0;
#endif
}

static inline bool
graphene_box_is_infinity (const graphene_box_t *box)
{
#ifdef HAVE_ISINFF
float vmin[3], vmax[3];

graphene_simd4f_dup_3f (box->min.value, vmin);
graphene_simd4f_dup_3f (box->max.value, vmax);

return (isinff (vmin[0]) == -1 && isinff (vmin[1]) == -1 && isinff (vmin[2]) == -1) &&
(isinff (vmax[0]) == 1 && isinff (vmax[1]) == 1 && isinff (vmax[2]) == 1);
#else
graphene_simd4f_t neg_inf = graphene_simd4f_init (-INFINITY, -INFINITY, -INFINITY, 0.f);
graphene_simd4f_t pos_inf = graphene_simd4f_init (INFINITY, INFINITY, INFINITY, 0.f);

/* This is only every going to be valid for boxes that we have
* initialized ourselves, because we use the same values; the
* bitwise comparison will not hold for infinities generated by
* other operations
*/
int min_cmp = memcmp (&box->min.value, &neg_inf, sizeof (graphene_simd4f_t));
int max_cmp = memcmp (&box->max.value, &pos_inf, sizeof (graphene_simd4f_t));

return min_cmp == 0 && max_cmp == 0;
#endif
}

/**
* graphene_box_get_size:
* @box: a #graphene_box_t
Expand All @@ -439,7 +492,12 @@ void
graphene_box_get_size (const graphene_box_t *box,
graphene_vec3_t *size)
{
size->value = graphene_simd4f_sub (box->max.value, box->min.value);
if (graphene_box_is_empty (box))
size->value = graphene_simd4f_init_zero ();
else if (graphene_box_is_infinity (box))
size->value = graphene_simd4f_init (INFINITY, INFINITY, INFINITY, 0.f);
else
size->value = graphene_simd4f_sub (box->max.value, box->min.value);
}

/**
Expand All @@ -458,7 +516,13 @@ graphene_box_get_center (const graphene_box_t *box,
{
graphene_vec3_t res;

graphene_vec3_subtract (&box->max, &box->min, &res);
if (graphene_box_is_empty (box) || graphene_box_is_infinity (box))
{
graphene_point3d_init (center, 0.f, 0.f, 0.f);
return;
}

graphene_vec3_add (&box->min, &box->max, &res);
graphene_vec3_scale (&res, 0.5f, &res);

graphene_point3d_init_from_vec3 (center, &res);
Expand Down Expand Up @@ -542,6 +606,12 @@ bool
graphene_box_contains_point (const graphene_box_t *box,
const graphene_point3d_t *point)
{
if (graphene_box_is_empty (box))
return false;

if (graphene_box_is_infinity (box))
return true;

graphene_simd4f_t p = graphene_simd4f_init (point->x, point->y, point->z, 0.f);

if (graphene_simd4f_cmp_ge (p, box->min.value) &&
Expand All @@ -567,6 +637,12 @@ bool
graphene_box_contains_box (const graphene_box_t *a,
const graphene_box_t *b)
{
if (graphene_box_is_empty (a) || graphene_box_is_infinity (b))
return false;

if (graphene_box_is_infinity (a) || graphene_box_is_empty (b))
return true;

/* we cheat a bit and access the SIMD directly */
if (graphene_simd4f_cmp_ge (b->min.value, a->min.value) &&
graphene_simd4f_cmp_le (b->max.value, a->max.value))
Expand All @@ -582,6 +658,16 @@ box_equal (const void *p1,
const graphene_box_t *a = p1;
const graphene_box_t *b = p2;

if (graphene_box_is_empty (a) && graphene_box_is_empty (b))
return true;
else if (graphene_box_is_empty (a) || graphene_box_is_empty (b))
return false;

if (graphene_box_is_infinity (a) && graphene_box_is_infinity (b))
return true;
else if (graphene_box_is_infinity (a) || graphene_box_is_infinity (b))
return false;

return graphene_vec3_equal (&a->min, &b->min) &&
graphene_vec3_equal (&a->max, &b->max);
}
Expand Down Expand Up @@ -618,12 +704,15 @@ void
graphene_box_get_bounding_sphere (const graphene_box_t *box,
graphene_sphere_t *sphere)
{
graphene_point3d_t center;
graphene_vec3_t size;

graphene_vec3_subtract (&box->max, &box->min, &size);
graphene_box_get_center (box, &center);

graphene_box_get_size (box, &size);
float radius = graphene_vec3_length (&size) * 0.5f;

graphene_vec3_scale (&size, 0.5f, &sphere->center);
sphere->radius = graphene_vec3_length (&size) * 0.5f;
graphene_sphere_init (sphere, &center, radius);
}

enum {
Expand Down
28 changes: 25 additions & 3 deletions src/tests/box.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,20 +192,42 @@ box_center (mutest_spec_t *spec)
{
graphene_point3d_t zero = GRAPHENE_POINT3D_INIT (0.0f, 0.0f, 0.0f);
graphene_point3d_t half = GRAPHENE_POINT3D_INIT (0.5f, 0.5f, 0.5f);
graphene_point3d_t minus_half = GRAPHENE_POINT3D_INIT (-0.5f, -0.5f, -0.5f);
graphene_point3d_t center;
graphene_box_t b;

graphene_box_init_from_box (&b, graphene_box_zero ());
graphene_box_get_center (&b, &center);
mutest_expect ("box(zero).center() is (0, 0, 0)",
mutest_expect ("box(zero).center() to be in (0, 0, 0)",
mutest_bool_value (graphene_point3d_equal (&center, &zero)),
mutest_to_be_true,
NULL);

graphene_box_init_from_box (&b, graphene_box_one ());
graphene_box_get_center (&b, &center);
mutest_expect ("box(1).center() is (0.5, 0.5, 0.5)",
mutest_bool_value (graphene_point3d_equal (&center, &half)),
mutest_expect ("box(1).center() to be in (0.5, 0.5, 0.5)",
mutest_bool_value (graphene_point3d_near (&center, &half, 0.0001f)),
mutest_to_be_true,
NULL);

graphene_box_init_from_box (&b, graphene_box_one_minus_one ());
graphene_box_get_center (&b, &center);
mutest_expect ("box(1, -1).center() to be in (0, 0, 0)",
mutest_bool_value (graphene_point3d_near (&center, &zero, 0.0001f)),
mutest_to_be_true,
NULL);

graphene_box_init_from_box (&b, graphene_box_minus_one ());
graphene_box_get_center (&b, &center);
mutest_expect ("box(-1).center() to be in (-0.5, -0.5, -0.5)",
mutest_bool_value (graphene_point3d_near (&center, &minus_half, 0.0001f)),
mutest_to_be_true,
NULL);

graphene_box_init_from_box (&b, graphene_box_empty ());
graphene_box_get_center (&b, &center);
mutest_expect ("box(empty).center() to be in (0, 0, 0)",
mutest_bool_value (graphene_point3d_equal (&center, &zero)),
mutest_to_be_true,
NULL);
}
Expand Down