From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/patch__lightmap_8cpp-source.html | 2061 +++++++++++++++++++++ 1 file changed, 2061 insertions(+) create mode 100644 docs/doxygen/nel/patch__lightmap_8cpp-source.html (limited to 'docs/doxygen/nel/patch__lightmap_8cpp-source.html') diff --git a/docs/doxygen/nel/patch__lightmap_8cpp-source.html b/docs/doxygen/nel/patch__lightmap_8cpp-source.html new file mode 100644 index 00000000..5acad7e2 --- /dev/null +++ b/docs/doxygen/nel/patch__lightmap_8cpp-source.html @@ -0,0 +1,2061 @@ + + + + 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  
+

patch_lightmap.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2000 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 
+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 // Precalc table used to decompress shadow map
+00052 // NB: if you want to change thoses values, see unpackLumelBlock, cause hardcoded.
+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         // Take the two alpha values
+00073         uint alpha0=src[0];
+00074         uint alpha1=src[1];
+00075 
+00076         // precompute the 8 possible values, for each possible code.
+00077         // ------------------
+00078         uint8   values[8];
+00079         // Case 0
+00080         if (alpha0>alpha1)
+00081         {
+00082                 // unrolled, and hardcoded for faster compute
+00083                 values[0]= alpha0;
+00084                 values[1]= alpha1;
+00085                 values[2]= (uint8) ( (alpha0*219 + alpha1*37 ) >>8 ) ;  // 6*256/7
+00086                 values[3]= (uint8) ( (alpha0*183 + alpha1*73 ) >>8 ) ;  // 5*256/7
+00087                 values[4]= (uint8) ( (alpha0*146 + alpha1*110) >>8 ) ;  // 4*256/7
+00088                 values[5]= (uint8) ( (alpha0*110 + alpha1*146) >>8 ) ;  // 3*256/7
+00089                 values[6]= (uint8) ( (alpha0*73  + alpha1*183) >>8 ) ;  // 2*256/7
+00090                 values[7]= (uint8) ( (alpha0*37  + alpha1*219) >>8 ) ;  // 1*256/7
+00091         }
+00092         // Case 1
+00093         else
+00094         {
+00095                 // unrolled, and hardcoded for faster compute
+00096                 values[0]= alpha0;
+00097                 values[1]= alpha1;
+00098                 values[2]= (uint8) ( (alpha0*205 + alpha1*51 ) >>8 ) ;  // 4*256/5
+00099                 values[3]= (uint8) ( (alpha0*154 + alpha1*102) >>8 ) ;  // 3*256/5
+00100                 values[4]= (uint8) ( (alpha0*102 + alpha1*154) >>8 ) ;  // 2*256/5
+00101                 values[5]= (uint8) ( (alpha0*51  + alpha1*205) >>8 ) ;  // 1*256/5
+00102                 values[6]= 0;
+00103                 values[7]= 255;
+00104         }
+00105 
+00106 
+00107         // For each pixel, set the value according to the code
+00108         // ------------------
+00109         uint    block8Pixs[2];
+00110         // Split the 48 bits data in 2 24 bits pass.
+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         // write all lumels
+00115         for(uint i=0; i<2; i++)
+00116         {
+00117                 uint    blockPix= block8Pixs[i];
+00118                 // parse the 8 pixs, and write seq to dest
+00119                 for(uint n=8; n>0; n--, dest++)
+00120                 {
+00121                         uint code= (blockPix>>21)&0x7;
+00122 
+00123                         // read LUT, and store
+00124                         *dest= values[code];
+00125 
+00126                         // shift the block
+00127                         blockPix<<= 3;
+00128                 }
+00129         }
+00130 
+00131 }
+00132 
+00133 // ***************************************************************************
+00134 inline uint8 getUnpackLumelBlock (const uint8 *src, uint pixel)
+00135 {
+00136         // Offset of the bit
+00137         pixel*=3;
+00138         uint offset=(pixel>>3)+2;
+00139         uint bits=pixel&7;
+00140 
+00141         // Uncompress 16 codes
+00142         uint code;
+00143 
+00144         // Get the code
+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         // Case 0
+00151         if (src[0]>src[1])
+00152         {
+00153                 // Decompress the data
+00154                 return (uint8)((NL3DDecompressLumelFactor0Case0[code]*src[0]+NL3DDecompressLumelFactor1Case0[code]*src[1])/7);
+00155         }
+00156         // Case 1
+00157         else
+00158         {
+00159                 // Decompress the data
+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         // Input of compresed data
+00173         uint8 *compressedData=&CompressedLumels[0];
+00174 
+00175         // Number of lumel by lines
+00176         uint lumelCount=OrderS*NL_LUMEL_BY_TILE;
+00177 
+00178         // Number of block in a line
+00179         nlassert ((lumelCount&0x3)==0);
+00180         uint numLumelBlock=lumelCount>>2;
+00181 
+00182         // Number of line
+00183         uint lineCount=OrderT*NL_LUMEL_BY_TILE;
+00184 
+00185         // Number of block line
+00186         nlassert ((lineCount&0x3)==0);
+00187         uint numLineBlock=lineCount>>2;
+00188 
+00189         // Destination lumel block size
+00190         uint lumelDestBlockSize=4;
+00191 
+00192         // Destination lumel line block size
+00193         uint lumelDestLineBlockSize=lumelCount*lumelDestBlockSize;
+00194 
+00195         // Each line block
+00196         for (uint lineBlock=0; lineBlock<numLineBlock; lineBlock++)
+00197         {
+00198                 uint countVx4=16;
+00199 
+00200                 // Block pointer
+00201                 uint8 *blockLine=pLumelDest;
+00202 
+00203                 // Each lumel block
+00204                 for (uint lumelBlock=0; lumelBlock<numLumelBlock; lumelBlock++)
+00205                 {
+00206                         // *** Unpack the block
+00207                         uint countU=4;
+00208 
+00209                         // Destination lumel
+00210                         uint8 *blockDest=blockLine;
+00211 
+00212                         // Temp block
+00213                         uint8 block[4*4];
+00214 
+00215                         // Block unpacking...
+00216                         unpackLumelBlock (block, compressedData);
+00217 
+00218                         // Copy the lumels
+00219                         for (uint v=0; v<countVx4; v+=4)
+00220                         {
+00221                                 for (uint u=0; u<countU; u++)
+00222                                 {
+00223                                         // Copy the lumel
+00224                                         blockDest[u]=block[v+u];
+00225                                 }
+00226 
+00227                                 // Next line
+00228                                 blockDest+=lumelCount;
+00229                         }
+00230 
+00231                         // Next source block
+00232                         compressedData+=NL_BLOCK_LUMEL_COMPRESSED_SIZE;
+00233 
+00234                         // Next block on the line
+00235                         blockLine+=lumelDestBlockSize;
+00236                 }
+00237 
+00238                 // Next line of block
+00239                 pLumelDest+=lumelDestLineBlockSize;
+00240         }
+00241 }
+00242 
+00243 // ***************************************************************************
+00244 uint            CPatch::evalLumelBlock (const uint8 *original, const uint8 *unCompressed, uint width, uint height)
+00245 {
+00246         // Sum
+00247         uint sum=0;
+00248 
+00249         // Eval error for each..
+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         // return the sum
+00257         return sum;
+00258 }
+00259 
+00260 // ***************************************************************************
+00261 void            CPatch::packLumelBlock (uint8 *dest, const uint8 *source, uint8 alpha0, uint8 alpha1)
+00262 {
+00263         // Precalc the height values..
+00264         uint8 value[8];
+00265 
+00266         // For each value
+00267         uint i;
+00268         for (i=0; i<8; i++)
+00269         {
+00270                 // Case 0 or 1 ?
+00271                 if (alpha0>alpha1)
+00272                         // Case 0
+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         // Store alpha value
+00286         dest[0]=alpha0;
+00287         dest[1]=alpha1;
+00288 
+00289         // Clear dest codes
+00290         for (i=0; i<6; i++)
+00291         {
+00292                 // Clear the code
+00293                 dest[2+i]=0;
+00294         }
+00295 
+00296         // For each original select the best
+00297         uint codeOffset=2;
+00298         sint codeShift=5;
+00299         for (i=0; i<16; i++)
+00300         {
+00301                 // Best dist and code
+00302                 uint bestDist=10000;
+00303                 uint8 bestCode=0;
+00304 
+00305                 // Calc distance
+00306                 for (uint code=0; code<8; code++)
+00307                 {
+00308                         // Distance from original value
+00309                         uint dist=abs ((sint)(source[i])-(sint)(value[code]));
+00310 
+00311                         // The best ?
+00312                         if (dist<bestDist)
+00313                         {
+00314                                 // New best
+00315                                 bestDist=dist;
+00316                                 bestCode=code;
+00317                         }
+00318 
+00319                         // Perfect, stop searching
+00320                         if (dist==0)
+00321                                 break;
+00322                 }
+00323 
+00324                 // Store the best
+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                 // Next shift
+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 // bilinear at center of the pixels. x E [0, 3], y E [0, 3].
+00358 inline void             bilinearColor(CRGBA     corners[4], uint x, uint y, uint &R, uint &G, uint &B)
+00359 {
+00360         // Fast bilinear and modulate. 
+00361         // \todo yoyo: TODO_OPTIMIZE: should be ASMed later. (MMX...)
+00362         // hardcoded for 4 pixels.
+00363         nlassert(NL_LUMEL_BY_TILE==4);
+00364 
+00365         // expand to be on center of pixel=> 1,3,5 or 7.
+00366         x= (x<<1)+1;
+00367         y= (y<<1)+1;
+00368         uint    x1= 8-x;
+00369         uint    y1= 8-y;
+00370 
+00371         // compute weight factors.
+00372         uint    xy=             x*y;
+00373         uint    x1y=    x1*y;
+00374         uint    xy1=    x*y1;
+00375         uint    x1y1=   x1*y1;
+00376 
+00377         // bilinear
+00378         // pix left top.
+00379         R = corners[0].R * x1y1;
+00380         G = corners[0].G * x1y1;
+00381         B = corners[0].B * x1y1;
+00382         // pix right top.
+00383         R+= corners[1].R * xy1;
+00384         G+= corners[1].G * xy1;
+00385         B+= corners[1].B * xy1;
+00386         // pix left bottom.
+00387         R+= corners[2].R * x1y;
+00388         G+= corners[2].G * x1y;
+00389         B+= corners[2].B * x1y;
+00390         // pix right bottom.
+00391         R+= corners[3].R * xy;
+00392         G+= corners[3].G * xy;
+00393         B+= corners[3].B * xy;
+00394 
+00395 }
+00396 
+00397 
+00398 // ***************************************************************************
+00399 // bilinear at center of the pixels. x E [0, 3], y E [0, 3].
+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         // modulate with input.
+00406         R*= res.R;
+00407         G*= res.G;
+00408         B*= res.B;
+00409 
+00410         // result.
+00411         res.R= R >> 14;
+00412         res.G= G >> 14;
+00413         res.B= B >> 14;
+00414 }
+00415 
+00416 
+00417 // ***************************************************************************
+00418 // bilinear at center of the pixels. x E [0, 3], y E [0, 3].
+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         // add with input.
+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         // result.
+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         // Get the tileColors around this tile
+00444         CRGBA   corners[4];
+00445         getTileTileColors(ts, tt, corners);
+00446 
+00447         // For all lumel, bilinear.
+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                         // compute this pixel, and modulate
+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         // Get the tileColors around this tile
+00464         CRGBA   corners[4];
+00465         getTileTileColors(ts, tt, corners);
+00466 
+00467         // get coordinate according to edge.
+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         // For all lumel of the edge, bilinear.
+00478         uint    i;
+00479         for(i=0; i<NL_LUMEL_BY_TILE; i++)
+00480         {
+00481                 // if vertical edge
+00482                 if( (edge&1)==0 )       y= i;
+00483                 // else horizontal edge
+00484                 else                            x= i;
+00485 
+00486                 // manage inverse.
+00487                 uint    where;
+00488                 if(inverse)             where= (NL_LUMEL_BY_TILE-1)-i;
+00489                 else                    where= i;
+00490                 // compute this pixel, and modulate
+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         // Get the tileColors around this tile
+00500         CRGBA   corners[4];
+00501         getTileTileColors(ts, tt, corners);
+00502 
+00503         // compute this pixel, and modulate
+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                         // compute this pixel.
+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         // get coordinate according to edge.
+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                 // if vertical edge
+00540                 if( (edge&1)==0 )       y= i;
+00541                 // else horizontal edge
+00542                 else                            x= i;
+00543 
+00544                 // manage inverse.
+00545                 uint    where;
+00546                 if(inverse)             where= (NL_LUMEL_BY_TILE-1)-i;
+00547                 else                    where= i;
+00548                 // compute this pixel.
+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         // use 3 computeVertex to compute a normal. This is slow....
+00560         CVector         p0, p1 ,p2;
+00561         // 1st vert. Top-left of the lumel.
+00562         u= (ts + s*lumelSize )/OrderS;
+00563         v= (tt + t*lumelSize )/OrderT;
+00564         p0= computeVertex(u, v);
+00565         // 2nd vert. Bottom-left of the lumel.
+00566         u= (ts + s*lumelSize )/OrderS;
+00567         v= (tt + (t+1)*lumelSize )/OrderT;
+00568         p1= computeVertex(u, v);
+00569         // 3rd vert. Center-Right of the lumel.
+00570         u= (ts + (s+1)*lumelSize )/OrderS;
+00571         v= (tt + (t+0.5f)*lumelSize )/OrderT;
+00572         p2= computeVertex(u, v);
+00573 
+00574         // the normal.
+00575         CVector         normal;
+00576         normal= (p1-p0)^(p2-p0);
+00577         normal.normalize();
+00578 
+00579         // lighting.
+00580         float   c= -normal*getLandscape()->getAutomaticLightDir();
+00581         c= max(c, 0.f);
+00582         sint    ic;
+00583 
+00584 #ifdef NL_OS_WINDOWS
+00585         // FastFloor using fistp. Don't care convention.
+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         // ambiant/diffuse lighting.
+00598         *dest= getLandscape()->getStaticLight()[ic];
+00599 }
+00600 
+00601 
+00602 // ***************************************************************************
+00603 void            CPatch::getTileLumelmapPrecomputed(uint ts, uint tt, uint8 *dest, uint stride)
+00604 {
+00605         // Unpack the lumels
+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         // Retrun it
+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                         // lumel
+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         // Return the lumel
+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         // Lumel table
+00634         const CRGBA* colorTable=getLandscape ()->getStaticLight ();
+00635         // Unpack the lumels
+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         // Retrun it
+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                         // lumel
+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         // Lumel table
+00660         const CRGBA* colorTable=getLandscape ()->getStaticLight ();
+00661 
+00662         // Witch corner to start ?
+00663         uint pixel=NL3DPixelStartLumel[edge];
+00664         uint delta=NL3DDeltaLumel[edge];
+00665 
+00666         // For each lumels
+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                         // lumel
+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                         // lumel
+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         // Lumel table
+00694         const CRGBA* colorTable=getLandscape ()->getStaticLight ();
+00695 
+00696         // Return the lumel
+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                 // Add the inlufence of TLI.
+00711                 addTileLightmapWithTLI(ts, tt, dest, stride);
+00712         }
+00713 
+00714         // modulate dest with tileColors (at center of lumels).
+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                 // Add the inlufence of TLI.
+00726                 addTileLightmapEdgeWithTLI(ts, tt, edge, dest, stride, inverse);
+00727         }
+00728 
+00729         // modulate dest with tileColors (at center of lumels).
+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                 // Add the inlufence of TLI.
+00743                 addTileLightmapPixelWithTLI(ts, tt, s, t, dest);
+00744         }
+00745 
+00746         // modulate dest with tileColors (at center of lumels).
+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         // Get the Uv, in [0,Order?*NL_LUMEL_BY_TILE] basis (ie lumel basis).
+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         // if allowed, try to go on neighbor patch.
+00762         if(lookAround)
+00763         {
+00764                 // try to know if we must go on a neighbor patch (maybe false with bind X/1).
+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         // If we must get (if possible) the pixel in the current patch, do it.
+00771         if(!mustLookOnNeighbor)
+00772         {
+00773                 // if out this patch, abort.
+00774                 if( u<0 || u>=OrderS*NL_LUMEL_BY_TILE || v<0 || v>=OrderT*NL_LUMEL_BY_TILE)
+00775                         return;
+00776                 else
+00777                 {
+00778                         // get this pixel.
+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         // else get from the best neighbor patch.
+00783         else
+00784         {
+00785                 // choose against which edge we must find the pixel.
+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                 // retrieve info on neighbor.
+00793                 CBindInfo                       bindInfo;
+00794                 getBindNeighbor(edge, bindInfo);
+00795 
+00796                 // if neighbor present.
+00797                 if(bindInfo.Zone)
+00798                 {
+00799                         CVector2f       stOut;
+00800                         CPatch          *patchOut;
+00801                         uint            patchId;
+00802 
+00803                         // Ok, search uv on this patch.
+00804                         CPatchUVLocator         uvLocator;
+00805                         uvLocator.build(this, edge, bindInfo);
+00806                         patchId= uvLocator.selectPatch(stIn);
+00807                         uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+00808 
+00809                         // retry only one time, so at next call, must find the data IN htis patch (else abort).
+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         // hardcoded for 10x10.
+00823         nlassert(NL_TILE_LIGHTMAP_SIZE==10);
+00824         CRGBA   *dest;
+00825         uint    edge;
+00826         uint    corner;
+00827 
+00828         // Compute center of the TessBlock: the 2x2 tiles.
+00829         //=================
+00830         // compute tile 0,0 of the tessBlock. must decal of 1 pixel.
+00831         dest= lightText+NL_TILE_LIGHTMAP_SIZE+1;
+00832         computeTileLightmap(ts, tt, dest, NL_TILE_LIGHTMAP_SIZE);
+00833         // compute tile 1,0 of the tessBlock. must decal of 1 pixel.
+00834         dest= lightText + NL_LUMEL_BY_TILE + NL_TILE_LIGHTMAP_SIZE+1 ;
+00835         computeTileLightmap(ts+1, tt, dest, NL_TILE_LIGHTMAP_SIZE);
+00836         // compute tile 0,1 of the tessBlock. must decal of 1 pixel.
+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         // compute tile 1,1 of the tessBlock. must decal of 1 pixel.
+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         // Compute edges of the TessBlock.
+00845         //=================
+00846         bool    edgeBorder[4];
+00847         // where are we on a border of a patch??
+00848         edgeBorder[0]= ( ts==0 );
+00849         edgeBorder[1]= ( tt == OrderT-2 );
+00850         edgeBorder[2]= ( ts == OrderS-2 );
+00851         edgeBorder[3]= ( tt==0 );
+00852 
+00853         // For all edges.
+00854         for(edge=0; edge<4; edge++)
+00855         {
+00856                 // compute dest info.
+00857                 //==============
+00858                 // Are we on a vertical edge or horizontal edge??
+00859                 uint    stride= (edge&1)==0? NL_TILE_LIGHTMAP_SIZE : 1;
+00860 
+00861                 // must compute on which tile we must find info.
+00862                 sint    decalS=0;
+00863                 sint    decalT=0;
+00864                 // and must compute ptr, where we store the result of the edge.
+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                 // compute the second tile dest info.
+00874                 CRGBA   *dest2;
+00875                 sint    decalS2;
+00876                 sint    decalT2;
+00877                 // if vertical edge.
+00878                 if((edge&1)==0)
+00879                 {
+00880                         // Next Y tile.
+00881                         dest2= dest + NL_LUMEL_BY_TILE*NL_TILE_LIGHTMAP_SIZE;
+00882                         decalS2= decalS;
+00883                         decalT2= decalT+1;
+00884                 }
+00885                 else
+00886                 {
+00887                         // Next X tile.
+00888                         dest2= dest + NL_LUMEL_BY_TILE;
+00889                         decalS2= decalS+1;
+00890                         decalT2= decalT;
+00891                 }
+00892 
+00893 
+00894                 // If we are not on a border of a patch, just compute on the interior of the patch.
+00895                 //==============
+00896                 if(!edgeBorder[edge])
+00897                 {
+00898                         // find the result on the mirrored border of us. First tile.
+00899                         computeTileLightmapEdge(ts+decalS, tt+decalT, (edge+2)&3, dest, stride, false);
+00900 
+00901                         // find the result on the mirrored border of us. Second Tile.
+00902                         computeTileLightmapEdge(ts+decalS2, tt+decalT2, (edge+2)&3, dest2, stride, false);
+00903 
+00904                 }
+00905                 // else, slightly complicated, must find the result on neighbor patch(s).
+00906                 //==============
+00907                 else
+00908                 {
+00909                         CPatchUVLocator         uvLocator;
+00910                         CBindInfo                       bindInfo;
+00911                         bindInfo.Zone= NULL;
+00912 
+00913                         // if smmothed edge, search the neighbor.
+00914                         if(getSmoothFlag(edge))
+00915                         {
+00916                                 // Build the bindInfo against this edge.
+00917                                 getBindNeighbor(edge, bindInfo);
+00918 
+00919                                 // if ok, build the uv info against this edge.
+00920                                 if(bindInfo.Zone)
+00921                                 {
+00922                                         uvLocator.build(this, edge, bindInfo);
+00923                                         // if there is not same tile order across the edge, invalidate the smooth.
+00924                                         // This is rare, so don't bother.
+00925                                         if(!uvLocator.sameEdgeOrder())
+00926                                                 bindInfo.Zone= NULL;
+00927                                 }
+00928                         }
+00929 
+00930 
+00931                         // Fast reject: if no neighbor, or if not smoothed, or if edge order pb, just copy from my interior.
+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                                 // fill the NL_LUMEL_BY_TILE*2 (8) pixels.
+00944                                 for(uint n=NL_LUMEL_BY_TILE*2; n>0; n--, src+=stride, dest+=stride)
+00945                                         *dest= *src;
+00946                         }
+00947                         // else, ok, get from neighbor.
+00948                         else
+00949                         {
+00950                                 CVector2f       stIn, stOut;
+00951                                 CPatch          *patchOut;
+00952                                 uint            patchId;
+00953                                 uint            edgeOut;
+00954                                 bool            inverse;
+00955 
+00956                                 // First Tile.
+00957                                 //=========
+00958                                 // to remove floor pbs, take the center of the wanted tile.
+00959                                 stIn.set(ts+decalS + 0.5f, tt+decalT + 0.5f);
+00960                                 patchId= uvLocator.selectPatch(stIn);
+00961                                 uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+00962                                 // must find what edge on neighbor to compute, and if we must inverse (swap) result.
+00963                                 // easy: the edge of the tile is the edge of the patch where we are binded.
+00964                                 edgeOut= bindInfo.Edge[patchId];
+00965                                 // edge0 is oriented in T increasing order. edge1 is oriented in S increasing order.
+00966                                 // edge2 is oriented in T decreasing order. edge3 is oriented in S decreasing order.
+00967                                 // inverse is true if same sens on both edges (because of mirroring, sens should be different).
+00968                                 inverse= (edge>>1)==(edgeOut>>1);
+00969                                 // compute the lightmap on the edge of the neighbor.
+00970                                 patchOut->computeTileLightmapEdge((sint)floor(stOut.x), (sint)floor(stOut.y), edgeOut, dest, stride, inverse);
+00971 
+00972                                 // Second Tile.
+00973                                 //=========
+00974                                 // same reasoning.
+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         // Compute corners of the TessBlock.
+00988         //=================
+00989         bool    cornerOnPatchEdge[4];
+00990         bool    cornerOnPatchCorner[4];
+00991         // where are we on a edge border of a patch??
+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         // where are we on a corner border of a patch??
+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         // For all corners.
+01003         for(corner=0; corner<4; corner++)
+01004         {
+01005                 // compute dest info.
+01006                 //==============
+01007                 // must compute on which tile we must find info.
+01008                 sint    decalS=0;
+01009                 sint    decalT=0;
+01010                 // and must compute ptr, where we store the result of the corner.
+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                 // If we are not on a border of a patch, just compute on the interior of the patch.
+01021                 //==============
+01022                 // if the corner is IN the patch.
+01023                 if(!cornerOnPatchCorner[corner] && !cornerOnPatchEdge[corner])
+01024                 {
+01025                         // what pixel to read.
+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                         // find the result on the corner of the neighbor tile.
+01033                         computeTileLightmapPixel(ts+decalS, tt+decalT, subS, subT, dest);
+01034                 }
+01035                 else
+01036                 {
+01037                         // By default, fill the corner with our interior corner. Because other methods may fail.
+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                         // fill the pixel.
+01048                         *dest= *src;
+01049 
+01050                         // get the coordinate of the corner, in our [0,Order] basis. get it at the center of the pixel.
+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                         // if the corner is on One edge only of the patch.
+01068                         if(cornerOnPatchEdge[corner])
+01069                         {
+01070                                 // find the edge where to read this corner: hard edge after or before this corner.
+01071                                 if(edgeBorder[corner])  edge= corner;
+01072                                 else                                    edge= (corner+4-1) & 3;
+01073 
+01074                                 // if this edge is smoothed, find on neighbor.
+01075                                 if(getSmoothFlag(edge))
+01076                                 {
+01077                                         // retrieve neigbhor info.
+01078                                         getBindNeighbor(edge, bindInfo);
+01079 
+01080                                         // if neighbor present.
+01081                                         if(bindInfo.Zone)
+01082                                         {
+01083                                                 // Ok, search uv on this patch.
+01084                                                 uvLocator.build(this, edge, bindInfo);
+01085                                                 patchId= uvLocator.selectPatch(stIn);
+01086                                                 uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+01087 
+01088                                                 // Get the Uv, in [0,Order?*NL_LUMEL_BY_TILE] basis (ie lumel basis), and get from neighbor patch
+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                                 // else we must still smooth with our lumel on this patch, so get it from neighbor on edge.
+01096                                 else
+01097                                 {
+01098                                         // first, clamp to our patch (recenter on the previous pixel)
+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                                         // Get the Uv, in [0,Order?*NL_LUMEL_BY_TILE] basis (ie lumel basis), and get from this patch
+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                         // else it is on a corner of the patch.
+01112                         else
+01113                         {
+01114                                 // if the corner of the patch (same as tile corner) is smoothed, find on neighbor
+01115                                 if(getCornerSmoothFlag(corner))
+01116                                 {
+01117                                         // retrieve neigbhor info. NB: use edgeId=corner, (corner X is the start of the edge X)it works.
+01118                                         getBindNeighbor(corner, bindInfo);
+01119 
+01120                                         // if neighbor present.
+01121                                         if(bindInfo.Zone)
+01122                                         {
+01123                                                 // Ok, search uv on this patch.
+01124                                                 uvLocator.build(this, corner, bindInfo);
+01125                                                 patchId= uvLocator.selectPatch(stIn);
+01126                                                 uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+01127 
+01128                                                 // same reasoning as in computeDisplaceCornerSmooth(), must find the pixel on the neighbor 
+01129                                                 // of our neighbor. But the current corner may be a corner on a bind X/1. All is managed by doing
+01130                                                 // this way.
+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         // TessBlocks must have been allocated.
+01147         nlassert(TessBlocks.size()!=0);
+01148 
+01149         // get what tessBlock to use.
+01150         uint    numtb, numtm;
+01151         computeTbTm(numtb, numtm, ts, tt);
+01152         CTessBlock      &tessBlock= TessBlocks[numtb];
+01153 
+01154         // If the lightmap Id has not been computed, compute it.
+01155         if(tessBlock.LightMapRefCount==0)
+01156         {
+01157                 // Compute the lightmap texture, with help of TileColors, with neighboring info etc...
+01158                 CRGBA   lightText[NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE];
+01159                 computeNearBlockLightmap(ts&(~1), tt&(~1), lightText);
+01160 
+01161                 // Create a rdrPass with this texture, donlod to Driver etc...
+01162                 tessBlock.LightMapId= Zone->Landscape->getTileLightMap(lightText, rdrpass);
+01163 
+01164                 // store this rdrpass ptr.
+01165                 tessBlock.LightMapRdrPass= rdrpass;
+01166         }
+01167 
+01168         // We are using this 2x2 tiles lightmap.
+01169         tessBlock.LightMapRefCount++;
+01170 
+01171 
+01172         // get the rdrpass ptr of the tessBlock lightmap
+01173         rdrpass= tessBlock.LightMapRdrPass;
+01174 }
+01175 
+01176 
+01177 // ***************************************************************************
+01178 void            CPatch::getTileLightMapUvInfo(uint ts, uint tt, CVector &uvScaleBias)
+01179 {
+01180         // TessBlocks must have been allocated.
+01181         nlassert(TessBlocks.size()!=0);
+01182 
+01183         // get what tessBlock to use.
+01184         uint    numtb, numtm;
+01185         computeTbTm(numtb, numtm, ts, tt);
+01186         CTessBlock      &tessBlock= TessBlocks[numtb];
+01187 
+01188         // Get the uvScaleBias for the tile 0,0  of the block.
+01189         Zone->Landscape->getTileLightMapUvInfo(tessBlock.LightMapId, uvScaleBias);
+01190 
+01191         // Must increment the bias, for the good tile in the 2x2 block Lightmap.
+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         // TessBlocks must have been allocated.
+01203         nlassert(TessBlocks.size()!=0);
+01204 
+01205         // get what tessBlock to use.
+01206         uint    numtb, numtm;
+01207         computeTbTm(numtb, numtm, ts, tt);
+01208         CTessBlock      &tessBlock= TessBlocks[numtb];
+01209 
+01210         // If no more tileMaterial use this lightmap, release it.
+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         // Number of lumel by lines
+01223         uint lumelCount=OrderS*NL_LUMEL_BY_TILE;
+01224 
+01225         // Number of block in a line
+01226         nlassert ((lumelCount&0x3)==0);
+01227         uint numLumelBlock=lumelCount>>2;
+01228 
+01229         // Number of line
+01230         uint lineCount=OrderT*NL_LUMEL_BY_TILE;
+01231 
+01232         // Number of block line
+01233         nlassert ((lineCount&0x3)==0);
+01234         uint numLineBlock=lineCount>>2;
+01235 
+01236         // Resize the compressed buffer
+01237         CompressedLumels.resize (numLumelBlock*numLineBlock*NL_BLOCK_LUMEL_COMPRESSED_SIZE);
+01238 
+01239         // Input of compresed data
+01240         uint8 *compressedData=&CompressedLumels[0];
+01241 
+01242         // Each line block
+01243         for (uint lineBlock=0; lineBlock<numLineBlock; lineBlock++)
+01244         {
+01245                 // Block pointer
+01246                 const uint8 *blockLine=pLumelSrc;
+01247 
+01248                 // Each lumel block
+01249                 for (uint lumelBlock=0; lumelBlock<numLumelBlock; lumelBlock++)
+01250                 {
+01251                         // *** Unpack the block
+01252                         uint countU;
+01253 
+01254                         // Last block ?
+01255                         if (lumelBlock==numLumelBlock-1)
+01256                                 countU=lumelCount&3;
+01257                         else
+01258                                 countU=4;
+01259 
+01260                         // Destination lumel
+01261                         const uint8 *blockSrc=blockLine;
+01262 
+01263                         // Temp block
+01264                         uint8 originalBlock[4*4];
+01265 
+01266                         // Copy the lumels in the bloc
+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                                         // Copy the lumel
+01272                                         originalBlock[(v<<2)+u]=blockSrc[u];
+01273                                 }
+01274 
+01275                                 // Next line
+01276                                 blockSrc+=lumelCount;
+01277                         }
+01278 
+01279                         // Get min and max alpha
+01280                         uint8 alphaMin=255;
+01281                         uint8 alphaMax=0;
+01282 
+01283                         // Scan
+01284                         for (uint i=0; i<16; i++)
+01285                         {
+01286                                 // Min ?
+01287                                 if (originalBlock[i]<alphaMin)
+01288                                         alphaMin=originalBlock[i];
+01289                                 if (originalBlock[i]>alphaMax)
+01290                                         alphaMax=originalBlock[i];
+01291                         }
+01292 
+01293                         // *** Try to compress by 2 methods
+01294 
+01295                         // Blcok uncompressed
+01296                         uint8 uncompressedBlock[4*4];
+01297         
+01298                         // Pack the block
+01299                         packLumelBlock (compressedData, originalBlock, alphaMin, alphaMax);
+01300 
+01301                         // Unpack the block
+01302                         unpackLumelBlock (uncompressedBlock, compressedData);
+01303 
+01304                         // Eval error
+01305                         uint firstMethod=evalLumelBlock (originalBlock, uncompressedBlock, NL_LUMEL_BY_TILE, NL_LUMEL_BY_TILE);
+01306 
+01307                         // second compression
+01308                         uint8 secondCompressedBlock[NL_BLOCK_LUMEL_COMPRESSED_SIZE];
+01309                         packLumelBlock (secondCompressedBlock, originalBlock, alphaMax, alphaMin);
+01310 
+01311                         // Unpack the block
+01312                         unpackLumelBlock (uncompressedBlock, secondCompressedBlock);
+01313 
+01314                         // Eval error
+01315                         uint secondMethod=evalLumelBlock (originalBlock, uncompressedBlock, NL_LUMEL_BY_TILE, NL_LUMEL_BY_TILE);
+01316 
+01317                         // Second best ?
+01318                         if (secondMethod<firstMethod)
+01319                         {
+01320                                 // Copy compressed data
+01321                                 memcpy (compressedData, secondCompressedBlock, NL_BLOCK_LUMEL_COMPRESSED_SIZE);
+01322                         }
+01323 
+01324                         // Next source block
+01325                         compressedData+=NL_BLOCK_LUMEL_COMPRESSED_SIZE;
+01326 
+01327                         // Next block on the line
+01328                         blockLine+=4;
+01329                 }
+01330 
+01331                 // Next line of block
+01332                 pLumelSrc+=lumelCount*4;
+01333         }
+01334 }
+01335 
+01336 // ***************************************************************************
+01337 void            CPatch::resetCompressedLumels ()
+01338 {
+01339         // Number of lumel by lines
+01340         uint lumelCount=OrderS*NL_LUMEL_BY_TILE;
+01341 
+01342         // Number of block in a line
+01343         nlassert ((lumelCount&0x3)==0);
+01344         uint numLumelBlock=lumelCount>>2;
+01345 
+01346         // Number of line
+01347         uint lineCount=OrderT*NL_LUMEL_BY_TILE;
+01348 
+01349         // Number of block line
+01350         nlassert ((lineCount&0x3)==0);
+01351         uint numLineBlock=lineCount>>2;
+01352 
+01353         // Size of the lumel array
+01354         uint size=numLineBlock*numLumelBlock*8;
+01355 
+01356         // 4 bits per lumel
+01357         CompressedLumels.resize (size);
+01358 
+01359         // No line have shadows.
+01360         memset (&CompressedLumels[0], 0, size);
+01361 }
+01362 
+01363 
+01364 // ***************************************************************************
+01365 // ***************************************************************************
+01366 // Functions (C/ASM).
+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         // Fast bilinear of a 5x5 tile.
+01405         // Corners must be set.
+01406         // Later: pass it to ASM.
+01407 
+01408         // Fill first column 0 and column 4.
+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         // Fill Line 0.
+01417         a20.avg2(a00, a40);
+01418         a10.avg2(a00, a20);
+01419         a30.avg2(a20, a40);
+01420 
+01421         // Fill Line 1.
+01422         a21.avg2(a01, a41);
+01423         a11.avg2(a01, a21);
+01424         a31.avg2(a21, a41);
+01425 
+01426         // Fill Line 2. 
+01427         a22.avg2(a02, a42);
+01428         a12.avg2(a02, a22);
+01429         a32.avg2(a22, a42);
+01430 
+01431         // Fill Line 3. 
+01432         a23.avg2(a03, a43);
+01433         a13.avg2(a03, a23);
+01434         a33.avg2(a23, a43);
+01435 
+01436         // Fill Line 4. 
+01437         a24.avg2(a04, a44);
+01438         a14.avg2(a04, a24);
+01439         a34.avg2(a24, a44);
+01440 
+01441 }
+01442 
+01443 
+01444 // ***************************************************************************
+01445 // ***************************************************************************
+01446 // Lightmap get interface.
+01447 // ***************************************************************************
+01448 // ***************************************************************************
+01449 
+01450 
+01451 // ***************************************************************************
+01452 uint8           CPatch::getLumel(const CUV &uv) const
+01453 {
+01454         // compute tile coord and lumel coord.
+01455         sint    ts, tt;
+01456         // get in lumel coord.
+01457         sint    w= (OrderS<<NL_LUMEL_BY_TILE_SHIFT);
+01458         sint    h= (OrderT<<NL_LUMEL_BY_TILE_SHIFT);
+01459         // fastFloor: use a precision of 256 to avoid doing OptFastFloorBegin.
+01460         // add 128, to round and get cneter of lumel.
+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         // get the lumel
+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 // TileLightInfluences
+01477 // ***************************************************************************
+01478 // ***************************************************************************
+01479 
+01480 
+01481 // ***************************************************************************
+01482 void            CPatch::resetTileLightInfluences()
+01483 {
+01484         // Fill default.
+01485         TileLightInfluences.resize((OrderS/2 +1) * (OrderT/2 +1));
+01486         // Disable All light influence on all points
+01487         for(uint i=0;i <TileLightInfluences.size(); i++)
+01488         {
+01489                 // Disable all light influence on this point.
+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         // Compute TLI coord for BiLinear.
+01500         sint    x,y;
+01501         // There is (OrderS/2+1) * (OrderT/2+1) tileLightInfluences (TLI).
+01502         sint    w= (OrderS>>1);
+01503         sint    h= (OrderT>>1);
+01504         sint    wTLI= w+1;
+01505         // fastFloor: use a precision of 256 to avoid doing OptFastFloorBegin.
+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         // compute the TLI coord, and the subCoord for bilinear.
+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         // Hence, xSub and ySub range is [0, 256].
+01515         xSub= x - (xTLI<<8);
+01516         ySub= y - (yTLI<<8);
+01517 
+01518 
+01519         // Use a CLightInfluenceInterpolator to biLinear light influence
+01520         CLightInfluenceInterpolator             interp;
+01521         // Must support only 2 light per TLI.
+01522         nlassert(CTileLightInfluence::NumLightPerCorner==2);
+01523         nlassert(CLightInfluenceInterpolator::NumLightPerCorner==2);
+01524         // Get ref on array of PointLightNamed.
+01525         CPointLightNamed        *zonePointLights= NULL;
+01526         if( getZone()->_PointLightArray.getPointLights().size() >0 )
+01527         {
+01528                 // const_cast, because will only change _IdInfluence, and 
+01529                 // also because CLightingManager will call appendLightedModel()
+01530                 zonePointLights= const_cast<CPointLightNamed*>(&(getZone()->_PointLightArray.getPointLights()[0]));
+01531         }
+01532         // For 4 corners.
+01533         for(y=0;y<2;y++)
+01534         {
+01535                 for(x=0;x<2;x++)
+01536                 {
+01537                         // get ref on TLI, and on corner.
+01538                         const CTileLightInfluence                               &tli= TileLightInfluences[ (yTLI+y)*wTLI + xTLI+x ];
+01539                         CLightInfluenceInterpolator::CCorner    &corner= interp.Corners[y*2 + x];
+01540                         // For all lights
+01541                         uint lid;
+01542                         for(lid= 0; lid<CTileLightInfluence::NumLightPerCorner; lid++)
+01543                         {
+01544                                 // get the id of the light in the zone
+01545                                 uint    tliLightId= tli.Light[lid];
+01546                                 // If empty id, stop
+01547                                 if(tliLightId==0xFF)
+01548                                         break;
+01549                                 else
+01550                                 {
+01551                                         // Set pointer of the light in the corner
+01552                                         corner.Lights[lid]= zonePointLights + tliLightId;
+01553                                 }
+01554                         }
+01555                         // Reset Empty slots.
+01556                         for(; lid<CTileLightInfluence::NumLightPerCorner; lid++)
+01557                         {
+01558                                 // set to NULL
+01559                                 corner.Lights[lid]= NULL;
+01560                         }
+01561                 }
+01562         }
+01563         // interpolate.
+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         // if at least the zone has pointLights, add them.
+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                         // Not influenced by a pointLight?, stop
+01586                         if(tli.Light[lid]==0xFF)
+01587                                 break;
+01588                         // Append the influence of this pointLight. 
+01589                         CRGBA   lightCol= zonePointLights[tli.Light[lid]].getDiffuse();
+01590                         // modulate with landscape Material.
+01591                         lightCol.modulateFromColorRGBOnly(lightCol, getLandscape()->getPointLightDiffuseMaterial() );
+01592                         // modulate with precomputed diffuse factor
+01593                         lightCol.modulateFromuiRGBOnly(lightCol, tli.getDiffuseLightFactor(lid) );
+01594                         // add to the corner
+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         // Get ref on array of PointLightNamed.
+01607         if( getZone()->_PointLightArray.getPointLights().size() >0 )
+01608         {
+01609                 // get coord of the tessBlock
+01610                 uint    tbs= ts>>1;
+01611                 uint    tbt= tt>>1;
+01612                 // get tile id local to tessBlock.
+01613                 uint    tls= ts-(tbs<<1);
+01614                 uint    tlt= tt-(tbt<<1);
+01615 
+01616                 // For each corner of the tessBlock, compute lighting with pointLights.
+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                 // Then biLinear to tile Level (tessBlock==2x2 tiles).
+01628                 CRGBA   tbEdges[4];
+01629                 CRGBA   tbMiddle;
+01630                 // left.
+01631                 tbEdges[0].avg2RGBOnly(tbCorners[0], tbCorners[2]);
+01632                 // bottom
+01633                 tbEdges[1].avg2RGBOnly(tbCorners[2], tbCorners[3]);
+01634                 // right
+01635                 tbEdges[2].avg2RGBOnly(tbCorners[1], tbCorners[3]);
+01636                 // up
+01637                 tbEdges[3].avg2RGBOnly(tbCorners[0], tbCorners[1]);
+01638                 // middle.
+01639                 tbMiddle.avg2RGBOnly(tbEdges[0], tbEdges[2]);
+01640                 
+01641                 // just copy result according to tile pos in tessBlock.
+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                 // Just fill with 0s.
+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         // compute colors ar corners of the tile.
+01691         CRGBA   corners[4];
+01692         getCurrentTileTLIColors(ts, tt, corners);
+01693 
+01694         // Bilinear accross the tile, and add to dest.
+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                         // compute this pixel, and add
+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         // compute colors ar corners of the tile.
+01710         CRGBA   corners[4];
+01711         getCurrentTileTLIColors(ts, tt, corners);
+01712 
+01713         // get coordinate according to edge.
+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         // For all lumel of the edge, bilinear.
+01724         uint    i;
+01725         for(i=0; i<NL_LUMEL_BY_TILE; i++)
+01726         {
+01727                 // if vertical edge
+01728                 if( (edge&1)==0 )       y= i;
+01729                 // else horizontal edge
+01730                 else                            x= i;
+01731 
+01732                 // manage inverse.
+01733                 uint    where;
+01734                 if(inverse)             where= (NL_LUMEL_BY_TILE-1)-i;
+01735                 else                    where= i;
+01736                 // compute this pixel, and modulate
+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         // compute colors ar corners of the tile.
+01745         CRGBA   corners[4];
+01746         getCurrentTileTLIColors(ts, tt, corners);
+01747 
+01748         // compute this pixel, and modulate
+01749         bilinearColorAndAdd(corners, s, t, *dest);
+01750 }
+01751 
+01752 
+01753 // ***************************************************************************
+01754 void            CPatch::computeCurrentTLILightmap(NLMISC::CRGBA *array) const
+01755 {
+01756         // Size of TileLightInfluences
+01757         uint    wTLI= (OrderS>>1)+1;
+01758         uint    hTLI= (OrderT>>1)+1;
+01759         // colros at corners of tiles size.
+01760         uint    wTC= OrderS+1;
+01761         uint    wTCx2= wTC*2;
+01762         uint    hTC= OrderT+1;
+01763         uint    x, y;
+01764 
+01765         // Compute TLI colors at each corner of each TessBlocks.
+01766         //=============
+01767         for(y=0;y<hTLI;y++)
+01768         {
+01769                 // store every 2 tiles corners.
+01770                 CRGBA   *dst= array + y*2*wTC;
+01771                 for(x=0;x<wTLI;x++)
+01772                 {
+01773                         *dst= getCurrentTLIColor(x, y);
+01774                         // skip 2 tiles corners.
+01775                         dst++;
+01776                         dst++;
+01777                 }
+01778         }
+01779 
+01780         // Compute TLI colors at each corner of each Tiles.
+01781         //=============
+01782 
+01783         // Compute corner at middle of vertical TessBlock edges.
+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                         // Average midlle with cur and next.
+01790                         (dst+wTC)->avg2RGBOnly(*dst, *(dst + wTCx2) );
+01791 
+01792                         // skip 2 tiles corners.
+01793                         dst++;
+01794                         dst++;
+01795                 }
+01796         }
+01797 
+01798         // Compute corner at middle of horizontal TessBlock edges, and at middle of TessBlock.
+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                         // Average midlle with cur and next.
+01805                         (dst+1)->avg2RGBOnly(*dst, *(dst+2));
+01806 
+01807                         // skip 2 tiles corners.
+01808                         dst++;
+01809                         dst++;
+01810                 }
+01811         }
+01812 
+01813 
+01814 }
+01815 
+01816 
+01817 
+01818 // ***************************************************************************
+01819 // ***************************************************************************
+01820 // UpdateLighting.
+01821 // ***************************************************************************
+01822 // ***************************************************************************
+01823 
+01824 
+01825 // ***************************************************************************
+01826 void CPatch::linkBeforeNearUL(CPatch *patchNext)
+01827 {
+01828         nlassert(patchNext);
+01829 
+01830         // first, unlink others from me. NB: works even if _ULNearPrec==_ULNearNext==this.
+01831         _ULNearNext->_ULNearPrec= _ULNearPrec;
+01832         _ULNearPrec->_ULNearNext= _ULNearNext;
+01833         // link to igNext.
+01834         _ULNearNext= patchNext;
+01835         _ULNearPrec= patchNext->_ULNearPrec;
+01836         // link others to me.
+01837         _ULNearNext->_ULNearPrec= this;
+01838         _ULNearPrec->_ULNearNext= this;
+01839 }
+01840 
+01841 
+01842 // ***************************************************************************
+01843 void CPatch::unlinkNearUL()
+01844 {
+01845         // first, unlink others from me. NB: works even if _ULNearPrec==_ULNearNext==this.
+01846         _ULNearNext->_ULNearPrec= _ULNearPrec;
+01847         _ULNearPrec->_ULNearNext= _ULNearNext;
+01848         // reset
+01849         _ULNearPrec= this;
+01850         _ULNearNext= this;
+01851 }
+01852 
+01853 
+01854 // ***************************************************************************
+01855 uint CPatch::updateTessBlockLighting(uint numTb)
+01856 {
+01857         // TessBlocks must have been allocated and tessBlockId must be ok.
+01858         nlassert(numTb<TessBlocks.size());
+01859 
+01860         // compute tessBlock coordinate
+01861         uint tbWidth= OrderS>>1;
+01862         uint ts= numTb&(tbWidth-1);
+01863         uint tt= numTb/tbWidth;
+01864         // expand to tile coordinate.
+01865         ts*= 2;
+01866         tt*= 2;
+01867 
+01868         // get what tessBlock to use.
+01869         CTessBlock      &tessBlock= TessBlocks[numTb];
+01870 
+01871         // If the lightmap Id has not been computed, quit
+01872         if(tessBlock.LightMapRefCount==0)
+01873                 return 0;
+01874         else
+01875         {
+01876                 // Recompute the lightmap texture, with help of TileColors, with neighboring info etc...
+01877                 CRGBA   lightText[NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE];
+01878                 computeNearBlockLightmap(ts&(~1), tt&(~1), lightText);
+01879 
+01880                 // donlod this texture to Driver etc...
+01881                 Zone->Landscape->refillTileLightMap(tessBlock.LightMapId, lightText);
+01882 
+01883                 // return number of pixels computed.
+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         // the patch must be compiled.
+01899         nlassert(Zone);
+01900 
+01901         // if 0, create the context.
+01902         if(_DLMContextRefCount==0)
+01903         {
+01904                 nlassert(_DLMContext==NULL);
+01905                 _DLMContext= new CPatchDLMContext;
+01906                 // init now the context.
+01907                 _DLMContext->generate(this, getLandscape()->getTextureDLM(), getLandscape()->getPatchDLMContextList());
+01908 
+01909                 // If the patch is visible, it may have Far Vertices created, 
+01910                 // hence, we must refill them with good DLM Uvs.
+01911                 if(!RenderClipped)
+01912                 {
+01913                         // setup DLM Uv with new _DLMContext
+01914                         fillVBFarsDLMUvOnly();
+01915                 }
+01916         }
+01917 
+01918         // incRef.
+01919         _DLMContextRefCount++;
+01920 }
+01921 
+01922 // ***************************************************************************
+01923 void                            CPatch::decRefDLMContext(uint count)
+01924 {
+01925         // the patch must be compiled.
+01926         nlassert(Zone);
+01927         nlassert(_DLMContextRefCount>0);
+01928 
+01929         // dec Ref.
+01930         _DLMContextRefCount-= count;
+01931         nlassert(_DLMContextRefCount>=0);
+01932 
+01933         // If 0, delete the context.
+01934         if(_DLMContextRefCount==0)
+01935         {
+01936                 delete _DLMContext;
+01937                 _DLMContext= NULL;
+01938 
+01939                 // If the patch is visible, it may have Far Vertices created, 
+01940                 // hence, we must reset their DLM Uvs (to point to black pixel)
+01941                 if(!RenderClipped)
+01942                 {
+01943                         // setup DLM Uv with new _DLMContext
+01944                         fillVBFarsDLMUvOnly();
+01945                 }
+01946         }
+01947 }
+01948 
+01949 
+01950 // ***************************************************************************
+01951 void            CPatch::beginDLMLighting()
+01952 {
+01953         nlassert(_DLMContext);
+01954 
+01955         // Must bkup prec pointLightCount in OldPointLightCount, and reset CurPointLightCount
+01956         _DLMContext->OldPointLightCount= _DLMContext->CurPointLightCount;
+01957         _DLMContext->CurPointLightCount= 0;
+01958 
+01959         // clear lighting, only if patch is visible
+01960         if(!RenderClipped)
+01961                 // NB: no-op if src is already full black.
+01962                 _DLMContext->clearLighting();
+01963 
+01964 }
+01965 
+01966 // ***************************************************************************
+01967 void            CPatch::processDLMLight(CPatchDLMPointLight &pl)
+01968 {
+01969         // add reference to currentLight, creating DLMContext if needed
+01970         addRefDLMContext();
+01971 
+01972         // add curLight counter
+01973         _DLMContext->CurPointLightCount++;
+01974 
+01975         // compute lighting, only if patch is visible
+01976         if(!RenderClipped)
+01977                 _DLMContext->addPointLightInfluence(pl);
+01978 }
+01979 
+01980 // ***************************************************************************
+01981 void            CPatch::endDLMLighting()
+01982 {
+01983         nlassert(_DLMContext);
+01984 
+01985         // delete reference from old pointLight influences, at prec render() pass. _DLMContext may be deleted here,
+01986         // if no more lights use it, and if the patch is not in Near.
+01987         decRefDLMContext(_DLMContext->OldPointLightCount);
+01988 }
+01989 
+01990 
+01991 } // NL3D
+01992 
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1