[80]  1  /********************************************************************** <BR>


 2  This file is part of Crack dot Com's free source code release of


 3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for


 4  information about compiling & licensing issues visit this URL</a>


 5  <PRE> If that doesn't help, contact Jonathan Clark at


 6  golgotha_source@usa.net (Subject should have "GOLG" in it)


 7  ***********************************************************************/


 8 


 9  #include "arch.hh"


 10  #include "software/r1_software.hh"


 11  #include "software/r1_software_globals.hh"


 12  #include "software/span_buffer.hh"


 13  #include "software/inline_fpu.hh"


 14  #include "software/mappers.hh"


 15 


 16  //all calls to qftoi() here assume it will truncate, so be sure that start_trunc() gets


 17  //called before these functions execute


 18 


 19  inline void standard_draw_tri(s_vert *v0,s_vert *v1, s_vert *v2, w8 poly_type)


 20  {


 21  if (!tri_draw_functions[poly_type]) return;


 22  if (!texture_scanline_functions[poly_type]) return;


 23 


 24  //find top, middle, and bottom verts


 25  s_vert *min_y=0,*mid_y=0,*max_y=0;


 26 


 27  sw32 midedgecompare,botedgecompare;


 28 


 29  //sort the vertices by increasing y. special case for 3 verts


 30  //is faster than a bubble sort or qsort, etc


 31  if (v0>iy < v1>iy)


 32  {


 33  if (v0>iy < v2>iy)


 34  {


 35  min_y = v0;


 36 


 37  if (v1>iy < v2>iy)


 38  {


 39  mid_y = v1;


 40  max_y = v2;


 41  midedgecompare=1;


 42  botedgecompare=2;


 43  }


 44  else


 45  {


 46  mid_y = v2;


 47  max_y = v1;


 48  midedgecompare=2;


 49  botedgecompare=1;


 50  }


 51  }


 52  else


 53  {


 54  min_y = v2;


 55  mid_y = v0;


 56  max_y = v1;


 57  midedgecompare=0;


 58  botedgecompare=1;


 59  }


 60  }


 61  else


 62  {


 63  if (v1>iy < v2>iy)


 64  {


 65  min_y = v1;


 66 


 67  if (v0>iy < v2>iy)


 68  {


 69  mid_y = v0;


 70  max_y = v2;


 71  midedgecompare=3;


 72  botedgecompare=2;


 73  }


 74  else


 75  {


 76  mid_y = v2;


 77  max_y = v0;


 78  midedgecompare=2;


 79  botedgecompare=3;


 80  }


 81  }


 82  else


 83  {


 84  min_y = v2;


 85  mid_y = v1;


 86  max_y = v0;


 87  midedgecompare=1;


 88  botedgecompare=0;


 89  }


 90  }


 91 


 92  //setup the edges


 93  tri_edge top_to_middle,


 94  top_to_bottom,


 95  mid_to_bottom;


 96 


 97  top_to_middle.dy = mid_y>iy  min_y>iy;


 98  if (top_to_middle.dy)


 99  {


 100  double dxdy = (mid_y>px  min_y>px) / (mid_y>py  min_y>py);


 101 


 102  top_to_middle.dxdy = dxdy;


 103  top_to_middle.dxdy_fixed = qftoi(dxdy * 65536.f);


 104 


 105  //starting point x for when we begin rasterizing


 106  top_to_middle.px = qftoi( (min_y>px + ((float)min_y>iy  min_y>py)*dxdy) * 65536.f );


 107  }


 108 


 109  top_to_bottom.dy = max_y>iy  min_y>iy;


 110  if (top_to_bottom.dy)


 111  {


 112  double dxdy = (max_y>px  min_y>px) / (max_y>py  min_y>py);


 113 


 114  top_to_bottom.dxdy = dxdy;


 115  top_to_bottom.dxdy_fixed = qftoi(dxdy * 65536.f);


 116 


 117  //starting point x for when we begin rasterizing


 118  top_to_bottom.px = qftoi( (min_y>px + ((float)min_y>iy  min_y>py)*dxdy) * 65536.f );


 119  }


 120 


 121  mid_to_bottom.dy = max_y>iy  mid_y>iy;


 122  if (mid_to_bottom.dy)


 123  {


 124  double dxdy = (max_y>px  mid_y>px) / (max_y>py  mid_y>py);


 125 


 126  mid_to_bottom.dxdy = dxdy;


 127  mid_to_bottom.dxdy_fixed = qftoi(dxdy * 65536.f);


 128 


 129  //starting point x for when we begin rasterizing


 130  mid_to_bottom.px = qftoi( (mid_y>px + ((float)mid_y>iy  mid_y>py)*dxdy) * 65536.f );


 131  }


 132 


 133  //set cur_scanline_texture_func to the appropriate type


 134  cur_scanline_texture_func = texture_scanline_functions[poly_type];


 135 


 136  //set the fpu in single precision 1st


 137 


 138  start_single();


 139 


 140  //call the appropriate rasterizer


 141  tri_draw_functions[poly_type](top_to_middle,top_to_bottom,mid_to_bottom,min_y>iy,(botedgecompare < midedgecompare));


 142 


 143  stop_single();


 144  }


 145 


 146  inline void setup_spans_for_poly(s_vert *v, sw32 t_verts, span_tri_info *new_tri, i4_bool reverse=0)


 147  {


 148  new_tri>color_tint = r1_software_class_instance.cur_color_tint;


 149 


 150  tri_gradients &grads = new_tri>grads;


 151 


 152  sw32 i,j,dy;


 153  sw32 one;


 154 


 155  //reverse is used to handle backfacing polys


 156  if (reverse)


 157  one = 1;


 158  else


 159  one = 1;


 160 


 161  for (i=0; i<t_verts; i++)


 162  {


 163  j = i + one;


 164 


 165  if (j==t_verts)


 166  j=0;


 167  else


 168  if (j==1)


 169  j=t_verts1;


 170 


 171  sw32 &min_y = v[i].iy;


 172  sw32 &max_y = v[j].iy;


 173 


 174  dy = max_y  min_y;


 175  if (dy==0) continue; //edge is perfectly horizontal? ignore it


 176 


 177  //allocate a new edge


 178  span_edge *new_edge = new_span_edge();


 179  if (!new_edge) return;


 180 


 181  if (dy<0)


 182  {


 183  //its a trailing edge (dy and min_y / max_y should be swapped/negated)


 184 


 185  new_edge>tri_1 = new_tri;


 186  new_edge>flags = 0; //0 means its trailing


 187 


 188  double dxdy = (v[i].px  v[j].px) / (v[i].py  v[j].py);


 189  new_edge>dxdy = qftoi(65536.f * dxdy);


 190  new_edge>x = qftoi( (v[j].px + ((float)v[j].iy  v[j].py)*dxdy) * 65536.f );


 191 


 192  add_start_edge(new_edge,max_y); //this edge will be added to the active edge table when processing


 193  //scanline min_y


 194 


 195  add_remove_edge(new_edge,min_y1); //this edge will be removed from the active edge table when done


 196  //processing scanline max_y1


 197  }


 198  else


 199  {


 200  //its a leading edge


 201 


 202  new_edge>tri_1 = new_tri;


 203  new_edge>flags = LEADING_1; //LEADING_1 means leading, obviously


 204 


 205  double dxdy = (v[j].px  v[i].px) / (v[j].py  v[i].py);


 206  new_edge>dxdy = qftoi(65536.f * dxdy);


 207  new_edge>x = qftoi( (v[i].px + ((float)v[i].iy  v[i].py)*dxdy) * 65536.f );


 208 


 209  add_start_edge(new_edge,min_y); //this edge will be added to the active edge table when processing


 210  //scanline min_y


 211 


 212  add_remove_edge(new_edge,max_y1); //this edge will be removed from the active edge table when done


 213  //processing scanline max_y1


 214  }


 215  }


 216  }


 217 


 218  void sprite_setup_affine_unlit_alpha(s_vert *v,sw32 t_verts)


 219  {


 220  if (t_verts != 4)


 221  {


 222  i4_warning("software::probably shouldnt be calling sprite_setup_affine_unlit_alpha w/out 4 vertices");


 223  }


 224 


 225  //just draw a sprite. calculate some necessary info first, though


 226 


 227  //alias the vertex list


 228  s_vert *v0 = &v[0],


 229  *v1 = &v[1],


 230  *v2 = &v[2];


 231 


 232  tri_area_struct *t = triangle_info; //areas for each tri have already been calculated and stored here


 233 


 234  i4_bool reverse; //used to determine if the sprite is backfacing


 235 


 236  float &dx1x0 = t>dx1x0;


 237  float &dx2x0 = t>dx2x0;


 238 


 239  float &dy1y0 = t>dy1y0;


 240  float &dy2y0 = t>dy2y0;


 241 


 242  float &denom_gradx = t>area;


 243 


 244  if (denom_gradx < 5)


 245  {


 246  if (denom_gradx > 5  !r1_software_class_instance.allow_backfaces)


 247  {


 248  return;


 249  }


 250  reverse = i4_T;


 251  }


 252  else


 253  reverse = i4_F;


 254 


 255  //setup an alias


 256  tri_gradients *grads;


 257 


 258  //setup new spanned triangle


 259  span_tri_info *new_tri = 0;


 260 


 261  if (r1_software_class_instance.use_spans)


 262  {


 263  new_tri = new_span_tri();


 264  if (!new_tri) return;


 265  grads = &new_tri>grads;


 266  }


 267  else


 268  grads = &cur_grads;


 269 


 270  //calculate these "magic" multipliers (based on triangle area, obviously)


 271  double oodgx = 1.0 / (double)denom_gradx;


 272  double oodgy = oodgx;


 273 


 274  //sprites dont have ooz deltas, their ooz is constant. duh. clear them.


 275  grads>doozdx = 0;


 276  grads>doozdy = 0;


 277  grads>oozat00 = v0>ooz;


 278 


 279  //scale these multipliers so our s and t gradients are preshifted when we


 280  //store them to integer registers (ie they'll already be 16:16 fixed)


 281  oodgx *= 65536.0;


 282  oodgy *= 65536.0;


 283 


 284  //calculate s and t deltas


 285  double ds1s0 = (v1>s  v0>s);


 286  double ds2s0 = (v2>s  v0>s);


 287 


 288  double dt1t0 = (v1>t  v0>t);


 289  double dt2t0 = (v2>t  v0>t);


 290 


 291  //calculate s gradient for affine tri


 292  grads>dsdx = (((ds2s0)*(dy1y0)  (ds1s0)*(dy2y0)) * oodgx);


 293  grads>dsdy = (((ds2s0)*(dx1x0)  (ds1s0)*(dx2x0)) * oodgy);


 294  grads>sat00 = v0>s*65536.0  (v0>px * grads>dsdx)  (v0>py * grads>dsdy);


 295 


 296  //determine s adjustment (needed to ensure we dont step outside texture boundary)


 297  grads>s_adjust = 0;


 298 


 299  if (grads>dsdx < 0)


 300  grads>s_adjust = (sw32)1;


 301  else


 302  if (grads>dsdy < 0)


 303  grads>s_adjust = (sw32)1;


 304 


 305  //calculate t gradient for affine tri


 306  grads>dtdx = (((dt2t0)*(dy1y0)  (dt1t0)*(dy2y0)) * oodgx);


 307  grads>dtdy = (((dt2t0)*(dx1x0)  (dt1t0)*(dx2x0)) * oodgy);


 308  grads>tat00 = v0>t*65536.0  (v0>px * grads>dtdx)  (v0>py * grads>dtdy);


 309 


 310  //determine t adjustment


 311  grads>t_adjust = 0;


 312 


 313  if (grads>dtdx < 0)


 314  grads>t_adjust = (sw32)1;


 315  else


 316  if (grads>dtdy < 0)


 317  grads>t_adjust = (sw32)1;


 318 


 319  if (r1_software_class_instance.use_spans)


 320  {


 321  //add it to spanlist if we're using spans


 322  //set up the remaining span tri information


 323 


 324  new_tri>texture = r1_software_texture_ptr;


 325  new_tri>twidth_log2 = r1_software_twidth_log2;


 326  new_tri>texture_width = r1_software_texture_width;


 327  new_tri>texture_height = r1_software_texture_height;


 328  new_tri>span_list_head = 0;


 329  new_tri>type = small_poly_type;


 330 


 331  setup_spans_for_poly(v,4,new_tri,reverse);


 332  }


 333  else


 334  {


 335  //no spans, gonna draw immediately, setup pertinent global vars (s_frac_add, t_frac_add, and s_t_carry)


 336 


 337  //about to draw, setup pertinent global vars (temp_dsdx, temp_dtdx, dsdx_frac, dtdx_frac, s_t_carry)


 338  temp_dsdx = qftoi(cur_grads.dsdx);


 339  temp_dtdx = qftoi(cur_grads.dtdx);


 340 


 341  dsdx_frac = (temp_dsdx<<16);


 342  dtdx_frac = (temp_dtdx<<16);


 343 


 344  s_t_carry[1] = (temp_dsdx>>16) + ((temp_dtdx>>16)<<r1_software_twidth_log2); //integral add when t doesnt carry


 345  s_t_carry[0] = s_t_carry[1] + r1_software_texture_width; //integral add when t carrys


 346 


 347  //draw the sprite as 2 triangles (blech)


 348  standard_draw_tri(v0,v1,v2,small_poly_type);


 349  v1++; v2++;


 350  standard_draw_tri(v0,v1,v2,small_poly_type);


 351  }


 352  }


 353 


 354  void poly_setup_affine_lit(s_vert *v,sw32 t_verts)


 355  {


 356  //step through the vertices and extract the tris for drawing (or span buffering)


 357 


 358  i4_bool do_light = (small_poly_type==SPAN_TRI_AFFINE_LIT);


 359 


 360  //alias the vertex list


 361  s_vert *v0 = &v[0],


 362  *v1 = &v[1],


 363  *v2 = &v[2];


 364 


 365  //temporary list of verts for each tri,


 366  //needed for the call to setup_spans_for_poly (which doesnt take tris, but rather polys)


 367  s_vert span_verts[3];


 368  span_verts[0] = *v0;


 369 


 370  tri_area_struct *t = triangle_info; //areas for each tri have already been calculated and stored here


 371 


 372  i4_bool reverse; //used to determine if the tri is backfacing


 373  sw32 i;


 374 


 375  for (i=1; i<t_verts1; i++,t++)


 376  {


 377  float &dx1x0 = t>dx1x0;


 378  float &dx2x0 = t>dx2x0;


 379 


 380  float &dy1y0 = t>dy1y0;


 381  float &dy2y0 = t>dy2y0;


 382 


 383  float &denom_gradx = t>area;


 384 


 385  i4_bool supersmall = i4_F;


 386 


 387  if (denom_gradx > 0)


 388  {


 389  if (denom_gradx < 5)


 390  supersmall = i4_T;


 391 


 392  reverse = i4_F;


 393  }


 394  else


 395  if (denom_gradx < 0 && r1_software_class_instance.allow_backfaces)


 396  {


 397  if (denom_gradx > 5)


 398  supersmall = i4_T;


 399 


 400  reverse = i4_T;


 401  }


 402  else


 403  {


 404  v1++;


 405  v2++;


 406  continue;


 407  }


 408 


 409  //setup an alias


 410  tri_gradients *grads;


 411 


 412  //setup new spanned triangle


 413  span_tri_info *new_tri = 0;


 414 


 415  if (r1_software_class_instance.use_spans)


 416  {


 417  new_tri = new_span_tri();


 418  if (!new_tri) return;


 419  grads = &new_tri>grads;


 420  }


 421  else


 422  grads = &cur_grads;


 423 


 424  if (supersmall)


 425  {


 426  //this could be optimized further but.. too complicated. we just want


 427  //SOMETHING to be drawn, so calculate the ooz gradient so that it sorts


 428  //correctly, set s t and l gradients to 0


 429 


 430  //calculate these "magic" multipliers (based on triangle area, obviously)


 431  double oodgx = 1.0 / (double)denom_gradx;


 432  double oodgy = oodgx;


 433 


 434  //calculate ooz deltas


 435  double dooz1ooz0 = (v1>ooz  v0>ooz);


 436  double dooz2ooz0 = (v2>ooz  v0>ooz);


 437 


 438  //calculate ooz gradient for affine tri (ie no doozdxspan calculated)


 439  grads>doozdx = ((dooz2ooz0)*(dy1y0)  (dooz1ooz0)*(dy2y0)) * oodgx;


 440  grads>doozdy = ((dooz2ooz0)*(dx1x0)  (dooz1ooz0)*(dx2x0)) * oodgy;


 441  grads>oozat00 = v0>ooz  (v0>px * grads>doozdx)  (v0>py * grads>doozdy);


 442 


 443  //calculate s gradient for affine tri


 444  grads>dsdx = 0;


 445  grads>dsdy = 0;


 446  grads>sat00 = v0>s*65536.0;


 447  grads>s_adjust = 0;


 448 


 449  //calculate t gradient for affine tri


 450  grads>dtdx = 0;


 451  grads>dtdy = 0;


 452  grads>tat00 = v0>t*65536.0;


 453  grads>t_adjust = 0;


 454 


 455  if (do_light)


 456  {


 457  grads>dldx = 0;


 458  grads>dldy = 0;


 459  grads>lat00 = v0>l*256.0;


 460  }


 461  }


 462  else


 463  {


 464  //calculate these "magic" multipliers (based on triangle area, obviously)


 465  double oodgx = 1.0 / (double)denom_gradx;


 466  double oodgy = oodgx;


 467 


 468  //calculate ooz deltas


 469  double dooz1ooz0 = (v1>ooz  v0>ooz);


 470  double dooz2ooz0 = (v2>ooz  v0>ooz);


 471 


 472  //calculate ooz gradient for affine tri (ie no doozdxspan calculated)


 473  grads>doozdx = ((dooz2ooz0)*(dy1y0)  (dooz1ooz0)*(dy2y0)) * oodgx;


 474  grads>doozdy = ((dooz2ooz0)*(dx1x0)  (dooz1ooz0)*(dx2x0)) * oodgy;


 475  grads>oozat00 = v0>ooz  (v0>px * grads>doozdx)  (v0>py * grads>doozdy);


 476 


 477  //calculate s and t deltas


 478  double ds1s0 = (v1>s  v0>s);


 479  double ds2s0 = (v2>s  v0>s);


 480 


 481  double dt1t0 = (v1>t  v0>t);


 482  double dt2t0 = (v2>t  v0>t);


 483 


 484  //scale these multipliers so our s and t gradients are preshifted when we


 485  //store them to integer registers (ie they'll already be 16:16 fixed)


 486  oodgx *= 65536.0;


 487  oodgy *= 65536.0;


 488 


 489  //calculate s gradient for affine tri


 490  grads>dsdx = (((ds2s0)*(dy1y0)  (ds1s0)*(dy2y0)) * oodgx);


 491  grads>dsdy = (((ds2s0)*(dx1x0)  (ds1s0)*(dx2x0)) * oodgy);


 492  grads>sat00 = v0>s*65536.0  (v0>px * grads>dsdx)  (v0>py * grads>dsdy);


 493 


 494  //determine s adjustment (needed to ensure we dont step outside texture boundary)


 495  grads>s_adjust = 0;


 496 


 497  if (grads>dsdx < 0)


 498  grads>s_adjust = (sw32)1;


 499  else


 500  if (grads>dsdy < 0)


 501  grads>s_adjust = (sw32)1;


 502 


 503  //calculate t gradient for affine tri


 504  grads>dtdx = (((dt2t0)*(dy1y0)  (dt1t0)*(dy2y0)) * oodgx);


 505  grads>dtdy = (((dt2t0)*(dx1x0)  (dt1t0)*(dx2x0)) * oodgy);


 506  grads>tat00 = v0>t*65536.0  (v0>px * grads>dtdx)  (v0>py * grads>dtdy);


 507 


 508  //determine t adjustment


 509  grads>t_adjust = 0;


 510 


 511  if (grads>dtdx < 0)


 512  grads>t_adjust = (sw32)1;


 513  else


 514  if (grads>dtdy < 0)


 515  grads>t_adjust = (sw32)1;


 516 


 517  if (do_light)


 518  {


 519  //scale the multipliers so the l gradient is preshifted to


 520  //fixed point 28:4


 521  oodgx *= (1.0/256.0);


 522  oodgy *= (1.0/256.0);


 523 


 524  //l gradient calculation


 525  double dl1l0 = (v1>l  v0>l);


 526  double dl2l0 = (v2>l  v0>l);


 527 


 528  grads>dldx = (((dl2l0)*(dy1y0)  (dl1l0)*(dy2y0)) * oodgx);


 529  grads>dldy = (((dl2l0)*(dx1x0)  (dl1l0)*(dx2x0)) * oodgy);


 530  grads>lat00 = ((v0>l*256.0)  (v0>px * grads>dldx)  (v0>py * grads>dldy));


 531  }


 532  }


 533 


 534  if (r1_software_class_instance.use_spans)


 535  {


 536  //add it to spanlist if we're using spans


 537  //set up the remaining span tri information


 538 


 539  new_tri>texture = r1_software_texture_ptr;


 540  new_tri>twidth_log2 = r1_software_twidth_log2;


 541  new_tri>texture_width = r1_software_texture_width;


 542  new_tri>texture_height = r1_software_texture_height;


 543  new_tri>span_list_head = 0;


 544  new_tri>type = small_poly_type;


 545 


 546  //copy the current 2 verts into the span_vert list


 547  span_verts[1] = *v1;


 548  span_verts[2] = *v2;


 549  setup_spans_for_poly(span_verts,3,new_tri,reverse);


 550  }


 551  else


 552  {


 553  //about to draw, setup pertinent global vars (temp_dsdx, temp_dtdx, dsdx_frac, dtdx_frac, s_t_carry)


 554  temp_dsdx = qftoi(cur_grads.dsdx);


 555  temp_dtdx = qftoi(cur_grads.dtdx);


 556 


 557  dsdx_frac = (temp_dsdx<<16);


 558  dtdx_frac = (temp_dtdx<<16);


 559 


 560  s_t_carry[1] = (temp_dsdx>>16) + ((temp_dtdx>>16)<<r1_software_twidth_log2); //integral add when t doesnt carry


 561  s_t_carry[0] = s_t_carry[1] + r1_software_texture_width; //integral add when t carrys


 562 


 563  if (do_light)


 564  dldx_fixed = qftoi(cur_grads.dldx);


 565 


 566  standard_draw_tri(v0,v1,v2,small_poly_type);


 567  }


 568 


 569  //advance the vertex pointers


 570  v1++;


 571  v2++;


 572  }


 573  }


 574 


 575  void poly_setup_perspective_lit(s_vert *v,sw32 t_verts)


 576  {


 577  i4_bool do_light = (big_poly_type==SPAN_TRI_PERSPECTIVE_LIT);


 578 


 579  i4_bool reverse;


 580  s_vert *v0,*v1,*v2;


 581  v0 = &v[0];


 582  v1 = &v[1];


 583  v2 = &v[2];


 584 


 585  sw32 i;


 586  s_vert v_2[3];


 587 


 588  if (!v0>st_projected)


 589  {


 590  v0>soz = v0>s * v0>ooz;


 591  v0>toz = v0>t * v0>ooz;


 592  v0>st_projected = i4_T;


 593  }


 594 


 595  v_2[0] = *v0;


 596 


 597  tri_area_struct *t = triangle_info;


 598 


 599  //by default this will be a "big" polygon (thats why the perspective


 600  //setup was called in the 1st place)


 601  //BUT if one of the triangles is super tiny (<5 pixels), it will be drawn affine


 602  //this_poly_type will override big_poly_type


 603 


 604  for (i=1; i<t_verts1; i++,t++)


 605  {


 606  float &dx1x0 = t>dx1x0;


 607  float &dx2x0 = t>dx2x0;


 608 


 609  float &dy1y0 = t>dy1y0;


 610  float &dy2y0 = t>dy2y0;


 611 


 612  float &denom_gradx = t>area;


 613 


 614  i4_bool supersmall = i4_F;


 615 


 616  if (denom_gradx > 0)


 617  {


 618  if (denom_gradx < 5)


 619  supersmall = i4_T;


 620 


 621  reverse = i4_F;


 622  }


 623  else


 624  if (denom_gradx < 0 && r1_software_class_instance.allow_backfaces)


 625  {


 626  if (denom_gradx > 5)


 627  supersmall = i4_T;


 628 


 629  reverse = i4_T;


 630  }


 631  else


 632  {


 633  v1++;


 634  v2++;


 635  continue;


 636  }


 637 


 638  //setup new spanned triangle


 639  span_tri_info *new_tri=0;


 640 


 641  //setup an alias


 642  tri_gradients *grads;


 643 


 644  if (r1_software_class_instance.use_spans)


 645  {


 646  new_tri = new_span_tri();


 647  if (!new_tri) return;


 648  grads = &new_tri>grads;


 649  }


 650  else


 651  grads = &cur_grads;


 652 


 653  if (supersmall)


 654  {


 655  double oodgx = 1.0 / (double) denom_gradx;


 656  double oodgy = oodgx;


 657 


 658  double dooz1ooz0 = (v1>ooz  v0>ooz);


 659  double dooz2ooz0 = (v2>ooz  v0>ooz);


 660 


 661  grads>doozdx = ((dooz2ooz0)*(dy1y0)  (dooz1ooz0)*(dy2y0)) * oodgx;


 662  grads>doozdy = ((dooz2ooz0)*(dx1x0)  (dooz1ooz0)*(dx2x0)) * oodgy;


 663  grads>oozat00 = (double)v0>ooz  ((double)v0>px * grads>doozdx)  ((double)v0>py * grads>doozdy);


 664 


 665  //soz gradient calculation


 666  grads>dsdx = 0;


 667  grads>dsdy = 0;


 668  grads>sat00 = v0>s*65536.0;


 669  grads>s_adjust = 0;


 670 


 671  //toz gradient calculation


 672  grads>dtdx = 0;


 673  grads>dtdy = 0;


 674  grads>tat00 = v0>t*65536.0;


 675  grads>t_adjust = 0;


 676 


 677  if (do_light)


 678  {


 679  //do light gradient setup


 680  grads>dldx = 0;


 681  grads>dldy = 0;


 682  grads>lat00 = v0>l*256.0;


 683  }


 684  }


 685  else


 686  {


 687  double oodgx = 1.0 / (double) denom_gradx;


 688  double oodgy = oodgx;


 689 


 690  double dooz1ooz0 = (v1>ooz  v0>ooz);


 691  double dooz2ooz0 = (v2>ooz  v0>ooz);


 692 


 693  grads>doozdx = ((dooz2ooz0)*(dy1y0)  (dooz1ooz0)*(dy2y0)) * oodgx;


 694  grads>doozdxspan = grads>doozdx * 16;


 695  grads>doozdy = ((dooz2ooz0)*(dx1x0)  (dooz1ooz0)*(dx2x0)) * oodgy;


 696  grads>oozat00 = (double)v0>ooz  ((double)v0>px * grads>doozdx)  ((double)v0>py * grads>doozdy);


 697 


 698  if (!v1>st_projected)


 699  {


 700  v1>soz = v1>s * v1>ooz;


 701  v1>toz = v1>t * v1>ooz;


 702  v1>st_projected = i4_T;


 703  }


 704 


 705  if (!v2>st_projected)


 706  {


 707  v2>soz = v2>s * v2>ooz;


 708  v2>toz = v2>t * v2>ooz;


 709  v2>st_projected = i4_T;


 710  }


 711 


 712  //do the s and t gradient setup


 713  double dsoz1soz0 = (v1>soz  v0>soz);


 714  double dsoz2soz0 = (v2>soz  v0>soz);


 715 


 716  double dtoz1toz0 = (v1>toz  v0>toz);


 717  double dtoz2toz0 = (v2>toz  v0>toz);


 718 


 719  oodgx *= 65536.0;


 720  oodgy *= 65536.0;


 721 


 722  //soz gradient calculation


 723  grads>dsozdx = (((dsoz2soz0)*(dy1y0)  (dsoz1soz0)*(dy2y0)) * oodgx);


 724  grads>dsozdxspan = grads>dsozdx * 16;


 725  grads>dsozdy = (((dsoz2soz0)*(dx1x0)  (dsoz1soz0)*(dx2x0)) * oodgy);


 726  grads>sozat00 = (v0>soz*65536.0)  (v0>px * grads>dsozdx)  (v0>py * grads>dsozdy);


 727  grads>s_adjust = 0;


 728 


 729  //toz gradient calculation


 730  grads>dtozdx = (((dtoz2toz0)*(dy1y0)  (dtoz1toz0)*(dy2y0)) * oodgx);


 731  grads>dtozdxspan = grads>dtozdx * 16;


 732  grads>dtozdy = (((dtoz2toz0)*(dx1x0)  (dtoz1toz0)*(dx2x0)) * oodgy);


 733  grads>tozat00 = (v0>toz*65536.0)  (v0>px * grads>dtozdx)  (v0>py * grads>dtozdy);


 734  grads>t_adjust = 0;


 735 


 736  if (do_light)


 737  {


 738  //do light gradient setup


 739  double dl1l0 = (v1>l  v0>l);


 740  double dl2l0 = (v2>l  v0>l);


 741 


 742  oodgx *= (1.0/256.0);


 743  oodgy *= (1.0/256.0);


 744 


 745  grads>dldx = (((dl2l0)*(dy1y0)  (dl1l0)*(dy2y0)) * oodgx);


 746  grads>dldy = (((dl2l0)*(dx1x0)  (dl1l0)*(dx2x0)) * oodgy);


 747  grads>lat00 = (v0>l*256.0)  (v0>px * grads>dldx)  (v0>py * grads>dldy);


 748  }


 749 


 750  i4_float dsdx_indicator = grads>dsozdx*v0>ooz  v0>soz*grads>doozdx*65536.0;


 751  if (dsdx_indicator < 0)


 752  grads>s_adjust = (sw32)1;


 753  else


 754  {


 755  i4_float dsdy_indicator = grads>dsozdy*v0>ooz  v0>soz*grads>doozdy*65536.0;


 756  if (dsdy_indicator<0)


 757  grads>s_adjust = (sw32)1;


 758  }


 759 


 760  i4_float dtdx_indicator = grads>dtozdx*v0>ooz  v0>toz*grads>doozdx*65536.0;


 761  if (dtdx_indicator < 0)


 762  grads>t_adjust = (sw32)1;


 763  else


 764  {


 765  i4_float dtdy_indicator = grads>dtozdy*v0>ooz  v0>toz*grads>doozdy*65536.0;


 766  if (dtdy_indicator<0)


 767  grads>t_adjust = (sw32)1;


 768  }


 769  }


 770 


 771  if (r1_software_class_instance.use_spans)


 772  {


 773  //set up the remaining tri info


 774  new_tri>texture = r1_software_texture_ptr;


 775  new_tri>twidth_log2 = r1_software_twidth_log2;


 776  new_tri>texture_width = r1_software_texture_width;


 777  new_tri>texture_height = r1_software_texture_height;


 778  new_tri>span_list_head = 0;


 779 


 780  if (supersmall)


 781  new_tri>type = small_poly_type;


 782  else


 783  new_tri>type = big_poly_type;


 784 


 785  v_2[1] = *v1;


 786  v_2[2] = *v2;


 787  setup_spans_for_poly(v_2,3,new_tri,reverse);


 788  }


 789  else


 790  {


 791  //about to draw, setup pertinent global vars (temp_dsdx, temp_dtdx, dsdx_frac, dtdx_frac, s_t_carry)


 792 


 793  if (do_light)


 794  dldx_fixed = qftoi(cur_grads.dldx);


 795 


 796  if (supersmall)


 797  {


 798  //setup for affine rasterization


 799  temp_dsdx = qftoi(cur_grads.dsdx);


 800  temp_dtdx = qftoi(cur_grads.dtdx);


 801 


 802  dsdx_frac = (temp_dsdx<<16);


 803  dtdx_frac = (temp_dtdx<<16);


 804 


 805  s_t_carry[1] = (temp_dsdx>>16) + ((temp_dtdx>>16)<<r1_software_twidth_log2); //integral add when t doesnt carry


 806  s_t_carry[0] = s_t_carry[1] + r1_software_texture_width; //integral add when t carrys


 807 


 808  standard_draw_tri(v0,v1,v2,small_poly_type);


 809  }


 810  else


 811  {


 812  //setup for perspective_correct rasterization


 813 


 814  s_mask = ((r1_software_texture_width 1)<<16)  0xFFFF;


 815  t_mask = ((r1_software_texture_height1)<<16)  0xFFFF;


 816 


 817  standard_draw_tri(v0,v1,v2,big_poly_type);


 818  }


 819  }


 820 


 821  //advance the vertex pointers


 822  v1++;


 823  v2++;


 824  }


 825  }


 826 


 827  void poly_setup_solid_color(s_vert *v, sw32 t_verts)


 828  {


 829  i4_bool reverse;


 830 


 831  s_vert *v0 = &v[0],


 832  *v1 = &v[1],


 833  *v2 = &v[2];


 834 


 835  sw32 i;


 836  tri_area_struct *t = triangle_info;


 837 


 838  if (r1_software_class_instance.use_spans)


 839  {


 840  span_tri_info *new_tri = 0;


 841 


 842  tri_area_struct *t = triangle_info;


 843 


 844  float &dx1x0 = t>dx1x0;


 845  float &dx2x0 = t>dx2x0;


 846 


 847  float &dy1y0 = t>dy1y0;


 848  float &dy2y0 = t>dy2y0;


 849 


 850  float &denom_gradx = t>area;


 851 


 852  if (total_poly_area > 0)


 853  reverse = i4_F;


 854  else


 855  if (total_poly_area < 0 && r1_software_class_instance.allow_backfaces)


 856  reverse = i4_T;


 857  else


 858  return;


 859 


 860  new_tri = new_span_tri();


 861  if (!new_tri) return;


 862 


 863  tri_gradients *grads = &new_tri>grads;


 864 


 865  double oodgx = 1.0 / (double) denom_gradx;


 866  double oodgy = oodgx;


 867 


 868  double dooz1ooz0 = (v1>ooz  v0>ooz);


 869  double dooz2ooz0 = (v2>ooz  v0>ooz);


 870 


 871  //setup the ooz gradient, its all he needs


 872  grads>doozdx = ((dooz2ooz0)*(dy1y0)  (dooz1ooz0)*(dy2y0)) * oodgx;


 873  grads>doozdy = ((dooz2ooz0)*(dx1x0)  (dooz1ooz0)*(dx2x0)) * oodgy;


 874  grads>oozat00 = v0>ooz  (v0>px * grads>doozdx)  (v0>py * grads>doozdy);


 875 


 876  //set his gradients here


 877  new_tri>span_list_head = 0;


 878  new_tri>type = small_poly_type;


 879  new_tri>color = v>color; //use the color from the first vertex


 880 


 881  setup_spans_for_poly(v,t_verts,new_tri,reverse);


 882  }


 883  else


 884  {


 885  //no solid rasterizer yet


 886  return;


 887 


 888  s_vert v_2[3];


 889  v_2[0] = *v0;


 890 


 891  for (i=1; i<t_verts1; i++,t++)


 892  {


 893  float &dx1x0 = t>dx1x0;


 894  float &dx2x0 = t>dx2x0;


 895 


 896  float &dy1y0 = t>dy1y0;


 897  float &dy2y0 = t>dy2y0;


 898 


 899  float &denom_gradx = t>area;


 900 


 901  if (denom_gradx > 0)


 902  {


 903  reverse = i4_F;


 904  }


 905  else


 906  if (denom_gradx < 0 && r1_software_class_instance.allow_backfaces)


 907  {


 908  reverse = i4_T;


 909  }


 910  else


 911  {


 912  v1++;


 913  v2++;


 914  continue;


 915  }


 916 


 917  tri_gradients *grads = &cur_grads;


 918 


 919  double oodgx = 1.0 / (double) denom_gradx;


 920  double oodgy = oodgx;


 921 


 922  double dooz1ooz0 = (v1>ooz  v0>ooz);


 923  double dooz2ooz0 = (v2>ooz  v0>ooz);


 924 


 925  grads>doozdx = ((dooz2ooz0)*(dy1y0)  (dooz1ooz0)*(dy2y0)) * oodgx;


 926  grads>doozdxspan = grads>doozdx * 16;


 927  grads>doozdy = ((dooz2ooz0)*(dx1x0)  (dooz1ooz0)*(dx2x0)) * oodgy;


 928  grads>oozat00 = (double)v0>ooz  ((double)v0>px * grads>doozdx)  ((double)v0>py * grads>doozdy);


 929 


 930  standard_draw_tri(v0,v1,v2,small_poly_type);


 931 


 932  //advance the vertex pointers


 933  v1++;


 934  v2++;


 935  }


 936  }


 937  }

