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