2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 alight_t r_viewlighting
= {128, 192, viewlightvec
};
31 int r_numallocatededges
;
33 qboolean r_drawculledpolys
;
34 qboolean r_worldpolysbacktofront
;
35 qboolean r_recursiveaffinetriangles
= true;
37 float r_aliasuvscale
= 1.0;
41 qboolean r_dowarp
, r_dowarpold
, r_viewchanged
;
44 btofpoly_t
*pbtofpolys
;
45 mvertex_t
*r_pcurrentvertbase
;
48 int r_maxsurfsseen
, r_maxedgesseen
, r_cnumsurfs
;
49 qboolean r_surfsonstack
;
56 qboolean r_fov_greater_than_90
;
63 vec3_t vright
, base_vright
;
70 float xcenter
, ycenter
;
72 float xscaleinv
, yscaleinv
;
73 float xscaleshrink
, yscaleshrink
;
74 float aliasxscale
, aliasyscale
, aliasxcenter
, aliasycenter
;
80 float verticalFieldOfView
;
81 float xOrigin
, yOrigin
;
83 mplane_t screenedge
[4];
88 int r_framecount
= 1; // so frame counts initialized to 0 don't match
95 #define VIEWMODNAME_LENGTH 256
96 char viewmodname
[VIEWMODNAME_LENGTH
+1];
99 int *pfrustum_indexes
[4];
100 int r_frustum_indexes
[4*6];
102 int reinit_surfcache
= 1; // if 1, surface cache is currently empty and
103 // must be reinitialized for current cache size
105 mleaf_t
*r_viewleaf
, *r_oldviewleaf
;
107 texture_t
*r_notexture_mip
;
109 float r_aliastransition
, r_resfudge
;
111 int d_lightstylevalue
[256]; // 8.8 fraction of base light value
113 float dp_time1
, dp_time2
, db_time1
, db_time2
, rw_time1
, rw_time2
;
114 float se_time1
, se_time2
, de_time1
, de_time2
, dv_time1
, dv_time2
;
116 void R_MarkLeaves (void);
118 cvar_t r_draworder
= {"r_draworder","0"};
119 cvar_t r_speeds
= {"r_speeds","0"};
120 cvar_t r_timegraph
= {"r_timegraph","0"};
121 cvar_t r_graphheight
= {"r_graphheight","10"};
122 cvar_t r_clearcolor
= {"r_clearcolor","2"};
123 cvar_t r_waterwarp
= {"r_waterwarp","1"};
124 cvar_t r_fullbright
= {"r_fullbright","0"};
125 cvar_t r_drawentities
= {"r_drawentities","1"};
126 cvar_t r_drawviewmodel
= {"r_drawviewmodel","1"};
127 cvar_t r_aliasstats
= {"r_polymodelstats","0"};
128 cvar_t r_dspeeds
= {"r_dspeeds","0"};
129 cvar_t r_drawflat
= {"r_drawflat", "0"};
130 cvar_t r_ambient
= {"r_ambient", "0"};
131 cvar_t r_reportsurfout
= {"r_reportsurfout", "0"};
132 cvar_t r_maxsurfs
= {"r_maxsurfs", "0"};
133 cvar_t r_numsurfs
= {"r_numsurfs", "0"};
134 cvar_t r_reportedgeout
= {"r_reportedgeout", "0"};
135 cvar_t r_maxedges
= {"r_maxedges", "0"};
136 cvar_t r_numedges
= {"r_numedges", "0"};
137 cvar_t r_aliastransbase
= {"r_aliastransbase", "200"};
138 cvar_t r_aliastransadj
= {"r_aliastransadj", "100"};
140 extern cvar_t scr_fov
;
142 void CreatePassages (void);
143 void SetVisibilityByPassages (void);
150 void R_InitTextures (void)
155 // create a simple checkerboard texture for the default
156 r_notexture_mip
= Hunk_AllocName (sizeof(texture_t
) + 16*16+8*8+4*4+2*2, "notexture");
158 r_notexture_mip
->width
= r_notexture_mip
->height
= 16;
159 r_notexture_mip
->offsets
[0] = sizeof(texture_t
);
160 r_notexture_mip
->offsets
[1] = r_notexture_mip
->offsets
[0] + 16*16;
161 r_notexture_mip
->offsets
[2] = r_notexture_mip
->offsets
[1] + 8*8;
162 r_notexture_mip
->offsets
[3] = r_notexture_mip
->offsets
[2] + 4*4;
164 for (m
=0 ; m
<4 ; m
++)
166 dest
= (byte
*)r_notexture_mip
+ r_notexture_mip
->offsets
[m
];
167 for (y
=0 ; y
< (16>>m
) ; y
++)
168 for (x
=0 ; x
< (16>>m
) ; x
++)
170 if ( (y
< (8>>m
) ) ^ (x
< (8>>m
) ) )
187 // get stack position so we can guess if we are going to overflow
188 r_stack_start
= (byte
*)&dummy
;
192 Cmd_AddCommand ("timerefresh", R_TimeRefresh_f
);
193 Cmd_AddCommand ("pointfile", R_ReadPointFile_f
);
195 Cvar_RegisterVariable (&r_draworder
);
196 Cvar_RegisterVariable (&r_speeds
);
197 Cvar_RegisterVariable (&r_timegraph
);
198 Cvar_RegisterVariable (&r_graphheight
);
199 Cvar_RegisterVariable (&r_drawflat
);
200 Cvar_RegisterVariable (&r_ambient
);
201 Cvar_RegisterVariable (&r_clearcolor
);
202 Cvar_RegisterVariable (&r_waterwarp
);
203 Cvar_RegisterVariable (&r_fullbright
);
204 Cvar_RegisterVariable (&r_drawentities
);
205 Cvar_RegisterVariable (&r_drawviewmodel
);
206 Cvar_RegisterVariable (&r_aliasstats
);
207 Cvar_RegisterVariable (&r_dspeeds
);
208 Cvar_RegisterVariable (&r_reportsurfout
);
209 Cvar_RegisterVariable (&r_maxsurfs
);
210 Cvar_RegisterVariable (&r_numsurfs
);
211 Cvar_RegisterVariable (&r_reportedgeout
);
212 Cvar_RegisterVariable (&r_maxedges
);
213 Cvar_RegisterVariable (&r_numedges
);
214 Cvar_RegisterVariable (&r_aliastransbase
);
215 Cvar_RegisterVariable (&r_aliastransadj
);
217 Cvar_SetValue ("r_maxedges", (float)NUMSTACKEDGES
);
218 Cvar_SetValue ("r_maxsurfs", (float)NUMSTACKSURFACES
);
220 view_clipplanes
[0].leftedge
= true;
221 view_clipplanes
[1].rightedge
= true;
222 view_clipplanes
[1].leftedge
= view_clipplanes
[2].leftedge
=
223 view_clipplanes
[3].leftedge
= false;
224 view_clipplanes
[0].rightedge
= view_clipplanes
[2].rightedge
=
225 view_clipplanes
[3].rightedge
= false;
227 r_refdef
.xOrigin
= XCENTERING
;
228 r_refdef
.yOrigin
= YCENTERING
;
232 // TODO: collect 386-specific code in one place
234 Sys_MakeCodeWriteable ((long)R_EdgeCodeStart
,
235 (long)R_EdgeCodeEnd
- (long)R_EdgeCodeStart
);
250 // clear out efrags in case the level hasn't been reloaded
251 // FIXME: is this one short?
252 for (i
=0 ; i
<cl
.worldmodel
->numleafs
; i
++)
253 cl
.worldmodel
->leafs
[i
].efrags
= NULL
;
258 r_cnumsurfs
= r_maxsurfs
.value
;
260 if (r_cnumsurfs
<= MINSURFACES
)
261 r_cnumsurfs
= MINSURFACES
;
263 if (r_cnumsurfs
> NUMSTACKSURFACES
)
265 surfaces
= Hunk_AllocName (r_cnumsurfs
* sizeof(surf_t
), "surfaces");
266 surface_p
= surfaces
;
267 surf_max
= &surfaces
[r_cnumsurfs
];
268 r_surfsonstack
= false;
269 // surface 0 doesn't really exist; it's just a dummy because index 0
270 // is used to indicate no edge attached to surface
276 r_surfsonstack
= true;
282 r_numallocatededges
= r_maxedges
.value
;
284 if (r_numallocatededges
< MINEDGES
)
285 r_numallocatededges
= MINEDGES
;
287 if (r_numallocatededges
<= NUMSTACKEDGES
)
293 auxedges
= Hunk_AllocName (r_numallocatededges
* sizeof(edge_t
),
298 r_viewchanged
= false;
310 void R_SetVrect (vrect_t
*pvrectin
, vrect_t
*pvrect
, int lineadj
)
315 size
= scr_viewsize
.value
> 100 ? 100 : scr_viewsize
.value
;
323 h
= pvrectin
->height
- lineadj
;
324 pvrect
->width
= pvrectin
->width
* size
;
325 if (pvrect
->width
< 96)
327 size
= 96.0 / pvrectin
->width
;
328 pvrect
->width
= 96; // min for icons
331 pvrect
->height
= pvrectin
->height
* size
;
332 if (pvrect
->height
> pvrectin
->height
- lineadj
)
333 pvrect
->height
= pvrectin
->height
- lineadj
;
335 pvrect
->height
&= ~1;
337 pvrect
->x
= (pvrectin
->width
- pvrect
->width
)/2;
338 pvrect
->y
= (h
- pvrect
->height
)/2;
344 pvrect
->height
>>= 1;
354 Called every time the vid structure or r_refdef changes.
355 Guaranteed to be called before the first refresh
358 void R_ViewChanged (vrect_t
*pvrect
, int lineadj
, float aspect
)
363 r_viewchanged
= true;
365 R_SetVrect (pvrect
, &r_refdef
.vrect
, lineadj
);
367 r_refdef
.horizontalFieldOfView
= 2.0 * tanf (r_refdef
.fov_x
/360*M_PI
);
368 r_refdef
.fvrectx
= (float)r_refdef
.vrect
.x
;
369 r_refdef
.fvrectx_adj
= (float)r_refdef
.vrect
.x
- 0.5;
370 r_refdef
.vrect_x_adj_shift20
= (r_refdef
.vrect
.x
<<20) + (1<<19) - 1;
371 r_refdef
.fvrecty
= (float)r_refdef
.vrect
.y
;
372 r_refdef
.fvrecty_adj
= (float)r_refdef
.vrect
.y
- 0.5;
373 r_refdef
.vrectright
= r_refdef
.vrect
.x
+ r_refdef
.vrect
.width
;
374 r_refdef
.vrectright_adj_shift20
= (r_refdef
.vrectright
<<20) + (1<<19) - 1;
375 r_refdef
.fvrectright
= (float)r_refdef
.vrectright
;
376 r_refdef
.fvrectright_adj
= (float)r_refdef
.vrectright
- 0.5;
377 r_refdef
.vrectrightedge
= (float)r_refdef
.vrectright
- 0.99;
378 r_refdef
.vrectbottom
= r_refdef
.vrect
.y
+ r_refdef
.vrect
.height
;
379 r_refdef
.fvrectbottom
= (float)r_refdef
.vrectbottom
;
380 r_refdef
.fvrectbottom_adj
= (float)r_refdef
.vrectbottom
- 0.5;
382 r_refdef
.aliasvrect
.x
= (int)(r_refdef
.vrect
.x
* r_aliasuvscale
);
383 r_refdef
.aliasvrect
.y
= (int)(r_refdef
.vrect
.y
* r_aliasuvscale
);
384 r_refdef
.aliasvrect
.width
= (int)(r_refdef
.vrect
.width
* r_aliasuvscale
);
385 r_refdef
.aliasvrect
.height
= (int)(r_refdef
.vrect
.height
* r_aliasuvscale
);
386 r_refdef
.aliasvrectright
= r_refdef
.aliasvrect
.x
+
387 r_refdef
.aliasvrect
.width
;
388 r_refdef
.aliasvrectbottom
= r_refdef
.aliasvrect
.y
+
389 r_refdef
.aliasvrect
.height
;
391 pixelAspect
= aspect
;
392 xOrigin
= r_refdef
.xOrigin
;
393 yOrigin
= r_refdef
.yOrigin
;
395 screenAspect
= r_refdef
.vrect
.width
*pixelAspect
/
396 r_refdef
.vrect
.height
;
397 // 320*200 1.0 pixelAspect = 1.6 screenAspect
398 // 320*240 1.0 pixelAspect = 1.3333 screenAspect
399 // proper 320*200 pixelAspect = 0.8333333
401 verticalFieldOfView
= r_refdef
.horizontalFieldOfView
/ screenAspect
;
403 // values for perspective projection
404 // if math were exact, the values would range from 0.5 to to range+0.5
405 // hopefully they wll be in the 0.000001 to range+.999999 and truncate
406 // the polygon rasterization will never render in the first row or column
407 // but will definately render in the [range] row and column, so adjust the
408 // buffer origin to get an exact edge to edge fill
409 xcenter
= ((float)r_refdef
.vrect
.width
* XCENTERING
) +
410 r_refdef
.vrect
.x
- 0.5;
411 aliasxcenter
= xcenter
* r_aliasuvscale
;
412 ycenter
= ((float)r_refdef
.vrect
.height
* YCENTERING
) +
413 r_refdef
.vrect
.y
- 0.5;
414 aliasycenter
= ycenter
* r_aliasuvscale
;
416 xscale
= r_refdef
.vrect
.width
/ r_refdef
.horizontalFieldOfView
;
417 aliasxscale
= xscale
* r_aliasuvscale
;
418 xscaleinv
= 1.0 / xscale
;
419 yscale
= xscale
* pixelAspect
;
420 aliasyscale
= yscale
* r_aliasuvscale
;
421 yscaleinv
= 1.0 / yscale
;
422 xscaleshrink
= (r_refdef
.vrect
.width
-6)/r_refdef
.horizontalFieldOfView
;
423 yscaleshrink
= xscaleshrink
*pixelAspect
;
426 screenedge
[0].normal
[0] = -1.0 / (xOrigin
*r_refdef
.horizontalFieldOfView
);
427 screenedge
[0].normal
[1] = 0;
428 screenedge
[0].normal
[2] = 1;
429 screenedge
[0].type
= PLANE_ANYZ
;
432 screenedge
[1].normal
[0] =
433 1.0 / ((1.0-xOrigin
)*r_refdef
.horizontalFieldOfView
);
434 screenedge
[1].normal
[1] = 0;
435 screenedge
[1].normal
[2] = 1;
436 screenedge
[1].type
= PLANE_ANYZ
;
439 screenedge
[2].normal
[0] = 0;
440 screenedge
[2].normal
[1] = -1.0 / (yOrigin
*verticalFieldOfView
);
441 screenedge
[2].normal
[2] = 1;
442 screenedge
[2].type
= PLANE_ANYZ
;
445 screenedge
[3].normal
[0] = 0;
446 screenedge
[3].normal
[1] = 1.0 / ((1.0-yOrigin
)*verticalFieldOfView
);
447 screenedge
[3].normal
[2] = 1;
448 screenedge
[3].type
= PLANE_ANYZ
;
450 for (i
=0 ; i
<4 ; i
++)
451 VectorNormalize (screenedge
[i
].normal
);
453 res_scale
= sqrtf ((float)(r_refdef
.vrect
.width
* r_refdef
.vrect
.height
) /
455 (2.0 / r_refdef
.horizontalFieldOfView
);
456 r_aliastransition
= r_aliastransbase
.value
* res_scale
;
457 r_resfudge
= r_aliastransadj
.value
* res_scale
;
459 if (scr_fov
.value
<= 90.0)
460 r_fov_greater_than_90
= false;
462 r_fov_greater_than_90
= true;
464 // TODO: collect 386-specific code in one place
468 Sys_MakeCodeWriteable ((long)R_Surf8Start
,
469 (long)R_Surf8End
- (long)R_Surf8Start
);
470 colormap
= vid
.colormap
;
475 Sys_MakeCodeWriteable ((long)R_Surf16Start
,
476 (long)R_Surf16End
- (long)R_Surf16Start
);
477 colormap
= vid
.colormap16
;
491 void R_MarkLeaves (void)
497 if (r_oldviewleaf
== r_viewleaf
)
501 r_oldviewleaf
= r_viewleaf
;
503 vis
= Mod_LeafPVS (r_viewleaf
, cl
.worldmodel
);
505 for (i
=0 ; i
<cl
.worldmodel
->numleafs
; i
++)
507 if (vis
[i
>>3] & (1<<(i
&7)))
509 node
= (mnode_t
*)&cl
.worldmodel
->leafs
[i
+1];
512 if (node
->visframe
== r_visframecount
)
514 node
->visframe
= r_visframecount
;
527 void R_DrawEntitiesOnList (void)
532 // FIXME: remove and do real lighting
533 float lightvec
[3] = {-1, 0, 0};
537 if (!r_drawentities
.value
)
540 for (i
=0 ; i
<cl_numvisedicts
; i
++)
542 currententity
= cl_visedicts
[i
];
544 if (currententity
== &cl_entities
[cl
.viewentity
])
545 continue; // don't draw the player
547 switch (currententity
->model
->type
)
550 VectorCopy (currententity
->origin
, r_entorigin
);
551 VectorSubtract (r_origin
, r_entorigin
, modelorg
);
556 VectorCopy (currententity
->origin
, r_entorigin
);
557 VectorSubtract (r_origin
, r_entorigin
, modelorg
);
559 // see if the bounding box lets us trivially reject, also sets
560 // trivial accept status
561 if (R_AliasCheckBBox ())
563 j
= R_LightPoint (currententity
->origin
);
565 lighting
.ambientlight
= j
;
566 lighting
.shadelight
= j
;
568 lighting
.plightvec
= lightvec
;
570 for (lnum
=0 ; lnum
<MAX_DLIGHTS
; lnum
++)
572 if (cl_dlights
[lnum
].die
>= cl
.time
)
574 VectorSubtract (currententity
->origin
,
575 cl_dlights
[lnum
].origin
,
577 add
= cl_dlights
[lnum
].radius
- Length(dist
);
580 lighting
.ambientlight
+= add
;
584 // clamp lighting so it doesn't overbright as much
585 if (lighting
.ambientlight
> 128)
586 lighting
.ambientlight
= 128;
587 if (lighting
.ambientlight
+ lighting
.shadelight
> 192)
588 lighting
.shadelight
= 192 - lighting
.ambientlight
;
590 R_AliasDrawModel (&lighting
);
606 void R_DrawViewModel (void)
608 // FIXME: remove and do real lighting
609 float lightvec
[3] = {-1, 0, 0};
616 if (!r_drawviewmodel
.value
|| r_fov_greater_than_90
)
619 if (cl
.items
& IT_INVISIBILITY
)
622 if (cl
.stats
[STAT_HEALTH
] <= 0)
625 currententity
= &cl
.viewent
;
626 if (!currententity
->model
)
629 VectorCopy (currententity
->origin
, r_entorigin
);
630 VectorSubtract (r_origin
, r_entorigin
, modelorg
);
632 VectorCopy (vup
, viewlightvec
);
633 VectorInverse (viewlightvec
);
635 j
= R_LightPoint (currententity
->origin
);
638 j
= 24; // allways give some light on gun
639 r_viewlighting
.ambientlight
= j
;
640 r_viewlighting
.shadelight
= j
;
642 // add dynamic lights
643 for (lnum
=0 ; lnum
<MAX_DLIGHTS
; lnum
++)
645 dl
= &cl_dlights
[lnum
];
650 if (dl
->die
< cl
.time
)
653 VectorSubtract (currententity
->origin
, dl
->origin
, dist
);
654 add
= dl
->radius
- Length(dist
);
656 r_viewlighting
.ambientlight
+= add
;
659 // clamp lighting so it doesn't overbright as much
660 if (r_viewlighting
.ambientlight
> 128)
661 r_viewlighting
.ambientlight
= 128;
662 if (r_viewlighting
.ambientlight
+ r_viewlighting
.shadelight
> 192)
663 r_viewlighting
.shadelight
= 192 - r_viewlighting
.ambientlight
;
665 r_viewlighting
.plightvec
= lightvec
;
668 cl
.light_level
= r_viewlighting
.ambientlight
;
671 R_AliasDrawModel (&r_viewlighting
);
680 int R_BmodelCheckBBox (model_t
*clmodel
, float *minmaxs
)
682 int i
, *pindex
, clipflags
;
683 vec3_t acceptpt
, rejectpt
;
688 if (currententity
->angles
[0] || currententity
->angles
[1]
689 || currententity
->angles
[2])
691 for (i
=0 ; i
<4 ; i
++)
693 d
= DotProduct (currententity
->origin
, view_clipplanes
[i
].normal
);
694 d
-= view_clipplanes
[i
].dist
;
696 if (d
<= -clmodel
->radius
)
697 return BMODEL_FULLY_CLIPPED
;
699 if (d
<= clmodel
->radius
)
705 for (i
=0 ; i
<4 ; i
++)
707 // generate accept and reject points
708 // FIXME: do with fast look-ups or integer tests based on the sign bit
709 // of the floating point values
711 pindex
= pfrustum_indexes
[i
];
713 rejectpt
[0] = minmaxs
[pindex
[0]];
714 rejectpt
[1] = minmaxs
[pindex
[1]];
715 rejectpt
[2] = minmaxs
[pindex
[2]];
717 d
= DotProduct (rejectpt
, view_clipplanes
[i
].normal
);
718 d
-= view_clipplanes
[i
].dist
;
721 return BMODEL_FULLY_CLIPPED
;
723 acceptpt
[0] = minmaxs
[pindex
[3+0]];
724 acceptpt
[1] = minmaxs
[pindex
[3+1]];
725 acceptpt
[2] = minmaxs
[pindex
[3+2]];
727 d
= DotProduct (acceptpt
, view_clipplanes
[i
].normal
);
728 d
-= view_clipplanes
[i
].dist
;
741 R_DrawBEntitiesOnList
744 void R_DrawBEntitiesOnList (void)
746 int i
, j
, k
, clipflags
;
751 if (!r_drawentities
.value
)
754 VectorCopy (modelorg
, oldorigin
);
756 r_dlightframecount
= r_framecount
;
758 for (i
=0 ; i
<cl_numvisedicts
; i
++)
760 currententity
= cl_visedicts
[i
];
762 switch (currententity
->model
->type
)
766 clmodel
= currententity
->model
;
768 // see if the bounding box lets us trivially reject, also sets
769 // trivial accept status
770 for (j
=0 ; j
<3 ; j
++)
772 minmaxs
[j
] = currententity
->origin
[j
] +
774 minmaxs
[3+j
] = currententity
->origin
[j
] +
778 clipflags
= R_BmodelCheckBBox (clmodel
, minmaxs
);
780 if (clipflags
!= BMODEL_FULLY_CLIPPED
)
782 VectorCopy (currententity
->origin
, r_entorigin
);
783 VectorSubtract (r_origin
, r_entorigin
, modelorg
);
784 // FIXME: is this needed?
785 VectorCopy (modelorg
, r_worldmodelorg
);
787 r_pcurrentvertbase
= clmodel
->vertexes
;
789 // FIXME: stop transforming twice
792 // calculate dynamic lighting for bmodel if it's not an
794 if (clmodel
->firstmodelsurface
!= 0)
796 for (k
=0 ; k
<MAX_DLIGHTS
; k
++)
798 if ((cl_dlights
[k
].die
< cl
.time
) ||
799 (!cl_dlights
[k
].radius
))
804 R_MarkLights (&cl_dlights
[k
], 1<<k
,
805 clmodel
->nodes
+ clmodel
->hulls
[0].firstclipnode
);
809 // if the driver wants polygons, deliver those. Z-buffering is on
810 // at this point, so no clipping to the world tree is needed, just
812 if (r_drawpolys
| r_drawculledpolys
)
814 R_ZDrawSubmodelPolys (clmodel
);
818 r_pefragtopnode
= NULL
;
820 for (j
=0 ; j
<3 ; j
++)
822 r_emins
[j
] = minmaxs
[j
];
823 r_emaxs
[j
] = minmaxs
[3+j
];
826 R_SplitEntityOnNode2 (cl
.worldmodel
->nodes
);
830 currententity
->topnode
= r_pefragtopnode
;
832 if (r_pefragtopnode
->contents
>= 0)
834 // not a leaf; has to be clipped to the world BSP
835 r_clipflags
= clipflags
;
836 R_DrawSolidClippedSubmodelPolygons (clmodel
);
840 // falls entirely in one leaf, so we just put all the
841 // edges in the edge list and let 1/z sorting handle
843 R_DrawSubmodelPolygons (clmodel
, clipflags
);
846 currententity
->topnode
= NULL
;
850 // put back world rotation and frustum clipping
851 // FIXME: R_RotateBmodel should just work off base_vxx
852 VectorCopy (base_vpn
, vpn
);
853 VectorCopy (base_vup
, vup
);
854 VectorCopy (base_vright
, vright
);
855 VectorCopy (base_modelorg
, modelorg
);
856 VectorCopy (oldorigin
, modelorg
);
857 R_TransformFrustum ();
876 void R_EdgeDrawing (void)
878 edge_t ledges
[NUMSTACKEDGES
+
879 ((CACHE_SIZE
- 1) / sizeof(edge_t
)) + 1];
880 surf_t lsurfs
[NUMSTACKSURFACES
+
881 ((CACHE_SIZE
- 1) / sizeof(surf_t
)) + 1];
890 (((long)&ledges
[0] + CACHE_SIZE
- 1) & ~(CACHE_SIZE
- 1));
895 surfaces
= (surf_t
*)
896 (((long)&lsurfs
[0] + CACHE_SIZE
- 1) & ~(CACHE_SIZE
- 1));
897 surf_max
= &surfaces
[r_cnumsurfs
];
898 // surface 0 doesn't really exist; it's just a dummy because index 0
899 // is used to indicate no edge attached to surface
908 rw_time1
= Sys_FloatTime ();
913 if (r_drawculledpolys
)
916 // only the world can be drawn back to front with no z reads or compares, just
917 // z writes, so have the driver turn z compares on now
922 rw_time2
= Sys_FloatTime ();
926 R_DrawBEntitiesOnList ();
930 db_time2
= Sys_FloatTime ();
934 if (!r_dspeeds
.value
)
937 S_ExtraUpdate (); // don't let sound get messed up if going slow
941 if (!(r_drawpolys
| r_drawculledpolys
))
950 r_refdef must be set before the first call
953 void R_RenderView_ (void)
955 byte warpbuffer
[WARP_WIDTH
* WARP_HEIGHT
];
957 r_warpbuffer
= warpbuffer
;
959 if (r_timegraph
.value
|| r_speeds
.value
|| r_dspeeds
.value
)
960 r_time1
= Sys_FloatTime ();
965 SetVisibilityByPassages ();
967 R_MarkLeaves (); // done here so we know if we're in water
970 // make FDIV fast. This reduces timing precision after we've been running for a
971 // while, so we don't do it globally. This also sets chop mode, and we do it
972 // here so that setup stuff like the refresh area calculations match what's
974 Sys_LowFPPrecision ();
976 if (!cl_entities
[0].model
|| !cl
.worldmodel
)
977 Sys_Error ("R_RenderView: NULL worldmodel");
979 if (!r_dspeeds
.value
)
982 S_ExtraUpdate (); // don't let sound get messed up if going slow
988 if (!r_dspeeds
.value
)
991 S_ExtraUpdate (); // don't let sound get messed up if going slow
997 se_time2
= Sys_FloatTime ();
1001 R_DrawEntitiesOnList ();
1003 if (r_dspeeds
.value
)
1005 de_time2
= Sys_FloatTime ();
1006 dv_time1
= de_time2
;
1011 if (r_dspeeds
.value
)
1013 dv_time2
= Sys_FloatTime ();
1014 dp_time1
= Sys_FloatTime ();
1019 if (r_dspeeds
.value
)
1020 dp_time2
= Sys_FloatTime ();
1025 V_SetContentsColor (r_viewleaf
->contents
);
1027 if (r_timegraph
.value
)
1030 if (r_aliasstats
.value
)
1031 R_PrintAliasStats ();
1036 if (r_dspeeds
.value
)
1039 if (r_reportsurfout
.value
&& r_outofsurfaces
)
1040 Con_Printf ("Short %d surfaces\n", r_outofsurfaces
);
1042 if (r_reportedgeout
.value
&& r_outofedges
)
1043 Con_Printf ("Short roughly %d edges\n", r_outofedges
* 2 / 3);
1045 // back to high floating-point precision
1046 Sys_HighFPPrecision ();
1049 void R_RenderView (void)
1054 delta
= (byte
*)&dummy
- r_stack_start
;
1055 if (delta
< -10000 || delta
> 10000)
1056 Sys_Error ("R_RenderView: called without enough stack");
1058 if ( Hunk_LowMark() & 3 )
1059 Sys_Error ("Hunk is missaligned");
1061 if ( (long)(&dummy
) & 3 )
1062 Sys_Error ("Stack is missaligned");
1064 if ( (long)(&r_warpbuffer
) & 3 )
1065 Sys_Error ("Globals are missaligned");
1075 void R_InitTurb (void)
1079 for (i
=0 ; i
<(SIN_BUFFER_SIZE
) ; i
++)
1081 sintable
[i
] = AMP
+ sinf(i
*3.14159*2/CYCLE
)*AMP
;
1082 intsintable
[i
] = AMP2
+ sinf(i
*3.14159*2/CYCLE
)*AMP2
; // AMP2, not 20