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?
59 float vx, vy, vz, vang, vpitch;
61 boolean willRenderSprites = true, freezeRLs = false;
63 lumobj_t *luminousList = 0;
64 int numLuminous = 0, maxLuminous = 0;
65 int dlMaxRad = 64; // Dynamic lights maximum radius.
67 // PRIVATE DATA DEFINITIONS ------------------------------------------------
69 static int viewpw, viewph; // Viewport size.
70 static float nearClip, farClip;
72 static float viewsidex, viewsidey; // For the black fog.
74 static boolean firstsubsector; // No range checking for the first one.
76 // CODE --------------------------------------------------------------------
78 // How far the point is from the viewside plane?
79 float PointDist2D(float c[2])
81 /* (YA-YC)(XB-XA)-(XA-XC)(YB-YA)
82 s = -----------------------------
84 Luckily, L**2 is one. dist = s*L. Even more luckily, L is also one.
86 float dist = (vz-c[VY])*viewsidex - (vx-c[VX])*viewsidey;
87 if(dist < 0) return -dist; // Always return positive.
91 // ---------------------------------------------------
95 OGL_TexInit(); // OpenGL texture manager.
96 bamsInit(); // Binary angle calculations.
98 RL_Init(); // Rendering lists.
101 void OGL_ResetData() // Called before starting a new level.
103 OGL_TexReset(); // Textures are deleted (at least skies need this???).
104 RL_DeleteLists(); // The rendering lists are destroyed.
106 // We'll delete the sky textures. New ones will be generated for each level.
107 //glDeleteTextures(2, skynames);
108 //skynames[0] = skynames[1] = 0;
110 // Ready for new fadeout colors.
111 fadeOut[0].set = fadeOut[1].set = 0;
116 void OGL_InitRenderer() // Initializes the renderer to 2D state.
118 GLfloat fogcol[4] = { .7f, .7f, .7f, 1 };
120 // PC_Init(&clipperclock);
121 // PC_Init(&rlclock);
122 // PC_Init(&miscclock);
128 // Here we configure the OpenGL state and set projection matrix.
130 glDisable(GL_CULL_FACE);
132 glDisable(GL_DEPTH_TEST);
133 glDepthFunc(GL_LESS);
134 glEnable(GL_TEXTURE_2D);
135 //glPolygonMode(GL_FRONT, GL_LINE);
137 // The projection matrix.
138 glMatrixMode(GL_PROJECTION);
140 gluOrtho2D(0,320,200,0);
142 // Initialize the modelview matrix.
143 glMatrixMode(GL_MODELVIEW);
146 // Clear also the texture matrix (I'm not using this, though).
147 glMatrixMode(GL_TEXTURE);
150 // Alpha blending is a go!
152 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
153 glEnable(GL_ALPHA_TEST);
154 glAlphaFunc(GL_GREATER, 0);
156 // Default state for the white fog is off.
159 glFogi(GL_FOG_MODE, GL_LINEAR);
160 glFogi(GL_FOG_END, 3500); // This should be tweaked a bit.
161 glFogfv(GL_FOG_COLOR, fogcol);
163 /*glEnable(GL_POLYGON_SMOOTH);
164 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);*/
166 // Check the performance counter.
170 QueryPerformanceFrequency(&freq);
171 QueryPerformanceCounter((LARGE_INTEGER*)&start);
172 printf( "Performance counter frequency: %I64d counts per second.\n", freq);
173 QueryPerformanceCounter((LARGE_INTEGER*)&end);
174 printf( "(the printing of that took %I64d tics)\n", end-start);
177 // We don't want any hassles with uninitialized names, do we?
178 //skynames[0] = skynames[1] = 0;
181 void OGL_UseWhiteFog(int yes)
185 // White fog is turned on.
189 else if(whitefog && !yes)
191 // White fog must be turned off.
195 // Otherwise we won't do a thing.
198 void OGL_SwitchTo3DState()
200 // extern int setblocks;
202 // Push the 2D state on the stack.
203 glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
204 glMatrixMode(GL_PROJECTION);
206 glMatrixMode(GL_MODELVIEW);
209 // Enable some.. things.
210 glEnable(GL_CULL_FACE);
211 glEnable(GL_DEPTH_TEST);
214 if(viewheight != SCREENHEIGHT)
216 int svx = viewwindowx * screenWidth/320,
217 svy = viewwindowy * screenHeight/200;
218 viewpw = viewwidth * screenWidth/320;
219 viewph = viewheight * screenHeight/200 + 1;
220 glViewport(svx, screenHeight-svy-viewph, viewpw, viewph);
224 viewpw = screenWidth;
225 viewph = screenHeight;
228 // The 3D projection matrix.
229 OGL_ProjectionMatrix();
232 void OGL_Restore2DState(int step)
236 extern int screenblocks;
237 glMatrixMode(GL_PROJECTION);
239 gluOrtho2D(0, 320, (screenblocks<11)?161:200, 0);
240 glMatrixMode(GL_MODELVIEW);
243 // Retrieve the old state.
246 glMatrixMode(GL_PROJECTION);
248 glMatrixMode(GL_MODELVIEW);
254 static void OGL_ProjectionMatrix()
256 // We're assuming pixels are squares... well, they are nowadays.
257 float aspect = (float)viewpw/(float)viewph;
258 //float aspect = 1.0;
259 glMatrixMode(GL_PROJECTION);
261 gluPerspective(yfov=90.0/aspect, aspect, nearClip, farClip);
262 // We'd like to have a left-handed coordinate system.
266 static void OGL_ModelViewMatrix()
271 vang = viewangle / (float)ANGLE_MAX * 360 - 90;
273 glMatrixMode(GL_MODELVIEW);
275 glRotatef(vpitch=viewpitch * 85.0/110.0, 1, 0, 0);
276 glRotatef(vang, 0, 1, 0);
277 glScalef(1, 1.2f, 1); // This is the aspect correction.
278 glTranslatef(-vx,-vy,-vz);
282 // *VERY* similar to SegFacingDir(). Well, this is actually the same
283 // function, only a more general version.
284 static int SegFacingPoint(float v1[2], float v2[2], float p[2])
286 float nx = v1[VY]-v2[VY], ny = v2[VX]-v1[VX];
287 float pvx = v1[VX]-p[VX], pvy = v1[VY]-p[VY];
289 if(nx*pvx+ny*pvy > 0) return 1; // Facing front.
290 return 0; // Facing away.
293 static void projectVector(float a[2], float b[2], float *a_on_b)
296 float factor = (a[0]*b[0] + a[1]*b[1]) / (b[0]*b[0] + b[1]*b[1]);
297 for(c=0; c<2; c++) a_on_b[c] = factor * b[c];
300 // Create dynamic light quads, if necessary.
301 static void DL_ProcessWall(rendquad_t *quad, float v1[2], float v2[2])
306 float vecLight[2]; // Vector from v1 to light point.
307 float uvecWall[2], uvecWallNormal[2]; // Unit vectors.
309 float dist; // Distance between light source and wall.
311 // We can't handle masked walls. The alpha...
312 if(quad->flags & RQF_MASKED) return;
314 for(i=0; i<numLuminous; i++)
316 lumobj_t *lum = luminousList + i;
317 // If the light is not in use, we skip it.
318 if(!lum->use) continue;
319 // First we must check orientation. Backfaces aren't lighted, naturally.
320 pntLight[VX] = FIX2FLT(lum->thing->x);
321 pntLight[VY] = FIX2FLT(lum->thing->y);
322 if(!SegFacingPoint(v1, v2, pntLight)) continue;
323 // Make a copy of the original.
324 memcpy(&dlq, quad, sizeof(dlq));
325 // Copy the given end points.
326 memcpy(dlq.v1, v1, sizeof(v1));
327 memcpy(dlq.v2, v2, sizeof(v2));
328 dlq.flags |= RQF_LIGHT; // This is a light texture.
329 dlq.texw = dlq.texh = dlMaxRad*2;
332 uvecWall[c] = (quad->v2[c] - quad->v1[c]) / quad->u.q.len;
334 uvecWallNormal[VX] = uvecWall[VY];
335 uvecWallNormal[VY] = -uvecWall[VX];
336 // The relative position of the light source.
337 for(c=0; c<2; c++) vecLight[c] = pntLight[c] - quad->v1[c];
338 // The distance vector. VecLight projected on the normal vector.
339 projectVector(vecLight, uvecWallNormal, vecDist);
340 // The accurate distance from the wall to the light.
341 dist = sqrt(vecDist[0]*vecDist[0] + vecDist[1]*vecDist[1]);
342 if(dist > dlMaxRad) continue; // Too far away.
343 // Now we can calculate the intensity of the light.
344 dlq.light = 1.5f - 1.5f*dist/dlMaxRad;
345 // Do a scalar projection for the offset.
346 dlq.texoffx = vecLight[0]*uvecWall[0] + vecLight[1]*uvecWall[1] - dlMaxRad;
347 // There is no need to draw the *whole* wall always. Adjust the start
348 // and end points so that only a relevant portion is included.
349 if(dlq.texoffx > dlq.u.q.len) continue; // Doesn't fit on the wall.
350 if(dlq.texoffx < -dlq.texw) continue; // Ditto, but in the other direction.
353 for(c=0; c<2; c++) dlq.v1[c] += dlq.texoffx * uvecWall[c];
354 if(dlq.texoffx+dlq.texw <= dlq.u.q.len) // Fits completely?
356 for(c=0; c<2; c++) dlq.v2[c] = dlq.v1[c] + dlq.texw*uvecWall[c];
357 dlq.u.q.len = dlq.texw;
360 dlq.u.q.len -= dlq.texoffx;
363 else // It goes off to the left.
365 if(dlq.texoffx+dlq.texw <= dlq.u.q.len) // Fits completely?
367 for(c=0; c<2; c++) dlq.v2[c] = dlq.v1[c] + (dlq.texw+dlq.texoffx)*uvecWall[c];
368 dlq.u.q.len = dlq.texw + dlq.texoffx;
371 // The vertical offset is easy to determine.
372 dlq.texoffy = FIX2FLT(lum->thing->z)+lum->top-lum->height/2 + dlMaxRad - dlq.top;
373 if(dlq.texoffy < -dlq.top+dlq.u.q.bottom) continue;
374 if(dlq.texoffy > dlq.texh) continue;
375 if(dlq.top+dlq.texoffy-dlq.texh >= dlq.u.q.bottom) // Fits completely?
376 dlq.u.q.bottom = dlq.top+dlq.texoffy-dlq.texh;
379 dlq.top += dlq.texoffy;
382 // As a final touch, move the light quad a bit away from the wall
383 // to avoid z-fighting.
386 dlq.v1[c] += .2 * uvecWallNormal[c];
387 dlq.v2[c] += .2 * uvecWallNormal[c];
389 // Now we can give the new quad to the rendering engine.
394 static int SegFacingDir(float v1[2], float v2[2])
396 float nx = v1[VY]-v2[VY], ny = v2[VX]-v1[VX];
397 float vvx = v1[VX]-vx, vvy = v1[VY]-vz;
400 if(nx*vvx+ny*vvy > 0) return 1; // Facing front.
401 return 0; // Facing away.
404 // The sector height should've been checked by now.
405 void R_RenderWallSeg(seg_t *seg, sector_t *frontsec, boolean accurate)
407 sector_t *backsec = seg->backsector;
408 side_t *sid = seg->sidedef;
409 line_t *ldef = seg->linedef;
410 float ffloor = FIX2FLT(frontsec->floorheight);
411 float fceil = FIX2FLT(frontsec->ceilingheight);
412 float bfloor, bceil, fsh = fceil-ffloor, bsh;
415 float origv1[2], origv2[2]; // The original end points, for dynlights.
417 memset(&quad, 0, sizeof(quad)); // Clear the quad.
419 // Get the start and end points. Full floating point conversion is
420 // actually only necessary for polyobjs.
423 quad.v1[VX] = FIX2FLT(seg->v1->x);
424 quad.v1[VY] = FIX2FLT(seg->v1->y);
425 quad.v2[VX] = FIX2FLT(seg->v2->x);
426 quad.v2[VY] = FIX2FLT(seg->v2->y);
427 // These are the original vertices, copy them.
428 memcpy(origv1, quad.v1, sizeof(origv1));
429 memcpy(origv2, quad.v2, sizeof(origv2));
435 quad.v1[VX] = Q_FIX2FLT(seg->v1->x);
436 quad.v1[VY] = Q_FIX2FLT(seg->v1->y);
437 quad.v2[VX] = Q_FIX2FLT(seg->v2->x);
438 quad.v2[VY] = Q_FIX2FLT(seg->v2->y);
439 // The original vertex. For dlights.
440 memcpy(origv1, quad.v1, sizeof(origv1));
441 memcpy(origv2, quad.v2, sizeof(origv2));
442 // Make the very small crack-hiding adjustment.
443 dx = quad.v2[VX] - quad.v1[VX];
444 dy = quad.v2[VY] - quad.v1[VY];
445 quad.v2[VX] += dx/seg->len/4;
446 quad.v2[VY] += dy/seg->len/4;
449 // Let's first check which way this seg is facing.
450 if(!SegFacingDir(quad.v1, quad.v2)) return; // The wrong direction?
452 // Calculate the distances.
453 quad.dist[0] = PointDist2D(quad.v1);
454 quad.dist[1] = PointDist2D(quad.v2);
456 // Calculate the lightlevel.
457 quad.light = frontsec->lightlevel;
458 /*if(quad.v1[VX] == quad.v2[VX]) quad.light += 16;
459 if(quad.v1[VY] == quad.v2[VY]) quad.light -= 16;*/
462 // This line is now seen in the map.
463 ldef->flags |= ML_MAPPED;
465 // Some texture coordinates.
466 quad.texoffx = (sid->textureoffset>>FRACBITS)+(seg->offset>>FRACBITS);
467 quad.u.q.len = seg->len;
468 tcyoff = Q_FIX2FLT(sid->rowoffset);
470 // The middle texture, single sided.
471 if(sid->midtexture && !backsec)
473 curtex = OGL_PrepareTexture(sid->midtexture);
474 quad.texoffy = tcyoff;
475 if(ldef->flags & ML_DONTPEGBOTTOM)
476 quad.texoffy += texh-fsh;
478 // Fill in the remaining quad data.
481 quad.u.q.bottom = ffloor;
484 RL_AddQuad(&quad, curtex);
485 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
487 //printf( "Solid segment in sector %p.\n", frontsec);
488 // This is guaranteed to be a solid segment.
489 C_AddViewRelSeg(quad.v1[VX],quad.v1[VY],quad.v2[VX],quad.v2[VY]);
494 if(!backsec || (backsec && (backsec->ceilingheight+(backsec->skyfix<<FRACBITS) <
495 frontsec->ceilingheight+(frontsec->skyfix<<FRACBITS))))// ||
496 //backsec->floorheight == frontsec->ceilingheight)))
498 quad.flags = RQF_SKY_MASK_WALL;
499 quad.top = fceil + frontsec->skyfix;
500 quad.u.q.bottom = fceil;
501 RL_AddQuad(&quad, curtex);
502 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
505 // If there is a back sector we may need upper and lower walls.
506 if(backsec) // A twosided seg?
508 bfloor = FIX2FLT(backsec->floorheight);
509 bceil = FIX2FLT(backsec->ceilingheight);
510 bsh = bceil - bfloor;
511 if(bsh <= 0 || bceil <= ffloor || bfloor >= fceil)
513 //printf( "Solid segment in sector %p (backvol=0).\n", frontsec);
514 // The backsector has no space. This is a solid segment.
515 C_AddViewRelSeg(quad.v1[VX],quad.v1[VY],quad.v2[VX],quad.v2[VY]);
517 if(sid->midtexture) // Quite probably a masked texture.
519 float mceil = (bceil<fceil)?bceil:fceil,
520 mfloor = (bfloor>ffloor)?bfloor:ffloor,
521 msh = mceil - mfloor;
524 curtex = OGL_PrepareTexture(sid->midtexture);
525 // Calculate the texture coordinates. Also restrict
526 // vertical tiling (if masked) by adjusting mceil and mfloor.
527 if(texmask) // A masked texture?
529 quad.flags = RQF_MASKED;
531 // We don't allow vertical tiling.
532 if(ldef->flags & ML_DONTPEGBOTTOM)
535 mceil = mfloor + texh;
540 mfloor = mceil - texh;
543 else // Normal texture.
546 quad.texoffy = tcyoff;
547 if(ldef->flags & ML_DONTPEGBOTTOM) // Lower unpegged. Align bottom.
548 quad.texoffy += texh-msh;
550 // Fill in the remainder of the data.
552 quad.u.q.bottom = mfloor;
555 RL_AddQuad(&quad, curtex);
556 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
560 if(bceil < fceil && !(frontsec->ceilingpic == skyflatnum && backsec->ceilingpic == skyflatnum))
562 float topwh = fceil - bceil;
563 if(sid->toptexture) // A texture present?
565 curtex = OGL_PrepareTexture(sid->toptexture);
566 // Calculate texture coordinates.
567 quad.texoffy = tcyoff;
568 if(!(ldef->flags & ML_DONTPEGTOP))
570 // Normal alignment to bottom.
571 quad.texoffy += texh-topwh;
577 // No texture? Bad thing. You don't deserve texture
578 // coordinates. Take the ceiling texture.
579 curtex = OGL_PrepareFlat(frontsec->ceilingpic);
580 quad.flags = RQF_FLAT | RQF_MISSING_WALL;
583 quad.u.q.bottom = bceil;
586 RL_AddQuad(&quad, curtex);
587 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
590 if(bfloor > ffloor && !(frontsec->floorpic == skyflatnum && backsec->floorpic == skyflatnum))
592 if(sid->bottomtexture) // There is a texture?
594 curtex = OGL_PrepareTexture(sid->bottomtexture);
595 // Calculate texture coordinates.
596 quad.texoffy = tcyoff;
597 if(ldef->flags & ML_DONTPEGBOTTOM)
599 // Lower unpegged. Align with normal middle texture.
600 //quad.texoffy += fsh-texh;
601 quad.texoffy += fceil-bfloor;
607 // No texture? Again!
608 curtex = OGL_PrepareFlat(frontsec->floorpic);
609 quad.flags = RQF_FLAT | RQF_MISSING_WALL;
612 quad.u.q.bottom = ffloor;
615 RL_AddQuad(&quad, curtex);
616 if(useDynLights) DL_ProcessWall(&quad, origv1, origv2);
621 void R_HandleSectorSpecials(sector_t *sect)
623 int scrollOffset = leveltime>>1 & 63;
625 switch(sect->special)
626 { // Handle scrolling flats
627 case 201: case 202: case 203: // Scroll_North_xxx
628 sect->flatoffy = (63-scrollOffset) << (sect->special-201);
630 case 204: case 205: case 206: // Scroll_East_xxx
631 sect->flatoffx = (63-scrollOffset) << (sect->special-204);
633 case 207: case 208: case 209: // Scroll_South_xxx
634 sect->flatoffy = scrollOffset << (sect->special-207);
636 case 210: case 211: case 212: // Scroll_West_xxx
637 sect->flatoffx = scrollOffset << (sect->special-210);
639 case 213: case 214: case 215: // Scroll_NorthWest_xxx
640 sect->flatoffx = scrollOffset << (sect->special-213);
641 sect->flatoffy = (63-scrollOffset) << (sect->special-213);
643 case 216: case 217: case 218: // Scroll_NorthEast_xxx
644 sect->flatoffx = (63-scrollOffset) << (sect->special-216);
645 sect->flatoffy = (63-scrollOffset) << (sect->special-216);
647 case 219: case 220: case 221: // Scroll_SouthEast_xxx
648 sect->flatoffx = (63-scrollOffset) << (sect->special-219);
649 sect->flatoffy = scrollOffset << (sect->special-219);
651 case 222: case 223: case 224: // Scroll_SouthWest_xxx
652 sect->flatoffx = scrollOffset << (sect->special-222);
653 sect->flatoffy = scrollOffset << (sect->special-222);
656 sect->flatoffx = sect->flatoffy = 0;
665 maxLuminous = numLuminous = 0;
668 boolean DL_AddLuminous(mobj_t *thing)
670 if(thing->frame & FF_FULLBRIGHT && !(thing->flags2&MF2_DONTDRAW))
673 spriteframe_t *sprframe;
677 // Only allocate memory when it's needed.
678 if(++numLuminous > maxLuminous)
679 luminousList = realloc(luminousList, sizeof(lumobj_t) * (maxLuminous+=5));
680 lum = luminousList + numLuminous-1;
682 // We need to know how tall the thing currently is.
683 sprdef = &sprites[thing->sprite];
684 sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK ];
686 lump = sprframe->lump[(R_PointToAngle(thing->x, thing->y) - thing->angle + (unsigned)(ANG45/2)*9) >> 29];
688 lump = sprframe->lump[0];
689 // This'll ensure we have up-to-date information.
690 OGL_PrepareSprite(lump);
691 lum->top = FIX2FLT(spritetopoffset[lump] - lum->thing->floorclip);
692 lum->height = spriteheights[lump];
693 //printf( "%p: t:%.2f h:%.2f\n", thing, lum->top, lum->height);
698 // We want to know which luminous objects are close enough the subsector.
699 void DL_MarkForSubsector(subsector_t *sub)
702 float minx, miny, maxx, maxy; // Subsector bounding box.
704 // First determine the subsector bounding box based on
706 /*maxx = minx = sub->edgeverts[0].x;
707 maxy = miny = sub->edgeverts[0].y;
708 for(i=1; i<sub->numedgeverts; i++)
710 float x = sub->edgeverts[i].x, y = sub->edgeverts[i].y;
711 if(x > maxx) maxx = x;
712 if(x < minx) minx = x;
713 if(y > maxy) maxy = y;
714 if(y < miny) miny = y;
716 // Adjust the bounding box to include the maximum radius of the
717 // dynamic lights (64).
718 maxx += dlMaxRad; minx -= dlMaxRad;
719 maxy += dlMaxRad; miny -= dlMaxRad;*/
721 // Adjust the bounding box to include the maximum radius of the
722 // dynamic lights (64).
723 minx = sub->bbox[0].x - dlMaxRad;
724 miny = sub->bbox[0].y - dlMaxRad;
725 maxx = sub->bbox[1].x + dlMaxRad;
726 maxy = sub->bbox[1].y + dlMaxRad;
727 // Now check all the luminous objects and mark those that
729 for(i=0; i<numLuminous; i++)
731 lumobj_t *lum = luminousList + i;
732 float x = Q_FIX2FLT(lum->thing->x), y = Q_FIX2FLT(lum->thing->y);
733 // By default the luminous object isn't used.
735 // Is inside the bounding box?
736 if(x > minx && y > miny && x < maxx && y < maxy)
741 void R_RenderSubsector(int ssecidx)
743 subsector_t *ssec = subsectors+ssecidx;
744 extern subsector_t *currentssec;
747 sector_t *sect = ssec->sector;
748 float ffloor = FIX2FLT(sect->floorheight);
749 float fceil = FIX2FLT(sect->ceilingheight);
752 if(fceil-ffloor <= 0)
754 return; // Skip this, no volume.
759 if(!C_CheckSubsector(ssec)) return; // This isn't visible.
762 firstsubsector = false;
764 // printf( "*** Rendering subsector %d (sector %p)\n", ssecidx, sect);
768 // Sprites for this sector have to be drawn. This must be done before
769 // the segments of this subsector are added to the clipper. Otherwise
770 // the sprites would get clipped by them, and that wouldn't be right.
774 if(useDynLights) DL_MarkForSubsector(ssec);
777 for(i=0, seg=segs+ssec->firstline; i<ssec->numlines; i++, seg++)
778 R_RenderWallSeg(seg, sect, false);
780 // Is there a polyobj on board?
782 for(i=0; i<ssec->poly->numsegs; i++)
783 R_RenderWallSeg(ssec->poly->segs[i], sect, true);
786 memset(&triangle, 0, sizeof(triangle));
787 triangle.flags = RQF_FLAT | RQF_FLOOR_FACING; // This is a flat floor triangle.
788 triangle.light = sect->lightlevel / 255.0;
789 if(viewz > sect->floorheight) // && vpitch < yfov)
791 // Check for sky... in the floor?
792 if(sect->floorpic == skyflatnum)
794 triangle.flags |= RQF_SKY_MASK;
795 skyhemispheres |= SKYHEMI_LOWER;
796 if(sect->special == 200) special200 = true;
798 curtex = OGL_PrepareFlat(sect->floorpic);
799 triangle.texw = texw;
800 triangle.texh = texh;
801 triangle.texoffx = sect->flatoffx;
802 triangle.texoffy = sect->flatoffy;
803 triangle.top = ffloor;
804 // The first vertex is always the first in the whole list.
805 RL_AddFlatQuads(&triangle, curtex, ssec->numedgeverts, ssec->edgeverts, 0);
807 if(useDynLights && sect->floorpic != skyflatnum)
809 triangle.flags |= RQF_LIGHT;
810 triangle.top += .05f; // An adjustment.
811 for(i=0; i<numLuminous; i++)
813 lumobj_t *lum = luminousList + i;
815 if(!lum->use) continue;
817 z = FIX2FLT(lum->thing->z);
818 // Check that we're on the right side.
819 if(z+lum->top < triangle.top) continue; // Under it.
820 // Check that the height difference isn't too big.
821 z += lum->top - lum->height/2; // Center Z.
822 if((hdiff=fabs(triangle.top-z)) > dlMaxRad) continue;
823 triangle.light = 1.5f - 1.5f*hdiff/dlMaxRad;
824 // We can add the light quads.
825 RL_AddFlatQuads(&triangle, (int)lum, ssec->numedgeverts, ssec->origedgeverts, 0);
830 triangle.flags = RQF_FLAT;
831 triangle.light = sect->lightlevel / 255.0;
832 if(viewz < sect->ceilingheight) //&& vpitch > -yfov)
835 if(sect->ceilingpic == skyflatnum)
837 triangle.flags |= RQF_SKY_MASK;
838 skyhemispheres |= SKYHEMI_UPPER;
839 if(sect->special == 200) special200 = true;
841 curtex = OGL_PrepareFlat(sect->ceilingpic);
842 triangle.texw = texw;
843 triangle.texh = texh;
844 triangle.texoffx = 0;
845 triangle.texoffy = 0;
846 triangle.top = fceil + sect->skyfix;
847 // The first vertex is always the last in the whole list.
848 RL_AddFlatQuads(&triangle, curtex, ssec->numedgeverts, ssec->edgeverts, 1);
850 if(useDynLights && sect->ceilingpic != skyflatnum)
852 triangle.flags |= RQF_LIGHT;
853 triangle.top -= .05f; // An adjustment.
854 for(i=0; i<numLuminous; i++)
856 lumobj_t *lum = luminousList + i;
858 if(!lum->use) continue;
860 z = FIX2FLT(lum->thing->z);
861 // Check that we're on the right side.
862 if(z+lum->top-lum->height > triangle.top) continue; // Under it.
863 // Check that the height difference isn't too big.
864 z += lum->top - lum->height/2; // Center Z.
865 if((hdiff=fabs(triangle.top-z)) > dlMaxRad) continue;
866 triangle.light = 1.5f - 1.5f*hdiff/dlMaxRad;
867 // We can add the light quads.
868 RL_AddFlatQuads(&triangle, (int)lum, ssec->numedgeverts, ssec->origedgeverts, 1);
874 void R_RenderNode(int bspnum)
879 // If the clipper is full we're pretty much done.
881 if(cliphead->start == 0 && cliphead->end == BANG_MAX)
884 if (bspnum & NF_SUBSECTOR)
887 R_RenderSubsector(0);
889 R_RenderSubsector(bspnum&(~NF_SUBSECTOR));
893 bsp = &nodes[bspnum];
896 // decide which side the view point is on
898 side = R_PointOnSide (viewx, viewy, bsp);
900 R_RenderNode (bsp->children[side]); // recursively divide front space
902 /* if(cliphead->start == 0 && cliphead->end == BANG_MAX)
903 return; // We can stop rendering.*/
905 //if (R_CheckBBox (bsp->bbox[side^1])) // possibly divide back space
906 // We can't use that, unfortunately.
907 R_RenderNode (bsp->children[side^1]);
916 // This is all the clearing we'll do.
917 glClear(GL_DEPTH_BUFFER_BIT);
919 // Setup the modelview matrix.
920 OGL_ModelViewMatrix();
922 // Let's scroll some floors. This way we have to check them all,
923 // but there's no redundancy. And this really isn't all that expensive.
924 for(i=0; i<numsectors; i++) R_HandleSectorSpecials(sectors+i);
931 RL_ClearLists(); // Clear the lists for new quads.
932 C_ClearRanges(); // Clear the clipper.
933 if(useDynLights) // Maintain luminous objects list.
935 numLuminous = 0; // Clear the luminous object list.
937 // Add all the luminous objects to the list.
938 for(i=0; i<numsectors; i++)
940 sector_t *sec = sectors + i;
942 for(iter=sec->thinglist; iter; iter=iter->snext)
944 //for(k=0; k<bmapheight; k++)
945 // for(i=0; i<bmapwidth; i++)
946 //P_BlockThingsIterator(i, k, DL_AddLuminous);
947 DL_AddLuminous(iter);
951 // Add the backside clipping range, vpitch allowing.
952 if(vpitch <= 90-yfov/2 && vpitch >= -90+yfov/2)
954 float a = fabs(vpitch) / (90-yfov/2);
955 binangle startAngle = (binangle) BANG_45*(1+a);
956 binangle angLen = BANG_180 - startAngle;
957 viewside = (viewangle>>16) + startAngle;
958 C_SafeAddRange(viewside, viewside+angLen);
959 C_SafeAddRange(viewside+angLen, viewside+2*angLen);
960 //C_SafeAddRange(viewside+BANG_135, viewside+2*BANG_135);
962 // The viewside line for the black fog distance calculations.
963 viewsidex = -FIX2FLT(viewsin);
964 viewsidey = FIX2FLT(viewcos);
966 // We don't want subsector clipchecking for the first subsector.
967 //misccount = I_GetPerformanceCount();
968 firstsubsector = true;
970 R_RenderNode(numnodes-1);
971 //misccount = I_GetPerformanceCount()-misccount;
975 // Clipping fragmentation happens when there are holes in the walls.
979 printf("\nTic: %d, Clipnodes are fragmented:\n", gametic);
980 for(ci=cliphead; ci; ci=ci->next)
981 printf( "range %p: %4x => %4x (%d)\n",ci,ci->start,ci->end,ci->used);
982 I_Error("---Fragmented clipper---\n");
986 void R_RenderSprite(vissprite_t *spr)
989 // float off = FIX2FLT(spriteoffset[spr->patch]);
990 float w = FIX2FLT(spritewidth[spr->patch]);
992 float p2w = FindNextPower2((int)w), p2h;
993 float v1[2];//, v2[2];
994 //float sinrv, cosrv;
995 float tcleft, tcright;
1000 OGL_SetSprite(spr->patch);
1001 sprh = spriteheights[spr->patch];
1002 p2h = FindNextPower2(sprh);
1004 // v1[VX] = FIX2FLT(spr->gx);
1005 //v1[VY] = FIX2FLT(spr->gy);
1007 // Set the lighting and alpha.
1008 if(spr->mobjflags & MF_SHADOW)
1010 else if(spr->mobjflags & MF_ALTSHADOW)
1015 if(spr->lightlevel < 0)
1016 glColor4f(1, 1, 1, alpha);
1019 v1[VX] = Q_FIX2FLT(spr->gx);
1020 v1[VY] = Q_FIX2FLT(spr->gy);
1021 SetVertexColor(spr->lightlevel/255.0, PointDist2D(v1), alpha);
1024 /* thangle = BANG2RAD(bamsAtan2((v1[VY]-vz)*10,(v1[VX]-vx)*10))-PI/2;
1025 sinrv = sin(thangle);
1026 cosrv = cos(thangle);*/
1028 // We must find the correct positioning using the sector floor and ceiling
1029 // heights as an aid.
1030 /*top = FIX2FLT(spr->gzt) + 4 - FIX2FLT(spr->floorclip);
1032 top = FIX2FLT(spr->gzt);
1033 if(sprh < spr->secceil-spr->secfloor) // Sprite fits in, adjustment possible?
1036 if(top > spr->secceil) top = spr->secceil;
1038 if(top-sprh < spr->secfloor)
1039 top = spr->secfloor+sprh;
1041 // Adjust by the floor clip.
1042 top -= FIX2FLT(spr->floorclip);
1045 /* v1[VX] -= cosrv*off;
1046 v1[VY] -= sinrv*off;
1047 v2[VX] = v1[VX] + cosrv*w;
1048 v2[VY] = v1[VY] + sinrv*w;*/
1050 if(spr->xiscale < 0)
1052 // This is the flipped version.
1058 // No flipping; the normal version.
1063 // Choose the color for the sprite.
1064 /*glColor4f(1, 1, 1, (spr->mobjflags&MF_SHADOW)? .333
1065 : (spr->mobjflags&MF_ALTSHADOW)? .666 : 1);*/
1068 glTexCoord2f(tcleft, 0);
1069 glVertex3f(spr->v1[VX], top, spr->v1[VY]);
1071 glTexCoord2f(tcright, 0);
1072 glVertex3f(spr->v2[VX], top, spr->v2[VY]);
1074 glTexCoord2f(tcright, sprh/p2h);
1075 glVertex3f(spr->v2[VX], bot, spr->v2[VY]);
1077 glTexCoord2f(tcleft, sprh/p2h);
1078 glVertex3f(spr->v1[VX], bot, spr->v1[VY]);
1082 void OGL_DrawPSprite(int x, int y, float scale, int flip, int lump)
1087 OGL_SetSprite(lump);
1088 w = spritewidth[lump]>>FRACBITS;
1089 h = spriteheights[lump];
1090 tcx = NextPower2Ratio(w);
1091 tcy = NextPower2Ratio(h);
1095 glTexCoord2f((flip)? tcx : 0, 0);
1098 glTexCoord2f((flip)? 0 : tcx, 0);
1099 glVertex2f(x+w*scale, y);
1101 glTexCoord2f((flip)? 0 : tcx, tcy);
1102 glVertex2f(x+w*scale, y+h*scale);
1104 glTexCoord2f((flip)? tcx : 0, tcy);
1105 glVertex2f(x, y+h*scale);