10 static int clip_edge(struct g3d_vertex *poly, int *vnumptr,
11 const struct g3d_vertex *v0, const struct g3d_vertex *v1,
12 const struct cplane *plane);
13 static float distance_signed(float *pos, const struct cplane *plane);
14 static int intersect(const struct ray *ray, const struct cplane *plane, float *t);
17 int clip_poly(struct g3d_vertex *vout, int *voutnum,
18 const struct g3d_vertex *vin, int vnum, struct cplane *plane)
21 int edges_clipped = 0;
24 for(i=0; i<vnum; i++) {
25 int res = clip_edge(vout, &out_vnum, vin + i, vin + (i + 1) % vnum, plane);
32 assert(edges_clipped == 0);
37 return edges_clipped > 0 ? 0 : 1;
40 #define LERP_VATTR(res, v0, v1, t) \
42 (res)->nx = (v0)->nx + ((v1)->nx - (v0)->nx) * (t); \
43 (res)->ny = (v0)->ny + ((v1)->ny - (v0)->ny) * (t); \
44 (res)->nz = (v0)->nz + ((v1)->nz - (v0)->nz) * (t); \
45 (res)->u = (v0)->u + ((v1)->u - (v0)->u) * (t); \
46 (res)->v = (v0)->v + ((v1)->v - (v0)->v) * (t); \
47 (res)->r = (v0)->r + ((v1)->r - (v0)->r) * (t); \
48 (res)->g = (v0)->g + ((v1)->g - (v0)->g) * (t); \
49 (res)->b = (v0)->b + ((v1)->b - (v0)->b) * (t); \
55 * 0 -> straddling and clipped
58 * also returns the size of the polygon through vnumptr
60 static int clip_edge(struct g3d_vertex *poly, int *vnumptr,
61 const struct g3d_vertex *v0, const struct g3d_vertex *v1,
62 const struct cplane *plane)
64 float pos0[3], pos1[3];
67 int i, vnum = *vnumptr;
69 pos0[0] = v0->x; pos0[1] = v0->y; pos0[2] = v0->z;
70 pos1[0] = v1->x; pos1[1] = v1->y; pos1[2] = v1->z;
72 d0 = distance_signed(pos0, plane);
73 d1 = distance_signed(pos1, plane);
76 ray.origin[i] = pos0[i];
77 ray.dir[i] = pos1[i] - pos0[i];
84 poly[vnum++] = *v1; /* append v1 */
89 struct g3d_vertex *vptr = poly + vnum;
91 intersect(&ray, plane, &t);
93 vptr->x = ray.origin[0] + ray.dir[0] * t;
94 vptr->y = ray.origin[1] + ray.dir[1] * t;
95 vptr->z = ray.origin[2] + ray.dir[2] * t;
98 LERP_VATTR(vptr, v0, v1, t);
99 vnum++; /* append new vertex on the intersection point */
105 struct g3d_vertex *vptr = poly + vnum;
107 intersect(&ray, plane, &t);
109 vptr->x = ray.origin[0] + ray.dir[0] + t;
110 vptr->y = ray.origin[1] + ray.dir[1] + t;
111 vptr->z = ray.origin[2] + ray.dir[2] + t;
114 LERP_VATTR(vptr, v0, v1, t);
115 vnum++; /* append new vertex on the intersection point */
117 /* then append v1 ... */
130 static float distance_signed(float *pos, const struct cplane *plane)
132 float dx = pos[0] - plane->x;
133 float dy = pos[1] - plane->y;
134 float dz = pos[2] - plane->z;
135 return dx * plane->nx + dy * plane->ny + dz * plane->nz;
138 static int intersect(const struct ray *ray, const struct cplane *plane, float *t)
140 float orig_pt_dir[3];
142 float ndotdir = plane->nx * ray->dir[0] + plane->ny * ray->dir[1] + plane->nz * ray->dir[2];
143 if(fabs(ndotdir) < 1e-4) {
148 orig_pt_dir[0] = plane->x - ray->origin[0];
149 orig_pt_dir[1] = plane->y - ray->origin[1];
150 orig_pt_dir[2] = plane->z - ray->origin[2];
152 *t = (plane->nx * orig_pt_dir[0] + plane->ny * orig_pt_dir[1] + plane->nz * orig_pt_dir[2]) / ndotdir;