+
+/* 24.8 */
+#define ISECT_NEAR(v0, v1) ((((v0)->z - NEAR_Z) << 8) / ((v0)->z - (v1)->z))
+
+#define LERP_VATTR(res, v0, v1, t) \
+ do { \
+ (res)->x = (v0)->x + (((v1)->x - (v0)->x) * (t) >> 8); \
+ (res)->y = (v0)->y + (((v1)->y - (v0)->y) * (t) >> 8); \
+ (res)->z = (v0)->z + (((v1)->z - (v0)->nx) >> 8) * (t); \
+ (res)->nx = (v0)->nx + (((v1)->nx - (v0)->nx) >> 8) * (t); \
+ (res)->ny = (v0)->ny + (((v1)->ny - (v0)->ny) >> 8) * (t); \
+ (res)->nz = (v0)->nz + (((v1)->nz - (v0)->nz) >> 8) * (t); \
+ (res)->tx = (v0)->tx + (((v1)->tx - (v0)->tx) >> 8) * (t); \
+ (res)->ty = (v0)->ty + (((v1)->ty - (v0)->ty) >> 8) * (t); \
+ (res)->lit = (v0)->lit + (((v1)->lit - (v0)->lit) >> 8) * (t); \
+ } while(0)
+
+static int clip_edge_near(struct xvertex *poly, int *vnumptr, struct xvertex *v0, struct xvertex *v1)
+{
+ int vnum = *vnumptr;
+ int in0, in1;
+ int32_t t;
+ struct xvertex *vptr;
+
+ in0 = v0->z >= NEAR_Z ? 1 : 0;
+ in1 = v1->z >= NEAR_Z ? 1 : 0;
+
+ if(in0) {
+ /* start inside */
+ if(in1) {
+ /* all inside */
+ poly[vnum++] = *v1; /* append v1 */
+ *vnumptr = vnum;
+ return 1;
+ } else {
+ /* going out */
+ vptr = poly + vnum;
+ t = ISECT_NEAR(v0, v1); /* 24:8 */
+ LERP_VATTR(vptr, v0, v1, t);
+ ++vnum; /* append new vertex on the intersection point */
+ }
+ } else {
+ /* start outside */
+ if(in1) {
+ /* going in */
+ vptr = poly + vnum;
+ t = ISECT_NEAR(v0, v1);
+ LERP_VATTR(vptr, v0, v1, t);
+ ++vnum; /* append new vertex ... */
+ /* then append v1 */
+ poly[vnum++] = *v1;
+ } else {
+ /* all outside */
+ return -1;
+ }
+ }
+
+ *vnumptr = vnum;
+ return 0;
+}
+
+/* special case near-plane clipper */
+int xgl_clip_near(struct xvertex *vout, int *voutnum, struct xvertex *vin, int vnum)
+{
+ int i, nextidx, res;
+ int edges_clipped = 0;
+
+ *voutnum = 0;
+
+ for(i=0; i<vnum; i++) {
+ nextidx = i + 1;
+ if(nextidx >= vnum) nextidx = 0;
+ res = clip_edge_near(vout, voutnum, vin + i, vin + nextidx);
+ if(res == 0) {
+ ++edges_clipped;
+ }
+ }
+
+ if(*voutnum <= 0) return -1;
+ return edges_clipped > 0 ? 0 : 1;
+}