X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fgeom.c;h=81e9df4117d181cd2263e0fc9aa42304077d8d13;hb=bf7eceb7d1cef825a64a1db7a20628f7d7005654;hp=21786644f8532b96a14701ef1ad0a76e931cae53;hpb=7e22a9e6549bf0ff36dc9a73c243de1f4b36b4a4;p=meshfrac diff --git a/src/geom.c b/src/geom.c index 2178664..81e9df4 100644 --- a/src/geom.c +++ b/src/geom.c @@ -1,3 +1,4 @@ +#include #include "geom.h" #include "dynarr.h" @@ -42,6 +43,41 @@ void poly_plane(const struct poly *poly, struct plane *plane) poly_normal(poly, &plane->norm); } +int plane_poly(const struct plane *plane, struct poly *poly, float size) +{ + static const float corn[][2] = {{1,1}, {-1,1}, {-1,-1}, {1, -1}}; + int i; + cgm_vec3 up, right; + struct vertex *vptr; + size *= 0.5f; + + if(!(poly->verts = dynarr_alloc(4, sizeof *poly->verts))) { + fprintf(stderr, "plane_poly: failed to allocate polygon vertices\n"); + return -1; + } + + cgm_vcons(&up, 0, 1, 0); + if(1.0f - fabs(cgm_vdot(&up, &plane->norm)) < 1e-2) { + cgm_vcons(&up, 0, 0, -1); + } + cgm_vcross(&right, &up, &plane->norm); + cgm_vnormalize(&right); + cgm_vcross(&up, &plane->norm, &right); + cgm_vnormalize(&up); + + vptr = poly->verts; + for(i=0; i<4; i++) { + vptr->pos.x = plane->pt.x + (right.x * corn[i][0] + up.x * corn[i][1]) * size; + vptr->pos.y = plane->pt.y + (right.y * corn[i][0] + up.y * corn[i][1]) * size; + vptr->pos.z = plane->pt.z + (right.z * corn[i][0] + up.z * corn[i][1]) * size; + + vptr->norm = plane->norm; + vptr->uv.x = vptr->uv.y = 0; + vptr++; + } + return 0; +} + float ray_plane(const cgm_ray *ray, const struct plane *plane) { float ndotdir, t; @@ -93,3 +129,85 @@ float ray_poly(const cgm_ray *ray, const struct poly *poly) } return t; } + + +/* returns: + * 1 -> both inside + * 0 -> straddling and clipped + * -1 -> both outside + */ +static int clip_edge(struct poly *pout, const struct vertex *v0, const struct vertex *v1, + const struct plane *plane) +{ + float d0, d1, t; + cgm_ray ray; + struct vertex vnew; + + d0 = plane_sdist(plane, &v0->pos); + d1 = plane_sdist(plane, &v1->pos); + + ray.origin = v0->pos; + ray.dir = v1->pos; + cgm_vsub(&ray.dir, &v0->pos); + + if(d0 >= 0.0) { + /* start inside */ + if(d1 >= 0.0) { + /* all inside */ + DYNARR_PUSH(pout->verts, v1); /* append v1 */ + return 1; + } else { + /* going out */ + t = ray_plane(&ray, plane); + cgm_raypos(&vnew.pos, &ray, t); + + cgm_vlerp(&vnew.norm, &v0->norm, &v1->norm, t); + vnew.uv.x = cgm_lerp(v0->uv.x, v1->uv.x, t); + vnew.uv.y = cgm_lerp(v0->uv.y, v1->uv.y, t); + /* append new vertex on the intersection point */ + DYNARR_PUSH(pout->verts, &vnew); + } + } else { + /* start outside */ + if(d1 >= 0) { + /* going in */ + t = ray_plane(&ray, plane); + cgm_raypos(&vnew.pos, &ray, t); + + cgm_vlerp(&vnew.norm, &v0->norm, &v1->norm, t); + vnew.uv.x = cgm_lerp(v0->uv.x, v1->uv.x, t); + vnew.uv.y = cgm_lerp(v0->uv.y, v1->uv.y, t); + /* append new vertex on the intersection point */ + DYNARR_PUSH(pout->verts, &vnew); + /* then append v1 ... */ + DYNARR_PUSH(pout->verts, v1); + } else { + /* all outside */ + return -1; + } + } + + return 0; +} + + +int clip_poly(struct poly *pout, const struct poly *pin, const struct plane *plane) +{ + int i, nextidx, res = 0, vnum; + int edges_clipped = 0; + + dynarr_clear(pout->verts); + + vnum = dynarr_size(pin->verts); + for(i=0; i= vnum) nextidx = 0; + res = clip_edge(pout, pin->verts + i, pin->verts + nextidx, plane); + if(res == 0) { + ++edges_clipped; + } + } + + return edges_clipped > 0 ? 0 : 1; + +}