more utility functions in geom
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 2 Jan 2023 03:52:41 +0000 (05:52 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 2 Jan 2023 03:52:41 +0000 (05:52 +0200)
src/geom.c
src/geom.h

index f7e1740..2178664 100644 (file)
@@ -1,4 +1,5 @@
 #include "geom.h"
+#include "dynarr.h"
 
 float plane_dist(const struct plane *p, const cgm_vec3 *pt)
 {
@@ -21,3 +22,74 @@ void midplane(struct plane *p, const cgm_vec3 *a, const cgm_vec3 *b)
        p->pt.y = a->y + p->norm.y * 0.5f;
        p->pt.z = a->z + p->norm.z * 0.5f;
 }
+
+void poly_normal(const struct poly *poly, cgm_vec3 *n)
+{
+       cgm_vec3 va, vb;
+
+       va = poly->verts[1].pos;
+       cgm_vsub(&va, &poly->verts[0].pos);
+       vb = poly->verts[2].pos;
+       cgm_vsub(&vb, &poly->verts[2].pos);
+
+       cgm_vcross(n, &va, &vb);
+       cgm_vnormalize(n);
+}
+
+void poly_plane(const struct poly *poly, struct plane *plane)
+{
+       plane->pt = poly->verts[0].pos;
+       poly_normal(poly, &plane->norm);
+}
+
+float ray_plane(const cgm_ray *ray, const struct plane *plane)
+{
+       float ndotdir, t;
+       cgm_vec3 pptdir;
+
+       ndotdir = cgm_vdot(&plane->norm, &ray->dir);
+       if(fabs(ndotdir) < 1e-4) {
+               return -1.0f;
+       }
+
+       pptdir = plane->pt;
+       cgm_vsub(&pptdir, &ray->origin);
+       t = cgm_vdot(&plane->norm, &pptdir) / ndotdir;
+       if(t < 1e-6) {
+               return -1.0f;
+       }
+       return t;
+}
+
+float ray_poly(const cgm_ray *ray, const struct poly *poly)
+{
+       float t;
+       struct plane plane;
+       cgm_vec3 hitp, vdir, edir, indir, vcross, incross;
+       int i, nverts;
+
+       poly_plane(poly, &plane);
+       if((t = ray_plane(ray, &plane)) < 0.0f) {
+               return -1.0f;
+       }
+       cgm_raypos(&hitp, ray, t);
+
+       /* see if the point is inside or outside the polygon */
+       nverts = dynarr_size(poly->verts);
+       for(i=0; i<nverts; i++) {
+               vdir = hitp;
+               cgm_vsub(&hitp, &poly->verts[i].pos);
+               edir = poly->verts[(i + 1) & nverts].pos;
+               cgm_vsub(&edir, &poly->verts[i].pos);
+               indir = poly->verts[(i + 2) & nverts].pos;
+               cgm_vsub(&indir, &poly->verts[i].pos);
+
+               cgm_vcross(&vcross, &vdir, &edir);
+               cgm_vcross(&incross, &indir, &edir);
+
+               if(cgm_vdot(&vcross, &incross) < 0.0f) {
+                       return -1.0f;
+               }
+       }
+       return t;
+}
index fa492f0..14faa82 100644 (file)
@@ -7,8 +7,23 @@ struct plane {
        cgm_vec3 pt, norm;
 };
 
+struct vertex {
+       cgm_vec3 pos, norm;
+       cgm_vec2 uv;
+};
+
+struct poly {
+       struct vertex *verts;   /* dynarr */
+};
+
 float plane_dist(const struct plane *p, const cgm_vec3 *pt);
 float plane_sdist(const struct plane *p, const cgm_vec3 *pt);
 void midplane(struct plane *p, const cgm_vec3 *a, const cgm_vec3 *b);
 
+void poly_plane(const struct poly *poly, struct plane *plane);
+
+/* returns negative if there's no intersection, parametric distance if there is */
+float ray_plane(const cgm_ray *ray, const struct plane *plane);
+float ray_poly(const cgm_ray *ray, const struct poly *poly);
+
 #endif /* GEOM_H_ */