From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- .../doxygen/nel/patchdlm__context_8cpp-source.html | 1328 ++++++++++++++++++++ 1 file changed, 1328 insertions(+) create mode 100644 docs/doxygen/nel/patchdlm__context_8cpp-source.html (limited to 'docs/doxygen/nel/patchdlm__context_8cpp-source.html') diff --git a/docs/doxygen/nel/patchdlm__context_8cpp-source.html b/docs/doxygen/nel/patchdlm__context_8cpp-source.html new file mode 100644 index 00000000..abd02197 --- /dev/null +++ b/docs/doxygen/nel/patchdlm__context_8cpp-source.html @@ -0,0 +1,1328 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

patchdlm_context.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2000-2002 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+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         // copy color
+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         // Copy Spot/Pos/Dir.
+00061         IsSpot= pl.getType() == CPointLight::SpotLight;
+00062         Pos= pl.getPosition();
+00063         Dir= pl.getSpotDirection();
+00064         
+00065         // compute spot params
+00066         if(IsSpot)
+00067         {
+00068                 CosMax= cosf(pl.getSpotAngleBegin());
+00069                 CosMin= cosf(pl.getSpotAngleEnd());
+00070         }
+00071         else
+00072         {
+00073                 // with tesse Values, we have always (cosSpot-CosMin) * OOCosDelta > 1.0f
+00074                 CosMax= -1;
+00075                 CosMin= -2;
+00076         }
+00077         OOCosDelta= 1.f / (CosMax-CosMin);
+00078 
+00079         // compute att params
+00080         AttMax= pl.getAttenuationEnd();
+00081         AttMin= pl.getAttenuationBegin();
+00082         // infinite pointLight?
+00083         if(AttMax==0)
+00084         {
+00085                 AttMax= maxAttEnd;
+00086                 AttMin= maxAttEnd*0.99f;
+00087         }
+00088         // To big pointLigt?
+00089         else if(AttMax>maxAttEnd)
+00090         {
+00091                 AttMax= maxAttEnd;
+00092                 AttMin= min(AttMin, maxAttEnd*0.99f);
+00093         }
+00094         // compile distance
+00095         OOAttDelta= 1.f / (AttMin-AttMax);
+00096 
+00097 
+00098         // Compute bounding sphere.
+00099         // If not a spot or if angleMin>Pi/2
+00100         if(!IsSpot || CosMin<0)
+00101         {
+00102                 // Take sphere of pointlight sphere
+00103                 BSphere.Center= Pos;
+00104                 BSphere.Radius= AttMax;
+00105                 // The bbox englobe the sphere.
+00106                 BBox.setCenter(Pos);
+00107                 BBox.setHalfSize(CVector(AttMax, AttMax, AttMax));
+00108         }
+00109         else
+00110         {
+00111                 // Compute BSphere.
+00112                 //==============
+00113 
+00114                 // compute sinus of AngleMin
+00115                 float   sinMin= sqrtf(1-sqr(CosMin));
+00116 
+00117                 // Test 2 centers: Center of radius along Dir: Pos+Dir*AttMax/2, and intersection of end cone with line (Pos,Dir)
+00118                 // Don't know why but I think they are sufficiently good :)
+00119                 // See below for computing of those centers.
+00120 
+00121                 /* compute radius of each sphere by taking max of 3 distances: distance to spotLight center, distance
+00122                         to spotLight forward extremity, and distance to spotLight circle interstion Cone/Sphere. (named DCCS)
+00123                         NB: Do the compute with radius=1 at first, then multiply later.
+00124                 */
+00125                 float   radius1= 0.5f;          // =max(0.5, 0.5); max distance to spot center and extremity center :)
+00126                 // for distance DCCS, this is the hypothenuse of (cosMin-0.5) + sinMin.
+00127                 float   dccs= sqrtf( sqr(CosMin-0.5f) + sqr(sinMin));
+00128                 // take the bigger.
+00129                 radius1= max(radius1, dccs );
+00130 
+00131                 // Same reasoning for center2.
+00132                 float   radius2= max(CosMin, 1-CosMin); // max distance to spot center and extremity center :)
+00133                 // for distance DCCS, it is simply sinMin!!
+00134                 dccs= sinMin;
+00135                 // take the bigger.
+00136                 radius2= max(radius2, dccs );
+00137 
+00138 
+00139                 // Then take the center which gives the smaller sphere
+00140                 if(radius1<radius2)
+00141                 {
+00142                         BSphere.Center= Pos + (Dir*0.5f*AttMax);
+00143                         // radius1 E [0,1], must take real size.
+00144                         BSphere.Radius= radius1 * AttMax;
+00145                 }
+00146                 else
+00147                 {
+00148                         BSphere.Center= Pos + (Dir*CosMin*AttMax);
+00149                         // radius2 E [0,1], must take real size.
+00150                         BSphere.Radius= radius2 * AttMax;
+00151                 }
+00152 
+00153 
+00154                 // Compute BBox.
+00155                 //==============
+00156                 
+00157                 // just take bbox of the sphere, even if not optimal.
+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         // By default there is crash in textures
+00179         _IsSrcTextureFullBlack= false;
+00180         _IsDstTextureFullBlack= false;
+00181 }
+00182 
+00183 
+00184 // ***************************************************************************
+00185 CPatchDLMContext::~CPatchDLMContext()
+00186 {
+00187         // release the lightmap in the texture
+00188         if(_DLMTexture)
+00189         {
+00190                 _DLMTexture->releaseLightMap(TextPosX, TextPosY);
+00191         }
+00192         // exit
+00193         _Patch= NULL;
+00194         _DLMTexture= NULL;
+00195 
+00196         // remove it from list.
+00197         if(_DLMContextList)
+00198                 _DLMContextList->remove(this);
+00199 }
+00200 
+00201 
+00202 // ***************************************************************************
+00203 #ifdef NL_DLM_TILE_RES
+00204 // if tileRes defined, still start to clip at tessBlockLevel.
+00205 #define NL_DLM_CLIP_FACTOR              2
+00206 #else
+00207 // start to clip at tessBlockLevel (same as dlm map precision)
+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         // keep info on patch/landscape.
+00221         _Patch= patch;
+00222         _DLMTexture= textureDLM;
+00223         // append to the list.
+00224         _DLMContextList= ctxList;
+00225         _DLMContextList->append(this);
+00226 
+00227         // Get Texture Size info; 
+00228 #ifdef NL_DLM_TILE_RES
+00229         // get coord at cornes of tiles
+00230         Width= (_Patch->getOrderS())+1;
+00231         Height= (_Patch->getOrderT())+1;
+00232 #else
+00233         // get coord at cornes of tessBlocks
+00234         Width= (_Patch->getOrderS()/2)+1;
+00235         Height= (_Patch->getOrderT()/2)+1;
+00236 #endif
+00237 
+00238         // Allocate space in texture
+00239         if(!_DLMTexture->createLightMap(Width, Height, TextPosX, TextPosY))
+00240         {
+00241                 // Mark as not allocated.
+00242                 // NB: the context still work with NULL _DLMTexture, but do nothing (excpetionnal case)
+00243                 _DLMTexture= NULL;
+00244         }
+00245 
+00246         // If the lightmap is correclty allocated in the global texture, compute UVBias.
+00247         if(_DLMTexture)
+00248         {
+00249                 // Compute patch UV matrix from pixels. Must map to center of pixels.
+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                 // Build UVBias such that the UVs point to Black
+00258                 // NB: TextureDLM ensure that point (MaxX,MaxY) of texture is black.
+00259                 DLMUScale= 0;
+00260                 DLMVScale= 0;
+00261                 DLMUBias= 1;
+00262                 DLMVBias= 1;
+00263         }
+00264 
+00265         // TestYoyo: to see lightmap usage in the big texture
+00266         /*DLMUScale= _Patch->getOrderS();
+00267         DLMVScale= _Patch->getOrderT();
+00268         DLMUBias= 0;
+00269         DLMVBias= 0;*/
+00270 
+00271 
+00272         // Bound 8bits UV for Vegetable. This is to ensure vegetable Dlm UVs won't peek in neighbor lightmaps.
+00273         sint    tmpU, tmpV;
+00274         // Bound U minimum
+00275         tmpU= (sint)ceil ( (DLMUBias) * 255 );
+00276         clamp(tmpU, 0, 255);
+00277         MinU8= tmpU;
+00278         // Bound U maximum
+00279         tmpU= (sint)floor( (DLMUBias+DLMUScale) * 255 );
+00280         clamp(tmpU, (sint)MinU8, 255);
+00281         MaxU8= tmpU;
+00282         // Bound V minimum
+00283         tmpV= (sint)ceil ( (DLMVBias) * 255 );
+00284         clamp(tmpV, 0, 255);
+00285         MinV8= tmpV;
+00286         // Bound V maximum
+00287         tmpV= (sint)floor( (DLMVBias+DLMVScale) * 255 );
+00288         clamp(tmpV, (sint)MinV8, 255);
+00289         MaxV8= tmpV;
+00290 
+00291 
+00292         // Allocate RAM Lightmap
+00293         _LightMap.resize(Width*Height);
+00294 
+00295         // generate Vertices: pos and normals
+00296         _Vertices.resize(Width*Height);
+00297         float   s, t;
+00298         float   ds= 1.0f / (Width-1);
+00299         float   dt= 1.0f / (Height-1);
+00300         // eval all the patch.
+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                         // NB: use the bezier patch, and don't take Noise into account, for speed reason.
+00310                         CBezierPatch    *bpatch= _Patch->unpackIntoCache();
+00311                         // Eval pos.
+00312                         vert.Pos= bpatch->eval(s, t);
+00313                         // Eval Normal.
+00314                         vert.Normal= bpatch->evalNormal(s, t);
+00315                 }
+00316         }
+00317 
+00318         // Build bounding Spheres QuadTree
+00319         //============
+00320 
+00321         // Size of the cluster array (at level 0)
+00322         uint    bsx, bsy;
+00323 #ifdef NL_DLM_TILE_RES
+00324         // level 0 is at tile level.
+00325         bsx= max(1, (_Patch->getOrderS())/NL_DLM_CLIP_FACTOR );
+00326         bsy= max(1, (_Patch->getOrderT())/NL_DLM_CLIP_FACTOR );
+00327 #else
+00328         // level 0 is at tessBlock level.
+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         // resize bboxes for level 0.
+00334         static  vector<CAABBox>         tmpBBoxes[NL_DLM_CLIP_NUM_LEVEL];
+00335         tmpBBoxes[0].resize(bsx * bsy);
+00336 
+00337         // Extend all leaves clusters BBoxes with patch coordinates
+00338         for(y=0;y<bsy;y++)
+00339         {
+00340                 // For Y, compute how many patch Positions used to extend bbox.
+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                         // For X, compute how many patch Positions used to extend bbox.
+00346                         uint    beginX= x*NL_DLM_CLIP_FACTOR;
+00347                         uint    endX= min((x+1)*NL_DLM_CLIP_FACTOR+1, Width);
+00348                         // Build a bbox.
+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                         // Set the BBox info.
+00359                         tmpBBoxes[0][y*bsx + x]= bbox;
+00360                 }
+00361         }
+00362 
+00363         // build parent BSpheres for quadTree hierarchy
+00364         uint    curLevel= 0;
+00365         uint    nextLevel= 1;
+00366         uint    nextBsx= max(1U, bsx/2);
+00367         uint    nextBsy= max(1U, bsy/2);
+00368         // the number of cluster Sons, and descendants this cluster level owns.
+00369         uint    tmpClusterNumToSkip[NL_DLM_CLIP_NUM_LEVEL];
+00370         // width for this cluster level.
+00371         uint    tmpClusterWidth[NL_DLM_CLIP_NUM_LEVEL];
+00372         // Number of sons per line/column
+00373         uint    tmpClusterWSon[NL_DLM_CLIP_NUM_LEVEL];
+00374         uint    tmpClusterHSon[NL_DLM_CLIP_NUM_LEVEL];
+00375         // Fill level 0 info
+00376         tmpClusterNumToSkip[0]= 0;
+00377         tmpClusterWidth[0]= bsx;
+00378         tmpClusterWSon[0]= 0;
+00379         tmpClusterHSon[0]= 0;
+00380         uint    finalClusterSize= bsx * bsy;
+00381 
+00382         // If the next level has 1x1 cases, it is not usefull (since same sphere as entire Patch)
+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                 // compute cluster level info.
+00390                 tmpClusterWidth[nextLevel]= nextBsx;
+00391                 tmpClusterWSon[nextLevel]= wSon;
+00392                 tmpClusterHSon[nextLevel]= hSon;
+00393                 // NB: level 0 has 0 sons to skip, hence level1 must skip (1+0)*4= 4  (wSon==hSon==2)
+00394                 // level2 must skip (1+4)*4= 20    (wSon==hSon==2)
+00395                 tmpClusterNumToSkip[nextLevel]= (1+tmpClusterNumToSkip[curLevel]) * wSon * hSon;
+00396 
+00397                 // alloc bboxes.
+00398                 tmpBBoxes[nextLevel].resize(nextBsx * nextBsy);
+00399 
+00400                 // For all cluster of upper level, build bb, as union of finers clusters
+00401                 for(y=0;y<nextBsy;y++)
+00402                 {
+00403                         for(x=0;x<nextBsx;x++)
+00404                         {
+00405                                 // compute coordinate in curLevel tmpBBoxes to look
+00406                                 uint    x2= x*wSon;
+00407                                 uint    y2= y*hSon;
+00408                                 // Build a bbox for 4 (or 2) children clusters
+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                                         // final father bbox.
+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                                         // final father bbox.
+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                                         // final father bbox.
+00434                                         tmpBBoxes[nextLevel][y*nextBsx + x]= bbox1;
+00435                                 }
+00436                                 else
+00437                                         // impossible...
+00438                                         nlstop;
+00439                         }
+00440                 }
+00441 
+00442                 // upper level.
+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         // Resize clusters with size according to all levels
+00453         _Clusters.resize(finalClusterSize);
+00454         uint    iDstCluster= 0;
+00455 
+00456         // Fill cluster hierarchy, in _Clusters.
+00457         uint    numLevels= nextLevel;
+00458         // NB: the principle is recursive, but it is "iterated", with a stack-like: tmpClusterX and tmpClusterY;
+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         // we start at curLevel (the highest Level), and we must fill all the squares of this level
+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         // while the "root" level is not pop
+00473         while(curLevel < numLevels)
+00474         {
+00475                 // If we ended with this level (all lines done).
+00476                 if(tmpClusterY[curLevel] >= tmpClusterYMax[curLevel])
+00477                 {
+00478                         // Ok, finished with this level, pop up.
+00479                         curLevel++;
+00480                         // skip.
+00481                         continue;
+00482                 }
+00483 
+00484                 nlassert(iDstCluster<_Clusters.size());
+00485 
+00486                 // get the bbox from current position.
+00487                 CAABBox bbox= tmpBBoxes[curLevel][ tmpClusterY[curLevel] * tmpClusterWidth[curLevel] + tmpClusterX[curLevel] ];
+00488                 // Fill _Clusters for this square.
+00489                 _Clusters[iDstCluster].BSphere.Center= bbox.getCenter(); 
+00490                 _Clusters[iDstCluster].BSphere.Radius= bbox.getRadius(); 
+00491                 // If leaf level, fill special info
+00492                 if(curLevel == 0)
+00493                 {
+00494                         _Clusters[iDstCluster].NSkips= 0;
+00495                         _Clusters[iDstCluster].X= tmpClusterX[0];
+00496                         _Clusters[iDstCluster].Y= tmpClusterY[0];
+00497                 }
+00498                 // else, set total number of sons to skips if "invisible"
+00499                 else
+00500                         _Clusters[iDstCluster].NSkips= tmpClusterNumToSkip[curLevel];
+00501 
+00502                 // next dst cluster
+00503                 iDstCluster ++;
+00504 
+00505 
+00506                 // If not Leaf level, recurs. First pass, use curLevel params (tmpClusterX...)
+00507                 if(curLevel > 0)
+00508                 {
+00509                         // compute info for next level.
+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                         // begin iteration of child level
+00515                         tmpClusterX[curLevel-1]= tmpClusterXMin[curLevel-1];
+00516                         tmpClusterY[curLevel-1]= tmpClusterYMin[curLevel-1];
+00517                 }
+00518 
+00519 
+00520                 // next square for this level
+00521                 tmpClusterX[curLevel]++;
+00522                 // if ended for X.
+00523                 if(tmpClusterX[curLevel] >= tmpClusterXMax[curLevel])
+00524                 {
+00525                         // reset X.
+00526                         tmpClusterX[curLevel]= tmpClusterXMin[curLevel];
+00527                         // next line.
+00528                         tmpClusterY[curLevel]++;
+00529                 }
+00530 
+00531 
+00532                 // If not Leaf level, recurs. Second pass, after tmpClusterX and tmpClusterY of curLevel are changed
+00533                 if(curLevel > 0)
+00534                 {
+00535                         // descend in hierarchy. (recurs)
+00536                         curLevel--;
+00537                 }
+00538 
+00539         }
+00540 
+00541         // All dst clusters must have been filled
+00542         nlassert(iDstCluster == _Clusters.size());
+00543 
+00544 
+00545         // PreProcess Patch TileColors.
+00546         //============
+00547         // Verify that a CTileColor is nothing more than a 565 color.
+00548         nlassert(sizeof(CTileColor)==sizeof(uint16));
+00549 #ifndef NL_DLM_TILE_RES
+00550 
+00551         // retrieve patch tileColor pointer.
+00552         nlassert(_Patch->TileColors.size()>0);
+00553         CTileColor      *tileColor= &_Patch->TileColors[0];
+00554 
+00555         // skip 1 tiles colors per column and per row
+00556         uint            wTileColor= _Patch->getOrderS()+1;
+00557         CTileColor      *tcOrigin= tileColor;
+00558         // alloc _LowResTileColors at same resolution than lightmap
+00559         _LowResTileColors.resize(Width*Height);
+00560         uint16  *dstLRtc= &_LowResTileColors[0];
+00561 
+00562         // For all lines of dst.
+00563         for(y=0;y<Height;y++)
+00564         {
+00565                 // tileColor start of line.
+00566                 tileColor= tcOrigin + y*2* wTileColor;
+00567                 sint    npix= Width;
+00568                 // for all pixels at corner of tessBlock.
+00569                 for(;npix>0; npix--, tileColor+=2, dstLRtc++)
+00570                 {
+00571                         *dstLRtc= tileColor->Color565;
+00572                 }
+00573 
+00574         }
+00575 #endif
+00576 
+00577 
+00578         // compute the TextureFar used for Far dynamic lightmaping.
+00579         //============
+00580         // NB: simpler to compute it at generate() time, even if not necessarly needed for near
+00581         computeTextureFar();
+00582 
+00583 
+00584         // fill texture with Black
+00585         //============
+00586         clearLighting();
+00587 
+00588         return true;
+00589 }
+00590 
+00591 // ***************************************************************************
+00592 void                    CPatchDLMContext::clearLighting()
+00593 {
+00594         // If the srcTexture is not already black.
+00595         if(!_IsSrcTextureFullBlack)
+00596         {
+00597                 // Reset Lightmap with black.
+00598                 uint    count= _LightMap.size();
+00599                 if(count>0)
+00600                 {
+00601                         memset(&_LightMap[0], 0, count * sizeof(CRGBA));
+00602                 }
+00603 
+00604                 // Now the src lightmap is fully black
+00605                 _IsSrcTextureFullBlack= true;
+00606         }
+00607 }
+00608 
+00609 
+00610 // ***************************************************************************
+00611 
+00612 // TestYoyo: I thought this code was better, but actually, this is not the case
+00613 /*
+00614 static  float   NL3D_Val1= 1.f;
+00615 inline void     __stdcall fastClamp01(float &x)
+00616 {
+00617         __asm
+00618         {
+00619                 mov esi, x
+00620                 mov eax, [esi]
+00621 
+00622                 // clamp to 0.
+00623                 cmp eax, 0x80000001             // set carry if sign bit is set.
+00624                 sbb ecx, ecx                    // if attDist is negative, ecx==0 , else 0xFFFFFFFF.
+00625                 and eax, ecx                    // if attDist is negative, eax=0, else unchanged
+00626 
+00627                 // clamp eax to 1 (NB: now we are sure eax>=0).
+00628                 cmp     eax, NL3D_Val1          // set carry if < Val1.
+00629                 sbb     ecx, ecx                        // if < Val1, ecx==0xFFFFFFFF, else 0.
+00630                 and     eax, ecx                        // if < Val1, ecx= eax, else ecx=0
+00631                 not     ecx
+00632                 and     ecx, NL3D_Val1          // if > Val1, ecx== Val1, else ecx= 0.
+00633                 add     eax, ecx                        // finally, eax= val clamped to 1.
+00634 
+00635                 // store.
+00636                 mov [esi], eax
+00637         }
+00638 }*/
+00639 
+00640 // faster to do a simple clamp ???
+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         // precise clip: parse the quadTree of sphere
+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                 // If the sphere intersect pl, 
+00669                 if(_Clusters[i].BSphere.intersect(pl.BSphere) )
+00670                 {
+00671                         // if this cluster is a leaf, extend start/end
+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                         // go to next cluster (a brother, a parent or a son)
+00682                         i++;
+00683                 }
+00684                 else
+00685                 {
+00686                         // if this cluster is a leaf, just go to next cluster (a parent or a brother)
+00687                         if(_Clusters[i].NSkips==0)
+00688                                 i++;
+00689                         // else, go to next brother or parent (NSkips say how to go)
+00690                         else
+00691                                 i+= _Clusters[i].NSkips;
+00692                 }
+00693         }
+00694         // if never intersect, just quit.
+00695         if(startX==0xFFFFFFFF)
+00696                 return;
+00697 
+00698         // get vertices in array to process.
+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         // TestYoyo only.
+00705         /*extern uint YOYO_LandDLCount;
+00706         YOYO_LandDLCount+= (endX - startX) * (endY - startY);*/
+00707         
+00708         // process all vertices
+00709         //================
+00710         float   r,g,b;
+00711         CRGBA   *dst= &_LightMap[0];
+00712         CVertex         *originVert= vert;
+00713         CRGBA           *originDst= dst;
+00714 
+00715         // TestYoyo: finally, precache does not seems to impact final result.
+00716         // precache loading, for better cache use. NB: precache the entire line, ignoring clip result.
+00717         // Precache only if interesting.
+00718         /*if( (endX - startX)*4>=Width && (endY-startY)>=2)
+00719         {
+00720                 vert= originVert + startY*Width;
+00721                 dst= originDst + startY*Width;
+00722                 uint    nPixelLine= (endY-startY)*Width;
+00723                 CFastMem::precacheBest(vert, nPixelLine * sizeof(CVertex));
+00724                 CFastMem::precacheBest(dst, nPixelLine * sizeof(CRGBA));
+00725         }*/
+00726 
+00727         // Start 24 precision, for faster compute.
+00728         OptFastFloorBegin24();
+00729 
+00730         // If the pointLight is a spot, compute is more complex/slower
+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                                 // compute cos for pl. attenuation
+00746                                 float   cosSpot= dirToP * pl.Dir;
+00747                                 float   attSpot= (cosSpot-pl.CosMin) * pl.OOCosDelta;
+00748                                 fastClamp01(attSpot);
+00749 
+00750                                 // distance attenuation
+00751                                 float   attDist= (dist-pl.AttMax) * pl.OOAttDelta;
+00752                                 fastClamp01(attDist);
+00753 
+00754                                 // compute diffuse lighting
+00755                                 float   diff= -(vert->Normal * dirToP);
+00756                                 fastClamp01(diff);
+00757                                 
+00758                                 // compute colors.
+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                                 // add to map.
+00770 #ifdef NL_OS_WINDOWS
+00771                                 // Fast AddClamp.
+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                                 // add and clamp to map.
+00796                                 dst->addRGBOnly(*dst, col);
+00797 #endif
+00798                         }
+00799                 }
+00800         }
+00801         // else, pointLight with no Spot cone attenuation
+00802         else
+00803         {
+00804                 // TestYoyo
+00805                 /*extern        void    YOYO_startDLMItCount();
+00806                 YOYO_startDLMItCount();*/
+00807 
+00808                 // Compute lightmap pixels of interest 
+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                                 // distance attenuation
+00823                                 float   attDist= (dist-pl.AttMax) * pl.OOAttDelta;
+00824                                 fastClamp01(attDist);
+00825 
+00826                                 // compute diffuse lighting
+00827                                 float   diff= -(vert->Normal * dirToP);
+00828                                 fastClamp01(diff);
+00829                                 
+00830                                 // compute colors.
+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                                 // add to map.
+00842 #ifdef NL_OS_WINDOWS
+00843                                 // Fast AddClamp.
+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                                 // add and clamp to map.
+00868                                 dst->addRGBOnly(*dst, col);
+00869 #endif
+00870                         }
+00871                 }
+00872 
+00873                 // TestYoyo
+00874                 /*extern        void    YOYO_endDLMItCount();
+00875                 YOYO_endDLMItCount();*/
+00876         }
+00877 
+00878         // Stop 24 bit precision
+00879         OptFastFloorEnd24();
+00880 
+00881         // Src texture is modified, hence it can't be black.
+00882         //==============
+00883         _IsSrcTextureFullBlack= false;
+00884 }
+00885 
+00886 
+00887 // ***************************************************************************
+00888 void                    CPatchDLMContext::compileLighting(TCompileType compType, CRGBA modulateCte)
+00889 {
+00890         // If srcTexture is full black, and if dst texture is already full black too, don't need to update dst texture
+00891         if(! (_IsSrcTextureFullBlack && _IsDstTextureFullBlack) )
+00892         {
+00893                 // if lightMap allocated
+00894                 if(_LightMap.size()>0 && _DLMTexture)
+00895                 {
+00896                         // If the srcTexture is full black (ie no pointLight influence touch it), 
+00897                         if(_IsSrcTextureFullBlack)
+00898                         {
+00899                                 // reset the texture to full black.
+00900                                 _DLMTexture->fillRect(TextPosX, TextPosY, Width, Height, 0);
+00901                         }
+00902                         // else the srcTexture is not full black (ie some pointLight influence touch it), 
+00903                         else
+00904                         {
+00905                                 // if must modulate with tileColor
+00906                                 if(compType == ModulateTileColor)
+00907                                 {
+00908                                         nlassert(_Patch->TileColors.size()>=0);
+00909                                         #ifdef NL_DLM_TILE_RES
+00910                                         // retrieve userColor pointer.
+00911                                         uint16  *tileColor= (uint16*)(&_Patch->TileColors[0]);
+00912                                         #else
+00913                                         uint16  *tileColor= (uint16*)(&_LowResTileColors[0]);
+00914                                         #endif
+00915 
+00916                                         // modulate and fill dest.
+00917                                         _DLMTexture->modulateAndfillRect565(TextPosX, TextPosY, Width, Height, &_LightMap[0], tileColor);
+00918                                 }
+00919                                 // else if must modulate with textureFar
+00920                                 else if(compType == ModulateTextureFar)
+00921                                 {
+00922                                         // modulate and fill dest.
+00923                                         _DLMTexture->modulateAndfillRect8888(TextPosX, TextPosY, Width, Height, &_LightMap[0], &_TextureFar[0]);
+00924                                 }
+00925                                 // else if must modulate with constante
+00926                                 else if(compType == ModulateConstant)
+00927                                 {
+00928                                         // modulate and fill dest.
+00929                                         _DLMTexture->modulateConstantAndfillRect(TextPosX, TextPosY, Width, Height, &_LightMap[0], modulateCte);
+00930                                 }
+00931                                 // else, no Modulate.
+00932                                 else
+00933                                 {
+00934                                         // just copy lightmap to texture
+00935                                         _DLMTexture->copyRect(TextPosX, TextPosY, Width, Height, &_LightMap[0]);
+00936                                 }
+00937                         }
+00938                 }
+00939 
+00940 
+00941                 // copy full black state
+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         // First compute Far at order1 Level (ie 2x2 pixels per tiles).
+00967         //==================
+00968         static  vector<CRGBA>   tileFars;
+00969         // Get the FarBank from landscape.
+00970         CTileFarBank    &farBank= _Patch->getLandscape()->TileFarBank;
+00971         // size of the texture.
+00972         uint    os= _Patch->getOrderS();
+00973         uint    ot= _Patch->getOrderT();
+00974         // resize tmp texture. keep a border of 1 pixel around this texture (for average with border)
+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         // default: fill dst with black (for possible non-existing tiles).
+00982         memset(dst, 0, tfSize*sizeof(CRGBA));
+00983 
+00984         // For all tiles.
+00985         uint    x, y;
+00986         for(y=0; y<ot; y++)
+00987         {
+00988                 for(x=0;x<os;x++)
+00989                 {
+00990                         // get the tile from patch.
+00991                         CTileElement    &tileElm= _Patch->Tiles[y*os + x];
+00992 
+00993                         // For all layers
+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                                         // Get the read only pointer on the far tile
+01000                                         const CTileFarBank::CTileFar*   pTile= farBank.getTile (tileId);
+01001                                         // if exist.
+01002                                         if(pTile && pTile->isFill (CTileFarBank::diffuse))
+01003                                         {
+01004                                                 // get tile element information.
+01005                                                 sint    nRot= tileElm.getTileOrient(l);
+01006                                                 bool    is256x256;
+01007                                                 uint8   uvOff;
+01008                                                 tileElm.getTile256Info(is256x256, uvOff);
+01009 
+01010                                                 // compute src pixel
+01011                                                 const CRGBA     *srcPixel= pTile->getPixels(CTileFarBank::diffuse, CTileFarBank::order1);
+01012                                                 // compute src info, for this tile rot and 256x256 context.
+01013                                                 sint srcDeltaX;
+01014                                                 sint srcDeltaY;
+01015                                                 srcPixel= computeTileFarSrcDeltas(nRot, is256x256, uvOff, srcPixel, srcDeltaX, srcDeltaY);
+01016 
+01017                                                 // compute dst coordinate. start writing at pixel (1,1)
+01018                                                 CRGBA   *dstPixel= dst + (y*2+1)*tfWidth + x*2+1;
+01019 
+01020                                                 if(l==0)
+01021                                                 {
+01022                                                         // copy the tile content to the texture.
+01023                                                         copyTileToTexture(srcPixel, srcDeltaX, srcDeltaY, dstPixel, tfWidth);
+01024                                                 }
+01025                                                 else
+01026                                                 {
+01027                                                         // blend the tile content to the texture.
+01028                                                         blendTileToTexture(srcPixel, srcDeltaX, srcDeltaY, dstPixel, tfWidth);
+01029                                                 }
+01030                                         }
+01031                                         else
+01032                                                 // go to next tile.
+01033                                                 break;
+01034                                 }
+01035                                 else
+01036                                         // go to next tile.
+01037                                         break;
+01038                         }
+01039                 }
+01040         }
+01041 
+01042         /* copy borders pixels from border of current patch
+01043                 NB: this is not correct, but visually sufficient.
+01044                 To look on neighbor would be more complex.
+01045         */
+01046 
+01047         // copy lines up and down.
+01048         y= tfHeight-1;
+01049         for(x=1;x<tfWidth-1;x++)
+01050         {
+01051                 // copy line 0 from line 1.
+01052                 dst[0*tfWidth + x]= dst[1*tfWidth + x];
+01053                 // copy last line from last line-1.
+01054                 dst[y*tfWidth + x]= dst[(y-1)*tfWidth + x];
+01055         }
+01056 
+01057         // copy column left and right
+01058         x= tfWidth-1;
+01059         for(y=1;y<tfHeight-1;y++)
+01060         {
+01061                 // copy column 0 from column 1.
+01062                 dst[y*tfWidth + 0]= dst[y*tfWidth + 1];
+01063                 // copy last column from last column-1.
+01064                 dst[y*tfWidth + x]= dst[y*tfWidth + x-1];
+01065         }
+01066 
+01067         // copy 4 corners
+01068         x= tfWidth-1;
+01069         y= tfHeight-1;
+01070         // top-left corner
+01071         dst[0]= dst[1];
+01072         // top-right corner
+01073         dst[x]= dst[x-1];
+01074         // bottom-left corner
+01075         dst[y*tfWidth + 0]= dst[y*tfWidth + 1];
+01076         // bottom-right corner
+01077         dst[y*tfWidth + x]= dst[y*tfWidth + x-1];
+01078 
+01079 
+01080         // Average to DLM resolution (ie OrderS+1, OrderT+1)
+01081         //==================
+01082         // resize _TextureFar.
+01083         _TextureFar.resize(Width*Height);
+01084         CRGBA   *src= &tileFars[0];
+01085         dst= &_TextureFar[0];
+01086 
+01087         // for all pixels of dst texture.
+01088         for(y=0;y<Height;y++)
+01089         {
+01090                 for(x=0;x<Width;x++, dst++)
+01091                 {
+01092                         // compute coordinate in tileFars.
+01093                         uint    x2, y2;
+01094 #ifdef  NL_DLM_TILE_RES
+01095                         x2= x * 2;
+01096                         y2= y * 2;
+01097 #else
+01098                         // easiest method: sample every 2 tiles.
+01099                         x2= x * 4;
+01100                         y2= y * 4;
+01101 #endif
+01102 
+01103                         // Average the 4 pixels around this tile corner
+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         // Modulate result with TileColors.
+01113         //==================
+01114         nlassert(_Patch->TileColors.size()>=0);
+01115         #ifdef NL_DLM_TILE_RES
+01116         // retrieve userColor pointer.
+01117         uint16  *tileColor= (uint16*)(&_Patch->TileColors[0]);
+01118         #else
+01119         uint16  *tileColor= (uint16*)(&_LowResTileColors[0]);
+01120         #endif
+01121 
+01122         // For all pixels
+01123         dst= &_TextureFar[0];
+01124         for(sint n= Width*Height; n>0; n--, dst++, tileColor++)
+01125         {
+01126                 uint16  tc= *tileColor;
+01127                 // modulate R.
+01128                 dst->R= ( (tc>>11) * dst->R)>>5;
+01129                 // modulate G.
+01130                 dst->G= (((tc>>5)&63) * dst->G)>>6;
+01131                 // modulate B.
+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         // NB: code copied from CTextureFar::rebuildRectangle()
+01143 
+01144         // The tileSize at order1 is 2.
+01145         uint    tileSize= 2;
+01146 
+01147         // Source size
+01148         sint sourceSize;
+01149 
+01150         // Source offset (for 256)
+01151         uint sourceOffset=0;
+01152 
+01153         // 256 ?
+01154         if (is256x256)
+01155         {
+01156                 // On the left ?
+01157                 if (uvOff&0x02)
+01158                         sourceOffset+=tileSize;
+01159 
+01160                 // On the bottom ?
+01161                 if ((uvOff==1)||(uvOff==2))
+01162                         sourceOffset+=2*tileSize*tileSize;
+01163 
+01164                 // Yes, 256
+01165                 sourceSize=tileSize<<1;
+01166         }
+01167         else
+01168         {
+01169                 // No, 128
+01170                 sourceSize=tileSize;
+01171         }
+01172 
+01173         // Compute offset and deltas
+01174         switch (nRot)
+01175         {
+01176         case 0:
+01177                 // Source pointers
+01178                 srcPixel= srcPixel+sourceOffset;
+01179 
+01180                 // Source delta
+01181                 srcDeltaX=1;
+01182                 srcDeltaY=sourceSize;
+01183                 break;
+01184         case 1:
+01185                 {
+01186                         // Source pointers
+01187                         uint newOffset=sourceOffset+(tileSize-1);
+01188                         srcPixel=srcPixel+newOffset;
+01189 
+01190                         // Source delta
+01191                         srcDeltaX=sourceSize;
+01192                         srcDeltaY=-1;
+01193                 }
+01194                 break;
+01195         case 2:
+01196                 {
+01197                         // Destination pointer
+01198                         uint newOffset=sourceOffset+(tileSize-1)*sourceSize+tileSize-1;
+01199                         srcPixel=srcPixel+newOffset;
+01200 
+01201                         // Source delta
+01202                         srcDeltaX=-1;
+01203                         srcDeltaY=-sourceSize;
+01204                 }
+01205                 break;
+01206         case 3:
+01207                 {
+01208                         // Destination pointer
+01209                         uint newOffset=sourceOffset+(tileSize-1)*sourceSize;
+01210                         srcPixel=srcPixel+newOffset;
+01211 
+01212                         // Source delta
+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         // copy the 2x2 tile to the texture.
+01227 
+01228         // first line.
+01229         dstPixel[0]= srcPixel[0];
+01230         dstPixel[1]= srcPixel[srcDeltaX];
+01231         // second line.
+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         // blend the 2x2 tile with the texture.
+01240         CRGBA   *dst;
+01241         CRGBA   src;
+01242 
+01243         // first line.
+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         // second line.
+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 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1