bitRender.cpp
Engine/source/core/bitRender.cpp
Classes:
class
Public Variables
Detailed Description
Public Defines
SF(x) ((x) >> 2)
SF32(a, b, c, d) {(),(),(c),(d)}
Public Variables
U8 bitTable [16][4]
U8 bitTableA [16][4]
U8 bitTableB [16][4]
U8 bitTableC [16][4]
U8 bitTableE [16][4]
U32 closeTable [32]
U32 openTable [32]
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "core/bitRender.h" 25 26U32 openTable[32] = { 0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFC,0xFFFFFFF8, 27 0xFFFFFFF0,0xFFFFFFE0,0xFFFFFFC0,0xFFFFFF80, 28 0xFFFFFF00,0xFFFFFE00,0xFFFFFC00,0xFFFFF800, 29 0xFFFFF000,0xFFFFE000,0xFFFFC000,0xFFFF8000, 30 0xFFFF0000,0xFFFE0000,0xFFFC0000,0xFFF80000, 31 0xFFF00000,0xFFE00000,0xFFC00000,0xFF800000, 32 0xFF000000,0xFE000000,0xFC000000,0xF8000000, 33 0xF0000000,0xE0000000,0xC0000000,0x80000000 }; 34 35U32 closeTable[32] = { 0x00000001,0x00000003,0x00000007,0x0000000F, 36 0x0000001F,0x0000003F,0x0000007F,0x000000FF, 37 0x000001FF,0x000003FF,0x000007FF,0x00000FFF, 38 0x00001FFF,0x00003FFF,0x00007FFF,0x0000FFFF, 39 0x0001FFFF,0x0003FFFF,0x0007FFFF,0x000FFFFF, 40 0x001FFFFF,0x003FFFFF,0x007FFFFF,0x00FFFFFF, 41 0x01FFFFFF,0x03FFFFFF,0x07FFFFFF,0x0FFFFFFF, 42 0x1FFFFFFF,0x3FFFFFFF,0x7FFFFFFF,0xFFFFFFFF }; 43 44struct DrawStruct 45{ 46 S16 start; 47 S16 num; 48}; 49 50void BitRender::render_strips(const U8 * draw, S32 numDraw, S32 szDraw, const U16 * indices, const Point2I * points, S32 dim, U32 * bits) 51{ 52 const U8 * drawEnd = draw + numDraw*szDraw; 53 54 // loop through strips... 55 for (; draw<drawEnd; draw += szDraw) 56 { 57 const DrawStruct * drawStruct = (DrawStruct*)draw; 58 const U16 * icurrent = indices + drawStruct->start; 59 const U16 * iend = icurrent + drawStruct->num; 60 61 const Point2I * vv0 = points + *(icurrent++); 62 const Point2I * vv1; 63 const Point2I * vv2 = points + *(icurrent++); 64 const Point2I **nextPt = &vv1; 65 66 while (icurrent<iend) 67 { 68 *nextPt = vv2; 69 nextPt = (const Point2I**)( (dsize_t)nextPt ^ (dsize_t)&vv0 ^ (dsize_t)&vv1 ); 70 vv2 = points + *(icurrent++); 71 72 // skip degenerate triangles... 73 if (vv0==vv1 || vv1==vv2 || vv2==vv0) 74 continue; 75 // following copied from BitRender::render...indented to highlight this fact, no function to indentation 76 { 77 const Point2I * v0 = vv0; 78 const Point2I * v1 = vv1; 79 const Point2I * v2 = vv2; 80 81 AssertFatal( v0->x>=0 && v0->x<dim && v0->y>=0 && v0->y<dim,"BitRender::render: v0 out of range"); 82 AssertFatal( v1->x>=0 && v1->x<dim && v1->y>=0 && v1->y<dim,"BitRender::render: v1 out of range"); 83 AssertFatal( v2->x>=0 && v2->x<dim && v2->y>=0 && v2->y<dim,"BitRender::render: v2 out of range"); 84 85 // back-face cull 86 if ((v0->x-v1->x)*(v2->y-v1->y) > (v0->y-v1->y)*(v2->x-v1->x)) 87 continue; 88 89 // rotate so that v0 holds topmost y coord 90 // Note: The particular inequalities used ( <=, <, then <=) are important. 91 // They guarantee that if there are two verts on the top row, that 92 // they will be vert v0 and v1 (also could be three). 93 if (v1->y <= v2->y) 94 { 95 if (v1->y < v0->y) 96 { 97 const Point2I * tmp = v0; 98 v0 = v1; 99 v1 = v2; 100 v2 = tmp; 101 } 102 } 103 else 104 { 105 if (v2->y <= v0->y) 106 { 107 const Point2I * tmp = v0; 108 v0 = v2; 109 v2 = v1; 110 v1 = tmp; 111 } 112 } 113 114 // all the control variables we have to set up... 115 S32 leftDeltaY, xLeftInc, xLeftErrInc, xLeftDir, xLeft, xLeftErr = 0; 116 S32 rightDeltaY, xRightInc, xRightErrInc, xRightDir, xRight, xRightErr = 0; 117 S32 * changeThisDelta; 118 S32 * changeThisInc; 119 S32 * changeThisErrInc; 120 S32 * changeThisDir; 121 S32 toThisDelta; 122 S32 toThisInc; 123 S32 toThisErrInc; 124 S32 toThisDir; 125 S32 ySwitch; 126 S32 yBottom; 127 128 // check for special case where top row holds two verts 129 if (v0->y==v1->y) 130 { 131 leftDeltaY = v2->y-v0->y; 132 rightDeltaY = v2->y-v1->y; 133 ySwitch = v2->y; 134 yBottom = v2->y; 135 136 if (v1->y==v2->y) 137 { 138 // special-special case where top row holds all three verts 139 xLeft = getMin(getMin(v0->x,v1->x),v2->x); 140 xRight = getMax(getMax(v0->x,v1->x),v2->x); 141 xLeftInc = xRightInc = 0; 142 xLeftErrInc = xRightErrInc = 0; 143 xLeftDir = xRightDir = 1; 144 } 145 else 146 { 147 // standard-special case...v2 on different row from v0 and v1 148 xLeft = v0->x; 149 xLeftInc = (v2->x-v0->x) / leftDeltaY; 150 xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc; 151 xLeftDir = v2->x-v0->x > 0 ? 1 : -1; 152 153 xRight = v1->x; 154 xRightInc = (v2->x-v1->x) / rightDeltaY; 155 xRightErrInc = (v2->x-v1->x) - rightDeltaY*xRightInc; 156 xRightDir = v2->x-v1->x > 0 ? 1 : -1; 157 } 158 159 // set these variables to avoid a crash... 160 changeThisDelta = &toThisDelta; 161 changeThisInc = &toThisInc; 162 changeThisErrInc = &toThisErrInc; 163 changeThisDir = &toThisDir; 164 } 165 else 166 { 167 leftDeltaY = v2->y-v0->y; 168 xLeftInc = (v2->x-v0->x) / leftDeltaY; 169 xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc; 170 xLeftDir = v2->x-v0->x > 0 ? 1 : -1; 171 172 rightDeltaY = v1->y-v0->y; 173 xRightInc = (v1->x-v0->x) / rightDeltaY; 174 xRightErrInc = (v1->x-v0->x) - rightDeltaY*xRightInc; 175 xRightDir = v1->x-v0->x > 0 ? 1 : -1; 176 177 xLeft = xRight = v0->x; 178 179 if (v1->y<v2->y) 180 { 181 // right edge bends 182 changeThisDelta = &rightDeltaY; 183 changeThisInc = &xRightInc; 184 changeThisErrInc = &xRightErrInc; 185 changeThisDir = &xRightDir; 186 toThisDelta = v2->y-v1->y; 187 toThisInc = (v2->x-v1->x) / toThisDelta; 188 toThisErrInc = (v2->x-v1->x) - toThisDelta * toThisInc; 189 toThisDir = v2->x-v1->x > 0 ? 1 : -1; 190 ySwitch = v1->y-1; 191 yBottom = v2->y; 192 } 193 else 194 { 195 // left edge bends 196 changeThisDelta = &leftDeltaY; 197 changeThisInc = &xLeftInc; 198 changeThisErrInc = &xLeftErrInc; 199 changeThisDir = &xLeftDir; 200 toThisDelta = v1->y-v2->y; 201 toThisInc = toThisDelta ? (v1->x-v2->x) / toThisDelta : 0; 202 toThisErrInc = toThisDelta ? (v1->x-v2->x) - toThisDelta * toThisInc : 0; 203 toThisDir = v1->x-v2->x > 0 ? 1 : -1; 204 ySwitch = v2->y-1; 205 yBottom = v1->y; 206 } 207 } 208 xLeftErrInc *= xLeftDir; 209 xRightErrInc *= xRightDir; 210 toThisErrInc *= toThisDir; 211 212 U32 * rowStart = bits + v0->y * (dim>>5); 213 for (S32 y=v0->y; y<=yBottom;) 214 { 215 do 216 { 217 AssertFatal(xLeft<=xRight,"BitRender::render"); 218 219 U32 open = openTable[xLeft&31]; 220 U32 close = closeTable[xRight&31]; 221 if ( (xLeft^xRight) & ~31) 222 { 223 U32 * x = rowStart+(xLeft>>5); 224 *x |= open; 225 U32 * xEnd = rowStart+(xRight>>5); 226 while (++x<xEnd) 227 *x |= 0xFFFFFFFF; 228 *x |= close; 229 } 230 else 231 rowStart[xLeft>>5] |= open & close; 232 233 xLeft += xLeftInc; 234 xLeftErr += xLeftErrInc; 235 if (xLeftErr >= leftDeltaY) 236 { 237 xLeft += xLeftDir; 238 xLeftErr -= leftDeltaY; 239 } 240 241 xRight += xRightInc; 242 xRightErr += xRightErrInc; 243 if (xRightErr >= rightDeltaY) 244 { 245 xRight += xRightDir; 246 xRightErr -= rightDeltaY; 247 } 248 249 rowStart += dim>>5; 250 251 } while (y++<ySwitch); 252 253 ySwitch=yBottom; // get here at most twice 254 *changeThisDelta = toThisDelta; 255 *changeThisInc = toThisInc; 256 *changeThisErrInc = toThisErrInc; 257 *changeThisDir = toThisDir; 258 } 259 260 } 261 } 262 } 263} 264 265void BitRender::render_tris(const U8 * draw, S32 numDraw, S32 szDraw, const U16 * indices, const Point2I * points, S32 dim, U32 * bits) 266{ 267 const U8 * drawEnd = draw + numDraw*szDraw; 268 269 // loop through strips... 270 for (; draw<drawEnd; draw += szDraw) 271 { 272 const DrawStruct * drawStruct = (DrawStruct*)draw; 273 const U16 * icurrent = indices + drawStruct->start; 274 const U16 * iend = icurrent + drawStruct->num; 275 276 while (icurrent<iend) 277 { 278 const Point2I * v0 = points + *(icurrent++); 279 const Point2I * v1 = points + *(icurrent++); 280 const Point2I * v2 = points + *(icurrent++); 281 282 // following copied from BitRender::render...indented to highlight this fact, no function to indentation 283 { 284 AssertFatal( v0->x>=0 && v0->x<dim && v0->y>=0 && v0->y<dim,"BitRender::render: v0 out of range"); 285 AssertFatal( v1->x>=0 && v1->x<dim && v1->y>=0 && v1->y<dim,"BitRender::render: v1 out of range"); 286 AssertFatal( v2->x>=0 && v2->x<dim && v2->y>=0 && v2->y<dim,"BitRender::render: v2 out of range"); 287 288 // back-face cull 289 if ((v0->x-v1->x)*(v2->y-v1->y) > (v0->y-v1->y)*(v2->x-v1->x)) 290 return; 291 292 // rotate so that v0 holds topmost y coord 293 // Note: The particular inequalities used ( <=, <, then <=) are important. 294 // They guarantee that if there are two verts on the top row, that 295 // they will be vert v0 and v1 (also could be three). 296 if (v1->y <= v2->y) 297 { 298 if (v1->y < v0->y) 299 { 300 const Point2I * tmp = v0; 301 v0 = v1; 302 v1 = v2; 303 v2 = tmp; 304 } 305 } 306 else 307 { 308 if (v2->y <= v0->y) 309 { 310 const Point2I * tmp = v0; 311 v0 = v2; 312 v2 = v1; 313 v1 = tmp; 314 } 315 } 316 317 // all the control variables we have to set up... 318 S32 leftDeltaY, xLeftInc = 0, xLeftErrInc, xLeftDir = 0, xLeft, xLeftErr = 0; 319 S32 rightDeltaY, xRightInc = 0, xRightErrInc, xRightDir = 0, xRight, xRightErr = 0; 320 S32 * changeThisDelta; 321 S32 * changeThisInc; 322 S32 * changeThisErrInc; 323 S32 * changeThisDir; 324 S32 toThisDelta; 325 S32 toThisInc; 326 S32 toThisErrInc; 327 S32 toThisDir; 328 S32 ySwitch; 329 S32 yBottom; 330 331 // check for special case where top row holds two verts 332 if (v0->y==v1->y) 333 { 334 leftDeltaY = v2->y-v0->y; 335 rightDeltaY = v2->y-v1->y; 336 ySwitch = v2->y; 337 yBottom = v2->y; 338 339 if (v1->y==v2->y) 340 { 341 // special-special case where top row holds all three verts 342 xLeft = getMin(getMin(v0->x,v1->x),v2->x); 343 xRight = getMax(getMax(v0->x,v1->x),v2->x); 344 xLeftErrInc = xRightErrInc = 0; 345 } 346 else 347 { 348 // standard-special case...v2 on different row from v0 and v1 349 xLeft = v0->x; 350 xLeftInc = (v2->x-v0->x) / leftDeltaY; 351 xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc; 352 xLeftDir = v2->x-v0->x > 0 ? 1 : -1; 353 354 xRight = v1->x; 355 xRightInc = (v2->x-v1->x) / rightDeltaY; 356 xRightErrInc = (v2->x-v1->x) - rightDeltaY*xRightInc; 357 xRightDir = v2->x-v1->x > 0 ? 1 : -1; 358 } 359 360 // set these variables to avoid a crash... 361 changeThisDelta = &toThisDelta; 362 changeThisInc = &toThisInc; 363 changeThisErrInc = &toThisErrInc; 364 changeThisDir = &toThisDir; 365 } 366 else 367 { 368 leftDeltaY = v2->y-v0->y; 369 xLeftInc = (v2->x-v0->x) / leftDeltaY; 370 xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc; 371 xLeftDir = v2->x-v0->x > 0 ? 1 : -1; 372 373 rightDeltaY = v1->y-v0->y; 374 xRightInc = (v1->x-v0->x) / rightDeltaY; 375 xRightErrInc = (v1->x-v0->x) - rightDeltaY*xRightInc; 376 xRightDir = v1->x-v0->x > 0 ? 1 : -1; 377 378 xLeft = xRight = v0->x; 379 380 if (v1->y<v2->y) 381 { 382 // right edge bends 383 changeThisDelta = &rightDeltaY; 384 changeThisInc = &xRightInc; 385 changeThisErrInc = &xRightErrInc; 386 changeThisDir = &xRightDir; 387 toThisDelta = v2->y-v1->y; 388 toThisInc = (v2->x-v1->x) / toThisDelta; 389 toThisErrInc = (v2->x-v1->x) - toThisDelta * toThisInc; 390 toThisDir = v2->x-v1->x > 0 ? 1 : -1; 391 ySwitch = v1->y-1; 392 yBottom = v2->y; 393 } 394 else 395 { 396 // left edge bends 397 changeThisDelta = &leftDeltaY; 398 changeThisInc = &xLeftInc; 399 changeThisErrInc = &xLeftErrInc; 400 changeThisDir = &xLeftDir; 401 toThisDelta = v1->y-v2->y; 402 toThisInc = toThisDelta ? (v1->x-v2->x) / toThisDelta : 0; 403 toThisErrInc = toThisDelta ? (v1->x-v2->x) - toThisDelta * toThisInc : 0; 404 toThisDir = v1->x-v2->x > 0 ? 1 : -1; 405 ySwitch = v2->y-1; 406 yBottom = v1->y; 407 } 408 } 409 xLeftErrInc *= xLeftDir; 410 xRightErrInc *= xRightDir; 411 toThisErrInc *= toThisDir; 412 413 U32 * rowStart = bits + v0->y * (dim>>5); 414 for (S32 y=v0->y; y<=yBottom;) 415 { 416 do 417 { 418 AssertFatal(xLeft<=xRight,"BitRender::render"); 419 420 U32 open = openTable[xLeft&31]; 421 U32 close = closeTable[xRight&31]; 422 if ( (xLeft^xRight) & ~31) 423 { 424 U32 * x = rowStart+(xLeft>>5); 425 *x |= open; 426 U32 * xEnd = rowStart+(xRight>>5); 427 while (++x<xEnd) 428 *x |= 0xFFFFFFFF; 429 *x |= close; 430 } 431 else 432 rowStart[xLeft>>5] |= open & close; 433 434 xLeft += xLeftInc; 435 xLeftErr += xLeftErrInc; 436 if (xLeftErr >= leftDeltaY) 437 { 438 xLeft += xLeftDir; 439 xLeftErr -= leftDeltaY; 440 } 441 442 xRight += xRightInc; 443 xRightErr += xRightErrInc; 444 if (xRightErr >= rightDeltaY) 445 { 446 xRight += xRightDir; 447 xRightErr -= rightDeltaY; 448 } 449 450 rowStart += dim>>5; 451 452 } while (y++<ySwitch); 453 454 ySwitch=yBottom; // get here at most twice 455 *changeThisDelta = toThisDelta; 456 *changeThisInc = toThisInc; 457 *changeThisErrInc = toThisErrInc; 458 *changeThisDir = toThisDir; 459 } 460 461 } 462 } 463 } 464} 465 466// assumes coords are in range 467void BitRender::render(const Point2I * v0, const Point2I * v1, const Point2I * v2, S32 dim, U32 * bits) 468{ 469 AssertFatal( v0->x>=0 && v0->x<dim && v0->y>=0 && v0->y<dim,"BitRender::render: v0 out of range"); 470 AssertFatal( v1->x>=0 && v1->x<dim && v1->y>=0 && v1->y<dim,"BitRender::render: v1 out of range"); 471 AssertFatal( v2->x>=0 && v2->x<dim && v2->y>=0 && v2->y<dim,"BitRender::render: v2 out of range"); 472 473 // back-face cull 474 if ((v0->x-v1->x)*(v2->y-v1->y) > (v0->y-v1->y)*(v2->x-v1->x)) 475 return; 476 477 // rotate so that v0 holds topmost y coord 478 // Note: The particular inequalities used ( <=, <, then <=) are important. 479 // They guarantee that if there are two verts on the top row, that 480 // they will be vert v0 and v1 (also could be three). 481 if (v1->y <= v2->y) 482 { 483 if (v1->y < v0->y) 484 { 485 const Point2I * tmp = v0; 486 v0 = v1; 487 v1 = v2; 488 v2 = tmp; 489 } 490 } 491 else 492 { 493 if (v2->y <= v0->y) 494 { 495 const Point2I * tmp = v0; 496 v0 = v2; 497 v2 = v1; 498 v1 = tmp; 499 } 500 } 501 502 // all the control variables we have to set up... 503 S32 leftDeltaY, xLeftInc = 0, xLeftErrInc, xLeftDir = 0, xLeft, xLeftErr = 0; 504 S32 rightDeltaY, xRightInc = 0, xRightErrInc, xRightDir = 0, xRight, xRightErr = 0; 505 S32 * changeThisDelta; 506 S32 * changeThisInc; 507 S32 * changeThisErrInc; 508 S32 * changeThisDir; 509 S32 toThisDelta; 510 S32 toThisInc; 511 S32 toThisErrInc; 512 S32 toThisDir; 513 S32 ySwitch; 514 S32 yBottom; 515 516 // check for special case where top row holds two verts 517 if (v0->y==v1->y) 518 { 519 leftDeltaY = v2->y-v0->y; 520 rightDeltaY = v2->y-v1->y; 521 ySwitch = v2->y; 522 yBottom = v2->y; 523 524 if (v1->y==v2->y) 525 { 526 // special-special case where top row holds all three verts 527 xLeft = getMin(getMin(v0->x,v1->x),v2->x); 528 xRight = getMax(getMax(v0->x,v1->x),v2->x); 529 xLeftErrInc = xRightErrInc = 0; 530 } 531 else 532 { 533 // standard-special case...v2 on different row from v0 and v1 534 xLeft = v0->x; 535 xLeftInc = (v2->x-v0->x) / leftDeltaY; 536 xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc; 537 xLeftDir = v2->x-v0->x > 0 ? 1 : -1; 538 539 xRight = v1->x; 540 xRightInc = (v2->x-v1->x) / rightDeltaY; 541 xRightErrInc = (v2->x-v1->x) - rightDeltaY*xRightInc; 542 xRightDir = v2->x-v1->x > 0 ? 1 : -1; 543 } 544 545 // set these variables to avoid a crash... 546 changeThisDelta = &toThisDelta; 547 changeThisInc = &toThisInc; 548 changeThisErrInc = &toThisErrInc; 549 changeThisDir = &toThisDir; 550 } 551 else 552 { 553 leftDeltaY = v2->y-v0->y; 554 xLeftInc = (v2->x-v0->x) / leftDeltaY; 555 xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc; 556 xLeftDir = v2->x-v0->x > 0 ? 1 : -1; 557 558 rightDeltaY = v1->y-v0->y; 559 xRightInc = (v1->x-v0->x) / rightDeltaY; 560 xRightErrInc = (v1->x-v0->x) - rightDeltaY*xRightInc; 561 xRightDir = v1->x-v0->x > 0 ? 1 : -1; 562 563 xLeft = xRight = v0->x; 564 565 if (v1->y<v2->y) 566 { 567 // right edge bends 568 changeThisDelta = &rightDeltaY; 569 changeThisInc = &xRightInc; 570 changeThisErrInc = &xRightErrInc; 571 changeThisDir = &xRightDir; 572 toThisDelta = v2->y-v1->y; 573 toThisInc = (v2->x-v1->x) / toThisDelta; 574 toThisErrInc = (v2->x-v1->x) - toThisDelta * toThisInc; 575 toThisDir = v2->x-v1->x > 0 ? 1 : -1; 576 ySwitch = v1->y-1; 577 yBottom = v2->y; 578 } 579 else 580 { 581 // left edge bends 582 changeThisDelta = &leftDeltaY; 583 changeThisInc = &xLeftInc; 584 changeThisErrInc = &xLeftErrInc; 585 changeThisDir = &xLeftDir; 586 toThisDelta = v1->y-v2->y; 587 toThisInc = toThisDelta ? (v1->x-v2->x) / toThisDelta : 0; 588 toThisErrInc = toThisDelta ? (v1->x-v2->x) - toThisDelta * toThisInc : 0; 589 toThisDir = v1->x-v2->x > 0 ? 1 : -1; 590 ySwitch = v2->y-1; 591 yBottom = v1->y; 592 } 593 } 594 xLeftErrInc *= xLeftDir; 595 xRightErrInc *= xRightDir; 596 toThisErrInc *= toThisDir; 597 598 U32 * rowStart = bits + v0->y * (dim>>5); 599 for (S32 y=v0->y; y<=yBottom;) 600 { 601 do 602 { 603 AssertFatal(xLeft<=xRight,"BitRender::render"); 604 605 U32 open = openTable[xLeft&31]; 606 U32 close = closeTable[xRight&31]; 607 if ( (xLeft^xRight) & ~31) 608 { 609 U32 * x = rowStart+(xLeft>>5); 610 *x |= open; 611 U32 * xEnd = rowStart+(xRight>>5); 612 while (++x<xEnd) 613 *x |= 0xFFFFFFFF; 614 *x |= close; 615 } 616 else 617 rowStart[xLeft>>5] |= open & close; 618 619 xLeft += xLeftInc; 620 xLeftErr += xLeftErrInc; 621 if (xLeftErr >= leftDeltaY) 622 { 623 xLeft += xLeftDir; 624 xLeftErr -= leftDeltaY; 625 } 626 627 xRight += xRightInc; 628 xRightErr += xRightErrInc; 629 if (xRightErr >= rightDeltaY) 630 { 631 xRight += xRightDir; 632 xRightErr -= rightDeltaY; 633 } 634 635 rowStart += dim>>5; 636 637 } while (y++<ySwitch); 638 639 ySwitch=yBottom; // get here at most twice 640 *changeThisDelta = toThisDelta; 641 *changeThisInc = toThisInc; 642 *changeThisErrInc = toThisErrInc; 643 *changeThisDir = toThisDir; 644 } 645} 646 647// These macros currently define how black the shadows get 648// Set the shift factor to zero results in totally black 649// shadows. Be nice to have this dynamic... 650#define SF(x) ((x) >> 2) 651#define SF32(a,b,c,d) {SF(a),SF(b),SF(c),SF(d)} 652 653/* 654// endian-ordering version of the SF macro, for the blur methods. 655#if PLATFORM_LITTLE_ENDIAN 656#define SF32E(a,b,c,d) SF32(a,b,c,d) 657#else 658#define SF32E(a,b,c,d) SF32(d,c,b,a) 659#endif 660*/ 661 662 663U8 bitTable[16][4] = 664{ 665 SF32( 0, 0, 0, 0), // 0 666 SF32(255, 0, 0, 0), // 1 667 SF32( 0,255, 0, 0), // 2 668 SF32(255,255, 0, 0), // 3 669 SF32( 0, 0,255, 0), // 4 670 SF32(255, 0,255, 0), // 5 671 SF32( 0,255,255, 0), // 6 672 SF32(255,255,255, 0), // 7 673 SF32( 0, 0, 0,255), // 8 674 SF32(255, 0, 0,255), // 9 675 SF32( 0,255, 0,255), // 10 676 SF32(255,255, 0,255), // 11 677 SF32( 0, 0,255,255), // 12 678 SF32(255, 0,255,255), // 13 679 SF32( 0,255,255,255), // 14 680 SF32(255,255,255,255), // 15 681}; 682 683void BitRender::bitTo8Bit(U32 * bits, U32 * eightBits, S32 dim) 684{ 685 dim *= dim>>5; 686 for (S32 i=0; i<dim; i++) 687 { 688 U32 val = *bits++; 689 690 *eightBits++ = *(U32*)&bitTable[val&0xF]; 691 val >>= 4; 692 693 *eightBits++ = *(U32*)&bitTable[val&0xF]; 694 val >>= 4; 695 696 *eightBits++ = *(U32*)&bitTable[val&0xF]; 697 val >>= 4; 698 699 *eightBits++ = *(U32*)&bitTable[val&0xF]; 700 val >>= 4; 701 702 *eightBits++ = *(U32*)&bitTable[val&0xF]; 703 val >>= 4; 704 705 *eightBits++ = *(U32*)&bitTable[val&0xF]; 706 val >>= 4; 707 708 *eightBits++ = *(U32*)&bitTable[val&0xF]; 709 val >>= 4; 710 711 *eightBits++ = *(U32*)&bitTable[val&0xF]; 712 val >>= 4; 713 } 714} 715 716 717U8 bitTableA[16][4] = 718{ 719 SF32( 0, 0, 0, 0), // 0 720 SF32( 0, 0, 0, 0), // 1 721 SF32( 0, 0, 0, 0), // 2 722 SF32( 0, 0, 0, 0), // 3 723 SF32( 0, 0, 0, 0), // 4 724 SF32( 0, 0, 0, 0), // 5 725 SF32( 0, 0, 0, 0), // 6 726 SF32( 0, 0, 0, 0), // 7 727 SF32( 17, 0, 0, 0), // 8 728 SF32( 17, 0, 0, 0), // 9 729 SF32( 17, 0, 0, 0), // 10 730 SF32( 17, 0, 0, 0), // 11 731 SF32( 17, 0, 0, 0), // 12 732 SF32( 17, 0, 0, 0), // 13 733 SF32( 17, 0, 0, 0), // 14 734 SF32( 17, 0, 0, 0), // 15 735}; 736 737U8 bitTableB[16][4] = 738{ 739 SF32( 0, 0, 0, 0), // 0 740 SF32( 34, 17, 0, 0), // 1 741 SF32( 17, 34, 17, 0), // 2 742 SF32( 51, 51, 17, 0), // 3 743 SF32( 0, 17, 34, 17), // 4 744 SF32( 34, 34, 34, 17), // 5 745 SF32( 17, 51, 51, 17), // 6 746 SF32( 51, 68, 51, 17), // 7 747 SF32( 0, 0, 17, 34), // 8 748 SF32( 34, 17, 17, 34), // 9 749 SF32( 17, 34, 34, 34), // 10 750 SF32( 51, 51, 34, 34), // 11 751 SF32( 0, 17, 51, 51), // 12 752 SF32( 34, 34, 51, 51), // 13 753 SF32( 17, 51, 68, 51), // 14 754 SF32( 51, 68, 68, 51), // 15 755}; 756 757 758U8 bitTableC[16][4] = 759{ 760 SF32( 0, 0, 0, 0), // 0 761 SF32( 0, 0, 0, 17), // 1 762 SF32( 0, 0, 0, 0), // 2 763 SF32( 0, 0, 0, 17), // 3 764 SF32( 0, 0, 0, 0), // 4 765 SF32( 0, 0, 0, 17), // 5 766 SF32( 0, 0, 0, 0), // 6 767 SF32( 0, 0, 0, 17), // 7 768 SF32( 0, 0, 0, 0), // 8 769 SF32( 0, 0, 0, 17), // 9 770 SF32( 0, 0, 0, 0), // 10 771 SF32( 0, 0, 0, 17), // 11 772 SF32( 0, 0, 0, 0), // 12 773 SF32( 0, 0, 0, 17), // 13 774 SF32( 0, 0, 0, 0), // 14 775 SF32( 0, 0, 0, 17), // 15 776}; 777 778U8 bitTableE[16][4] = 779{ 780 SF32( 0, 0, 0, 0), // 0 781 SF32( 51, 34, 0, 0), // 1 782 SF32( 34, 51, 34, 0), // 2 783 SF32( 85, 85, 34, 0), // 3 784 SF32( 0, 34, 51, 34), // 4 785 SF32( 51, 68, 51, 34), // 5 786 SF32( 34, 85, 85, 34), // 6 787 SF32( 85,119, 85, 34), // 7 788 SF32( 0, 0, 34, 51), // 8 789 SF32( 51, 34, 34, 51), // 9 790 SF32( 34, 51, 68, 51), // 10 791 SF32( 85, 85, 68, 51), // 11 792 SF32( 0, 34, 85, 85), // 12 793 SF32( 51, 68, 85, 85), // 13 794 SF32( 34, 85,119, 85), // 14 795 SF32( 85,119,119, 85), // 15 796}; 797 798void BitRender::bitTo8Bit_3(U32 * bits, U32 * eightBits, S32 dim) 799{ 800#if defined(TORQUE_BIG_ENDIAN) 801#define MAX_SHADOW_TEXELS (256 + 4) //256 seems big enough, +4 so we can run off end of buffer. 802 // slow fake gaussian 803 S32 i, j, c; 804 U8 tmpLine[3][MAX_SHADOW_TEXELS]; 805 U8 *src0, *src1, *src2; 806 U8 *s0, *s1, *s2; 807 U32 dimS2 = dim>>2; 808 U32 *src32; 809 U32 *currLine = bits; 810 U32 currVal; 811 U32 sampleVal; 812 U8 c00, c01, c02, c10, c11, c12, c20, c21, c22; 813 S32 openBuf; 814 815 src0 = tmpLine[0]; 816 src1 = tmpLine[1]; 817 src2 = tmpLine[2]; 818 openBuf = 2; // the one src2 is using right now. 819 820 // pre-process two rows into our tmp buffers. 821 src32 = (U32*)(src0); 822 for(i=0; i<(dimS2>>3); i++) // walk 4 bytes at a time, 4 bits at a time. 823 { 824 currVal = *currLine++; 825 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 826 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 827 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 828 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 829 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 830 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 831 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 832 *src32++ = *(U32*)&bitTable[currVal]; 833 } 834 835 src32 = (U32*)(src1); 836 for(i=0; i<(dimS2>>3); i++) 837 { 838 currVal = *currLine++; 839 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 840 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 841 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 842 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 843 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 844 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 845 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 846 *src32++ = *(U32*)&bitTable[currVal]; 847 } 848 849 // pre-clear first row of depth buffer. 850 for (i=0; i<dimS2; i++) 851 *eightBits++ = 0L; 852 853 // start. 854 j = dim - 2; // we pre-process two lines, and only really do the internal -2 rows 855 while (j>0) 856 { 857 j--; 858 // process new line (currLine) into new tmp buffer (src2) 859 src32 = (U32*)(src2); 860 for(i=0; i<(dimS2>>3); i++) // 8 at a time. 861 { 862 currVal = *currLine++; 863 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 864 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 865 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 866 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 867 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 868 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 869 *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4; 870 *src32++ = *(U32*)&bitTable[currVal]; 871 } 872 873 // blur & copy current src1 to current dest 874#if NO_BLUR 875 // test for basic functionality. 876 srcTmp = src1; 877 src32 = (U32*)srcTmp; 878 for (i=0; i<dimS2; i++) 879 *eightBits++ = *src32++; 880#else 881 s0 = src0; 882 s1 = src1; 883 s2 = src2; 884 // c#0 will be copied in at end of loop... 885 c00 = 0; c01 = *s0++; 886 c10 = 0; c11 = *s1++; 887 c20 = 0; c21 = *s2++; 888 for (i=0; i<dimS2; i++) // process samples in 32bit inc. 889 { 890 currVal = 0L; 891 for (c=0; c<4; c++) 892 { 893 // update right-edge samples -- for very last pixel this reads off end of real data. 894 c02 = *s0++; 895 c12 = *s1++; 896 c22 = *s2++; 897 898 // process sample i*4+c 899 if (!i && !c) // very first pixel 900 sampleVal = 0; //c11; // take mid as it's the right thing. 901 else 902 if (i==(dimS2-1) && c==3) // very last pixel 903 sampleVal = 0; //c12; // take end. 904 else // inner pixel 905 { 906 const S32 wXP = 3; // corners 907 const S32 wPP = 4; // plus/NSEW 908 const S32 wCP = 4; // center 909 sampleVal = (c00+c02+c20+c22)*wXP + (c01+c10+c12+c21)*wPP + c11*wCP; 910 sampleVal >>= 5; // div by 32 subsamples 911 } 912 // mix into val store to hold. 913 currVal |= sampleVal << (8*(3-c)); 914 c00 = c01; c01 = c02; 915 c10 = c11; c11 = c12; 916 c20 = c21; c21 = c22; 917 //c#2 defd next time round 918 } 919 // put samples into dest buffer. 920 *eightBits++ = currVal; 921 } 922#endif 923 924 // flip around ptrs for next row processing. 925 openBuf++; 926 if (openBuf>2) 927 openBuf = 0; 928 src0 = src1; 929 src1 = src2; 930 src2 = tmpLine[openBuf]; 931 } 932 933 // clear last dest buffer row 934 for (i=0; i<dimS2; i++) 935 *eightBits++ = 0L; 936 937#else // the old windows implementation, which isn't working on Mac right now. 938 // clear out first row of dest 939 U32 * end32 = eightBits + (dim>>2); 940 do { *eightBits++=0; } while (eightBits<end32); 941 end32 += (dim>>2)*(dim-1); 942 943 U8 * p0 = (U8*)bits; 944 U8 bitLo10 = 0x0F & *p0; 945 U8 bitHi10 = (*p0) >> 4; 946 p0++; 947 948 U8 * p1 = (U8*)bits + (dim>>3); 949 U8 bitLo11 = 0x0F & *p1; 950 U8 bitHi11 = (*p1) >> 4; 951 p1++; 952 953 U8 * p2 = (U8*)bits + (dim>>2); 954 U8 bitLo12 = 0x0F & *p2; 955 U8 bitHi12 = (*p2) >> 4; 956 p2++; 957 958 U8 bitLo20, bitHi20; 959 U8 bitLo21, bitHi21; 960 U8 bitLo22, bitHi22; 961 U8 bitHi00 = 0; 962 U8 bitHi01 = 0; 963 U8 bitHi02 = 0; 964 965 // go thru penultimate row (but stop before last entry in that row) 966 U8 * end = (U8*)bits + dim*(dim>>3) - 1; 967 do 968 { 969 bitLo20 = 0x0F & *p0; 970 bitHi20 = (*p0) >> 4; 971 bitLo21 = 0x0F & *p1; 972 bitHi21 = (*p1) >> 4; 973 bitLo22 = 0x0F & *p2; 974 bitHi22 = (*p2) >> 4; 975 976 *eightBits++ = *(U32*)&bitTableA[bitHi00] + *(U32*)&bitTableB[bitLo10] + *(U32*)&bitTableC[bitHi10] + 977 *(U32*)&bitTableA[bitHi01]*2 + *(U32*)&bitTableE[bitLo11] + *(U32*)&bitTableC[bitHi11]*2 + 978 *(U32*)&bitTableA[bitHi02] + *(U32*)&bitTableB[bitLo12] + *(U32*)&bitTableC[bitHi12]; 979 *eightBits++ = *(U32*)&bitTableA[bitLo10] + *(U32*)&bitTableB[bitHi10] + *(U32*)&bitTableC[bitLo20] + 980 *(U32*)&bitTableA[bitLo11]*2 + *(U32*)&bitTableE[bitHi11] + *(U32*)&bitTableC[bitLo21]*2 + 981 *(U32*)&bitTableA[bitLo12] + *(U32*)&bitTableB[bitHi12] + *(U32*)&bitTableC[bitLo22]; 982 983 bitHi00 = bitHi10; 984 bitLo10 = bitLo20; 985 bitHi10 = bitHi20; 986 bitHi01 = bitHi11; 987 bitLo11 = bitLo21; 988 bitHi11 = bitHi21; 989 bitHi02 = bitHi12; 990 bitLo12 = bitLo22; 991 bitHi12 = bitHi22; 992 993 p0++; 994 p1++; 995 p2++; 996 } 997 while (p2<end); 998 999 // clear out last row of dest 1000 do { *eightBits++=0; } while (eightBits<end32); 1001#endif 1002} 1003 1004 1005 1006