QuadBlitter_scanning.inl
Go to the documentation of this file.00001 #define SETUP_SECOND_UV 00002 #ifdef USE_UV 00003 #undef SETUP_SECOND_UV 00004 #define SETUP_SECOND_UV u0=u0b;v0=v0b;u1=u1b;v1=v1b; 00005 #endif 00006 00007 #define SET_UV(uv0u,uv0v,uv1u,uv1v) u0=uv0u;v0=uv0v;u1=uv1u;v1=uv1v; 00008 00009 00010 #define SET_UV_TWO(uv0u,uv0v,uv1u,uv1v,uv0ub,uv0vb,uv1ub,uv1vb) u0=uv0u;v0=uv0v;u1=uv1u;v1=uv1v; u0b=uv0ub;v0b=uv0vb;u1b=uv1ub;v1b=uv1vb; 00011 00012 #define INT_SETUP_UV 00013 #ifdef USE_UV 00014 #undef INT_SETUP_UV 00015 #define INT_SETUP_UV \ 00016 int stepU=(u1-u0)/(DeltaY);\ 00017 int stepV=(v1-v0)/(DeltaY);\ 00018 00019 #endif 00020 00021 #define INT_UPDATE_UV 00022 #ifdef USE_UV 00023 #undef INT_UPDATE_UV 00024 #define INT_UPDATE_UV \ 00025 u0+=stepU;\ 00026 v0+=stepV;\ 00027 00028 #endif 00029 00030 #define INT_ASSIGN_UV 00031 #ifdef USE_UV 00032 #undef INT_ASSIGN_UV 00033 #define INT_ASSIGN_UV \ 00034 (*tempBuffer).u=u0; \ 00035 (*tempBuffer).v=v0; \ 00036 00037 #endif 00038 00039 #define INTERPOLATE_EDGE_XMAJOR(X0,Y0,DeltaX,DeltaY,XDirection)\ 00040 {\ 00041 INT_SETUP_UV\ 00042 int XMajorAdvanceAmt=(DeltaX/DeltaY)*XDirection;\ 00043 int ErrorTermAdvance=DeltaX%DeltaY;\ 00044 int ErrorTerm=0;\ 00045 int height=DeltaY;\ 00046 if (XDirection<0)\ 00047 {\ 00048 ErrorTerm = -DeltaY + 1; \ 00049 }\ 00050 (*tempBuffer).x=(unsigned short)X0; \ 00051 INT_ASSIGN_UV\ 00052 while ( DeltaY-- )\ 00053 {\ 00054 INT_UPDATE_UV\ 00055 X0 += XMajorAdvanceAmt; \ 00056 ErrorTerm += ErrorTermAdvance;\ 00057 if (ErrorTerm > 0) \ 00058 {\ 00059 X0 += XDirection; \ 00060 ErrorTerm -= height; \ 00061 }\ 00062 tempBuffer+=2;\ 00063 (*tempBuffer).x=(unsigned short)X0; \ 00064 INT_ASSIGN_UV\ 00065 }\ 00066 }\ 00067 00068 00069 00070 #define INTERPOLATE_EDGE_YMAJOR(X0,Y0,DeltaX,DeltaY,XDirection)\ 00071 {\ 00072 INT_SETUP_UV\ 00073 /* Set up initial error term and values used inside drawing loop */\ 00074 int DeltaXx2 = DeltaX + DeltaX;\ 00075 int DeltaXx2MinusDeltaYx2 = DeltaXx2 - ( DeltaY + DeltaY );\ 00076 int ErrorTerm = DeltaXx2 - DeltaY;\ 00077 (*tempBuffer).x=(unsigned short)X0; \ 00078 INT_ASSIGN_UV\ 00079 while ( DeltaY-- ) \ 00080 {\ 00081 INT_UPDATE_UV\ 00082 /* See if it's time to advance the X coordinate */\ 00083 if ( ErrorTerm >= 0 ) \ 00084 {\ 00085 /* Advance the X coordinate & adjust the error term back down */\ 00086 X0 += XDirection;\ 00087 ErrorTerm += DeltaXx2MinusDeltaYx2;\ 00088 } \ 00089 else \ 00090 {\ 00091 /* Add to the error term */\ 00092 ErrorTerm += DeltaXx2;\ 00093 }\ 00094 tempBuffer+=2;\ 00095 (*tempBuffer).x=(unsigned short)X0; \ 00096 INT_ASSIGN_UV\ 00097 }\ 00098 }\ 00099 00100 00101 00102 #define EGDE_INTERPOLATION(XP0,YP0,XP1,YP1) \ 00103 {\ 00104 int X0=XP0;\ 00105 int Y0=YP0;\ 00106 int X1=XP1;\ 00107 int Y1=YP1;\ 00108 /* calculate the length of the line in each coordinate */\ 00109 int DeltaX=X1-X0; \ 00110 int DeltaY=Y1-Y0;\ 00111 /* Handle as four separate cases, for the four octants in which Y1 is greater than Y0 */\ 00112 if (DeltaX>0 ) \ 00113 {\ 00114 int XDirection=1;\ 00115 if (DeltaX>DeltaY)\ 00116 {\ 00117 INTERPOLATE_EDGE_XMAJOR(X0, Y0, DeltaX, DeltaY, 1);\ 00118 } \ 00119 else \ 00120 {\ 00121 INTERPOLATE_EDGE_YMAJOR(X0, Y0, DeltaX, DeltaY, 1);\ 00122 }\ 00123 } \ 00124 else \ 00125 {\ 00126 int XDirection=-1;\ 00127 DeltaX=-DeltaX; /* absolute value of DeltaX */\ 00128 if (DeltaX>DeltaY ) \ 00129 {\ 00130 INTERPOLATE_EDGE_XMAJOR(X0, Y0, DeltaX, DeltaY, -1);\ 00131 } \ 00132 else \ 00133 {\ 00134 INTERPOLATE_EDGE_YMAJOR(X0, Y0, DeltaX, DeltaY, -1);\ 00135 }\ 00136 }\ 00137 }\ 00138 00139 00140 #define ScanEdge(x1, y1, x2, y2, edgeBufferPtr) \ 00141 { \ 00142 int tempX1=x1;\ 00143 int tempY1=y1;\ 00144 int tempX2=x2;\ 00145 int tempY2=y2;\ 00146 EDGE_TYPE* tempBuffer=edgeBufferPtr;\ 00147 EGDE_INTERPOLATION(tempX1,tempY1,tempX2,tempY2); \ 00148 }\ 00149 00150 00151 #define ScanTwoEdges(x1a, y1a, x2a, y2a, x1b, y1b, x2b, y2b, edgeBufferPtr) \ 00152 { \ 00153 int tempX1a=x1a;\ 00154 int tempY1a=y1a;\ 00155 int tempX2a=x2a;\ 00156 int tempY2a=y2a;\ 00157 int tempX1b=x1b;\ 00158 int tempY1b=y1b;\ 00159 int tempX2b=x2b;\ 00160 int tempY2b=y2b;\ 00161 EDGE_TYPE* tempBuffer=edgeBufferPtr;\ 00162 EGDE_INTERPOLATION(tempX1a,tempY1a,tempX2a,tempY2a); \ 00163 SETUP_SECOND_UV\ 00164 EGDE_INTERPOLATION(tempX1b,tempY1b,tempX2b,tempY2b); \ 00165 }\ 00166 00167 00168 //*** MAIN CODE *** 00169 00170 00171 int p0x=targetX1; 00172 int p0y=targetY1; 00173 int p1x=targetX2; 00174 int p1y=targetY2; 00175 int p2x=targetX3; 00176 int p2y=targetY3; 00177 int p3x=targetX4; 00178 int p3y=targetY4; 00179 00180 #ifdef USE_UV 00181 int s0x=sourceX1<<16; 00182 int s0y=sourceY1<<16; 00183 int s1x=sourceX2<<16; 00184 int s1y=sourceY2<<16; 00185 int s2x=sourceX3<<16; 00186 int s2y=sourceY3<<16; 00187 int s3x=sourceX4<<16; 00188 int s3y=sourceY4<<16; 00189 #endif 00190 00191 // order by y 00192 if (p1y<p0y) 00193 { 00194 Swap(p1x,p0x); 00195 Swap(p1y,p0y); 00196 #ifdef USE_UV 00197 Swap(s1x,s0x); 00198 Swap(s1y,s0y); 00199 #endif 00200 } 00201 if (p2y<p0y) 00202 { 00203 Swap(p2x,p0x); 00204 Swap(p2y,p0y); 00205 #ifdef USE_UV 00206 Swap(s2x,s0x); 00207 Swap(s2y,s0y); 00208 #endif 00209 } 00210 if (p3y<p0y) 00211 { 00212 Swap(p3x,p0x); 00213 Swap(p3y,p0y); 00214 #ifdef USE_UV 00215 Swap(s3x,s0x); 00216 Swap(s3y,s0y); 00217 #endif 00218 } 00219 if (p2y<p1y) 00220 { 00221 Swap(p2x,p1x); 00222 Swap(p2y,p1y); 00223 #ifdef USE_UV 00224 Swap(s2x,s1x); 00225 Swap(s2y,s1y); 00226 #endif 00227 } 00228 if (p3y<p1y) 00229 { 00230 Swap(p3x,p1x); 00231 Swap(p3y,p1y); 00232 #ifdef USE_UV 00233 Swap(s3x,s1x); 00234 Swap(s3y,s1y); 00235 #endif 00236 } 00237 if (p3y<p2y) 00238 { 00239 Swap(p3x,p2x); 00240 Swap(p3y,p2y); 00241 #ifdef USE_UV 00242 Swap(s3x,s2x); 00243 Swap(s3y,s2y); 00244 #endif 00245 } 00246 00247 Assert(p0y<=p1y && p1y<=p2y && p2y<=p3y,"Sort order error"); 00248 00249 // Allocate or reallocate edge buffer if needed 00250 edgeBuffer_.SetMinSize(sizeof(EDGE_TYPE)*2*(p3y-p0y+1)); 00251 EDGE_TYPE* edgeBuffer=static_cast<EDGE_TYPE*>(edgeBuffer_.buffer_); 00252 00253 #ifdef USE_UV 00254 int u0=0; 00255 int v0=0; 00256 int u1=0; 00257 int v1=0; 00258 int u0b=0; 00259 int v0b=0; 00260 int u1b=0; 00261 int v1b=0; 00262 #endif 00263 00264 // Flat top and bottom? 00265 if (p0y==p1y && p2y==p3y) 00266 { 00267 if (p0x<p1x) 00268 { 00269 #ifdef USE_UV 00270 SET_UV(s0x,s0y,s3x,s3y); 00271 #endif 00272 ScanEdge(p0x,p0y,p3x,p3y,edgeBuffer); 00273 00274 #ifdef USE_UV 00275 SET_UV(s1x,s1y,s2x,s2y); 00276 #endif 00277 ScanEdge(p1x,p1y,p2x,p2y,edgeBuffer+1); 00278 } 00279 else 00280 { 00281 #ifdef USE_UV 00282 SET_UV(s1x,s1y,s2x,s2y); 00283 #endif 00284 ScanEdge(p1x,p1y,p2x,p2y,edgeBuffer); 00285 00286 #ifdef USE_UV 00287 SET_UV(s0x,s0y,s3x,s3y); 00288 #endif 00289 ScanEdge(p0x,p0y,p3x,p3y,edgeBuffer+1); 00290 } 00291 } 00292 00293 // Flat top? 00294 else if (p0y==p1y) 00295 { 00296 if (p0x<p1x) 00297 { 00298 if (p2x<p3x) 00299 { 00300 //0 to 2, 2 to 3 00301 #ifdef USE_UV 00302 SET_UV_TWO(s0x,s0y,s2x,s2y,s2x,s2y,s3x,s3y); 00303 #endif 00304 ScanTwoEdges(p0x,p0y,p2x,p2y,p2x,p2y,p3x,p3y,edgeBuffer); 00305 00306 //1 to 3 00307 #ifdef USE_UV 00308 SET_UV(s1x,s1y,s3x,s3y); 00309 #endif 00310 ScanEdge(p1x,p1y,p3x,p3y,edgeBuffer+1); 00311 } 00312 else 00313 { 00314 //0 to 3 00315 #ifdef USE_UV 00316 SET_UV(s0x,s0y,s3x,s3y); 00317 #endif 00318 ScanEdge(p0x,p0y,p3x,p3y,edgeBuffer); 00319 00320 //1 to 2, 2 to 3 00321 #ifdef USE_UV 00322 SET_UV_TWO(s1x,s1y,s2x,s2y,s2x,s2y,s3x,s3y); 00323 #endif 00324 ScanTwoEdges(p1x,p1y,p2x,p2y,p2x,p2y,p3x,p3y,edgeBuffer+1); 00325 } 00326 } 00327 else 00328 { 00329 if (p2x<p3x) 00330 { 00331 // 1 to 2, 2 to 3 00332 #ifdef USE_UV 00333 SET_UV_TWO(s1x,s1y,s2x,s2y,s2x,s2y,s3x,s3y); 00334 #endif 00335 ScanTwoEdges(p1x,p1y,p2x,p2y,p2x,p2y,p3x,p3y,edgeBuffer); 00336 00337 //0 to 3 00338 #ifdef USE_UV 00339 SET_UV(s0x,s0y,s3x,s3y); 00340 #endif 00341 ScanEdge(p0x,p0y,p3x,p3y,edgeBuffer+1); 00342 } 00343 else 00344 { 00345 // 1 to 3 00346 #ifdef USE_UV 00347 SET_UV(s1x,s1y,s3x,s3y); 00348 #endif 00349 ScanEdge(p1x,p1y,p3x,p3y,edgeBuffer); 00350 00351 // 0 to 2, 2 to 3 00352 #ifdef USE_UV 00353 SET_UV_TWO(s0x,s0y,s2x,s2y,s2x,s2y,s3x,s3y); 00354 #endif 00355 ScanTwoEdges(p0x,p0y,p2x,p2y,p2x,p2y,p3x,p3y,edgeBuffer+1); 00356 } 00357 } 00358 } 00359 00360 // Flat bottom? 00361 else if (p2y==p3y) 00362 { 00363 if (p3x<p2x) 00364 { 00365 if (p1x<p0x) 00366 { 00367 // 0 to 1, 1 to 3 00368 #ifdef USE_UV 00369 SET_UV_TWO(s0x,s0y,s1x,s1y,s1x,s1y,s3x,s3y); 00370 #endif 00371 ScanTwoEdges(p0x,p0y,p1x,p1y,p1x,p1y,p3x,p3y,edgeBuffer); 00372 00373 // 0 to 2 00374 #ifdef USE_UV 00375 SET_UV(s0x,s0y,s2x,s2y); 00376 #endif 00377 ScanEdge(p0x,p0y,p2x,p2y,edgeBuffer+1); 00378 } 00379 else 00380 { 00381 // 0 to 3 00382 #ifdef USE_UV 00383 SET_UV(s0x,s0y,s3x,s3y); 00384 #endif 00385 ScanEdge(p0x,p0y,p3x,p3y,edgeBuffer); 00386 00387 // 0 to 1, 1 to 2 00388 #ifdef USE_UV 00389 SET_UV_TWO(s0x,s0y,s1x,s1y,s1x,s1y,s2x,s2y); 00390 #endif 00391 ScanTwoEdges(p0x,p0y,p1x,p1y,p1x,p1y,p2x,p2y,edgeBuffer+1); 00392 } 00393 } 00394 else 00395 { 00396 if (p0x<p1x) 00397 { 00398 // 0 to 2 00399 #ifdef USE_UV 00400 SET_UV(s0x,s0y,s2x,s2y); 00401 #endif 00402 ScanEdge(p0x,p0y,p2x,p2y,edgeBuffer); 00403 00404 // 0 to 1, 1 to 3 00405 #ifdef USE_UV 00406 SET_UV_TWO(s0x,s0y,s1x,s1y,s1x,s1y,s3x,s3y); 00407 #endif 00408 ScanTwoEdges(p0x,p0y,p1x,p1y,p1x,p1y,p3x,p3y,edgeBuffer+1); 00409 } 00410 else 00411 { 00412 // 0 to 1, 1 to 2 00413 #ifdef USE_UV 00414 SET_UV_TWO(s0x,s0y,s1x,s1y,s1x,s1y,s2x,s2y); 00415 #endif 00416 ScanTwoEdges(p0x,p0y,p1x,p1y,p1x,p1y,p2x,p2y,edgeBuffer); 00417 00418 // 0 to 3 00419 #ifdef USE_UV 00420 SET_UV(s0x,s0y,s3x,s3y); 00421 #endif 00422 ScanEdge(p0x,p0y,p3x,p3y,edgeBuffer+1); 00423 } 00424 00425 } 00426 } 00427 00428 // Generic case 00429 else 00430 { 00431 if (p1x<p2x) 00432 { 00433 #ifdef USE_UV 00434 SET_UV_TWO(s0x,s0y,s1x,s1y,s1x,s1y,s3x,s3y); 00435 #endif 00436 ScanTwoEdges(p0x,p0y,p1x,p1y,p1x,p1y,p3x,p3y,edgeBuffer); 00437 00438 #ifdef USE_UV 00439 SET_UV_TWO(s0x,s0y,s2x,s2y,s2x,s2y,s3x,s3y); 00440 #endif 00441 ScanTwoEdges(p0x,p0y,p2x,p2y,p2x,p2y,p3x,p3y,edgeBuffer+1); 00442 } 00443 else 00444 { 00445 #ifdef USE_UV 00446 SET_UV_TWO(s0x,s0y,s2x,s2y,s2x,s2y,s3x,s3y); 00447 #endif 00448 ScanTwoEdges(p0x,p0y,p2x,p2y,p2x,p2y,p3x,p3y,edgeBuffer); 00449 00450 #ifdef USE_UV 00451 SET_UV_TWO(s0x,s0y,s1x,s1y,s1x,s1y,s3x,s3y); 00452 #endif 00453 ScanTwoEdges(p0x,p0y,p1x,p1y,p1x,p1y,p3x,p3y,edgeBuffer+1); 00454 } 00455 } 00456 00457 #undef INTERPOLATE_EDGE_XMAJOR 00458 #undef INTERPOLATE_EDGE_YMAJOR 00459 #undef EGDE_INTERPOLATION 00460 #undef ScanEdge 00461 #undef ScanTwoEdges 00462 #undef SETUP_SECOND_UV 00463 #undef SET_UV 00464 #undef SET_UV_TWO 00465 #undef INT_SETUP_UV 00466 #undef INT_UPDATE_UV 00467 #undef INT_ASSIGN_UV
Reproduction/republishing of any material on this site without permission is strictly prohibited.
