|
Blender
V2.59
|
00001 /* 00002 * $Id: zbuf.c 38092 2011-07-04 19:22:37Z jbakker $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * Contributors: Hos, RPW 00024 * 2004-2006 Blender Foundation, full recode 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00035 /*---------------------------------------------------------------------------*/ 00036 /* Common includes */ 00037 /*---------------------------------------------------------------------------*/ 00038 00039 #include <math.h> 00040 #include <float.h> 00041 #include <stdlib.h> 00042 #include <limits.h> 00043 #include <string.h> 00044 00045 #include "BLI_math.h" 00046 #include "BLI_blenlib.h" 00047 #include "BLI_jitter.h" 00048 #include "BLI_threads.h" 00049 #include "BLI_utildefines.h" 00050 00051 #include "MEM_guardedalloc.h" 00052 00053 #include "DNA_lamp_types.h" 00054 #include "DNA_mesh_types.h" 00055 #include "DNA_node_types.h" 00056 #include "DNA_meshdata_types.h" 00057 #include "DNA_material_types.h" 00058 00059 #include "BKE_global.h" 00060 #include "BKE_material.h" 00061 00062 00063 #include "RE_render_ext.h" 00064 00065 /* local includes */ 00066 #include "gammaCorrectionTables.h" 00067 #include "pixelblending.h" 00068 #include "render_types.h" 00069 #include "renderpipeline.h" 00070 #include "renderdatabase.h" 00071 #include "rendercore.h" 00072 #include "shadbuf.h" 00073 #include "shading.h" 00074 #include "sss.h" 00075 #include "strand.h" 00076 00077 /* own includes */ 00078 #include "zbuf.h" 00079 00080 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00081 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ 00082 /* only to be used here in this file, it's for speed */ 00083 extern struct Render R; 00084 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00085 00086 00087 /* ****************** Spans ******************************* */ 00088 00089 /* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */ 00090 void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop) 00091 { 00092 memset(zspan, 0, sizeof(ZSpan)); 00093 00094 zspan->rectx= rectx; 00095 zspan->recty= recty; 00096 00097 zspan->span1= MEM_mallocN(recty*sizeof(float), "zspan"); 00098 zspan->span2= MEM_mallocN(recty*sizeof(float), "zspan"); 00099 00100 zspan->clipcrop= clipcrop; 00101 } 00102 00103 void zbuf_free_span(ZSpan *zspan) 00104 { 00105 if(zspan) { 00106 if(zspan->span1) MEM_freeN(zspan->span1); 00107 if(zspan->span2) MEM_freeN(zspan->span2); 00108 zspan->span1= zspan->span2= NULL; 00109 } 00110 } 00111 00112 /* reset range for clipping */ 00113 static void zbuf_init_span(ZSpan *zspan) 00114 { 00115 zspan->miny1= zspan->miny2= zspan->recty+1; 00116 zspan->maxy1= zspan->maxy2= -1; 00117 zspan->minp1= zspan->maxp1= zspan->minp2= zspan->maxp2= NULL; 00118 } 00119 00120 static void zbuf_add_to_span(ZSpan *zspan, float *v1, float *v2) 00121 { 00122 float *minv, *maxv, *span; 00123 float xx1, dx0, xs0; 00124 int y, my0, my2; 00125 00126 if(v1[1]<v2[1]) { 00127 minv= v1; maxv= v2; 00128 } 00129 else { 00130 minv= v2; maxv= v1; 00131 } 00132 00133 my0= ceil(minv[1]); 00134 my2= floor(maxv[1]); 00135 00136 if(my2<0 || my0>= zspan->recty) return; 00137 00138 /* clip top */ 00139 if(my2>=zspan->recty) my2= zspan->recty-1; 00140 /* clip bottom */ 00141 if(my0<0) my0= 0; 00142 00143 if(my0>my2) return; 00144 /* if(my0>my2) should still fill in, that way we get spans that skip nicely */ 00145 00146 xx1= maxv[1]-minv[1]; 00147 if(xx1>FLT_EPSILON) { 00148 dx0= (minv[0]-maxv[0])/xx1; 00149 xs0= dx0*(minv[1]-my2) + minv[0]; 00150 } 00151 else { 00152 dx0= 0.0f; 00153 xs0= MIN2(minv[0],maxv[0]); 00154 } 00155 00156 /* empty span */ 00157 if(zspan->maxp1 == NULL) { 00158 span= zspan->span1; 00159 } 00160 else { /* does it complete left span? */ 00161 if( maxv == zspan->minp1 || minv==zspan->maxp1) { 00162 span= zspan->span1; 00163 } 00164 else { 00165 span= zspan->span2; 00166 } 00167 } 00168 00169 if(span==zspan->span1) { 00170 // printf("left span my0 %d my2 %d\n", my0, my2); 00171 if(zspan->minp1==NULL || zspan->minp1[1] > minv[1] ) { 00172 zspan->minp1= minv; 00173 } 00174 if(zspan->maxp1==NULL || zspan->maxp1[1] < maxv[1] ) { 00175 zspan->maxp1= maxv; 00176 } 00177 if(my0<zspan->miny1) zspan->miny1= my0; 00178 if(my2>zspan->maxy1) zspan->maxy1= my2; 00179 } 00180 else { 00181 // printf("right span my0 %d my2 %d\n", my0, my2); 00182 if(zspan->minp2==NULL || zspan->minp2[1] > minv[1] ) { 00183 zspan->minp2= minv; 00184 } 00185 if(zspan->maxp2==NULL || zspan->maxp2[1] < maxv[1] ) { 00186 zspan->maxp2= maxv; 00187 } 00188 if(my0<zspan->miny2) zspan->miny2= my0; 00189 if(my2>zspan->maxy2) zspan->maxy2= my2; 00190 } 00191 00192 for(y=my2; y>=my0; y--, xs0+= dx0) { 00193 /* xs0 is the xcoord! */ 00194 span[y]= xs0; 00195 } 00196 } 00197 00198 /*-----------------------------------------------------------*/ 00199 /* Functions */ 00200 /*-----------------------------------------------------------*/ 00201 00202 void fillrect(int *rect, int x, int y, int val) 00203 { 00204 int len, *drect; 00205 00206 len= x*y; 00207 drect= rect; 00208 while(len>0) { 00209 len--; 00210 *drect= val; 00211 drect++; 00212 } 00213 } 00214 00215 /* based on Liang&Barsky, for clipping of pyramidical volume */ 00216 static short cliptestf(float p, float q, float *u1, float *u2) 00217 { 00218 float r; 00219 00220 if(p<0.0) { 00221 if(q<p) return 0; 00222 else if(q<0.0) { 00223 r= q/p; 00224 if(r>*u2) return 0; 00225 else if(r>*u1) *u1=r; 00226 } 00227 } 00228 else { 00229 if(p>0.0) { 00230 if(q<0.0) return 0; 00231 else if(q<p) { 00232 r= q/p; 00233 if(r<*u1) return 0; 00234 else if(r<*u2) *u2=r; 00235 } 00236 } 00237 else if(q<0.0) return 0; 00238 } 00239 return 1; 00240 } 00241 00242 int testclip(float *v) 00243 { 00244 float abs4; /* WATCH IT: this function should do the same as cliptestf, otherwise troubles in zbufclip()*/ 00245 short c=0; 00246 00247 /* if we set clip flags, the clipping should be at least larger than epsilon. 00248 prevents issues with vertices lying exact on borders */ 00249 abs4= fabs(v[3]) + FLT_EPSILON; 00250 00251 if( v[0] < -abs4) c+=1; 00252 else if( v[0] > abs4) c+=2; 00253 00254 if( v[1] > abs4) c+=4; 00255 else if( v[1] < -abs4) c+=8; 00256 00257 if(v[2] < -abs4) c+=16; /* this used to be " if(v[2]<0) ", see clippz() */ 00258 else if(v[2]> abs4) c+= 32; 00259 00260 return c; 00261 } 00262 00263 00264 00265 /* ************* ACCUMULATION ZBUF ************ */ 00266 00267 00268 static APixstr *addpsmainA(ListBase *lb) 00269 { 00270 APixstrMain *psm; 00271 00272 psm= MEM_mallocN(sizeof(APixstrMain), "addpsmainA"); 00273 BLI_addtail(lb, psm); 00274 psm->ps= MEM_callocN(4096*sizeof(APixstr),"pixstr"); 00275 00276 return psm->ps; 00277 } 00278 00279 void freepsA(ListBase *lb) 00280 { 00281 APixstrMain *psm, *psmnext; 00282 00283 for(psm= lb->first; psm; psm= psmnext) { 00284 psmnext= psm->next; 00285 if(psm->ps) 00286 MEM_freeN(psm->ps); 00287 MEM_freeN(psm); 00288 } 00289 } 00290 00291 static APixstr *addpsA(ZSpan *zspan) 00292 { 00293 /* make new PS */ 00294 if(zspan->apsmcounter==0) { 00295 zspan->curpstr= addpsmainA(zspan->apsmbase); 00296 zspan->apsmcounter= 4095; 00297 } 00298 else { 00299 zspan->curpstr++; 00300 zspan->apsmcounter--; 00301 } 00302 return zspan->curpstr; 00303 } 00304 00305 static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) 00306 { 00307 APixstr *ap, *apofs, *apn; 00308 double zxd, zyd, zy0, zverg; 00309 float x0,y0,z0; 00310 float x1,y1,z1,x2,y2,z2,xx1; 00311 float *span1, *span2; 00312 int *rz, *rm, x, y; 00313 int sn1, sn2, rectx, *rectzofs, *rectmaskofs, my0, my2, mask; 00314 00315 /* init */ 00316 zbuf_init_span(zspan); 00317 00318 /* set spans */ 00319 zbuf_add_to_span(zspan, v1, v2); 00320 zbuf_add_to_span(zspan, v2, v3); 00321 if(v4) { 00322 zbuf_add_to_span(zspan, v3, v4); 00323 zbuf_add_to_span(zspan, v4, v1); 00324 } 00325 else 00326 zbuf_add_to_span(zspan, v3, v1); 00327 00328 /* clipped */ 00329 if(zspan->minp2==NULL || zspan->maxp2==NULL) return; 00330 00331 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; 00332 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; 00333 00334 if(my2<my0) return; 00335 00336 /* ZBUF DX DY, in floats still */ 00337 x1= v1[0]- v2[0]; 00338 x2= v2[0]- v3[0]; 00339 y1= v1[1]- v2[1]; 00340 y2= v2[1]- v3[1]; 00341 z1= v1[2]- v2[2]; 00342 z2= v2[2]- v3[2]; 00343 x0= y1*z2-z1*y2; 00344 y0= z1*x2-x1*z2; 00345 z0= x1*y2-y1*x2; 00346 00347 if(z0==0.0) return; 00348 00349 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; 00350 00351 zxd= -(double)x0/(double)z0; 00352 zyd= -(double)y0/(double)z0; 00353 zy0= ((double)my2)*zyd + (double)xx1; 00354 00355 /* start-offset in rect */ 00356 rectx= zspan->rectx; 00357 rectzofs= (int *)(zspan->arectz+rectx*(my2)); 00358 rectmaskofs= (int *)(zspan->rectmask+rectx*(my2)); 00359 apofs= (zspan->apixbuf+ rectx*(my2)); 00360 mask= zspan->mask; 00361 00362 /* correct span */ 00363 sn1= (my0 + my2)/2; 00364 if(zspan->span1[sn1] < zspan->span2[sn1]) { 00365 span1= zspan->span1+my2; 00366 span2= zspan->span2+my2; 00367 } 00368 else { 00369 span1= zspan->span2+my2; 00370 span2= zspan->span1+my2; 00371 } 00372 00373 for(y=my2; y>=my0; y--, span1--, span2--) { 00374 00375 sn1= floor(*span1); 00376 sn2= floor(*span2); 00377 sn1++; 00378 00379 if(sn2>=rectx) sn2= rectx-1; 00380 if(sn1<0) sn1= 0; 00381 00382 if(sn2>=sn1) { 00383 int intzverg; 00384 00385 zverg= (double)sn1*zxd + zy0; 00386 rz= rectzofs+sn1; 00387 rm= rectmaskofs+sn1; 00388 ap= apofs+sn1; 00389 x= sn2-sn1; 00390 00391 zverg-= zspan->polygon_offset; 00392 00393 while(x>=0) { 00394 intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX); 00395 00396 if( intzverg < *rz) { 00397 if(!zspan->rectmask || intzverg > *rm) { 00398 00399 apn= ap; 00400 while(apn) { 00401 if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= intzverg; apn->mask[0]= mask; break; } 00402 if(apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; } 00403 if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= intzverg; apn->mask[1]= mask; break; } 00404 if(apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; } 00405 if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= intzverg; apn->mask[2]= mask; break; } 00406 if(apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; } 00407 if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= intzverg; apn->mask[3]= mask; break; } 00408 if(apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; } 00409 if(apn->next==NULL) apn->next= addpsA(zspan); 00410 apn= apn->next; 00411 } 00412 } 00413 } 00414 zverg+= zxd; 00415 rz++; 00416 rm++; 00417 ap++; 00418 x--; 00419 } 00420 } 00421 00422 zy0-=zyd; 00423 rectzofs-= rectx; 00424 rectmaskofs-= rectx; 00425 apofs-= rectx; 00426 } 00427 } 00428 00429 00430 00431 static void zbuflineAc(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec2) 00432 { 00433 APixstr *ap, *apn; 00434 int *rectz, *rectmask; 00435 int start, end, x, y, oldx, oldy, ofs; 00436 int dz, vergz, mask, maxtest=0; 00437 float dx, dy; 00438 float v1[3], v2[3]; 00439 00440 dx= vec2[0]-vec1[0]; 00441 dy= vec2[1]-vec1[1]; 00442 00443 mask= zspan->mask; 00444 00445 if(fabs(dx) > fabs(dy)) { 00446 00447 /* all lines from left to right */ 00448 if(vec1[0]<vec2[0]) { 00449 VECCOPY(v1, vec1); 00450 VECCOPY(v2, vec2); 00451 } 00452 else { 00453 VECCOPY(v2, vec1); 00454 VECCOPY(v1, vec2); 00455 dx= -dx; dy= -dy; 00456 } 00457 00458 start= floor(v1[0]); 00459 end= start+floor(dx); 00460 if(end>=zspan->rectx) end= zspan->rectx-1; 00461 00462 oldy= floor(v1[1]); 00463 dy/= dx; 00464 00465 vergz= v1[2]; 00466 vergz-= zspan->polygon_offset; 00467 dz= (v2[2]-v1[2])/dx; 00468 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow 00469 00470 rectz= (int *)(zspan->arectz+zspan->rectx*(oldy) +start); 00471 rectmask= (int *)(zspan->rectmask+zspan->rectx*(oldy) +start); 00472 ap= (zspan->apixbuf+ zspan->rectx*(oldy) +start); 00473 00474 if(dy<0) ofs= -zspan->rectx; 00475 else ofs= zspan->rectx; 00476 00477 for(x= start; x<=end; x++, rectz++, rectmask++, ap++) { 00478 00479 y= floor(v1[1]); 00480 if(y!=oldy) { 00481 oldy= y; 00482 rectz+= ofs; 00483 rectmask+= ofs; 00484 ap+= ofs; 00485 } 00486 00487 if(x>=0 && y>=0 && y<zspan->recty) { 00488 if(vergz<*rectz) { 00489 if(!zspan->rectmask || vergz>*rectmask) { 00490 00491 apn= ap; 00492 while(apn) { /* loop unrolled */ 00493 if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; } 00494 if(apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; } 00495 if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; } 00496 if(apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; } 00497 if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; } 00498 if(apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; } 00499 if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; } 00500 if(apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; } 00501 if(apn->next==0) apn->next= addpsA(zspan); 00502 apn= apn->next; 00503 } 00504 } 00505 } 00506 } 00507 00508 v1[1]+= dy; 00509 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; 00510 else vergz+= dz; 00511 } 00512 } 00513 else { 00514 00515 /* all lines from top to bottom */ 00516 if(vec1[1]<vec2[1]) { 00517 VECCOPY(v1, vec1); 00518 VECCOPY(v2, vec2); 00519 } 00520 else { 00521 VECCOPY(v2, vec1); 00522 VECCOPY(v1, vec2); 00523 dx= -dx; dy= -dy; 00524 } 00525 00526 start= floor(v1[1]); 00527 end= start+floor(dy); 00528 00529 if(start>=zspan->recty || end<0) return; 00530 00531 if(end>=zspan->recty) end= zspan->recty-1; 00532 00533 oldx= floor(v1[0]); 00534 dx/= dy; 00535 00536 vergz= v1[2]; 00537 vergz-= zspan->polygon_offset; 00538 dz= (v2[2]-v1[2])/dy; 00539 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow 00540 00541 rectz= (int *)( zspan->arectz+ (start)*zspan->rectx+ oldx ); 00542 rectmask= (int *)( zspan->rectmask+ (start)*zspan->rectx+ oldx ); 00543 ap= (zspan->apixbuf+ zspan->rectx*(start) +oldx); 00544 00545 if(dx<0) ofs= -1; 00546 else ofs= 1; 00547 00548 for(y= start; y<=end; y++, rectz+=zspan->rectx, rectmask+=zspan->rectx, ap+=zspan->rectx) { 00549 00550 x= floor(v1[0]); 00551 if(x!=oldx) { 00552 oldx= x; 00553 rectz+= ofs; 00554 rectmask+= ofs; 00555 ap+= ofs; 00556 } 00557 00558 if(x>=0 && y>=0 && x<zspan->rectx) { 00559 if(vergz<*rectz) { 00560 if(!zspan->rectmask || vergz>*rectmask) { 00561 00562 apn= ap; 00563 while(apn) { /* loop unrolled */ 00564 if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; } 00565 if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; } 00566 if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; } 00567 if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; } 00568 if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; } 00569 if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; } 00570 if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; } 00571 if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; } 00572 if(apn->next==0) apn->next= addpsA(zspan); 00573 apn= apn->next; 00574 } 00575 } 00576 } 00577 } 00578 00579 v1[0]+= dx; 00580 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; 00581 else vergz+= dz; 00582 } 00583 } 00584 } 00585 00586 /* ************* NORMAL ZBUFFER ************ */ 00587 00588 static void zbufline(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec2) 00589 { 00590 int *rectz, *rectp, *recto, *rectmask; 00591 int start, end, x, y, oldx, oldy, ofs; 00592 int dz, vergz, maxtest= 0; 00593 float dx, dy; 00594 float v1[3], v2[3]; 00595 00596 dx= vec2[0]-vec1[0]; 00597 dy= vec2[1]-vec1[1]; 00598 00599 if(fabs(dx) > fabs(dy)) { 00600 00601 /* all lines from left to right */ 00602 if(vec1[0]<vec2[0]) { 00603 VECCOPY(v1, vec1); 00604 VECCOPY(v2, vec2); 00605 } 00606 else { 00607 VECCOPY(v2, vec1); 00608 VECCOPY(v1, vec2); 00609 dx= -dx; dy= -dy; 00610 } 00611 00612 start= floor(v1[0]); 00613 end= start+floor(dx); 00614 if(end>=zspan->rectx) end= zspan->rectx-1; 00615 00616 oldy= floor(v1[1]); 00617 dy/= dx; 00618 00619 vergz= floor(v1[2]); 00620 dz= floor((v2[2]-v1[2])/dx); 00621 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow 00622 00623 rectz= zspan->rectz + oldy*zspan->rectx+ start; 00624 rectp= zspan->rectp + oldy*zspan->rectx+ start; 00625 recto= zspan->recto + oldy*zspan->rectx+ start; 00626 rectmask= zspan->rectmask + oldy*zspan->rectx+ start; 00627 00628 if(dy<0) ofs= -zspan->rectx; 00629 else ofs= zspan->rectx; 00630 00631 for(x= start; x<=end; x++, rectz++, rectp++, recto++, rectmask++) { 00632 00633 y= floor(v1[1]); 00634 if(y!=oldy) { 00635 oldy= y; 00636 rectz+= ofs; 00637 rectp+= ofs; 00638 recto+= ofs; 00639 rectmask+= ofs; 00640 } 00641 00642 if(x>=0 && y>=0 && y<zspan->recty) { 00643 if(vergz<*rectz) { 00644 if(!zspan->rectmask || vergz>*rectmask) { 00645 *recto= obi; 00646 *rectz= vergz; 00647 *rectp= zvlnr; 00648 } 00649 } 00650 } 00651 00652 v1[1]+= dy; 00653 00654 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; 00655 else vergz+= dz; 00656 } 00657 } 00658 else { 00659 /* all lines from top to bottom */ 00660 if(vec1[1]<vec2[1]) { 00661 VECCOPY(v1, vec1); 00662 VECCOPY(v2, vec2); 00663 } 00664 else { 00665 VECCOPY(v2, vec1); 00666 VECCOPY(v1, vec2); 00667 dx= -dx; dy= -dy; 00668 } 00669 00670 start= floor(v1[1]); 00671 end= start+floor(dy); 00672 00673 if(end>=zspan->recty) end= zspan->recty-1; 00674 00675 oldx= floor(v1[0]); 00676 dx/= dy; 00677 00678 vergz= floor(v1[2]); 00679 dz= floor((v2[2]-v1[2])/dy); 00680 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow 00681 00682 rectz= zspan->rectz + start*zspan->rectx+ oldx; 00683 rectp= zspan->rectp + start*zspan->rectx+ oldx; 00684 recto= zspan->recto + start*zspan->rectx+ oldx; 00685 rectmask= zspan->rectmask + start*zspan->rectx+ oldx; 00686 00687 if(dx<0) ofs= -1; 00688 else ofs= 1; 00689 00690 for(y= start; y<=end; y++, rectz+=zspan->rectx, rectp+=zspan->rectx, recto+=zspan->rectx, rectmask+=zspan->rectx) { 00691 00692 x= floor(v1[0]); 00693 if(x!=oldx) { 00694 oldx= x; 00695 rectz+= ofs; 00696 rectp+= ofs; 00697 recto+= ofs; 00698 rectmask+= ofs; 00699 } 00700 00701 if(x>=0 && y>=0 && x<zspan->rectx) { 00702 if(vergz<*rectz) { 00703 if(!zspan->rectmask || vergz>*rectmask) { 00704 *rectz= vergz; 00705 *rectp= zvlnr; 00706 *recto= obi; 00707 } 00708 } 00709 } 00710 00711 v1[0]+= dx; 00712 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; 00713 else vergz+= dz; 00714 } 00715 } 00716 } 00717 00718 static void zbufline_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr), float *vec1, float *vec2) 00719 { 00720 int *rectz, *rectz1= NULL; 00721 int start, end, x, y, oldx, oldy, ofs; 00722 int dz, vergz, maxtest= 0; 00723 float dx, dy; 00724 float v1[3], v2[3]; 00725 00726 dx= vec2[0]-vec1[0]; 00727 dy= vec2[1]-vec1[1]; 00728 00729 if(fabs(dx) > fabs(dy)) { 00730 00731 /* all lines from left to right */ 00732 if(vec1[0]<vec2[0]) { 00733 VECCOPY(v1, vec1); 00734 VECCOPY(v2, vec2); 00735 } 00736 else { 00737 VECCOPY(v2, vec1); 00738 VECCOPY(v1, vec2); 00739 dx= -dx; dy= -dy; 00740 } 00741 00742 start= floor(v1[0]); 00743 end= start+floor(dx); 00744 if(end>=zspan->rectx) end= zspan->rectx-1; 00745 00746 oldy= floor(v1[1]); 00747 dy/= dx; 00748 00749 vergz= floor(v1[2]); 00750 dz= floor((v2[2]-v1[2])/dx); 00751 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow 00752 00753 rectz= zspan->rectz + oldy*zspan->rectx+ start; 00754 if(zspan->rectz1) 00755 rectz1= zspan->rectz1 + oldy*zspan->rectx+ start; 00756 00757 if(dy<0) ofs= -zspan->rectx; 00758 else ofs= zspan->rectx; 00759 00760 for(x= start; x<=end; x++, rectz++) { 00761 00762 y= floor(v1[1]); 00763 if(y!=oldy) { 00764 oldy= y; 00765 rectz+= ofs; 00766 if(rectz1) rectz1+= ofs; 00767 } 00768 00769 if(x>=0 && y>=0 && y<zspan->recty) { 00770 if(vergz < *rectz) { 00771 if(rectz1) *rectz1= *rectz; 00772 *rectz= vergz; 00773 } 00774 else if(rectz1 && vergz < *rectz1) 00775 *rectz1= vergz; 00776 } 00777 00778 v1[1]+= dy; 00779 00780 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; 00781 else vergz+= dz; 00782 00783 if(rectz1) rectz1++; 00784 } 00785 } 00786 else { 00787 /* all lines from top to bottom */ 00788 if(vec1[1]<vec2[1]) { 00789 VECCOPY(v1, vec1); 00790 VECCOPY(v2, vec2); 00791 } 00792 else { 00793 VECCOPY(v2, vec1); 00794 VECCOPY(v1, vec2); 00795 dx= -dx; dy= -dy; 00796 } 00797 00798 start= floor(v1[1]); 00799 end= start+floor(dy); 00800 00801 if(end>=zspan->recty) end= zspan->recty-1; 00802 00803 oldx= floor(v1[0]); 00804 dx/= dy; 00805 00806 vergz= floor(v1[2]); 00807 dz= floor((v2[2]-v1[2])/dy); 00808 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow 00809 00810 rectz= zspan->rectz + start*zspan->rectx+ oldx; 00811 if(zspan->rectz1) 00812 rectz1= zspan->rectz1 + start*zspan->rectx+ oldx; 00813 00814 if(dx<0) ofs= -1; 00815 else ofs= 1; 00816 00817 for(y= start; y<=end; y++, rectz+=zspan->rectx) { 00818 00819 x= floor(v1[0]); 00820 if(x!=oldx) { 00821 oldx= x; 00822 rectz+= ofs; 00823 if(rectz1) rectz1+= ofs; 00824 } 00825 00826 if(x>=0 && y>=0 && x<zspan->rectx) { 00827 if(vergz < *rectz) { 00828 if(rectz1) *rectz1= *rectz; 00829 *rectz= vergz; 00830 } 00831 else if(rectz1 && vergz < *rectz1) 00832 *rectz1= vergz; 00833 } 00834 00835 v1[0]+= dx; 00836 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0; 00837 else vergz+= dz; 00838 00839 if(rectz1) 00840 rectz1+=zspan->rectx; 00841 } 00842 } 00843 } 00844 00845 00846 static int clipline(float *v1, float *v2) /* return 0: do not draw */ 00847 { 00848 float dz,dw, u1=0.0, u2=1.0; 00849 float dx, dy, v13; 00850 00851 dz= v2[2]-v1[2]; 00852 dw= v2[3]-v1[3]; 00853 00854 /* this 1.01 is for clipping x and y just a tinsy larger. that way it is 00855 filled in with zbufwire correctly when rendering in parts. otherwise 00856 you see line endings at edges... */ 00857 00858 if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) { 00859 if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) { 00860 00861 dx= v2[0]-v1[0]; 00862 dz= 1.01*(v2[3]-v1[3]); 00863 v13= 1.01*v1[3]; 00864 00865 if(cliptestf(-dx-dz, v1[0]+v13, &u1,&u2)) { 00866 if(cliptestf(dx-dz, v13-v1[0], &u1,&u2)) { 00867 00868 dy= v2[1]-v1[1]; 00869 00870 if(cliptestf(-dy-dz, v1[1]+v13, &u1,&u2)) { 00871 if(cliptestf(dy-dz, v13-v1[1], &u1,&u2)) { 00872 00873 if(u2<1.0) { 00874 v2[0]= v1[0]+u2*dx; 00875 v2[1]= v1[1]+u2*dy; 00876 v2[2]= v1[2]+u2*dz; 00877 v2[3]= v1[3]+u2*dw; 00878 } 00879 if(u1>0.0) { 00880 v1[0]= v1[0]+u1*dx; 00881 v1[1]= v1[1]+u1*dy; 00882 v1[2]= v1[2]+u1*dz; 00883 v1[3]= v1[3]+u1*dw; 00884 } 00885 return 1; 00886 } 00887 } 00888 } 00889 } 00890 } 00891 } 00892 00893 return 0; 00894 } 00895 00896 void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco) 00897 { 00898 float div; 00899 00900 div= 1.0f/hoco[3]; 00901 zco[0]= zspan->zmulx*(1.0+hoco[0]*div) + zspan->zofsx; 00902 zco[1]= zspan->zmuly*(1.0+hoco[1]*div) + zspan->zofsy; 00903 zco[2]= 0x7FFFFFFF *(hoco[2]*div); 00904 } 00905 00906 void zbufclipwire(ZSpan *zspan, int obi, int zvlnr, int ec, float *ho1, float *ho2, float *ho3, float *ho4, int c1, int c2, int c3, int c4) 00907 { 00908 float vez[20]; 00909 int and, or; 00910 00911 /* edgecode: 1= draw */ 00912 if(ec==0) return; 00913 00914 if(ho4) { 00915 and= (c1 & c2 & c3 & c4); 00916 or= (c1 | c2 | c3 | c4); 00917 } 00918 else { 00919 and= (c1 & c2 & c3); 00920 or= (c1 | c2 | c3); 00921 } 00922 00923 if(or) { /* not in the middle */ 00924 if(and) { /* out completely */ 00925 return; 00926 } 00927 else { /* clipping */ 00928 00929 if(ec & ME_V1V2) { 00930 QUATCOPY(vez, ho1); 00931 QUATCOPY(vez+4, ho2); 00932 if( clipline(vez, vez+4)) { 00933 hoco_to_zco(zspan, vez, vez); 00934 hoco_to_zco(zspan, vez+4, vez+4); 00935 zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); 00936 } 00937 } 00938 if(ec & ME_V2V3) { 00939 QUATCOPY(vez, ho2); 00940 QUATCOPY(vez+4, ho3); 00941 if( clipline(vez, vez+4)) { 00942 hoco_to_zco(zspan, vez, vez); 00943 hoco_to_zco(zspan, vez+4, vez+4); 00944 zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); 00945 } 00946 } 00947 if(ho4) { 00948 if(ec & ME_V3V4) { 00949 QUATCOPY(vez, ho3); 00950 QUATCOPY(vez+4, ho4); 00951 if( clipline(vez, vez+4)) { 00952 hoco_to_zco(zspan, vez, vez); 00953 hoco_to_zco(zspan, vez+4, vez+4); 00954 zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); 00955 } 00956 } 00957 if(ec & ME_V4V1) { 00958 QUATCOPY(vez, ho4); 00959 QUATCOPY(vez+4, ho1); 00960 if( clipline(vez, vez+4)) { 00961 hoco_to_zco(zspan, vez, vez); 00962 hoco_to_zco(zspan, vez+4, vez+4); 00963 zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); 00964 } 00965 } 00966 } 00967 else { 00968 if(ec & ME_V3V1) { 00969 QUATCOPY(vez, ho3); 00970 QUATCOPY(vez+4, ho1); 00971 if( clipline(vez, vez+4)) { 00972 hoco_to_zco(zspan, vez, vez); 00973 hoco_to_zco(zspan, vez+4, vez+4); 00974 zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); 00975 } 00976 } 00977 } 00978 00979 return; 00980 } 00981 } 00982 00983 hoco_to_zco(zspan, vez, ho1); 00984 hoco_to_zco(zspan, vez+4, ho2); 00985 hoco_to_zco(zspan, vez+8, ho3); 00986 if(ho4) { 00987 hoco_to_zco(zspan, vez+12, ho4); 00988 00989 if(ec & ME_V3V4) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez+12); 00990 if(ec & ME_V4V1) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+12, vez); 00991 } 00992 else { 00993 if(ec & ME_V3V1) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez); 00994 } 00995 00996 if(ec & ME_V1V2) zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4); 00997 if(ec & ME_V2V3) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+4, vez+8); 00998 00999 } 01000 01001 void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, float *ho1, float *ho2) 01002 { 01003 float f1[4], f2[4]; 01004 int c1, c2; 01005 01006 c1= testclip(ho1); 01007 c2= testclip(ho2); 01008 01009 if(c1 | c2) { /* not in the middle */ 01010 if(!(c1 & c2)) { /* not out completely */ 01011 QUATCOPY(f1, ho1); 01012 QUATCOPY(f2, ho2); 01013 01014 if(clipline(f1, f2)) { 01015 hoco_to_zco(zspan, f1, f1); 01016 hoco_to_zco(zspan, f2, f2); 01017 zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2); 01018 } 01019 } 01020 } 01021 else { 01022 hoco_to_zco(zspan, f1, ho1); 01023 hoco_to_zco(zspan, f2, ho2); 01024 01025 zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2); 01026 } 01027 } 01028 01040 static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) 01041 { 01042 double zxd, zyd, zy0, zverg; 01043 float x0,y0,z0; 01044 float x1,y1,z1,x2,y2,z2,xx1; 01045 float *span1, *span2; 01046 int *rectoofs, *ro; 01047 int *rectpofs, *rp; 01048 int *rectmaskofs, *rm; 01049 int *rz, x, y; 01050 int sn1, sn2, rectx, *rectzofs, my0, my2; 01051 01052 /* init */ 01053 zbuf_init_span(zspan); 01054 01055 /* set spans */ 01056 zbuf_add_to_span(zspan, v1, v2); 01057 zbuf_add_to_span(zspan, v2, v3); 01058 if(v4) { 01059 zbuf_add_to_span(zspan, v3, v4); 01060 zbuf_add_to_span(zspan, v4, v1); 01061 } 01062 else 01063 zbuf_add_to_span(zspan, v3, v1); 01064 01065 /* clipped */ 01066 if(zspan->minp2==NULL || zspan->maxp2==NULL) return; 01067 01068 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; 01069 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; 01070 01071 // printf("my %d %d\n", my0, my2); 01072 if(my2<my0) return; 01073 01074 01075 /* ZBUF DX DY, in floats still */ 01076 x1= v1[0]- v2[0]; 01077 x2= v2[0]- v3[0]; 01078 y1= v1[1]- v2[1]; 01079 y2= v2[1]- v3[1]; 01080 z1= v1[2]- v2[2]; 01081 z2= v2[2]- v3[2]; 01082 x0= y1*z2-z1*y2; 01083 y0= z1*x2-x1*z2; 01084 z0= x1*y2-y1*x2; 01085 01086 if(z0==0.0) return; 01087 01088 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; 01089 01090 zxd= -(double)x0/(double)z0; 01091 zyd= -(double)y0/(double)z0; 01092 zy0= ((double)my2)*zyd + (double)xx1; 01093 01094 /* start-offset in rect */ 01095 rectx= zspan->rectx; 01096 rectzofs= (zspan->rectz+rectx*my2); 01097 rectpofs= (zspan->rectp+rectx*my2); 01098 rectoofs= (zspan->recto+rectx*my2); 01099 rectmaskofs= (zspan->rectmask+rectx*my2); 01100 01101 /* correct span */ 01102 sn1= (my0 + my2)/2; 01103 if(zspan->span1[sn1] < zspan->span2[sn1]) { 01104 span1= zspan->span1+my2; 01105 span2= zspan->span2+my2; 01106 } 01107 else { 01108 span1= zspan->span2+my2; 01109 span2= zspan->span1+my2; 01110 } 01111 01112 for(y=my2; y>=my0; y--, span1--, span2--) { 01113 01114 sn1= floor(*span1); 01115 sn2= floor(*span2); 01116 sn1++; 01117 01118 if(sn2>=rectx) sn2= rectx-1; 01119 if(sn1<0) sn1= 0; 01120 01121 if(sn2>=sn1) { 01122 int intzverg; 01123 01124 zverg= (double)sn1*zxd + zy0; 01125 rz= rectzofs+sn1; 01126 rp= rectpofs+sn1; 01127 ro= rectoofs+sn1; 01128 rm= rectmaskofs+sn1; 01129 x= sn2-sn1; 01130 01131 while(x>=0) { 01132 intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX); 01133 01134 if( intzverg > *rz || *rz==0x7FFFFFFF) { 01135 if(!zspan->rectmask || intzverg > *rm) { 01136 *ro= obi; 01137 *rz= intzverg; 01138 *rp= zvlnr; 01139 } 01140 } 01141 zverg+= zxd; 01142 rz++; 01143 rp++; 01144 ro++; 01145 rm++; 01146 x--; 01147 } 01148 } 01149 01150 zy0-=zyd; 01151 rectzofs-= rectx; 01152 rectpofs-= rectx; 01153 rectoofs-= rectx; 01154 rectmaskofs-= rectx; 01155 } 01156 } 01157 01158 /* uses spanbuffers */ 01159 01160 static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) 01161 { 01162 double zxd, zyd, zy0, zverg; 01163 float x0,y0,z0; 01164 float x1,y1,z1,x2,y2,z2,xx1; 01165 float *span1, *span2; 01166 int *rectoofs, *ro; 01167 int *rectpofs, *rp; 01168 int *rectmaskofs, *rm; 01169 int *rz, x, y; 01170 int sn1, sn2, rectx, *rectzofs, my0, my2; 01171 01172 /* init */ 01173 zbuf_init_span(zspan); 01174 01175 /* set spans */ 01176 zbuf_add_to_span(zspan, v1, v2); 01177 zbuf_add_to_span(zspan, v2, v3); 01178 if(v4) { 01179 zbuf_add_to_span(zspan, v3, v4); 01180 zbuf_add_to_span(zspan, v4, v1); 01181 } 01182 else 01183 zbuf_add_to_span(zspan, v3, v1); 01184 01185 /* clipped */ 01186 if(zspan->minp2==NULL || zspan->maxp2==NULL) return; 01187 01188 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; 01189 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; 01190 01191 // printf("my %d %d\n", my0, my2); 01192 if(my2<my0) return; 01193 01194 01195 /* ZBUF DX DY, in floats still */ 01196 x1= v1[0]- v2[0]; 01197 x2= v2[0]- v3[0]; 01198 y1= v1[1]- v2[1]; 01199 y2= v2[1]- v3[1]; 01200 z1= v1[2]- v2[2]; 01201 z2= v2[2]- v3[2]; 01202 x0= y1*z2-z1*y2; 01203 y0= z1*x2-x1*z2; 01204 z0= x1*y2-y1*x2; 01205 01206 if(z0==0.0) return; 01207 01208 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; 01209 01210 zxd= -(double)x0/(double)z0; 01211 zyd= -(double)y0/(double)z0; 01212 zy0= ((double)my2)*zyd + (double)xx1; 01213 01214 /* start-offset in rect */ 01215 rectx= zspan->rectx; 01216 rectzofs= (zspan->rectz+rectx*my2); 01217 rectpofs= (zspan->rectp+rectx*my2); 01218 rectoofs= (zspan->recto+rectx*my2); 01219 rectmaskofs= (zspan->rectmask+rectx*my2); 01220 01221 /* correct span */ 01222 sn1= (my0 + my2)/2; 01223 if(zspan->span1[sn1] < zspan->span2[sn1]) { 01224 span1= zspan->span1+my2; 01225 span2= zspan->span2+my2; 01226 } 01227 else { 01228 span1= zspan->span2+my2; 01229 span2= zspan->span1+my2; 01230 } 01231 01232 for(y=my2; y>=my0; y--, span1--, span2--) { 01233 01234 sn1= floor(*span1); 01235 sn2= floor(*span2); 01236 sn1++; 01237 01238 if(sn2>=rectx) sn2= rectx-1; 01239 if(sn1<0) sn1= 0; 01240 01241 if(sn2>=sn1) { 01242 int intzverg; 01243 01244 zverg= (double)sn1*zxd + zy0; 01245 rz= rectzofs+sn1; 01246 rp= rectpofs+sn1; 01247 ro= rectoofs+sn1; 01248 rm= rectmaskofs+sn1; 01249 x= sn2-sn1; 01250 01251 while(x>=0) { 01252 intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX); 01253 01254 if(intzverg < *rz) { 01255 if(!zspan->rectmask || intzverg > *rm) { 01256 *rz= intzverg; 01257 *rp= zvlnr; 01258 *ro= obi; 01259 } 01260 } 01261 zverg+= zxd; 01262 rz++; 01263 rp++; 01264 ro++; 01265 rm++; 01266 x--; 01267 } 01268 } 01269 01270 zy0-=zyd; 01271 rectzofs-= rectx; 01272 rectpofs-= rectx; 01273 rectoofs-= rectx; 01274 rectmaskofs-= rectx; 01275 } 01276 } 01277 01289 /* now: filling two Z values, the closest and 2nd closest */ 01290 static void zbuffillGL_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr), float *v1, float *v2, float *v3, float *v4) 01291 { 01292 double zxd, zyd, zy0, zverg; 01293 float x0,y0,z0; 01294 float x1,y1,z1,x2,y2,z2,xx1; 01295 float *span1, *span2; 01296 int *rz, *rz1, x, y; 01297 int sn1, sn2, rectx, *rectzofs, *rectzofs1= NULL, my0, my2; 01298 01299 /* init */ 01300 zbuf_init_span(zspan); 01301 01302 /* set spans */ 01303 zbuf_add_to_span(zspan, v1, v2); 01304 zbuf_add_to_span(zspan, v2, v3); 01305 if(v4) { 01306 zbuf_add_to_span(zspan, v3, v4); 01307 zbuf_add_to_span(zspan, v4, v1); 01308 } 01309 else 01310 zbuf_add_to_span(zspan, v3, v1); 01311 01312 /* clipped */ 01313 if(zspan->minp2==NULL || zspan->maxp2==NULL) return; 01314 01315 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; 01316 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; 01317 01318 // printf("my %d %d\n", my0, my2); 01319 if(my2<my0) return; 01320 01321 01322 /* ZBUF DX DY, in floats still */ 01323 x1= v1[0]- v2[0]; 01324 x2= v2[0]- v3[0]; 01325 y1= v1[1]- v2[1]; 01326 y2= v2[1]- v3[1]; 01327 z1= v1[2]- v2[2]; 01328 z2= v2[2]- v3[2]; 01329 x0= y1*z2-z1*y2; 01330 y0= z1*x2-x1*z2; 01331 z0= x1*y2-y1*x2; 01332 01333 if(z0==0.0) return; 01334 01335 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; 01336 01337 zxd= -(double)x0/(double)z0; 01338 zyd= -(double)y0/(double)z0; 01339 zy0= ((double)my2)*zyd + (double)xx1; 01340 01341 /* start-offset in rect */ 01342 rectx= zspan->rectx; 01343 rectzofs= (zspan->rectz+rectx*my2); 01344 if(zspan->rectz1) 01345 rectzofs1= (zspan->rectz1+rectx*my2); 01346 01347 /* correct span */ 01348 sn1= (my0 + my2)/2; 01349 if(zspan->span1[sn1] < zspan->span2[sn1]) { 01350 span1= zspan->span1+my2; 01351 span2= zspan->span2+my2; 01352 } 01353 else { 01354 span1= zspan->span2+my2; 01355 span2= zspan->span1+my2; 01356 } 01357 01358 for(y=my2; y>=my0; y--, span1--, span2--) { 01359 01360 sn1= floor(*span1); 01361 sn2= floor(*span2); 01362 sn1++; 01363 01364 if(sn2>=rectx) sn2= rectx-1; 01365 if(sn1<0) sn1= 0; 01366 01367 if(sn2>=sn1) { 01368 zverg= (double)sn1*zxd + zy0; 01369 rz= rectzofs+sn1; 01370 rz1= rectzofs1+sn1; 01371 x= sn2-sn1; 01372 01373 while(x>=0) { 01374 int zvergi= (int)CLAMPIS(zverg, INT_MIN, INT_MAX); 01375 01376 /* option: maintain two depth values, closest and 2nd closest */ 01377 if(zvergi < *rz) { 01378 if(rectzofs1) *rz1= *rz; 01379 *rz= zvergi; 01380 } 01381 else if(rectzofs1 && zvergi < *rz1) 01382 *rz1= zvergi; 01383 01384 zverg+= zxd; 01385 01386 rz++; 01387 rz1++; 01388 x--; 01389 } 01390 } 01391 01392 zy0-=zyd; 01393 rectzofs-= rectx; 01394 if(rectzofs1) rectzofs1-= rectx; 01395 } 01396 } 01397 01398 /* 2d scanconvert for tria, calls func for each x,y coordinate and gives UV barycentrics */ 01399 void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) ) 01400 { 01401 float x0, y0, x1, y1, x2, y2, z0, z1, z2, z; 01402 float u, v, uxd, uyd, vxd, vyd, uy0, vy0, zxd, zyd, zy0, xx1; 01403 float *span1, *span2; 01404 int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2; 01405 01406 /* init */ 01407 zbuf_init_span(zspan); 01408 01409 /* set spans */ 01410 zbuf_add_to_span(zspan, v1, v2); 01411 zbuf_add_to_span(zspan, v2, v3); 01412 zbuf_add_to_span(zspan, v3, v1); 01413 01414 /* clipped */ 01415 if(zspan->minp2==NULL || zspan->maxp2==NULL) return; 01416 01417 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; 01418 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; 01419 01420 // printf("my %d %d\n", my0, my2); 01421 if(my2<my0) return; 01422 01423 /* ZBUF DX DY, in floats still */ 01424 x1= v1[0]- v2[0]; 01425 x2= v2[0]- v3[0]; 01426 y1= v1[1]- v2[1]; 01427 y2= v2[1]- v3[1]; 01428 z1= v1[2]- v2[2]; 01429 z2= v2[2]- v3[2]; 01430 01431 x0= y1*z2-z1*y2; 01432 y0= z1*x2-x1*z2; 01433 z0= x1*y2-y1*x2; 01434 01435 if(z0==0.0f) return; 01436 01437 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; 01438 zxd= -(double)x0/(double)z0; 01439 zyd= -(double)y0/(double)z0; 01440 zy0= ((double)my2)*zyd + (double)xx1; 01441 01442 z1= 1.0f; // (u1 - u2) 01443 z2= 0.0f; // (u2 - u3) 01444 01445 x0= y1*z2-z1*y2; 01446 y0= z1*x2-x1*z2; 01447 01448 xx1= (x0*v1[0] + y0*v1[1])/z0 + 1.0f; 01449 uxd= -(double)x0/(double)z0; 01450 uyd= -(double)y0/(double)z0; 01451 uy0= ((double)my2)*uyd + (double)xx1; 01452 01453 z1= -1.0f; // (v1 - v2) 01454 z2= 1.0f; // (v2 - v3) 01455 01456 x0= y1*z2-z1*y2; 01457 y0= z1*x2-x1*z2; 01458 01459 xx1= (x0*v1[0] + y0*v1[1])/z0; 01460 vxd= -(double)x0/(double)z0; 01461 vyd= -(double)y0/(double)z0; 01462 vy0= ((double)my2)*vyd + (double)xx1; 01463 01464 /* correct span */ 01465 sn1= (my0 + my2)/2; 01466 if(zspan->span1[sn1] < zspan->span2[sn1]) { 01467 span1= zspan->span1+my2; 01468 span2= zspan->span2+my2; 01469 } 01470 else { 01471 span1= zspan->span2+my2; 01472 span2= zspan->span1+my2; 01473 } 01474 01475 for(y=my2; y>=my0; y--, span1--, span2--) { 01476 01477 sn1= floor(*span1); 01478 sn2= floor(*span2); 01479 sn1++; 01480 01481 if(sn2>=rectx) sn2= rectx-1; 01482 if(sn1<0) sn1= 0; 01483 01484 u= (double)sn1*uxd + uy0; 01485 v= (double)sn1*vxd + vy0; 01486 z= (double)sn1*zxd + zy0; 01487 01488 for(x= sn1; x<=sn2; x++, u+=uxd, v+=vxd, z+=zxd) 01489 func(handle, x, y, u, v, z); 01490 01491 uy0 -= uyd; 01492 vy0 -= vyd; 01493 zy0 -= zyd; 01494 } 01495 } 01496 01497 /* scanconvert for strand triangles, calls func for each x,y coordinate and gives UV barycentrics and z */ 01498 01499 void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) ) 01500 { 01501 float x0, y0, x1, y1, x2, y2, z0, z1, z2; 01502 float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1; 01503 float *span1, *span2; 01504 int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2; 01505 01506 /* init */ 01507 zbuf_init_span(zspan); 01508 01509 /* set spans */ 01510 zbuf_add_to_span(zspan, v1, v2); 01511 zbuf_add_to_span(zspan, v2, v3); 01512 zbuf_add_to_span(zspan, v3, v1); 01513 01514 /* clipped */ 01515 if(zspan->minp2==NULL || zspan->maxp2==NULL) return; 01516 01517 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; 01518 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; 01519 01520 // printf("my %d %d\n", my0, my2); 01521 if(my2<my0) return; 01522 01523 /* ZBUF DX DY, in floats still */ 01524 x1= v1[0]- v2[0]; 01525 x2= v2[0]- v3[0]; 01526 y1= v1[1]- v2[1]; 01527 y2= v2[1]- v3[1]; 01528 01529 z1= 1.0f; // (u1 - u2) 01530 z2= 0.0f; // (u2 - u3) 01531 01532 x0= y1*z2-z1*y2; 01533 y0= z1*x2-x1*z2; 01534 z0= x1*y2-y1*x2; 01535 01536 if(z0==0.0f) return; 01537 01538 xx1= (x0*v1[0] + y0*v1[1])/z0 + 1.0f; 01539 uxd= -(double)x0/(double)z0; 01540 uyd= -(double)y0/(double)z0; 01541 uy0= ((double)my2)*uyd + (double)xx1; 01542 01543 z1= -1.0f; // (v1 - v2) 01544 z2= 1.0f; // (v2 - v3) 01545 01546 x0= y1*z2-z1*y2; 01547 y0= z1*x2-x1*z2; 01548 01549 xx1= (x0*v1[0] + y0*v1[1])/z0; 01550 vxd= -(double)x0/(double)z0; 01551 vyd= -(double)y0/(double)z0; 01552 vy0= ((double)my2)*vyd + (double)xx1; 01553 01554 /* correct span */ 01555 sn1= (my0 + my2)/2; 01556 if(zspan->span1[sn1] < zspan->span2[sn1]) { 01557 span1= zspan->span1+my2; 01558 span2= zspan->span2+my2; 01559 } 01560 else { 01561 span1= zspan->span2+my2; 01562 span2= zspan->span1+my2; 01563 } 01564 01565 for(y=my2; y>=my0; y--, span1--, span2--) { 01566 01567 sn1= floor(*span1); 01568 sn2= floor(*span2); 01569 sn1++; 01570 01571 if(sn2>=rectx) sn2= rectx-1; 01572 if(sn1<0) sn1= 0; 01573 01574 u= (double)sn1*uxd + uy0; 01575 v= (double)sn1*vxd + vy0; 01576 01577 for(x= sn1; x<=sn2; x++, u+=uxd, v+=vxd) 01578 func(handle, x, y, u, v); 01579 01580 uy0 -= uyd; 01581 vy0 -= vyd; 01582 } 01583 } 01584 01585 01586 01601 static void clippyra(float *labda, float *v1, float *v2, int *b2, int *b3, int a, float clipcrop) 01602 { 01603 float da,dw,u1=0.0,u2=1.0; 01604 float v13; 01605 01606 labda[0]= -1.0; 01607 labda[1]= -1.0; 01608 01609 da= v2[a]-v1[a]; 01610 /* prob; we clip slightly larger, osa renders add 2 pixels on edges, should become variable? */ 01611 /* or better; increase r.winx/y size, but thats quite a complex one. do it later */ 01612 if(a==2) { 01613 dw= (v2[3]-v1[3]); 01614 v13= v1[3]; 01615 } 01616 else { 01617 dw= clipcrop*(v2[3]-v1[3]); 01618 v13= clipcrop*v1[3]; 01619 } 01620 /* according the original article by Liang&Barsky, for clipping of 01621 * homogenous coordinates with viewplane, the value of "0" is used instead of "-w" . 01622 * This differs from the other clipping cases (like left or top) and I considered 01623 * it to be not so 'homogenic'. But later it has proven to be an error, 01624 * who would have thought that of L&B! 01625 */ 01626 01627 if(cliptestf(-da-dw, v13+v1[a], &u1,&u2)) { 01628 if(cliptestf(da-dw, v13-v1[a], &u1,&u2)) { 01629 *b3=1; 01630 if(u2<1.0) { 01631 labda[1]= u2; 01632 *b2=1; 01633 } 01634 else labda[1]=1.0; /* u2 */ 01635 if(u1>0.0) { 01636 labda[0]= u1; 01637 *b2=1; 01638 } else labda[0]=0.0; 01639 } 01640 } 01641 } 01642 01658 static void makevertpyra(float *vez, float *labda, float **trias, float *v1, float *v2, int *b1, int *clve) 01659 { 01660 float l1, l2, *adr; 01661 01662 l1= labda[0]; 01663 l2= labda[1]; 01664 01665 if(l1!= -1.0) { 01666 if(l1!= 0.0) { 01667 adr= vez+4*(*clve); 01668 trias[*b1]=adr; 01669 (*clve)++; 01670 adr[0]= v1[0]+l1*(v2[0]-v1[0]); 01671 adr[1]= v1[1]+l1*(v2[1]-v1[1]); 01672 adr[2]= v1[2]+l1*(v2[2]-v1[2]); 01673 adr[3]= v1[3]+l1*(v2[3]-v1[3]); 01674 } 01675 else trias[*b1]= v1; 01676 01677 (*b1)++; 01678 } 01679 if(l2!= -1.0) { 01680 if(l2!= 1.0) { 01681 adr= vez+4*(*clve); 01682 trias[*b1]=adr; 01683 (*clve)++; 01684 adr[0]= v1[0]+l2*(v2[0]-v1[0]); 01685 adr[1]= v1[1]+l2*(v2[1]-v1[1]); 01686 adr[2]= v1[2]+l2*(v2[2]-v1[2]); 01687 adr[3]= v1[3]+l2*(v2[3]-v1[3]); 01688 (*b1)++; 01689 } 01690 } 01691 } 01692 01693 /* ------------------------------------------------------------------------- */ 01694 01695 void projectverto(float *v1, float winmat[][4], float *adr) 01696 { 01697 /* calcs homogenic coord of vertex v1 */ 01698 float x,y,z; 01699 01700 x= v1[0]; 01701 y= v1[1]; 01702 z= v1[2]; 01703 adr[0]= x*winmat[0][0] + z*winmat[2][0] + winmat[3][0]; 01704 adr[1]= y*winmat[1][1] + z*winmat[2][1] + winmat[3][1]; 01705 adr[2]= z*winmat[2][2] + winmat[3][2]; 01706 adr[3]= z*winmat[2][3] + winmat[3][3]; 01707 01708 //printf("hoco %f %f %f %f\n", adr[0], adr[1], adr[2], adr[3]); 01709 } 01710 01711 /* ------------------------------------------------------------------------- */ 01712 01713 void projectvert(float *v1, float winmat[][4], float *adr) 01714 { 01715 /* calcs homogenic coord of vertex v1 */ 01716 float x,y,z; 01717 01718 x= v1[0]; 01719 y= v1[1]; 01720 z= v1[2]; 01721 adr[0]= x*winmat[0][0]+ y*winmat[1][0]+ z*winmat[2][0]+ winmat[3][0]; 01722 adr[1]= x*winmat[0][1]+ y*winmat[1][1]+ z*winmat[2][1]+ winmat[3][1]; 01723 adr[2]= x*winmat[0][2]+ y*winmat[1][2]+ z*winmat[2][2]+ winmat[3][2]; 01724 adr[3]= x*winmat[0][3]+ y*winmat[1][3]+ z*winmat[2][3]+ winmat[3][3]; 01725 } 01726 01727 /* ------------------------------------------------------------------------- */ 01728 01729 #define ZBUF_PROJECT_CACHE_SIZE 256 01730 01731 typedef struct ZbufProjectCache { 01732 int index, clip; 01733 float ho[4]; 01734 } ZbufProjectCache; 01735 01736 static void zbuf_project_cache_clear(ZbufProjectCache *cache, int size) 01737 { 01738 int i; 01739 01740 if(size > ZBUF_PROJECT_CACHE_SIZE) 01741 size= ZBUF_PROJECT_CACHE_SIZE; 01742 01743 memset(cache, 0, sizeof(ZbufProjectCache)*size); 01744 for(i=0; i<size; i++) 01745 cache[i].index= -1; 01746 } 01747 01748 static int zbuf_shadow_project(ZbufProjectCache *cache, int index, float winmat[][4], float *co, float *ho) 01749 { 01750 int clipflag, cindex= index & 255; 01751 01752 if(cache[cindex].index == index) { 01753 QUATCOPY(ho, cache[cindex].ho); 01754 return cache[cindex].clip; 01755 } 01756 else { 01757 projectvert(co, winmat, ho); 01758 clipflag= testclip(ho); 01759 01760 QUATCOPY(cache[cindex].ho, ho); 01761 cache[cindex].clip= clipflag; 01762 cache[cindex].index= index; 01763 01764 return clipflag; 01765 } 01766 } 01767 01768 static void zbuffer_part_bounds(int winx, int winy, RenderPart *pa, float *bounds) 01769 { 01770 bounds[0]= (2*pa->disprect.xmin - winx-1)/(float)winx; 01771 bounds[1]= (2*pa->disprect.xmax - winx+1)/(float)winx; 01772 bounds[2]= (2*pa->disprect.ymin - winy-1)/(float)winy; 01773 bounds[3]= (2*pa->disprect.ymax - winy+1)/(float)winy; 01774 } 01775 01776 static int zbuf_part_project(ZbufProjectCache *cache, int index, float winmat[][4], float *bounds, float *co, float *ho) 01777 { 01778 float vec[3], wco; 01779 int clipflag= 0, cindex= index & 255; 01780 01781 if(cache[cindex].index == index) { 01782 QUATCOPY(ho, cache[cindex].ho); 01783 return cache[cindex].clip; 01784 } 01785 else { 01786 VECCOPY(vec, co) 01787 projectvert(co, winmat, ho); 01788 01789 wco= ho[3]; 01790 if(ho[0] < bounds[0]*wco) clipflag |= 1; 01791 else if(ho[0] > bounds[1]*wco) clipflag |= 2; 01792 if(ho[1] > bounds[3]*wco) clipflag |= 4; 01793 else if(ho[1] < bounds[2]*wco) clipflag |= 8; 01794 01795 QUATCOPY(cache[cindex].ho, ho); 01796 cache[cindex].clip= clipflag; 01797 cache[cindex].index= index; 01798 01799 return clipflag; 01800 } 01801 } 01802 01803 void zbuf_render_project(float winmat[][4], float *co, float *ho) 01804 { 01805 float vec[3]; 01806 01807 VECCOPY(vec, co) 01808 projectvert(vec, winmat, ho); 01809 } 01810 01811 void zbuf_make_winmat(Render *re, float winmat[][4]) 01812 { 01813 if(re->r.mode & R_PANORAMA) { 01814 float panomat[4][4]= MAT4_UNITY; 01815 01816 panomat[0][0]= re->panoco; 01817 panomat[0][2]= re->panosi; 01818 panomat[2][0]= -re->panosi; 01819 panomat[2][2]= re->panoco; 01820 01821 mul_m4_m4m4(winmat, panomat, re->winmat); 01822 } 01823 else 01824 copy_m4_m4(winmat, re->winmat); 01825 } 01826 01827 /* do zbuffering and clip, f1 f2 f3 are hocos, c1 c2 c3 are clipping flags */ 01828 01829 void zbufclip(ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3) 01830 { 01831 float *vlzp[32][3], labda[3][2]; 01832 float vez[400], *trias[40]; 01833 01834 if(c1 | c2 | c3) { /* not in middle */ 01835 if(c1 & c2 & c3) { /* completely out */ 01836 return; 01837 } else { /* clipping */ 01838 int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1; 01839 01840 vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3]; 01841 vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3]; 01842 vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3]; 01843 01844 vlzp[0][0]= vez; 01845 vlzp[0][1]= vez+4; 01846 vlzp[0][2]= vez+8; 01847 01848 clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) ); 01849 if(clipflag[0]==0) { /* othwerwise it needs to be calculated again, after the first (z) clip */ 01850 clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) ); 01851 clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) ); 01852 } 01853 else clipflag[1]=clipflag[2]= 0; 01854 01855 for(b=0;b<3;b++) { 01856 01857 if(clipflag[b]) { 01858 01859 clvlo= clvl; 01860 01861 for(v=0; v<clvlo; v++) { 01862 01863 if(vlzp[v][0]!=NULL) { /* face is still there */ 01864 b2= b3 =0; /* clip flags */ 01865 01866 if(b==0) arg= 2; 01867 else if (b==1) arg= 0; 01868 else arg= 1; 01869 01870 clippyra(labda[0], vlzp[v][0],vlzp[v][1], &b2,&b3, arg, zspan->clipcrop); 01871 clippyra(labda[1], vlzp[v][1],vlzp[v][2], &b2,&b3, arg, zspan->clipcrop); 01872 clippyra(labda[2], vlzp[v][2],vlzp[v][0], &b2,&b3, arg, zspan->clipcrop); 01873 01874 if(b2==0 && b3==1) { 01875 /* completely 'in', but we copy because of last for() loop in this section */; 01876 vlzp[clvl][0]= vlzp[v][0]; 01877 vlzp[clvl][1]= vlzp[v][1]; 01878 vlzp[clvl][2]= vlzp[v][2]; 01879 vlzp[v][0]= NULL; 01880 clvl++; 01881 } else if(b3==0) { 01882 vlzp[v][0]= NULL; 01883 /* completely 'out' */; 01884 } else { 01885 b1=0; 01886 makevertpyra(vez, labda[0], trias, vlzp[v][0],vlzp[v][1], &b1,&clve); 01887 makevertpyra(vez, labda[1], trias, vlzp[v][1],vlzp[v][2], &b1,&clve); 01888 makevertpyra(vez, labda[2], trias, vlzp[v][2],vlzp[v][0], &b1,&clve); 01889 01890 /* after front clip done: now set clip flags */ 01891 if(b==0) { 01892 clipflag[1]= clipflag[2]= 0; 01893 f1= vez; 01894 for(b3=0; b3<clve; b3++) { 01895 c4= testclip(f1); 01896 clipflag[1] |= (c4 & 3); 01897 clipflag[2] |= (c4 & 12); 01898 f1+= 4; 01899 } 01900 } 01901 01902 vlzp[v][0]= NULL; 01903 if(b1>2) { 01904 for(b3=3; b3<=b1; b3++) { 01905 vlzp[clvl][0]= trias[0]; 01906 vlzp[clvl][1]= trias[b3-2]; 01907 vlzp[clvl][2]= trias[b3-1]; 01908 clvl++; 01909 } 01910 } 01911 } 01912 } 01913 } 01914 } 01915 } 01916 01917 /* warning, this should never happen! */ 01918 if(clve>38 || clvl>31) printf("clip overflow: clve clvl %d %d\n",clve,clvl); 01919 01920 /* perspective division */ 01921 f1=vez; 01922 for(c1=0;c1<clve;c1++) { 01923 hoco_to_zco(zspan, f1, f1); 01924 f1+=4; 01925 } 01926 for(b=1;b<clvl;b++) { 01927 if(vlzp[b][0]) { 01928 zspan->zbuffunc(zspan, obi, zvlnr, vlzp[b][0],vlzp[b][1],vlzp[b][2], NULL); 01929 } 01930 } 01931 return; 01932 } 01933 } 01934 01935 /* perspective division: HCS to ZCS */ 01936 hoco_to_zco(zspan, vez, f1); 01937 hoco_to_zco(zspan, vez+4, f2); 01938 hoco_to_zco(zspan, vez+8, f3); 01939 zspan->zbuffunc(zspan, obi, zvlnr, vez,vez+4,vez+8, NULL); 01940 } 01941 01942 void zbufclip4(ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4) 01943 { 01944 float vez[16]; 01945 01946 if(c1 | c2 | c3 | c4) { /* not in middle */ 01947 if(c1 & c2 & c3 & c4) { /* completely out */ 01948 return; 01949 } else { /* clipping */ 01950 zbufclip(zspan, obi, zvlnr, f1, f2, f3, c1, c2, c3); 01951 zbufclip(zspan, obi, zvlnr, f1, f3, f4, c1, c3, c4); 01952 } 01953 return; 01954 } 01955 01956 /* perspective division: HCS to ZCS */ 01957 hoco_to_zco(zspan, vez, f1); 01958 hoco_to_zco(zspan, vez+4, f2); 01959 hoco_to_zco(zspan, vez+8, f3); 01960 hoco_to_zco(zspan, vez+12, f4); 01961 01962 zspan->zbuffunc(zspan, obi, zvlnr, vez, vez+4, vez+8, vez+12); 01963 } 01964 01965 /* ************** ZMASK ******************************** */ 01966 01967 #define EXTEND_PIXEL(a) if(temprectp[a]) {z+= rectz[a]; tot++;} 01968 01969 /* changes the zbuffer to be ready for z-masking: applies an extend-filter, and then clears */ 01970 static void zmask_rect(int *rectz, int *rectp, int xs, int ys, int neg) 01971 { 01972 int len=0, x, y; 01973 int *temprectp; 01974 int row1, row2, row3, *curp, *curz; 01975 01976 temprectp= MEM_dupallocN(rectp); 01977 01978 /* extend: if pixel is not filled in, we check surrounding pixels and average z value */ 01979 01980 for(y=1; y<=ys; y++) { 01981 /* setup row indices */ 01982 row1= (y-2)*xs; 01983 row2= row1 + xs; 01984 row3= row2 + xs; 01985 if(y==1) 01986 row1= row2; 01987 else if(y==ys) 01988 row3= row2; 01989 01990 curp= rectp + (y-1)*xs; 01991 curz= rectz + (y-1)*xs; 01992 01993 for(x=0; x<xs; x++, curp++, curz++) { 01994 if(curp[0]==0) { 01995 int tot= 0; 01996 float z= 0.0f; 01997 01998 EXTEND_PIXEL(row1); 01999 EXTEND_PIXEL(row2); 02000 EXTEND_PIXEL(row3); 02001 EXTEND_PIXEL(row1 + 1); 02002 EXTEND_PIXEL(row3 + 1); 02003 if(x!=xs-1) { 02004 EXTEND_PIXEL(row1 + 2); 02005 EXTEND_PIXEL(row2 + 2); 02006 EXTEND_PIXEL(row3 + 2); 02007 } 02008 if(tot) { 02009 len++; 02010 curz[0]= (int)(z/(float)tot); 02011 curp[0]= -1; /* env */ 02012 } 02013 } 02014 02015 if(x!=0) { 02016 row1++; row2++; row3++; 02017 } 02018 } 02019 } 02020 02021 MEM_freeN(temprectp); 02022 02023 if(neg); /* z values for negative are already correct */ 02024 else { 02025 /* clear not filled z values */ 02026 for(len= xs*ys -1; len>=0; len--) { 02027 if(rectp[len]==0) { 02028 rectz[len] = -0x7FFFFFFF; 02029 rectp[len]= -1; /* env code */ 02030 } 02031 } 02032 } 02033 } 02034 02035 02036 02037 02038 /* ***************** ZBUFFER MAIN ROUTINES **************** */ 02039 02040 void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart*, ZSpan*, int, void*), void *data) 02041 { 02042 ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; 02043 ZSpan zspans[16], *zspan; /* 16 = RE_MAX_OSA */ 02044 VlakRen *vlr= NULL; 02045 VertRen *v1, *v2, *v3, *v4; 02046 Material *ma=0; 02047 ObjectInstanceRen *obi; 02048 ObjectRen *obr; 02049 float obwinmat[4][4], winmat[4][4], bounds[4]; 02050 float ho1[4], ho2[4], ho3[4], ho4[4]={0}; 02051 unsigned int lay= rl->lay, lay_zmask= rl->lay_zmask; 02052 int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0; 02053 short nofill=0, env=0, wire=0, zmaskpass=0; 02054 short all_z= (rl->layflag & SCE_LAY_ALL_Z) && !(rl->layflag & SCE_LAY_ZMASK); 02055 short neg_zmask= (rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK); 02056 02057 zbuf_make_winmat(&R, winmat); 02058 02059 samples= (R.osa? R.osa: 1); 02060 samples= MIN2(4, samples-pa->sample); 02061 02062 for(zsample=0; zsample<samples; zsample++) { 02063 zspan= &zspans[zsample]; 02064 02065 zbuffer_part_bounds(R.winx, R.winy, pa, bounds); 02066 zbuf_alloc_span(zspan, pa->rectx, pa->recty, R.clipcrop); 02067 02068 /* needed for transform from hoco to zbuffer co */ 02069 zspan->zmulx= ((float)R.winx)/2.0; 02070 zspan->zmuly= ((float)R.winy)/2.0; 02071 02072 if(R.osa) { 02073 zspan->zofsx= -pa->disprect.xmin - R.jit[pa->sample+zsample][0]; 02074 zspan->zofsy= -pa->disprect.ymin - R.jit[pa->sample+zsample][1]; 02075 } 02076 else if(R.i.curblur) { 02077 zspan->zofsx= -pa->disprect.xmin - R.mblur_jit[R.i.curblur-1][0]; 02078 zspan->zofsy= -pa->disprect.ymin - R.mblur_jit[R.i.curblur-1][1]; 02079 } 02080 else { 02081 zspan->zofsx= -pa->disprect.xmin; 02082 zspan->zofsy= -pa->disprect.ymin; 02083 } 02084 /* to center the sample position */ 02085 zspan->zofsx -= 0.5f; 02086 zspan->zofsy -= 0.5f; 02087 02088 /* the buffers */ 02089 if(zsample == samples-1) { 02090 zspan->rectp= pa->rectp; 02091 zspan->recto= pa->recto; 02092 02093 if(neg_zmask) 02094 zspan->rectz= pa->rectmask; 02095 else 02096 zspan->rectz= pa->rectz; 02097 } 02098 else { 02099 zspan->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); 02100 zspan->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); 02101 zspan->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); 02102 } 02103 02104 fillrect(zspan->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); 02105 fillrect(zspan->rectp, pa->rectx, pa->recty, 0); 02106 fillrect(zspan->recto, pa->rectx, pa->recty, 0); 02107 } 02108 02109 /* in case zmask we fill Z for objects in lay_zmask first, then clear Z, and then do normal zbuffering */ 02110 if(rl->layflag & SCE_LAY_ZMASK) 02111 zmaskpass= 1; 02112 02113 for(; zmaskpass >=0; zmaskpass--) { 02114 ma= NULL; 02115 02116 /* filling methods */ 02117 for(zsample=0; zsample<samples; zsample++) { 02118 zspan= &zspans[zsample]; 02119 02120 if(zmaskpass && neg_zmask) 02121 zspan->zbuffunc= zbuffillGLinv4; 02122 else 02123 zspan->zbuffunc= zbuffillGL4; 02124 zspan->zbuflinefunc= zbufline; 02125 } 02126 02127 /* regular zbuffering loop, does all sample buffers */ 02128 for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) { 02129 obr= obi->obr; 02130 02131 /* continue happens in 2 different ways... zmaskpass only does lay_zmask stuff */ 02132 if(zmaskpass) { 02133 if((obi->lay & lay_zmask)==0) 02134 continue; 02135 } 02136 else if(!all_z && !(obi->lay & (lay|lay_zmask))) 02137 continue; 02138 02139 if(obi->flag & R_TRANSFORMED) 02140 mul_m4_m4m4(obwinmat, obi->mat, winmat); 02141 else 02142 copy_m4_m4(obwinmat, winmat); 02143 02144 if(clip_render_object(obi->obr->boundbox, bounds, obwinmat)) 02145 continue; 02146 02147 zbuf_project_cache_clear(cache, obr->totvert); 02148 02149 for(v=0; v<obr->totvlak; v++) { 02150 if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak; 02151 else vlr++; 02152 02153 /* the cases: visible for render, only z values, zmask, nothing */ 02154 if(obi->lay & lay) { 02155 if(vlr->mat!=ma) { 02156 ma= vlr->mat; 02157 nofill= (ma->mode & MA_ONLYCAST) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)); 02158 env= (ma->mode & MA_ENV); 02159 wire= (ma->material_type == MA_TYPE_WIRE); 02160 02161 for(zsample=0; zsample<samples; zsample++) { 02162 if(ma->mode & MA_ZINV || (zmaskpass && neg_zmask)) 02163 zspans[zsample].zbuffunc= zbuffillGLinv4; 02164 else 02165 zspans[zsample].zbuffunc= zbuffillGL4; 02166 } 02167 } 02168 } 02169 else if(all_z || (obi->lay & lay_zmask)) { 02170 env= 1; 02171 nofill= 0; 02172 ma= NULL; 02173 } 02174 else { 02175 nofill= 1; 02176 ma= NULL; /* otherwise nofill can hang */ 02177 } 02178 02179 if(!(vlr->flag & R_HIDDEN) && nofill==0) { 02180 unsigned short partclip; 02181 02182 v1= vlr->v1; 02183 v2= vlr->v2; 02184 v3= vlr->v3; 02185 v4= vlr->v4; 02186 02187 c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1); 02188 c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2); 02189 c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3); 02190 02191 /* partclipping doesn't need viewplane clipping */ 02192 partclip= c1 & c2 & c3; 02193 if(v4) { 02194 c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4); 02195 partclip &= c4; 02196 } 02197 02198 if(partclip==0) { 02199 02200 if(env) zvlnr= -1; 02201 else zvlnr= v+1; 02202 02203 c1= testclip(ho1); 02204 c2= testclip(ho2); 02205 c3= testclip(ho3); 02206 if(v4) 02207 c4= testclip(ho4); 02208 02209 for(zsample=0; zsample<samples; zsample++) { 02210 zspan= &zspans[zsample]; 02211 02212 if(wire) { 02213 if(v4) 02214 zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); 02215 else 02216 zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0); 02217 } 02218 else { 02219 /* strands allow to be filled in as quad */ 02220 if(v4 && (vlr->flag & R_STRAND)) { 02221 zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4); 02222 } 02223 else { 02224 zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); 02225 if(v4) 02226 zbufclip(zspan, i, (env)? zvlnr: zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); 02227 } 02228 } 02229 } 02230 } 02231 } 02232 } 02233 } 02234 02235 /* clear all z to close value, so it works as mask for next passes (ztra+strand) */ 02236 if(zmaskpass) { 02237 for(zsample=0; zsample<samples; zsample++) { 02238 zspan= &zspans[zsample]; 02239 02240 if(neg_zmask) { 02241 zspan->rectmask= zspan->rectz; 02242 if(zsample == samples-1) 02243 zspan->rectz= pa->rectz; 02244 else 02245 zspan->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); 02246 fillrect(zspan->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); 02247 02248 zmask_rect(zspan->rectmask, zspan->rectp, pa->rectx, pa->recty, 1); 02249 } 02250 else 02251 zmask_rect(zspan->rectz, zspan->rectp, pa->rectx, pa->recty, 0); 02252 } 02253 } 02254 } 02255 02256 for(zsample=0; zsample<samples; zsample++) { 02257 zspan= &zspans[zsample]; 02258 02259 if(fillfunc) 02260 fillfunc(pa, zspan, pa->sample+zsample, data); 02261 02262 if(zsample != samples-1) { 02263 MEM_freeN(zspan->rectz); 02264 MEM_freeN(zspan->rectp); 02265 MEM_freeN(zspan->recto); 02266 if(zspan->rectmask) 02267 MEM_freeN(zspan->rectmask); 02268 } 02269 02270 zbuf_free_span(zspan); 02271 } 02272 } 02273 02274 void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int size, float jitx, float jity) 02275 { 02276 ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; 02277 ZSpan zspan; 02278 ObjectInstanceRen *obi; 02279 ObjectRen *obr; 02280 VlakRen *vlr= NULL; 02281 Material *ma= NULL; 02282 StrandSegment sseg; 02283 StrandRen *strand= NULL; 02284 StrandVert *svert; 02285 StrandBound *sbound; 02286 float obwinmat[4][4], ho1[4], ho2[4], ho3[4], ho4[4]; 02287 int a, b, c, i, c1, c2, c3, c4, ok=1, lay= -1; 02288 02289 if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; 02290 02291 /* 1.0f for clipping in clippyra()... bad stuff actually */ 02292 zbuf_alloc_span(&zspan, size, size, 1.0f); 02293 zspan.zmulx= ((float)size)/2.0; 02294 zspan.zmuly= ((float)size)/2.0; 02295 /* -0.5f to center the sample position */ 02296 zspan.zofsx= jitx - 0.5f; 02297 zspan.zofsy= jity - 0.5f; 02298 02299 /* the buffers */ 02300 zspan.rectz= rectz; 02301 fillrect(rectz, size, size, 0x7FFFFFFE); 02302 if(lar->buftype==LA_SHADBUF_HALFWAY) { 02303 zspan.rectz1= MEM_mallocN(size*size*sizeof(int), "seconday z buffer"); 02304 fillrect(zspan.rectz1, size, size, 0x7FFFFFFE); 02305 } 02306 02307 /* filling methods */ 02308 zspan.zbuflinefunc= zbufline_onlyZ; 02309 zspan.zbuffunc= zbuffillGL_onlyZ; 02310 02311 for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) { 02312 obr= obi->obr; 02313 02314 if(obr->ob==re->excludeob) 02315 continue; 02316 else if(!(obi->lay & lay)) 02317 continue; 02318 02319 if(obi->flag & R_TRANSFORMED) 02320 mul_m4_m4m4(obwinmat, obi->mat, winmat); 02321 else 02322 copy_m4_m4(obwinmat, winmat); 02323 02324 if(clip_render_object(obi->obr->boundbox, NULL, obwinmat)) 02325 continue; 02326 02327 zbuf_project_cache_clear(cache, obr->totvert); 02328 02329 /* faces */ 02330 for(a=0; a<obr->totvlak; a++) { 02331 02332 if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; 02333 else vlr++; 02334 02335 /* note, these conditions are copied in shadowbuf_autoclip() */ 02336 if(vlr->mat!= ma) { 02337 ma= vlr->mat; 02338 ok= 1; 02339 if((ma->mode & MA_SHADBUF)==0) ok= 0; 02340 } 02341 02342 if(ok && (obi->lay & lay) && !(vlr->flag & R_HIDDEN)) { 02343 c1= zbuf_shadow_project(cache, vlr->v1->index, obwinmat, vlr->v1->co, ho1); 02344 c2= zbuf_shadow_project(cache, vlr->v2->index, obwinmat, vlr->v2->co, ho2); 02345 c3= zbuf_shadow_project(cache, vlr->v3->index, obwinmat, vlr->v3->co, ho3); 02346 02347 if((ma->material_type == MA_TYPE_WIRE) || (vlr->flag & R_STRAND)) { 02348 if(vlr->v4) { 02349 c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4); 02350 zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); 02351 } 02352 else 02353 zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0); 02354 } 02355 else { 02356 if(vlr->v4) { 02357 c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4); 02358 zbufclip4(&zspan, 0, 0, ho1, ho2, ho3, ho4, c1, c2, c3, c4); 02359 } 02360 else 02361 zbufclip(&zspan, 0, 0, ho1, ho2, ho3, c1, c2, c3); 02362 } 02363 } 02364 02365 if((a & 255)==255 && re->test_break(re->tbh)) 02366 break; 02367 } 02368 02369 /* strands */ 02370 if(obr->strandbuf) { 02371 /* for each bounding box containing a number of strands */ 02372 sbound= obr->strandbuf->bound; 02373 for(c=0; c<obr->strandbuf->totbound; c++, sbound++) { 02374 if(clip_render_object(sbound->boundbox, NULL, obwinmat)) 02375 continue; 02376 02377 /* for each strand in this bounding box */ 02378 for(a=sbound->start; a<sbound->end; a++) { 02379 strand= RE_findOrAddStrand(obr, a); 02380 02381 sseg.obi= obi; 02382 sseg.buffer= strand->buffer; 02383 sseg.sqadaptcos= sseg.buffer->adaptcos; 02384 sseg.sqadaptcos *= sseg.sqadaptcos; 02385 sseg.strand= strand; 02386 svert= strand->vert; 02387 02388 /* note, these conditions are copied in shadowbuf_autoclip() */ 02389 if(sseg.buffer->ma!= ma) { 02390 ma= sseg.buffer->ma; 02391 ok= 1; 02392 if((ma->mode & MA_SHADBUF)==0) ok= 0; 02393 } 02394 02395 if(ok && (sseg.buffer->lay & lay)) { 02396 zbuf_project_cache_clear(cache, strand->totvert); 02397 02398 for(b=0; b<strand->totvert-1; b++, svert++) { 02399 sseg.v[0]= (b > 0)? (svert-1): svert; 02400 sseg.v[1]= svert; 02401 sseg.v[2]= svert+1; 02402 sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1; 02403 02404 c1= zbuf_shadow_project(cache, sseg.v[0]-strand->vert, obwinmat, sseg.v[0]->co, ho1); 02405 c2= zbuf_shadow_project(cache, sseg.v[1]-strand->vert, obwinmat, sseg.v[1]->co, ho2); 02406 c3= zbuf_shadow_project(cache, sseg.v[2]-strand->vert, obwinmat, sseg.v[2]->co, ho3); 02407 c4= zbuf_shadow_project(cache, sseg.v[3]-strand->vert, obwinmat, sseg.v[3]->co, ho4); 02408 02409 if(!(c1 & c2 & c3 & c4)) 02410 render_strand_segment(re, winmat, NULL, &zspan, 1, &sseg); 02411 } 02412 } 02413 02414 if((a & 255)==255 && re->test_break(re->tbh)) 02415 break; 02416 } 02417 } 02418 } 02419 02420 if(re->test_break(re->tbh)) 02421 break; 02422 } 02423 02424 /* merge buffers */ 02425 if(lar->buftype==LA_SHADBUF_HALFWAY) { 02426 for(a=size*size -1; a>=0; a--) 02427 rectz[a]= (rectz[a]>>1) + (zspan.rectz1[a]>>1); 02428 02429 MEM_freeN(zspan.rectz1); 02430 } 02431 02432 zbuf_free_span(&zspan); 02433 } 02434 02435 static void zbuffill_sss(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) 02436 { 02437 double zxd, zyd, zy0, z; 02438 float x0, y0, x1, y1, x2, y2, z0, z1, z2, xx1, *span1, *span2; 02439 int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2; 02440 /* init */ 02441 zbuf_init_span(zspan); 02442 02443 /* set spans */ 02444 zbuf_add_to_span(zspan, v1, v2); 02445 zbuf_add_to_span(zspan, v2, v3); 02446 if(v4) { 02447 zbuf_add_to_span(zspan, v3, v4); 02448 zbuf_add_to_span(zspan, v4, v1); 02449 } 02450 else 02451 zbuf_add_to_span(zspan, v3, v1); 02452 02453 /* clipped */ 02454 if(zspan->minp2==NULL || zspan->maxp2==NULL) return; 02455 02456 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; 02457 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; 02458 02459 if(my2<my0) return; 02460 02461 /* ZBUF DX DY, in floats still */ 02462 x1= v1[0]- v2[0]; 02463 x2= v2[0]- v3[0]; 02464 y1= v1[1]- v2[1]; 02465 y2= v2[1]- v3[1]; 02466 z1= v1[2]- v2[2]; 02467 z2= v2[2]- v3[2]; 02468 02469 x0= y1*z2-z1*y2; 02470 y0= z1*x2-x1*z2; 02471 z0= x1*y2-y1*x2; 02472 02473 if(z0==0.0f) return; 02474 02475 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; 02476 zxd= -(double)x0/(double)z0; 02477 zyd= -(double)y0/(double)z0; 02478 zy0= ((double)my2)*zyd + (double)xx1; 02479 02480 /* correct span */ 02481 sn1= (my0 + my2)/2; 02482 if(zspan->span1[sn1] < zspan->span2[sn1]) { 02483 span1= zspan->span1+my2; 02484 span2= zspan->span2+my2; 02485 } 02486 else { 02487 span1= zspan->span2+my2; 02488 span2= zspan->span1+my2; 02489 } 02490 02491 for(y=my2; y>=my0; y--, span1--, span2--) { 02492 sn1= floor(*span1); 02493 sn2= floor(*span2); 02494 sn1++; 02495 02496 if(sn2>=rectx) sn2= rectx-1; 02497 if(sn1<0) sn1= 0; 02498 02499 z= (double)sn1*zxd + zy0; 02500 02501 for(x= sn1; x<=sn2; x++, z+=zxd) 02502 zspan->sss_func(zspan->sss_handle, obi, zvlnr, x, y, z); 02503 02504 zy0 -= zyd; 02505 } 02506 } 02507 02508 void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void*, int, int, int, int, int)) 02509 { 02510 ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; 02511 ZSpan zspan; 02512 ObjectInstanceRen *obi; 02513 ObjectRen *obr; 02514 VlakRen *vlr= NULL; 02515 VertRen *v1, *v2, *v3, *v4; 02516 Material *ma=0, *sss_ma= R.sss_mat; 02517 float obwinmat[4][4], winmat[4][4], bounds[4]; 02518 float ho1[4], ho2[4], ho3[4], ho4[4]={0}; 02519 int i, v, zvlnr, c1, c2, c3, c4=0; 02520 short nofill=0, env=0, wire=0; 02521 02522 zbuf_make_winmat(&R, winmat); 02523 zbuffer_part_bounds(R.winx, R.winy, pa, bounds); 02524 zbuf_alloc_span(&zspan, pa->rectx, pa->recty, R.clipcrop); 02525 02526 zspan.sss_handle= handle; 02527 zspan.sss_func= func; 02528 02529 /* needed for transform from hoco to zbuffer co */ 02530 zspan.zmulx= ((float)R.winx)/2.0; 02531 zspan.zmuly= ((float)R.winy)/2.0; 02532 02533 /* -0.5f to center the sample position */ 02534 zspan.zofsx= -pa->disprect.xmin - 0.5f; 02535 zspan.zofsy= -pa->disprect.ymin - 0.5f; 02536 02537 /* filling methods */ 02538 zspan.zbuffunc= zbuffill_sss; 02539 02540 /* fill front and back zbuffer */ 02541 if(pa->rectz) { 02542 fillrect(pa->recto, pa->rectx, pa->recty, 0); 02543 fillrect(pa->rectp, pa->rectx, pa->recty, 0); 02544 fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); 02545 } 02546 if(pa->rectbackz) { 02547 fillrect(pa->rectbacko, pa->rectx, pa->recty, 0); 02548 fillrect(pa->rectbackp, pa->rectx, pa->recty, 0); 02549 fillrect(pa->rectbackz, pa->rectx, pa->recty, -0x7FFFFFFF); 02550 } 02551 02552 for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) { 02553 obr= obi->obr; 02554 02555 if(!(obi->lay & lay)) 02556 continue; 02557 02558 if(obi->flag & R_TRANSFORMED) 02559 mul_m4_m4m4(obwinmat, obi->mat, winmat); 02560 else 02561 copy_m4_m4(obwinmat, winmat); 02562 02563 if(clip_render_object(obi->obr->boundbox, bounds, obwinmat)) 02564 continue; 02565 02566 zbuf_project_cache_clear(cache, obr->totvert); 02567 02568 for(v=0; v<obr->totvlak; v++) { 02569 if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak; 02570 else vlr++; 02571 02572 if(material_in_material(vlr->mat, sss_ma)) { 02573 /* three cases, visible for render, only z values and nothing */ 02574 if(obi->lay & lay) { 02575 if(vlr->mat!=ma) { 02576 ma= vlr->mat; 02577 nofill= ma->mode & MA_ONLYCAST; 02578 env= (ma->mode & MA_ENV); 02579 wire= (ma->material_type == MA_TYPE_WIRE); 02580 } 02581 } 02582 else { 02583 nofill= 1; 02584 ma= NULL; /* otherwise nofill can hang */ 02585 } 02586 02587 if(nofill==0 && wire==0 && env==0) { 02588 unsigned short partclip; 02589 02590 v1= vlr->v1; 02591 v2= vlr->v2; 02592 v3= vlr->v3; 02593 v4= vlr->v4; 02594 02595 c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1); 02596 c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2); 02597 c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3); 02598 02599 /* partclipping doesn't need viewplane clipping */ 02600 partclip= c1 & c2 & c3; 02601 if(v4) { 02602 c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4); 02603 partclip &= c4; 02604 } 02605 02606 if(partclip==0) { 02607 c1= testclip(ho1); 02608 c2= testclip(ho2); 02609 c3= testclip(ho3); 02610 02611 zvlnr= v+1; 02612 zbufclip(&zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); 02613 if(v4) { 02614 c4= testclip(ho4); 02615 zbufclip(&zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); 02616 } 02617 } 02618 } 02619 } 02620 } 02621 } 02622 02623 zbuf_free_span(&zspan); 02624 } 02625 02626 /* ******************** VECBLUR ACCUM BUF ************************* */ 02627 02628 typedef struct DrawBufPixel { 02629 float *colpoin; 02630 float alpha; 02631 } DrawBufPixel; 02632 02633 02634 static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float *v2, float *v3, float *v4) 02635 { 02636 DrawBufPixel *rectpofs, *rp; 02637 double zxd, zyd, zy0, zverg; 02638 float x0,y0,z0; 02639 float x1,y1,z1,x2,y2,z2,xx1; 02640 float *span1, *span2; 02641 float *rectzofs, *rz; 02642 int x, y; 02643 int sn1, sn2, rectx, my0, my2; 02644 02645 /* init */ 02646 zbuf_init_span(zspan); 02647 02648 /* set spans */ 02649 zbuf_add_to_span(zspan, v1, v2); 02650 zbuf_add_to_span(zspan, v2, v3); 02651 zbuf_add_to_span(zspan, v3, v4); 02652 zbuf_add_to_span(zspan, v4, v1); 02653 02654 /* clipped */ 02655 if(zspan->minp2==NULL || zspan->maxp2==NULL) return; 02656 02657 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1; 02658 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1; 02659 02660 // printf("my %d %d\n", my0, my2); 02661 if(my2<my0) return; 02662 02663 /* ZBUF DX DY, in floats still */ 02664 x1= v1[0]- v2[0]; 02665 x2= v2[0]- v3[0]; 02666 y1= v1[1]- v2[1]; 02667 y2= v2[1]- v3[1]; 02668 z1= v1[2]- v2[2]; 02669 z2= v2[2]- v3[2]; 02670 x0= y1*z2-z1*y2; 02671 y0= z1*x2-x1*z2; 02672 z0= x1*y2-y1*x2; 02673 02674 if(z0==0.0) return; 02675 02676 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2]; 02677 02678 zxd= -(double)x0/(double)z0; 02679 zyd= -(double)y0/(double)z0; 02680 zy0= ((double)my2)*zyd + (double)xx1; 02681 02682 /* start-offset in rect */ 02683 rectx= zspan->rectx; 02684 rectzofs= (float *)(zspan->rectz + rectx*my2); 02685 rectpofs= ((DrawBufPixel *)zspan->rectp) + rectx*my2; 02686 02687 /* correct span */ 02688 sn1= (my0 + my2)/2; 02689 if(zspan->span1[sn1] < zspan->span2[sn1]) { 02690 span1= zspan->span1+my2; 02691 span2= zspan->span2+my2; 02692 } 02693 else { 02694 span1= zspan->span2+my2; 02695 span2= zspan->span1+my2; 02696 } 02697 02698 for(y=my2; y>=my0; y--, span1--, span2--) { 02699 02700 sn1= floor(*span1); 02701 sn2= floor(*span2); 02702 sn1++; 02703 02704 if(sn2>=rectx) sn2= rectx-1; 02705 if(sn1<0) sn1= 0; 02706 02707 if(sn2>=sn1) { 02708 zverg= (double)sn1*zxd + zy0; 02709 rz= rectzofs+sn1; 02710 rp= rectpofs+sn1; 02711 x= sn2-sn1; 02712 02713 while(x>=0) { 02714 if( zverg < *rz) { 02715 *rz= zverg; 02716 *rp= *col; 02717 } 02718 zverg+= zxd; 02719 rz++; 02720 rp++; 02721 x--; 02722 } 02723 } 02724 02725 zy0-=zyd; 02726 rectzofs-= rectx; 02727 rectpofs-= rectx; 02728 } 02729 } 02730 02731 /* char value==255 is filled in, rest should be zero */ 02732 /* returns alpha values, but sets alpha to 1 for zero alpha pixels that have an alpha value as neighbour */ 02733 void antialias_tagbuf(int xsize, int ysize, char *rectmove) 02734 { 02735 char *row1, *row2, *row3; 02736 char prev, next; 02737 int a, x, y, step; 02738 02739 /* 1: tag pixels to be candidate for AA */ 02740 for(y=2; y<ysize; y++) { 02741 /* setup rows */ 02742 row1= rectmove + (y-2)*xsize; 02743 row2= row1 + xsize; 02744 row3= row2 + xsize; 02745 for(x=2; x<xsize; x++, row1++, row2++, row3++) { 02746 if(row2[1]) { 02747 if(row2[0]==0 || row2[2]==0 || row1[1]==0 || row3[1]==0) 02748 row2[1]= 128; 02749 } 02750 } 02751 } 02752 02753 /* 2: evaluate horizontal scanlines and calculate alphas */ 02754 row1= rectmove; 02755 for(y=0; y<ysize; y++) { 02756 row1++; 02757 for(x=1; x<xsize; x++, row1++) { 02758 if(row1[0]==128 && row1[1]==128) { 02759 /* find previous color and next color and amount of steps to blend */ 02760 prev= row1[-1]; 02761 step= 1; 02762 while(x+step<xsize && row1[step]==128) 02763 step++; 02764 02765 if(x+step!=xsize) { 02766 /* now we can blend values */ 02767 next= row1[step]; 02768 02769 /* note, prev value can be next value, but we do this loop to clear 128 then */ 02770 for(a=0; a<step; a++) { 02771 int fac, mfac; 02772 02773 fac= ((a+1)<<8)/(step+1); 02774 mfac= 255-fac; 02775 02776 row1[a]= (prev*mfac + next*fac)>>8; 02777 } 02778 } 02779 } 02780 } 02781 } 02782 02783 /* 3: evaluate vertical scanlines and calculate alphas */ 02784 /* use for reading a copy of the original tagged buffer */ 02785 for(x=0; x<xsize; x++) { 02786 row1= rectmove + x+xsize; 02787 02788 for(y=1; y<ysize; y++, row1+=xsize) { 02789 if(row1[0]==128 && row1[xsize]==128) { 02790 /* find previous color and next color and amount of steps to blend */ 02791 prev= row1[-xsize]; 02792 step= 1; 02793 while(y+step<ysize && row1[step*xsize]==128) 02794 step++; 02795 02796 if(y+step!=ysize) { 02797 /* now we can blend values */ 02798 next= row1[step*xsize]; 02799 /* note, prev value can be next value, but we do this loop to clear 128 then */ 02800 for(a=0; a<step; a++) { 02801 int fac, mfac; 02802 02803 fac= ((a+1)<<8)/(step+1); 02804 mfac= 255-fac; 02805 02806 row1[a*xsize]= (prev*mfac + next*fac)>>8; 02807 } 02808 } 02809 } 02810 } 02811 } 02812 02813 /* last: pixels with 0 we fill in zbuffer, with 1 we skip for mask */ 02814 for(y=2; y<ysize; y++) { 02815 /* setup rows */ 02816 row1= rectmove + (y-2)*xsize; 02817 row2= row1 + xsize; 02818 row3= row2 + xsize; 02819 for(x=2; x<xsize; x++, row1++, row2++, row3++) { 02820 if(row2[1]==0) { 02821 if(row2[0]>1 || row2[2]>1 || row1[1]>1 || row3[1]>1) 02822 row2[1]= 1; 02823 } 02824 } 02825 } 02826 } 02827 02828 /* in: two vectors, first vector points from origin back in time, 2nd vector points to future */ 02829 /* we make this into 3 points, center point is (0,0) */ 02830 /* and offset the center point just enough to make curve go through midpoint */ 02831 02832 static void quad_bezier_2d(float *result, float *v1, float *v2, float *ipodata) 02833 { 02834 float p1[2], p2[2], p3[2]; 02835 02836 p3[0]= -v2[0]; 02837 p3[1]= -v2[1]; 02838 02839 p1[0]= v1[0]; 02840 p1[1]= v1[1]; 02841 02842 /* official formula 2*p2 - .5*p1 - .5*p3 */ 02843 p2[0]= -0.5*p1[0] - 0.5*p3[0]; 02844 p2[1]= -0.5*p1[1] - 0.5*p3[1]; 02845 02846 result[0]= ipodata[0]*p1[0] + ipodata[1]*p2[0] + ipodata[2]*p3[0]; 02847 result[1]= ipodata[0]*p1[1] + ipodata[1]*p2[1] + ipodata[2]*p3[1]; 02848 } 02849 02850 static void set_quad_bezier_ipo(float fac, float *data) 02851 { 02852 float mfac= (1.0f-fac); 02853 02854 data[0]= mfac*mfac; 02855 data[1]= 2.0f*mfac*fac; 02856 data[2]= fac*fac; 02857 } 02858 02859 void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect) 02860 { 02861 ZSpan zspan; 02862 DrawBufPixel *rectdraw, *dr; 02863 static float jit[256][2]; 02864 float v1[3], v2[3], v3[3], v4[3], fx, fy; 02865 float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz; 02866 float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm, *ro; 02867 float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed, totfac; 02868 int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples; 02869 int tsktsk= 0; 02870 static int firsttime= 1; 02871 char *rectmove, *dm; 02872 02873 zbuf_alloc_span(&zspan, xsize, ysize, 1.0f); 02874 zspan.zmulx= ((float)xsize)/2.0; 02875 zspan.zmuly= ((float)ysize)/2.0; 02876 zspan.zofsx= 0.0f; 02877 zspan.zofsy= 0.0f; 02878 02879 /* the buffers */ 02880 rectz= MEM_mapallocN(sizeof(float)*xsize*ysize, "zbuf accum"); 02881 zspan.rectz= (int *)rectz; 02882 02883 rectmove= MEM_mapallocN(xsize*ysize, "rectmove"); 02884 rectdraw= MEM_mapallocN(sizeof(DrawBufPixel)*xsize*ysize, "rect draw"); 02885 zspan.rectp= (int *)rectdraw; 02886 02887 rectweight= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect weight"); 02888 rectmax= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect max"); 02889 02890 /* debug... check if PASS_VECTOR_MAX still is in buffers */ 02891 dvec1= vecbufrect; 02892 for(x= 4*xsize*ysize; x>0; x--, dvec1++) { 02893 if(dvec1[0]==PASS_VECTOR_MAX) { 02894 dvec1[0]= 0.0f; 02895 tsktsk= 1; 02896 } 02897 } 02898 if(tsktsk) printf("Found uninitialized speed in vector buffer... fixed.\n"); 02899 02900 /* min speed? then copy speedbuffer to recalculate speed vectors */ 02901 if(nbd->minspeed) { 02902 float minspeed= (float)nbd->minspeed; 02903 float minspeedsq= minspeed*minspeed; 02904 02905 minvecbufrect= MEM_mapallocN(4*sizeof(float)*xsize*ysize, "minspeed buf"); 02906 02907 dvec1= vecbufrect; 02908 dvec2= minvecbufrect; 02909 for(x= 2*xsize*ysize; x>0; x--, dvec1+=2, dvec2+=2) { 02910 if(dvec1[0]==0.0f && dvec1[1]==0.0f) { 02911 dvec2[0]= dvec1[0]; 02912 dvec2[1]= dvec1[1]; 02913 } 02914 else { 02915 float speedsq= dvec1[0]*dvec1[0] + dvec1[1]*dvec1[1]; 02916 if(speedsq <= minspeedsq) { 02917 dvec2[0]= 0.0f; 02918 dvec2[1]= 0.0f; 02919 } 02920 else { 02921 speedsq= 1.0f - minspeed/sqrt(speedsq); 02922 dvec2[0]= speedsq*dvec1[0]; 02923 dvec2[1]= speedsq*dvec1[1]; 02924 } 02925 } 02926 } 02927 SWAP(float *, minvecbufrect, vecbufrect); 02928 } 02929 02930 /* make vertex buffer with averaged speed and zvalues */ 02931 rectvz= MEM_mapallocN(4*sizeof(float)*(xsize+1)*(ysize+1), "vertices"); 02932 dvz= rectvz; 02933 for(y=0; y<=ysize; y++) { 02934 02935 if(y==0) 02936 dvec1= vecbufrect + 4*y*xsize; 02937 else 02938 dvec1= vecbufrect + 4*(y-1)*xsize; 02939 02940 if(y==ysize) 02941 dvec2= vecbufrect + 4*(y-1)*xsize; 02942 else 02943 dvec2= vecbufrect + 4*y*xsize; 02944 02945 for(x=0; x<=xsize; x++) { 02946 02947 /* two vectors, so a step loop */ 02948 for(step=0; step<2; step++, dvec1+=2, dvec2+=2, dvz+=2) { 02949 /* average on minimal speed */ 02950 int div= 0; 02951 02952 if(x!=0) { 02953 if(dvec1[-4]!=0.0f || dvec1[-3]!=0.0f) { 02954 dvz[0]= dvec1[-4]; 02955 dvz[1]= dvec1[-3]; 02956 div++; 02957 } 02958 if(dvec2[-4]!=0.0f || dvec2[-3]!=0.0f) { 02959 if(div==0) { 02960 dvz[0]= dvec2[-4]; 02961 dvz[1]= dvec2[-3]; 02962 div++; 02963 } 02964 else if( (ABS(dvec2[-4]) + ABS(dvec2[-3]))< (ABS(dvz[0]) + ABS(dvz[1])) ) { 02965 dvz[0]= dvec2[-4]; 02966 dvz[1]= dvec2[-3]; 02967 } 02968 } 02969 } 02970 02971 if(x!=xsize) { 02972 if(dvec1[0]!=0.0f || dvec1[1]!=0.0f) { 02973 if(div==0) { 02974 dvz[0]= dvec1[0]; 02975 dvz[1]= dvec1[1]; 02976 div++; 02977 } 02978 else if( (ABS(dvec1[0]) + ABS(dvec1[1]))< (ABS(dvz[0]) + ABS(dvz[1])) ) { 02979 dvz[0]= dvec1[0]; 02980 dvz[1]= dvec1[1]; 02981 } 02982 } 02983 if(dvec2[0]!=0.0f || dvec2[1]!=0.0f) { 02984 if(div==0) { 02985 dvz[0]= dvec2[0]; 02986 dvz[1]= dvec2[1]; 02987 } 02988 else if( (ABS(dvec2[0]) + ABS(dvec2[1]))< (ABS(dvz[0]) + ABS(dvz[1])) ) { 02989 dvz[0]= dvec2[0]; 02990 dvz[1]= dvec2[1]; 02991 } 02992 } 02993 } 02994 if(maxspeed) { 02995 float speedsq= dvz[0]*dvz[0] + dvz[1]*dvz[1]; 02996 if(speedsq > maxspeedsq) { 02997 speedsq= (float)maxspeed/sqrt(speedsq); 02998 dvz[0]*= speedsq; 02999 dvz[1]*= speedsq; 03000 } 03001 } 03002 } 03003 } 03004 } 03005 03006 /* set border speeds to keep border speeds on border */ 03007 dz1= rectvz; 03008 dz2= rectvz+4*(ysize)*(xsize+1); 03009 for(x=0; x<=xsize; x++, dz1+=4, dz2+=4) { 03010 dz1[1]= 0.0f; 03011 dz2[1]= 0.0f; 03012 dz1[3]= 0.0f; 03013 dz2[3]= 0.0f; 03014 } 03015 dz1= rectvz; 03016 dz2= rectvz+4*(xsize); 03017 for(y=0; y<=ysize; y++, dz1+=4*(xsize+1), dz2+=4*(xsize+1)) { 03018 dz1[0]= 0.0f; 03019 dz2[0]= 0.0f; 03020 dz1[2]= 0.0f; 03021 dz2[2]= 0.0f; 03022 } 03023 03024 /* tag moving pixels, only these faces we draw */ 03025 dm= rectmove; 03026 dvec1= vecbufrect; 03027 for(x=xsize*ysize; x>0; x--, dm++, dvec1+=4) { 03028 if((dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f)) 03029 *dm= 255; 03030 } 03031 03032 antialias_tagbuf(xsize, ysize, rectmove); 03033 03034 /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */ 03035 if(firsttime) { 03036 firsttime= 0; 03037 BLI_initjit(jit[0], 256); 03038 } 03039 03040 memset(newrect, 0, sizeof(float)*xsize*ysize*4); 03041 totfac= 0.0f; 03042 03043 /* accumulate */ 03044 samples/= 2; 03045 for(step= 1; step<=samples; step++) { 03046 float speedfac= 0.5f*nbd->fac*(float)step/(float)(samples+1); 03047 int side; 03048 03049 for(side=0; side<2; side++) { 03050 float blendfac, ipodata[4]; 03051 03052 /* clear zbuf, if we draw future we fill in not moving pixels */ 03053 if(0) 03054 for(x= xsize*ysize-1; x>=0; x--) rectz[x]= 10e16; 03055 else 03056 for(x= xsize*ysize-1; x>=0; x--) { 03057 if(rectmove[x]==0) 03058 rectz[x]= zbufrect[x]; 03059 else 03060 rectz[x]= 10e16; 03061 } 03062 03063 /* clear drawing buffer */ 03064 for(x= xsize*ysize-1; x>=0; x--) rectdraw[x].colpoin= NULL; 03065 03066 dimg= imgrect; 03067 dm= rectmove; 03068 dz= zbufrect; 03069 dz1= rectvz; 03070 dz2= rectvz + 4*(xsize + 1); 03071 03072 if(side) { 03073 if(nbd->curved==0) { 03074 dz1+= 2; 03075 dz2+= 2; 03076 } 03077 speedfac= -speedfac; 03078 } 03079 03080 set_quad_bezier_ipo(0.5f + 0.5f*speedfac, ipodata); 03081 03082 for(fy= -0.5f+jit[step & 255][0], y=0; y<ysize; y++, fy+=1.0f) { 03083 for(fx= -0.5f+jit[step & 255][1], x=0; x<xsize; x++, fx+=1.0f, dimg+=4, dz1+=4, dz2+=4, dm++, dz++) { 03084 if(*dm>1) { 03085 float jfx = fx + 0.5f; 03086 float jfy = fy + 0.5f; 03087 DrawBufPixel col; 03088 03089 /* make vertices */ 03090 if(nbd->curved) { /* curved */ 03091 quad_bezier_2d(v1, dz1, dz1+2, ipodata); 03092 v1[0]+= jfx; v1[1]+= jfy; v1[2]= *dz; 03093 03094 quad_bezier_2d(v2, dz1+4, dz1+4+2, ipodata); 03095 v2[0]+= jfx+1.0f; v2[1]+= jfy; v2[2]= *dz; 03096 03097 quad_bezier_2d(v3, dz2+4, dz2+4+2, ipodata); 03098 v3[0]+= jfx+1.0f; v3[1]+= jfy+1.0f; v3[2]= *dz; 03099 03100 quad_bezier_2d(v4, dz2, dz2+2, ipodata); 03101 v4[0]+= jfx; v4[1]+= jfy+1.0f; v4[2]= *dz; 03102 } 03103 else { 03104 v1[0]= speedfac*dz1[0]+jfx; v1[1]= speedfac*dz1[1]+jfy; v1[2]= *dz; 03105 v2[0]= speedfac*dz1[4]+jfx+1.0f; v2[1]= speedfac*dz1[5]+jfy; v2[2]= *dz; 03106 v3[0]= speedfac*dz2[4]+jfx+1.0f; v3[1]= speedfac*dz2[5]+jfy+1.0f; v3[2]= *dz; 03107 v4[0]= speedfac*dz2[0]+jfx; v4[1]= speedfac*dz2[1]+jfy+1.0f; v4[2]= *dz; 03108 } 03109 if(*dm==255) col.alpha= 1.0f; 03110 else if(*dm<2) col.alpha= 0.0f; 03111 else col.alpha= ((float)*dm)/255.0f; 03112 col.colpoin= dimg; 03113 03114 zbuf_fill_in_rgba(&zspan, &col, v1, v2, v3, v4); 03115 } 03116 } 03117 dz1+=4; 03118 dz2+=4; 03119 } 03120 03121 /* blend with a falloff. this fixes the ugly effect you get with 03122 * a fast moving object. then it looks like a solid object overlayed 03123 * over a very transparent moving version of itself. in reality, the 03124 * whole object should become transparent if it is moving fast, be 03125 * we don't know what is behind it so we don't do that. this hack 03126 * overestimates the contribution of foreground pixels but looks a 03127 * bit better without a sudden cutoff. */ 03128 blendfac= ((samples - step)/(float)samples); 03129 /* smoothstep to make it look a bit nicer as well */ 03130 blendfac= 3.0f*pow(blendfac, 2.0f) - 2.0f*pow(blendfac, 3.0f); 03131 03132 /* accum */ 03133 rw= rectweight; 03134 rm= rectmax; 03135 for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4, rw++, rm++) { 03136 if(dr->colpoin) { 03137 float bfac= dr->alpha*blendfac; 03138 03139 dz2[0] += bfac*dr->colpoin[0]; 03140 dz2[1] += bfac*dr->colpoin[1]; 03141 dz2[2] += bfac*dr->colpoin[2]; 03142 dz2[3] += bfac*dr->colpoin[3]; 03143 03144 *rw += bfac; 03145 *rm= MAX2(*rm, bfac); 03146 } 03147 } 03148 } 03149 } 03150 03151 /* blend between original images and accumulated image */ 03152 rw= rectweight; 03153 rm= rectmax; 03154 ro= imgrect; 03155 dm= rectmove; 03156 for(dz2=newrect, x= xsize*ysize-1; x>=0; x--, dz2+=4, ro+=4, rw++, rm++, dm++) { 03157 float mfac = *rm; 03158 float fac = (*rw == 0.0f)? 0.0f: mfac/(*rw); 03159 float nfac = 1.0f - mfac; 03160 03161 dz2[0]= fac*dz2[0] + nfac*ro[0]; 03162 dz2[1]= fac*dz2[1] + nfac*ro[1]; 03163 dz2[2]= fac*dz2[2] + nfac*ro[2]; 03164 dz2[3]= fac*dz2[3] + nfac*ro[3]; 03165 } 03166 03167 MEM_freeN(rectz); 03168 MEM_freeN(rectmove); 03169 MEM_freeN(rectdraw); 03170 MEM_freeN(rectvz); 03171 MEM_freeN(rectweight); 03172 MEM_freeN(rectmax); 03173 if(minvecbufrect) MEM_freeN(vecbufrect); /* rects were swapped! */ 03174 zbuf_free_span(&zspan); 03175 } 03176 03177 /* ******************** ABUF ************************* */ 03178 03183 static void copyto_abufz(RenderPart *pa, int *arectz, int *rectmask, int sample) 03184 { 03185 PixStr *ps; 03186 int x, y, *rza, *rma; 03187 intptr_t *rd; 03188 03189 if(R.osa==0) { 03190 if(!pa->rectz) 03191 fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFE); 03192 else 03193 memcpy(arectz, pa->rectz, sizeof(int)*pa->rectx*pa->recty); 03194 03195 if(rectmask && pa->rectmask) 03196 memcpy(rectmask, pa->rectmask, sizeof(int)*pa->rectx*pa->recty); 03197 03198 return; 03199 } 03200 else if(!pa->rectdaps) { 03201 fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFE); 03202 return; 03203 } 03204 03205 rza= arectz; 03206 rma= rectmask; 03207 rd= pa->rectdaps; 03208 03209 sample= (1<<sample); 03210 03211 for(y=0; y<pa->recty; y++) { 03212 for(x=0; x<pa->rectx; x++) { 03213 03214 *rza= 0x7FFFFFFF; 03215 if(rectmask) *rma= 0x7FFFFFFF; 03216 if(*rd) { 03217 /* when there's a sky pixstruct, fill in sky-Z, otherwise solid Z */ 03218 for(ps= (PixStr *)(*rd); ps; ps= ps->next) { 03219 if(sample & ps->mask) { 03220 *rza= ps->z; 03221 if(rectmask) *rma= ps->maskz; 03222 break; 03223 } 03224 } 03225 } 03226 03227 rd++; rza++, rma++; 03228 } 03229 } 03230 } 03231 03232 03233 /* ------------------------------------------------------------------------ */ 03234 03239 static int zbuffer_abuf(Render *re, RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, unsigned int lay, int negzmask, float winmat[][4], int winx, int winy, int samples, float (*jit)[2], float UNUSED(clipcrop), int shadow) 03240 { 03241 ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; 03242 ZSpan zspans[16], *zspan; /* MAX_OSA */ 03243 Material *ma=NULL; 03244 ObjectInstanceRen *obi; 03245 ObjectRen *obr; 03246 VlakRen *vlr=NULL; 03247 VertRen *v1, *v2, *v3, *v4; 03248 float vec[3], hoco[4], mul, zval, fval; 03249 float obwinmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0}; 03250 int i, v, zvlnr, c1, c2, c3, c4=0, dofill= 0; 03251 int zsample, polygon_offset; 03252 03253 zbuffer_part_bounds(winx, winy, pa, bounds); 03254 03255 for(zsample=0; zsample<samples; zsample++) { 03256 zspan= &zspans[zsample]; 03257 03258 zbuf_alloc_span(zspan, pa->rectx, pa->recty, re->clipcrop); 03259 03260 /* needed for transform from hoco to zbuffer co */ 03261 zspan->zmulx= ((float)winx)/2.0; 03262 zspan->zmuly= ((float)winy)/2.0; 03263 03264 /* the buffers */ 03265 zspan->arectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectz"); 03266 zspan->apixbuf= APixbuf; 03267 zspan->apsmbase= apsmbase; 03268 03269 if(negzmask) 03270 zspan->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectmask"); 03271 03272 /* filling methods */ 03273 zspan->zbuffunc= zbuffillAc4; 03274 zspan->zbuflinefunc= zbuflineAc; 03275 03276 copyto_abufz(pa, zspan->arectz, zspan->rectmask, zsample); /* init zbuffer */ 03277 zspan->mask= 1<<zsample; 03278 03279 if(jit) { 03280 zspan->zofsx= -pa->disprect.xmin - jit[zsample][0]; 03281 zspan->zofsy= -pa->disprect.ymin - jit[zsample][1]; 03282 } 03283 else { 03284 zspan->zofsx= -pa->disprect.xmin; 03285 zspan->zofsy= -pa->disprect.ymin; 03286 } 03287 03288 /* to center the sample position */ 03289 zspan->zofsx -= 0.5f; 03290 zspan->zofsy -= 0.5f; 03291 } 03292 03293 /* we use this to test if nothing was filled in */ 03294 zvlnr= 0; 03295 03296 for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) { 03297 obr= obi->obr; 03298 03299 if(!(obi->lay & lay)) 03300 continue; 03301 03302 if(obi->flag & R_TRANSFORMED) 03303 mul_m4_m4m4(obwinmat, obi->mat, winmat); 03304 else 03305 copy_m4_m4(obwinmat, winmat); 03306 03307 if(clip_render_object(obi->obr->boundbox, bounds, obwinmat)) 03308 continue; 03309 03310 zbuf_project_cache_clear(cache, obr->totvert); 03311 03312 for(v=0; v<obr->totvlak; v++) { 03313 if((v & 255)==0) 03314 vlr= obr->vlaknodes[v>>8].vlak; 03315 else vlr++; 03316 03317 if(vlr->mat!=ma) { 03318 ma= vlr->mat; 03319 if(shadow) 03320 dofill= (ma->mode & MA_SHADBUF); 03321 else 03322 dofill= (((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) && !(ma->mode & MA_ONLYCAST)); 03323 } 03324 03325 if(dofill) { 03326 if(!(vlr->flag & R_HIDDEN) && (obi->lay & lay)) { 03327 unsigned short partclip; 03328 03329 v1= vlr->v1; 03330 v2= vlr->v2; 03331 v3= vlr->v3; 03332 v4= vlr->v4; 03333 03334 c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1); 03335 c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2); 03336 c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3); 03337 03338 /* partclipping doesn't need viewplane clipping */ 03339 partclip= c1 & c2 & c3; 03340 if(v4) { 03341 c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4); 03342 partclip &= c4; 03343 } 03344 03345 if(partclip==0) { 03346 /* a little advantage for transp rendering (a z offset) */ 03347 if(!shadow && ma->zoffs != 0.0) { 03348 mul= 0x7FFFFFFF; 03349 zval= mul*(1.0+ho1[2]/ho1[3]); 03350 03351 VECCOPY(vec, v1->co); 03352 /* z is negative, otherwise its being clipped */ 03353 vec[2]-= ma->zoffs; 03354 projectverto(vec, obwinmat, hoco); 03355 fval= mul*(1.0+hoco[2]/hoco[3]); 03356 03357 polygon_offset= (int) fabs(zval - fval ); 03358 } 03359 else polygon_offset= 0; 03360 03361 zvlnr= v+1; 03362 03363 c1= testclip(ho1); 03364 c2= testclip(ho2); 03365 c3= testclip(ho3); 03366 if(v4) 03367 c4= testclip(ho4); 03368 03369 for(zsample=0; zsample<samples; zsample++) { 03370 zspan= &zspans[zsample]; 03371 zspan->polygon_offset= polygon_offset; 03372 03373 if(ma->material_type == MA_TYPE_WIRE) { 03374 if(v4) 03375 zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); 03376 else 03377 zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0); 03378 } 03379 else { 03380 if(v4 && (vlr->flag & R_STRAND)) { 03381 zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4); 03382 } 03383 else { 03384 zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); 03385 if(v4) 03386 zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); 03387 } 03388 } 03389 } 03390 } 03391 if((v & 255)==255) 03392 if(re->test_break(re->tbh)) 03393 break; 03394 } 03395 } 03396 } 03397 03398 if(re->test_break(re->tbh)) break; 03399 } 03400 03401 for(zsample=0; zsample<samples; zsample++) { 03402 zspan= &zspans[zsample]; 03403 MEM_freeN(zspan->arectz); 03404 if(zspan->rectmask) 03405 MEM_freeN(zspan->rectmask); 03406 zbuf_free_span(zspan); 03407 } 03408 03409 return zvlnr; 03410 } 03411 03412 static int zbuffer_abuf_render(RenderPart *pa, APixstr *APixbuf, APixstrand *APixbufstrand, ListBase *apsmbase, RenderLayer *rl, StrandShadeCache *sscache) 03413 { 03414 float winmat[4][4], (*jit)[2]; 03415 int samples, negzmask, doztra= 0; 03416 03417 samples= (R.osa)? R.osa: 1; 03418 negzmask= ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)); 03419 03420 if(R.osa) 03421 jit= R.jit; 03422 else if(R.i.curblur) 03423 jit= &R.mblur_jit[R.i.curblur-1]; 03424 else 03425 jit= NULL; 03426 03427 zbuf_make_winmat(&R, winmat); 03428 03429 if(rl->layflag & SCE_LAY_ZTRA) 03430 doztra+= zbuffer_abuf(&R, pa, APixbuf, apsmbase, rl->lay, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0); 03431 if((rl->layflag & SCE_LAY_STRAND) && APixbufstrand) 03432 doztra+= zbuffer_strands_abuf(&R, pa, APixbufstrand, apsmbase, rl->lay, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0, sscache); 03433 03434 return doztra; 03435 } 03436 03437 void zbuffer_abuf_shadow(Render *re, LampRen *lar, float winmat[][4], APixstr *APixbuf, APixstrand *APixbufstrand, ListBase *apsmbase, int size, int samples, float (*jit)[2]) 03438 { 03439 RenderPart pa; 03440 int lay= -1; 03441 03442 if(lar->mode & LA_LAYER) lay= lar->lay; 03443 03444 memset(&pa, 0, sizeof(RenderPart)); 03445 pa.rectx= size; 03446 pa.recty= size; 03447 pa.disprect.xmin= 0; 03448 pa.disprect.ymin= 0; 03449 pa.disprect.xmax= size; 03450 pa.disprect.ymax= size; 03451 03452 zbuffer_abuf(re, &pa, APixbuf, apsmbase, lay, 0, winmat, size, size, samples, jit, 1.0f, 1); 03453 if(APixbufstrand) 03454 zbuffer_strands_abuf(re, &pa, APixbufstrand, apsmbase, lay, 0, winmat, size, size, samples, jit, 1.0f, 1, NULL); 03455 } 03456 03457 /* different rules for speed in transparent pass... */ 03458 /* speed pointer NULL = sky, we clear */ 03459 /* else if either alpha is full or no solid was filled in: copy speed */ 03460 /* else fill in minimum speed */ 03461 void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, intptr_t *rdrect) 03462 { 03463 RenderPass *rpass; 03464 03465 for(rpass= rl->passes.first; rpass; rpass= rpass->next) { 03466 if(rpass->passtype==SCE_PASS_VECTOR) { 03467 float *fp= rpass->rect + 4*offset; 03468 03469 if(speed==NULL) { 03470 /* clear */ 03471 if(fp[0]==PASS_VECTOR_MAX) fp[0]= 0.0f; 03472 if(fp[1]==PASS_VECTOR_MAX) fp[1]= 0.0f; 03473 if(fp[2]==PASS_VECTOR_MAX) fp[2]= 0.0f; 03474 if(fp[3]==PASS_VECTOR_MAX) fp[3]= 0.0f; 03475 } 03476 else if(rdrect==NULL || rdrect[offset]==0 || alpha>0.95f) { 03477 QUATCOPY(fp, speed); 03478 } 03479 else { 03480 /* add minimum speed in pixel */ 03481 if( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { 03482 fp[0]= speed[0]; 03483 fp[1]= speed[1]; 03484 } 03485 if( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { 03486 fp[2]= speed[2]; 03487 fp[3]= speed[3]; 03488 } 03489 } 03490 break; 03491 } 03492 } 03493 } 03494 03495 static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob) 03496 { 03497 RenderPass *rpass; 03498 03499 for(rpass= rl->passes.first; rpass; rpass= rpass->next) { 03500 if(rpass->passtype == SCE_PASS_INDEXOB||rpass->passtype == SCE_PASS_INDEXMA) { 03501 float *fp= rpass->rect + offset; 03502 *fp= (float)ob->index; 03503 break; 03504 } 03505 } 03506 } 03507 03508 /* ONLY OSA! merge all shaderesult samples to one */ 03509 /* target should have been cleared */ 03510 void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) 03511 { 03512 RenderPass *rpass; 03513 float weight= 1.0f/((float)R.osa); 03514 int delta= sizeof(ShadeResult)/4; 03515 03516 for(rpass= rl->passes.first; rpass; rpass= rpass->next) { 03517 float *col= NULL; 03518 int pixsize= 3; 03519 03520 switch(rpass->passtype) { 03521 case SCE_PASS_RGBA: 03522 col= shr->col; 03523 pixsize= 4; 03524 break; 03525 case SCE_PASS_EMIT: 03526 col= shr->emit; 03527 break; 03528 case SCE_PASS_DIFFUSE: 03529 col= shr->diff; 03530 break; 03531 case SCE_PASS_SPEC: 03532 col= shr->spec; 03533 break; 03534 case SCE_PASS_SHADOW: 03535 col= shr->shad; 03536 break; 03537 case SCE_PASS_AO: 03538 col= shr->ao; 03539 break; 03540 case SCE_PASS_ENVIRONMENT: 03541 col= shr->env; 03542 break; 03543 case SCE_PASS_INDIRECT: 03544 col= shr->indirect; 03545 break; 03546 case SCE_PASS_REFLECT: 03547 col= shr->refl; 03548 break; 03549 case SCE_PASS_REFRACT: 03550 col= shr->refr; 03551 break; 03552 case SCE_PASS_NORMAL: 03553 col= shr->nor; 03554 break; 03555 case SCE_PASS_MIST: 03556 col= &shr->mist; 03557 pixsize= 1; 03558 break; 03559 case SCE_PASS_Z: 03560 col= &shr->z; 03561 pixsize= 1; 03562 break; 03563 case SCE_PASS_VECTOR: 03564 03565 { 03566 ShadeResult *shr_t= shr+1; 03567 float *fp= shr->winspeed; /* was initialized */ 03568 int samp; 03569 03570 /* add minimum speed in pixel */ 03571 for(samp= 1; samp<R.osa; samp++, shr_t++) { 03572 03573 if(shr_t->combined[3] > 0.0f) { 03574 float *speed= shr_t->winspeed; 03575 03576 if( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { 03577 fp[0]= speed[0]; 03578 fp[1]= speed[1]; 03579 } 03580 if( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { 03581 fp[2]= speed[2]; 03582 fp[3]= speed[3]; 03583 } 03584 } 03585 } 03586 } 03587 break; 03588 } 03589 if(col) { 03590 float *fp= col+delta; 03591 int samp; 03592 03593 for(samp= 1; samp<R.osa; samp++, fp+=delta) { 03594 col[0]+= fp[0]; 03595 if(pixsize>1) { 03596 col[1]+= fp[1]; 03597 col[2]+= fp[2]; 03598 if(pixsize==4) col[3]+= fp[3]; 03599 } 03600 } 03601 col[0]*= weight; 03602 if(pixsize>1) { 03603 col[1]*= weight; 03604 col[2]*= weight; 03605 if(pixsize==4) col[3]*= weight; 03606 } 03607 } 03608 } 03609 03610 } 03611 03612 void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha) 03613 { 03614 RenderPass *rpass; 03615 03616 for(rpass= rl->passes.first; rpass; rpass= rpass->next) { 03617 float *fp, *col= NULL; 03618 int pixsize= 3; 03619 03620 switch(rpass->passtype) { 03621 case SCE_PASS_Z: 03622 fp= rpass->rect + offset; 03623 if(shr->z < *fp) 03624 *fp= shr->z; 03625 break; 03626 case SCE_PASS_RGBA: 03627 fp= rpass->rect + 4*offset; 03628 addAlphaOverFloat(fp, shr->col); 03629 break; 03630 case SCE_PASS_EMIT: 03631 col= shr->emit; 03632 break; 03633 case SCE_PASS_DIFFUSE: 03634 col= shr->diff; 03635 break; 03636 case SCE_PASS_SPEC: 03637 col= shr->spec; 03638 break; 03639 case SCE_PASS_SHADOW: 03640 col= shr->shad; 03641 break; 03642 case SCE_PASS_AO: 03643 col= shr->ao; 03644 break; 03645 case SCE_PASS_ENVIRONMENT: 03646 col= shr->env; 03647 break; 03648 case SCE_PASS_INDIRECT: 03649 col= shr->indirect; 03650 break; 03651 case SCE_PASS_REFLECT: 03652 col= shr->refl; 03653 break; 03654 case SCE_PASS_REFRACT: 03655 col= shr->refr; 03656 break; 03657 case SCE_PASS_NORMAL: 03658 col= shr->nor; 03659 break; 03660 case SCE_PASS_MIST: 03661 col= &shr->mist; 03662 pixsize= 1; 03663 break; 03664 } 03665 if(col) { 03666 03667 fp= rpass->rect + pixsize*offset; 03668 fp[0]= col[0] + (1.0f-alpha)*fp[0]; 03669 if(pixsize==3) { 03670 fp[1]= col[1] + (1.0f-alpha)*fp[1]; 03671 fp[2]= col[2] + (1.0f-alpha)*fp[2]; 03672 } 03673 } 03674 } 03675 } 03676 03677 typedef struct ZTranspRow { 03678 int obi; 03679 int z; 03680 int p; 03681 int mask; 03682 int segment; 03683 float u, v; 03684 } ZTranspRow; 03685 03686 static int vergzvlak(const void *a1, const void *a2) 03687 { 03688 const ZTranspRow *r1 = a1, *r2 = a2; 03689 03690 if(r1->z < r2->z) return 1; 03691 else if(r1->z > r2->z) return -1; 03692 return 0; 03693 } 03694 03695 static void shade_strand_samples(StrandShadeCache *cache, ShadeSample *ssamp, int UNUSED(x), int UNUSED(y), ZTranspRow *row, int addpassflag) 03696 { 03697 StrandSegment sseg; 03698 StrandVert *svert; 03699 ObjectInstanceRen *obi; 03700 ObjectRen *obr; 03701 03702 obi= R.objectinstance + row->obi; 03703 obr= obi->obr; 03704 03705 sseg.obi= obi; 03706 sseg.strand= RE_findOrAddStrand(obr, row->p-1); 03707 sseg.buffer= sseg.strand->buffer; 03708 03709 svert= sseg.strand->vert + row->segment; 03710 sseg.v[0]= (row->segment > 0)? (svert-1): svert; 03711 sseg.v[1]= svert; 03712 sseg.v[2]= svert+1; 03713 sseg.v[3]= (row->segment < sseg.strand->totvert-2)? svert+2: svert+1; 03714 03715 ssamp->tot= 1; 03716 strand_shade_segment(&R, cache, &sseg, ssamp, row->v, row->u, addpassflag); 03717 ssamp->shi[0].mask= row->mask; 03718 } 03719 03720 static void unref_strand_samples(StrandShadeCache *cache, ZTranspRow *row, int totface) 03721 { 03722 StrandVert *svert; 03723 ObjectInstanceRen *obi; 03724 ObjectRen *obr; 03725 StrandRen *strand; 03726 03727 /* remove references to samples that are not being rendered, but we still 03728 * need to remove them so that the reference count of strand vertex shade 03729 * samples correctly drops to zero */ 03730 while(totface > 0) { 03731 totface--; 03732 03733 if(row[totface].segment != -1) { 03734 obi= R.objectinstance + row[totface].obi; 03735 obr= obi->obr; 03736 strand= RE_findOrAddStrand(obr, row[totface].p-1); 03737 svert= strand->vert + row[totface].segment; 03738 03739 strand_shade_unref(cache, svert); 03740 strand_shade_unref(cache, svert+1); 03741 } 03742 } 03743 } 03744 03745 static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int obi, int facenr, int curmask) 03746 { 03747 ShadeInput *shi= ssamp->shi; 03748 float xs, ys; 03749 03750 ssamp->tot= 0; 03751 03752 shade_input_set_triangle(shi, obi, facenr, 1); 03753 03754 /* officially should always be true... we have no sky info */ 03755 if(shi->vlr) { 03756 03757 /* full osa is only set for OSA renders */ 03758 if(shi->vlr->flag & R_FULL_OSA) { 03759 short shi_inc= 0, samp; 03760 03761 for(samp=0; samp<R.osa; samp++) { 03762 if(curmask & (1<<samp)) { 03763 xs= (float)x + R.jit[samp][0] + 0.5f; /* zbuffer has this inverse corrected, ensures xs,ys are inside pixel */ 03764 ys= (float)y + R.jit[samp][1] + 0.5f; 03765 03766 if(shi_inc) { 03767 shade_input_copy_triangle(shi+1, shi); 03768 shi++; 03769 } 03770 shi->mask= (1<<samp); 03771 shi->samplenr= R.shadowsamplenr[shi->thread]++; 03772 shade_input_set_viewco(shi, x, y, xs, ys, (float)z); 03773 shade_input_set_uv(shi); 03774 if(shi_inc==0) 03775 shade_input_set_normals(shi); 03776 else /* XXX shi->flippednor messes up otherwise */ 03777 shade_input_set_vertex_normals(shi); 03778 03779 shi_inc= 1; 03780 } 03781 } 03782 } 03783 else { 03784 if(R.osa) { 03785 short b= R.samples->centmask[curmask]; 03786 xs= (float)x + R.samples->centLut[b & 15] + 0.5f; 03787 ys= (float)y + R.samples->centLut[b>>4] + 0.5f; 03788 } 03789 else { 03790 xs= (float)x + 0.5f; 03791 ys= (float)y + 0.5f; 03792 } 03793 shi->mask= curmask; 03794 shi->samplenr= R.shadowsamplenr[shi->thread]++; 03795 shade_input_set_viewco(shi, x, y, xs, ys, (float)z); 03796 shade_input_set_uv(shi); 03797 shade_input_set_normals(shi); 03798 } 03799 03800 /* total sample amount, shi->sample is static set in initialize */ 03801 ssamp->tot= shi->sample+1; 03802 } 03803 } 03804 03805 static int shade_tra_samples(ShadeSample *ssamp, StrandShadeCache *cache, int x, int y, ZTranspRow *row, int addpassflag) 03806 { 03807 if(row->segment != -1) { 03808 shade_strand_samples(cache, ssamp, x, y, row, addpassflag); 03809 return 1; 03810 } 03811 03812 shade_tra_samples_fill(ssamp, x, y, row->z, row->obi, row->p, row->mask); 03813 03814 if(ssamp->tot) { 03815 ShadeInput *shi= ssamp->shi; 03816 ShadeResult *shr= ssamp->shr; 03817 int samp; 03818 03819 /* if AO? */ 03820 shade_samples_do_AO(ssamp); 03821 03822 /* if shade (all shadepinputs have same passflag) */ 03823 if(shi->passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB|SCE_PASS_INDEXMA)) { 03824 for(samp=0; samp<ssamp->tot; samp++, shi++, shr++) { 03825 shade_input_set_shade_texco(shi); 03826 shade_input_do_shade(shi, shr); 03827 03828 /* include lamphalos for ztra, since halo layer was added already */ 03829 if(R.flag & R_LAMPHALO) 03830 if(shi->layflag & SCE_LAY_HALO) 03831 renderspothalo(shi, shr->combined, shr->combined[3]); 03832 } 03833 } 03834 else if(shi->passflag & SCE_PASS_Z) { 03835 for(samp=0; samp<ssamp->tot; samp++, shi++, shr++) 03836 shr->z= -shi->co[2]; 03837 } 03838 03839 return 1; 03840 } 03841 return 0; 03842 } 03843 03844 static void addvecmul(float *v1, float *v2, float fac) 03845 { 03846 v1[0]= v1[0]+fac*v2[0]; 03847 v1[1]= v1[1]+fac*v2[1]; 03848 v1[2]= v1[2]+fac*v2[2]; 03849 } 03850 03851 static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag) 03852 { 03853 int a, sample, osa = (R.osa? R.osa: 1), retval = osa; 03854 03855 for(a=0; a < osa; a++, samp_shr++) { 03856 ShadeInput *shi= ssamp->shi; 03857 ShadeResult *shr= ssamp->shr; 03858 03859 for(sample=0; sample<ssamp->tot; sample++, shi++, shr++) { 03860 03861 if(shi->mask & (1<<a)) { 03862 float fac= (1.0f - samp_shr->combined[3])*shr->combined[3]; 03863 03864 addAlphaUnderFloat(samp_shr->combined, shr->combined); 03865 03866 samp_shr->z= MIN2(samp_shr->z, shr->z); 03867 03868 if(addpassflag & SCE_PASS_VECTOR) { 03869 QUATCOPY(samp_shr->winspeed, shr->winspeed); 03870 } 03871 /* optim... */ 03872 if(addpassflag & ~(SCE_PASS_VECTOR)) { 03873 03874 if(addpassflag & SCE_PASS_RGBA) 03875 addAlphaUnderFloat(samp_shr->col, shr->col); 03876 03877 if(addpassflag & SCE_PASS_NORMAL) 03878 addvecmul(samp_shr->nor, shr->nor, fac); 03879 03880 if(addpassflag & SCE_PASS_EMIT) 03881 addvecmul(samp_shr->emit, shr->emit, fac); 03882 03883 if(addpassflag & SCE_PASS_DIFFUSE) 03884 addvecmul(samp_shr->diff, shr->diff, fac); 03885 03886 if(addpassflag & SCE_PASS_SPEC) 03887 addvecmul(samp_shr->spec, shr->spec, fac); 03888 03889 if(addpassflag & SCE_PASS_SHADOW) 03890 addvecmul(samp_shr->shad, shr->shad, fac); 03891 03892 if(addpassflag & SCE_PASS_AO) 03893 addvecmul(samp_shr->ao, shr->ao, fac); 03894 03895 if(addpassflag & SCE_PASS_ENVIRONMENT) 03896 addvecmul(samp_shr->env, shr->env, fac); 03897 03898 if(addpassflag & SCE_PASS_INDIRECT) 03899 addvecmul(samp_shr->indirect, shr->indirect, fac); 03900 03901 if(addpassflag & SCE_PASS_REFLECT) 03902 addvecmul(samp_shr->refl, shr->refl, fac); 03903 03904 if(addpassflag & SCE_PASS_REFRACT) 03905 addvecmul(samp_shr->refr, shr->refr, fac); 03906 03907 if(addpassflag & SCE_PASS_MIST) 03908 samp_shr->mist= samp_shr->mist+fac*shr->mist; 03909 03910 } 03911 } 03912 } 03913 03914 if(samp_shr->combined[3]>0.999f) retval--; 03915 } 03916 return retval; 03917 } 03918 03919 static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf) 03920 { 03921 /* speed vector exception... if solid render was done, sky pixels are set to zero already */ 03922 /* for all pixels with alpha zero, we re-initialize speed again then */ 03923 float *fp, *col; 03924 int a; 03925 03926 fp= RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR); 03927 if(fp==NULL) return; 03928 col= rectf+3; 03929 03930 for(a= 4*pa->rectx*pa->recty -4; a>=0; a-=4) { 03931 if(col[a]==0.0f) { 03932 fp[a]= PASS_VECTOR_MAX; 03933 fp[a+1]= PASS_VECTOR_MAX; 03934 fp[a+2]= PASS_VECTOR_MAX; 03935 fp[a+3]= PASS_VECTOR_MAX; 03936 } 03937 } 03938 } 03939 03940 #define MAX_ZROW 2000 03941 03942 /* main render call to do the z-transparent layer */ 03943 /* returns a mask, only if a) transp rendered and b) solid was rendered */ 03944 unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass, ListBase *UNUSED(psmlist)) 03945 { 03946 RenderResult *rr= pa->result; 03947 ShadeSample ssamp; 03948 APixstr *APixbuf; /* Zbuffer: linked list of face samples */ 03949 APixstrand *APixbufstrand = NULL; 03950 APixstr *ap, *aprect, *apn; 03951 APixstrand *apstrand, *aprectstrand, *apnstrand; 03952 ListBase apsmbase={NULL, NULL}; 03953 ShadeResult samp_shr[16]; /* MAX_OSA */ 03954 ZTranspRow zrow[MAX_ZROW]; 03955 StrandShadeCache *sscache= NULL; 03956 RenderLayer *rlpp[RE_MAX_OSA]; 03957 float sampalpha, alpha, *passrect= pass; 03958 intptr_t *rdrect; 03959 int x, y, crop=0, a, b, totface, totfullsample, totsample, doztra; 03960 int addpassflag, offs= 0, od, osa = (R.osa? R.osa: 1); 03961 unsigned short *ztramask= NULL, filled; 03962 03963 /* looks nicer for calling code */ 03964 if(R.test_break(R.tbh)) 03965 return NULL; 03966 03967 if(R.osa>16) { /* MAX_OSA */ 03968 printf("zbuffer_transp_shade: osa too large\n"); 03969 G.afbreek= 1; 03970 return NULL; 03971 } 03972 03973 APixbuf= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstr), "APixbuf"); 03974 if(R.totstrand && (rl->layflag & SCE_LAY_STRAND)) { 03975 APixbufstrand= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstrand), "APixbufstrand"); 03976 sscache= strand_shade_cache_create(); 03977 } 03978 03979 /* general shader info, passes */ 03980 shade_sample_initialize(&ssamp, pa, rl); 03981 addpassflag= rl->passflag & ~(SCE_PASS_COMBINED); 03982 03983 if(R.osa) 03984 sampalpha= 1.0f/(float)R.osa; 03985 else 03986 sampalpha= 1.0f; 03987 03988 /* fill the Apixbuf */ 03989 doztra= zbuffer_abuf_render(pa, APixbuf, APixbufstrand, &apsmbase, rl, sscache); 03990 03991 if(doztra == 0) { 03992 /* nothing filled in */ 03993 MEM_freeN(APixbuf); 03994 if(APixbufstrand) 03995 MEM_freeN(APixbufstrand); 03996 if(sscache) 03997 strand_shade_cache_free(sscache); 03998 freepsA(&apsmbase); 03999 return NULL; 04000 } 04001 04002 aprect= APixbuf; 04003 aprectstrand= APixbufstrand; 04004 rdrect= pa->rectdaps; 04005 04006 /* needed for correct zbuf/index pass */ 04007 totfullsample= get_sample_layers(pa, rl, rlpp); 04008 04009 /* irregular shadowb buffer creation */ 04010 if(R.r.mode & R_SHADOW) 04011 ISB_create(pa, APixbuf); 04012 04013 /* masks, to have correct alpha combine */ 04014 if(R.osa && (rl->layflag & SCE_LAY_SOLID) && pa->fullresult.first==NULL) 04015 ztramask= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "ztramask"); 04016 04017 /* zero alpha pixels get speed vector max again */ 04018 if(addpassflag & SCE_PASS_VECTOR) 04019 if(rl->layflag & SCE_LAY_SOLID) 04020 reset_sky_speedvectors(pa, rl, rl->acolrect?rl->acolrect:rl->rectf); /* if acolrect is set we use it */ 04021 04022 /* filtered render, for now we assume only 1 filter size */ 04023 if(pa->crop) { 04024 crop= 1; 04025 offs= pa->rectx + 1; 04026 passrect+= 4*offs; 04027 aprect+= offs; 04028 aprectstrand+= offs; 04029 } 04030 04031 /* init scanline updates */ 04032 rr->renrect.ymin= 0; 04033 rr->renrect.ymax= -pa->crop; 04034 rr->renlay= rl; 04035 04036 /* render the tile */ 04037 for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) { 04038 pass= passrect; 04039 ap= aprect; 04040 apstrand= aprectstrand; 04041 od= offs; 04042 04043 if(R.test_break(R.tbh)) 04044 break; 04045 04046 for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, ap++, apstrand++, pass+=4, od++) { 04047 04048 if(ap->p[0]==0 && (!APixbufstrand || apstrand->p[0]==0)) { 04049 if(addpassflag & SCE_PASS_VECTOR) 04050 add_transp_speed(rl, od, NULL, 0.0f, rdrect); 04051 } 04052 else { 04053 /* sort in z */ 04054 totface= 0; 04055 apn= ap; 04056 while(apn) { 04057 for(a=0; a<4; a++) { 04058 if(apn->p[a]) { 04059 zrow[totface].obi= apn->obi[a]; 04060 zrow[totface].z= apn->z[a]; 04061 zrow[totface].p= apn->p[a]; 04062 zrow[totface].mask= apn->mask[a]; 04063 zrow[totface].segment= -1; 04064 totface++; 04065 if(totface>=MAX_ZROW) totface= MAX_ZROW-1; 04066 } 04067 else break; 04068 } 04069 apn= apn->next; 04070 } 04071 04072 apnstrand= (APixbufstrand)? apstrand: NULL; 04073 while(apnstrand) { 04074 for(a=0; a<4; a++) { 04075 if(apnstrand->p[a]) { 04076 zrow[totface].obi= apnstrand->obi[a]; 04077 zrow[totface].z= apnstrand->z[a]; 04078 zrow[totface].p= apnstrand->p[a]; 04079 zrow[totface].mask= apnstrand->mask[a]; 04080 zrow[totface].segment= apnstrand->seg[a]; 04081 04082 if(R.osa) { 04083 totsample= 0; 04084 for(b=0; b<R.osa; b++) 04085 if(zrow[totface].mask & (1<<b)) 04086 totsample++; 04087 } 04088 else 04089 totsample= 1; 04090 04091 zrow[totface].u= apnstrand->u[a]/totsample; 04092 zrow[totface].v= apnstrand->v[a]/totsample; 04093 totface++; 04094 if(totface>=MAX_ZROW) totface= MAX_ZROW-1; 04095 } 04096 } 04097 apnstrand= apnstrand->next; 04098 } 04099 04100 if(totface==2) { 04101 if(zrow[0].z < zrow[1].z) { 04102 SWAP(ZTranspRow, zrow[0], zrow[1]); 04103 } 04104 04105 } 04106 else if(totface>2) { 04107 qsort(zrow, totface, sizeof(ZTranspRow), vergzvlak); 04108 } 04109 04110 /* front face does index pass for transparent, no AA or filters, but yes FSA */ 04111 if(addpassflag & SCE_PASS_INDEXOB) { 04112 ObjectRen *obr= R.objectinstance[zrow[totface-1].obi].obr; 04113 if(obr->ob) { 04114 for(a= 0; a<totfullsample; a++) 04115 add_transp_obindex(rlpp[a], od, obr->ob); 04116 } 04117 } 04118 if(addpassflag & SCE_PASS_INDEXMA) { 04119 ObjectRen *obr= R.objectinstance[zrow[totface-1].obi].obr; 04120 if(obr->ob) { 04121 for(a= 0; a<totfullsample; a++) 04122 add_transp_obindex(rlpp[a], od, obr->ob); 04123 } 04124 } 04125 04126 /* for each mask-sample we alpha-under colors. then in end it's added using filter */ 04127 memset(samp_shr, 0, sizeof(ShadeResult)*osa); 04128 for(a=0; a<osa; a++) { 04129 samp_shr[a].z= 10e10f; 04130 if(addpassflag & SCE_PASS_VECTOR) { 04131 samp_shr[a].winspeed[0]= PASS_VECTOR_MAX; 04132 samp_shr[a].winspeed[1]= PASS_VECTOR_MAX; 04133 samp_shr[a].winspeed[2]= PASS_VECTOR_MAX; 04134 samp_shr[a].winspeed[3]= PASS_VECTOR_MAX; 04135 } 04136 } 04137 04138 if(R.osa==0) { 04139 while(totface>0) { 04140 totface--; 04141 04142 if(shade_tra_samples(&ssamp, sscache, x, y, &zrow[totface], addpassflag)) { 04143 filled= addtosamp_shr(samp_shr, &ssamp, addpassflag); 04144 addAlphaUnderFloat(pass, ssamp.shr[0].combined); 04145 04146 if(filled == 0) { 04147 if(sscache) 04148 unref_strand_samples(sscache, zrow, totface); 04149 break; 04150 } 04151 } 04152 } 04153 04154 alpha= samp_shr->combined[3]; 04155 if(alpha!=0.0f) { 04156 add_transp_passes(rl, od, samp_shr, alpha); 04157 if(addpassflag & SCE_PASS_VECTOR) 04158 add_transp_speed(rl, od, samp_shr->winspeed, alpha, rdrect); 04159 } 04160 } 04161 else { 04162 short *sp= (short *)(ztramask+od); 04163 04164 while(totface>0) { 04165 totface--; 04166 04167 if(shade_tra_samples(&ssamp, sscache, x, y, &zrow[totface], addpassflag)) { 04168 filled= addtosamp_shr(samp_shr, &ssamp, addpassflag); 04169 04170 if(ztramask) 04171 *sp |= zrow[totface].mask; 04172 if(filled==0) { 04173 if(sscache) 04174 unref_strand_samples(sscache, zrow, totface); 04175 break; 04176 } 04177 } 04178 } 04179 04180 /* multisample buffers or filtered mask filling? */ 04181 if(pa->fullresult.first) { 04182 for(a=0; a<R.osa; a++) { 04183 alpha= samp_shr[a].combined[3]; 04184 if(alpha!=0.0f) { 04185 RenderLayer *rl= ssamp.rlpp[a]; 04186 04187 addAlphaOverFloat(rl->rectf + 4*od, samp_shr[a].combined); 04188 04189 add_transp_passes(rl, od, &samp_shr[a], alpha); 04190 if(addpassflag & SCE_PASS_VECTOR) 04191 add_transp_speed(rl, od, samp_shr[a].winspeed, alpha, rdrect); 04192 } 04193 } 04194 } 04195 else { 04196 alpha= 0.0f; 04197 04198 /* note; cannot use pass[3] for alpha due to filtermask */ 04199 for(a=0; a<R.osa; a++) { 04200 add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx); 04201 alpha+= samp_shr[a].combined[3]; 04202 } 04203 04204 if(addpassflag) { 04205 alpha*= sampalpha; 04206 04207 /* merge all in one, and then add */ 04208 merge_transp_passes(rl, samp_shr); 04209 add_transp_passes(rl, od, samp_shr, alpha); 04210 04211 if(addpassflag & SCE_PASS_VECTOR) 04212 add_transp_speed(rl, od, samp_shr[0].winspeed, alpha, rdrect); 04213 } 04214 } 04215 } 04216 } 04217 } 04218 04219 aprect+= pa->rectx; 04220 aprectstrand+= pa->rectx; 04221 passrect+= 4*pa->rectx; 04222 offs+= pa->rectx; 04223 } 04224 04225 /* disable scanline updating */ 04226 rr->renlay= NULL; 04227 04228 MEM_freeN(APixbuf); 04229 if(APixbufstrand) 04230 MEM_freeN(APixbufstrand); 04231 if(sscache) 04232 strand_shade_cache_free(sscache); 04233 freepsA(&apsmbase); 04234 04235 if(R.r.mode & R_SHADOW) 04236 ISB_free(pa); 04237 04238 return ztramask; 04239 } 04240 04241 04242 /* end of zbuf.c */ 04243 04244 04245 04246