00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/patchdlm_context.h"
00029 #include "3d/patch.h"
00030 #include "3d/bezier_patch.h"
00031 #include "3d/point_light.h"
00032 #include "3d/texture_dlm.h"
00033 #include "3d/fast_floor.h"
00034 #include "3d/tile_far_bank.h"
00035 #include "3d/landscape.h"
00036 #include "nel/misc/system_info.h"
00037 #include "nel/misc/fast_mem.h"
00038
00039
00040 using namespace std;
00041 using namespace NLMISC;
00042
00043 namespace NL3D
00044 {
00045
00046
00047
00048
00049
00050
00051
00052 void CPatchDLMPointLight::compile(const CPointLight &pl, NLMISC::CRGBA landDiffMat, float maxAttEnd)
00053 {
00054 nlassert(maxAttEnd>0);
00055
00056
00057 R= (float) (( pl.getDiffuse().R*(landDiffMat.R+1) ) >>8);
00058 G= (float) (( pl.getDiffuse().G*(landDiffMat.G+1) ) >>8);
00059 B= (float) (( pl.getDiffuse().B*(landDiffMat.B+1) ) >>8);
00060
00061 IsSpot= pl.getType() == CPointLight::SpotLight;
00062 Pos= pl.getPosition();
00063 Dir= pl.getSpotDirection();
00064
00065
00066 if(IsSpot)
00067 {
00068 CosMax= cosf(pl.getSpotAngleBegin());
00069 CosMin= cosf(pl.getSpotAngleEnd());
00070 }
00071 else
00072 {
00073
00074 CosMax= -1;
00075 CosMin= -2;
00076 }
00077 OOCosDelta= 1.f / (CosMax-CosMin);
00078
00079
00080 AttMax= pl.getAttenuationEnd();
00081 AttMin= pl.getAttenuationBegin();
00082
00083 if(AttMax==0)
00084 {
00085 AttMax= maxAttEnd;
00086 AttMin= maxAttEnd*0.99f;
00087 }
00088
00089 else if(AttMax>maxAttEnd)
00090 {
00091 AttMax= maxAttEnd;
00092 AttMin= min(AttMin, maxAttEnd*0.99f);
00093 }
00094
00095 OOAttDelta= 1.f / (AttMin-AttMax);
00096
00097
00098
00099
00100 if(!IsSpot || CosMin<0)
00101 {
00102
00103 BSphere.Center= Pos;
00104 BSphere.Radius= AttMax;
00105
00106 BBox.setCenter(Pos);
00107 BBox.setHalfSize(CVector(AttMax, AttMax, AttMax));
00108 }
00109 else
00110 {
00111
00112
00113
00114
00115 float sinMin= sqrtf(1-sqr(CosMin));
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 float radius1= 0.5f;
00126
00127 float dccs= sqrtf( sqr(CosMin-0.5f) + sqr(sinMin));
00128
00129 radius1= max(radius1, dccs );
00130
00131
00132 float radius2= max(CosMin, 1-CosMin);
00133
00134 dccs= sinMin;
00135
00136 radius2= max(radius2, dccs );
00137
00138
00139
00140 if(radius1<radius2)
00141 {
00142 BSphere.Center= Pos + (Dir*0.5f*AttMax);
00143
00144 BSphere.Radius= radius1 * AttMax;
00145 }
00146 else
00147 {
00148 BSphere.Center= Pos + (Dir*CosMin*AttMax);
00149
00150 BSphere.Radius= radius2 * AttMax;
00151 }
00152
00153
00154
00155
00156
00157
00158 BBox.setCenter(BSphere.Center);
00159 float rad= BSphere.Radius;
00160 BBox.setHalfSize( CVector(rad, rad, rad) );
00161 }
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171 CPatchDLMContext::CPatchDLMContext()
00172 {
00173 _Patch= NULL;
00174 _DLMTexture= NULL;
00175 _DLMContextList= NULL;
00176 OldPointLightCount= 0;
00177 CurPointLightCount= 0;
00178
00179 _IsSrcTextureFullBlack= false;
00180 _IsDstTextureFullBlack= false;
00181 }
00182
00183
00184
00185 CPatchDLMContext::~CPatchDLMContext()
00186 {
00187
00188 if(_DLMTexture)
00189 {
00190 _DLMTexture->releaseLightMap(TextPosX, TextPosY);
00191 }
00192
00193 _Patch= NULL;
00194 _DLMTexture= NULL;
00195
00196
00197 if(_DLMContextList)
00198 _DLMContextList->remove(this);
00199 }
00200
00201
00202
00203 #ifdef NL_DLM_TILE_RES
00204
00205 #define NL_DLM_CLIP_FACTOR 2
00206 #else
00207
00208 #define NL_DLM_CLIP_FACTOR 1
00209 #endif
00210
00211 #define NL_DLM_CLIP_NUM_LEVEL 3
00212
00213
00214 bool CPatchDLMContext::generate(CPatch *patch, CTextureDLM *textureDLM, CPatchDLMContextList *ctxList)
00215 {
00216 nlassert(patch);
00217 nlassert(textureDLM);
00218 nlassert(ctxList);
00219
00220
00221 _Patch= patch;
00222 _DLMTexture= textureDLM;
00223
00224 _DLMContextList= ctxList;
00225 _DLMContextList->append(this);
00226
00227
00228 #ifdef NL_DLM_TILE_RES
00229
00230 Width= (_Patch->getOrderS())+1;
00231 Height= (_Patch->getOrderT())+1;
00232 #else
00233
00234 Width= (_Patch->getOrderS()/2)+1;
00235 Height= (_Patch->getOrderT()/2)+1;
00236 #endif
00237
00238
00239 if(!_DLMTexture->createLightMap(Width, Height, TextPosX, TextPosY))
00240 {
00241
00242
00243 _DLMTexture= NULL;
00244 }
00245
00246
00247 if(_DLMTexture)
00248 {
00249
00250 DLMUScale= (float)(Width-1) / (float)_DLMTexture->getWidth();
00251 DLMVScale= (float)(Height-1) / (float)_DLMTexture->getHeight();
00252 DLMUBias= ((float)TextPosX+0.5f) / (float)_DLMTexture->getWidth();
00253 DLMVBias= ((float)TextPosY+0.5f) / (float)_DLMTexture->getHeight();
00254 }
00255 else
00256 {
00257
00258
00259 DLMUScale= 0;
00260 DLMVScale= 0;
00261 DLMUBias= 1;
00262 DLMVBias= 1;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 sint tmpU, tmpV;
00274
00275 tmpU= (sint)ceil ( (DLMUBias) * 255 );
00276 clamp(tmpU, 0, 255);
00277 MinU8= tmpU;
00278
00279 tmpU= (sint)floor( (DLMUBias+DLMUScale) * 255 );
00280 clamp(tmpU, (sint)MinU8, 255);
00281 MaxU8= tmpU;
00282
00283 tmpV= (sint)ceil ( (DLMVBias) * 255 );
00284 clamp(tmpV, 0, 255);
00285 MinV8= tmpV;
00286
00287 tmpV= (sint)floor( (DLMVBias+DLMVScale) * 255 );
00288 clamp(tmpV, (sint)MinV8, 255);
00289 MaxV8= tmpV;
00290
00291
00292
00293 _LightMap.resize(Width*Height);
00294
00295
00296 _Vertices.resize(Width*Height);
00297 float s, t;
00298 float ds= 1.0f / (Width-1);
00299 float dt= 1.0f / (Height-1);
00300
00301 t= 0;
00302 uint x,y;
00303 for(y=0; y<Height; y++, t+=dt)
00304 {
00305 s= 0;
00306 for(x=0; x<Width; x++, s+=ds)
00307 {
00308 CVertex &vert= _Vertices[y*Width+x];
00309
00310 CBezierPatch *bpatch= _Patch->unpackIntoCache();
00311
00312 vert.Pos= bpatch->eval(s, t);
00313
00314 vert.Normal= bpatch->evalNormal(s, t);
00315 }
00316 }
00317
00318
00319
00320
00321
00322 uint bsx, bsy;
00323 #ifdef NL_DLM_TILE_RES
00324
00325 bsx= max(1, (_Patch->getOrderS())/NL_DLM_CLIP_FACTOR );
00326 bsy= max(1, (_Patch->getOrderT())/NL_DLM_CLIP_FACTOR );
00327 #else
00328
00329 bsx= max(1, (_Patch->getOrderS()/2)/NL_DLM_CLIP_FACTOR );
00330 bsy= max(1, (_Patch->getOrderT()/2)/NL_DLM_CLIP_FACTOR );
00331 #endif
00332
00333
00334 static vector<CAABBox> tmpBBoxes[NL_DLM_CLIP_NUM_LEVEL];
00335 tmpBBoxes[0].resize(bsx * bsy);
00336
00337
00338 for(y=0;y<bsy;y++)
00339 {
00340
00341 uint beginY= y*NL_DLM_CLIP_FACTOR;
00342 uint endY= min( (y+1)*NL_DLM_CLIP_FACTOR+1, Height);
00343 for(x=0;x<bsx;x++)
00344 {
00345
00346 uint beginX= x*NL_DLM_CLIP_FACTOR;
00347 uint endX= min((x+1)*NL_DLM_CLIP_FACTOR+1, Width);
00348
00349 CAABBox bbox;
00350 bbox.setCenter(_Vertices[beginY*Width + beginX].Pos);
00351 for(uint yi= beginY; yi<endY; yi++)
00352 {
00353 for(uint xi= beginX; xi<endX; xi++)
00354 {
00355 bbox.extend(_Vertices[yi*Width + xi].Pos);
00356 }
00357 }
00358
00359 tmpBBoxes[0][y*bsx + x]= bbox;
00360 }
00361 }
00362
00363
00364 uint curLevel= 0;
00365 uint nextLevel= 1;
00366 uint nextBsx= max(1U, bsx/2);
00367 uint nextBsy= max(1U, bsy/2);
00368
00369 uint tmpClusterNumToSkip[NL_DLM_CLIP_NUM_LEVEL];
00370
00371 uint tmpClusterWidth[NL_DLM_CLIP_NUM_LEVEL];
00372
00373 uint tmpClusterWSon[NL_DLM_CLIP_NUM_LEVEL];
00374 uint tmpClusterHSon[NL_DLM_CLIP_NUM_LEVEL];
00375
00376 tmpClusterNumToSkip[0]= 0;
00377 tmpClusterWidth[0]= bsx;
00378 tmpClusterWSon[0]= 0;
00379 tmpClusterHSon[0]= 0;
00380 uint finalClusterSize= bsx * bsy;
00381
00382
00383 while(nextBsx * nextBsy > 1 && nextLevel<NL_DLM_CLIP_NUM_LEVEL )
00384 {
00385 finalClusterSize+= nextBsx * nextBsy;
00386
00387 uint wSon= (bsx/nextBsx);
00388 uint hSon= (bsy/nextBsy);
00389
00390 tmpClusterWidth[nextLevel]= nextBsx;
00391 tmpClusterWSon[nextLevel]= wSon;
00392 tmpClusterHSon[nextLevel]= hSon;
00393
00394
00395 tmpClusterNumToSkip[nextLevel]= (1+tmpClusterNumToSkip[curLevel]) * wSon * hSon;
00396
00397
00398 tmpBBoxes[nextLevel].resize(nextBsx * nextBsy);
00399
00400
00401 for(y=0;y<nextBsy;y++)
00402 {
00403 for(x=0;x<nextBsx;x++)
00404 {
00405
00406 uint x2= x*wSon;
00407 uint y2= y*hSon;
00408
00409 if(wSon>1 && hSon>1)
00410 {
00411 CAABBox bbox1;
00412 CAABBox bbox2;
00413 bbox1= CAABBox::computeAABBoxUnion(
00414 tmpBBoxes[curLevel][y2*bsx + x2], tmpBBoxes[curLevel][y2*bsx + x2+1]);
00415 bbox2= CAABBox::computeAABBoxUnion(
00416 tmpBBoxes[curLevel][(y2+1)*bsx + x2], tmpBBoxes[curLevel][(y2+1)*bsx + x2+1]);
00417
00418 tmpBBoxes[nextLevel][y*nextBsx + x]= CAABBox::computeAABBoxUnion(bbox1, bbox2);
00419 }
00420 else if(wSon==1)
00421 {
00422 CAABBox bbox1;
00423 bbox1= CAABBox::computeAABBoxUnion(
00424 tmpBBoxes[curLevel][y2*bsx + x2], tmpBBoxes[curLevel][(y2+1)*bsx + x2]);
00425
00426 tmpBBoxes[nextLevel][y*nextBsx + x]= bbox1;
00427 }
00428 else if(hSon==1)
00429 {
00430 CAABBox bbox1;
00431 bbox1= CAABBox::computeAABBoxUnion(
00432 tmpBBoxes[curLevel][y2*bsx + x2], tmpBBoxes[curLevel][y2*bsx + x2+1]);
00433
00434 tmpBBoxes[nextLevel][y*nextBsx + x]= bbox1;
00435 }
00436 else
00437
00438 nlstop;
00439 }
00440 }
00441
00442
00443 bsx= nextBsx;
00444 bsy= nextBsy;
00445 nextBsx= max(1U, nextBsx/2);
00446 nextBsy= max(1U, nextBsy/2);
00447 curLevel++;
00448 nextLevel++;
00449 }
00450
00451
00452
00453 _Clusters.resize(finalClusterSize);
00454 uint iDstCluster= 0;
00455
00456
00457 uint numLevels= nextLevel;
00458
00459 uint tmpClusterX[NL_DLM_CLIP_NUM_LEVEL];
00460 uint tmpClusterY[NL_DLM_CLIP_NUM_LEVEL];
00461 uint tmpClusterXMin[NL_DLM_CLIP_NUM_LEVEL];
00462 uint tmpClusterYMin[NL_DLM_CLIP_NUM_LEVEL];
00463 uint tmpClusterXMax[NL_DLM_CLIP_NUM_LEVEL];
00464 uint tmpClusterYMax[NL_DLM_CLIP_NUM_LEVEL];
00465
00466 tmpClusterX[curLevel]= 0;
00467 tmpClusterY[curLevel]= 0;
00468 tmpClusterXMin[curLevel]= 0;
00469 tmpClusterYMin[curLevel]= 0;
00470 tmpClusterXMax[curLevel]= bsx;
00471 tmpClusterYMax[curLevel]= bsy;
00472
00473 while(curLevel < numLevels)
00474 {
00475
00476 if(tmpClusterY[curLevel] >= tmpClusterYMax[curLevel])
00477 {
00478
00479 curLevel++;
00480
00481 continue;
00482 }
00483
00484 nlassert(iDstCluster<_Clusters.size());
00485
00486
00487 CAABBox bbox= tmpBBoxes[curLevel][ tmpClusterY[curLevel] * tmpClusterWidth[curLevel] + tmpClusterX[curLevel] ];
00488
00489 _Clusters[iDstCluster].BSphere.Center= bbox.getCenter();
00490 _Clusters[iDstCluster].BSphere.Radius= bbox.getRadius();
00491
00492 if(curLevel == 0)
00493 {
00494 _Clusters[iDstCluster].NSkips= 0;
00495 _Clusters[iDstCluster].X= tmpClusterX[0];
00496 _Clusters[iDstCluster].Y= tmpClusterY[0];
00497 }
00498
00499 else
00500 _Clusters[iDstCluster].NSkips= tmpClusterNumToSkip[curLevel];
00501
00502
00503 iDstCluster ++;
00504
00505
00506
00507 if(curLevel > 0)
00508 {
00509
00510 tmpClusterXMin[curLevel-1]= tmpClusterX[curLevel] * tmpClusterWSon[curLevel];
00511 tmpClusterYMin[curLevel-1]= tmpClusterY[curLevel] * tmpClusterHSon[curLevel];
00512 tmpClusterXMax[curLevel-1]= (tmpClusterX[curLevel]+1) * tmpClusterWSon[curLevel];
00513 tmpClusterYMax[curLevel-1]= (tmpClusterY[curLevel]+1) * tmpClusterHSon[curLevel];
00514
00515 tmpClusterX[curLevel-1]= tmpClusterXMin[curLevel-1];
00516 tmpClusterY[curLevel-1]= tmpClusterYMin[curLevel-1];
00517 }
00518
00519
00520
00521 tmpClusterX[curLevel]++;
00522
00523 if(tmpClusterX[curLevel] >= tmpClusterXMax[curLevel])
00524 {
00525
00526 tmpClusterX[curLevel]= tmpClusterXMin[curLevel];
00527
00528 tmpClusterY[curLevel]++;
00529 }
00530
00531
00532
00533 if(curLevel > 0)
00534 {
00535
00536 curLevel--;
00537 }
00538
00539 }
00540
00541
00542 nlassert(iDstCluster == _Clusters.size());
00543
00544
00545
00546
00547
00548 nlassert(sizeof(CTileColor)==sizeof(uint16));
00549 #ifndef NL_DLM_TILE_RES
00550
00551
00552 nlassert(_Patch->TileColors.size()>0);
00553 CTileColor *tileColor= &_Patch->TileColors[0];
00554
00555
00556 uint wTileColor= _Patch->getOrderS()+1;
00557 CTileColor *tcOrigin= tileColor;
00558
00559 _LowResTileColors.resize(Width*Height);
00560 uint16 *dstLRtc= &_LowResTileColors[0];
00561
00562
00563 for(y=0;y<Height;y++)
00564 {
00565
00566 tileColor= tcOrigin + y*2* wTileColor;
00567 sint npix= Width;
00568
00569 for(;npix>0; npix--, tileColor+=2, dstLRtc++)
00570 {
00571 *dstLRtc= tileColor->Color565;
00572 }
00573
00574 }
00575 #endif
00576
00577
00578
00579
00580
00581 computeTextureFar();
00582
00583
00584
00585
00586 clearLighting();
00587
00588 return true;
00589 }
00590
00591
00592 void CPatchDLMContext::clearLighting()
00593 {
00594
00595 if(!_IsSrcTextureFullBlack)
00596 {
00597
00598 uint count= _LightMap.size();
00599 if(count>0)
00600 {
00601 memset(&_LightMap[0], 0, count * sizeof(CRGBA));
00602 }
00603
00604
00605 _IsSrcTextureFullBlack= true;
00606 }
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 inline void fastClamp01(float &x)
00642 {
00643 clamp(x, 0.f, 1.f);
00644 }
00645
00646
00647
00648 void CPatchDLMContext::addPointLightInfluence(const CPatchDLMPointLight &pl)
00649 {
00650 uint nverts= _Vertices.size();
00651 nlassert(nverts==_LightMap.size());
00652
00653 if(nverts==0)
00654 return;
00655 CVertex *vert= &_Vertices[0];
00656
00657
00658
00659
00660 uint i, x,y;
00661 uint startX, startY, endX, endY;
00662 startX= 0xFFFFFFFF;
00663 startY= 0xFFFFFFFF;
00664 endX= 0;
00665 endY= 0;
00666 for(i=0;i<_Clusters.size();)
00667 {
00668
00669 if(_Clusters[i].BSphere.intersect(pl.BSphere) )
00670 {
00671
00672 if(_Clusters[i].NSkips==0)
00673 {
00674 x= _Clusters[i].X;
00675 y= _Clusters[i].Y;
00676 startX= min(startX, x);
00677 startY= min(startY, y);
00678 endX= max(endX, x+1);
00679 endY= max(endY, y+1);
00680 }
00681
00682 i++;
00683 }
00684 else
00685 {
00686
00687 if(_Clusters[i].NSkips==0)
00688 i++;
00689
00690 else
00691 i+= _Clusters[i].NSkips;
00692 }
00693 }
00694
00695 if(startX==0xFFFFFFFF)
00696 return;
00697
00698
00699 startX*=NL_DLM_CLIP_FACTOR;
00700 startY*=NL_DLM_CLIP_FACTOR;
00701 endX= min(endX*NL_DLM_CLIP_FACTOR+1, Width);
00702 endY= min(endY*NL_DLM_CLIP_FACTOR+1, Height);
00703
00704
00705
00706
00707
00708
00709
00710 float r,g,b;
00711 CRGBA *dst= &_LightMap[0];
00712 CVertex *originVert= vert;
00713 CRGBA *originDst= dst;
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 OptFastFloorBegin24();
00729
00730
00731 if(pl.IsSpot)
00732 {
00733 for(y=startY; y<endY; y++)
00734 {
00735 nverts= endX - startX;
00736
00737 vert= originVert + startX + y*Width;
00738 dst= originDst + startX + y*Width;
00739 for(;nverts>0; nverts--, vert++, dst++)
00740 {
00741 CVector dirToP= vert->Pos - pl.Pos;
00742 float dist= dirToP.norm();
00743 dirToP/= dist;
00744
00745
00746 float cosSpot= dirToP * pl.Dir;
00747 float attSpot= (cosSpot-pl.CosMin) * pl.OOCosDelta;
00748 fastClamp01(attSpot);
00749
00750
00751 float attDist= (dist-pl.AttMax) * pl.OOAttDelta;
00752 fastClamp01(attDist);
00753
00754
00755 float diff= -(vert->Normal * dirToP);
00756 fastClamp01(diff);
00757
00758
00759 diff*= attSpot * attDist;
00760 r= pl.R*diff;
00761 g= pl.G*diff;
00762 b= pl.B*diff;
00763
00764 CRGBA col;
00765 col.R= (uint8)OptFastFloor24(r);
00766 col.G= (uint8)OptFastFloor24(g);
00767 col.B= (uint8)OptFastFloor24(b);
00768
00769
00770 #ifdef NL_OS_WINDOWS
00771
00772 __asm
00773 {
00774 mov esi, dst
00775
00776 mov al, [esi]dst.R
00777 add al, col.R
00778 sbb cl, cl
00779 or al, cl
00780 mov [esi]dst.R, al
00781
00782 mov al, [esi]dst.G
00783 add al, col.G
00784 sbb cl, cl
00785 or al, cl
00786 mov [esi]dst.G, al
00787
00788 mov al, [esi]dst.B
00789 add al, col.B
00790 sbb cl, cl
00791 or al, cl
00792 mov [esi]dst.B, al
00793 }
00794 #else
00795
00796 dst->addRGBOnly(*dst, col);
00797 #endif
00798 }
00799 }
00800 }
00801
00802 else
00803 {
00804
00805
00806
00807
00808
00809 for(y=startY; y<endY; y++)
00810 {
00811 nverts= endX - startX;
00812
00813 vert= originVert + startX + y*Width;
00814 dst= originDst + startX + y*Width;
00815 for(;nverts>0; nverts--, vert++, dst++)
00816 {
00817 CVector dirToP= vert->Pos - pl.Pos;
00818 float dist= dirToP.norm();
00819 float OODist= 1.0f / dist;
00820 dirToP*= OODist;
00821
00822
00823 float attDist= (dist-pl.AttMax) * pl.OOAttDelta;
00824 fastClamp01(attDist);
00825
00826
00827 float diff= -(vert->Normal * dirToP);
00828 fastClamp01(diff);
00829
00830
00831 diff*= attDist;
00832 r= pl.R*diff;
00833 g= pl.G*diff;
00834 b= pl.B*diff;
00835
00836 CRGBA col;
00837 col.R= (uint8)OptFastFloor24(r);
00838 col.G= (uint8)OptFastFloor24(g);
00839 col.B= (uint8)OptFastFloor24(b);
00840
00841
00842 #ifdef NL_OS_WINDOWS
00843
00844 __asm
00845 {
00846 mov esi, dst
00847
00848 mov al, [esi]dst.R
00849 add al, col.R
00850 sbb cl, cl
00851 or al, cl
00852 mov [esi]dst.R, al
00853
00854 mov al, [esi]dst.G
00855 add al, col.G
00856 sbb cl, cl
00857 or al, cl
00858 mov [esi]dst.G, al
00859
00860 mov al, [esi]dst.B
00861 add al, col.B
00862 sbb cl, cl
00863 or al, cl
00864 mov [esi]dst.B, al
00865 }
00866 #else
00867
00868 dst->addRGBOnly(*dst, col);
00869 #endif
00870 }
00871 }
00872
00873
00874
00875
00876 }
00877
00878
00879 OptFastFloorEnd24();
00880
00881
00882
00883 _IsSrcTextureFullBlack= false;
00884 }
00885
00886
00887
00888 void CPatchDLMContext::compileLighting(TCompileType compType, CRGBA modulateCte)
00889 {
00890
00891 if(! (_IsSrcTextureFullBlack && _IsDstTextureFullBlack) )
00892 {
00893
00894 if(_LightMap.size()>0 && _DLMTexture)
00895 {
00896
00897 if(_IsSrcTextureFullBlack)
00898 {
00899
00900 _DLMTexture->fillRect(TextPosX, TextPosY, Width, Height, 0);
00901 }
00902
00903 else
00904 {
00905
00906 if(compType == ModulateTileColor)
00907 {
00908 nlassert(_Patch->TileColors.size()>=0);
00909 #ifdef NL_DLM_TILE_RES
00910
00911 uint16 *tileColor= (uint16*)(&_Patch->TileColors[0]);
00912 #else
00913 uint16 *tileColor= (uint16*)(&_LowResTileColors[0]);
00914 #endif
00915
00916
00917 _DLMTexture->modulateAndfillRect565(TextPosX, TextPosY, Width, Height, &_LightMap[0], tileColor);
00918 }
00919
00920 else if(compType == ModulateTextureFar)
00921 {
00922
00923 _DLMTexture->modulateAndfillRect8888(TextPosX, TextPosY, Width, Height, &_LightMap[0], &_TextureFar[0]);
00924 }
00925
00926 else if(compType == ModulateConstant)
00927 {
00928
00929 _DLMTexture->modulateConstantAndfillRect(TextPosX, TextPosY, Width, Height, &_LightMap[0], modulateCte);
00930 }
00931
00932 else
00933 {
00934
00935 _DLMTexture->copyRect(TextPosX, TextPosY, Width, Height, &_LightMap[0]);
00936 }
00937 }
00938 }
00939
00940
00941
00942 _IsDstTextureFullBlack= _IsSrcTextureFullBlack;
00943 }
00944 }
00945
00946
00947
00948 uint CPatchDLMContext::getMemorySize() const
00949 {
00950 uint size= sizeof(CPatchDLMContext);
00951 size+= _Vertices.size() * sizeof(CVertex);
00952 size+= _LightMap.size() * sizeof(CRGBA);
00953 size+= _Clusters.size() * sizeof(CCluster);
00954 size+= _TextureFar.size() * sizeof(CRGBA);
00955 #ifndef NL_DLM_TILE_RES
00956 size+= _LowResTileColors.size() * sizeof(uint16);
00957 #endif
00958
00959 return size;
00960 }
00961
00962
00963
00964 void CPatchDLMContext::computeTextureFar()
00965 {
00966
00967
00968 static vector<CRGBA> tileFars;
00969
00970 CTileFarBank &farBank= _Patch->getLandscape()->TileFarBank;
00971
00972 uint os= _Patch->getOrderS();
00973 uint ot= _Patch->getOrderT();
00974
00975 uint tfWidth= os*2+2;
00976 uint tfHeight= ot*2+2;
00977 uint tfSize= tfWidth * tfHeight;
00978 tileFars.resize(tfSize);
00979 CRGBA *dst= &tileFars[0];
00980
00981
00982 memset(dst, 0, tfSize*sizeof(CRGBA));
00983
00984
00985 uint x, y;
00986 for(y=0; y<ot; y++)
00987 {
00988 for(x=0;x<os;x++)
00989 {
00990
00991 CTileElement &tileElm= _Patch->Tiles[y*os + x];
00992
00993
00994 for(uint l=0; l<3;l++)
00995 {
00996 uint16 tileId= tileElm.Tile[0];
00997 if (tileId!=NL_TILE_ELM_LAYER_EMPTY)
00998 {
00999
01000 const CTileFarBank::CTileFar* pTile= farBank.getTile (tileId);
01001
01002 if(pTile && pTile->isFill (CTileFarBank::diffuse))
01003 {
01004
01005 sint nRot= tileElm.getTileOrient(l);
01006 bool is256x256;
01007 uint8 uvOff;
01008 tileElm.getTile256Info(is256x256, uvOff);
01009
01010
01011 const CRGBA *srcPixel= pTile->getPixels(CTileFarBank::diffuse, CTileFarBank::order1);
01012
01013 sint srcDeltaX;
01014 sint srcDeltaY;
01015 srcPixel= computeTileFarSrcDeltas(nRot, is256x256, uvOff, srcPixel, srcDeltaX, srcDeltaY);
01016
01017
01018 CRGBA *dstPixel= dst + (y*2+1)*tfWidth + x*2+1;
01019
01020 if(l==0)
01021 {
01022
01023 copyTileToTexture(srcPixel, srcDeltaX, srcDeltaY, dstPixel, tfWidth);
01024 }
01025 else
01026 {
01027
01028 blendTileToTexture(srcPixel, srcDeltaX, srcDeltaY, dstPixel, tfWidth);
01029 }
01030 }
01031 else
01032
01033 break;
01034 }
01035 else
01036
01037 break;
01038 }
01039 }
01040 }
01041
01042
01043
01044
01045
01046
01047
01048 y= tfHeight-1;
01049 for(x=1;x<tfWidth-1;x++)
01050 {
01051
01052 dst[0*tfWidth + x]= dst[1*tfWidth + x];
01053
01054 dst[y*tfWidth + x]= dst[(y-1)*tfWidth + x];
01055 }
01056
01057
01058 x= tfWidth-1;
01059 for(y=1;y<tfHeight-1;y++)
01060 {
01061
01062 dst[y*tfWidth + 0]= dst[y*tfWidth + 1];
01063
01064 dst[y*tfWidth + x]= dst[y*tfWidth + x-1];
01065 }
01066
01067
01068 x= tfWidth-1;
01069 y= tfHeight-1;
01070
01071 dst[0]= dst[1];
01072
01073 dst[x]= dst[x-1];
01074
01075 dst[y*tfWidth + 0]= dst[y*tfWidth + 1];
01076
01077 dst[y*tfWidth + x]= dst[y*tfWidth + x-1];
01078
01079
01080
01081
01082
01083 _TextureFar.resize(Width*Height);
01084 CRGBA *src= &tileFars[0];
01085 dst= &_TextureFar[0];
01086
01087
01088 for(y=0;y<Height;y++)
01089 {
01090 for(x=0;x<Width;x++, dst++)
01091 {
01092
01093 uint x2, y2;
01094 #ifdef NL_DLM_TILE_RES
01095 x2= x * 2;
01096 y2= y * 2;
01097 #else
01098
01099 x2= x * 4;
01100 y2= y * 4;
01101 #endif
01102
01103
01104 dst->avg4RGBOnly(src[y2*tfWidth + x2],
01105 src[y2*tfWidth + x2+1],
01106 src[(y2+1)*tfWidth + x2],
01107 src[(y2+1)*tfWidth + x2+1]);
01108 }
01109 }
01110
01111
01112
01113
01114 nlassert(_Patch->TileColors.size()>=0);
01115 #ifdef NL_DLM_TILE_RES
01116
01117 uint16 *tileColor= (uint16*)(&_Patch->TileColors[0]);
01118 #else
01119 uint16 *tileColor= (uint16*)(&_LowResTileColors[0]);
01120 #endif
01121
01122
01123 dst= &_TextureFar[0];
01124 for(sint n= Width*Height; n>0; n--, dst++, tileColor++)
01125 {
01126 uint16 tc= *tileColor;
01127
01128 dst->R= ( (tc>>11) * dst->R)>>5;
01129
01130 dst->G= (((tc>>5)&63) * dst->G)>>6;
01131
01132 dst->B= ( (tc&31) * dst->B)>>5;
01133 }
01134
01135 }
01136
01137
01138
01139
01140 const CRGBA *CPatchDLMContext::computeTileFarSrcDeltas(sint nRot, bool is256x256, uint8 uvOff, const CRGBA *srcPixel, sint &srcDeltaX, sint &srcDeltaY)
01141 {
01142
01143
01144
01145 uint tileSize= 2;
01146
01147
01148 sint sourceSize;
01149
01150
01151 uint sourceOffset=0;
01152
01153
01154 if (is256x256)
01155 {
01156
01157 if (uvOff&0x02)
01158 sourceOffset+=tileSize;
01159
01160
01161 if ((uvOff==1)||(uvOff==2))
01162 sourceOffset+=2*tileSize*tileSize;
01163
01164
01165 sourceSize=tileSize<<1;
01166 }
01167 else
01168 {
01169
01170 sourceSize=tileSize;
01171 }
01172
01173
01174 switch (nRot)
01175 {
01176 case 0:
01177
01178 srcPixel= srcPixel+sourceOffset;
01179
01180
01181 srcDeltaX=1;
01182 srcDeltaY=sourceSize;
01183 break;
01184 case 1:
01185 {
01186
01187 uint newOffset=sourceOffset+(tileSize-1);
01188 srcPixel=srcPixel+newOffset;
01189
01190
01191 srcDeltaX=sourceSize;
01192 srcDeltaY=-1;
01193 }
01194 break;
01195 case 2:
01196 {
01197
01198 uint newOffset=sourceOffset+(tileSize-1)*sourceSize+tileSize-1;
01199 srcPixel=srcPixel+newOffset;
01200
01201
01202 srcDeltaX=-1;
01203 srcDeltaY=-sourceSize;
01204 }
01205 break;
01206 case 3:
01207 {
01208
01209 uint newOffset=sourceOffset+(tileSize-1)*sourceSize;
01210 srcPixel=srcPixel+newOffset;
01211
01212
01213 srcDeltaX=-sourceSize;
01214 srcDeltaY=1;
01215 }
01216 break;
01217 }
01218
01219 return srcPixel;
01220 }
01221
01222
01223
01224 void CPatchDLMContext::copyTileToTexture(const CRGBA *srcPixel, sint srcDeltaX, sint srcDeltaY, CRGBA *dstPixel, uint dstStride)
01225 {
01226
01227
01228
01229 dstPixel[0]= srcPixel[0];
01230 dstPixel[1]= srcPixel[srcDeltaX];
01231
01232 dstPixel[0+dstStride]= srcPixel[srcDeltaY];
01233 dstPixel[1+dstStride]= srcPixel[srcDeltaY+srcDeltaX];
01234 }
01235
01236
01237 void CPatchDLMContext::blendTileToTexture(const CRGBA *srcPixel, sint srcDeltaX, sint srcDeltaY, CRGBA *dstPixel, uint dstStride)
01238 {
01239
01240 CRGBA *dst;
01241 CRGBA src;
01242
01243
01244 dst= &dstPixel[0]; src= srcPixel[0];
01245 dst->blendFromuiRGBOnly(*dst, src, src.A);
01246
01247 dst= &dstPixel[1]; src= srcPixel[srcDeltaX];
01248 dst->blendFromuiRGBOnly(*dst, src, src.A);
01249
01250
01251 dst= &dstPixel[0+dstStride]; src= srcPixel[srcDeltaY];
01252 dst->blendFromuiRGBOnly(*dst, src, src.A);
01253
01254 dst= &dstPixel[1+dstStride]; src= srcPixel[srcDeltaY+srcDeltaX];
01255 dst->blendFromuiRGBOnly(*dst, src, src.A);
01256 }
01257
01258
01259 }