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