1 //**************************************************************************
9 //** Rendering lists and other rendering.
11 //**************************************************************************
13 // HEADER FILES ------------------------------------------------------------
16 #define WIN32_LEAN_AND_MEAN
33 // MACROS ------------------------------------------------------------------
35 // TYPES -------------------------------------------------------------------
37 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
39 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
41 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
43 static void OGL_ProjectionMatrix();
44 void RL_DynLightQuad(rendquad_t *quad, lumobj_t *lum);
47 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
51 extern fadeout_t fadeOut[2]; // For both skies.
52 extern int skyhemispheres;
54 // PUBLIC DATA DEFINITIONS -------------------------------------------------
56 boolean whitefog = false; // Is the white fog in use?
58 float vx, vy, vz, vang, vpitch;
60 boolean willRenderSprites = true, freezeRLs = false;
62 lumobj_t *luminousList = 0;
63 int numLuminous = 0, maxLuminous = 0;
64 int dlMaxRad = 64; // Dynamic lights maximum radius.
66 // PRIVATE DATA DEFINITIONS ------------------------------------------------
68 static int viewpw, viewph; // Viewport size.
69 static float nearClip, farClip;
71 static float viewsidex, viewsidey; // For the black fog.
73 static boolean firstsubsector; // No range checking for the first one.
75 // CODE --------------------------------------------------------------------
77 // How far the point is from the viewside plane?
78 float PointDist2D(float c[2])
80 /* (YA-YC)(XB-XA)-(XA-XC)(YB-YA)
81 s = -----------------------------
83 Luckily, L**2 is one. dist = s*L. Even more luckily, L is also one.
85 float dist = (vz-c[VY])*viewsidex - (vx-c[VX])*viewsidey;
86 if(dist < 0) return -dist; // Always return positive.
90 // ---------------------------------------------------
94 OGL_TexInit(); // OpenGL texture manager.
95 bamsInit(); // Binary angle calculations.
97 RL_Init(); // Rendering lists.
100 void OGL_ResetData() // Called before starting a new level.
102 OGL_TexReset(); // Textures are deleted (at least skies need this???).
103 RL_DeleteLists(); // The rendering lists are destroyed.
105 // We'll delete the sky textures. New ones will be generated for each level.
106 //glDeleteTextures(2, skynames);
107 //skynames[0] = skynames[1] = 0;
109 // Ready for new fadeout colors.
110 fadeOut[0].set = fadeOut[1].set = 0;
115 void OGL_InitRenderer() // Initializes the renderer to 2D state.
117 GLfloat fogcol[4] = { .7f, .7f, .7f, 1 };
119 // PC_Init(&clipperclock);
120 // PC_Init(&rlclock);
121 // PC_Init(&miscclock);
127 // Here we configure the OpenGL state and set projection matrix.
129 glDisable(GL_CULL_FACE);
131 glDisable(GL_DEPTH_TEST);
132 glDepthFunc(GL_LESS);
133 glEnable(GL_TEXTURE_2D);
134 //glPolygonMode(GL_FRONT, GL_LINE);
136 // The projection matrix.
137 glMatrixMode(GL_PROJECTION);
139 gluOrtho2D(0,320,200,0);
141 // Initialize the modelview matrix.
142 glMatrixMode(GL_MODELVIEW);
145 // Clear also the texture matrix (I'm not using this, though).
146 glMatrixMode(GL_TEXTURE);
149 // Alpha blending is a go!
151 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
152 glEnable(GL_ALPHA_TEST);
153 glAlphaFunc(GL_GREATER, 0);
155 // Default state for the white fog is off.
158 glFogi(GL_FOG_MODE, GL_LINEAR);
159 glFogi(GL_FOG_END, 3500); // This should be tweaked a bit.
160 glFogfv(GL_FOG_COLOR, fogcol);
162 /*glEnable(GL_POLYGON_SMOOTH);
163 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);*/
165 // Check the performance counter.
169 QueryPerformanceFrequency(&freq);
170 QueryPerformanceCounter((LARGE_INTEGER*)&start);
171 printf( "Performance counter frequency: %I64d counts per second.\n", freq);
172 QueryPerformanceCounter((LARGE_INTEGER*)&end);
173 printf( "(the printing of that took %I64d tics)\n", end-start);
176 // We don't want any hassles with uninitialized names, do we?
177 //skynames[0] = skynames[1] = 0;
180 void OGL_UseWhiteFog(int yes)
184 // White fog is turned on.
188 else if(whitefog && !yes)
190 // White fog must be turned off.
194 // Otherwise we won't do a thing.
197 void OGL_SwitchTo3DState()
199 // extern int setblocks;
201 // Push the 2D state on the stack.
202 glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
203 glMatrixMode(GL_PROJECTION);
205 glMatrixMode(GL_MODELVIEW);
208 // Enable some.. things.
209 glEnable(GL_CULL_FACE);
210 glEnable(GL_DEPTH_TEST);
213 if(viewheight != SCREENHEIGHT)
215 int svx = viewwindowx * screenWidth/320,
216 svy = viewwindowy * screenHeight/200;
217 viewpw = viewwidth * screenWidth/320;
218 viewph = viewheight * screenHeight/200 + 1;
219 glViewport(svx, screenHeight-svy-viewph, viewpw, viewph);
223 viewpw = screenWidth;
224 viewph = screenHeight;
227 // The 3D projection matrix.
228 OGL_ProjectionMatrix();
231 void OGL_Restore2DState(int step)
235 extern int screenblocks;
236 glMatrixMode(GL_PROJECTION);
238 gluOrtho2D(0, 320, (screenblocks<11)?161:200, 0);
239 glMatrixMode(GL_MODELVIEW);
242 // Retrieve the old state.
245 glMatrixMode(GL_PROJECTION);
247 glMatrixMode(GL_MODELVIEW);
253 static void OGL_ProjectionMatrix()
255 // We're assuming pixels are squares... well, they are nowadays.
256 float aspect = (float)viewpw/(float)viewph;
257 //float aspect = 1.0;
258 glMatrixMode(GL_PROJECTION);
260 gluPerspective(yfov=90.0/aspect, aspect, nearClip, farClip);
261 // We'd like to have a left-handed coordinate system.
265 static void OGL_ModelViewMatrix()
270 vang = viewangle / (float)ANGLE_MAX * 360 - 90;
272 glMatrixMode(GL_MODELVIEW);
274 glRotatef(vpitch=viewpitch * 42.5/110.0, 1, 0, 0);
275 glRotatef(vang, 0, 1, 0);
276 glScalef(1, 1.2f, 1); // This is the aspect correction.
277 glTranslatef(-vx,-vy,-vz);
281 // *VERY* similar to SegFacingDir(). Well, this is actually the same
282 // function, only a more general version.
283 static int SegFacingPoint(float v1[2], float v2[2], float p[2])
285 float nx = v1[VY]-v2[VY], ny = v2[VX]-v1[VX];
286 float pvx = v1[VX]-p[VX], pvy = v1[VY]-p[VY];
288 if(nx*pvx+ny*pvy > 0) return 1; // Facing front.
289 return 0; // Facing away.
292 static void projectVector(float a[2], float b[2], float *a_on_b)
295 float factor = (a[0]*b[0] + a[1]*b[1]) / (b[0]*b[0] + b[1]*b[1]);
296 for(c=0; c<2; c++) a_on_b[c] = factor * b[c];
299 // Create dynamic light quads, if necessary.
300 static void DL_ProcessWall(rendquad_t *quad, float v1[2], float v2[2])
305 float vecLight[2]; // Vector from v1 to light point.
306 float uvecWall[2], uvecWallNormal[2]; // Unit vectors.
308 float dist; // Distance between light source and wall.
310 // We can't handle masked walls. The alpha...
311 if(quad->flags & RQF_MASKED) return;
313 for(i=0; i<numLuminous; i++)
315 lumobj_t *lum = luminousList + i;
316 // If the light is not in use, we skip it.
317 if(!lum->use) continue;
318 // First we must check orientation. Backfaces aren't lighted, naturally.
319 pntLight[VX] = FIX2FLT(lum->thing->x);
320 pntLight[VY] = FIX2FLT(lum->thing->y);
321 if(!SegFacingPoint(v1, v2, pntLight)) continue;
322 // Make a copy of the original.
323 memcpy(&dlq, quad, sizeof(dlq));
324 // Copy the given end points.
325 memcpy(dlq.v1, v1, sizeof(v1));
326 memcpy(dlq.v2, v2, sizeof(v2));
327 dlq.flags |= RQF_LIGHT; // This is a light texture.
328 dlq.texw = dlq.texh = dlMaxRad*2;
331 uvecWall[c] = (quad->v2[c] - quad->v1[c]) / quad->u.q.len;
333 uvecWallNormal[VX] = uvecWall[VY];
334 uvecWallNormal[VY] = -uvecWall[VX];
335 // The relative position of the light source.
336 for(c=0; c<2; c++) vecLight[c] = pntLight[c] - quad->v1[c];
337 // The distance vector. VecLight projected on the normal vector.
338 projectVector(vecLight, uvecWallNormal, vecDist);
339 // The accurate distance from the wall to the light.
340 dist = sqrt(vecDist[0]*vecDist[0] + vecDist[1]*vecDist[1]);
341 if(dist > dlMaxRad) continue; // Too far away.
342 // Now we can calculate the intensity of the light.
343 dlq.light = 1.5f - 1.5f*dist/dlMaxRad;
344 // Do a scalar projection for the offset.
345 dlq.texoffx = vecLight[0]*uvecWall[0] + vecLight[1]*uvecWall[1] - dlMaxRad;
346 // There is no need to draw the *whole* wall always. Adjust the start
347 // and end points so that only a relevant portion is included.
348 if(dlq.texoffx > dlq.u.q.len) continue; // Doesn't fit on the wall.
349 if(dlq.texoffx < -dlq.texw) continue; // Ditto, but in the other direction.
352 for(c=0; c<2; c++) dlq.v1[c] += dlq.texoffx * uvecWall[c];
353 if(dlq.texoffx+dlq.texw <= dlq.u.q.len) // Fits completely?
355 for(c=0; c<2; c++) dlq.v2[c] = dlq.v1[c] + dlq.texw*uvecWall[c];
356 dlq.u.q.len = dlq.texw;
359 dlq.u.q.len -= dlq.texoffx;
362 else // It goes off to the left.
364 if(dlq.texoffx+dlq.texw <= dlq.u.q.len) // Fits completely?
366 for(c=0; c<2; c++) dlq.v2[c] = dlq.v1[c] + (dlq.texw+dlq.texoffx)*uvecWall[c];
367 dlq.u.q.len = dlq.texw + dlq.texoffx;
370 // The vertical offset is easy to determine.
371 dlq.texoffy = FIX2FLT(lum->thing->z)+lum->top-lum->height/2 + dlMaxRad - dlq.top;
372 if(dlq.texoffy < -dlq.top+dlq.u.q.bottom) continue;
373 if(dlq.texoffy > dlq.texh) continue;
374 if(dlq.top+dlq.texoffy-dlq.texh >= dlq.u.q.bottom) // Fits completely?
375 dlq.u.q.bottom = dlq.top+dlq.texoffy-dlq.texh;
378 dlq.top += dlq.texoffy;
381 // As a final touch, move the light quad a bit away from the wall
382 // to avoid z-fighting.
385 dlq.v1[c] += .2 * uvecWallNormal[c];
386 dlq.v2[c] += .2 * uvecWallNormal[c];
388 // Now we can give the new quad to the rendering engine.
393 static int SegFacingDir(float v1[2], float v2[2])
395 float nx = v1[VY]-v2[VY], ny = v2[VX]-v1[VX];
396 float vvx = v1[VX]-vx, vvy = v1[VY]-vz;
399 if(nx*vvx+ny*vvy > 0) return 1; // Facing front.
400 return 0; // Facing away.
403 // The sector height should've been checked by now.
404 void R_RenderWallSeg(seg_t *seg, sector_t *frontsec, boolean accurate)
406 sector_t *backsec = seg->backsector;
407 side_t *sid = seg->sidedef;
408 line_t *ldef = seg->linedef;
409 float ffloor = FIX2FLT(frontsec->floorheight);
410 float fceil = FIX2FLT(frontsec->ceilingheight);
411 float bfloor, bceil, fsh = fceil-ffloor, bsh;
414 float origv1[2], origv2[2]; // The original end points, for dynlights.
416 memset(&quad, 0, sizeof(quad)); // Clear the quad.
418 // Get the start and end points. Full floating point conversion is
419 // actually only necessary for polyobjs.
422 quad.v1[VX] = FIX2FLT(seg->v1->x);
423 quad.v1[VY] = FIX2FLT(seg->v1->y);
424 quad.v2[VX] = FIX2FLT(seg->v2->x);
425 quad.v2[VY] = FIX2FLT(seg->v2->y);
426 // These are the original vertices, copy them.
427 memcpy(origv1, quad.v1, sizeof(origv1));
428 memcpy(origv2, quad.v2, sizeof(origv2));
434 quad.v1[VX] = Q_FIX2FLT(seg->v1->x);
435 quad.v1[VY] = Q_FIX2FLT(seg->v1->y);
436 quad.v2[VX] = Q_FIX2FLT(seg->v2->x);
437 quad.v2[VY] = Q_FIX2FLT(seg->v2->y);
438 // The original vertex. For dlights.
439 memcpy(origv1, quad.v1, sizeof(origv1));
440 memcpy(origv2, quad.v2, sizeof(origv2));
441 // Make the very small crack-hiding adjustment.
442 dx = quad.v2[VX] - quad.v1[VX];
443 dy = quad.v2[VY] - quad.v1[VY];
444 quad.v2[VX] += dx/seg->len/4;
445 quad.v2[VY] += dy/seg->len/4;
448 // Let's first check which way this seg is facing.
449 if(!SegFacingDir(quad.v1, quad.v2)) return; // The wrong direction?
451 // Calculate the distances.
452 quad.dist[0] = PointDist2D(quad.v1);
453 quad.dist[1] = PointDist2D(quad.v2);
455 // Calculate the lightlevel.
456 quad.light = frontsec->lightlevel;
457 /*if(quad.v1[VX] == quad.v2[VX]) quad.light += 16;
458 if(quad.v1[VY] == quad.v2[VY]) quad.light -= 16;*/
461 // This line is now seen in the map.
462 ldef->flags |= ML_MAPPED;
464 // Some texture coordinates.
465 quad.texoffx = (sid->textureoffset>>FRACBITS)+(seg->offset>>FRACBITS);
466 quad.u.q.len = seg->len;
467 tcyoff = Q_FIX2FLT(sid->rowoffset);
469 // The middle texture, single sided.
470 if(sid->midtexture && !backsec)
472 curtex = OGL_PrepareTexture(sid->midtexture);
473 quad.texoffy = tcyoff;
474 if(ldef->flags & ML_DONTPEGBOTTOM)
475 quad.texoffy += texh-fsh;
477 // Fill in the remaining quad data.
480 quad.u.q.bottom = ffloor;
483 RL_AddQuad(&quad, curtex);
484 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
486 //printf( "Solid segment in sector %p.\n", frontsec);
487 // This is guaranteed to be a solid segment.
488 C_AddViewRelSeg(quad.v1[VX],quad.v1[VY],quad.v2[VX],quad.v2[VY]);
493 if(!backsec || (backsec && (backsec->ceilingheight+(backsec->skyfix<<FRACBITS) <
494 frontsec->ceilingheight+(frontsec->skyfix<<FRACBITS))))// ||
495 //backsec->floorheight == frontsec->ceilingheight)))
497 quad.flags = RQF_SKY_MASK_WALL;
498 quad.top = fceil + frontsec->skyfix;
499 quad.u.q.bottom = fceil;
500 RL_AddQuad(&quad, curtex);
501 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
504 // If there is a back sector we may need upper and lower walls.
505 if(backsec) // A twosided seg?
507 bfloor = FIX2FLT(backsec->floorheight);
508 bceil = FIX2FLT(backsec->ceilingheight);
509 bsh = bceil - bfloor;
510 if(bsh <= 0 || bceil <= ffloor || bfloor >= fceil)
512 //printf( "Solid segment in sector %p (backvol=0).\n", frontsec);
513 // The backsector has no space. This is a solid segment.
514 C_AddViewRelSeg(quad.v1[VX],quad.v1[VY],quad.v2[VX],quad.v2[VY]);
516 if(sid->midtexture) // Quite probably a masked texture.
518 float mceil = (bceil<fceil)?bceil:fceil,
519 mfloor = (bfloor>ffloor)?bfloor:ffloor,
520 msh = mceil - mfloor;
523 curtex = OGL_PrepareTexture(sid->midtexture);
524 // Calculate the texture coordinates. Also restrict
525 // vertical tiling (if masked) by adjusting mceil and mfloor.
526 if(texmask) // A masked texture?
528 quad.flags = RQF_MASKED;
530 // We don't allow vertical tiling.
531 if(ldef->flags & ML_DONTPEGBOTTOM)
534 mceil = mfloor + texh;
539 mfloor = mceil - texh;
542 else // Normal texture.
545 quad.texoffy = tcyoff;
546 if(ldef->flags & ML_DONTPEGBOTTOM) // Lower unpegged. Align bottom.
547 quad.texoffy += texh-msh;
549 // Fill in the remainder of the data.
551 quad.u.q.bottom = mfloor;
554 RL_AddQuad(&quad, curtex);
555 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
559 if(bceil < fceil && !(frontsec->ceilingpic == skyflatnum && backsec->ceilingpic == skyflatnum))
561 float topwh = fceil - bceil;
562 if(sid->toptexture) // A texture present?
564 curtex = OGL_PrepareTexture(sid->toptexture);
565 // Calculate texture coordinates.
566 quad.texoffy = tcyoff;
567 if(!(ldef->flags & ML_DONTPEGTOP))
569 // Normal alignment to bottom.
570 quad.texoffy += texh-topwh;
576 // No texture? Bad thing. You don't deserve texture
577 // coordinates. Take the ceiling texture.
578 curtex = OGL_PrepareFlat(frontsec->ceilingpic);
579 quad.flags = RQF_FLAT | RQF_MISSING_WALL;
582 quad.u.q.bottom = bceil;
585 RL_AddQuad(&quad, curtex);
586 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
589 if(bfloor > ffloor && !(frontsec->floorpic == skyflatnum && backsec->floorpic == skyflatnum))
591 if(sid->bottomtexture) // There is a texture?
593 curtex = OGL_PrepareTexture(sid->bottomtexture);
594 // Calculate texture coordinates.
595 quad.texoffy = tcyoff;
596 if(ldef->flags & ML_DONTPEGBOTTOM)
598 // Lower unpegged. Align with normal middle texture.
599 //quad.texoffy += fsh-texh;
600 quad.texoffy += fceil-bfloor;
606 // No texture? Again!
607 curtex = OGL_PrepareFlat(frontsec->floorpic);
608 quad.flags = RQF_FLAT | RQF_MISSING_WALL;
611 quad.u.q.bottom = ffloor;
614 RL_AddQuad(&quad, curtex);
615 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
620 void R_HandleSectorSpecials(sector_t *sect)
622 int scrollOffset = leveltime>>1 & 63;
624 switch(sect->special)
625 { // Handle scrolling flats
626 case 201: case 202: case 203: // Scroll_North_xxx
627 sect->flatoffy = (63-scrollOffset) << (sect->special-201);
629 case 204: case 205: case 206: // Scroll_East_xxx
630 sect->flatoffx = (63-scrollOffset) << (sect->special-204);
632 case 207: case 208: case 209: // Scroll_South_xxx
633 sect->flatoffy = scrollOffset << (sect->special-207);
635 case 210: case 211: case 212: // Scroll_West_xxx
636 sect->flatoffx = scrollOffset << (sect->special-210);
638 case 213: case 214: case 215: // Scroll_NorthWest_xxx
639 sect->flatoffx = scrollOffset << (sect->special-213);
640 sect->flatoffy = (63-scrollOffset) << (sect->special-213);
642 case 216: case 217: case 218: // Scroll_NorthEast_xxx
643 sect->flatoffx = (63-scrollOffset) << (sect->special-216);
644 sect->flatoffy = (63-scrollOffset) << (sect->special-216);
646 case 219: case 220: case 221: // Scroll_SouthEast_xxx
647 sect->flatoffx = (63-scrollOffset) << (sect->special-219);
648 sect->flatoffy = scrollOffset << (sect->special-219);
650 case 222: case 223: case 224: // Scroll_SouthWest_xxx
651 sect->flatoffx = scrollOffset << (sect->special-222);
652 sect->flatoffy = scrollOffset << (sect->special-222);
655 sect->flatoffx = sect->flatoffy = 0;
662 if (luminousList) free(luminousList);
664 maxLuminous = numLuminous = 0;
667 boolean DL_AddLuminous(mobj_t *thing)
669 if(thing->frame & FF_FULLBRIGHT && !(thing->flags2&MF2_DONTDRAW))
672 spriteframe_t *sprframe;
676 // Only allocate memory when it's needed.
677 if(++numLuminous > maxLuminous)
678 luminousList = realloc(luminousList, sizeof(lumobj_t) * (maxLuminous+=5));
679 lum = luminousList + numLuminous-1;
681 // We need to know how tall the thing currently is.
682 sprdef = &sprites[thing->sprite];
683 sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK ];
685 lump = sprframe->lump[(R_PointToAngle(thing->x, thing->y) - thing->angle + (unsigned)(ANG45/2)*9) >> 29];
687 lump = sprframe->lump[0];
688 // This'll ensure we have up-to-date information.
689 OGL_PrepareSprite(lump);
690 lum->top = FIX2FLT(spritetopoffset[lump]);
691 lum->height = spriteheights[lump];
692 //printf( "%p: t:%.2f h:%.2f\n", thing, lum->top, lum->height);
697 // We want to know which luminous objects are close enough the subsector.
698 void DL_MarkForSubsector(subsector_t *sub)
701 float minx, miny, maxx, maxy; // Subsector bounding box.
703 // First determine the subsector bounding box based on
705 /*maxx = minx = sub->edgeverts[0].x;
706 maxy = miny = sub->edgeverts[0].y;
707 for(i=1; i<sub->numedgeverts; i++)
709 float x = sub->edgeverts[i].x, y = sub->edgeverts[i].y;
710 if(x > maxx) maxx = x;
711 if(x < minx) minx = x;
712 if(y > maxy) maxy = y;
713 if(y < miny) miny = y;
715 // Adjust the bounding box to include the maximum radius of the
716 // dynamic lights (64).
717 maxx += dlMaxRad; minx -= dlMaxRad;
718 maxy += dlMaxRad; miny -= dlMaxRad;*/
720 // Adjust the bounding box to include the maximum radius of the
721 // dynamic lights (64).
722 minx = sub->bbox[0].x - dlMaxRad;
723 miny = sub->bbox[0].y - dlMaxRad;
724 maxx = sub->bbox[1].x + dlMaxRad;
725 maxy = sub->bbox[1].y + dlMaxRad;
726 // Now check all the luminous objects and mark those that
728 for(i=0; i<numLuminous; i++)
730 lumobj_t *lum = luminousList + i;
731 float x = Q_FIX2FLT(lum->thing->x), y = Q_FIX2FLT(lum->thing->y);
732 // By default the luminous object isn't used.
734 // Is inside the bounding box?
735 if(x > minx && y > miny && x < maxx && y < maxy)
740 void R_RenderSubsector(int ssecidx)
742 subsector_t *ssec = subsectors+ssecidx;
743 extern subsector_t *currentssec;
746 sector_t *sect = ssec->sector;
747 float ffloor = FIX2FLT(sect->floorheight);
748 float fceil = FIX2FLT(sect->ceilingheight);
751 if(fceil-ffloor <= 0)
753 return; // Skip this, no volume.
758 if(!C_CheckSubsector(ssec)) return; // This isn't visible.
761 firstsubsector = false;
763 // printf( "*** Rendering subsector %d (sector %p)\n", ssecidx, sect);
767 // Sprites for this sector have to be drawn. This must be done before
768 // the segments of this subsector are added to the clipper. Otherwise
769 // the sprites would get clipped by them, and that wouldn't be right.
773 if(useDynLights) DL_MarkForSubsector(ssec);
776 for(i=0, seg=segs+ssec->firstline; i<ssec->numlines; i++, seg++)
777 R_RenderWallSeg(seg, sect, false);
779 // Is there a polyobj on board?
782 memset(&triangle, 0, sizeof(triangle));
783 triangle.flags = RQF_FLAT | RQF_FLOOR_FACING; // This is a flat floor triangle.
784 triangle.light = sect->lightlevel / 255.0;
785 if(viewz > sect->floorheight) // && vpitch < yfov)
787 // Check for sky... in the floor?
788 if(sect->floorpic == skyflatnum)
790 triangle.flags |= RQF_SKY_MASK;
791 skyhemispheres |= SKYHEMI_LOWER;
793 curtex = OGL_PrepareFlat(sect->floorpic);
794 triangle.texw = texw;
795 triangle.texh = texh;
796 triangle.texoffx = sect->flatoffx;
797 triangle.texoffy = sect->flatoffy;
798 triangle.top = ffloor;
799 // The first vertex is always the first in the whole list.
800 RL_AddFlatQuads(&triangle, curtex, ssec->numedgeverts, ssec->edgeverts, 0);
802 if(useDynLights && sect->floorpic != skyflatnum)
804 triangle.flags |= RQF_LIGHT;
805 triangle.top += .05f; // An adjustment.
806 for(i=0; i<numLuminous; i++)
808 lumobj_t *lum = luminousList + i;
810 if(!lum->use) continue;
812 z = FIX2FLT(lum->thing->z);
813 // Check that we're on the right side.
814 if(z+lum->top < triangle.top) continue; // Under it.
815 // Check that the height difference isn't too big.
816 z += lum->top - lum->height/2; // Center Z.
817 if((hdiff=fabs(triangle.top-z)) > dlMaxRad) continue;
818 triangle.light = 1.5f - 1.5f*hdiff/dlMaxRad;
819 // We can add the light quads.
820 RL_AddFlatQuads(&triangle, (int)lum, ssec->numedgeverts, ssec->origedgeverts, 0);
825 triangle.flags = RQF_FLAT;
826 triangle.light = sect->lightlevel / 255.0;
827 if(viewz < sect->ceilingheight) //&& vpitch > -yfov)
830 if(sect->ceilingpic == skyflatnum)
832 triangle.flags |= RQF_SKY_MASK;
833 skyhemispheres |= SKYHEMI_UPPER;
835 // Don't ask me why this works - DDOI
836 curtex = OGL_PrepareFlat(sect->ceilingpic);
837 triangle.texw = texw;
838 triangle.texh = texh;
839 triangle.texoffx = 0;
840 triangle.texoffy = 0;
841 triangle.top = fceil + sect->skyfix;
842 // The first vertex is always the last in the whole list
843 RL_AddFlatQuads(&triangle, curtex, ssec->numedgeverts, ssec->edgeverts, 1);
846 if(useDynLights && sect->ceilingpic != skyflatnum)
848 triangle.flags |= RQF_LIGHT;
849 triangle.top -= .05f; // An adjustment.
850 for(i=0; i<numLuminous; i++)
852 lumobj_t *lum = luminousList + i;
854 if(!lum->use) continue;
856 z = FIX2FLT(lum->thing->z);
857 // Check that we're on the right side.
858 if(z+lum->top-lum->height > triangle.top) continue; // Under it.
859 // Check that the height difference isn't too big.
860 z += lum->top - lum->height/2; // Center Z.
861 if((hdiff=fabs(triangle.top-z)) > dlMaxRad) continue;
862 triangle.light = 1.5f - 1.5f*hdiff/dlMaxRad;
863 // We can add the light quads.
864 RL_AddFlatQuads(&triangle, (int)lum, ssec->numedgeverts, ssec->origedgeverts, 1);
870 void R_RenderNode(int bspnum)
875 // If the clipper is full we're pretty much done.
877 if(cliphead->start == 0 && cliphead->end == BANG_MAX)
880 if (bspnum & NF_SUBSECTOR)
883 R_RenderSubsector(0);
885 R_RenderSubsector(bspnum&(~NF_SUBSECTOR));
889 bsp = &nodes[bspnum];
892 // decide which side the view point is on
894 side = R_PointOnSide (viewx, viewy, bsp);
896 R_RenderNode (bsp->children[side]); // recursively divide front space
898 /* if(cliphead->start == 0 && cliphead->end == BANG_MAX)
899 return; // We can stop rendering.*/
901 //if (R_CheckBBox (bsp->bbox[side^1])) // possibly divide back space
902 // We can't use that, unfortunately.
903 R_RenderNode (bsp->children[side^1]);
907 void R_RenderMap(void)
912 // This is all the clearing we'll do.
913 glClear(GL_DEPTH_BUFFER_BIT);
915 // Setup the modelview matrix.
916 OGL_ModelViewMatrix();
918 // Let's scroll some floors. This way we have to check them all,
919 // but there's no redundancy. And this really isn't all that expensive.
920 for(i=0; i<numsectors; i++) R_HandleSectorSpecials(sectors+i);
927 RL_ClearLists(); // Clear the lists for new quads.
928 C_ClearRanges(); // Clear the clipper.
929 if(useDynLights) // Maintain luminous objects list.
931 numLuminous = 0; // Clear the luminous object list.
933 // Add all the luminous objects to the list.
934 for(i=0; i<numsectors; i++)
936 sector_t *sec = sectors + i;
938 for(iter=sec->thinglist; iter; iter=iter->snext)
940 //for(k=0; k<bmapheight; k++)
941 // for(i=0; i<bmapwidth; i++)
942 //P_BlockThingsIterator(i, k, DL_AddLuminous);
943 DL_AddLuminous(iter);
947 // Add the backside clipping range, vpitch allowing.
948 if(vpitch <= 90-yfov/2 && vpitch >= -90+yfov/2)
950 float a = fabs(vpitch) / (90-yfov/2);
951 binangle startAngle = (binangle) BANG_45*(1+a);
952 binangle angLen = BANG_180 - startAngle;
953 viewside = (viewangle>>16) + startAngle;
954 C_SafeAddRange(viewside, viewside+angLen);
955 C_SafeAddRange(viewside+angLen, viewside+2*angLen);
956 //C_SafeAddRange(viewside+BANG_135, viewside+2*BANG_135);
958 // The viewside line for the black fog distance calculations.
959 viewsidex = -FIX2FLT(viewsin);
960 viewsidey = FIX2FLT(viewcos);
962 // We don't want subsector clipchecking for the first subsector.
963 //misccount = I_GetPerformanceCount();
964 firstsubsector = true;
965 R_RenderNode(numnodes-1);
966 //misccount = I_GetPerformanceCount()-misccount;
970 // Clipping fragmentation happens when there are holes in the walls.
974 printf("\nTic: %d, Clipnodes are fragmented:\n", gametic);
975 for(ci=cliphead; ci; ci=ci->next)
976 printf( "range %p: %4x => %4x (%d)\n",ci,ci->start,ci->end,ci->used);
977 I_Error("---Fragmented clipper---\n");
981 void R_RenderSprite(vissprite_t *spr)
984 // float off = FIX2FLT(spriteoffset[spr->patch]);
985 float w = FIX2FLT(spritewidth[spr->patch]);
987 float p2w = FindNextPower2((int)w), p2h;
988 float v1[2];//, v2[2];
989 //float sinrv, cosrv;
990 float tcleft, tcright;
995 OGL_SetSprite(spr->patch);
996 sprh = spriteheights[spr->patch];
997 p2h = FindNextPower2(sprh);
999 // v1[VX] = FIX2FLT(spr->gx);
1000 //v1[VY] = FIX2FLT(spr->gy);
1002 // Set the lighting and alpha.
1003 if(spr->mobjflags & MF_SHADOW)
1008 if(spr->lightlevel < 0)
1009 glColor4f(1, 1, 1, alpha);
1012 v1[VX] = Q_FIX2FLT(spr->gx);
1013 v1[VY] = Q_FIX2FLT(spr->gy);
1014 SetVertexColor(spr->lightlevel/255.0, PointDist2D(v1), alpha);
1017 /* thangle = BANG2RAD(bamsAtan2((v1[VY]-vz)*10,(v1[VX]-vx)*10))-PI/2;
1018 sinrv = sin(thangle);
1019 cosrv = cos(thangle);*/
1021 // We must find the correct positioning using the sector floor and ceiling
1022 // heights as an aid.
1023 /*top = FIX2FLT(spr->gzt) + 4 - FIX2FLT(spr->floorclip);
1025 top = FIX2FLT(spr->gzt);
1026 if(sprh < spr->secceil-spr->secfloor) // Sprite fits in, adjustment possible?
1029 if(top > spr->secceil) top = spr->secceil;
1031 if(top-sprh < spr->secfloor)
1032 top = spr->secfloor+sprh;
1034 // Adjust by the floor clip.
1037 /* v1[VX] -= cosrv*off;
1038 v1[VY] -= sinrv*off;
1039 v2[VX] = v1[VX] + cosrv*w;
1040 v2[VY] = v1[VY] + sinrv*w;*/
1042 if(spr->xiscale < 0)
1044 // This is the flipped version.
1050 // No flipping; the normal version.
1055 // Choose the color for the sprite.
1056 /*glColor4f(1, 1, 1, (spr->mobjflags&MF_SHADOW)? .333
1057 : (spr->mobjflags&MF_ALTSHADOW)? .666 : 1);*/
1060 glTexCoord2f(tcleft, 0);
1061 glVertex3f(spr->v1[VX], top, spr->v1[VY]);
1063 glTexCoord2f(tcright, 0);
1064 glVertex3f(spr->v2[VX], top, spr->v2[VY]);
1066 glTexCoord2f(tcright, sprh/p2h);
1067 glVertex3f(spr->v2[VX], bot, spr->v2[VY]);
1069 glTexCoord2f(tcleft, sprh/p2h);
1070 glVertex3f(spr->v1[VX], bot, spr->v1[VY]);
1074 void OGL_DrawPSprite(int x, int y, float scale, int flip, int lump)
1079 OGL_SetSprite(lump);
1080 w = spritewidth[lump]>>FRACBITS;
1081 h = spriteheights[lump];
1082 tcx = NextPower2Ratio(w);
1083 tcy = NextPower2Ratio(h);
1087 glTexCoord2f((flip)? tcx : 0, 0);
1090 glTexCoord2f((flip)? 0 : tcx, 0);
1091 glVertex2f(x+w*scale, y);
1093 glTexCoord2f((flip)? 0 : tcx, tcy);
1094 glVertex2f(x+w*scale, y+h*scale);
1096 glTexCoord2f((flip)? tcx : 0, tcy);
1097 glVertex2f(x, y+h*scale);