| 1 | /* |
| 2 | * Glide64 - Glide video plugin for Nintendo 64 emulators. |
| 3 | * Copyright (c) 2002 Dave2001 |
| 4 | * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | * any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with this program; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ |
| 20 | |
| 21 | //**************************************************************** |
| 22 | // |
| 23 | // Glide64 - Glide Plugin for Nintendo 64 emulators |
| 24 | // Project started on December 29th, 2001 |
| 25 | // |
| 26 | // Authors: |
| 27 | // Dave2001, original author, founded the project in 2001, left it in 2002 |
| 28 | // Gugaman, joined the project in 2002, left it in 2002 |
| 29 | // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 |
| 30 | // Hiroshi 'KoolSmoky' Morii, joined the project in 2007 |
| 31 | // |
| 32 | //**************************************************************** |
| 33 | // |
| 34 | // To modify Glide64: |
| 35 | // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. |
| 36 | // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. |
| 37 | // |
| 38 | //**************************************************************** |
| 39 | |
| 40 | #include <math.h> |
| 41 | #include "Gfx_1.3.h" |
| 42 | #include "Util.h" |
| 43 | #include "Combine.h" |
| 44 | #include "3dmath.h" |
| 45 | #include "Debugger.h" |
| 46 | #include "TexCache.h" |
| 47 | #include "DepthBufferRender.h" |
| 48 | |
| 49 | #define Vj rdp.vtxbuf2[j] |
| 50 | #define Vi rdp.vtxbuf2[i] |
| 51 | |
| 52 | VERTEX *vtx_list1[32]; // vertex indexing |
| 53 | VERTEX *vtx_list2[32]; |
| 54 | |
| 55 | // |
| 56 | // util_init - initialize data for the functions in this file |
| 57 | // |
| 58 | |
| 59 | void util_init () |
| 60 | { |
| 61 | for (int i=0; i<32; i++) |
| 62 | { |
| 63 | vtx_list1[i] = &rdp.vtx1[i]; |
| 64 | vtx_list2[i] = &rdp.vtx2[i]; |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | static wxUint32 u_cull_mode = 0; |
| 69 | |
| 70 | //software backface culling. Gonetz |
| 71 | // mega modifications by Dave2001 |
| 72 | int cull_tri(VERTEX **v) // type changed to VERTEX** [Dave2001] |
| 73 | { |
| 74 | int i; |
| 75 | |
| 76 | if (v[0]->scr_off & v[1]->scr_off & v[2]->scr_off) |
| 77 | { |
| 78 | LRDP (" clipped\n"); |
| 79 | return TRUE; |
| 80 | } |
| 81 | |
| 82 | // Triangle can't be culled, if it need clipping |
| 83 | int draw = FALSE; |
| 84 | |
| 85 | for (i=0; i<3; i++) |
| 86 | { |
| 87 | if (!v[i]->screen_translated) |
| 88 | { |
| 89 | v[i]->sx = rdp.view_trans[0] + v[i]->x_w * rdp.view_scale[0] + rdp.offset_x; |
| 90 | v[i]->sy = rdp.view_trans[1] + v[i]->y_w * rdp.view_scale[1] + rdp.offset_y; |
| 91 | v[i]->sz = rdp.view_trans[2] + v[i]->z_w * rdp.view_scale[2]; |
| 92 | v[i]->screen_translated = 1; |
| 93 | } |
| 94 | if (v[i]->w < 0.01f) //need clip_z. can't be culled now |
| 95 | draw = 1; |
| 96 | } |
| 97 | |
| 98 | u_cull_mode = (rdp.flags & CULLMASK); |
| 99 | if (draw || u_cull_mode == 0 || u_cull_mode == CULLMASK) //no culling set |
| 100 | { |
| 101 | u_cull_mode >>= CULLSHIFT; |
| 102 | return FALSE; |
| 103 | } |
| 104 | |
| 105 | #define SW_CULLING |
| 106 | #ifdef SW_CULLING |
| 107 | #if 1 // H.Morii - faster float comparisons with zero area check added |
| 108 | |
| 109 | const float x1 = v[0]->sx - v[1]->sx; |
| 110 | const float y1 = v[0]->sy - v[1]->sy; |
| 111 | const float x2 = v[2]->sx - v[1]->sx; |
| 112 | const float y2 = v[2]->sy - v[1]->sy; |
| 113 | const float area = y1*x2 - x1*y2; |
| 114 | |
| 115 | const int iarea = *(int*)&area; |
| 116 | const unsigned int mode = (u_cull_mode << 19UL); |
| 117 | u_cull_mode >>= CULLSHIFT; |
| 118 | |
| 119 | if ((iarea & 0x7FFFFFFF) == 0) |
| 120 | { |
| 121 | LRDP (" zero area triangles\n"); |
| 122 | return TRUE; |
| 123 | } |
| 124 | |
| 125 | if ((rdp.flags & CULLMASK) && ((int)(iarea ^ mode)) >= 0) |
| 126 | { |
| 127 | LRDP (" culled\n"); |
| 128 | return TRUE; |
| 129 | } |
| 130 | #else |
| 131 | |
| 132 | float x1 = v[0]->sx - v[1]->sx; |
| 133 | float y1 = v[0]->sy - v[1]->sy; |
| 134 | float x2 = v[2]->sx - v[1]->sx; |
| 135 | float y2 = v[2]->sy - v[1]->sy; |
| 136 | |
| 137 | u_cull_mode >>= CULLSHIFT; |
| 138 | switch (u_cull_mode) |
| 139 | { |
| 140 | case 1: // cull front |
| 141 | // if ((x1*y2 - y1*x2) < 0.0f) //counter-clockwise, positive |
| 142 | if ((y1*x2-x1*y2) < 0.0f) //counter-clockwise, positive |
| 143 | { |
| 144 | LRDP (" culled!\n"); |
| 145 | return TRUE; |
| 146 | } |
| 147 | return FALSE; |
| 148 | case 2: // cull back |
| 149 | // if ((x1*y2 - y1*x2) >= 0.0f) //clockwise, negative |
| 150 | if ((y1*x2-x1*y2) >= 0.0f) //clockwise, negative |
| 151 | { |
| 152 | LRDP (" culled!\n"); |
| 153 | return TRUE; |
| 154 | } |
| 155 | return FALSE; |
| 156 | } |
| 157 | #endif |
| 158 | #endif |
| 159 | |
| 160 | return FALSE; |
| 161 | } |
| 162 | |
| 163 | |
| 164 | void apply_shade_mods (VERTEX *v) |
| 165 | { |
| 166 | float col[4]; |
| 167 | wxUint32 mod; |
| 168 | memcpy (col, rdp.col, 16); |
| 169 | |
| 170 | if (rdp.cmb_flags) |
| 171 | { |
| 172 | if (v->shade_mod == 0) |
| 173 | v->color_backup = *(wxUint32*)(&(v->b)); |
| 174 | else |
| 175 | *(wxUint32*)(&(v->b)) = v->color_backup; |
| 176 | mod = rdp.cmb_flags; |
| 177 | if (mod & CMB_SET) |
| 178 | { |
| 179 | if (col[0] > 1.0f) col[0] = 1.0f; |
| 180 | if (col[1] > 1.0f) col[1] = 1.0f; |
| 181 | if (col[2] > 1.0f) col[2] = 1.0f; |
| 182 | if (col[0] < 0.0f) col[0] = 0.0f; |
| 183 | if (col[1] < 0.0f) col[1] = 0.0f; |
| 184 | if (col[2] < 0.0f) col[2] = 0.0f; |
| 185 | v->r = (wxUint8)(255.0f * col[0]); |
| 186 | v->g = (wxUint8)(255.0f * col[1]); |
| 187 | v->b = (wxUint8)(255.0f * col[2]); |
| 188 | } |
| 189 | if (mod & CMB_A_SET) |
| 190 | { |
| 191 | if (col[3] > 1.0f) col[3] = 1.0f; |
| 192 | if (col[3] < 0.0f) col[3] = 0.0f; |
| 193 | v->a = (wxUint8)(255.0f * col[3]); |
| 194 | } |
| 195 | if (mod & CMB_SETSHADE_SHADEALPHA) |
| 196 | { |
| 197 | v->r = v->g = v->b = v->a; |
| 198 | } |
| 199 | if (mod & CMB_MULT_OWN_ALPHA) |
| 200 | { |
| 201 | float percent = v->a / 255.0f; |
| 202 | v->r = (wxUint8)(v->r * percent); |
| 203 | v->g = (wxUint8)(v->g * percent); |
| 204 | v->b = (wxUint8)(v->b * percent); |
| 205 | } |
| 206 | if (mod & CMB_MULT) |
| 207 | { |
| 208 | if (col[0] > 1.0f) col[0] = 1.0f; |
| 209 | if (col[1] > 1.0f) col[1] = 1.0f; |
| 210 | if (col[2] > 1.0f) col[2] = 1.0f; |
| 211 | if (col[0] < 0.0f) col[0] = 0.0f; |
| 212 | if (col[1] < 0.0f) col[1] = 0.0f; |
| 213 | if (col[2] < 0.0f) col[2] = 0.0f; |
| 214 | v->r = (wxUint8)(v->r * col[0]); |
| 215 | v->g = (wxUint8)(v->g * col[1]); |
| 216 | v->b = (wxUint8)(v->b * col[2]); |
| 217 | } |
| 218 | if (mod & CMB_A_MULT) |
| 219 | { |
| 220 | if (col[3] > 1.0f) col[3] = 1.0f; |
| 221 | if (col[3] < 0.0f) col[3] = 0.0f; |
| 222 | v->a = (wxUint8)(v->a * col[3]); |
| 223 | } |
| 224 | if (mod & CMB_SUB) |
| 225 | { |
| 226 | int r = v->r - (int)(255.0f * rdp.coladd[0]); |
| 227 | int g = v->g - (int)(255.0f * rdp.coladd[1]); |
| 228 | int b = v->b - (int)(255.0f * rdp.coladd[2]); |
| 229 | if (r < 0) r = 0; |
| 230 | if (g < 0) g = 0; |
| 231 | if (b < 0) b = 0; |
| 232 | v->r = (wxUint8)r; |
| 233 | v->g = (wxUint8)g; |
| 234 | v->b = (wxUint8)b; |
| 235 | } |
| 236 | if (mod & CMB_A_SUB) |
| 237 | { |
| 238 | int a = v->a - (int)(255.0f * rdp.coladd[3]); |
| 239 | if (a < 0) a = 0; |
| 240 | v->a = (wxUint8)a; |
| 241 | } |
| 242 | if (mod & CMB_ADD) |
| 243 | { |
| 244 | int r = v->r + (int)(255.0f * rdp.coladd[0]); |
| 245 | int g = v->g + (int)(255.0f * rdp.coladd[1]); |
| 246 | int b = v->b + (int)(255.0f * rdp.coladd[2]); |
| 247 | if (r > 255) r = 255; |
| 248 | if (g > 255) g = 255; |
| 249 | if (b > 255) b = 255; |
| 250 | v->r = (wxUint8)r; |
| 251 | v->g = (wxUint8)g; |
| 252 | v->b = (wxUint8)b; |
| 253 | } |
| 254 | if (mod & CMB_A_ADD) |
| 255 | { |
| 256 | int a = v->a + (int)(255.0f * rdp.coladd[3]); |
| 257 | if (a > 255) a = 255; |
| 258 | v->a = (wxUint8)a; |
| 259 | } |
| 260 | if (mod & CMB_COL_SUB_OWN) |
| 261 | { |
| 262 | int r = (wxUint8)(255.0f * rdp.coladd[0]) - v->r; |
| 263 | int g = (wxUint8)(255.0f * rdp.coladd[1]) - v->g; |
| 264 | int b = (wxUint8)(255.0f * rdp.coladd[2]) - v->b; |
| 265 | if (r < 0) r = 0; |
| 266 | if (g < 0) g = 0; |
| 267 | if (b < 0) b = 0; |
| 268 | v->r = (wxUint8)r; |
| 269 | v->g = (wxUint8)g; |
| 270 | v->b = (wxUint8)b; |
| 271 | } |
| 272 | v->shade_mod = cmb.shade_mod_hash; |
| 273 | } |
| 274 | if (rdp.cmb_flags_2 & CMB_INTER) |
| 275 | { |
| 276 | v->r = (wxUint8)(rdp.col_2[0] * rdp.shade_factor * 255.0f + v->r * (1.0f - rdp.shade_factor)); |
| 277 | v->g = (wxUint8)(rdp.col_2[1] * rdp.shade_factor * 255.0f + v->g * (1.0f - rdp.shade_factor)); |
| 278 | v->b = (wxUint8)(rdp.col_2[2] * rdp.shade_factor * 255.0f + v->b * (1.0f - rdp.shade_factor)); |
| 279 | v->shade_mod = cmb.shade_mod_hash; |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | static int dzdx = 0; |
| 284 | static int deltaZ = 0; |
| 285 | VERTEX **org_vtx; |
| 286 | |
| 287 | void draw_tri (VERTEX **vtx, wxUint16 linew) |
| 288 | { |
| 289 | deltaZ = dzdx = 0; |
| 290 | if (linew == 0 && (fb_depth_render_enabled || (rdp.rm & 0xC00) == 0xC00)) |
| 291 | { |
| 292 | float X0 = vtx[0]->sx / rdp.scale_x; |
| 293 | float Y0 = vtx[0]->sy / rdp.scale_y; |
| 294 | float X1 = vtx[1]->sx / rdp.scale_x; |
| 295 | float Y1 = vtx[1]->sy / rdp.scale_y; |
| 296 | float X2 = vtx[2]->sx / rdp.scale_x; |
| 297 | float Y2 = vtx[2]->sy / rdp.scale_y; |
| 298 | float diffy_02 = Y0 - Y2; |
| 299 | float diffy_12 = Y1 - Y2; |
| 300 | float diffx_02 = X0 - X2; |
| 301 | float diffx_12 = X1 - X2; |
| 302 | |
| 303 | float denom = (diffx_02 * diffy_12 - diffx_12 * diffy_02); |
| 304 | if(denom*denom > 0.0f) |
| 305 | { |
| 306 | float diffz_02 = vtx[0]->sz - vtx[2]->sz; |
| 307 | float diffz_12 = vtx[1]->sz - vtx[2]->sz; |
| 308 | float fdzdx = (diffz_02 * diffy_12 - diffz_12 * diffy_02) / denom; |
| 309 | if ((rdp.rm & 0xC00) == 0xC00) { |
| 310 | // Calculate deltaZ per polygon for Decal z-mode |
| 311 | float fdzdy = (diffz_02 * diffx_12 - diffz_12 * diffx_02) / denom; |
| 312 | float fdz = fabs(fdzdx) + fabs(fdzdy); |
| 313 | if ((settings.hacks & hack_Zelda) && (rdp.rm & 0x800)) |
| 314 | fdz *= 4.0f; // Decal mode in Zelda sometimes needs mutiplied deltaZ to work correct, e.g. roads |
| 315 | deltaZ = max(8, (int)fdz); |
| 316 | } |
| 317 | dzdx = (int)(fdzdx * 65536.0); |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | org_vtx = vtx; |
| 322 | |
| 323 | for (int i=0; i<3; i++) |
| 324 | { |
| 325 | VERTEX *v = vtx[i]; |
| 326 | |
| 327 | if (v->uv_calculated != rdp.tex_ctr) |
| 328 | { |
| 329 | #ifdef EXTREME_LOGGING |
| 330 | FRDP(" * CALCULATING VERTEX U/V: %d\n", v->number); |
| 331 | #endif |
| 332 | v->uv_calculated = rdp.tex_ctr; |
| 333 | |
| 334 | if (!(rdp.geom_mode & 0x00020000)) |
| 335 | { |
| 336 | if (!(rdp.geom_mode & 0x00000200)) |
| 337 | { |
| 338 | if (rdp.geom_mode & 0x00000004) // flat shading |
| 339 | { |
| 340 | int flag = min(2, (rdp.cmd1 >> 24) & 3); |
| 341 | v->a = vtx[flag]->a; |
| 342 | v->b = vtx[flag]->b; |
| 343 | v->g = vtx[flag]->g; |
| 344 | v->r = vtx[flag]->r; |
| 345 | #ifdef EXTREME_LOGGING |
| 346 | FRDP(" * Flat shaded, flag%d - r: %d, g: %d, b: %d, a: %d\n", flag, v->r, v->g, v->b, v->a); |
| 347 | #endif |
| 348 | } |
| 349 | else // prim color |
| 350 | { |
| 351 | #ifdef EXTREME_LOGGING |
| 352 | FRDP(" * Prim shaded %08lx\n", rdp.prim_color); |
| 353 | #endif |
| 354 | v->a = (wxUint8)(rdp.prim_color & 0xFF); |
| 355 | v->b = (wxUint8)((rdp.prim_color >> 8) & 0xFF); |
| 356 | v->g = (wxUint8)((rdp.prim_color >> 16) & 0xFF); |
| 357 | v->r = (wxUint8)((rdp.prim_color >> 24) & 0xFF); |
| 358 | } |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | // Fix texture coordinates |
| 363 | if (!v->uv_scaled) |
| 364 | { |
| 365 | v->ou *= rdp.tiles[rdp.cur_tile].s_scale; |
| 366 | v->ov *= rdp.tiles[rdp.cur_tile].t_scale; |
| 367 | v->uv_scaled = 1; |
| 368 | if (!rdp.Persp_en) |
| 369 | { |
| 370 | // v->oow = v->w = 1.0f; |
| 371 | v->ou *= 0.5f; |
| 372 | v->ov *= 0.5f; |
| 373 | } |
| 374 | } |
| 375 | v->u1 = v->u0 = v->ou; |
| 376 | v->v1 = v->v0 = v->ov; |
| 377 | |
| 378 | if (rdp.tex >= 1 && rdp.cur_cache[0]) |
| 379 | { |
| 380 | if (rdp.aTBuffTex[0]) |
| 381 | { |
| 382 | v->u0 += rdp.aTBuffTex[0]->u_shift + rdp.aTBuffTex[0]->tile_uls; |
| 383 | v->v0 += rdp.aTBuffTex[0]->v_shift + rdp.aTBuffTex[0]->tile_ult; |
| 384 | } |
| 385 | |
| 386 | if (rdp.tiles[rdp.cur_tile].shift_s) |
| 387 | { |
| 388 | if (rdp.tiles[rdp.cur_tile].shift_s > 10) |
| 389 | v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s)); |
| 390 | else |
| 391 | v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s); |
| 392 | } |
| 393 | if (rdp.tiles[rdp.cur_tile].shift_t) |
| 394 | { |
| 395 | if (rdp.tiles[rdp.cur_tile].shift_t > 10) |
| 396 | v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t)); |
| 397 | else |
| 398 | v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t); |
| 399 | } |
| 400 | |
| 401 | if (rdp.aTBuffTex[0]) |
| 402 | { |
| 403 | if (rdp.aTBuffTex[0]->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s) |
| 404 | v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s; |
| 405 | if (rdp.aTBuffTex[0]->tile_ult != (int)rdp.tiles[rdp.cur_tile].f_ul_t || (settings.hacks&hack_Megaman)) |
| 406 | v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; //required for megaman (boss special attack) |
| 407 | v->u0 *= rdp.aTBuffTex[0]->u_scale; |
| 408 | v->v0 *= rdp.aTBuffTex[0]->v_scale; |
| 409 | #ifdef EXTREME_LOGGING |
| 410 | FRDP("tbuff_tex t0: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0); |
| 411 | #endif |
| 412 | } |
| 413 | else |
| 414 | { |
| 415 | v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s; |
| 416 | v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; |
| 417 | v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0; |
| 418 | v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0; |
| 419 | } |
| 420 | v->u0_w = v->u0 / v->w; |
| 421 | v->v0_w = v->v0 / v->w; |
| 422 | } |
| 423 | |
| 424 | if (rdp.tex >= 2 && rdp.cur_cache[1]) |
| 425 | { |
| 426 | if (rdp.aTBuffTex[1]) |
| 427 | { |
| 428 | v->u1 += rdp.aTBuffTex[1]->u_shift + rdp.aTBuffTex[1]->tile_uls; |
| 429 | v->v1 += rdp.aTBuffTex[1]->v_shift + rdp.aTBuffTex[1]->tile_ult; |
| 430 | } |
| 431 | if (rdp.tiles[rdp.cur_tile+1].shift_s) |
| 432 | { |
| 433 | if (rdp.tiles[rdp.cur_tile+1].shift_s > 10) |
| 434 | v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s)); |
| 435 | else |
| 436 | v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s); |
| 437 | } |
| 438 | if (rdp.tiles[rdp.cur_tile+1].shift_t) |
| 439 | { |
| 440 | if (rdp.tiles[rdp.cur_tile+1].shift_t > 10) |
| 441 | v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t)); |
| 442 | else |
| 443 | v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t); |
| 444 | } |
| 445 | |
| 446 | if (rdp.aTBuffTex[1]) |
| 447 | { |
| 448 | if (rdp.aTBuffTex[1]->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s) |
| 449 | v->u1 -= rdp.tiles[rdp.cur_tile].f_ul_s; |
| 450 | v->u1 *= rdp.aTBuffTex[1]->u_scale; |
| 451 | v->v1 *= rdp.aTBuffTex[1]->v_scale; |
| 452 | #ifdef EXTREME_LOGGING |
| 453 | FRDP("tbuff_tex t1: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u1, v->v1); |
| 454 | #endif |
| 455 | } |
| 456 | else |
| 457 | { |
| 458 | v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s; |
| 459 | v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t; |
| 460 | v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1; |
| 461 | v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1; |
| 462 | } |
| 463 | |
| 464 | v->u1_w = v->u1 / v->w; |
| 465 | v->v1_w = v->v1 / v->w; |
| 466 | } |
| 467 | // FRDP(" * CALCULATING VERTEX U/V: %d u0: %f, v0: %f, u1: %f, v1: %f\n", v->number, v->u0, v->v0, v->u1, v->v1); |
| 468 | } |
| 469 | #ifdef EXTREME_LOGGING |
| 470 | FRDP("draw_tri. v[%d] ou=%f, ov = %f\n", i, v->ou, v->ov); |
| 471 | #endif |
| 472 | if (v->shade_mod != cmb.shade_mod_hash) |
| 473 | apply_shade_mods (v); |
| 474 | } //for |
| 475 | |
| 476 | rdp.clip = 0; |
| 477 | |
| 478 | if ((vtx[0]->scr_off & 16) || |
| 479 | (vtx[1]->scr_off & 16) || |
| 480 | (vtx[2]->scr_off & 16)) |
| 481 | rdp.clip |= CLIP_WMIN; |
| 482 | |
| 483 | vtx[0]->not_zclipped = vtx[1]->not_zclipped = vtx[2]->not_zclipped = 1; |
| 484 | |
| 485 | if (rdp.cur_cache[0] && (rdp.tex & 1) && (rdp.cur_cache[0]->splits > 1) && !rdp.aTBuffTex[0] && !rdp.clip) |
| 486 | { |
| 487 | int index,i,j, min_256,max_256, cur_256,left_256,right_256; |
| 488 | float percent; |
| 489 | |
| 490 | min_256 = min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line |
| 491 | min_256 = min(min_256,(int)vtx[2]->u0) >> 8; // or it will be calculated twice |
| 492 | |
| 493 | max_256 = max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference |
| 494 | max_256 = max(max_256,(int)vtx[2]->u0) >> 8; // anyway :P |
| 495 | |
| 496 | for (cur_256=min_256; cur_256<=max_256; cur_256++) |
| 497 | { |
| 498 | left_256 = cur_256 << 8; |
| 499 | right_256 = (cur_256+1) << 8; |
| 500 | |
| 501 | // Set vertex buffers |
| 502 | rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1 |
| 503 | rdp.vtxbuf2 = rdp.vtx2; |
| 504 | rdp.vtx_buffer = 0; |
| 505 | rdp.n_global = 3; |
| 506 | index = 0; |
| 507 | |
| 508 | // ** Left plane ** |
| 509 | for (i=0; i<3; i++) |
| 510 | { |
| 511 | j = i+1; |
| 512 | if (j == 3) j = 0; |
| 513 | |
| 514 | VERTEX *v1 = vtx[i]; |
| 515 | VERTEX *v2 = vtx[j]; |
| 516 | |
| 517 | if (v1->u0 >= left_256) |
| 518 | { |
| 519 | if (v2->u0 >= left_256) // Both are in, save the last one |
| 520 | { |
| 521 | rdp.vtxbuf[index] = *v2; |
| 522 | rdp.vtxbuf[index].u0 -= left_256; |
| 523 | rdp.vtxbuf[index++].v0 += cur_256 * rdp.cur_cache[0]->splitheight; |
| 524 | } |
| 525 | else // First is in, second is out, save intersection |
| 526 | { |
| 527 | percent = (left_256 - v1->u0) / (v2->u0 - v1->u0); |
| 528 | rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent; |
| 529 | rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent; |
| 530 | rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent; |
| 531 | rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent; |
| 532 | rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent; |
| 533 | rdp.vtxbuf[index].u0 = 0.5f; |
| 534 | rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent + |
| 535 | cur_256 * rdp.cur_cache[0]->splitheight; |
| 536 | rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent; |
| 537 | rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent; |
| 538 | rdp.vtxbuf[index].b = (wxUint8)(v1->b + (v2->b - v1->b) * percent); |
| 539 | rdp.vtxbuf[index].g = (wxUint8)(v1->g + (v2->g - v1->g) * percent); |
| 540 | rdp.vtxbuf[index].r = (wxUint8)(v1->r + (v2->r - v1->r) * percent); |
| 541 | rdp.vtxbuf[index++].a = (wxUint8)(v1->a + (v2->a - v1->a) * percent); |
| 542 | } |
| 543 | } |
| 544 | else |
| 545 | { |
| 546 | //if (v2->u0 < left_256) // Both are out, save nothing |
| 547 | if (v2->u0 >= left_256) // First is out, second is in, save intersection & in point |
| 548 | { |
| 549 | percent = (left_256 - v2->u0) / (v1->u0 - v2->u0); |
| 550 | rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent; |
| 551 | rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent; |
| 552 | rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent; |
| 553 | rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent; |
| 554 | rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent; |
| 555 | rdp.vtxbuf[index].u0 = 0.5f; |
| 556 | rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent + |
| 557 | cur_256 * rdp.cur_cache[0]->splitheight; |
| 558 | rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent; |
| 559 | rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent; |
| 560 | rdp.vtxbuf[index].b = (wxUint8)(v2->b + (v1->b - v2->b) * percent); |
| 561 | rdp.vtxbuf[index].g = (wxUint8)(v2->g + (v1->g - v2->g) * percent); |
| 562 | rdp.vtxbuf[index].r = (wxUint8)(v2->r + (v1->r - v2->r) * percent); |
| 563 | rdp.vtxbuf[index++].a = (wxUint8)(v2->a + (v1->a - v2->a) * percent); |
| 564 | |
| 565 | // Save the in point |
| 566 | rdp.vtxbuf[index] = *v2; |
| 567 | rdp.vtxbuf[index].u0 -= left_256; |
| 568 | rdp.vtxbuf[index++].v0 += cur_256 * rdp.cur_cache[0]->splitheight; |
| 569 | } |
| 570 | } |
| 571 | } |
| 572 | rdp.n_global = index; |
| 573 | |
| 574 | rdp.vtxbuf = rdp.vtx2; // now vtx1 holds the value, & vtx2 is the destination |
| 575 | rdp.vtxbuf2 = rdp.vtx1; |
| 576 | rdp.vtx_buffer ^= 1; |
| 577 | index = 0; |
| 578 | |
| 579 | for (i=0; i<rdp.n_global; i++) |
| 580 | { |
| 581 | j = i+1; |
| 582 | if (j == rdp.n_global) j = 0; |
| 583 | |
| 584 | VERTEX *v1 = &rdp.vtxbuf2[i]; |
| 585 | VERTEX *v2 = &rdp.vtxbuf2[j]; |
| 586 | |
| 587 | // ** Right plane ** |
| 588 | if (v1->u0 <= right_256) |
| 589 | { |
| 590 | if (v2->u0 <= right_256) // Both are in, save the last one |
| 591 | { |
| 592 | rdp.vtxbuf[index] = *v2; |
| 593 | rdp.vtxbuf[index++].not_zclipped = 0; |
| 594 | } |
| 595 | else // First is in, second is out, save intersection |
| 596 | { |
| 597 | percent = (right_256 - v1->u0) / (v2->u0 - v1->u0); |
| 598 | rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent; |
| 599 | rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent; |
| 600 | rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent; |
| 601 | rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent; |
| 602 | rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent; |
| 603 | rdp.vtxbuf[index].u0 = 255.5f; |
| 604 | rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent; |
| 605 | rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent; |
| 606 | rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent; |
| 607 | rdp.vtxbuf[index].b = (wxUint8)(v1->b + (v2->b - v1->b) * percent); |
| 608 | rdp.vtxbuf[index].g = (wxUint8)(v1->g + (v2->g - v1->g) * percent); |
| 609 | rdp.vtxbuf[index].r = (wxUint8)(v1->r + (v2->r - v1->r) * percent); |
| 610 | rdp.vtxbuf[index].a = (wxUint8)(v1->a + (v2->a - v1->a) * percent); |
| 611 | rdp.vtxbuf[index++].not_zclipped = 0; |
| 612 | } |
| 613 | } |
| 614 | else |
| 615 | { |
| 616 | //if (v2->u0 > 256.0f) // Both are out, save nothing |
| 617 | if (v2->u0 <= right_256) // First is out, second is in, save intersection & in point |
| 618 | { |
| 619 | percent = (right_256 - v2->u0) / (v1->u0 - v2->u0); |
| 620 | rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent; |
| 621 | rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent; |
| 622 | rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent; |
| 623 | rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent; |
| 624 | rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent; |
| 625 | rdp.vtxbuf[index].u0 = 255.5f; |
| 626 | rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent; |
| 627 | rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent; |
| 628 | rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent; |
| 629 | rdp.vtxbuf[index].b = (wxUint8)(v2->b + (v1->b - v2->b) * percent); |
| 630 | rdp.vtxbuf[index].g = (wxUint8)(v2->g + (v1->g - v2->g) * percent); |
| 631 | rdp.vtxbuf[index].r = (wxUint8)(v2->r + (v1->r - v2->r) * percent); |
| 632 | rdp.vtxbuf[index].a = (wxUint8)(v2->a + (v1->a - v2->a) * percent); |
| 633 | rdp.vtxbuf[index++].not_zclipped = 0; |
| 634 | |
| 635 | // Save the in point |
| 636 | rdp.vtxbuf[index] = *v2; |
| 637 | rdp.vtxbuf[index++].not_zclipped = 0; |
| 638 | } |
| 639 | } |
| 640 | } |
| 641 | rdp.n_global = index; |
| 642 | |
| 643 | do_triangle_stuff (linew, TRUE); |
| 644 | } |
| 645 | } |
| 646 | else |
| 647 | { |
| 648 | // Set vertex buffers |
| 649 | rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1 |
| 650 | rdp.vtxbuf2 = rdp.vtx2; |
| 651 | rdp.vtx_buffer = 0; |
| 652 | rdp.n_global = 3; |
| 653 | |
| 654 | rdp.vtxbuf[0] = *vtx[0]; |
| 655 | rdp.vtxbuf[0].number = 1; |
| 656 | rdp.vtxbuf[1] = *vtx[1]; |
| 657 | rdp.vtxbuf[1].number = 2; |
| 658 | rdp.vtxbuf[2] = *vtx[2]; |
| 659 | rdp.vtxbuf[2].number = 4; |
| 660 | |
| 661 | do_triangle_stuff (linew, FALSE); |
| 662 | } |
| 663 | } |
| 664 | |
| 665 | #define interp2p(a, b, r) (a + (b - a) * r) |
| 666 | |
| 667 | //* |
| 668 | static void InterpolateColors(VERTEX & va, VERTEX & vb, VERTEX & res, float percent) |
| 669 | { |
| 670 | res.b = (wxUint8)interp2p(va.b, vb.b, percent); |
| 671 | res.g = (wxUint8)interp2p(va.g, vb.g, percent);; |
| 672 | res.r = (wxUint8)interp2p(va.r, vb.r, percent);; |
| 673 | res.a = (wxUint8)interp2p(va.a, vb.a, percent);; |
| 674 | res.f = interp2p(va.f, vb.f, percent);; |
| 675 | } |
| 676 | //*/ |
| 677 | // |
| 678 | // clip_w - clips aint the z-axis |
| 679 | // |
| 680 | static void clip_w (int interpolate_colors) |
| 681 | { |
| 682 | int i,j,index,n=rdp.n_global; |
| 683 | float percent; |
| 684 | // Swap vertex buffers |
| 685 | VERTEX *tmp = rdp.vtxbuf2; |
| 686 | rdp.vtxbuf2 = rdp.vtxbuf; |
| 687 | rdp.vtxbuf = tmp; |
| 688 | rdp.vtx_buffer ^= 1; |
| 689 | index = 0; |
| 690 | |
| 691 | // Check the vertices for clipping |
| 692 | for (i=0; i<n; i++) |
| 693 | { |
| 694 | j = i+1; |
| 695 | if (j == 3) j = 0; |
| 696 | |
| 697 | if (Vi.w >= 0.01f) |
| 698 | { |
| 699 | if (Vj.w >= 0.01f) // Both are in, save the last one |
| 700 | { |
| 701 | rdp.vtxbuf[index] = Vj; |
| 702 | rdp.vtxbuf[index++].not_zclipped = 1; |
| 703 | } |
| 704 | else // First is in, second is out, save intersection |
| 705 | { |
| 706 | percent = (-Vi.w) / (Vj.w - Vi.w); |
| 707 | rdp.vtxbuf[index].not_zclipped = 0; |
| 708 | rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent; |
| 709 | rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent; |
| 710 | rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent; |
| 711 | rdp.vtxbuf[index].w = 0.01f; |
| 712 | rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent; |
| 713 | rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent; |
| 714 | rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent; |
| 715 | rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent; |
| 716 | if (interpolate_colors) |
| 717 | InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent); |
| 718 | else |
| 719 | rdp.vtxbuf[index++].number = Vi.number | Vj.number; |
| 720 | } |
| 721 | } |
| 722 | else |
| 723 | { |
| 724 | //if (Vj.w < 0.01f) // Both are out, save nothing |
| 725 | if (Vj.w >= 0.01f) // First is out, second is in, save intersection & in point |
| 726 | { |
| 727 | percent = (-Vj.w) / (Vi.w - Vj.w); |
| 728 | rdp.vtxbuf[index].not_zclipped = 0; |
| 729 | rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent; |
| 730 | rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent; |
| 731 | rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent; |
| 732 | rdp.vtxbuf[index].w = 0.01f; |
| 733 | rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; |
| 734 | rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; |
| 735 | rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; |
| 736 | rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; |
| 737 | if (interpolate_colors) |
| 738 | InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent); |
| 739 | else |
| 740 | rdp.vtxbuf[index++].number = Vi.number | Vj.number; |
| 741 | |
| 742 | // Save the in point |
| 743 | rdp.vtxbuf[index] = Vj; |
| 744 | rdp.vtxbuf[index++].not_zclipped = 1; |
| 745 | } |
| 746 | } |
| 747 | } |
| 748 | rdp.n_global = index; |
| 749 | } |
| 750 | |
| 751 | static void render_tri (wxUint16 linew, int old_interpolate); |
| 752 | |
| 753 | void do_triangle_stuff (wxUint16 linew, int old_interpolate) // what else?? do the triangle stuff :P (to keep from writing code twice) |
| 754 | { |
| 755 | int i; |
| 756 | |
| 757 | if (rdp.clip & CLIP_WMIN) |
| 758 | clip_w (old_interpolate); |
| 759 | |
| 760 | float maxZ = (rdp.zsrc != 1) ? rdp.view_trans[2] + rdp.view_scale[2] : rdp.prim_depth; |
| 761 | |
| 762 | wxUint8 no_clip = 2; |
| 763 | for (i=0; i<rdp.n_global; i++) |
| 764 | { |
| 765 | if (rdp.vtxbuf[i].not_zclipped)// && rdp.zsrc != 1) |
| 766 | { |
| 767 | #ifdef EXTREME_LOGGING |
| 768 | FRDP (" * NOT ZCLIPPPED: %d\n", rdp.vtxbuf[i].number); |
| 769 | #endif |
| 770 | rdp.vtxbuf[i].x = rdp.vtxbuf[i].sx; |
| 771 | rdp.vtxbuf[i].y = rdp.vtxbuf[i].sy; |
| 772 | rdp.vtxbuf[i].z = rdp.vtxbuf[i].sz; |
| 773 | rdp.vtxbuf[i].q = rdp.vtxbuf[i].oow; |
| 774 | rdp.vtxbuf[i].u0 = rdp.vtxbuf[i].u0_w; |
| 775 | rdp.vtxbuf[i].v0 = rdp.vtxbuf[i].v0_w; |
| 776 | rdp.vtxbuf[i].u1 = rdp.vtxbuf[i].u1_w; |
| 777 | rdp.vtxbuf[i].v1 = rdp.vtxbuf[i].v1_w; |
| 778 | } |
| 779 | else |
| 780 | { |
| 781 | #ifdef EXTREME_LOGGING |
| 782 | FRDP (" * ZCLIPPED: %d\n", rdp.vtxbuf[i].number); |
| 783 | #endif |
| 784 | rdp.vtxbuf[i].q = 1.0f / rdp.vtxbuf[i].w; |
| 785 | rdp.vtxbuf[i].x = rdp.view_trans[0] + rdp.vtxbuf[i].x * rdp.vtxbuf[i].q * rdp.view_scale[0] + rdp.offset_x; |
| 786 | rdp.vtxbuf[i].y = rdp.view_trans[1] + rdp.vtxbuf[i].y * rdp.vtxbuf[i].q * rdp.view_scale[1] + rdp.offset_y; |
| 787 | rdp.vtxbuf[i].z = rdp.view_trans[2] + rdp.vtxbuf[i].z * rdp.vtxbuf[i].q * rdp.view_scale[2]; |
| 788 | if (rdp.tex >= 1) |
| 789 | { |
| 790 | rdp.vtxbuf[i].u0 *= rdp.vtxbuf[i].q; |
| 791 | rdp.vtxbuf[i].v0 *= rdp.vtxbuf[i].q; |
| 792 | } |
| 793 | if (rdp.tex >= 2) |
| 794 | { |
| 795 | rdp.vtxbuf[i].u1 *= rdp.vtxbuf[i].q; |
| 796 | rdp.vtxbuf[i].v1 *= rdp.vtxbuf[i].q; |
| 797 | } |
| 798 | } |
| 799 | |
| 800 | if (rdp.zsrc == 1) |
| 801 | rdp.vtxbuf[i].z = rdp.prim_depth; |
| 802 | |
| 803 | // Don't remove clipping, or it will freeze |
| 804 | if (rdp.vtxbuf[i].x > rdp.clip_max_x) rdp.clip |= CLIP_XMAX; |
| 805 | if (rdp.vtxbuf[i].x < rdp.clip_min_x) rdp.clip |= CLIP_XMIN; |
| 806 | if (rdp.vtxbuf[i].y > rdp.clip_max_y) rdp.clip |= CLIP_YMAX; |
| 807 | if (rdp.vtxbuf[i].y < rdp.clip_min_y) rdp.clip |= CLIP_YMIN; |
| 808 | if (rdp.vtxbuf[i].z > maxZ) rdp.clip |= CLIP_ZMAX; |
| 809 | if (rdp.vtxbuf[i].z < 0.0f) rdp.clip |= CLIP_ZMIN; |
| 810 | no_clip &= rdp.vtxbuf[i].screen_translated; |
| 811 | } |
| 812 | if (no_clip) |
| 813 | rdp.clip = 0; |
| 814 | else |
| 815 | { |
| 816 | if (!settings.clip_zmin) |
| 817 | rdp.clip &= ~CLIP_ZMIN; |
| 818 | if (!settings.clip_zmax) |
| 819 | rdp.clip &= ~CLIP_ZMAX; |
| 820 | } |
| 821 | render_tri (linew, old_interpolate); |
| 822 | } |
| 823 | |
| 824 | void do_triangle_stuff_2 (wxUint16 linew) |
| 825 | { |
| 826 | rdp.clip = 0; |
| 827 | |
| 828 | for (int i=0; i<rdp.n_global; i++) |
| 829 | { |
| 830 | // Don't remove clipping, or it will freeze |
| 831 | if (rdp.vtxbuf[i].x > rdp.clip_max_x) rdp.clip |= CLIP_XMAX; |
| 832 | if (rdp.vtxbuf[i].x < rdp.clip_min_x) rdp.clip |= CLIP_XMIN; |
| 833 | if (rdp.vtxbuf[i].y > rdp.clip_max_y) rdp.clip |= CLIP_YMAX; |
| 834 | if (rdp.vtxbuf[i].y < rdp.clip_min_y) rdp.clip |= CLIP_YMIN; |
| 835 | } |
| 836 | |
| 837 | render_tri (linew, TRUE); |
| 838 | } |
| 839 | |
| 840 | __inline wxUint8 real_to_char(double x) |
| 841 | { |
| 842 | return (wxUint8)(((int)floor(x+0.5))&0xFF); |
| 843 | } |
| 844 | |
| 845 | //* |
| 846 | static void InterpolateColors2(VERTEX & va, VERTEX & vb, VERTEX & res, float percent) |
| 847 | { |
| 848 | float w = 1.0f/(va.oow + (vb.oow-va.oow) * percent); |
| 849 | // res.oow = va.oow + (vb.oow-va.oow) * percent; |
| 850 | // res.q = res.oow; |
| 851 | float ba = va.b * va.oow; |
| 852 | float bb = vb.b * vb.oow; |
| 853 | res.b = real_to_char(interp2p(ba, bb, percent) * w); |
| 854 | float ga = va.g * va.oow; |
| 855 | float gb = vb.g * vb.oow; |
| 856 | res.g = real_to_char(interp2p(ga, gb, percent) * w); |
| 857 | float ra = va.r * va.oow; |
| 858 | float rb = vb.r * vb.oow; |
| 859 | res.r = real_to_char(interp2p(ra, rb, percent) * w); |
| 860 | float aa = va.a * va.oow; |
| 861 | float ab = vb.a * vb.oow; |
| 862 | res.a = real_to_char(interp2p(aa, ab, percent) * w); |
| 863 | float fa = va.f * va.oow; |
| 864 | float fb = vb.f * vb.oow; |
| 865 | res.f = interp2p(fa, fb, percent) * w; |
| 866 | /* |
| 867 | float u0a = va.u0_w * va.oow; |
| 868 | float u0b = vb.u0_w * vb.oow; |
| 869 | res.u0 = (u0a + (u0b - u0a) * percent) * w; |
| 870 | float v0a = va.v0_w * va.oow; |
| 871 | float v0b = vb.v0_w * vb.oow; |
| 872 | res.v0 = (v0a + (v0b - v0a) * percent) * w; |
| 873 | float u1a = va.u1_w * va.oow; |
| 874 | float u1b = vb.u1_w * vb.oow; |
| 875 | res.u1 = (u1a + (u1b - u1a) * percent) * w; |
| 876 | float v1a = va.v1_w * va.oow; |
| 877 | float v1b = vb.v1_w * vb.oow; |
| 878 | res.v1 = (v1a + (v1b - v1a) * percent) * w; |
| 879 | */ |
| 880 | } |
| 881 | //*/ |
| 882 | |
| 883 | typedef struct { |
| 884 | float d; //*SEB* was doubles |
| 885 | float x; |
| 886 | float y; |
| 887 | } LineEuqationType; |
| 888 | |
| 889 | static float EvaLine(LineEuqationType &li, float x, float y) //*SEB* all double before |
| 890 | { |
| 891 | return li.x*x+li.y*y+li.d; |
| 892 | } |
| 893 | |
| 894 | static void Create1LineEq(LineEuqationType &l, VERTEX &v1, VERTEX &v2, VERTEX &v3) |
| 895 | { |
| 896 | // Line between (x1,y1) to (x2,y2) |
| 897 | l.x = v2.sy-v1.sy; |
| 898 | l.y = v1.sx-v2.sx; |
| 899 | l.d = -(l.x*v2.sx+(l.y)*v2.sy); |
| 900 | if (EvaLine(l,v3.sx,v3.sy)*v3.oow < 0) |
| 901 | { |
| 902 | l.x = -l.x; |
| 903 | l.y = -l.y; |
| 904 | l.d = -l.d; |
| 905 | } |
| 906 | } |
| 907 | |
| 908 | |
| 909 | __inline float interp3p(float a, float b, float c, float r1, float r2) //*SEB* r1 and r2 and function was double |
| 910 | { |
| 911 | return (a)+(((b)+((c)-(b))*(r2))-(a))*(r1); |
| 912 | } |
| 913 | /* |
| 914 | #define interp3p(a, b, c, r1, r2) \ |
| 915 | (a+(((b)+((c)-(b))*(r2))-(a))*(r1)) |
| 916 | */ |
| 917 | |
| 918 | static void InterpolateColors3(VERTEX &v1, VERTEX &v2, VERTEX &v3, VERTEX &out) //*SEB* all double before |
| 919 | { |
| 920 | |
| 921 | LineEuqationType line; |
| 922 | Create1LineEq(line, v2, v3, v1); |
| 923 | |
| 924 | float aDot = (out.x*line.x + out.y*line.y); |
| 925 | float bDot = (v1.sx*line.x + v1.sy*line.y); |
| 926 | |
| 927 | float scale1 = ( - line.d - aDot) / ( bDot - aDot ); |
| 928 | |
| 929 | float tx = out.x + scale1 * (v1.sx - out.x); |
| 930 | float ty = out.y + scale1 * (v1.sy - out.y); |
| 931 | |
| 932 | float s1 = 101.0, s2 = 101.0; |
| 933 | float den = tx - v1.sx; |
| 934 | if (fabsf(den) > 1.0) |
| 935 | s1 = (out.x-v1.sx)/den; |
| 936 | if (s1 > 100.0f) |
| 937 | s1 = (out.y-v1.sy)/(ty-v1.sy); |
| 938 | |
| 939 | den = v3.sx - v2.sx; |
| 940 | if (fabsf(den) > 1.0) |
| 941 | s2 = (tx-v2.sx)/den; |
| 942 | if (s2 > 100.0f) |
| 943 | s2 =(ty-v2.sy)/(v3.sy-v2.sy); |
| 944 | |
| 945 | float w = 1.0/interp3p(v1.oow,v2.oow,v3.oow,s1,s2); |
| 946 | |
| 947 | out.r = real_to_char(interp3p(v1.r*v1.oow,v2.r*v2.oow,v3.r*v3.oow,s1,s2)*w); |
| 948 | out.g = real_to_char(interp3p(v1.g*v1.oow,v2.g*v2.oow,v3.g*v3.oow,s1,s2)*w); |
| 949 | out.b = real_to_char(interp3p(v1.b*v1.oow,v2.b*v2.oow,v3.b*v3.oow,s1,s2)*w); |
| 950 | out.a = real_to_char(interp3p(v1.a*v1.oow,v2.a*v2.oow,v3.a*v3.oow,s1,s2)*w); |
| 951 | out.f = (float)(interp3p(v1.f*v1.oow,v2.f*v2.oow,v3.f*v3.oow,s1,s2)*w); |
| 952 | /* |
| 953 | out.u0 = interp3p(v1.u0_w*v1.oow,v2.u0_w*v2.oow,v3.u0_w*v3.oow,s1,s2)/oow; |
| 954 | out.v0 = interp3p(v1.v0_w*v1.oow,v2.v0_w*v2.oow,v3.v0_w*v3.oow,s1,s2)/oow; |
| 955 | out.u1 = interp3p(v1.u1_w*v1.oow,v2.u1_w*v2.oow,v3.u1_w*v3.oow,s1,s2)/oow; |
| 956 | out.v1 = interp3p(v1.v1_w*v1.oow,v2.v1_w*v2.oow,v3.v1_w*v3.oow,s1,s2)/oow; |
| 957 | */ |
| 958 | } |
| 959 | |
| 960 | static void CalculateLOD(VERTEX *v, int n) |
| 961 | { |
| 962 | //rdp.update |= UPDATE_TEXTURE; |
| 963 | /* |
| 964 | if (rdp.lod_calculated) |
| 965 | { |
| 966 | float detailmax; |
| 967 | if (dc0_detailmax < 0.5) |
| 968 | detailmax = rdp.lod_fraction; |
| 969 | else |
| 970 | detailmax = 1.0f - rdp.lod_fraction; |
| 971 | grTexDetailControl (GR_TMU0, dc0_lodbias, dc0_detailscale, detailmax); |
| 972 | if (num_tmu == 2) |
| 973 | grTexDetailControl (GR_TMU1, dc1_lodbias, dc1_detailscale, detailmax); |
| 974 | return; |
| 975 | } |
| 976 | */ |
| 977 | float deltaS, deltaT; |
| 978 | float deltaX, deltaY; |
| 979 | float deltaTexels, deltaPixels, lodFactor = 0; //*SEB* double before |
| 980 | float intptr; //*SEB* double before |
| 981 | float s_scale = rdp.tiles[rdp.cur_tile].width / 255.0f; |
| 982 | float t_scale = rdp.tiles[rdp.cur_tile].height / 255.0f; |
| 983 | if (settings.lodmode == 1) |
| 984 | { |
| 985 | deltaS = (v[1].u0/v[1].q - v[0].u0/v[0].q) * s_scale; |
| 986 | deltaT = (v[1].v0/v[1].q - v[0].v0/v[0].q) * t_scale; |
| 987 | deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT ); |
| 988 | |
| 989 | deltaX = (v[1].x - v[0].x)/rdp.scale_x; |
| 990 | deltaY = (v[1].y - v[0].y)/rdp.scale_y; |
| 991 | deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY ); |
| 992 | |
| 993 | lodFactor = deltaTexels / deltaPixels; |
| 994 | } |
| 995 | else |
| 996 | { |
| 997 | int i, j; |
| 998 | for (i = 0; i < n; i++) |
| 999 | { |
| 1000 | j = (i < n-1) ? i + 1 : 0; |
| 1001 | |
| 1002 | deltaS = (v[j].u0/v[j].q - v[i].u0/v[i].q) * s_scale; |
| 1003 | deltaT = (v[j].v0/v[j].q - v[i].v0/v[i].q) * t_scale; |
| 1004 | // deltaS = v[j].ou - v[i].ou; |
| 1005 | // deltaT = v[j].ov - v[i].ov; |
| 1006 | deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT ); |
| 1007 | |
| 1008 | deltaX = (v[j].x - v[i].x)/rdp.scale_x; |
| 1009 | deltaY = (v[j].y - v[i].y)/rdp.scale_y; |
| 1010 | deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY ); |
| 1011 | |
| 1012 | lodFactor += deltaTexels / deltaPixels; |
| 1013 | } |
| 1014 | // Divide by n (n edges) to find average |
| 1015 | lodFactor = lodFactor / n; |
| 1016 | } |
| 1017 | int ilod = (int)lodFactor; |
| 1018 | int lod_tile = min((int)(log10f((float)ilod)/log10f(2.0f)), rdp.cur_tile + rdp.mipmap_level); |
| 1019 | float lod_fraction = 1.0f; |
| 1020 | if (lod_tile < rdp.cur_tile + rdp.mipmap_level) |
| 1021 | { |
| 1022 | lod_fraction = max((float)modff(lodFactor / powf(2.,lod_tile),&intptr), (float)rdp.prim_lodmin / 255.0f); |
| 1023 | } |
| 1024 | float detailmax; |
| 1025 | if (cmb.dc0_detailmax < 0.5f) |
| 1026 | detailmax = lod_fraction; |
| 1027 | else |
| 1028 | detailmax = 1.0f - lod_fraction; |
| 1029 | grTexDetailControl (GR_TMU0, cmb.dc0_lodbias, cmb.dc0_detailscale, detailmax); |
| 1030 | if (voodoo.num_tmu == 2) |
| 1031 | grTexDetailControl (GR_TMU1, cmb.dc1_lodbias, cmb.dc1_detailscale, detailmax); |
| 1032 | FRDP("CalculateLOD factor: %f, tile: %d, lod_fraction: %f\n", (float)lodFactor, lod_tile, lod_fraction); |
| 1033 | } |
| 1034 | |
| 1035 | float ScaleZ(float z) |
| 1036 | { |
| 1037 | if (settings.n64_z_scale) |
| 1038 | { |
| 1039 | int iz = (int)(z*8.0f+0.5f); |
| 1040 | if (iz < 0) iz = 0; |
| 1041 | else if (iz >= 0x40000) iz = 0x40000 - 1; |
| 1042 | return (float)zLUT[iz]; |
| 1043 | } |
| 1044 | if (z < 0.0f) return 0.0f; |
| 1045 | z *= 1.9f; |
| 1046 | if (z > 65534.0f) return 65534.0f; |
| 1047 | return z; |
| 1048 | } |
| 1049 | |
| 1050 | static void DepthBuffer(VERTEX * vtx, int n) |
| 1051 | { |
| 1052 | if (fb_depth_render_enabled && !(settings.hacks&hack_RE2) && dzdx && (rdp.flags & ZBUF_UPDATE)) |
| 1053 | { |
| 1054 | vertexi v[12]; |
| 1055 | if (u_cull_mode == 1) //cull front |
| 1056 | { |
| 1057 | for(int i=0; i<n; i++) |
| 1058 | { |
| 1059 | v[i].x = (int)((vtx[n-i-1].x-rdp.offset_x) / rdp.scale_x * 65536.0); |
| 1060 | v[i].y = (int)((vtx[n-i-1].y-rdp.offset_y) / rdp.scale_y * 65536.0); |
| 1061 | v[i].z = (int)(vtx[n-i-1].z * 65536.0); |
| 1062 | } |
| 1063 | } |
| 1064 | else |
| 1065 | { |
| 1066 | for(int i=0; i<n; i++) |
| 1067 | { |
| 1068 | v[i].x = (int)((vtx[i].x-rdp.offset_x) / rdp.scale_x * 65536.0); |
| 1069 | v[i].y = (int)((vtx[i].y-rdp.offset_y) / rdp.scale_y * 65536.0); |
| 1070 | v[i].z = (int)(vtx[i].z * 65536.0); |
| 1071 | } |
| 1072 | } |
| 1073 | Rasterize(v, n, dzdx); |
| 1074 | } |
| 1075 | for(int i=0; i<n; i++) |
| 1076 | vtx[i].z = ScaleZ(vtx[i].z); |
| 1077 | } |
| 1078 | |
| 1079 | /* |
| 1080 | std::ofstream loga; |
| 1081 | #define LOGG(x) loga.open("glide_log.txt",std::ios::app); loga << x; loga.flush(); loga.close(); |
| 1082 | __inline void FRDP2(char *fmt, ...) |
| 1083 | { |
| 1084 | va_list ap; |
| 1085 | va_start(ap, fmt); |
| 1086 | vsprintf(out_buf, fmt, ap); |
| 1087 | LOGG(out_buf); |
| 1088 | va_end(ap); |
| 1089 | } |
| 1090 | //*/ |
| 1091 | //#define LOGG(x) |
| 1092 | //#define FRDP2(x) |
| 1093 | |
| 1094 | |
| 1095 | void clip_tri(int interpolate_colors) |
| 1096 | { |
| 1097 | int i,j,index,n=rdp.n_global; |
| 1098 | float percent; |
| 1099 | |
| 1100 | // Check which clipping is needed |
| 1101 | if (rdp.clip & CLIP_XMAX) // right of the screen |
| 1102 | { |
| 1103 | // Swap vertex buffers |
| 1104 | VERTEX *tmp = rdp.vtxbuf2; |
| 1105 | rdp.vtxbuf2 = rdp.vtxbuf; |
| 1106 | rdp.vtxbuf = tmp; |
| 1107 | rdp.vtx_buffer ^= 1; |
| 1108 | index = 0; |
| 1109 | |
| 1110 | // Check the vertices for clipping |
| 1111 | for (i=0; i<n; i++) |
| 1112 | { |
| 1113 | j = i+1; |
| 1114 | if (j == n) j = 0; |
| 1115 | |
| 1116 | if (Vi.x <= rdp.clip_max_x) |
| 1117 | { |
| 1118 | if (Vj.x <= rdp.clip_max_x) // Both are in, save the last one |
| 1119 | { |
| 1120 | rdp.vtxbuf[index++] = Vj; |
| 1121 | } |
| 1122 | else // First is in, second is out, save intersection |
| 1123 | { |
| 1124 | percent = (rdp.clip_max_x - Vi.x) / (Vj.x - Vi.x); |
| 1125 | rdp.vtxbuf[index].x = rdp.clip_max_x; |
| 1126 | rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent; |
| 1127 | rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent; |
| 1128 | rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent; |
| 1129 | rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent; |
| 1130 | rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent; |
| 1131 | rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent; |
| 1132 | rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent; |
| 1133 | if (interpolate_colors) |
| 1134 | InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent); |
| 1135 | else |
| 1136 | rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8; |
| 1137 | } |
| 1138 | } |
| 1139 | else |
| 1140 | { |
| 1141 | //if (Vj.x > rdp.clip_max_x) // Both are out, save nothing |
| 1142 | if (Vj.x <= rdp.clip_max_x) // First is out, second is in, save intersection & in point |
| 1143 | { |
| 1144 | percent = (rdp.clip_max_x - Vj.x) / (Vi.x - Vj.x); |
| 1145 | rdp.vtxbuf[index].x = rdp.clip_max_x; |
| 1146 | rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent; |
| 1147 | rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent; |
| 1148 | rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent; |
| 1149 | rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; |
| 1150 | rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; |
| 1151 | rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; |
| 1152 | rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; |
| 1153 | if (interpolate_colors) |
| 1154 | InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent); |
| 1155 | else |
| 1156 | rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8; |
| 1157 | |
| 1158 | // Save the in point |
| 1159 | rdp.vtxbuf[index++] = Vj; |
| 1160 | } |
| 1161 | } |
| 1162 | } |
| 1163 | n = index; |
| 1164 | } |
| 1165 | if (rdp.clip & CLIP_XMIN) // left of the screen |
| 1166 | { |
| 1167 | // Swap vertex buffers |
| 1168 | VERTEX *tmp = rdp.vtxbuf2; |
| 1169 | rdp.vtxbuf2 = rdp.vtxbuf; |
| 1170 | rdp.vtxbuf = tmp; |
| 1171 | rdp.vtx_buffer ^= 1; |
| 1172 | index = 0; |
| 1173 | |
| 1174 | // Check the vertices for clipping |
| 1175 | for (i=0; i<n; i++) |
| 1176 | { |
| 1177 | j = i+1; |
| 1178 | if (j == n) j = 0; |
| 1179 | |
| 1180 | if (Vi.x >= rdp.clip_min_x) |
| 1181 | { |
| 1182 | if (Vj.x >= rdp.clip_min_x) // Both are in, save the last one |
| 1183 | { |
| 1184 | rdp.vtxbuf[index++] = Vj; |
| 1185 | } |
| 1186 | else // First is in, second is out, save intersection |
| 1187 | { |
| 1188 | percent = (rdp.clip_min_x - Vi.x) / (Vj.x - Vi.x); |
| 1189 | rdp.vtxbuf[index].x = rdp.clip_min_x; |
| 1190 | rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent; |
| 1191 | rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent; |
| 1192 | rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent; |
| 1193 | rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent; |
| 1194 | rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent; |
| 1195 | rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent; |
| 1196 | rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent; |
| 1197 | if (interpolate_colors) |
| 1198 | InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent); |
| 1199 | else |
| 1200 | rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8; |
| 1201 | } |
| 1202 | } |
| 1203 | else |
| 1204 | { |
| 1205 | //if (Vj.x < rdp.clip_min_x) // Both are out, save nothing |
| 1206 | if (Vj.x >= rdp.clip_min_x) // First is out, second is in, save intersection & in point |
| 1207 | { |
| 1208 | percent = (rdp.clip_min_x - Vj.x) / (Vi.x - Vj.x); |
| 1209 | rdp.vtxbuf[index].x = rdp.clip_min_x; |
| 1210 | rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent; |
| 1211 | rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent; |
| 1212 | rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent; |
| 1213 | rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; |
| 1214 | rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; |
| 1215 | rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; |
| 1216 | rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; |
| 1217 | if (interpolate_colors) |
| 1218 | InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent); |
| 1219 | else |
| 1220 | rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8; |
| 1221 | |
| 1222 | // Save the in point |
| 1223 | rdp.vtxbuf[index++] = Vj; |
| 1224 | } |
| 1225 | } |
| 1226 | } |
| 1227 | n = index; |
| 1228 | } |
| 1229 | if (rdp.clip & CLIP_YMAX) // top of the screen |
| 1230 | { |
| 1231 | // Swap vertex buffers |
| 1232 | VERTEX *tmp = rdp.vtxbuf2; |
| 1233 | rdp.vtxbuf2 = rdp.vtxbuf; |
| 1234 | rdp.vtxbuf = tmp; |
| 1235 | rdp.vtx_buffer ^= 1; |
| 1236 | index = 0; |
| 1237 | |
| 1238 | // Check the vertices for clipping |
| 1239 | for (i=0; i<n; i++) |
| 1240 | { |
| 1241 | j = i+1; |
| 1242 | if (j == n) j = 0; |
| 1243 | |
| 1244 | if (Vi.y <= rdp.clip_max_y) |
| 1245 | { |
| 1246 | if (Vj.y <= rdp.clip_max_y) // Both are in, save the last one |
| 1247 | { |
| 1248 | rdp.vtxbuf[index++] = Vj; |
| 1249 | } |
| 1250 | else // First is in, second is out, save intersection |
| 1251 | { |
| 1252 | percent = (rdp.clip_max_y - Vi.y) / (Vj.y - Vi.y); |
| 1253 | rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent; |
| 1254 | rdp.vtxbuf[index].y = rdp.clip_max_y; |
| 1255 | rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent; |
| 1256 | rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent; |
| 1257 | rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent; |
| 1258 | rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent; |
| 1259 | rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent; |
| 1260 | rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent; |
| 1261 | if (interpolate_colors) |
| 1262 | InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent); |
| 1263 | else |
| 1264 | rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16; |
| 1265 | } |
| 1266 | } |
| 1267 | else |
| 1268 | { |
| 1269 | //if (Vj.y > rdp.clip_max_y) // Both are out, save nothing |
| 1270 | if (Vj.y <= rdp.clip_max_y) // First is out, second is in, save intersection & in point |
| 1271 | { |
| 1272 | percent = (rdp.clip_max_y - Vj.y) / (Vi.y - Vj.y); |
| 1273 | rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent; |
| 1274 | rdp.vtxbuf[index].y = rdp.clip_max_y; |
| 1275 | rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent; |
| 1276 | rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent; |
| 1277 | rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; |
| 1278 | rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; |
| 1279 | rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; |
| 1280 | rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; |
| 1281 | if (interpolate_colors) |
| 1282 | InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent); |
| 1283 | else |
| 1284 | rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16; |
| 1285 | |
| 1286 | // Save the in point |
| 1287 | rdp.vtxbuf[index++] = Vj; |
| 1288 | } |
| 1289 | } |
| 1290 | } |
| 1291 | n = index; |
| 1292 | } |
| 1293 | if (rdp.clip & CLIP_YMIN) // bottom of the screen |
| 1294 | { |
| 1295 | // Swap vertex buffers |
| 1296 | VERTEX *tmp = rdp.vtxbuf2; |
| 1297 | rdp.vtxbuf2 = rdp.vtxbuf; |
| 1298 | rdp.vtxbuf = tmp; |
| 1299 | rdp.vtx_buffer ^= 1; |
| 1300 | index = 0; |
| 1301 | |
| 1302 | // Check the vertices for clipping |
| 1303 | for (i=0; i<n; i++) |
| 1304 | { |
| 1305 | j = i+1; |
| 1306 | if (j == n) j = 0; |
| 1307 | |
| 1308 | if (Vi.y >= rdp.clip_min_y) |
| 1309 | { |
| 1310 | if (Vj.y >= rdp.clip_min_y) // Both are in, save the last one |
| 1311 | { |
| 1312 | rdp.vtxbuf[index++] = Vj; |
| 1313 | } |
| 1314 | else // First is in, second is out, save intersection |
| 1315 | { |
| 1316 | percent = (rdp.clip_min_y - Vi.y) / (Vj.y - Vi.y); |
| 1317 | rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent; |
| 1318 | rdp.vtxbuf[index].y = rdp.clip_min_y; |
| 1319 | rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent; |
| 1320 | rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent; |
| 1321 | rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent; |
| 1322 | rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent; |
| 1323 | rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent; |
| 1324 | rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent; |
| 1325 | if (interpolate_colors) |
| 1326 | InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent); |
| 1327 | else |
| 1328 | rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16; |
| 1329 | } |
| 1330 | } |
| 1331 | else |
| 1332 | { |
| 1333 | //if (Vj.y < rdp.clip_min_y) // Both are out, save nothing |
| 1334 | if (Vj.y >= rdp.clip_min_y) // First is out, second is in, save intersection & in point |
| 1335 | { |
| 1336 | percent = (rdp.clip_min_y - Vj.y) / (Vi.y - Vj.y); |
| 1337 | rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent; |
| 1338 | rdp.vtxbuf[index].y = rdp.clip_min_y; |
| 1339 | rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent; |
| 1340 | rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent; |
| 1341 | rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; |
| 1342 | rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; |
| 1343 | rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; |
| 1344 | rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; |
| 1345 | if (interpolate_colors) |
| 1346 | InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent); |
| 1347 | else |
| 1348 | rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16; |
| 1349 | |
| 1350 | // Save the in point |
| 1351 | rdp.vtxbuf[index++] = Vj; |
| 1352 | } |
| 1353 | } |
| 1354 | } |
| 1355 | n = index; |
| 1356 | } |
| 1357 | if (rdp.clip & CLIP_ZMAX) // far plane |
| 1358 | { |
| 1359 | // Swap vertex buffers |
| 1360 | VERTEX *tmp = rdp.vtxbuf2; |
| 1361 | rdp.vtxbuf2 = rdp.vtxbuf; |
| 1362 | rdp.vtxbuf = tmp; |
| 1363 | rdp.vtx_buffer ^= 1; |
| 1364 | index = 0; |
| 1365 | float maxZ = rdp.view_trans[2] + rdp.view_scale[2]; |
| 1366 | |
| 1367 | // Check the vertices for clipping |
| 1368 | for (i=0; i<n; i++) |
| 1369 | { |
| 1370 | j = i+1; |
| 1371 | if (j == n) j = 0; |
| 1372 | |
| 1373 | if (Vi.z < maxZ) |
| 1374 | { |
| 1375 | if (Vj.z < maxZ) // Both are in, save the last one |
| 1376 | { |
| 1377 | rdp.vtxbuf[index++] = Vj; |
| 1378 | } |
| 1379 | else // First is in, second is out, save intersection |
| 1380 | { |
| 1381 | percent = (maxZ - Vi.z) / (Vj.z - Vi.z); |
| 1382 | rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent; |
| 1383 | rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent; |
| 1384 | rdp.vtxbuf[index].z = maxZ - 0.001f; |
| 1385 | rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent; |
| 1386 | rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent; |
| 1387 | rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent; |
| 1388 | rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent; |
| 1389 | rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent; |
| 1390 | if (interpolate_colors) |
| 1391 | InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent); |
| 1392 | else |
| 1393 | rdp.vtxbuf[index++].number = Vi.number | Vj.number; |
| 1394 | } |
| 1395 | } |
| 1396 | else |
| 1397 | { |
| 1398 | //if (Vj.z > maxZ) // Both are out, save nothing |
| 1399 | if (Vj.z < maxZ) // First is out, second is in, save intersection & in point |
| 1400 | { |
| 1401 | percent = (maxZ - Vj.z) / (Vi.z - Vj.z); |
| 1402 | rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent; |
| 1403 | rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent; |
| 1404 | rdp.vtxbuf[index].z = maxZ - 0.001f;; |
| 1405 | rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent; |
| 1406 | rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; |
| 1407 | rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; |
| 1408 | rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; |
| 1409 | rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; |
| 1410 | if (interpolate_colors) |
| 1411 | InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent); |
| 1412 | else |
| 1413 | rdp.vtxbuf[index++].number = Vi.number | Vj.number; |
| 1414 | |
| 1415 | // Save the in point |
| 1416 | rdp.vtxbuf[index++] = Vj; |
| 1417 | } |
| 1418 | } |
| 1419 | } |
| 1420 | n = index; |
| 1421 | } |
| 1422 | /* |
| 1423 | if (rdp.clip & CLIP_ZMIN) // near Z |
| 1424 | { |
| 1425 | // Swap vertex buffers |
| 1426 | VERTEX *tmp = rdp.vtxbuf2; |
| 1427 | rdp.vtxbuf2 = rdp.vtxbuf; |
| 1428 | rdp.vtxbuf = tmp; |
| 1429 | rdp.vtx_buffer ^= 1; |
| 1430 | index = 0; |
| 1431 | |
| 1432 | // Check the vertices for clipping |
| 1433 | for (i=0; i<n; i++) |
| 1434 | { |
| 1435 | j = i+1; |
| 1436 | if (j == n) j = 0; |
| 1437 | |
| 1438 | if (Vi.z >= 0.0f) |
| 1439 | { |
| 1440 | if (Vj.z >= 0.0f) // Both are in, save the last one |
| 1441 | { |
| 1442 | rdp.vtxbuf[index++] = Vj; |
| 1443 | } |
| 1444 | else // First is in, second is out, save intersection |
| 1445 | { |
| 1446 | percent = (-Vi.z) / (Vj.z - Vi.z); |
| 1447 | rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent; |
| 1448 | rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent; |
| 1449 | rdp.vtxbuf[index].z = 0.0f; |
| 1450 | rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent; |
| 1451 | rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent; |
| 1452 | rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent; |
| 1453 | rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent; |
| 1454 | rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent; |
| 1455 | if (interpolate_colors) |
| 1456 | InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent); |
| 1457 | else |
| 1458 | rdp.vtxbuf[index++].number = Vi.number | Vj.number; |
| 1459 | } |
| 1460 | } |
| 1461 | else |
| 1462 | { |
| 1463 | //if (Vj.z < 0.0f) // Both are out, save nothing |
| 1464 | if (Vj.z >= 0.0f) // First is out, second is in, save intersection & in point |
| 1465 | { |
| 1466 | percent = (-Vj.z) / (Vi.z - Vj.z); |
| 1467 | rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent; |
| 1468 | rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent; |
| 1469 | rdp.vtxbuf[index].z = 0.0f;; |
| 1470 | rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent; |
| 1471 | rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; |
| 1472 | rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; |
| 1473 | rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; |
| 1474 | rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; |
| 1475 | if (interpolate_colors) |
| 1476 | InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent); |
| 1477 | else |
| 1478 | rdp.vtxbuf[index++].number = Vi.number | Vj.number; |
| 1479 | |
| 1480 | // Save the in point |
| 1481 | rdp.vtxbuf[index++] = Vj; |
| 1482 | } |
| 1483 | } |
| 1484 | } |
| 1485 | n = index; |
| 1486 | } |
| 1487 | */ |
| 1488 | rdp.n_global = n; |
| 1489 | } |
| 1490 | |
| 1491 | static void render_tri (wxUint16 linew, int old_interpolate) |
| 1492 | { |
| 1493 | if (rdp.clip) |
| 1494 | clip_tri(old_interpolate); |
| 1495 | int n = rdp.n_global; |
| 1496 | if (n < 3) |
| 1497 | { |
| 1498 | FRDP (" * render_tri: n < 3\n"); |
| 1499 | return; |
| 1500 | } |
| 1501 | int i,j; |
| 1502 | //* |
| 1503 | if ((rdp.clip & CLIP_ZMIN) && (rdp.othermode_l & 0x00000030)) |
| 1504 | { |
| 1505 | |
| 1506 | int to_render = FALSE; |
| 1507 | for (i = 0; i < n; i++) |
| 1508 | { |
| 1509 | if (rdp.vtxbuf[i].z >= 0.0f) |
| 1510 | { |
| 1511 | to_render = TRUE; |
| 1512 | break; |
| 1513 | } |
| 1514 | } |
| 1515 | if (!to_render) //all z < 0 |
| 1516 | { |
| 1517 | FRDP (" * render_tri: all z < 0\n"); |
| 1518 | return; |
| 1519 | } |
| 1520 | } |
| 1521 | //*/ |
| 1522 | if (rdp.clip && !old_interpolate) |
| 1523 | { |
| 1524 | for (i = 0; i < n; i++) |
| 1525 | { |
| 1526 | float percent = 101.0f; |
| 1527 | VERTEX * v1 = 0, * v2 = 0; |
| 1528 | switch (rdp.vtxbuf[i].number&7) |
| 1529 | { |
| 1530 | case 1: |
| 1531 | case 2: |
| 1532 | case 4: |
| 1533 | continue; |
| 1534 | break; |
| 1535 | case 3: |
| 1536 | v1 = org_vtx[0]; |
| 1537 | v2 = org_vtx[1]; |
| 1538 | break; |
| 1539 | case 5: |
| 1540 | v1 = org_vtx[0]; |
| 1541 | v2 = org_vtx[2]; |
| 1542 | break; |
| 1543 | case 6: |
| 1544 | v1 = org_vtx[1]; |
| 1545 | v2 = org_vtx[2]; |
| 1546 | break; |
| 1547 | case 7: |
| 1548 | InterpolateColors3(*org_vtx[0], *org_vtx[1], *org_vtx[2], rdp.vtxbuf[i]); |
| 1549 | continue; |
| 1550 | break; |
| 1551 | } |
| 1552 | switch (rdp.vtxbuf[i].number&24) |
| 1553 | { |
| 1554 | case 8: |
| 1555 | percent = (rdp.vtxbuf[i].x-v1->sx)/(v2->sx-v1->sx); |
| 1556 | break; |
| 1557 | case 16: |
| 1558 | percent = (rdp.vtxbuf[i].y-v1->sy)/(v2->sy-v1->sy); |
| 1559 | break; |
| 1560 | default: |
| 1561 | { |
| 1562 | float d = (v2->sx-v1->sx); |
| 1563 | if (fabs(d) > 1.0) |
| 1564 | percent = (rdp.vtxbuf[i].x-v1->sx)/d; |
| 1565 | if (percent > 100.0f) |
| 1566 | percent = (rdp.vtxbuf[i].y-v1->sy)/(v2->sy-v1->sy); |
| 1567 | } |
| 1568 | } |
| 1569 | InterpolateColors2(*v1, *v2, rdp.vtxbuf[i], percent); |
| 1570 | } |
| 1571 | } |
| 1572 | /* |
| 1573 | if (rdp.clip) |
| 1574 | { |
| 1575 | LOGG("Colors before clipping:\n"); |
| 1576 | unsigned int k; |
| 1577 | for(k=0; k<3; k++) |
| 1578 | { |
| 1579 | FRDP2("V%d: r=%d, g=%d, b=%d, a=%d, f=%d\n", k, org_vtx[k]->r, org_vtx[k]->g, org_vtx[k]->b, org_vtx[k]->a, (short)org_vtx[k]->f); |
| 1580 | } |
| 1581 | FRDP("Got %d vertex after clipping\n", n); |
| 1582 | for(k=0; k<n; k++) |
| 1583 | { |
| 1584 | FRDP("V%d: r=%d, g=%d, b=%d, a=%d, f=%d\n", k, rdp.vtxbuf[k].r, rdp.vtxbuf[k].g, rdp.vtxbuf[k].b, rdp.vtxbuf[k].a, (short)rdp.vtxbuf[k].f); |
| 1585 | } |
| 1586 | } |
| 1587 | */ |
| 1588 | |
| 1589 | ConvertCoordsConvert (rdp.vtxbuf, n); |
| 1590 | if (rdp.fog_mode == RDP::fog_enabled) |
| 1591 | { |
| 1592 | for (i = 0; i < n; i++) |
| 1593 | { |
| 1594 | rdp.vtxbuf[i].f = 1.0f/max(4.0f, rdp.vtxbuf[i].f); |
| 1595 | } |
| 1596 | } |
| 1597 | else if (rdp.fog_mode == RDP::fog_blend) |
| 1598 | { |
| 1599 | float fog = 1.0f/max(1, rdp.fog_color&0xFF); |
| 1600 | for (i = 0; i < n; i++) |
| 1601 | { |
| 1602 | rdp.vtxbuf[i].f = fog; |
| 1603 | } |
| 1604 | } |
| 1605 | else if (rdp.fog_mode == RDP::fog_blend_inverse) |
| 1606 | { |
| 1607 | float fog = 1.0f/max(1, (~rdp.fog_color)&0xFF); |
| 1608 | for (i = 0; i < n; i++) |
| 1609 | { |
| 1610 | rdp.vtxbuf[i].f = fog; |
| 1611 | } |
| 1612 | } |
| 1613 | |
| 1614 | if (settings.lodmode > 0 && rdp.cur_tile < rdp.mipmap_level) |
| 1615 | CalculateLOD(rdp.vtxbuf, n); |
| 1616 | |
| 1617 | cmb.cmb_ext_use = cmb.tex_cmb_ext_use = 0; |
| 1618 | |
| 1619 | /* |
| 1620 | if (rdp.tbuff_tex) |
| 1621 | { |
| 1622 | for (int k = 0; k < 3; k++) |
| 1623 | { |
| 1624 | FRDP("v%d %f->%f, width: %d. height: %d, tex_width: %d, tex_height: %d, lr_u: %f, lr_v: %f\n", k, vv0[k], pv[k]->v1, rdp.tbuff_tex->width, rdp.tbuff_tex->height, rdp.tbuff_tex->tex_width, rdp.tbuff_tex->tex_height, rdp.tbuff_tex->lr_u, rdp.tbuff_tex->lr_v); |
| 1625 | } |
| 1626 | } |
| 1627 | */ |
| 1628 | if (fullscreen) |
| 1629 | { |
| 1630 | if (settings.wireframe) |
| 1631 | { |
| 1632 | SetWireframeCol (); |
| 1633 | for (i=0; i<n; i++) |
| 1634 | { |
| 1635 | j = i+1; |
| 1636 | if (j == n) j = 0; |
| 1637 | grDrawLine (&rdp.vtxbuf[i], &rdp.vtxbuf[j]); |
| 1638 | } |
| 1639 | } |
| 1640 | else |
| 1641 | { |
| 1642 | |
| 1643 | // VERTEX ** pv = rdp.vtx_buffer?(vtx_list2):(vtx_list1); |
| 1644 | // for (int k = 0; k < n; k ++) |
| 1645 | // FRDP ("DRAW[%d]: v.x = %f, v.y = %f, v.z = %f, v.u = %f, v.v = %f\n", k, pv[k]->x, pv[k]->y, pv[k]->z, pv[k]->coord[rdp.t0<<1], pv[k]->coord[(rdp.t0<<1)+1]); |
| 1646 | // pv[k]->y = settings.res_y - pv[k]->y; |
| 1647 | |
| 1648 | if (linew > 0) |
| 1649 | { |
| 1650 | VERTEX *V0 = &rdp.vtxbuf[0]; |
| 1651 | VERTEX *V1 = &rdp.vtxbuf[1]; |
| 1652 | if (fabs(V0->x - V1->x) < 0.01 && fabs(V0->y - V1->y) < 0.01) |
| 1653 | V1 = &rdp.vtxbuf[2]; |
| 1654 | V0->z = ScaleZ(V0->z); |
| 1655 | V1->z = ScaleZ(V1->z); |
| 1656 | VERTEX v[4]; |
| 1657 | v[0] = *V0; |
| 1658 | v[1] = *V0; |
| 1659 | v[2] = *V1; |
| 1660 | v[3] = *V1; |
| 1661 | float width = linew * 0.25f; |
| 1662 | if (fabs(V0->y - V1->y) < 0.0001) |
| 1663 | { |
| 1664 | v[0].x = v[1].x = V0->x; |
| 1665 | v[2].x = v[3].x = V1->x; |
| 1666 | |
| 1667 | width *= rdp.scale_y; |
| 1668 | v[0].y = v[2].y = V0->y - width; |
| 1669 | v[1].y = v[3].y = V0->y + width; |
| 1670 | } |
| 1671 | else if (fabs(V0->x - V1->x) < 0.0001) |
| 1672 | { |
| 1673 | v[0].y = v[1].y = V0->y; |
| 1674 | v[2].y = v[3].y = V1->y; |
| 1675 | |
| 1676 | width *= rdp.scale_x; |
| 1677 | v[0].x = v[2].x = V0->x - width; |
| 1678 | v[1].x = v[3].x = V0->x + width; |
| 1679 | } |
| 1680 | else |
| 1681 | { |
| 1682 | float dx = V1->x - V0->x; |
| 1683 | float dy = V1->y - V0->y; |
| 1684 | float len = sqrtf(dx*dx + dy*dy); |
| 1685 | float wx = dy * width * rdp.scale_x / len; |
| 1686 | float wy = dx * width * rdp.scale_y / len; |
| 1687 | v[0].x = V0->x + wx; |
| 1688 | v[0].y = V0->y - wy; |
| 1689 | v[1].x = V0->x - wx; |
| 1690 | v[1].y = V0->y + wy; |
| 1691 | v[2].x = V1->x + wx; |
| 1692 | v[2].y = V1->y - wy; |
| 1693 | v[3].x = V1->x - wx; |
| 1694 | v[3].y = V1->y + wy; |
| 1695 | } |
| 1696 | grDrawTriangle(&v[0], &v[1], &v[2]); |
| 1697 | grDrawTriangle(&v[1], &v[2], &v[3]); |
| 1698 | } |
| 1699 | else |
| 1700 | { |
| 1701 | DepthBuffer(rdp.vtxbuf, n); |
| 1702 | if ((rdp.rm & 0xC10) == 0xC10) |
| 1703 | grDepthBiasLevel (-deltaZ); |
| 1704 | grDrawVertexArray (GR_TRIANGLE_FAN, n, rdp.vtx_buffer?(&vtx_list2):(&vtx_list1)); |
| 1705 | } |
| 1706 | } |
| 1707 | } |
| 1708 | |
| 1709 | if (_debugger.capture) add_tri (rdp.vtxbuf, n, TRI_TRIANGLE); |
| 1710 | } |
| 1711 | |
| 1712 | void add_tri (VERTEX *v, int n, int type) |
| 1713 | { |
| 1714 | //FRDP ("ENTER (%f, %f, %f), (%f, %f, %f), (%f, %f, %f)\n", v[0].x, v[0].y, v[0].w, |
| 1715 | // v[1].x, v[1].y, v[1].w, v[2].x, v[2].y, v[2].w); |
| 1716 | |
| 1717 | // Debug capture |
| 1718 | if (_debugger.capture) |
| 1719 | { |
| 1720 | rdp.debug_n ++; |
| 1721 | |
| 1722 | TRI_INFO *info = new TRI_INFO; |
| 1723 | info->nv = n; |
| 1724 | info->v = new VERTEX [n]; |
| 1725 | memcpy (info->v, v, sizeof(VERTEX)*n); |
| 1726 | info->cycle_mode = rdp.cycle_mode; |
| 1727 | info->cycle1 = rdp.cycle1; |
| 1728 | info->cycle2 = rdp.cycle2; |
| 1729 | info->uncombined = rdp.uncombined; |
| 1730 | info->geom_mode = rdp.geom_mode; |
| 1731 | info->othermode_h = rdp.othermode_h; |
| 1732 | info->othermode_l = rdp.othermode_l; |
| 1733 | info->tri_n = rdp.tri_n; |
| 1734 | info->type = type; |
| 1735 | |
| 1736 | for (int i=0; i<2; i++) |
| 1737 | { |
| 1738 | int j = rdp.cur_tile+i; |
| 1739 | if (i == 0) |
| 1740 | info->t[i].tmu = rdp.t0; |
| 1741 | else |
| 1742 | info->t[i].tmu = rdp.t1; |
| 1743 | info->t[i].cur_cache[0] = rdp.cur_cache_n[rdp.t0]; |
| 1744 | info->t[i].cur_cache[1] = rdp.cur_cache_n[rdp.t1]; |
| 1745 | info->t[i].format = rdp.tiles[j].format; |
| 1746 | info->t[i].size = rdp.tiles[j].size; |
| 1747 | info->t[i].width = rdp.tiles[j].width; |
| 1748 | info->t[i].height = rdp.tiles[j].height; |
| 1749 | info->t[i].line = rdp.tiles[j].line; |
| 1750 | info->t[i].palette = rdp.tiles[j].palette; |
| 1751 | info->t[i].clamp_s = rdp.tiles[j].clamp_s; |
| 1752 | info->t[i].clamp_t = rdp.tiles[j].clamp_t; |
| 1753 | info->t[i].mirror_s = rdp.tiles[j].mirror_s; |
| 1754 | info->t[i].mirror_t = rdp.tiles[j].mirror_t; |
| 1755 | info->t[i].shift_s = rdp.tiles[j].shift_s; |
| 1756 | info->t[i].shift_t = rdp.tiles[j].shift_t; |
| 1757 | info->t[i].mask_s = rdp.tiles[j].mask_s; |
| 1758 | info->t[i].mask_t = rdp.tiles[j].mask_t; |
| 1759 | info->t[i].ul_s = rdp.tiles[j].ul_s; |
| 1760 | info->t[i].ul_t = rdp.tiles[j].ul_t; |
| 1761 | info->t[i].lr_s = rdp.tiles[j].lr_s; |
| 1762 | info->t[i].lr_t = rdp.tiles[j].lr_t; |
| 1763 | info->t[i].t_ul_s = rdp.tiles[7].t_ul_s; |
| 1764 | info->t[i].t_ul_t = rdp.tiles[7].t_ul_t; |
| 1765 | info->t[i].t_lr_s = rdp.tiles[7].t_lr_s; |
| 1766 | info->t[i].t_lr_t = rdp.tiles[7].t_lr_t; |
| 1767 | info->t[i].scale_s = rdp.tiles[j].s_scale; |
| 1768 | info->t[i].scale_t = rdp.tiles[j].t_scale; |
| 1769 | } |
| 1770 | |
| 1771 | info->fog_color = rdp.fog_color; |
| 1772 | info->fill_color = rdp.fill_color; |
| 1773 | info->prim_color = rdp.prim_color; |
| 1774 | info->blend_color = rdp.blend_color; |
| 1775 | info->env_color = rdp.env_color; |
| 1776 | info->prim_lodmin = rdp.prim_lodmin; |
| 1777 | info->prim_lodfrac = rdp.prim_lodfrac; |
| 1778 | |
| 1779 | info->pNext = _debugger.tri_list; |
| 1780 | _debugger.tri_list = info; |
| 1781 | |
| 1782 | if (_debugger.tri_last == NULL) |
| 1783 | _debugger.tri_last = _debugger.tri_list; |
| 1784 | } |
| 1785 | } |
| 1786 | |
| 1787 | void update_scissor () |
| 1788 | { |
| 1789 | if (rdp.update & UPDATE_SCISSOR) |
| 1790 | { |
| 1791 | rdp.update ^= UPDATE_SCISSOR; |
| 1792 | |
| 1793 | // KILL the floating point error with 0.01f |
| 1794 | rdp.scissor.ul_x = (wxUint32)max(min((rdp.scissor_o.ul_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0); |
| 1795 | rdp.scissor.lr_x = (wxUint32)max(min((rdp.scissor_o.lr_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0); |
| 1796 | rdp.scissor.ul_y = (wxUint32)max(min((rdp.scissor_o.ul_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0); |
| 1797 | rdp.scissor.lr_y = (wxUint32)max(min((rdp.scissor_o.lr_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0); |
| 1798 | //grClipWindow specifies the hardware clipping window. Any pixels outside the clipping window are rejected. |
| 1799 | //Values are inclusive for minimum x and y values and exclusive for maximum x and y values. |
| 1800 | // grClipWindow (rdp.scissor.ul_x?rdp.scissor.ul_x+1:0, rdp.scissor.ul_y?rdp.scissor.ul_y+1:0, rdp.scissor.lr_x, rdp.scissor.lr_y); |
| 1801 | if (fullscreen) |
| 1802 | grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); |
| 1803 | FRDP (" |- scissor - (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, |
| 1804 | rdp.scissor.lr_x, rdp.scissor.lr_y); |
| 1805 | } |
| 1806 | } |
| 1807 | |
| 1808 | // |
| 1809 | // update - update states if they need it |
| 1810 | // |
| 1811 | |
| 1812 | typedef struct |
| 1813 | { |
| 1814 | unsigned int c2_m2b:2; |
| 1815 | unsigned int c1_m2b:2; |
| 1816 | unsigned int c2_m2a:2; |
| 1817 | unsigned int c1_m2a:2; |
| 1818 | unsigned int c2_m1b:2; |
| 1819 | unsigned int c1_m1b:2; |
| 1820 | unsigned int c2_m1a:2; |
| 1821 | unsigned int c1_m1a:2; |
| 1822 | } rdp_blender_setting; |
| 1823 | |
| 1824 | void update () |
| 1825 | { |
| 1826 | LRDP ("-+ update called\n"); |
| 1827 | // Check for rendermode changes |
| 1828 | // Z buffer |
| 1829 | if (rdp.render_mode_changed & 0x00000C30) |
| 1830 | { |
| 1831 | FRDP (" |- render_mode_changed zbuf - decal: %s, update: %s, compare: %s\n", |
| 1832 | str_yn[(rdp.othermode_l & 0x00000400)?1:0], |
| 1833 | str_yn[(rdp.othermode_l&0x00000020)?1:0], |
| 1834 | str_yn[(rdp.othermode_l&0x00000010)?1:0]); |
| 1835 | |
| 1836 | rdp.render_mode_changed &= ~0x00000C30; |
| 1837 | rdp.update |= UPDATE_ZBUF_ENABLED; |
| 1838 | |
| 1839 | // Update? |
| 1840 | if ((rdp.othermode_l & 0x00000020)) |
| 1841 | rdp.flags |= ZBUF_UPDATE; |
| 1842 | else |
| 1843 | rdp.flags &= ~ZBUF_UPDATE; |
| 1844 | |
| 1845 | // Compare? |
| 1846 | if (rdp.othermode_l & 0x00000010) |
| 1847 | rdp.flags |= ZBUF_COMPARE; |
| 1848 | else |
| 1849 | rdp.flags &= ~ZBUF_COMPARE; |
| 1850 | } |
| 1851 | |
| 1852 | // Alpha compare |
| 1853 | if (rdp.render_mode_changed & 0x00001000) |
| 1854 | { |
| 1855 | FRDP (" |- render_mode_changed alpha compare - on: %s\n", |
| 1856 | str_yn[(rdp.othermode_l&0x00001000)?1:0]); |
| 1857 | rdp.render_mode_changed &= ~0x00001000; |
| 1858 | rdp.update |= UPDATE_ALPHA_COMPARE; |
| 1859 | |
| 1860 | if (rdp.othermode_l & 0x00001000) |
| 1861 | rdp.flags |= ALPHA_COMPARE; |
| 1862 | else |
| 1863 | rdp.flags &= ~ALPHA_COMPARE; |
| 1864 | } |
| 1865 | |
| 1866 | if (rdp.render_mode_changed & 0x00002000) // alpha cvg sel |
| 1867 | { |
| 1868 | FRDP (" |- render_mode_changed alpha cvg sel - on: %s\n", |
| 1869 | str_yn[(rdp.othermode_l&0x00002000)?1:0]); |
| 1870 | rdp.render_mode_changed &= ~0x00002000; |
| 1871 | rdp.update |= UPDATE_COMBINE; |
| 1872 | rdp.update |= UPDATE_ALPHA_COMPARE; |
| 1873 | } |
| 1874 | |
| 1875 | // Force blend |
| 1876 | if (rdp.render_mode_changed & 0xFFFF0000) |
| 1877 | { |
| 1878 | FRDP (" |- render_mode_changed force_blend - %08lx\n", rdp.othermode_l&0xFFFF0000); |
| 1879 | rdp.render_mode_changed &= 0x0000FFFF; |
| 1880 | |
| 1881 | rdp.fbl_a0 = (wxUint8)((rdp.othermode_l>>30)&0x3); |
| 1882 | rdp.fbl_b0 = (wxUint8)((rdp.othermode_l>>26)&0x3); |
| 1883 | rdp.fbl_c0 = (wxUint8)((rdp.othermode_l>>22)&0x3); |
| 1884 | rdp.fbl_d0 = (wxUint8)((rdp.othermode_l>>18)&0x3); |
| 1885 | rdp.fbl_a1 = (wxUint8)((rdp.othermode_l>>28)&0x3); |
| 1886 | rdp.fbl_b1 = (wxUint8)((rdp.othermode_l>>24)&0x3); |
| 1887 | rdp.fbl_c1 = (wxUint8)((rdp.othermode_l>>20)&0x3); |
| 1888 | rdp.fbl_d1 = (wxUint8)((rdp.othermode_l>>16)&0x3); |
| 1889 | |
| 1890 | rdp.update |= UPDATE_COMBINE; |
| 1891 | } |
| 1892 | |
| 1893 | // Combine MUST go before texture |
| 1894 | if ((rdp.update & UPDATE_COMBINE) && rdp.allow_combine) |
| 1895 | { |
| 1896 | TBUFF_COLOR_IMAGE * aTBuff[2] = {0, 0}; |
| 1897 | if (rdp.aTBuffTex[0]) |
| 1898 | aTBuff[rdp.aTBuffTex[0]->tile] = rdp.aTBuffTex[0]; |
| 1899 | if (rdp.aTBuffTex[1]) |
| 1900 | aTBuff[rdp.aTBuffTex[1]->tile] = rdp.aTBuffTex[1]; |
| 1901 | rdp.aTBuffTex[0] = aTBuff[0]; |
| 1902 | rdp.aTBuffTex[1] = aTBuff[1]; |
| 1903 | |
| 1904 | LRDP (" |-+ update_combine\n"); |
| 1905 | Combine (); |
| 1906 | } |
| 1907 | |
| 1908 | if (rdp.update & UPDATE_TEXTURE) // note: UPDATE_TEXTURE and UPDATE_COMBINE are the same |
| 1909 | { |
| 1910 | rdp.tex_ctr ++; |
| 1911 | if (rdp.tex_ctr == 0xFFFFFFFF) |
| 1912 | rdp.tex_ctr = 0; |
| 1913 | |
| 1914 | TexCache (); |
| 1915 | if (rdp.noise == RDP::noise_none) |
| 1916 | rdp.update ^= UPDATE_TEXTURE; |
| 1917 | } |
| 1918 | |
| 1919 | if (fullscreen) |
| 1920 | { |
| 1921 | // Z buffer |
| 1922 | if (rdp.update & UPDATE_ZBUF_ENABLED) |
| 1923 | { |
| 1924 | // already logged above |
| 1925 | rdp.update ^= UPDATE_ZBUF_ENABLED; |
| 1926 | |
| 1927 | if (((rdp.flags & ZBUF_ENABLED) || rdp.zsrc == 1) && rdp.cycle_mode < 2) |
| 1928 | { |
| 1929 | if (rdp.flags & ZBUF_COMPARE) |
| 1930 | { |
| 1931 | switch ((rdp.rm & 0xC00)>>10) { |
| 1932 | case 0: |
| 1933 | grDepthBiasLevel(0); |
| 1934 | grDepthBufferFunction (settings.zmode_compare_less ? GR_CMP_LESS : GR_CMP_LEQUAL); |
| 1935 | break; |
| 1936 | case 1: |
| 1937 | grDepthBiasLevel(-4); |
| 1938 | grDepthBufferFunction (settings.zmode_compare_less ? GR_CMP_LESS : GR_CMP_LEQUAL); |
| 1939 | break; |
| 1940 | case 2: |
| 1941 | grDepthBiasLevel(settings.ucode == 7 ? -4 : 0); |
| 1942 | grDepthBufferFunction (GR_CMP_LESS); |
| 1943 | break; |
| 1944 | case 3: |
| 1945 | // will be set dynamically per polygon |
| 1946 | //grDepthBiasLevel(-deltaZ); |
| 1947 | grDepthBufferFunction (GR_CMP_LEQUAL); |
| 1948 | break; |
| 1949 | } |
| 1950 | } |
| 1951 | else |
| 1952 | { |
| 1953 | grDepthBiasLevel(0); |
| 1954 | grDepthBufferFunction (GR_CMP_ALWAYS); |
| 1955 | } |
| 1956 | |
| 1957 | if (rdp.flags & ZBUF_UPDATE) |
| 1958 | grDepthMask (FXTRUE); |
| 1959 | else |
| 1960 | grDepthMask (FXFALSE); |
| 1961 | } |
| 1962 | else |
| 1963 | { |
| 1964 | grDepthBiasLevel(0); |
| 1965 | grDepthBufferFunction (GR_CMP_ALWAYS); |
| 1966 | grDepthMask (FXFALSE); |
| 1967 | } |
| 1968 | } |
| 1969 | |
| 1970 | // Alpha compare |
| 1971 | if (rdp.update & UPDATE_ALPHA_COMPARE) |
| 1972 | { |
| 1973 | // already logged above |
| 1974 | rdp.update ^= UPDATE_ALPHA_COMPARE; |
| 1975 | |
| 1976 | // if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && !force_full_alpha) |
| 1977 | // if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (rdp.blend_color&0xFF)) |
| 1978 | if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (!(rdp.othermode_l & 0x00004000) || (rdp.blend_color&0xFF))) |
| 1979 | { |
| 1980 | wxUint8 reference = (wxUint8)(rdp.blend_color&0xFF); |
| 1981 | grAlphaTestFunction (reference ? GR_CMP_GEQUAL : GR_CMP_GREATER); |
| 1982 | grAlphaTestReferenceValue (reference); |
| 1983 | FRDP (" |- alpha compare: blend: %02lx\n", reference); |
| 1984 | } |
| 1985 | else |
| 1986 | { |
| 1987 | if (rdp.flags & ALPHA_COMPARE) |
| 1988 | { |
| 1989 | if ((rdp.othermode_l & 0x5000) != 0x5000) |
| 1990 | { |
| 1991 | grAlphaTestFunction (GR_CMP_GEQUAL); |
| 1992 | grAlphaTestReferenceValue (0x20);//0xA0); |
| 1993 | LRDP (" |- alpha compare: 0x20\n"); |
| 1994 | } |
| 1995 | else |
| 1996 | { |
| 1997 | grAlphaTestFunction (GR_CMP_GREATER); |
| 1998 | if (rdp.acmp == 3) |
| 1999 | { |
| 2000 | grAlphaTestReferenceValue ((wxUint8)(rdp.blend_color&0xFF)); |
| 2001 | FRDP (" |- alpha compare: blend: %02lx\n", rdp.blend_color&0xFF); |
| 2002 | } |
| 2003 | else |
| 2004 | { |
| 2005 | grAlphaTestReferenceValue (0x00); |
| 2006 | LRDP (" |- alpha compare: 0x00\n"); |
| 2007 | } |
| 2008 | } |
| 2009 | } |
| 2010 | else |
| 2011 | { |
| 2012 | grAlphaTestFunction (GR_CMP_ALWAYS); |
| 2013 | LRDP (" |- alpha compare: none\n"); |
| 2014 | } |
| 2015 | } |
| 2016 | if (rdp.acmp == 3 && rdp.cycle_mode < 2) |
| 2017 | { |
| 2018 | if (grStippleModeExt != 0) |
| 2019 | { |
| 2020 | if (settings.old_style_adither || rdp.alpha_dither_mode != 3) { |
| 2021 | LRDP (" |- alpha compare: dither\n"); |
| 2022 | grStippleModeExt(settings.stipple_mode); |
| 2023 | } |
| 2024 | else |
| 2025 | grStippleModeExt(GR_STIPPLE_DISABLE); |
| 2026 | } |
| 2027 | } |
| 2028 | else |
| 2029 | { |
| 2030 | if (grStippleModeExt) |
| 2031 | { |
| 2032 | //LRDP (" |- alpha compare: dither disabled\n"); |
| 2033 | grStippleModeExt(GR_STIPPLE_DISABLE); |
| 2034 | } |
| 2035 | } |
| 2036 | } |
| 2037 | // Cull mode (leave this in for z-clipped triangles) |
| 2038 | if (rdp.update & UPDATE_CULL_MODE) |
| 2039 | { |
| 2040 | rdp.update ^= UPDATE_CULL_MODE; |
| 2041 | wxUint32 mode = (rdp.flags & CULLMASK) >> CULLSHIFT; |
| 2042 | FRDP (" |- cull_mode - mode: %s\n", str_cull[mode]); |
| 2043 | switch (mode) |
| 2044 | { |
| 2045 | case 0: // cull none |
| 2046 | case 3: // cull both |
| 2047 | grCullMode(GR_CULL_DISABLE); |
| 2048 | break; |
| 2049 | case 1: // cull front |
| 2050 | // grCullMode(GR_CULL_POSITIVE); |
| 2051 | grCullMode(GR_CULL_NEGATIVE); |
| 2052 | break; |
| 2053 | case 2: // cull back |
| 2054 | // grCullMode (GR_CULL_NEGATIVE); |
| 2055 | grCullMode (GR_CULL_POSITIVE); |
| 2056 | break; |
| 2057 | } |
| 2058 | } |
| 2059 | |
| 2060 | //Added by Gonetz. |
| 2061 | if (settings.fog && (rdp.update & UPDATE_FOG_ENABLED)) |
| 2062 | { |
| 2063 | rdp.update ^= UPDATE_FOG_ENABLED; |
| 2064 | |
| 2065 | wxUint16 blender = (wxUint16)(rdp.othermode_l >> 16); |
| 2066 | if (rdp.flags & FOG_ENABLED) |
| 2067 | { |
| 2068 | rdp_blender_setting &bl = *(rdp_blender_setting*)(&(blender)); |
| 2069 | if((rdp.fog_multiplier > 0) && (bl.c1_m1a==3 || bl.c1_m2a == 3 || bl.c2_m1a == 3 || bl.c2_m2a == 3)) |
| 2070 | { |
| 2071 | grFogColorValue(rdp.fog_color); |
| 2072 | grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); |
| 2073 | rdp.fog_mode = RDP::fog_enabled; |
| 2074 | LRDP("fog enabled \n"); |
| 2075 | } |
| 2076 | else |
| 2077 | { |
| 2078 | LRDP("fog disabled in blender\n"); |
| 2079 | rdp.fog_mode = RDP::fog_disabled; |
| 2080 | grFogMode (GR_FOG_DISABLE); |
| 2081 | } |
| 2082 | } |
| 2083 | else if (blender == 0xc410 || blender == 0xc411 || blender == 0xf500) |
| 2084 | { |
| 2085 | grFogColorValue(rdp.fog_color); |
| 2086 | grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); |
| 2087 | rdp.fog_mode = RDP::fog_blend; |
| 2088 | LRDP("fog blend \n"); |
| 2089 | } |
| 2090 | else if (blender == 0x04d1) |
| 2091 | { |
| 2092 | grFogColorValue(rdp.fog_color); |
| 2093 | grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); |
| 2094 | rdp.fog_mode = RDP::fog_blend_inverse; |
| 2095 | LRDP("fog blend \n"); |
| 2096 | } |
| 2097 | else |
| 2098 | { |
| 2099 | LRDP("fog disabled\n"); |
| 2100 | rdp.fog_mode = RDP::fog_disabled; |
| 2101 | grFogMode (GR_FOG_DISABLE); |
| 2102 | } |
| 2103 | } |
| 2104 | } |
| 2105 | |
| 2106 | if (rdp.update & UPDATE_VIEWPORT) |
| 2107 | { |
| 2108 | rdp.update ^= UPDATE_VIEWPORT; |
| 2109 | if (fullscreen) |
| 2110 | { |
| 2111 | float scale_x = (float)fabs(rdp.view_scale[0]); |
| 2112 | float scale_y = (float)fabs(rdp.view_scale[1]); |
| 2113 | |
| 2114 | rdp.clip_min_x = max((rdp.view_trans[0] - scale_x + rdp.offset_x) / rdp.clip_ratio, 0.0f); |
| 2115 | rdp.clip_min_y = max((rdp.view_trans[1] - scale_y + rdp.offset_y) / rdp.clip_ratio, 0.0f); |
| 2116 | rdp.clip_max_x = min((rdp.view_trans[0] + scale_x + rdp.offset_x) * rdp.clip_ratio, settings.res_x); |
| 2117 | rdp.clip_max_y = min((rdp.view_trans[1] + scale_y + rdp.offset_y) * rdp.clip_ratio, settings.res_y); |
| 2118 | |
| 2119 | FRDP (" |- viewport - (%d, %d, %d, %d)\n", (wxUint32)rdp.clip_min_x, (wxUint32)rdp.clip_min_y, (wxUint32)rdp.clip_max_x, (wxUint32)rdp.clip_max_y); |
| 2120 | if (!rdp.scissor_set) |
| 2121 | { |
| 2122 | rdp.scissor.ul_x = (wxUint32)rdp.clip_min_x; |
| 2123 | rdp.scissor.lr_x = (wxUint32)rdp.clip_max_x; |
| 2124 | rdp.scissor.ul_y = (wxUint32)rdp.clip_min_y; |
| 2125 | rdp.scissor.lr_y = (wxUint32)rdp.clip_max_y; |
| 2126 | grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); |
| 2127 | } |
| 2128 | } |
| 2129 | } |
| 2130 | |
| 2131 | if (rdp.update & UPDATE_SCISSOR) |
| 2132 | update_scissor (); |
| 2133 | |
| 2134 | LRDP (" + update end\n"); |
| 2135 | } |
| 2136 | |
| 2137 | void set_message_combiner () |
| 2138 | { |
| 2139 | grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, |
| 2140 | GR_COMBINE_FACTOR_ONE, |
| 2141 | GR_COMBINE_LOCAL_NONE, |
| 2142 | GR_COMBINE_OTHER_TEXTURE, |
| 2143 | FXFALSE); |
| 2144 | grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, |
| 2145 | GR_COMBINE_FACTOR_ONE, |
| 2146 | GR_COMBINE_LOCAL_NONE, |
| 2147 | GR_COMBINE_OTHER_TEXTURE, |
| 2148 | FXFALSE); |
| 2149 | if (settings.buff_clear && (settings.show_fps & 0x08)) |
| 2150 | grAlphaBlendFunction (GR_BLEND_SRC_ALPHA, |
| 2151 | GR_BLEND_ONE_MINUS_SRC_ALPHA, |
| 2152 | GR_BLEND_ZERO, |
| 2153 | GR_BLEND_ZERO); |
| 2154 | else |
| 2155 | grAlphaBlendFunction (GR_BLEND_ONE, |
| 2156 | GR_BLEND_ZERO, |
| 2157 | GR_BLEND_ZERO, |
| 2158 | GR_BLEND_ZERO); |
| 2159 | grAlphaTestFunction (GR_CMP_ALWAYS); |
| 2160 | if (grStippleModeExt) |
| 2161 | { |
| 2162 | grStippleModeExt(GR_STIPPLE_DISABLE); |
| 2163 | } |
| 2164 | grTexFilterMode (0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR); |
| 2165 | grTexCombine (GR_TMU1, |
| 2166 | GR_COMBINE_FUNCTION_NONE, |
| 2167 | GR_COMBINE_FACTOR_NONE, |
| 2168 | GR_COMBINE_FUNCTION_NONE, |
| 2169 | GR_COMBINE_FACTOR_NONE, |
| 2170 | FXFALSE, FXFALSE); |
| 2171 | grTexCombine (GR_TMU0, |
| 2172 | GR_COMBINE_FUNCTION_LOCAL, |
| 2173 | GR_COMBINE_FACTOR_NONE, |
| 2174 | GR_COMBINE_FUNCTION_LOCAL, |
| 2175 | GR_COMBINE_FACTOR_NONE, |
| 2176 | FXFALSE, FXFALSE); |
| 2177 | grTexSource(GR_TMU0, |
| 2178 | voodoo.tex_min_addr[GR_TMU0] + offset_font, |
| 2179 | GR_MIPMAPLEVELMASK_BOTH, |
| 2180 | &fontTex); |
| 2181 | grFogMode (GR_FOG_DISABLE); |
| 2182 | } |
| 2183 | |