1 /* 2 Copyright (C) 1996-1997 Id Software, Inc. 3 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. 8 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. 12 13 See the GNU General Public License for more details. 14 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. 18 19 */ 20 // d_edge.c 21 22 #include "quakedef.h" 23 #include "d_local.h" 24 25 static int miplevel; 26 27 float scale_for_mip; 28 int screenwidth; 29 int ubasestep, errorterm, erroradjustup, erroradjustdown; 30 int vstartscan; 31 32 // FIXME: should go away 33 extern void R_RotateBmodel (void); 34 extern void R_TransformFrustum (void); 35 36 vec3_t transformed_modelorg; 37 38 /* 39 ============== 40 D_DrawPoly 41 42 ============== 43 */ 44 void D_DrawPoly (void) 45 { 46 // this driver takes spans, not polygons 47 } 48 49 50 /* 51 ============= 52 D_MipLevelForScale 53 ============= 54 */ 55 int 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 ============== 77 D_DrawSolidSurface 78 ============== 79 */ 80 81 // FIXME: clean this up 82 83 void 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 ============== 120 D_CalcGradients 121 ============== 122 */ 123 void 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 ============== 171 D_DrawSurfaces 172 ============== 173 */ 174 void 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 = &cl_entities[0]; 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 D_DrawSolidSurface (s, (int)s->data & 0xFF); 199 D_DrawZSpans (s->spans); 200 } 201 } 202 else 203 { 204 for (s = &surfaces[1] ; s<surface_p ; s++) 205 { 206 if (!s->spans) 207 continue; 208 209 r_drawnpolycount++; 210 211 d_zistepu = s->d_zistepu; 212 d_zistepv = s->d_zistepv; 213 d_ziorigin = s->d_ziorigin; 214 215 if (s->flags & SURF_DRAWSKY) 216 { 217 if (!r_skymade) 218 { 219 R_MakeSky (); 220 } 221 222 D_DrawSkyScans8 (s->spans); 223 D_DrawZSpans (s->spans); 224 } 225 else if (s->flags & SURF_DRAWBACKGROUND) 226 { 227 // set up a gradient for the background surface that places it 228 // effectively at infinity distance from the viewpoint 229 d_zistepu = 0; 230 d_zistepv = 0; 231 d_ziorigin = -0.9; 232 233 D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF); 234 D_DrawZSpans (s->spans); 235 } 236 else if (s->flags & SURF_DRAWTURB) 237 { 238 pface = s->data; 239 miplevel = 0; 240 cacheblock = (pixel_t *) 241 ((byte *)pface->texinfo->texture + 242 pface->texinfo->texture->offsets[0]); 243 cachewidth = 64; 244 245 if (s->insubmodel) 246 { 247 // FIXME: we don't want to do all this for every polygon! 248 // TODO: store once at start of frame 249 currententity = s->entity; //FIXME: make this passed in to 250 // R_RotateBmodel () 251 VectorSubtract (r_origin, currententity->origin, 252 local_modelorg); 253 TransformVector (local_modelorg, transformed_modelorg); 254 255 R_RotateBmodel (); // FIXME: don't mess with the frustum, 256 // make entity passed in 257 } 258 259 D_CalcGradients (pface); 260 Turbulent8 (s->spans); 261 D_DrawZSpans (s->spans); 262 263 if (s->insubmodel) 264 { 265 // 266 // restore the old drawing state 267 // FIXME: we don't want to do this every time! 268 // TODO: speed up 269 // 270 currententity = &cl_entities[0]; 271 VectorCopy (world_transformed_modelorg, 272 transformed_modelorg); 273 VectorCopy (base_vpn, vpn); 274 VectorCopy (base_vup, vup); 275 VectorCopy (base_vright, vright); 276 VectorCopy (base_modelorg, modelorg); 277 R_TransformFrustum (); 278 } 279 } 280 else 281 { 282 if (s->insubmodel) 283 { 284 // FIXME: we don't want to do all this for every polygon! 285 // TODO: store once at start of frame 286 currententity = s->entity; //FIXME: make this passed in to 287 // R_RotateBmodel () 288 VectorSubtract (r_origin, currententity->origin, local_modelorg); 289 TransformVector (local_modelorg, transformed_modelorg); 290 291 R_RotateBmodel (); // FIXME: don't mess with the frustum, 292 // make entity passed in 293 } 294 295 pface = s->data; 296 miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip 297 * pface->texinfo->mipadjust); 298 299 // FIXME: make this passed in to D_CacheSurface 300 pcurrentcache = D_CacheSurface (pface, miplevel); 301 302 cacheblock = (pixel_t *)pcurrentcache->data; 303 cachewidth = pcurrentcache->width; 304 305 D_CalcGradients (pface); 306 307 (*d_drawspans) (s->spans); 308 309 D_DrawZSpans (s->spans); 310 311 if (s->insubmodel) 312 { 313 // 314 // restore the old drawing state 315 // FIXME: we don't want to do this every time! 316 // TODO: speed up 317 // 318 currententity = &cl_entities[0]; 319 VectorCopy (world_transformed_modelorg, 320 transformed_modelorg); 321 VectorCopy (base_vpn, vpn); 322 VectorCopy (base_vup, vup); 323 VectorCopy (base_vright, vright); 324 VectorCopy (base_modelorg, modelorg); 325 R_TransformFrustum (); 326 } 327 } 328 } 329 } 330 } 331 332