Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/Util.cpp
2 views
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
double X0 = vtx[0]->sx / rdp.scale_x;
293
double Y0 = vtx[0]->sy / rdp.scale_y;
294
double X1 = vtx[1]->sx / rdp.scale_x;
295
double Y1 = vtx[1]->sy / rdp.scale_y;
296
double X2 = vtx[2]->sx / rdp.scale_x;
297
double Y2 = vtx[2]->sy / rdp.scale_y;
298
double diffy_02 = Y0 - Y2;
299
double diffy_12 = Y1 - Y2;
300
double diffx_02 = X0 - X2;
301
double diffx_12 = X1 - X2;
302
303
double denom = (diffx_02 * diffy_12 - diffx_12 * diffy_02);
304
if(denom*denom > 0.0)
305
{
306
double diffz_02 = vtx[0]->sz - vtx[2]->sz;
307
double diffz_12 = vtx[1]->sz - vtx[2]->sz;
308
double 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
double fdzdy = (diffz_02 * diffx_12 - diffz_12 * diffx_02) / denom;
312
double fdz = fabs(fdzdx) + fabs(fdzdy);
313
if ((settings.hacks & hack_Zelda) && (rdp.rm & 0x800))
314
fdz *= 4.0; // 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
double d;
885
double x;
886
double y;
887
} LineEuqationType;
888
889
static double EvaLine(LineEuqationType &li, double x, double y)
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 double interp3p(float a, float b, float c, double r1, double r2)
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)
919
{
920
921
LineEuqationType line;
922
Create1LineEq(line, v2, v3, v1);
923
924
double aDot = (out.x*line.x + out.y*line.y);
925
double bDot = (v1.sx*line.x + v1.sy*line.y);
926
927
double scale1 = ( - line.d - aDot) / ( bDot - aDot );
928
929
double tx = out.x + scale1 * (v1.sx - out.x);
930
double ty = out.y + scale1 * (v1.sy - out.y);
931
932
double s1 = 101.0, s2 = 101.0;
933
double den = tx - v1.sx;
934
if (fabs(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 (fabs(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
double 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
double deltaTexels, deltaPixels, lodFactor = 0;
980
double intptr;
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)modf(lodFactor / pow(2.,lod_tile),&intptr), 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
2184
2185