1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19*/ 20// d_edge.c 21 22#include "quakedef.h" 23#include "d_local.h" 24 25static int miplevel; 26 27float scale_for_mip; 28int screenwidth; 29int ubasestep, errorterm, erroradjustup, erroradjustdown; 30int vstartscan; 31 32// FIXME: should go away 33extern void R_RotateBmodel (void); 34extern void R_TransformFrustum (void); 35 36vec3_t transformed_modelorg; 37 38/* 39============== 40D_DrawPoly 41 42============== 43*/ 44void D_DrawPoly (void) 45{ 46// this driver takes spans, not polygons 47} 48 49 50/* 51============= 52D_MipLevelForScale 53============= 54*/ 55int D_MipLevelForScale (float scale) 56{ 57 int lmiplevel; 58 59 if (scale >= d_scalemip[0] ) 60 lmiplevel = 0; 61 else if (scale >= d_scalemip[1] ) 62 lmiplevel = 1; 63 else if (scale >= d_scalemip[2] ) 64 lmiplevel = 2; 65 else 66 lmiplevel = 3; 67 68 if (lmiplevel < d_minmip) 69 lmiplevel = d_minmip; 70 71 return lmiplevel; 72} 73 74 75/* 76============== 77D_DrawSolidSurface 78============== 79*/ 80 81// FIXME: clean this up 82 83void D_DrawSolidSurface (surf_t *surf, int color) 84{ 85 espan_t *span; 86 byte *pdest; 87 int u, u2, pix; 88 89 pix = (color<<24) | (color<<16) | (color<<8) | color; 90 for (span=surf->spans ; span ; span=span->pnext) 91 { 92 pdest = (byte *)d_viewbuffer + screenwidth*span->v; 93 u = span->u; 94 u2 = span->u + span->count - 1; 95 ((byte *)pdest)[u] = pix; 96 97 if (u2 - u < 8) 98 { 99 for (u++ ; u <= u2 ; u++) 100 ((byte *)pdest)[u] = pix; 101 } 102 else 103 { 104 for (u++ ; u & 3 ; u++) 105 ((byte *)pdest)[u] = pix; 106 107 u2 -= 4; 108 for ( ; u <= u2 ; u+=4) 109 *(int *)((byte *)pdest + u) = pix; 110 u2 += 4; 111 for ( ; u <= u2 ; u++) 112 ((byte *)pdest)[u] = pix; 113 } 114 } 115} 116 117 118/* 119============== 120D_CalcGradients 121============== 122*/ 123void D_CalcGradients (msurface_t *pface) 124{ 125 mplane_t *pplane; 126 float mipscale; 127 vec3_t p_temp1; 128 vec3_t p_saxis, p_taxis; 129 float t; 130 131 pplane = pface->plane; 132 133 mipscale = 1.0 / (float)(1 << miplevel); 134 135 TransformVector (pface->texinfo->vecs[0], p_saxis); 136 TransformVector (pface->texinfo->vecs[1], p_taxis); 137 138 t = xscaleinv * mipscale; 139 d_sdivzstepu = p_saxis[0] * t; 140 d_tdivzstepu = p_taxis[0] * t; 141 142 t = yscaleinv * mipscale; 143 d_sdivzstepv = -p_saxis[1] * t; 144 d_tdivzstepv = -p_taxis[1] * t; 145 146 d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu - 147 ycenter * d_sdivzstepv; 148 d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu - 149 ycenter * d_tdivzstepv; 150 151 VectorScale (transformed_modelorg, mipscale, p_temp1); 152 153 t = 0x10000*mipscale; 154 sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - 155 ((pface->texturemins[0] << 16) >> miplevel) 156 + pface->texinfo->vecs[0][3]*t; 157 tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - 158 ((pface->texturemins[1] << 16) >> miplevel) 159 + pface->texinfo->vecs[1][3]*t; 160 161// 162// -1 (-epsilon) so we never wander off the edge of the texture 163// 164 bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; 165 bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; 166} 167 168 169/* 170============== 171D_DrawSurfaces 172============== 173*/ 174void D_DrawSurfaces (void) 175{ 176 surf_t *s; 177 msurface_t *pface; 178 surfcache_t *pcurrentcache; 179 vec3_t world_transformed_modelorg; 180 vec3_t local_modelorg; 181 182 currententity = &r_worldentity; 183 TransformVector (modelorg, transformed_modelorg); 184 VectorCopy (transformed_modelorg, world_transformed_modelorg); 185 186// TODO: could preset a lot of this at mode set time 187 if (r_drawflat.value) 188 { 189 for (s = &surfaces[1] ; s<surface_p ; s++) 190 { 191 if (!s->spans) 192 continue; 193 194 d_zistepu = s->d_zistepu; 195 d_zistepv = s->d_zistepv; 196 d_ziorigin = s->d_ziorigin; 197 198#ifdef __alpha__ 199 D_DrawSolidSurface (s, (int)((long)s->data & 0xFF)); 200#else 201 D_DrawSolidSurface (s, (int)s->data & 0xFF); 202#endif 203 D_DrawZSpans (s->spans); 204 } 205 } 206 else 207 { 208 for (s = &surfaces[1] ; s<surface_p ; s++) 209 { 210 if (!s->spans) 211 continue; 212 213 r_drawnpolycount++; 214 215 d_zistepu = s->d_zistepu; 216 d_zistepv = s->d_zistepv; 217 d_ziorigin = s->d_ziorigin; 218 219 if (s->flags & SURF_DRAWSKY) 220 { 221 if (!r_skymade) 222 { 223 R_MakeSky (); 224 } 225 226 D_DrawSkyScans8 (s->spans); 227 D_DrawZSpans (s->spans); 228 } 229 else if (s->flags & SURF_DRAWBACKGROUND) 230 { 231 // set up a gradient for the background surface that places it 232 // effectively at infinity distance from the viewpoint 233 d_zistepu = 0; 234 d_zistepv = 0; 235 d_ziorigin = -0.9; 236 237 D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF); 238 D_DrawZSpans (s->spans); 239 } 240 else if (s->flags & SURF_DRAWTURB) 241 { 242 pface = s->data; 243 miplevel = 0; 244 cacheblock = (pixel_t *) 245 ((byte *)pface->texinfo->texture + 246 pface->texinfo->texture->offsets[0]); 247 cachewidth = 64; 248 249 if (s->insubmodel) 250 { 251 // FIXME: we don't want to do all this for every polygon! 252 // TODO: store once at start of frame 253 currententity = s->entity; //FIXME: make this passed in to 254 // R_RotateBmodel () 255 VectorSubtract (r_origin, currententity->origin, 256 local_modelorg); 257 TransformVector (local_modelorg, transformed_modelorg); 258 259 R_RotateBmodel (); // FIXME: don't mess with the frustum, 260 // make entity passed in 261 } 262 263 D_CalcGradients (pface); 264 265 Turbulent8 (s->spans); 266 D_DrawZSpans (s->spans); 267 268 if (s->insubmodel) 269 { 270 // 271 // restore the old drawing state 272 // FIXME: we don't want to do this every time! 273 // TODO: speed up 274 // 275 currententity = &r_worldentity; 276 VectorCopy (world_transformed_modelorg, 277 transformed_modelorg); 278 VectorCopy (base_vpn, vpn); 279 VectorCopy (base_vup, vup); 280 VectorCopy (base_vright, vright); 281 VectorCopy (base_modelorg, modelorg); 282 R_TransformFrustum (); 283 } 284 } 285 else 286 { 287 if (s->insubmodel) 288 { 289 // FIXME: we don't want to do all this for every polygon! 290 // TODO: store once at start of frame 291 currententity = s->entity; //FIXME: make this passed in to 292 // R_RotateBmodel () 293 VectorSubtract (r_origin, currententity->origin, local_modelorg); 294 TransformVector (local_modelorg, transformed_modelorg); 295 296 R_RotateBmodel (); // FIXME: don't mess with the frustum, 297 // make entity passed in 298 } 299 300 pface = s->data; 301 miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip 302 * pface->texinfo->mipadjust); 303 304 // FIXME: make this passed in to D_CacheSurface 305 pcurrentcache = D_CacheSurface (pface, miplevel); 306 307 cacheblock = (pixel_t *)pcurrentcache->data; 308 cachewidth = pcurrentcache->width; 309 310 D_CalcGradients (pface); 311 312 (*d_drawspans) (s->spans); 313 314 D_DrawZSpans (s->spans); 315 316 if (s->insubmodel) 317 { 318 // 319 // restore the old drawing state 320 // FIXME: we don't want to do this every time! 321 // TODO: speed up 322 // 323 VectorCopy (world_transformed_modelorg, 324 transformed_modelorg); 325 VectorCopy (base_vpn, vpn); 326 VectorCopy (base_vup, vup); 327 VectorCopy (base_vright, vright); 328 VectorCopy (base_modelorg, modelorg); 329 R_TransformFrustum (); 330 currententity = &r_worldentity; 331 } 332 } 333 } 334 } 335} 336 337