X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fgeom.c;fp=src%2Fgeom.c;h=0b943851b6211792a107f773d2b658cb44f9ed37;hb=34e07fdc87e289e9ce574df7755e5e781136c20b;hp=21786644f8532b96a14701ef1ad0a76e931cae53;hpb=7e22a9e6549bf0ff36dc9a73c243de1f4b36b4a4;p=meshfrac diff --git a/src/geom.c b/src/geom.c index 2178664..0b94385 100644 --- a/src/geom.c +++ b/src/geom.c @@ -42,6 +42,37 @@ 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 pos, up, right, dir; + 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); + + for(i=0; i<4; i++) { + v.x = plane->pt.x + (right.x * corn[i][0] + up.x * corn[i][1]) * size; + v.y = plane->pt.y + (right.y * corn[i][0] + up.y * corn[i][1]) * size; + v.z = plane->pt.z + (right.z * corn[i][0] + up.z * corn[i][1]) * size; + + + + +} + float ray_plane(const cgm_ray *ray, const struct plane *plane) { float ndotdir, t; @@ -93,3 +124,91 @@ 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; + int i, vnum = dynarr_size(pout->verts); + struct vertex vnew; + + d0 = plane_sdist(plane, &v0->pos); + d1 = plane_sdist(plane, &v1->pos); + + ray.orig = v0->pos; + ray.dir = v1->pos; + cgm_vsub(&ray.dir, &v0->pos); + + for(i=0; i<3; i++) { + ray.origin[i] = pos0[i]; + ray.dir[i] = pos1[i] - pos0[i]; + } + + 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; + +}