bitRender.cpp

Engine/source/core/bitRender.cpp

More...

Classes:

Public Defines

define
SF(x) ((x) >> 2)
define
SF32(a, b, c, d) {(),(),(c),(d)}

Public Variables

bitTable [16][4]
bitTableA [16][4]
bitTableB [16][4]
bitTableC [16][4]
bitTableE [16][4]

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