/** * graphene_triangle_contains_point: * @t: a #graphene_triangle_t * @p: a #graphene_point3d_t * * Checks whether the given triangle @t contains the point @p. * * Returns: `true` if the point is inside the triangle * * Since: 1.2 */ bool graphene_triangle_contains_point (const graphene_triangle_t *t, const graphene_point3d_t *p) { graphene_vec3_t point, v1, v2, v3; float dot_11, dot_12, dot_13; float dot_22, dot_23; float inv_denom, u, v; graphene_point3d_to_vec3 (p, &point); /* we use the barycoordinates from the given point to check * if the point is inside the triangle. * * see: http://www.blackpawn.com/texts/pointinpoly/default.html */ graphene_vec3_subtract (&t->c, &t->a, &v1); graphene_vec3_subtract (&t->b, &t->a, &v2); graphene_vec3_subtract (&point, &t->a, &v3); dot_11 = graphene_vec3_dot (&v1, &v1); dot_12 = graphene_vec3_dot (&v1, &v2); dot_13 = graphene_vec3_dot (&v1, &v3); dot_22 = graphene_vec3_dot (&v2, &v2); dot_23 = graphene_vec3_dot (&v2, &v3); inv_denom = 1.f / (dot_11 * dot_22 - dot_12 * dot_12); u = (dot_22 * dot_13 - dot_12 * dot_23) * inv_denom; v = (dot_11 * dot_23 - dot_12 * dot_13) * inv_denom; return (u >= 0.f) && (v >= 0.f) && (u + v < 1.f); }
/** * graphene_ray_get_distance_to_point: * @r: a #graphene_ray_t * @p: a #graphene_point3d_t * * Computes the distance from the origin of the given ray to the given point. * * Returns: the distance of the point * * Since: 1.4 */ float graphene_ray_get_distance_to_point (const graphene_ray_t *r, const graphene_point3d_t *p) { graphene_vec3_t point; graphene_vec3_t tmp; float distance; graphene_point3d_to_vec3 (p, &point); graphene_vec3_subtract (&point, &r->origin, &tmp); distance = graphene_vec3_dot (&tmp, &r->direction); /* the point is behind the ray */ if (distance < 0) { graphene_vec3_subtract (&r->origin, &point, &tmp); return graphene_vec3_length (&tmp); } /* get the position on the ray at the given distance */ graphene_vec3_scale (&r->direction, distance, &tmp); graphene_vec3_add (&tmp, &r->origin, &tmp); graphene_vec3_subtract (&tmp, &point, &tmp); return graphene_vec3_length (&tmp); }
/** * graphene_triangle_get_area: * @t: a #graphene_triangle_t * * Computes the area of the given #graphene_triangle_t. * * Returns: the area of the triangle * * Since: 1.2 */ float graphene_triangle_get_area (const graphene_triangle_t *t) { graphene_vec3_t v1, v2, tmp; graphene_vec3_subtract (&t->c, &t->b, &v1); graphene_vec3_subtract (&t->a, &t->b, &v2); graphene_vec3_cross (&v1, &v2, &tmp); return graphene_vec3_length (&tmp) * .5f; }
/** * graphene_matrix_project_point: * @m: ... * @p: ... * @res: (out caller-allocates): ... * * ... * * Since: 1.0 */ void graphene_matrix_project_point (const graphene_matrix_t *m, const graphene_point_t *p, graphene_point_t *res) { graphene_vec3_t pa, qa; graphene_vec3_t pback, qback, uback; float p_z, u_z, t; g_return_if_fail (m != NULL); g_return_if_fail (p != NULL); g_return_if_fail (res != NULL); graphene_vec3_init (&pa, p->x, p->y, 0.0f); graphene_vec3_init (&qa, p->x, p->y, 1.0f); graphene_matrix_transform_vec3 (m, &pa, &pback); graphene_matrix_transform_vec3 (m, &qa, &qback); graphene_vec3_subtract (&qback, &pback, &uback); p_z = graphene_vec3_get_z (&pback); u_z = graphene_vec3_get_z (&uback); t = -p_z / u_z; graphene_point_init (res, graphene_vec3_get_x (&pback) + t * graphene_vec3_get_x (&uback), graphene_vec3_get_y (&pback) + t * graphene_vec3_get_y (&uback)); }
/** * graphene_triangle_get_normal: * @t: a #graphene_triangle_t * @res: (out caller-allocates): return location for the normal vector * * Computes the normal vector of the given #graphene_triangle_t. * * Since: 1.2 */ void graphene_triangle_get_normal (const graphene_triangle_t *t, graphene_vec3_t *res) { graphene_vec3_t v1, v2, tmp; float length_sq; graphene_vec3_subtract (&t->c, &t->b, &v1); graphene_vec3_subtract (&t->a, &t->b, &v2); graphene_vec3_cross (&v1, &v2, &tmp); length_sq = graphene_vec3_dot (&tmp, &tmp); if (length_sq > 0) graphene_vec3_scale (&tmp, 1.f / sqrtf (length_sq), res); else graphene_vec3_init_from_vec3 (res, graphene_vec3_zero ()); }
/** * graphene_ray_get_closest_point_to_point: * @r: a #graphene_ray_t * @p: a #graphene_point3d_t * @res: (out caller-allocates): return location for the closest point3d * * Computes the point on the given #graphene_ray_t that is closest to the * given point @p. * * Since: 1.4 */ void graphene_ray_get_closest_point_to_point (const graphene_ray_t *r, const graphene_point3d_t *p, graphene_point3d_t *res) { graphene_vec3_t point, result; float distance; graphene_point3d_to_vec3 (p, &point); graphene_vec3_subtract (&point, &r->origin, &result); distance = graphene_vec3_dot (&result, &r->direction); if (distance < 0) graphene_vec3_init_from_vec3 (&result, &r->origin); else { graphene_vec3_scale (&r->direction, distance, &result); graphene_vec3_add (&result, &r->origin, &result); } graphene_point3d_init_from_vec3 (res, &result); }