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 // r_aclip.c: clip routines for drawing Alias models directly to the screen 21 22 #include "quakedef.h" 23 #include "r_local.h" 24 #include "d_local.h" 25 26 static finalvert_t fv[2][8]; 27 static auxvert_t av[8]; 28 29 void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av); 30 void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, 31 finalvert_t *out); 32 void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, 33 finalvert_t *out); 34 void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, 35 finalvert_t *out); 36 void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, 37 finalvert_t *out); 38 39 40 /* 41 ================ 42 R_Alias_clip_z 43 44 pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex 45 ================ 46 */ 47 void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) 48 { 49 float scale; 50 auxvert_t *pav0, *pav1, avout; 51 52 pav0 = &av[pfv0 - &fv[0][0]]; 53 pav1 = &av[pfv1 - &fv[0][0]]; 54 55 if (pfv0->v[1] >= pfv1->v[1]) 56 { 57 scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) / 58 (pav1->fv[2] - pav0->fv[2]); 59 60 avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale; 61 avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale; 62 avout.fv[2] = ALIAS_Z_CLIP_PLANE; 63 64 out->v[2] = pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale; 65 out->v[3] = pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale; 66 out->v[4] = pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale; 67 } 68 else 69 { 70 scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) / 71 (pav0->fv[2] - pav1->fv[2]); 72 73 avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale; 74 avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale; 75 avout.fv[2] = ALIAS_Z_CLIP_PLANE; 76 77 out->v[2] = pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale; 78 out->v[3] = pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale; 79 out->v[4] = pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale; 80 } 81 82 R_AliasProjectFinalVert (out, &avout); 83 84 if (out->v[0] < r_refdef.aliasvrect.x) 85 out->flags |= ALIAS_LEFT_CLIP; 86 if (out->v[1] < r_refdef.aliasvrect.y) 87 out->flags |= ALIAS_TOP_CLIP; 88 if (out->v[0] > r_refdef.aliasvrectright) 89 out->flags |= ALIAS_RIGHT_CLIP; 90 if (out->v[1] > r_refdef.aliasvrectbottom) 91 out->flags |= ALIAS_BOTTOM_CLIP; 92 } 93 94 95 #if !id386 96 97 void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) 98 { 99 float scale; 100 int i; 101 102 if (pfv0->v[1] >= pfv1->v[1]) 103 { 104 scale = (float)(r_refdef.aliasvrect.x - pfv0->v[0]) / 105 (pfv1->v[0] - pfv0->v[0]); 106 for (i=0 ; i<6 ; i++) 107 out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; 108 } 109 else 110 { 111 scale = (float)(r_refdef.aliasvrect.x - pfv1->v[0]) / 112 (pfv0->v[0] - pfv1->v[0]); 113 for (i=0 ; i<6 ; i++) 114 out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; 115 } 116 } 117 118 119 void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, 120 finalvert_t *out) 121 { 122 float scale; 123 int i; 124 125 if (pfv0->v[1] >= pfv1->v[1]) 126 { 127 scale = (float)(r_refdef.aliasvrectright - pfv0->v[0]) / 128 (pfv1->v[0] - pfv0->v[0]); 129 for (i=0 ; i<6 ; i++) 130 out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; 131 } 132 else 133 { 134 scale = (float)(r_refdef.aliasvrectright - pfv1->v[0]) / 135 (pfv0->v[0] - pfv1->v[0]); 136 for (i=0 ; i<6 ; i++) 137 out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; 138 } 139 } 140 141 142 void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) 143 { 144 float scale; 145 int i; 146 147 if (pfv0->v[1] >= pfv1->v[1]) 148 { 149 scale = (float)(r_refdef.aliasvrect.y - pfv0->v[1]) / 150 (pfv1->v[1] - pfv0->v[1]); 151 for (i=0 ; i<6 ; i++) 152 out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; 153 } 154 else 155 { 156 scale = (float)(r_refdef.aliasvrect.y - pfv1->v[1]) / 157 (pfv0->v[1] - pfv1->v[1]); 158 for (i=0 ; i<6 ; i++) 159 out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; 160 } 161 } 162 163 164 void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, 165 finalvert_t *out) 166 { 167 float scale; 168 int i; 169 170 if (pfv0->v[1] >= pfv1->v[1]) 171 { 172 scale = (float)(r_refdef.aliasvrectbottom - pfv0->v[1]) / 173 (pfv1->v[1] - pfv0->v[1]); 174 175 for (i=0 ; i<6 ; i++) 176 out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; 177 } 178 else 179 { 180 scale = (float)(r_refdef.aliasvrectbottom - pfv1->v[1]) / 181 (pfv0->v[1] - pfv1->v[1]); 182 183 for (i=0 ; i<6 ; i++) 184 out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; 185 } 186 } 187 188 #endif 189 190 191 int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count, 192 void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) ) 193 { 194 int i,j,k; 195 int flags, oldflags; 196 197 j = count-1; 198 k = 0; 199 for (i=0 ; i<count ; j = i, i++) 200 { 201 oldflags = in[j].flags & flag; 202 flags = in[i].flags & flag; 203 204 if (flags && oldflags) 205 continue; 206 if (oldflags ^ flags) 207 { 208 clip (&in[j], &in[i], &out[k]); 209 out[k].flags = 0; 210 if (out[k].v[0] < r_refdef.aliasvrect.x) 211 out[k].flags |= ALIAS_LEFT_CLIP; 212 if (out[k].v[1] < r_refdef.aliasvrect.y) 213 out[k].flags |= ALIAS_TOP_CLIP; 214 if (out[k].v[0] > r_refdef.aliasvrectright) 215 out[k].flags |= ALIAS_RIGHT_CLIP; 216 if (out[k].v[1] > r_refdef.aliasvrectbottom) 217 out[k].flags |= ALIAS_BOTTOM_CLIP; 218 k++; 219 } 220 if (!flags) 221 { 222 out[k] = in[i]; 223 k++; 224 } 225 } 226 227 return k; 228 } 229 230 231 /* 232 ================ 233 R_AliasClipTriangle 234 ================ 235 */ 236 void R_AliasClipTriangle (mtriangle_t *ptri) 237 { 238 int i, k, pingpong; 239 mtriangle_t mtri; 240 unsigned clipflags; 241 242 // copy vertexes and fix seam texture coordinates 243 if (ptri->facesfront) 244 { 245 fv[0][0] = pfinalverts[ptri->vertindex[0]]; 246 fv[0][1] = pfinalverts[ptri->vertindex[1]]; 247 fv[0][2] = pfinalverts[ptri->vertindex[2]]; 248 } 249 else 250 { 251 for (i=0 ; i<3 ; i++) 252 { 253 fv[0][i] = pfinalverts[ptri->vertindex[i]]; 254 255 if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM) ) 256 fv[0][i].v[2] += r_affinetridesc.seamfixupX16; 257 } 258 } 259 260 // clip 261 clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags; 262 263 if (clipflags & ALIAS_Z_CLIP) 264 { 265 for (i=0 ; i<3 ; i++) 266 av[i] = pauxverts[ptri->vertindex[i]]; 267 268 k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z); 269 if (k == 0) 270 return; 271 272 pingpong = 1; 273 clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags; 274 } 275 else 276 { 277 pingpong = 0; 278 k = 3; 279 } 280 281 if (clipflags & ALIAS_LEFT_CLIP) 282 { 283 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], 284 ALIAS_LEFT_CLIP, k, R_Alias_clip_left); 285 if (k == 0) 286 return; 287 288 pingpong ^= 1; 289 } 290 291 if (clipflags & ALIAS_RIGHT_CLIP) 292 { 293 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], 294 ALIAS_RIGHT_CLIP, k, R_Alias_clip_right); 295 if (k == 0) 296 return; 297 298 pingpong ^= 1; 299 } 300 301 if (clipflags & ALIAS_BOTTOM_CLIP) 302 { 303 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], 304 ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom); 305 if (k == 0) 306 return; 307 308 pingpong ^= 1; 309 } 310 311 if (clipflags & ALIAS_TOP_CLIP) 312 { 313 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], 314 ALIAS_TOP_CLIP, k, R_Alias_clip_top); 315 if (k == 0) 316 return; 317 318 pingpong ^= 1; 319 } 320 321 for (i=0 ; i<k ; i++) 322 { 323 if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x) 324 fv[pingpong][i].v[0] = r_refdef.aliasvrect.x; 325 else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright) 326 fv[pingpong][i].v[0] = r_refdef.aliasvrectright; 327 328 if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y) 329 fv[pingpong][i].v[1] = r_refdef.aliasvrect.y; 330 else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom) 331 fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom; 332 333 fv[pingpong][i].flags = 0; 334 } 335 336 // draw triangles 337 mtri.facesfront = ptri->facesfront; 338 r_affinetridesc.ptriangles = &mtri; 339 r_affinetridesc.pfinalverts = fv[pingpong]; 340 341 // FIXME: do all at once as trifan? 342 mtri.vertindex[0] = 0; 343 for (i=1 ; i<k-1 ; i++) 344 { 345 mtri.vertindex[1] = i; 346 mtri.vertindex[2] = i+1; 347 D_PolysetDraw (); 348 } 349 } 350 351