1 //**************************************************************************
9 //** Rendering lists and other rendering.
11 //**************************************************************************
13 // HEADER FILES ------------------------------------------------------------
16 #define WIN32_LEAN_AND_MEAN
32 // MACROS ------------------------------------------------------------------
34 // TYPES -------------------------------------------------------------------
36 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
38 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
40 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
42 static void OGL_ProjectionMatrix();
43 void RL_DynLightQuad(rendquad_t *quad, lumobj_t *lum);
46 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
50 extern fadeout_t fadeOut[2]; // For both skies.
51 extern int skyhemispheres;
53 // PUBLIC DATA DEFINITIONS -------------------------------------------------
55 boolean whitefog = false; // Is the white fog in use?
57 float vx, vy, vz, vang, vpitch;
59 boolean willRenderSprites = true, freezeRLs = false;
61 lumobj_t *luminousList = 0;
62 int numLuminous = 0, maxLuminous = 0;
63 int dlMaxRad = 64; // Dynamic lights maximum radius.
65 // PRIVATE DATA DEFINITIONS ------------------------------------------------
68 static float nearClip = 5, farClip = 8000;
69 static float viewph, viewpw;
70 static float viewsidex, viewsidey; // For the black fog.
72 static boolean firstsubsector; // No range checking for the first one.
74 // CODE --------------------------------------------------------------------
76 // How far the point is from the viewside plane?
77 float PointDist2D(float c[2])
79 /* (YA-YC)(XB-XA)-(XA-XC)(YB-YA)
80 s = -----------------------------
82 Luckily, L**2 is one. dist = s*L. Even more luckily, L is also one.
84 float dist = (vz-c[VY])*viewsidex - (vx-c[VX])*viewsidey;
85 if(dist < 0) return -dist; // Always return positive.
89 // ---------------------------------------------------
93 OGL_TexInit(); // OpenGL texture manager.
94 bamsInit(); // Binary angle calculations.
96 RL_Init(); // Rendering lists.
99 void OGL_ResetData() // Called before starting a new level.
101 OGL_TexReset(); // Textures are deleted (at least skies need this???).
102 RL_DeleteLists(); // The rendering lists are destroyed.
104 // We'll delete the sky textures. New ones will be generated for each level.
105 //glDeleteTextures(2, skynames);
106 //skynames[0] = skynames[1] = 0;
108 // Ready for new fadeout colors.
109 fadeOut[0].set = fadeOut[1].set = 0;
114 void OGL_InitRenderer() // Initializes the renderer to 2D state.
116 GLfloat fogcol[4] = { .7f, .7f, .7f, 1 };
118 // PC_Init(&clipperclock);
119 // PC_Init(&rlclock);
120 // PC_Init(&miscclock);
122 // Here we configure the OpenGL state and set projection matrix.
124 glDisable(GL_CULL_FACE);
126 glDisable(GL_DEPTH_TEST);
127 glDepthFunc(GL_LESS);
128 glEnable(GL_TEXTURE_2D);
129 //glPolygonMode(GL_FRONT, GL_LINE);
131 // The projection matrix.
132 glMatrixMode(GL_PROJECTION);
134 glOrtho (0, 320, 200, 0, -1, 1);
136 // Initialize the modelview matrix.
137 glMatrixMode(GL_MODELVIEW);
140 // Clear also the texture matrix (I'm not using this, though).
141 glMatrixMode(GL_TEXTURE);
144 // Alpha blending is a go!
146 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
147 glEnable(GL_ALPHA_TEST);
148 glAlphaFunc(GL_GREATER, 0);
150 // Default state for the white fog is off.
153 glFogi(GL_FOG_MODE, GL_LINEAR);
154 glFogi(GL_FOG_END, 3500); // This should be tweaked a bit.
155 glFogfv(GL_FOG_COLOR, fogcol);
157 /*glEnable(GL_POLYGON_SMOOTH);
158 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);*/
160 // Check the performance counter.
164 QueryPerformanceFrequency(&freq);
165 QueryPerformanceCounter((LARGE_INTEGER*)&start);
166 printf( "Performance counter frequency: %I64d counts per second.\n", freq);
167 QueryPerformanceCounter((LARGE_INTEGER*)&end);
168 printf( "(the printing of that took %I64d tics)\n", end-start);
171 // We don't want any hassles with uninitialized names, do we?
172 //skynames[0] = skynames[1] = 0;
175 void OGL_UseWhiteFog(int yes)
179 // White fog is turned on.
183 else if(whitefog && !yes)
185 // White fog must be turned off.
189 // Otherwise we won't do a thing.
192 void OGL_SwitchTo3DState()
194 // extern int setblocks;
196 // Push the 2D state on the stack.
197 glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
198 glMatrixMode(GL_PROJECTION);
200 glMatrixMode(GL_MODELVIEW);
203 // Enable some.. things.
204 glEnable(GL_CULL_FACE);
205 glEnable(GL_DEPTH_TEST);
208 if(viewheight != SCREENHEIGHT)
210 int svx = viewwindowx * screenWidth/320,
211 svy = viewwindowy * screenHeight/200;
212 viewpw = viewwidth * screenWidth/320;
213 viewph = viewheight * screenHeight/200 + 1;
214 glViewport(svx, screenHeight-svy-viewph, viewpw, viewph);
218 viewpw = screenWidth;
219 viewph = screenHeight;
222 // The 3D projection matrix.
223 OGL_ProjectionMatrix();
226 void OGL_Restore2DState(int step)
230 extern int screenblocks;
231 glMatrixMode(GL_PROJECTION);
233 glOrtho (0, 320, (screenblocks<11)?161:200, 0, -1, 1);
234 glMatrixMode(GL_MODELVIEW);
237 // Retrieve the old state.
240 glMatrixMode(GL_PROJECTION);
242 glMatrixMode(GL_MODELVIEW);
248 static void OGL_ProjectionMatrix()
250 // We're assuming pixels are squares... well, they are nowadays.
251 float aspect = (float)viewpw/(float)viewph;
252 //float aspect = 1.0;
253 glMatrixMode(GL_PROJECTION);
255 gluPerspective(yfov=90.0/aspect, aspect, nearClip, farClip);
259 static void OGL_ModelViewMatrix()
264 vang = viewangle / (float)ANGLE_MAX * 360 - 90;
266 glMatrixMode(GL_MODELVIEW);
268 glRotatef(vpitch=viewpitch * 42.5/110.0, 1, 0, 0);
269 glRotatef(vang, 0, 1, 0);
270 glScalef(1, 1.2f, 1); // This is the aspect correction.
271 glTranslatef(-vx,-vy,-vz);
275 // *VERY* similar to SegFacingDir(). Well, this is actually the same
276 // function, only a more general version.
277 static int SegFacingPoint(float v1[2], float v2[2], float p[2])
279 float nx = v1[VY]-v2[VY], ny = v2[VX]-v1[VX];
280 float pvx = v1[VX]-p[VX], pvy = v1[VY]-p[VY];
282 if(nx*pvx+ny*pvy > 0) return 1; // Facing front.
283 return 0; // Facing away.
286 static void projectVector(float a[2], float b[2], float *a_on_b)
289 float factor = (a[0]*b[0] + a[1]*b[1]) / (b[0]*b[0] + b[1]*b[1]);
290 for(c=0; c<2; c++) a_on_b[c] = factor * b[c];
293 // Create dynamic light quads, if necessary.
294 static void DL_ProcessWall(rendquad_t *quad, float v1[2], float v2[2])
299 float vecLight[2]; // Vector from v1 to light point.
300 float uvecWall[2], uvecWallNormal[2]; // Unit vectors.
302 float dist; // Distance between light source and wall.
304 // We can't handle masked walls. The alpha...
305 if(quad->flags & RQF_MASKED) return;
307 for(i=0; i<numLuminous; i++)
309 lumobj_t *lum = luminousList + i;
310 // If the light is not in use, we skip it.
311 if(!lum->use) continue;
312 // First we must check orientation. Backfaces aren't lighted, naturally.
313 pntLight[VX] = FIX2FLT(lum->thing->x);
314 pntLight[VY] = FIX2FLT(lum->thing->y);
315 if(!SegFacingPoint(v1, v2, pntLight)) continue;
316 // Make a copy of the original.
317 memcpy(&dlq, quad, sizeof(dlq));
318 // Copy the given end points.
319 memcpy(dlq.v1, v1, sizeof(v1));
320 memcpy(dlq.v2, v2, sizeof(v2));
321 dlq.flags |= RQF_LIGHT; // This is a light texture.
322 dlq.texw = dlq.texh = dlMaxRad*2;
325 uvecWall[c] = (quad->v2[c] - quad->v1[c]) / quad->u.q.len;
327 uvecWallNormal[VX] = uvecWall[VY];
328 uvecWallNormal[VY] = -uvecWall[VX];
329 // The relative position of the light source.
330 for(c=0; c<2; c++) vecLight[c] = pntLight[c] - quad->v1[c];
331 // The distance vector. VecLight projected on the normal vector.
332 projectVector(vecLight, uvecWallNormal, vecDist);
333 // The accurate distance from the wall to the light.
334 dist = sqrt(vecDist[0]*vecDist[0] + vecDist[1]*vecDist[1]);
335 if(dist > dlMaxRad) continue; // Too far away.
336 // Now we can calculate the intensity of the light.
337 dlq.light = 1.5f - 1.5f*dist/dlMaxRad;
338 // Do a scalar projection for the offset.
339 dlq.texoffx = vecLight[0]*uvecWall[0] + vecLight[1]*uvecWall[1] - dlMaxRad;
340 // There is no need to draw the *whole* wall always. Adjust the start
341 // and end points so that only a relevant portion is included.
342 if(dlq.texoffx > dlq.u.q.len) continue; // Doesn't fit on the wall.
343 if(dlq.texoffx < -dlq.texw) continue; // Ditto, but in the other direction.
346 for(c=0; c<2; c++) dlq.v1[c] += dlq.texoffx * uvecWall[c];
347 if(dlq.texoffx+dlq.texw <= dlq.u.q.len) // Fits completely?
349 for(c=0; c<2; c++) dlq.v2[c] = dlq.v1[c] + dlq.texw*uvecWall[c];
350 dlq.u.q.len = dlq.texw;
353 dlq.u.q.len -= dlq.texoffx;
356 else // It goes off to the left.
358 if(dlq.texoffx+dlq.texw <= dlq.u.q.len) // Fits completely?
360 for(c=0; c<2; c++) dlq.v2[c] = dlq.v1[c] + (dlq.texw+dlq.texoffx)*uvecWall[c];
361 dlq.u.q.len = dlq.texw + dlq.texoffx;
364 // The vertical offset is easy to determine.
365 dlq.texoffy = FIX2FLT(lum->thing->z)+lum->top-lum->height/2 + dlMaxRad - dlq.top;
366 if(dlq.texoffy < -dlq.top+dlq.u.q.bottom) continue;
367 if(dlq.texoffy > dlq.texh) continue;
368 if(dlq.top+dlq.texoffy-dlq.texh >= dlq.u.q.bottom) // Fits completely?
369 dlq.u.q.bottom = dlq.top+dlq.texoffy-dlq.texh;
372 dlq.top += dlq.texoffy;
375 // As a final touch, move the light quad a bit away from the wall
376 // to avoid z-fighting.
379 dlq.v1[c] += .2 * uvecWallNormal[c];
380 dlq.v2[c] += .2 * uvecWallNormal[c];
382 // Now we can give the new quad to the rendering engine.
387 static int SegFacingDir(float v1[2], float v2[2])
389 float nx = v1[VY]-v2[VY], ny = v2[VX]-v1[VX];
390 float vvx = v1[VX]-vx, vvy = v1[VY]-vz;
393 if(nx*vvx+ny*vvy > 0) return 1; // Facing front.
394 return 0; // Facing away.
397 // The sector height should've been checked by now.
398 void R_RenderWallSeg(seg_t *seg, sector_t *frontsec, boolean accurate)
400 sector_t *backsec = seg->backsector;
401 side_t *sid = seg->sidedef;
402 line_t *ldef = seg->linedef;
403 float ffloor = FIX2FLT(frontsec->floorheight);
404 float fceil = FIX2FLT(frontsec->ceilingheight);
405 float bfloor, bceil, fsh = fceil-ffloor, bsh;
408 float origv1[2], origv2[2]; // The original end points, for dynlights.
410 memset(&quad, 0, sizeof(quad)); // Clear the quad.
412 // Get the start and end points. Full floating point conversion is
413 // actually only necessary for polyobjs.
416 quad.v1[VX] = FIX2FLT(seg->v1->x);
417 quad.v1[VY] = FIX2FLT(seg->v1->y);
418 quad.v2[VX] = FIX2FLT(seg->v2->x);
419 quad.v2[VY] = FIX2FLT(seg->v2->y);
420 // These are the original vertices, copy them.
421 memcpy(origv1, quad.v1, sizeof(origv1));
422 memcpy(origv2, quad.v2, sizeof(origv2));
428 quad.v1[VX] = Q_FIX2FLT(seg->v1->x);
429 quad.v1[VY] = Q_FIX2FLT(seg->v1->y);
430 quad.v2[VX] = Q_FIX2FLT(seg->v2->x);
431 quad.v2[VY] = Q_FIX2FLT(seg->v2->y);
432 // The original vertex. For dlights.
433 memcpy(origv1, quad.v1, sizeof(origv1));
434 memcpy(origv2, quad.v2, sizeof(origv2));
435 // Make the very small crack-hiding adjustment.
436 dx = quad.v2[VX] - quad.v1[VX];
437 dy = quad.v2[VY] - quad.v1[VY];
438 quad.v2[VX] += dx/seg->len/4;
439 quad.v2[VY] += dy/seg->len/4;
442 // Let's first check which way this seg is facing.
443 if(!SegFacingDir(quad.v1, quad.v2)) return; // The wrong direction?
445 // Calculate the distances.
446 quad.dist[0] = PointDist2D(quad.v1);
447 quad.dist[1] = PointDist2D(quad.v2);
449 // Calculate the lightlevel.
450 quad.light = frontsec->lightlevel;
451 /*if(quad.v1[VX] == quad.v2[VX]) quad.light += 16;
452 if(quad.v1[VY] == quad.v2[VY]) quad.light -= 16;*/
455 // This line is now seen in the map.
456 ldef->flags |= ML_MAPPED;
458 // Some texture coordinates.
459 quad.texoffx = (sid->textureoffset>>FRACBITS)+(seg->offset>>FRACBITS);
460 quad.u.q.len = seg->len;
461 tcyoff = Q_FIX2FLT(sid->rowoffset);
463 // The middle texture, single sided.
464 if(sid->midtexture && !backsec)
466 curtex = OGL_PrepareTexture(sid->midtexture);
467 quad.texoffy = tcyoff;
468 if(ldef->flags & ML_DONTPEGBOTTOM)
469 quad.texoffy += texh-fsh;
471 // Fill in the remaining quad data.
474 quad.u.q.bottom = ffloor;
477 RL_AddQuad(&quad, curtex);
478 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
480 //printf( "Solid segment in sector %p.\n", frontsec);
481 // This is guaranteed to be a solid segment.
482 C_AddViewRelSeg(quad.v1[VX],quad.v1[VY],quad.v2[VX],quad.v2[VY]);
487 if(!backsec || (backsec && (backsec->ceilingheight+(backsec->skyfix<<FRACBITS) <
488 frontsec->ceilingheight+(frontsec->skyfix<<FRACBITS))))// ||
489 //backsec->floorheight == frontsec->ceilingheight)))
491 quad.flags = RQF_SKY_MASK_WALL;
492 quad.top = fceil + frontsec->skyfix;
493 quad.u.q.bottom = fceil;
494 RL_AddQuad(&quad, curtex);
495 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
498 // If there is a back sector we may need upper and lower walls.
499 if(backsec) // A twosided seg?
501 bfloor = FIX2FLT(backsec->floorheight);
502 bceil = FIX2FLT(backsec->ceilingheight);
503 bsh = bceil - bfloor;
504 if(bsh <= 0 || bceil <= ffloor || bfloor >= fceil)
506 //printf( "Solid segment in sector %p (backvol=0).\n", frontsec);
507 // The backsector has no space. This is a solid segment.
508 C_AddViewRelSeg(quad.v1[VX],quad.v1[VY],quad.v2[VX],quad.v2[VY]);
510 if(sid->midtexture) // Quite probably a masked texture.
512 float mceil = (bceil<fceil)?bceil:fceil,
513 mfloor = (bfloor>ffloor)?bfloor:ffloor,
514 msh = mceil - mfloor;
517 curtex = OGL_PrepareTexture(sid->midtexture);
518 // Calculate the texture coordinates. Also restrict
519 // vertical tiling (if masked) by adjusting mceil and mfloor.
520 if(texmask) // A masked texture?
522 quad.flags = RQF_MASKED;
524 // We don't allow vertical tiling.
525 if(ldef->flags & ML_DONTPEGBOTTOM)
528 mceil = mfloor + texh;
533 mfloor = mceil - texh;
536 else // Normal texture.
539 quad.texoffy = tcyoff;
540 if(ldef->flags & ML_DONTPEGBOTTOM) // Lower unpegged. Align bottom.
541 quad.texoffy += texh-msh;
543 // Fill in the remainder of the data.
545 quad.u.q.bottom = mfloor;
548 RL_AddQuad(&quad, curtex);
549 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
553 if(bceil < fceil && !(frontsec->ceilingpic == skyflatnum && backsec->ceilingpic == skyflatnum))
555 float topwh = fceil - bceil;
556 if(sid->toptexture) // A texture present?
558 curtex = OGL_PrepareTexture(sid->toptexture);
559 // Calculate texture coordinates.
560 quad.texoffy = tcyoff;
561 if(!(ldef->flags & ML_DONTPEGTOP))
563 // Normal alignment to bottom.
564 quad.texoffy += texh-topwh;
570 // No texture? Bad thing. You don't deserve texture
571 // coordinates. Take the ceiling texture.
572 curtex = OGL_PrepareFlat(frontsec->ceilingpic);
573 quad.flags = RQF_FLAT | RQF_MISSING_WALL;
576 quad.u.q.bottom = bceil;
579 RL_AddQuad(&quad, curtex);
580 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
583 if(bfloor > ffloor && !(frontsec->floorpic == skyflatnum && backsec->floorpic == skyflatnum))
585 if(sid->bottomtexture) // There is a texture?
587 curtex = OGL_PrepareTexture(sid->bottomtexture);
588 // Calculate texture coordinates.
589 quad.texoffy = tcyoff;
590 if(ldef->flags & ML_DONTPEGBOTTOM)
592 // Lower unpegged. Align with normal middle texture.
593 //quad.texoffy += fsh-texh;
594 quad.texoffy += fceil-bfloor;
600 // No texture? Again!
601 curtex = OGL_PrepareFlat(frontsec->floorpic);
602 quad.flags = RQF_FLAT | RQF_MISSING_WALL;
605 quad.u.q.bottom = ffloor;
608 RL_AddQuad(&quad, curtex);
609 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
614 void R_HandleSectorSpecials(sector_t *sect)
616 int scrollOffset = leveltime>>1 & 63;
618 switch(sect->special)
619 { // Handle scrolling flats
620 case 201: case 202: case 203: // Scroll_North_xxx
621 sect->flatoffy = (63-scrollOffset) << (sect->special-201);
623 case 204: case 205: case 206: // Scroll_East_xxx
624 sect->flatoffx = (63-scrollOffset) << (sect->special-204);
626 case 207: case 208: case 209: // Scroll_South_xxx
627 sect->flatoffy = scrollOffset << (sect->special-207);
629 case 210: case 211: case 212: // Scroll_West_xxx
630 sect->flatoffx = scrollOffset << (sect->special-210);
632 case 213: case 214: case 215: // Scroll_NorthWest_xxx
633 sect->flatoffx = scrollOffset << (sect->special-213);
634 sect->flatoffy = (63-scrollOffset) << (sect->special-213);
636 case 216: case 217: case 218: // Scroll_NorthEast_xxx
637 sect->flatoffx = (63-scrollOffset) << (sect->special-216);
638 sect->flatoffy = (63-scrollOffset) << (sect->special-216);
640 case 219: case 220: case 221: // Scroll_SouthEast_xxx
641 sect->flatoffx = (63-scrollOffset) << (sect->special-219);
642 sect->flatoffy = scrollOffset << (sect->special-219);
644 case 222: case 223: case 224: // Scroll_SouthWest_xxx
645 sect->flatoffx = scrollOffset << (sect->special-222);
646 sect->flatoffy = scrollOffset << (sect->special-222);
649 sect->flatoffx = sect->flatoffy = 0;
656 if (luminousList) free(luminousList);
658 maxLuminous = numLuminous = 0;
661 boolean DL_AddLuminous(mobj_t *thing)
663 if(thing->frame & FF_FULLBRIGHT && !(thing->flags2&MF2_DONTDRAW))
666 spriteframe_t *sprframe;
670 // Only allocate memory when it's needed.
671 if(++numLuminous > maxLuminous)
672 luminousList = realloc(luminousList, sizeof(lumobj_t) * (maxLuminous+=5));
673 lum = luminousList + numLuminous-1;
675 // We need to know how tall the thing currently is.
676 sprdef = &sprites[thing->sprite];
677 sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK ];
679 lump = sprframe->lump[(R_PointToAngle(thing->x, thing->y) - thing->angle + (unsigned)(ANG45/2)*9) >> 29];
681 lump = sprframe->lump[0];
682 // This'll ensure we have up-to-date information.
683 OGL_PrepareSprite(lump);
684 lum->top = FIX2FLT(spritetopoffset[lump]);
685 lum->height = spriteheights[lump];
686 //printf( "%p: t:%.2f h:%.2f\n", thing, lum->top, lum->height);
691 // We want to know which luminous objects are close enough the subsector.
692 void DL_MarkForSubsector(subsector_t *sub)
695 float minx, miny, maxx, maxy; // Subsector bounding box.
697 // First determine the subsector bounding box based on
699 /*maxx = minx = sub->edgeverts[0].x;
700 maxy = miny = sub->edgeverts[0].y;
701 for(i=1; i<sub->numedgeverts; i++)
703 float x = sub->edgeverts[i].x, y = sub->edgeverts[i].y;
704 if(x > maxx) maxx = x;
705 if(x < minx) minx = x;
706 if(y > maxy) maxy = y;
707 if(y < miny) miny = y;
709 // Adjust the bounding box to include the maximum radius of the
710 // dynamic lights (64).
711 maxx += dlMaxRad; minx -= dlMaxRad;
712 maxy += dlMaxRad; miny -= dlMaxRad;*/
714 // Adjust the bounding box to include the maximum radius of the
715 // dynamic lights (64).
716 minx = sub->bbox[0].x - dlMaxRad;
717 miny = sub->bbox[0].y - dlMaxRad;
718 maxx = sub->bbox[1].x + dlMaxRad;
719 maxy = sub->bbox[1].y + dlMaxRad;
720 // Now check all the luminous objects and mark those that
722 for(i=0; i<numLuminous; i++)
724 lumobj_t *lum = luminousList + i;
725 float x = Q_FIX2FLT(lum->thing->x), y = Q_FIX2FLT(lum->thing->y);
726 // By default the luminous object isn't used.
728 // Is inside the bounding box?
729 if(x > minx && y > miny && x < maxx && y < maxy)
734 void R_RenderSubsector(int ssecidx)
736 subsector_t *ssec = subsectors+ssecidx;
737 extern subsector_t *currentssec;
740 sector_t *sect = ssec->sector;
741 float ffloor = FIX2FLT(sect->floorheight);
742 float fceil = FIX2FLT(sect->ceilingheight);
745 if(fceil-ffloor <= 0)
747 return; // Skip this, no volume.
752 if(!C_CheckSubsector(ssec)) return; // This isn't visible.
755 firstsubsector = false;
757 // printf( "*** Rendering subsector %d (sector %p)\n", ssecidx, sect);
761 // Sprites for this sector have to be drawn. This must be done before
762 // the segments of this subsector are added to the clipper. Otherwise
763 // the sprites would get clipped by them, and that wouldn't be right.
767 if(useDynLights) DL_MarkForSubsector(ssec);
770 for(i=0, seg=segs+ssec->firstline; i<ssec->numlines; i++, seg++)
771 R_RenderWallSeg(seg, sect, false);
773 // Is there a polyobj on board?
776 memset(&triangle, 0, sizeof(triangle));
777 triangle.flags = RQF_FLAT | RQF_FLOOR_FACING; // This is a flat floor triangle.
778 triangle.light = sect->lightlevel / 255.0;
779 if(viewz > sect->floorheight) // && vpitch < yfov)
781 // Check for sky... in the floor?
782 if(sect->floorpic == skyflatnum)
784 triangle.flags |= RQF_SKY_MASK;
785 skyhemispheres |= SKYHEMI_LOWER;
787 curtex = OGL_PrepareFlat(sect->floorpic);
788 triangle.texw = texw;
789 triangle.texh = texh;
790 triangle.texoffx = sect->flatoffx;
791 triangle.texoffy = sect->flatoffy;
792 triangle.top = ffloor;
793 // The first vertex is always the first in the whole list.
794 RL_AddFlatQuads(&triangle, curtex, ssec->numedgeverts, ssec->edgeverts, 0);
796 if(useDynLights && sect->floorpic != skyflatnum)
798 triangle.flags |= RQF_LIGHT;
799 triangle.top += .05f; // An adjustment.
800 for(i=0; i<numLuminous; i++)
802 lumobj_t *lum = luminousList + i;
804 if(!lum->use) continue;
806 z = FIX2FLT(lum->thing->z);
807 // Check that we're on the right side.
808 if(z+lum->top < triangle.top) continue; // Under it.
809 // Check that the height difference isn't too big.
810 z += lum->top - lum->height/2; // Center Z.
811 if((hdiff=fabs(triangle.top-z)) > dlMaxRad) continue;
812 triangle.light = 1.5f - 1.5f*hdiff/dlMaxRad;
813 // We can add the light quads.
814 RL_AddFlatQuads(&triangle, (int)lum, ssec->numedgeverts, ssec->origedgeverts, 0);
819 triangle.flags = RQF_FLAT;
820 triangle.light = sect->lightlevel / 255.0;
821 if(viewz < sect->ceilingheight) //&& vpitch > -yfov)
824 if(sect->ceilingpic == skyflatnum)
826 triangle.flags |= RQF_SKY_MASK;
827 skyhemispheres |= SKYHEMI_UPPER;
829 // Don't ask me why this works - DDOI
830 curtex = OGL_PrepareFlat(sect->ceilingpic);
831 triangle.texw = texw;
832 triangle.texh = texh;
833 triangle.texoffx = 0;
834 triangle.texoffy = 0;
835 triangle.top = fceil + sect->skyfix;
836 // The first vertex is always the last in the whole list
837 RL_AddFlatQuads(&triangle, curtex, ssec->numedgeverts, ssec->edgeverts, 1);
840 if(useDynLights && sect->ceilingpic != skyflatnum)
842 triangle.flags |= RQF_LIGHT;
843 triangle.top -= .05f; // An adjustment.
844 for(i=0; i<numLuminous; i++)
846 lumobj_t *lum = luminousList + i;
848 if(!lum->use) continue;
850 z = FIX2FLT(lum->thing->z);
851 // Check that we're on the right side.
852 if(z+lum->top-lum->height > triangle.top) continue; // Under it.
853 // Check that the height difference isn't too big.
854 z += lum->top - lum->height/2; // Center Z.
855 if((hdiff=fabs(triangle.top-z)) > dlMaxRad) continue;
856 triangle.light = 1.5f - 1.5f*hdiff/dlMaxRad;
857 // We can add the light quads.
858 RL_AddFlatQuads(&triangle, (int)lum, ssec->numedgeverts, ssec->origedgeverts, 1);
864 void R_RenderNode(int bspnum)
869 // If the clipper is full we're pretty much done.
871 if(cliphead->start == 0 && cliphead->end == BANG_MAX)
874 if (bspnum & NF_SUBSECTOR)
877 R_RenderSubsector(0);
879 R_RenderSubsector(bspnum&(~NF_SUBSECTOR));
883 bsp = &nodes[bspnum];
886 // decide which side the view point is on
888 side = R_PointOnSide (viewx, viewy, bsp);
890 R_RenderNode (bsp->children[side]); // recursively divide front space
892 /* if(cliphead->start == 0 && cliphead->end == BANG_MAX)
893 return; // We can stop rendering.*/
895 //if (R_CheckBBox (bsp->bbox[side^1])) // possibly divide back space
896 // We can't use that, unfortunately.
897 R_RenderNode (bsp->children[side^1]);
901 void R_RenderMap(void)
906 // This is all the clearing we'll do.
907 glClear(GL_DEPTH_BUFFER_BIT);
909 // Setup the modelview matrix.
910 OGL_ModelViewMatrix();
912 // Let's scroll some floors. This way we have to check them all,
913 // but there's no redundancy. And this really isn't all that expensive.
914 for(i=0; i<numsectors; i++) R_HandleSectorSpecials(sectors+i);
921 RL_ClearLists(); // Clear the lists for new quads.
922 C_ClearRanges(); // Clear the clipper.
923 if(useDynLights) // Maintain luminous objects list.
925 numLuminous = 0; // Clear the luminous object list.
927 // Add all the luminous objects to the list.
928 for(i=0; i<numsectors; i++)
930 sector_t *sec = sectors + i;
932 for(iter=sec->thinglist; iter; iter=iter->snext)
934 //for(k=0; k<bmapheight; k++)
935 // for(i=0; i<bmapwidth; i++)
936 //P_BlockThingsIterator(i, k, DL_AddLuminous);
937 DL_AddLuminous(iter);
941 // Add the backside clipping range, vpitch allowing.
942 if(vpitch <= 90-yfov/2 && vpitch >= -90+yfov/2)
944 float a = fabs(vpitch) / (90-yfov/2);
945 binangle startAngle = (binangle) BANG_45*(1+a);
946 binangle angLen = BANG_180 - startAngle;
947 viewside = (viewangle>>16) + startAngle;
948 C_SafeAddRange(viewside, viewside+angLen);
949 C_SafeAddRange(viewside+angLen, viewside+2*angLen);
950 //C_SafeAddRange(viewside+BANG_135, viewside+2*BANG_135);
952 // The viewside line for the black fog distance calculations.
953 viewsidex = -FIX2FLT(viewsin);
954 viewsidey = FIX2FLT(viewcos);
956 // We don't want subsector clipchecking for the first subsector.
957 //misccount = I_GetPerformanceCount();
958 firstsubsector = true;
959 R_RenderNode(numnodes-1);
960 //misccount = I_GetPerformanceCount()-misccount;
964 // Clipping fragmentation happens when there are holes in the walls.
968 printf("\nTic: %d, Clipnodes are fragmented:\n", gametic);
969 for(ci=cliphead; ci; ci=ci->next)
970 printf( "range %p: %4x => %4x (%d)\n",ci,ci->start,ci->end,ci->used);
971 I_Error("---Fragmented clipper---\n");
975 void R_RenderSprite(vissprite_t *spr)
978 // float off = FIX2FLT(spriteoffset[spr->patch]);
979 float w = FIX2FLT(spritewidth[spr->patch]);
981 float p2w = FindNextPower2((int)w), p2h;
982 float v1[2];//, v2[2];
983 //float sinrv, cosrv;
984 float tcleft, tcright;
989 OGL_SetSprite(spr->patch);
990 sprh = spriteheights[spr->patch];
991 p2h = FindNextPower2(sprh);
993 // v1[VX] = FIX2FLT(spr->gx);
994 //v1[VY] = FIX2FLT(spr->gy);
996 // Set the lighting and alpha.
997 if(spr->mobjflags & MF_SHADOW)
1002 if(spr->lightlevel < 0)
1003 glColor4f(1, 1, 1, alpha);
1006 v1[VX] = Q_FIX2FLT(spr->gx);
1007 v1[VY] = Q_FIX2FLT(spr->gy);
1008 SetVertexColor(spr->lightlevel/255.0, PointDist2D(v1), alpha);
1011 /* thangle = BANG2RAD(bamsAtan2((v1[VY]-vz)*10,(v1[VX]-vx)*10))-PI/2;
1012 sinrv = sin(thangle);
1013 cosrv = cos(thangle);*/
1015 // We must find the correct positioning using the sector floor and ceiling
1016 // heights as an aid.
1017 /*top = FIX2FLT(spr->gzt) + 4 - FIX2FLT(spr->floorclip);
1019 top = FIX2FLT(spr->gzt);
1020 if(sprh < spr->secceil-spr->secfloor) // Sprite fits in, adjustment possible?
1023 if(top > spr->secceil) top = spr->secceil;
1025 if(top-sprh < spr->secfloor)
1026 top = spr->secfloor+sprh;
1028 // Adjust by the floor clip.
1031 /* v1[VX] -= cosrv*off;
1032 v1[VY] -= sinrv*off;
1033 v2[VX] = v1[VX] + cosrv*w;
1034 v2[VY] = v1[VY] + sinrv*w;*/
1036 if(spr->xiscale < 0)
1038 // This is the flipped version.
1044 // No flipping; the normal version.
1049 // Choose the color for the sprite.
1050 /*glColor4f(1, 1, 1, (spr->mobjflags&MF_SHADOW)? .333
1051 : (spr->mobjflags&MF_ALTSHADOW)? .666 : 1);*/
1054 glTexCoord2f(tcleft, 0);
1055 glVertex3f(spr->v1[VX], top, spr->v1[VY]);
1057 glTexCoord2f(tcright, 0);
1058 glVertex3f(spr->v2[VX], top, spr->v2[VY]);
1060 glTexCoord2f(tcright, sprh/p2h);
1061 glVertex3f(spr->v2[VX], bot, spr->v2[VY]);
1063 glTexCoord2f(tcleft, sprh/p2h);
1064 glVertex3f(spr->v1[VX], bot, spr->v1[VY]);
1068 void OGL_DrawPSprite(int x, int y, float scale, int flip, int lump)
1073 OGL_SetSprite(lump);
1074 w = spritewidth[lump]>>FRACBITS;
1075 h = spriteheights[lump];
1076 tcx = NextPower2Ratio(w);
1077 tcy = NextPower2Ratio(h);
1081 glTexCoord2f((flip)? tcx : 0, 0);
1084 glTexCoord2f((flip)? 0 : tcx, 0);
1085 glVertex2f(x+w*scale, y);
1087 glTexCoord2f((flip)? 0 : tcx, tcy);
1088 glVertex2f(x+w*scale, y+h*scale);
1090 glTexCoord2f((flip)? tcx : 0, tcy);
1091 glVertex2f(x, y+h*scale);