00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "std3d.h"
00028
00029
00030 #include "3d/patch.h"
00031 #include "3d/tessellation.h"
00032 #include "3d/bezier_patch.h"
00033 #include "3d/zone.h"
00034 #include "3d/landscape.h"
00035 #include "nel/misc/vector.h"
00036 #include "nel/misc/common.h"
00037 #include "3d/patchuv_locator.h"
00038 #include "3d/vegetable_manager.h"
00039 #include "3d/fast_floor.h"
00040 #include "3d/light_influence_interpolator.h"
00041 #include "3d/patchdlm_context.h"
00042 using namespace std;
00043 using namespace NLMISC;
00044
00045
00046 namespace NL3D
00047 {
00048
00049
00050
00051
00052
00053 static const uint NL3DDecompressLumelFactor0Case0[8]=
00054 {
00055 7, 0, 6, 5, 4, 3, 2, 1
00056 };
00057 static const uint NL3DDecompressLumelFactor1Case0[8]=
00058 {
00059 0, 7, 1, 2, 3, 4, 5, 6
00060 };
00061 static const uint NL3DDecompressLumelFactor0Case1[6]=
00062 {
00063 5, 0, 4, 3, 2, 1,
00064 };
00065 static const uint NL3DDecompressLumelFactor1Case1[6]=
00066 {
00067 0, 5, 1, 2, 3, 4,
00068 };
00069
00070 void CPatch::unpackLumelBlock (uint8 *dest, const uint8 *src)
00071 {
00072
00073 uint alpha0=src[0];
00074 uint alpha1=src[1];
00075
00076
00077
00078 uint8 values[8];
00079
00080 if (alpha0>alpha1)
00081 {
00082
00083 values[0]= alpha0;
00084 values[1]= alpha1;
00085 values[2]= (uint8) ( (alpha0*219 + alpha1*37 ) >>8 ) ;
00086 values[3]= (uint8) ( (alpha0*183 + alpha1*73 ) >>8 ) ;
00087 values[4]= (uint8) ( (alpha0*146 + alpha1*110) >>8 ) ;
00088 values[5]= (uint8) ( (alpha0*110 + alpha1*146) >>8 ) ;
00089 values[6]= (uint8) ( (alpha0*73 + alpha1*183) >>8 ) ;
00090 values[7]= (uint8) ( (alpha0*37 + alpha1*219) >>8 ) ;
00091 }
00092
00093 else
00094 {
00095
00096 values[0]= alpha0;
00097 values[1]= alpha1;
00098 values[2]= (uint8) ( (alpha0*205 + alpha1*51 ) >>8 ) ;
00099 values[3]= (uint8) ( (alpha0*154 + alpha1*102) >>8 ) ;
00100 values[4]= (uint8) ( (alpha0*102 + alpha1*154) >>8 ) ;
00101 values[5]= (uint8) ( (alpha0*51 + alpha1*205) >>8 ) ;
00102 values[6]= 0;
00103 values[7]= 255;
00104 }
00105
00106
00107
00108
00109 uint block8Pixs[2];
00110
00111 block8Pixs[0]= ((uint)src[2]<<16) + ((uint)src[3]<<8) + ((uint)src[4]) ;
00112 block8Pixs[1]= ((uint)src[5]<<16) + ((uint)src[6]<<8) + ((uint)src[7]) ;
00113
00114
00115 for(uint i=0; i<2; i++)
00116 {
00117 uint blockPix= block8Pixs[i];
00118
00119 for(uint n=8; n>0; n--, dest++)
00120 {
00121 uint code= (blockPix>>21)&0x7;
00122
00123
00124 *dest= values[code];
00125
00126
00127 blockPix<<= 3;
00128 }
00129 }
00130
00131 }
00132
00133
00134 inline uint8 getUnpackLumelBlock (const uint8 *src, uint pixel)
00135 {
00136
00137 pixel*=3;
00138 uint offset=(pixel>>3)+2;
00139 uint bits=pixel&7;
00140
00141
00142 uint code;
00143
00144
00145 if (bits<=5)
00146 code=(src[offset]>>(5-bits))&0x7;
00147 else
00148 code= ( (src[offset]<<(bits-5)) | (src[offset+1]>>(13-bits)) )&0x7;
00149
00150
00151 if (src[0]>src[1])
00152 {
00153
00154 return (uint8)((NL3DDecompressLumelFactor0Case0[code]*src[0]+NL3DDecompressLumelFactor1Case0[code]*src[1])/7);
00155 }
00156
00157 else
00158 {
00159
00160 if (code<6)
00161 return (uint8)((NL3DDecompressLumelFactor0Case1[code]*src[0]+NL3DDecompressLumelFactor1Case1[code]*src[1])/5);
00162 else if (code==6)
00163 return 0;
00164 else
00165 return 255;
00166 }
00167 }
00168
00169
00170 void CPatch::unpackShadowMap (uint8 *pLumelDest)
00171 {
00172
00173 uint8 *compressedData=&CompressedLumels[0];
00174
00175
00176 uint lumelCount=OrderS*NL_LUMEL_BY_TILE;
00177
00178
00179 nlassert ((lumelCount&0x3)==0);
00180 uint numLumelBlock=lumelCount>>2;
00181
00182
00183 uint lineCount=OrderT*NL_LUMEL_BY_TILE;
00184
00185
00186 nlassert ((lineCount&0x3)==0);
00187 uint numLineBlock=lineCount>>2;
00188
00189
00190 uint lumelDestBlockSize=4;
00191
00192
00193 uint lumelDestLineBlockSize=lumelCount*lumelDestBlockSize;
00194
00195
00196 for (uint lineBlock=0; lineBlock<numLineBlock; lineBlock++)
00197 {
00198 uint countVx4=16;
00199
00200
00201 uint8 *blockLine=pLumelDest;
00202
00203
00204 for (uint lumelBlock=0; lumelBlock<numLumelBlock; lumelBlock++)
00205 {
00206
00207 uint countU=4;
00208
00209
00210 uint8 *blockDest=blockLine;
00211
00212
00213 uint8 block[4*4];
00214
00215
00216 unpackLumelBlock (block, compressedData);
00217
00218
00219 for (uint v=0; v<countVx4; v+=4)
00220 {
00221 for (uint u=0; u<countU; u++)
00222 {
00223
00224 blockDest[u]=block[v+u];
00225 }
00226
00227
00228 blockDest+=lumelCount;
00229 }
00230
00231
00232 compressedData+=NL_BLOCK_LUMEL_COMPRESSED_SIZE;
00233
00234
00235 blockLine+=lumelDestBlockSize;
00236 }
00237
00238
00239 pLumelDest+=lumelDestLineBlockSize;
00240 }
00241 }
00242
00243
00244 uint CPatch::evalLumelBlock (const uint8 *original, const uint8 *unCompressed, uint width, uint height)
00245 {
00246
00247 uint sum=0;
00248
00249
00250 for (uint v=0; v<height; v++)
00251 for (uint u=0; u<width; u++)
00252 {
00253 sum += abs((sint)original[v*4+u]-(sint)unCompressed[v*4+u]);
00254 }
00255
00256
00257 return sum;
00258 }
00259
00260
00261 void CPatch::packLumelBlock (uint8 *dest, const uint8 *source, uint8 alpha0, uint8 alpha1)
00262 {
00263
00264 uint8 value[8];
00265
00266
00267 uint i;
00268 for (i=0; i<8; i++)
00269 {
00270
00271 if (alpha0>alpha1)
00272
00273 value[i]=(NL3DDecompressLumelFactor0Case0[i]*alpha0+NL3DDecompressLumelFactor1Case0[i]*alpha1)/7;
00274 else
00275 {
00276 if (i<6)
00277 value[i]=(NL3DDecompressLumelFactor0Case1[i]*alpha0+NL3DDecompressLumelFactor1Case1[i]*alpha1)/5;
00278 else if (i==6)
00279 value[i]=0;
00280 else
00281 value[i]=255;
00282 }
00283 }
00284
00285
00286 dest[0]=alpha0;
00287 dest[1]=alpha1;
00288
00289
00290 for (i=0; i<6; i++)
00291 {
00292
00293 dest[2+i]=0;
00294 }
00295
00296
00297 uint codeOffset=2;
00298 sint codeShift=5;
00299 for (i=0; i<16; i++)
00300 {
00301
00302 uint bestDist=10000;
00303 uint8 bestCode=0;
00304
00305
00306 for (uint code=0; code<8; code++)
00307 {
00308
00309 uint dist=abs ((sint)(source[i])-(sint)(value[code]));
00310
00311
00312 if (dist<bestDist)
00313 {
00314
00315 bestDist=dist;
00316 bestCode=code;
00317 }
00318
00319
00320 if (dist==0)
00321 break;
00322 }
00323
00324
00325 if (codeShift>=0)
00326 dest[codeOffset]|=bestCode<<codeShift;
00327 else
00328 {
00329 dest[codeOffset]|=bestCode>>(-codeShift);
00330 dest[codeOffset+1]|=bestCode<<(8+codeShift);
00331 }
00332
00333
00334
00335 codeShift-=3;
00336 if (codeShift<=-3)
00337 {
00338 codeOffset++;
00339 codeShift+=8;
00340 }
00341 }
00342 }
00343
00344
00345 void CPatch::getTileTileColors(uint ts, uint tt, CRGBA corners[4])
00346 {
00347 for(sint i=0;i<4;i++)
00348 {
00349 CTileColor &tcol= TileColors[ (tt+(i>>1))*(OrderS+1) + (ts+(i&1)) ];
00350 CRGBA &col= corners[i];
00351 col.set565 (tcol.Color565);
00352 }
00353 }
00354
00355
00356
00357
00358 inline void bilinearColor(CRGBA corners[4], uint x, uint y, uint &R, uint &G, uint &B)
00359 {
00360
00361
00362
00363 nlassert(NL_LUMEL_BY_TILE==4);
00364
00365
00366 x= (x<<1)+1;
00367 y= (y<<1)+1;
00368 uint x1= 8-x;
00369 uint y1= 8-y;
00370
00371
00372 uint xy= x*y;
00373 uint x1y= x1*y;
00374 uint xy1= x*y1;
00375 uint x1y1= x1*y1;
00376
00377
00378
00379 R = corners[0].R * x1y1;
00380 G = corners[0].G * x1y1;
00381 B = corners[0].B * x1y1;
00382
00383 R+= corners[1].R * xy1;
00384 G+= corners[1].G * xy1;
00385 B+= corners[1].B * xy1;
00386
00387 R+= corners[2].R * x1y;
00388 G+= corners[2].G * x1y;
00389 B+= corners[2].B * x1y;
00390
00391 R+= corners[3].R * xy;
00392 G+= corners[3].G * xy;
00393 B+= corners[3].B * xy;
00394
00395 }
00396
00397
00398
00399
00400 inline void bilinearColorAndModulate(CRGBA corners[4], uint x, uint y, CRGBA &res)
00401 {
00402 uint R,G,B;
00403 bilinearColor(corners, x, y, R, G, B);
00404
00405
00406 R*= res.R;
00407 G*= res.G;
00408 B*= res.B;
00409
00410
00411 res.R= R >> 14;
00412 res.G= G >> 14;
00413 res.B= B >> 14;
00414 }
00415
00416
00417
00418
00419 inline void bilinearColorAndAdd(CRGBA corners[4], uint x, uint y, CRGBA &res)
00420 {
00421 uint R,G,B;
00422 bilinearColor(corners, x, y, R, G, B);
00423
00424
00425 R= (R>>6) + res.R;
00426 G= (G>>6) + res.G;
00427 B= (B>>6) + res.B;
00428 R= min(R, 255U);
00429 G= min(G, 255U);
00430 B= min(B, 255U);
00431
00432
00433 res.R= R;
00434 res.G= G;
00435 res.B= B;
00436 }
00437
00438
00439
00440
00441 void CPatch::modulateTileLightmapWithTileColors(uint ts, uint tt, CRGBA *dest, uint stride)
00442 {
00443
00444 CRGBA corners[4];
00445 getTileTileColors(ts, tt, corners);
00446
00447
00448 uint x, y;
00449 for(y=0; y<NL_LUMEL_BY_TILE; y++)
00450 {
00451 for(x=0; x<NL_LUMEL_BY_TILE; x++)
00452 {
00453
00454 bilinearColorAndModulate(corners, x, y, dest[y*stride + x]);
00455 }
00456 }
00457 }
00458
00459
00460
00461 void CPatch::modulateTileLightmapEdgeWithTileColors(uint ts, uint tt, uint edge, CRGBA *dest, uint stride, bool inverse)
00462 {
00463
00464 CRGBA corners[4];
00465 getTileTileColors(ts, tt, corners);
00466
00467
00468 uint x=0,y=0;
00469 switch(edge)
00470 {
00471 case 0: x= 0; break;
00472 case 1: y= NL_LUMEL_BY_TILE-1; break;
00473 case 2: x= NL_LUMEL_BY_TILE-1; break;
00474 case 3: y= 0; break;
00475 };
00476
00477
00478 uint i;
00479 for(i=0; i<NL_LUMEL_BY_TILE; i++)
00480 {
00481
00482 if( (edge&1)==0 ) y= i;
00483
00484 else x= i;
00485
00486
00487 uint where;
00488 if(inverse) where= (NL_LUMEL_BY_TILE-1)-i;
00489 else where= i;
00490
00491 bilinearColorAndModulate(corners, x, y, dest[where*stride]);
00492 }
00493 }
00494
00495
00496
00497 void CPatch::modulateTileLightmapPixelWithTileColors(uint ts, uint tt, uint s, uint t, CRGBA *dest)
00498 {
00499
00500 CRGBA corners[4];
00501 getTileTileColors(ts, tt, corners);
00502
00503
00504 bilinearColorAndModulate(corners, s, t, *dest);
00505 }
00506
00507
00508
00509
00510 void CPatch::computeTileLightmapAutomatic(uint ts, uint tt, CRGBA *dest, uint stride)
00511 {
00512 uint x, y;
00513 for(y=0; y<NL_LUMEL_BY_TILE; y++)
00514 {
00515 for(x=0; x<NL_LUMEL_BY_TILE; x++)
00516 {
00517
00518 computeTileLightmapPixelAutomatic(ts, tt, x, y, dest+ y*stride + x);
00519 }
00520 }
00521 }
00522
00523
00524 void CPatch::computeTileLightmapEdgeAutomatic(uint ts, uint tt, uint edge, CRGBA *dest, uint stride, bool inverse)
00525 {
00526
00527 uint x=0,y=0;
00528 switch(edge)
00529 {
00530 case 0: x= 0; break;
00531 case 1: y= NL_LUMEL_BY_TILE-1; break;
00532 case 2: x= NL_LUMEL_BY_TILE-1; break;
00533 case 3: y= 0; break;
00534 };
00535
00536 uint i;
00537 for(i=0; i<NL_LUMEL_BY_TILE; i++)
00538 {
00539
00540 if( (edge&1)==0 ) y= i;
00541
00542 else x= i;
00543
00544
00545 uint where;
00546 if(inverse) where= (NL_LUMEL_BY_TILE-1)-i;
00547 else where= i;
00548
00549 computeTileLightmapPixelAutomatic(ts, tt, x, y, dest+ where*stride);
00550 }
00551 }
00552
00553
00554 void CPatch::computeTileLightmapPixelAutomatic(uint ts, uint tt, uint s, uint t, CRGBA *dest)
00555 {
00556 float u,v;
00557 static const float lumelSize= 1.f/NL_LUMEL_BY_TILE;
00558
00559
00560 CVector p0, p1 ,p2;
00561
00562 u= (ts + s*lumelSize )/OrderS;
00563 v= (tt + t*lumelSize )/OrderT;
00564 p0= computeVertex(u, v);
00565
00566 u= (ts + s*lumelSize )/OrderS;
00567 v= (tt + (t+1)*lumelSize )/OrderT;
00568 p1= computeVertex(u, v);
00569
00570 u= (ts + (s+1)*lumelSize )/OrderS;
00571 v= (tt + (t+0.5f)*lumelSize )/OrderT;
00572 p2= computeVertex(u, v);
00573
00574
00575 CVector normal;
00576 normal= (p1-p0)^(p2-p0);
00577 normal.normalize();
00578
00579
00580 float c= -normal*getLandscape()->getAutomaticLightDir();
00581 c= max(c, 0.f);
00582 sint ic;
00583
00584 #ifdef NL_OS_WINDOWS
00585
00586 float fc= c*256;
00587 _asm
00588 {
00589 fld fc
00590 fistp ic
00591 }
00592 #else
00593 ic= (sint)floor(c*256);
00594 #endif
00595 clamp(ic, 0, 255);
00596
00597
00598 *dest= getLandscape()->getStaticLight()[ic];
00599 }
00600
00601
00602
00603 void CPatch::getTileLumelmapPrecomputed(uint ts, uint tt, uint8 *dest, uint stride)
00604 {
00605
00606 uint8 buffer[NL_LUMEL_BY_TILE*NL_LUMEL_BY_TILE];
00607 unpackLumelBlock (buffer, &(CompressedLumels[(ts + (tt*OrderS))*NL_BLOCK_LUMEL_COMPRESSED_SIZE]));
00608
00609
00610 uint x, y;
00611 for(y=0; y<NL_LUMEL_BY_TILE; y++)
00612 {
00613 for(x=0; x<NL_LUMEL_BY_TILE; x++)
00614 {
00615
00616 dest[y*stride + x]= buffer[x+(y<<NL_LUMEL_BY_TILE_SHIFT)];
00617 }
00618 }
00619 }
00620
00621
00622
00623 void CPatch::getTileLumelmapPixelPrecomputed(uint ts, uint tt, uint s, uint t, uint8 &dest) const
00624 {
00625
00626 dest= getUnpackLumelBlock (&(CompressedLumels[(ts + (tt*OrderS))*NL_BLOCK_LUMEL_COMPRESSED_SIZE]), s+(t<<2));
00627 }
00628
00629
00630
00631 void CPatch::computeTileLightmapPrecomputed(uint ts, uint tt, CRGBA *dest, uint stride)
00632 {
00633
00634 const CRGBA* colorTable=getLandscape ()->getStaticLight ();
00635
00636 uint8 buffer[NL_LUMEL_BY_TILE*NL_LUMEL_BY_TILE];
00637 unpackLumelBlock (buffer, &(CompressedLumels[(ts + (tt*OrderS))*NL_BLOCK_LUMEL_COMPRESSED_SIZE]));
00638
00639
00640 uint x, y;
00641 for(y=0; y<NL_LUMEL_BY_TILE; y++)
00642 {
00643 for(x=0; x<NL_LUMEL_BY_TILE; x++)
00644 {
00645
00646 dest[y*stride + x]=colorTable[buffer[x+(y<<NL_LUMEL_BY_TILE_SHIFT)]];
00647 }
00648 }
00649 }
00650
00651
00652
00653 static uint NL3DPixelStartLumel[4]={0, 4*3, 3, 0};
00654 static uint NL3DDeltaLumel[4]={4, 1, 4, 1};
00655
00656
00657 void CPatch::computeTileLightmapEdgePrecomputed(uint ts, uint tt, uint edge, CRGBA *dest, uint stride, bool inverse)
00658 {
00659
00660 const CRGBA* colorTable=getLandscape ()->getStaticLight ();
00661
00662
00663 uint pixel=NL3DPixelStartLumel[edge];
00664 uint delta=NL3DDeltaLumel[edge];
00665
00666
00667 const uint8 *src=&(CompressedLumels[(ts + (tt*OrderS))*NL_BLOCK_LUMEL_COMPRESSED_SIZE]);
00668 uint x;
00669 if (inverse)
00670 {
00671 uint inverseStride=stride*(4-1);
00672 for(x=0; x<4; x++)
00673 {
00674
00675 dest[inverseStride-x*stride]=colorTable[getUnpackLumelBlock (src, pixel)];
00676 pixel+=delta;
00677 }
00678 }
00679 else
00680 {
00681 for(x=0; x<4; x++)
00682 {
00683
00684 dest[x*stride]=colorTable[getUnpackLumelBlock (src, pixel)];
00685 pixel+=delta;
00686 }
00687 }
00688 }
00689
00690
00691 void CPatch::computeTileLightmapPixelPrecomputed(uint ts, uint tt, uint s, uint t, CRGBA *dest)
00692 {
00693
00694 const CRGBA* colorTable=getLandscape ()->getStaticLight ();
00695
00696
00697 *dest=colorTable[getUnpackLumelBlock (&(CompressedLumels[(ts + (tt*OrderS))*NL_BLOCK_LUMEL_COMPRESSED_SIZE]), s+(t<<2))];
00698 }
00699
00700
00701
00702
00703 void CPatch::computeTileLightmap(uint ts, uint tt, CRGBA *dest, uint stride)
00704 {
00705 if(getLandscape()->getAutomaticLighting())
00706 computeTileLightmapAutomatic(ts, tt, dest, stride);
00707 else
00708 {
00709 computeTileLightmapPrecomputed(ts, tt, dest, stride);
00710
00711 addTileLightmapWithTLI(ts, tt, dest, stride);
00712 }
00713
00714
00715 modulateTileLightmapWithTileColors(ts, tt, dest, stride);
00716 }
00717
00718 void CPatch::computeTileLightmapEdge(uint ts, uint tt, uint edge, CRGBA *dest, uint stride, bool inverse)
00719 {
00720 if(getLandscape()->getAutomaticLighting())
00721 computeTileLightmapEdgeAutomatic(ts, tt, edge, dest, stride, inverse);
00722 else
00723 {
00724 computeTileLightmapEdgePrecomputed(ts, tt, edge, dest, stride, inverse);
00725
00726 addTileLightmapEdgeWithTLI(ts, tt, edge, dest, stride, inverse);
00727 }
00728
00729
00730 modulateTileLightmapEdgeWithTileColors(ts, tt, edge, dest, stride, inverse);
00731 }
00732
00733
00734
00735 void CPatch::computeTileLightmapPixel(uint ts, uint tt, uint s, uint t, CRGBA *dest)
00736 {
00737 if(getLandscape()->getAutomaticLighting())
00738 computeTileLightmapPixelAutomatic(ts, tt, s, t, dest);
00739 else
00740 {
00741 computeTileLightmapPixelPrecomputed(ts, tt, s, t, dest);
00742
00743 addTileLightmapPixelWithTLI(ts, tt, s, t, dest);
00744 }
00745
00746
00747 modulateTileLightmapPixelWithTileColors(ts, tt, s, t, dest);
00748 }
00749
00750
00751
00752 void CPatch::computeTileLightmapPixelAroundCorner(const CVector2f &stIn, CRGBA *dest, bool lookAround)
00753 {
00754 bool mustLookOnNeighbor= false;
00755
00756
00757 sint u, v;
00758 u= (sint)floor(stIn.x*NL_LUMEL_BY_TILE);
00759 v= (sint)floor(stIn.y*NL_LUMEL_BY_TILE);
00760
00761
00762 if(lookAround)
00763 {
00764
00765 if( u<0 || u>=OrderS*NL_LUMEL_BY_TILE || v<0 || v>=OrderT*NL_LUMEL_BY_TILE)
00766 mustLookOnNeighbor= true;
00767 }
00768
00769
00770
00771 if(!mustLookOnNeighbor)
00772 {
00773
00774 if( u<0 || u>=OrderS*NL_LUMEL_BY_TILE || v<0 || v>=OrderT*NL_LUMEL_BY_TILE)
00775 return;
00776 else
00777 {
00778
00779 computeTileLightmapPixel(u>>NL_LUMEL_BY_TILE_SHIFT, v>>NL_LUMEL_BY_TILE_SHIFT, u&(NL_LUMEL_BY_TILE-1), v&(NL_LUMEL_BY_TILE-1), dest);
00780 }
00781 }
00782
00783 else
00784 {
00785
00786 uint edge=0;
00787 if(u<0) edge=0;
00788 else if(v>=OrderT*NL_LUMEL_BY_TILE) edge=1;
00789 else if(u>=OrderS*NL_LUMEL_BY_TILE) edge=2;
00790 else if(v<0) edge=3;
00791
00792
00793 CBindInfo bindInfo;
00794 getBindNeighbor(edge, bindInfo);
00795
00796
00797 if(bindInfo.Zone)
00798 {
00799 CVector2f stOut;
00800 CPatch *patchOut;
00801 uint patchId;
00802
00803
00804 CPatchUVLocator uvLocator;
00805 uvLocator.build(this, edge, bindInfo);
00806 patchId= uvLocator.selectPatch(stIn);
00807 uvLocator.locateUV(stIn, patchId, patchOut, stOut);
00808
00809
00810 patchOut->computeTileLightmapPixelAroundCorner(stOut, dest, false);
00811 }
00812 }
00813 }
00814
00815
00816
00817 void CPatch::computeNearBlockLightmap(uint uts, uint utt, CRGBA *lightText)
00818 {
00819 sint ts= uts;
00820 sint tt= utt;
00821
00822
00823 nlassert(NL_TILE_LIGHTMAP_SIZE==10);
00824 CRGBA *dest;
00825 uint edge;
00826 uint corner;
00827
00828
00829
00830
00831 dest= lightText+NL_TILE_LIGHTMAP_SIZE+1;
00832 computeTileLightmap(ts, tt, dest, NL_TILE_LIGHTMAP_SIZE);
00833
00834 dest= lightText + NL_LUMEL_BY_TILE + NL_TILE_LIGHTMAP_SIZE+1 ;
00835 computeTileLightmap(ts+1, tt, dest, NL_TILE_LIGHTMAP_SIZE);
00836
00837 dest= lightText + NL_LUMEL_BY_TILE*NL_TILE_LIGHTMAP_SIZE + NL_TILE_LIGHTMAP_SIZE+1 ;
00838 computeTileLightmap(ts, tt+1, dest, NL_TILE_LIGHTMAP_SIZE);
00839
00840 dest= lightText + NL_LUMEL_BY_TILE*NL_TILE_LIGHTMAP_SIZE + NL_LUMEL_BY_TILE + NL_TILE_LIGHTMAP_SIZE+1 ;
00841 computeTileLightmap(ts+1, tt+1, dest, NL_TILE_LIGHTMAP_SIZE);
00842
00843
00844
00845
00846 bool edgeBorder[4];
00847
00848 edgeBorder[0]= ( ts==0 );
00849 edgeBorder[1]= ( tt == OrderT-2 );
00850 edgeBorder[2]= ( ts == OrderS-2 );
00851 edgeBorder[3]= ( tt==0 );
00852
00853
00854 for(edge=0; edge<4; edge++)
00855 {
00856
00857
00858
00859 uint stride= (edge&1)==0? NL_TILE_LIGHTMAP_SIZE : 1;
00860
00861
00862 sint decalS=0;
00863 sint decalT=0;
00864
00865 switch(edge)
00866 {
00867 case 0: decalS=-1; dest= lightText + 0 + NL_TILE_LIGHTMAP_SIZE; break;
00868 case 1: decalT= 2; dest= lightText + 1 + (NL_TILE_LIGHTMAP_SIZE-1)*NL_TILE_LIGHTMAP_SIZE; break;
00869 case 2: decalS= 2; dest= lightText + (NL_TILE_LIGHTMAP_SIZE-1) + NL_TILE_LIGHTMAP_SIZE; break;
00870 case 3: decalT=-1; dest= lightText + 1; break;
00871 };
00872
00873
00874 CRGBA *dest2;
00875 sint decalS2;
00876 sint decalT2;
00877
00878 if((edge&1)==0)
00879 {
00880
00881 dest2= dest + NL_LUMEL_BY_TILE*NL_TILE_LIGHTMAP_SIZE;
00882 decalS2= decalS;
00883 decalT2= decalT+1;
00884 }
00885 else
00886 {
00887
00888 dest2= dest + NL_LUMEL_BY_TILE;
00889 decalS2= decalS+1;
00890 decalT2= decalT;
00891 }
00892
00893
00894
00895
00896 if(!edgeBorder[edge])
00897 {
00898
00899 computeTileLightmapEdge(ts+decalS, tt+decalT, (edge+2)&3, dest, stride, false);
00900
00901
00902 computeTileLightmapEdge(ts+decalS2, tt+decalT2, (edge+2)&3, dest2, stride, false);
00903
00904 }
00905
00906
00907 else
00908 {
00909 CPatchUVLocator uvLocator;
00910 CBindInfo bindInfo;
00911 bindInfo.Zone= NULL;
00912
00913
00914 if(getSmoothFlag(edge))
00915 {
00916
00917 getBindNeighbor(edge, bindInfo);
00918
00919
00920 if(bindInfo.Zone)
00921 {
00922 uvLocator.build(this, edge, bindInfo);
00923
00924
00925 if(!uvLocator.sameEdgeOrder())
00926 bindInfo.Zone= NULL;
00927 }
00928 }
00929
00930
00931
00932 if(!bindInfo.Zone)
00933 {
00934 CRGBA *src=0;
00935 switch(edge)
00936 {
00937 case 0: src= dest + 1; break;
00938 case 1: src= dest - NL_TILE_LIGHTMAP_SIZE; break;
00939 case 2: src= dest - 1; break;
00940 case 3: src= dest + NL_TILE_LIGHTMAP_SIZE; break;
00941 };
00942
00943
00944 for(uint n=NL_LUMEL_BY_TILE*2; n>0; n--, src+=stride, dest+=stride)
00945 *dest= *src;
00946 }
00947
00948 else
00949 {
00950 CVector2f stIn, stOut;
00951 CPatch *patchOut;
00952 uint patchId;
00953 uint edgeOut;
00954 bool inverse;
00955
00956
00957
00958
00959 stIn.set(ts+decalS + 0.5f, tt+decalT + 0.5f);
00960 patchId= uvLocator.selectPatch(stIn);
00961 uvLocator.locateUV(stIn, patchId, patchOut, stOut);
00962
00963
00964 edgeOut= bindInfo.Edge[patchId];
00965
00966
00967
00968 inverse= (edge>>1)==(edgeOut>>1);
00969
00970 patchOut->computeTileLightmapEdge((sint)floor(stOut.x), (sint)floor(stOut.y), edgeOut, dest, stride, inverse);
00971
00972
00973
00974
00975 stIn.set(ts+decalS2 + 0.5f, tt+decalT2 + 0.5f);
00976 patchId= uvLocator.selectPatch(stIn);
00977 uvLocator.locateUV(stIn, patchId, patchOut, stOut);
00978 edgeOut= bindInfo.Edge[patchId];
00979 inverse= (edge>>1)==(edgeOut>>1);
00980 patchOut->computeTileLightmapEdge((sint)floor(stOut.x), (sint)floor(stOut.y), edgeOut, dest2, stride, inverse);
00981 }
00982
00983 }
00984 }
00985
00986
00987
00988
00989 bool cornerOnPatchEdge[4];
00990 bool cornerOnPatchCorner[4];
00991
00992 cornerOnPatchEdge[0]= edgeBorder[3] != edgeBorder[0];
00993 cornerOnPatchEdge[1]= edgeBorder[0] != edgeBorder[1];
00994 cornerOnPatchEdge[2]= edgeBorder[1] != edgeBorder[2];
00995 cornerOnPatchEdge[3]= edgeBorder[2] != edgeBorder[3];
00996
00997 cornerOnPatchCorner[0]= edgeBorder[3] && edgeBorder[0];
00998 cornerOnPatchCorner[1]= edgeBorder[0] && edgeBorder[1];
00999 cornerOnPatchCorner[2]= edgeBorder[1] && edgeBorder[2];
01000 cornerOnPatchCorner[3]= edgeBorder[2] && edgeBorder[3];
01001
01002
01003 for(corner=0; corner<4; corner++)
01004 {
01005
01006
01007
01008 sint decalS=0;
01009 sint decalT=0;
01010
01011 switch(corner)
01012 {
01013 case 0: decalS=-1; decalT=-1; dest= lightText + 0 + 0; break;
01014 case 1: decalS=-1; decalT= 2; dest= lightText + 0 + (NL_TILE_LIGHTMAP_SIZE-1)*NL_TILE_LIGHTMAP_SIZE; break;
01015 case 2: decalS= 2; decalT= 2; dest= lightText + (NL_TILE_LIGHTMAP_SIZE-1) + (NL_TILE_LIGHTMAP_SIZE-1)*NL_TILE_LIGHTMAP_SIZE; break;
01016 case 3: decalS= 2; decalT=-1; dest= lightText + (NL_TILE_LIGHTMAP_SIZE-1) + 0; break;
01017 };
01018
01019
01020
01021
01022
01023 if(!cornerOnPatchCorner[corner] && !cornerOnPatchEdge[corner])
01024 {
01025
01026 uint subS, subT;
01027 if(decalS==-1) subS= NL_LUMEL_BY_TILE-1;
01028 else subS= 0;
01029 if(decalT==-1) subT= NL_LUMEL_BY_TILE-1;
01030 else subT= 0;
01031
01032
01033 computeTileLightmapPixel(ts+decalS, tt+decalT, subS, subT, dest);
01034 }
01035 else
01036 {
01037
01038 CRGBA *src=0;
01039 switch(corner)
01040 {
01041 case 0: src= dest + 1 + NL_TILE_LIGHTMAP_SIZE; break;
01042 case 1: src= dest + 1 - NL_TILE_LIGHTMAP_SIZE; break;
01043 case 2: src= dest - 1 - NL_TILE_LIGHTMAP_SIZE; break;
01044 case 3: src= dest - 1 + NL_TILE_LIGHTMAP_SIZE; break;
01045 };
01046
01047
01048 *dest= *src;
01049
01050
01051 CBindInfo bindInfo;
01052 CPatchUVLocator uvLocator;
01053 CVector2f stIn, stOut;
01054 CPatch *patchOut;
01055 uint patchId;
01056 float decX, decY;
01057 static const float lumelSize= 1.f/NL_LUMEL_BY_TILE;
01058 static const float semiLumelSize= 0.5f*lumelSize;
01059
01060 if(decalS==-1) decX= - semiLumelSize;
01061 else decX= 2+ semiLumelSize;
01062 if(decalT==-1) decY= - semiLumelSize;
01063 else decY= 2+ semiLumelSize;
01064 stIn.set( ts+decX, tt+decY);
01065
01066
01067
01068 if(cornerOnPatchEdge[corner])
01069 {
01070
01071 if(edgeBorder[corner]) edge= corner;
01072 else edge= (corner+4-1) & 3;
01073
01074
01075 if(getSmoothFlag(edge))
01076 {
01077
01078 getBindNeighbor(edge, bindInfo);
01079
01080
01081 if(bindInfo.Zone)
01082 {
01083
01084 uvLocator.build(this, edge, bindInfo);
01085 patchId= uvLocator.selectPatch(stIn);
01086 uvLocator.locateUV(stIn, patchId, patchOut, stOut);
01087
01088
01089 sint u, v;
01090 u= (sint)floor(stOut.x*NL_LUMEL_BY_TILE);
01091 v= (sint)floor(stOut.y*NL_LUMEL_BY_TILE);
01092 patchOut->computeTileLightmapPixel(u>>NL_LUMEL_BY_TILE_SHIFT, v>>NL_LUMEL_BY_TILE_SHIFT, u&(NL_LUMEL_BY_TILE-1), v&(NL_LUMEL_BY_TILE-1), dest);
01093 }
01094 }
01095
01096 else
01097 {
01098
01099 if(stIn.x<0) stIn.x+= lumelSize;
01100 else if(stIn.x>OrderS) stIn.x-= lumelSize;
01101 else if(stIn.y<0) stIn.y+= lumelSize;
01102 else if(stIn.y>OrderT) stIn.y-= lumelSize;
01103
01104
01105 sint u, v;
01106 u= (sint)floor(stIn.x*NL_LUMEL_BY_TILE);
01107 v= (sint)floor(stIn.y*NL_LUMEL_BY_TILE);
01108 computeTileLightmapPixel(u>>NL_LUMEL_BY_TILE_SHIFT, v>>NL_LUMEL_BY_TILE_SHIFT, u&(NL_LUMEL_BY_TILE-1), v&(NL_LUMEL_BY_TILE-1), dest);
01109 }
01110 }
01111
01112 else
01113 {
01114
01115 if(getCornerSmoothFlag(corner))
01116 {
01117
01118 getBindNeighbor(corner, bindInfo);
01119
01120
01121 if(bindInfo.Zone)
01122 {
01123
01124 uvLocator.build(this, corner, bindInfo);
01125 patchId= uvLocator.selectPatch(stIn);
01126 uvLocator.locateUV(stIn, patchId, patchOut, stOut);
01127
01128
01129
01130
01131 patchOut->computeTileLightmapPixelAroundCorner(stOut, dest, true);
01132 }
01133 }
01134 }
01135 }
01136
01137 }
01138
01139
01140 }
01141
01142
01143
01144 void CPatch::getTileLightMap(uint ts, uint tt, CPatchRdrPass *&rdrpass)
01145 {
01146
01147 nlassert(TessBlocks.size()!=0);
01148
01149
01150 uint numtb, numtm;
01151 computeTbTm(numtb, numtm, ts, tt);
01152 CTessBlock &tessBlock= TessBlocks[numtb];
01153
01154
01155 if(tessBlock.LightMapRefCount==0)
01156 {
01157
01158 CRGBA lightText[NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE];
01159 computeNearBlockLightmap(ts&(~1), tt&(~1), lightText);
01160
01161
01162 tessBlock.LightMapId= Zone->Landscape->getTileLightMap(lightText, rdrpass);
01163
01164
01165 tessBlock.LightMapRdrPass= rdrpass;
01166 }
01167
01168
01169 tessBlock.LightMapRefCount++;
01170
01171
01172
01173 rdrpass= tessBlock.LightMapRdrPass;
01174 }
01175
01176
01177
01178 void CPatch::getTileLightMapUvInfo(uint ts, uint tt, CVector &uvScaleBias)
01179 {
01180
01181 nlassert(TessBlocks.size()!=0);
01182
01183
01184 uint numtb, numtm;
01185 computeTbTm(numtb, numtm, ts, tt);
01186 CTessBlock &tessBlock= TessBlocks[numtb];
01187
01188
01189 Zone->Landscape->getTileLightMapUvInfo(tessBlock.LightMapId, uvScaleBias);
01190
01191
01192 uint tsDec= ts & 1;
01193 uint ttDec= tt & 1;
01194 uvScaleBias.x+= tsDec * uvScaleBias.z;
01195 uvScaleBias.y+= ttDec * uvScaleBias.z;
01196 }
01197
01198
01199
01200 void CPatch::releaseTileLightMap(uint ts, uint tt)
01201 {
01202
01203 nlassert(TessBlocks.size()!=0);
01204
01205
01206 uint numtb, numtm;
01207 computeTbTm(numtb, numtm, ts, tt);
01208 CTessBlock &tessBlock= TessBlocks[numtb];
01209
01210
01211 nlassert(tessBlock.LightMapRefCount>0);
01212 tessBlock.LightMapRefCount--;
01213 if(tessBlock.LightMapRefCount==0)
01214 {
01215 Zone->Landscape->releaseTileLightMap(tessBlock.LightMapId);
01216 }
01217 }
01218
01219
01220 void CPatch::packShadowMap (const uint8 *pLumelSrc)
01221 {
01222
01223 uint lumelCount=OrderS*NL_LUMEL_BY_TILE;
01224
01225
01226 nlassert ((lumelCount&0x3)==0);
01227 uint numLumelBlock=lumelCount>>2;
01228
01229
01230 uint lineCount=OrderT*NL_LUMEL_BY_TILE;
01231
01232
01233 nlassert ((lineCount&0x3)==0);
01234 uint numLineBlock=lineCount>>2;
01235
01236
01237 CompressedLumels.resize (numLumelBlock*numLineBlock*NL_BLOCK_LUMEL_COMPRESSED_SIZE);
01238
01239
01240 uint8 *compressedData=&CompressedLumels[0];
01241
01242
01243 for (uint lineBlock=0; lineBlock<numLineBlock; lineBlock++)
01244 {
01245
01246 const uint8 *blockLine=pLumelSrc;
01247
01248
01249 for (uint lumelBlock=0; lumelBlock<numLumelBlock; lumelBlock++)
01250 {
01251
01252 uint countU;
01253
01254
01255 if (lumelBlock==numLumelBlock-1)
01256 countU=lumelCount&3;
01257 else
01258 countU=4;
01259
01260
01261 const uint8 *blockSrc=blockLine;
01262
01263
01264 uint8 originalBlock[4*4];
01265
01266
01267 for (uint v=0; v<NL_LUMEL_BY_TILE; v++)
01268 {
01269 for (uint u=0; u<NL_LUMEL_BY_TILE; u++)
01270 {
01271
01272 originalBlock[(v<<2)+u]=blockSrc[u];
01273 }
01274
01275
01276 blockSrc+=lumelCount;
01277 }
01278
01279
01280 uint8 alphaMin=255;
01281 uint8 alphaMax=0;
01282
01283
01284 for (uint i=0; i<16; i++)
01285 {
01286
01287 if (originalBlock[i]<alphaMin)
01288 alphaMin=originalBlock[i];
01289 if (originalBlock[i]>alphaMax)
01290 alphaMax=originalBlock[i];
01291 }
01292
01293
01294
01295
01296 uint8 uncompressedBlock[4*4];
01297
01298
01299 packLumelBlock (compressedData, originalBlock, alphaMin, alphaMax);
01300
01301
01302 unpackLumelBlock (uncompressedBlock, compressedData);
01303
01304
01305 uint firstMethod=evalLumelBlock (originalBlock, uncompressedBlock, NL_LUMEL_BY_TILE, NL_LUMEL_BY_TILE);
01306
01307
01308 uint8 secondCompressedBlock[NL_BLOCK_LUMEL_COMPRESSED_SIZE];
01309 packLumelBlock (secondCompressedBlock, originalBlock, alphaMax, alphaMin);
01310
01311
01312 unpackLumelBlock (uncompressedBlock, secondCompressedBlock);
01313
01314
01315 uint secondMethod=evalLumelBlock (originalBlock, uncompressedBlock, NL_LUMEL_BY_TILE, NL_LUMEL_BY_TILE);
01316
01317
01318 if (secondMethod<firstMethod)
01319 {
01320
01321 memcpy (compressedData, secondCompressedBlock, NL_BLOCK_LUMEL_COMPRESSED_SIZE);
01322 }
01323
01324
01325 compressedData+=NL_BLOCK_LUMEL_COMPRESSED_SIZE;
01326
01327
01328 blockLine+=4;
01329 }
01330
01331
01332 pLumelSrc+=lumelCount*4;
01333 }
01334 }
01335
01336
01337 void CPatch::resetCompressedLumels ()
01338 {
01339
01340 uint lumelCount=OrderS*NL_LUMEL_BY_TILE;
01341
01342
01343 nlassert ((lumelCount&0x3)==0);
01344 uint numLumelBlock=lumelCount>>2;
01345
01346
01347 uint lineCount=OrderT*NL_LUMEL_BY_TILE;
01348
01349
01350 nlassert ((lineCount&0x3)==0);
01351 uint numLineBlock=lineCount>>2;
01352
01353
01354 uint size=numLineBlock*numLumelBlock*8;
01355
01356
01357 CompressedLumels.resize (size);
01358
01359
01360 memset (&CompressedLumels[0], 0, size);
01361 }
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372 #define a00 tex[0]
01373 #define a10 tex[1]
01374 #define a20 tex[2]
01375 #define a30 tex[3]
01376 #define a40 tex[4]
01377
01378 #define a01 tex[5]
01379 #define a11 tex[6]
01380 #define a21 tex[7]
01381 #define a31 tex[8]
01382 #define a41 tex[9]
01383
01384 #define a02 tex[10]
01385 #define a12 tex[11]
01386 #define a22 tex[12]
01387 #define a32 tex[13]
01388 #define a42 tex[14]
01389
01390 #define a03 tex[15]
01391 #define a13 tex[16]
01392 #define a23 tex[17]
01393 #define a33 tex[18]
01394 #define a43 tex[19]
01395
01396 #define a04 tex[20]
01397 #define a14 tex[21]
01398 #define a24 tex[22]
01399 #define a34 tex[23]
01400 #define a44 tex[24]
01401
01402 void NL3D_bilinearTileLightMap(CRGBA *tex)
01403 {
01404
01405
01406
01407
01408
01409 a02.avg2(a00, a04);
01410 a01.avg2(a00, a02);
01411 a03.avg2(a02, a04);
01412 a42.avg2(a40, a44);
01413 a41.avg2(a40, a42);
01414 a43.avg2(a42, a44);
01415
01416
01417 a20.avg2(a00, a40);
01418 a10.avg2(a00, a20);
01419 a30.avg2(a20, a40);
01420
01421
01422 a21.avg2(a01, a41);
01423 a11.avg2(a01, a21);
01424 a31.avg2(a21, a41);
01425
01426
01427 a22.avg2(a02, a42);
01428 a12.avg2(a02, a22);
01429 a32.avg2(a22, a42);
01430
01431
01432 a23.avg2(a03, a43);
01433 a13.avg2(a03, a23);
01434 a33.avg2(a23, a43);
01435
01436
01437 a24.avg2(a04, a44);
01438 a14.avg2(a04, a24);
01439 a34.avg2(a24, a44);
01440
01441 }
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452 uint8 CPatch::getLumel(const CUV &uv) const
01453 {
01454
01455 sint ts, tt;
01456
01457 sint w= (OrderS<<NL_LUMEL_BY_TILE_SHIFT);
01458 sint h= (OrderT<<NL_LUMEL_BY_TILE_SHIFT);
01459
01460
01461 ts= OptFastFloor(uv.U* (w<<8) + 128); ts>>=8;
01462 tt= OptFastFloor(uv.V* (h<<8) + 128); tt>>=8;
01463 clamp(ts, 0, w-1);
01464 clamp(tt, 0, h-1);
01465
01466 uint8 ret;
01467 getTileLumelmapPixelPrecomputed(ts>>NL_LUMEL_BY_TILE_SHIFT, tt>>NL_LUMEL_BY_TILE_SHIFT,
01468 ts&(NL_LUMEL_BY_TILE-1), tt&(NL_LUMEL_BY_TILE-1), ret);
01469
01470 return ret;
01471 }
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482 void CPatch::resetTileLightInfluences()
01483 {
01484
01485 TileLightInfluences.resize((OrderS/2 +1) * (OrderT/2 +1));
01486
01487 for(uint i=0;i <TileLightInfluences.size(); i++)
01488 {
01489
01490 TileLightInfluences[i].Light[0]= 0xFF;
01491 }
01492 }
01493
01494
01495
01496 void CPatch::appendTileLightInfluences(const CUV &uv,
01497 std::vector<CPointLightInfluence> &pointLightList) const
01498 {
01499
01500 sint x,y;
01501
01502 sint w= (OrderS>>1);
01503 sint h= (OrderT>>1);
01504 sint wTLI= w+1;
01505
01506 x= OptFastFloor(uv.U * (w<<8));
01507 y= OptFastFloor(uv.V * (h<<8));
01508 clamp(x, 0, w<<8);
01509 clamp(y, 0, h<<8);
01510
01511 sint xTLI,yTLI, xSub, ySub;
01512 xTLI= x>>8; clamp(xTLI, 0, w-1);
01513 yTLI= y>>8; clamp(yTLI, 0, h-1);
01514
01515 xSub= x - (xTLI<<8);
01516 ySub= y - (yTLI<<8);
01517
01518
01519
01520 CLightInfluenceInterpolator interp;
01521
01522 nlassert(CTileLightInfluence::NumLightPerCorner==2);
01523 nlassert(CLightInfluenceInterpolator::NumLightPerCorner==2);
01524
01525 CPointLightNamed *zonePointLights= NULL;
01526 if( getZone()->_PointLightArray.getPointLights().size() >0 )
01527 {
01528
01529
01530 zonePointLights= const_cast<CPointLightNamed*>(&(getZone()->_PointLightArray.getPointLights()[0]));
01531 }
01532
01533 for(y=0;y<2;y++)
01534 {
01535 for(x=0;x<2;x++)
01536 {
01537
01538 const CTileLightInfluence &tli= TileLightInfluences[ (yTLI+y)*wTLI + xTLI+x ];
01539 CLightInfluenceInterpolator::CCorner &corner= interp.Corners[y*2 + x];
01540
01541 uint lid;
01542 for(lid= 0; lid<CTileLightInfluence::NumLightPerCorner; lid++)
01543 {
01544
01545 uint tliLightId= tli.Light[lid];
01546
01547 if(tliLightId==0xFF)
01548 break;
01549 else
01550 {
01551
01552 corner.Lights[lid]= zonePointLights + tliLightId;
01553 }
01554 }
01555
01556 for(; lid<CTileLightInfluence::NumLightPerCorner; lid++)
01557 {
01558
01559 corner.Lights[lid]= NULL;
01560 }
01561 }
01562 }
01563
01564 interp.interpolate(pointLightList, xSub/256.f, ySub/256.f);
01565 }
01566
01567
01568
01569 CRGBA CPatch::getCurrentTLIColor(uint x, uint y) const
01570 {
01571 CRGBA ret;
01572 ret= CRGBA::Black;
01573
01574
01575 if( getZone()->_PointLightArray.getPointLights().size() >0 )
01576 {
01577 const CPointLightNamed *zonePointLights;
01578 zonePointLights= (&(getZone()->_PointLightArray.getPointLights()[0]));
01579
01580 uint wTLI= (OrderS>>1)+1;
01581
01582 const CTileLightInfluence &tli= TileLightInfluences[ y*wTLI + x];
01583 for(uint lid=0;lid<CTileLightInfluence::NumLightPerCorner;lid++)
01584 {
01585
01586 if(tli.Light[lid]==0xFF)
01587 break;
01588
01589 CRGBA lightCol= zonePointLights[tli.Light[lid]].getDiffuse();
01590
01591 lightCol.modulateFromColorRGBOnly(lightCol, getLandscape()->getPointLightDiffuseMaterial() );
01592
01593 lightCol.modulateFromuiRGBOnly(lightCol, tli.getDiffuseLightFactor(lid) );
01594
01595 ret.addRGBOnly(ret, lightCol);
01596 }
01597 }
01598
01599 return ret;
01600 }
01601
01602
01603
01604 void CPatch::getCurrentTileTLIColors(uint ts, uint tt, NLMISC::CRGBA corners[4])
01605 {
01606
01607 if( getZone()->_PointLightArray.getPointLights().size() >0 )
01608 {
01609
01610 uint tbs= ts>>1;
01611 uint tbt= tt>>1;
01612
01613 uint tls= ts-(tbs<<1);
01614 uint tlt= tt-(tbt<<1);
01615
01616
01617 CRGBA tbCorners[4];
01618 for(uint y=0;y<2;y++)
01619 {
01620 for(uint x=0;x<2;x++)
01621 {
01622 CRGBA &cornerCol= tbCorners[y*2+x];
01623 cornerCol= getCurrentTLIColor(tbs+x, tbt+y);
01624 }
01625 }
01626
01627
01628 CRGBA tbEdges[4];
01629 CRGBA tbMiddle;
01630
01631 tbEdges[0].avg2RGBOnly(tbCorners[0], tbCorners[2]);
01632
01633 tbEdges[1].avg2RGBOnly(tbCorners[2], tbCorners[3]);
01634
01635 tbEdges[2].avg2RGBOnly(tbCorners[1], tbCorners[3]);
01636
01637 tbEdges[3].avg2RGBOnly(tbCorners[0], tbCorners[1]);
01638
01639 tbMiddle.avg2RGBOnly(tbEdges[0], tbEdges[2]);
01640
01641
01642 if(tlt==0)
01643 {
01644 if(tls==0)
01645 {
01646 corners[0]= tbCorners[0];
01647 corners[1]= tbEdges[3];
01648 corners[2]= tbEdges[0];
01649 corners[3]= tbMiddle;
01650 }
01651 else
01652 {
01653 corners[0]= tbEdges[3];
01654 corners[1]= tbCorners[1];
01655 corners[2]= tbMiddle;
01656 corners[3]= tbEdges[2];
01657 }
01658 }
01659 else
01660 {
01661 if(tls==0)
01662 {
01663 corners[0]= tbEdges[0];
01664 corners[1]= tbMiddle;
01665 corners[2]= tbCorners[2];
01666 corners[3]= tbEdges[1];
01667 }
01668 else
01669 {
01670 corners[0]= tbMiddle;
01671 corners[1]= tbEdges[2];
01672 corners[2]= tbEdges[1];
01673 corners[3]= tbCorners[3];
01674 }
01675 }
01676 }
01677 else
01678 {
01679
01680 corners[0]= CRGBA::Black;
01681 corners[1]= CRGBA::Black;
01682 corners[2]= CRGBA::Black;
01683 corners[3]= CRGBA::Black;
01684 }
01685 }
01686
01687
01688 void CPatch::addTileLightmapWithTLI(uint ts, uint tt, NLMISC::CRGBA *dest, uint stride)
01689 {
01690
01691 CRGBA corners[4];
01692 getCurrentTileTLIColors(ts, tt, corners);
01693
01694
01695 uint x, y;
01696 for(y=0; y<NL_LUMEL_BY_TILE; y++)
01697 {
01698 for(x=0; x<NL_LUMEL_BY_TILE; x++)
01699 {
01700
01701 bilinearColorAndAdd(corners, x, y, dest[y*stride + x]);
01702 }
01703 }
01704 }
01705
01706
01707 void CPatch::addTileLightmapEdgeWithTLI(uint ts, uint tt, uint edge, NLMISC::CRGBA *dest, uint stride, bool inverse)
01708 {
01709
01710 CRGBA corners[4];
01711 getCurrentTileTLIColors(ts, tt, corners);
01712
01713
01714 uint x=0,y=0;
01715 switch(edge)
01716 {
01717 case 0: x= 0; break;
01718 case 1: y= NL_LUMEL_BY_TILE-1; break;
01719 case 2: x= NL_LUMEL_BY_TILE-1; break;
01720 case 3: y= 0; break;
01721 };
01722
01723
01724 uint i;
01725 for(i=0; i<NL_LUMEL_BY_TILE; i++)
01726 {
01727
01728 if( (edge&1)==0 ) y= i;
01729
01730 else x= i;
01731
01732
01733 uint where;
01734 if(inverse) where= (NL_LUMEL_BY_TILE-1)-i;
01735 else where= i;
01736
01737 bilinearColorAndAdd(corners, x, y, dest[where*stride]);
01738 }
01739 }
01740
01741
01742 void CPatch::addTileLightmapPixelWithTLI(uint ts, uint tt, uint s, uint t, NLMISC::CRGBA *dest)
01743 {
01744
01745 CRGBA corners[4];
01746 getCurrentTileTLIColors(ts, tt, corners);
01747
01748
01749 bilinearColorAndAdd(corners, s, t, *dest);
01750 }
01751
01752
01753
01754 void CPatch::computeCurrentTLILightmap(NLMISC::CRGBA *array) const
01755 {
01756
01757 uint wTLI= (OrderS>>1)+1;
01758 uint hTLI= (OrderT>>1)+1;
01759
01760 uint wTC= OrderS+1;
01761 uint wTCx2= wTC*2;
01762 uint hTC= OrderT+1;
01763 uint x, y;
01764
01765
01766
01767 for(y=0;y<hTLI;y++)
01768 {
01769
01770 CRGBA *dst= array + y*2*wTC;
01771 for(x=0;x<wTLI;x++)
01772 {
01773 *dst= getCurrentTLIColor(x, y);
01774
01775 dst++;
01776 dst++;
01777 }
01778 }
01779
01780
01781
01782
01783
01784 for(y=0;y<hTC-1;y+=2)
01785 {
01786 CRGBA *dst= array + y*wTC;
01787 for(x=0;x<wTC;x+=2)
01788 {
01789
01790 (dst+wTC)->avg2RGBOnly(*dst, *(dst + wTCx2) );
01791
01792
01793 dst++;
01794 dst++;
01795 }
01796 }
01797
01798
01799 for(y=0;y<hTC;y++)
01800 {
01801 CRGBA *dst= array + y*wTC;
01802 for(x=0;x<wTC-1;x+=2)
01803 {
01804
01805 (dst+1)->avg2RGBOnly(*dst, *(dst+2));
01806
01807
01808 dst++;
01809 dst++;
01810 }
01811 }
01812
01813
01814 }
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826 void CPatch::linkBeforeNearUL(CPatch *patchNext)
01827 {
01828 nlassert(patchNext);
01829
01830
01831 _ULNearNext->_ULNearPrec= _ULNearPrec;
01832 _ULNearPrec->_ULNearNext= _ULNearNext;
01833
01834 _ULNearNext= patchNext;
01835 _ULNearPrec= patchNext->_ULNearPrec;
01836
01837 _ULNearNext->_ULNearPrec= this;
01838 _ULNearPrec->_ULNearNext= this;
01839 }
01840
01841
01842
01843 void CPatch::unlinkNearUL()
01844 {
01845
01846 _ULNearNext->_ULNearPrec= _ULNearPrec;
01847 _ULNearPrec->_ULNearNext= _ULNearNext;
01848
01849 _ULNearPrec= this;
01850 _ULNearNext= this;
01851 }
01852
01853
01854
01855 uint CPatch::updateTessBlockLighting(uint numTb)
01856 {
01857
01858 nlassert(numTb<TessBlocks.size());
01859
01860
01861 uint tbWidth= OrderS>>1;
01862 uint ts= numTb&(tbWidth-1);
01863 uint tt= numTb/tbWidth;
01864
01865 ts*= 2;
01866 tt*= 2;
01867
01868
01869 CTessBlock &tessBlock= TessBlocks[numTb];
01870
01871
01872 if(tessBlock.LightMapRefCount==0)
01873 return 0;
01874 else
01875 {
01876
01877 CRGBA lightText[NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE];
01878 computeNearBlockLightmap(ts&(~1), tt&(~1), lightText);
01879
01880
01881 Zone->Landscape->refillTileLightMap(tessBlock.LightMapId, lightText);
01882
01883
01884 return NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE;
01885 }
01886 }
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896 void CPatch::addRefDLMContext()
01897 {
01898
01899 nlassert(Zone);
01900
01901
01902 if(_DLMContextRefCount==0)
01903 {
01904 nlassert(_DLMContext==NULL);
01905 _DLMContext= new CPatchDLMContext;
01906
01907 _DLMContext->generate(this, getLandscape()->getTextureDLM(), getLandscape()->getPatchDLMContextList());
01908
01909
01910
01911 if(!RenderClipped)
01912 {
01913
01914 fillVBFarsDLMUvOnly();
01915 }
01916 }
01917
01918
01919 _DLMContextRefCount++;
01920 }
01921
01922
01923 void CPatch::decRefDLMContext(uint count)
01924 {
01925
01926 nlassert(Zone);
01927 nlassert(_DLMContextRefCount>0);
01928
01929
01930 _DLMContextRefCount-= count;
01931 nlassert(_DLMContextRefCount>=0);
01932
01933
01934 if(_DLMContextRefCount==0)
01935 {
01936 delete _DLMContext;
01937 _DLMContext= NULL;
01938
01939
01940
01941 if(!RenderClipped)
01942 {
01943
01944 fillVBFarsDLMUvOnly();
01945 }
01946 }
01947 }
01948
01949
01950
01951 void CPatch::beginDLMLighting()
01952 {
01953 nlassert(_DLMContext);
01954
01955
01956 _DLMContext->OldPointLightCount= _DLMContext->CurPointLightCount;
01957 _DLMContext->CurPointLightCount= 0;
01958
01959
01960 if(!RenderClipped)
01961
01962 _DLMContext->clearLighting();
01963
01964 }
01965
01966
01967 void CPatch::processDLMLight(CPatchDLMPointLight &pl)
01968 {
01969
01970 addRefDLMContext();
01971
01972
01973 _DLMContext->CurPointLightCount++;
01974
01975
01976 if(!RenderClipped)
01977 _DLMContext->addPointLightInfluence(pl);
01978 }
01979
01980
01981 void CPatch::endDLMLighting()
01982 {
01983 nlassert(_DLMContext);
01984
01985
01986
01987 decRefDLMContext(_DLMContext->OldPointLightCount);
01988 }
01989
01990
01991 }
01992