4 typedef struct clipsurf_s
6 struct clipsurf_s *next, *prev;
11 void (*callback)(void *nativedata, void *nativedata2);
14 float wstepx, wstepy, w00;
15 // wcurrent is a cached copy of w00 + wstepy * y,
16 // updated each time the surface is added to the stack,
17 // for quicker comparisons.
19 // this is a linked list of all edges belonging to this surface,
20 // used to remove them if this is a non-solid surface that is
21 // marked visible (it can not hide anything, so it is useless)
22 // struct clipedge_s *edgechain;
26 typedef struct clipedge_s
28 float x, realx, realxstep;
29 struct clipedge_s *next, *prev, *nextremove;
36 clipsurf_t *pavailsurf, *clipsurfs, *clipsurfsend;
37 clipedge_t *pavailedge, *clipedges, *clipedgesend, *newedges, **removeedges;
40 clipedge_t edgehead, edgetail;
41 clipedge_t maxedge = {2000000000.0f};
43 cvar_t r_clipwidth = {"r_clipwidth", "800"};
44 cvar_t r_clipheight = {"r_clipheight", "600"};
45 cvar_t r_clipedges = {"r_clipedges", "32768", true};
46 cvar_t r_clipsurfaces = {"r_clipsurfaces", "8192", true};
48 int clipwidth = 0, clipheight = 0;
49 int maxclipsurfs = 0, maxclipedges = 0;
50 int needededges, neededsurfs;
55 float w; // inverse depth (1/z)
59 clippixel_t *clipbuffer;
62 float r_clip_viewmatrix[3][3], r_clip_viewmulx, r_clip_viewmuly, r_clip_viewcenterx, r_clip_viewcentery;
64 //float xscale, yscale, xscaleinv, yscaleinv;
65 //float r_clip_nearclipdist, r_clip_nearclipdist2;
66 tinyplane_t r_clip_viewplane[5];
68 void R_Clip_MakeViewMatrix(void)
70 float pixelaspect, screenaspect, horizontalfieldofview, verticalfieldofview;
71 pixelaspect = (float) clipheight / (float) clipwidth * 320 / 240.0;
72 horizontalfieldofview = 2.0 * tan (r_refdef.fov_x/360*M_PI);
73 screenaspect = clipwidth * pixelaspect / clipheight;
74 verticalfieldofview = horizontalfieldofview / screenaspect;
75 r_clip_viewcenterx = clipwidth * 0.5 - 0.5;
76 r_clip_viewcentery = clipheight * 0.5 - 0.5;
77 r_clip_viewmulx = clipwidth / horizontalfieldofview;
78 r_clip_viewmuly = r_clip_viewmulx * pixelaspect;
79 // this constructs a transposed rotation matrix for the view (transposed matrices do the opposite of their normal behavior)
80 VectorCopy (vright, r_clip_viewmatrix[0]);
81 VectorNegate (vup, r_clip_viewmatrix[1]);
82 VectorCopy (vpn, r_clip_viewmatrix[2]);
83 // r_clip_nearclipdist = DotProduct(r_origin, vpn) + 4.0f;
84 // r_clip_nearclipdist2 = r_clip_nearclipdist - 8.0f;
85 VectorCopy (vpn, r_clip_viewplane[0].normal);
86 r_clip_viewplane[0].dist = DotProduct(r_origin, vpn);
87 memcpy(&r_clip_viewplane[1], &frustum[0], sizeof(tinyplane_t));
88 memcpy(&r_clip_viewplane[2], &frustum[1], sizeof(tinyplane_t));
89 memcpy(&r_clip_viewplane[3], &frustum[2], sizeof(tinyplane_t));
90 memcpy(&r_clip_viewplane[4], &frustum[3], sizeof(tinyplane_t));
92 // maxscreenscaleinv = (1.0f / max(clipwidth, clipheight)) * horizontalfieldofview * 0.5f;
93 // xscale = clipwidth / horizontalfieldofview;
94 // xscaleinv = 1.0 / xscale;
95 // yscale = xscale * pixelaspect;
96 // yscaleinv = 1.0 / yscale;
99 void R_Clip_StartFrame(void)
102 int newwidth, newheight, newmaxedges, newmaxsurfs;
103 newwidth = bound(80, (int) r_clipwidth.value, vid.width * 2);
104 newheight = bound(60, (int) r_clipheight.value, vid.height * 2);
105 newmaxedges = bound(128, (int) r_clipedges.value, 262144);
106 newmaxsurfs = bound(32, (int) r_clipsurfaces.value, 65536);
107 if (newwidth != clipwidth || newheight != clipheight || maxclipedges != newmaxedges || maxclipsurfs != newmaxsurfs)
121 clipwidth = newwidth;
122 clipheight = newheight;
123 maxclipedges = newmaxedges;
124 maxclipsurfs = newmaxsurfs;
126 clipbuffer = qmalloc(clipwidth * clipheight * sizeof(clippixel_t));
128 clipedges = qmalloc(maxclipedges * sizeof(clipedge_t));
129 clipsurfs = qmalloc(maxclipsurfs * sizeof(clipsurf_t));
130 newedges = qmalloc(clipheight * sizeof(clipedge_t));
131 removeedges = qmalloc(clipheight * sizeof(clipedge_t *));
132 clipedgesend = clipedges + maxclipedges;
133 clipsurfsend = clipsurfs + maxclipsurfs;
136 memset(clipbuffer, 0, clipwidth * clipheight * sizeof(clippixel_t));
138 pavailedge = clipedges;
139 pavailsurf = clipsurfs;
140 // Clear the lists of edges to add and remove on each scan line.
144 for (i = 0;i < clipheight;i++)
146 newedges[i].next = &maxedge;
147 removeedges[i] = NULL;
150 R_Clip_MakeViewMatrix();
153 void ScanEdges (void);
155 void R_Clip_EndFrame(void)
158 if (maxclipedges < needededges)
160 Con_Printf("R_Clip: ran out of edges, increasing limit from %d to %d\n", maxclipedges, needededges);
161 Cvar_SetValue("r_clipedges", needededges);
163 if (maxclipsurfs < neededsurfs)
165 Con_Printf("R_Clip: ran out of surfaces, increasing limit from %d to %d\n", maxclipsurfs, neededsurfs);
166 Cvar_SetValue("r_clipsurfaces", neededsurfs);
170 void r_clip_start(void)
174 void r_clip_shutdown(void)
197 void r_clip_newmap(void)
201 void R_Clip_Init(void)
203 Cvar_RegisterVariable(&r_clipwidth);
204 Cvar_RegisterVariable(&r_clipheight);
205 Cvar_RegisterVariable(&r_clipedges);
206 Cvar_RegisterVariable(&r_clipsurfaces);
207 R_RegisterModule("R_Clip", r_clip_start, r_clip_shutdown, r_clip_newmap);
210 int R_Clip_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p)
214 VectorSubtract(point1, point2, v1);
215 VectorSubtract(point3, point2, v2);
216 CrossProduct(v1, v2, p->normal);
217 number = DotProduct(p->normal, p->normal);
220 *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
221 y = y * (1.5f - (number * 0.5f * y * y));
222 VectorScale(p->normal, y, p->normal);
223 p->dist = DotProduct(point1, p->normal);
231 int R_Clip_TriangleToDoublePlane(double *point1, double *point2, double *point3, tinydoubleplane_t *p)
235 VectorSubtract(point1, point2, v1);
236 VectorSubtract(point3, point2, v2);
237 CrossProduct(v1, v2, p->normal);
238 number = DotProduct(p->normal, p->normal);
241 y = 1.0 / sqrt(number);
242 VectorScale(p->normal, y, p->normal);
243 p->dist = DotProduct(point1, p->normal);
251 int R_Clip_ClipPolygonToPlane(float *in, float *out, int inpoints, int stride, tinyplane_t *plane)
253 int i, outpoints, prevside, side;
254 float *prevpoint, prevdist, dist, dot;
256 // begin with the last point, then enter the loop with the first point as current
257 prevpoint = (float *) ((byte *)in + stride * (inpoints - 1));
258 prevdist = DotProduct(prevpoint, plane->normal) - plane->dist;
259 prevside = prevdist >= 0 ? SIDE_FRONT : SIDE_BACK;
263 for (;i < inpoints;i++)
268 (byte *)in += stride;
271 dist = DotProduct(in, plane->normal) - plane->dist;
272 side = dist >= 0 ? SIDE_FRONT : SIDE_BACK;
274 if (prevside == SIDE_FRONT)
276 VectorCopy(prevpoint, out);
279 if (side == SIDE_FRONT)
282 else if (side == SIDE_BACK)
285 // generate a split point
286 dot = prevdist / (prevdist - dist);
287 out[0] = prevpoint[0] + dot * (in[0] - prevpoint[0]);
288 out[1] = prevpoint[1] + dot * (in[1] - prevpoint[1]);
289 out[2] = prevpoint[2] + dot * (in[2] - prevpoint[2]);
297 float tempverts[256][3];
298 float tempverts2[256][3];
299 float screenverts[256][3];
301 // LordHavoc: this code is based primarily on the ddjzsort code
303 // Clips polygon to view frustum and nearclip, transforms polygon to viewspace, perspective projects polygon to screenspace,
304 // and adds polygon's edges to the global edge table.
305 void R_Clip_AddPolygon (vec_t *points, int numverts, int stride, int solid, void (*callback)(void *nativedata, void *nativedata2), void *nativedata, void *nativedata2, tinyplane_t *polyplane)
307 float deltax, deltay, vx, vy, vz, fx;
308 int i, j, k, nextvert, temp, topy, bottomy, height, addededges;
310 // tinydoubleplane_t plane;
311 tinyplane_t localplane;
312 // tinyplane_t testplane;
318 if (polyplane == NULL)
320 polyplane = &localplane;
321 // calculate the plane for the polygon
322 if (!R_Clip_TriangleToPlane((float *) points, (float *) ((byte *)points + stride), (float *) ((byte *)points + 2 * stride), polyplane))
324 for (i = 0;i < numverts;i++)
325 for (j = i + 1;j < numverts;j++)
326 for (k = j + 1;k < numverts;k++)
327 if (R_Clip_TriangleToPlane((float *) ((byte *)points + i * stride), (float *) ((byte *)points + j * stride), (float *) ((byte *)points + k * stride), polyplane))
333 // caller hasn't checked if this polygon faces the view, so we have to check
334 if (DotProduct(r_origin, polyplane->normal) < (polyplane->dist + 0.5f))
337 #if 0 // debugging (validates planes passed in)
340 // calculate the plane for the polygon
341 if (!R_Clip_TriangleToPlane((float *) points, (float *) ((byte *)points + stride), (float *) ((byte *)points + 2 * stride), &localplane))
343 for (i = 0;i < numverts;i++)
344 for (j = i + 1;j < numverts;j++)
345 for (k = j + 1;k < numverts;k++)
346 if (R_Clip_TriangleToPlane((float *) ((byte *)points + i * stride), (float *) ((byte *)points + j * stride), (float *) ((byte *)points + k * stride), &localplane))
352 // if ((DotProduct(r_origin, polyplane->normal) < (polyplane->dist + 0.5f)) != (DotProduct(r_origin, localplane.normal) < (localplane.dist + 0.5f)))
353 if (DotProduct(polyplane->normal, localplane.normal) < 0.9f)
361 // for adaptive limits
362 needededges += numverts;
365 if (pavailsurf >= clipsurfsend)
368 // clip to view frustum and nearclip
369 if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(points , tempverts2[0], numverts, stride, &r_clip_viewplane[0]);
370 if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts2[0], tempverts[0], numverts, sizeof(float) * 3, &r_clip_viewplane[1]);
371 if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts[0], tempverts2[0], numverts, sizeof(float) * 3, &r_clip_viewplane[2]);
372 if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts2[0], tempverts[0], numverts, sizeof(float) * 3, &r_clip_viewplane[3]);
373 if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts[0], tempverts2[0], numverts, sizeof(float) * 3, &r_clip_viewplane[4]);
377 Sys_Error("R_Clip_AddPolygon: polygon exceeded 256 vertex buffer\n");
379 // it survived the clipping, transform to viewspace and project to screenspace
381 if (pavailedge + numverts > clipedgesend)
385 for (i = 0;i < numverts;i++)
387 vx = tempverts2[i][0] - r_origin[0];
388 vy = tempverts2[i][1] - r_origin[1];
389 vz = tempverts2[i][2] - r_origin[2];
390 screenverts[i][2] = 1.0f / (r_clip_viewmatrix[2][0] * vx + r_clip_viewmatrix[2][1] * vy + r_clip_viewmatrix[2][2] * vz);
391 screenverts[i][0] = (r_clip_viewmatrix[0][0] * vx + r_clip_viewmatrix[0][1] * vy + r_clip_viewmatrix[0][2] * vz) * r_clip_viewmulx * screenverts[i][2] + r_clip_viewcenterx;
392 screenverts[i][1] = (r_clip_viewmatrix[1][0] * vx + r_clip_viewmatrix[1][1] * vy + r_clip_viewmatrix[1][2] * vz) * r_clip_viewmuly * screenverts[i][2] + r_clip_viewcentery;
396 if (polyplane != NULL)
400 distinv = 1.0f / (polyplane->dist - DotProduct(r_origin, polyplane->normal));
401 pavailsurf->wstepx = DotProduct(r_clip_viewmatrix[0], polyplane->normal) * xscaleinv * distinv;
402 pavailsurf->wstepy = DotProduct(r_clip_viewmatrix[1], polyplane->normal) * yscaleinv * distinv;
403 pavailsurf->w00 = DotProduct(r_clip_viewmatrix[2], polyplane->normal) * distinv - r_clip_viewcenterx * pavailsurf->wstepx - r_clip_viewcentery * pavailsurf->wstepy;
410 // calculate the plane for the polygon
411 if (!R_Clip_TriangleToPlane(screenverts[0], screenverts[1], screenverts[2], &localplane))
413 for (i = 0;i < numverts;i++)
414 for (j = i + 1;j < numverts;j++)
415 for (k = j + 1;k < numverts;k++)
416 if (R_Clip_TriangleToPlane(screenverts[i], screenverts[j], screenverts[k], &localplane))
422 // Set up the 1/z gradients from the polygon, calculating the
423 // base value at screen coordinate 0,0 so we can use screen
424 // coordinates directly when calculating 1/z from the gradients
425 distinv = 1.0f / localplane.normal[2];
426 pavailsurf->wstepx = -(localplane.normal[0] * distinv);
427 pavailsurf->wstepy = -(localplane.normal[1] * distinv);
428 pavailsurf->w00 = localplane.dist * distinv;
434 prevdist = z1 * plane.normal[2] - plane.dist;
435 dist = z2 * plane.normal[2] - plane.dist;
436 d = prevdist / (prevdist - dist);
437 zc = z1 + d * (z2 - z1);
439 prevdist = plane.normal[0] + z1 * plane.normal[2] - plane.dist;
440 dist = plane.normal[0] + z2 * plane.normal[2] - plane.dist;
441 d = prevdist / (prevdist - dist);
442 zx = (z1 + d * (z2 - z1)) - zc;
444 prevdist = plane.normal[1] + z1 * plane.normal[2] - plane.dist;
445 dist = plane.normal[1] + z2 * plane.normal[2] - plane.dist;
446 d = prevdist / (prevdist - dist);
447 zy = (z1 + d * (z2 - z1)) - zc;
451 zc = (-plane.dist) / ((-plane.dist) - (plane.normal[2] - plane.dist));
452 zx = ((plane.normal[0] - plane.dist) / ((plane.normal[0] - plane.dist) - (plane.normal[0] + plane.normal[2] - plane.dist))) - zc;
453 zy = ((plane.normal[1] - plane.dist) / ((plane.normal[1] - plane.dist) - (plane.normal[1] + plane.normal[2] - plane.dist))) - zc;
456 // zc = (plane.dist / plane.normal[2]);
457 // zx = -(plane.normal[0] / plane.normal[2]);
458 // zy = -(plane.normal[1] / plane.normal[2]);
459 // zy = ((plane.normal[1] - plane.dist) / (-plane.normal[2])) + ((plane.dist) / (-plane.normal[2]));
461 for (i = 0;i < numverts;i++)
463 vx = tempverts2[i][0] - r_origin[0];
464 vy = tempverts2[i][1] - r_origin[1];
465 vz = tempverts2[i][2] - r_origin[2];
466 screenverts[i][0] = r_clip_viewmatrix[0][0] * vx + r_clip_viewmatrix[0][1] * vy + r_clip_viewmatrix[0][2] * vz;
467 screenverts[i][1] = r_clip_viewmatrix[1][0] * vx + r_clip_viewmatrix[1][1] * vy + r_clip_viewmatrix[1][2] * vz;
468 screenverts[i][2] = r_clip_viewmatrix[2][0] * vx + r_clip_viewmatrix[2][1] * vy + r_clip_viewmatrix[2][2] * vz;
472 // calculate the plane for the polygon
473 for (i = 0;i < numverts;i++)
474 for (j = i + 1;j < numverts;j++)
475 for (k = j + 1;k < numverts;k++)
476 if (R_Clip_TriangleToDoublePlane(screenverts[i], screenverts[j], screenverts[k], &plane))
481 distinv = 1.0f / plane.dist;
482 pavailsurf->d_zistepx = plane.normal[0] * xscaleinv * distinv;
483 pavailsurf->d_zistepy = -plane.normal[1] * yscaleinv * distinv;
484 pavailsurf->d_ziorigin = plane.normal[2] * distinv - r_clip_viewcenterx * pavailsurf->wstepx - r_clip_viewcentery * pavailsurf->wstepy;
486 for (i = 0;i < numverts;i++)
488 screenverts[i][2] = 1.0f / (screenverts[i][2]);
489 screenverts[i][0] = screenverts[i][0] * r_clip_viewmulx * screenverts[i][2] + r_clip_viewcenterx;
490 screenverts[i][1] = screenverts[i][1] * r_clip_viewmuly * screenverts[i][2] + r_clip_viewcentery;
492 // if (screenverts[i][0] < -0.5)
493 // screenverts[i][0] = -0.5;
494 // if (screenverts[i][0] > (clipwidth - 0.5))
495 // screenverts[i][0] = clipwidth - 0.5;
496 // if (screenverts[i][1] < -0.5)
497 // screenverts[i][1] = -0.5;
498 // if (screenverts[i][1] > (clipheight - 0.5))
499 // screenverts[i][1] = clipheight - 0.5;
500 // if (screenverts[i][2] <= 0.0)
501 // Con_Printf("R_Clip_AddPolygon: vertex z <= 0!\n");
507 // Add each edge in turn
508 for (i = 0;i < numverts;i++)
511 if (nextvert >= numverts)
514 topy = (int)ceil(screenverts[i][1]);
515 bottomy = (int)ceil(screenverts[nextvert][1]);
516 height = bottomy - topy;
518 continue; // doesn't cross any scan lines
527 if (bottomy > clipheight)
528 bottomy = clipheight;
532 pavailedge->leading = 1;
534 deltax = screenverts[i][0] - screenverts[nextvert][0];
535 deltay = screenverts[i][1] - screenverts[nextvert][1];
537 pavailedge->realxstep = deltax / deltay;
538 pavailedge->realx = screenverts[nextvert][0] + ((float)topy - screenverts[nextvert][1]) * pavailedge->realxstep;
545 if (bottomy > clipheight)
546 bottomy = clipheight;
550 pavailedge->leading = 0;
552 deltax = screenverts[nextvert][0] - screenverts[i][0];
553 deltay = screenverts[nextvert][1] - screenverts[i][1];
555 pavailedge->realxstep = deltax / deltay;
556 pavailedge->realx = screenverts[i][0] + ((float)topy - screenverts[i][1]) * pavailedge->realxstep;
559 // Put the edge on the list to be added on top scan
560 fx = pavailedge->x = bound(0.0f, pavailedge->realx, clipwidth - 0.5f);
561 pedge = &newedges[topy];
562 while (fx > pedge->next->x)
564 pavailedge->next = pedge->next;
565 pedge->next = pavailedge;
567 // Put the edge on the list to be removed after final scan
568 pavailedge->nextremove = removeedges[bottomy - 1];
569 removeedges[bottomy - 1] = pavailedge;
571 // Associate the edge with the surface
572 pavailedge->psurf = pavailsurf;
582 // Create the surface, so we'll know how to sort and draw from the edges
583 pavailsurf->next = NULL;
584 pavailsurf->prev = NULL;
585 pavailsurf->state = 0;
586 pavailsurf->visible = false;
587 pavailsurf->callback = callback;
588 pavailsurf->nativedata = nativedata;
589 pavailsurf->nativedata2 = nativedata2;
590 pavailsurf->solid = solid;
591 pavailsurf->removed = false;
595 /////////////////////////////////////////////////////////////////////
596 // Scan all the edges in the global edge table into spans.
597 /////////////////////////////////////////////////////////////////////
598 void ScanEdges (void)
601 float fx, fy, w, w2, clipwidthf = clipwidth - 0.5f;
602 clipedge_t *pedge, *pedge2, *ptemp;
603 clipsurf_t *psurf, *psurf2;
611 // Set up the active edge list as initially empty, containing
612 // only the sentinels (which are also the background fill). Most
613 // of these fields could be set up just once at start-up
614 edgehead.next = &edgetail;
615 edgehead.prev = NULL;
616 edgehead.x = edgehead.realx = -0.9999f; // left edge of screen
617 edgehead.realxstep = 0;
618 edgehead.leading = 1;
619 edgehead.psurf = &surfstack;
621 edgetail.next = NULL; // mark end of list
622 edgetail.prev = &edgehead;
623 edgetail.x = edgetail.realx = clipwidth + 0.5f; // right edge of screen
624 edgetail.realxstep = 0;
625 edgetail.leading = 0;
626 edgetail.psurf = &surfstack;
628 // The background surface is the entire stack initially, and
629 // is infinitely far away, so everything sorts in front of it.
630 // This could be set just once at start-up
631 surfstack.solid = true;
632 surfstack.visible = true; // no callback
633 surfstack.next = surfstack.prev = &surfstack;
634 surfstack.wcurrent = surfstack.w00 = -999999.0;
635 surfstack.wstepx = surfstack.wstepy = 0.0;
636 surfstack.removed = false;
638 // rescan causes the edges to be compared at the span level
639 // it is false if the scanline will be identical to the previous
641 for (y = 0;y < clipheight;y++)
645 cb = clipbuffer + y * clipwidth;
648 // Sort in any edges that start on this scan
649 if (newedges[y].next != &maxedge)
652 pedge = newedges[y].next;
654 while (pedge != &maxedge)
656 if (pedge->psurf->removed)
662 while (pedge->x > pedge2->next->x)
663 pedge2 = pedge2->next;
666 pedge->next = pedge2->next;
667 pedge->prev = pedge2;
668 pedge2->next->prev = pedge;
669 pedge2->next = pedge;
676 // Scan out the active edges into spans
678 // Start out with the left background edge already inserted, and the surface stack containing only the background
682 // must always rescan if rendering to wbuffer
687 for (pedge = edgehead.next;pedge;pedge = pedge->next)
690 psurf = pedge->psurf;
693 pedge2 = pedge->next;
694 pedge->prev->next = pedge->next;
695 pedge->next->prev = pedge->prev;
696 pedge->next = pedge->prev = pedge;
706 // It's a leading edge. Figure out where it is
707 // relative to the current surfaces and insert in
708 // the surface stack; if it's on top, emit the span
709 // for the current top.
710 // First, make sure the edges don't cross
711 if (++psurf->state == 1)
714 // Calculate the surface's 1/z value at this pixel, and cache the y depth for quick compares later
715 w = (psurf->wcurrent = psurf->w00 + psurf->wstepy * fy) + psurf->wstepx * fx;
719 // See if that makes it a new top surface
720 psurf2 = surfstack.next;
721 w2 = psurf2->wcurrent + psurf2->wstepx * fx;
722 // if (w2 < 0 && psurf2 != &surfstack)
727 // It's a new top surface
728 // emit the span for the current top
729 if (fx > cx && !psurf2->visible)
731 psurf2->visible = true;
732 psurf2->callback(psurf2->nativedata, psurf2->nativedata2);
736 for (x = ceil(cx), x2 = ceil(fx) >= clipwidth ? clipwidth : ceil(fx), zi = psurf2->wcurrent + psurf2->wstepx * x;x < x2;x++, zi += psurf2->wstepx)
742 // Add the edge to the stack
743 psurf->next = psurf2;
744 psurf2->prev = psurf;
745 surfstack.next = psurf;
746 psurf->prev = &surfstack;
750 // Not a new top; sort into the surface stack.
751 // Guaranteed to terminate due to sentinel background surface
754 psurf2 = psurf2->next;
755 w2 = psurf2->wcurrent + psurf2->wstepx * fx;
756 // if (w2 < 0 && psurf2 != &surfstack)
761 // Insert the surface into the stack
762 psurf->next = psurf2;
763 psurf->prev = psurf2->prev;
764 psurf2->prev->next = psurf;
765 psurf2->prev = psurf;
771 // It's a trailing edge; if this was the top surface,
772 // emit the span and remove it.
773 // First, make sure the edges didn't cross
774 if (--psurf->state == 0)
776 if (surfstack.next == psurf)
780 // It's on top, emit the span
781 if (fx > cx && !psurf->visible)
783 psurf->visible = true;
784 psurf->callback(psurf->nativedata, psurf->nativedata2);
789 for (x = ceil(cx), x2 = ceil(fx) >= clipwidth ? clipwidth : ceil(fx), zi = psurf->w00 + psurf->wstepx * x + psurf->wstepy * fy;x < x2;x++, zi += psurf->wstepx)
796 // Remove the surface from the stack
797 psurf->next->prev = psurf->prev;
798 psurf->prev->next = psurf->next;
802 // mark and remove all non-solid surfaces that are ontop
803 while (!surfstack.next->solid)
805 psurf = surfstack.next;
808 psurf->visible = true;
809 psurf->callback(psurf->nativedata, psurf->nativedata2);
811 psurf->removed = true;
812 psurf->next->prev = psurf->prev;
813 psurf->prev->next = psurf->next;
814 // isolate the surface
815 psurf->next = psurf->prev = psurf;
821 // Remove edges that are done
822 pedge = removeedges[y];
827 if (!pedge->psurf->removed)
829 pedge->prev->next = pedge->next;
830 pedge->next->prev = pedge->prev;
831 if (pedge->psurf->visible)
834 pedge = pedge->nextremove;
838 // Step the remaining edges one scan line, and re-sort
839 for (pedge = edgehead.next;pedge != &edgetail;)
842 if (pedge->psurf->removed)
844 pedge->next->prev = pedge->prev;
845 pedge->prev->next = pedge->next;
846 pedge->next = pedge->prev = pedge;
852 if (pedge->realxstep)
854 pedge->realx += pedge->realxstep;
855 pedge->x = bound(0.0f, pedge->realx, clipwidthf);
859 // Move the edge back to the proper sorted location, if necessary
860 while (fx < pedge->prev->x)
862 if (!rescan && (pedge->psurf->solid || pedge->prev->psurf->solid))
864 pedge2 = pedge->prev;
865 pedge2->next = pedge->next;
866 pedge->next->prev = pedge2;
867 pedge2->prev->next = pedge;
868 pedge->prev = pedge2->prev;
869 pedge->next = pedge2;
870 pedge2->prev = pedge;
878 void R_Clip_DisplayBuffer(void)
882 static int firstupload = true;
883 byte clipbuffertex[256*256], *b;
886 if (clipwidth > 256 || clipheight > 256)
888 glBlendFunc(GL_ONE, GL_ONE);
889 glBindTexture(GL_TEXTURE_2D, 8000);
892 memset(clipbuffertex, 0, sizeof(clipbuffertex));
893 glTexImage2D(GL_TEXTURE_2D, 0, 1, 256, 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, clipbuffertex);
895 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
896 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
897 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
899 glColor3f(0.5, 0.5, 0.5);
904 for (i = 0;i < clipwidth*clipheight;i++)
906 if (clipbuffer[i].w > 0)
907 *b++ = bound(0, (int) (clipbuffer[i].w * 4096.0f), 255);
911 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, clipwidth, clipheight, GL_LUMINANCE, GL_UNSIGNED_BYTE, clipbuffertex);
913 glTexCoord2f (0 , 0 );glVertex2f (0 , 0 );
914 glTexCoord2f (clipwidth / 256.0f, 0 );glVertex2f (vid.width, 0 );
915 glTexCoord2f (clipwidth / 256.0f, clipheight / 256.0f);glVertex2f (vid.width, vid.height);
916 glTexCoord2f (0 , clipheight / 256.0f);glVertex2f (0 , vid.height);
918 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
919 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
920 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
924 float boxpoints[4*3];
926 #define R_Clip_MinsBoxPolygon(axis, axisvalue, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, callback, nativedata, nativedata2, plane) \
928 if (r_origin[(axis)] < ((axisvalue) - 0.5f))\
930 (plane)->dist = -axisvalue;\
931 boxpoints[ 0] = x1;boxpoints[ 1] = y1;boxpoints[ 2] = z1;\
932 boxpoints[ 3] = x2;boxpoints[ 4] = y2;boxpoints[ 5] = z2;\
933 boxpoints[ 6] = x3;boxpoints[ 7] = y3;boxpoints[ 8] = z3;\
934 boxpoints[ 9] = x4;boxpoints[10] = y4;boxpoints[11] = z4;\
935 R_Clip_AddPolygon (boxpoints, 4, sizeof(float[3]), false, callback, nativedata, nativedata2, plane);\
939 #define R_Clip_MaxsBoxPolygon(axis, axisvalue, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, callback, nativedata, nativedata2, plane) \
941 if (r_origin[(axis)] > ((axisvalue) + 0.5f))\
943 (plane)->dist = axisvalue;\
944 boxpoints[ 0] = x1;boxpoints[ 1] = y1;boxpoints[ 2] = z1;\
945 boxpoints[ 3] = x2;boxpoints[ 4] = y2;boxpoints[ 5] = z2;\
946 boxpoints[ 6] = x3;boxpoints[ 7] = y3;boxpoints[ 8] = z3;\
947 boxpoints[ 9] = x4;boxpoints[10] = y4;boxpoints[11] = z4;\
948 R_Clip_AddPolygon (boxpoints, 4, sizeof(float[3]), false, callback, nativedata, nativedata2, plane);\
952 tinyplane_t clipboxplane[6] =
962 void R_Clip_AddBox(float *a, float *b, void (*callback)(void *nativedata, void *nativedata2), void *nativedata, void *nativedata2)
964 if (r_origin[0] >= (a[0] - 5.0f) && r_origin[0] < (b[0] + 5.0f)
965 && r_origin[1] >= (a[1] - 5.0f) && r_origin[1] < (b[1] + 5.0f)
966 && r_origin[2] >= (a[2] - 5.0f) && r_origin[2] < (b[2] + 5.0f))
968 callback(nativedata, nativedata2);
975 R_Clip_MinsBoxPolygon
982 callback, nativedata, nativedata2, &clipboxplane[0]
984 R_Clip_MaxsBoxPolygon
991 callback, nativedata, nativedata2, &clipboxplane[1]
993 R_Clip_MinsBoxPolygon
1000 callback, nativedata, nativedata2, &clipboxplane[2]
1002 R_Clip_MaxsBoxPolygon
1009 callback, nativedata, nativedata2, &clipboxplane[3]
1011 R_Clip_MinsBoxPolygon
1018 callback, nativedata, nativedata2, &clipboxplane[4]
1020 R_Clip_MaxsBoxPolygon
1027 callback, nativedata, nativedata2, &clipboxplane[5]