# 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  

texture_far.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 #include "std3d.h"
00027 
00028 #include "3d/texture_far.h"
00029 #include "3d/tile_far_bank.h"
00030 #include "3d/patch.h"
00031 #include "3d/tile_color.h"
00032 #include "3d/zone.h"
00033 #include "3d/landscape.h"
00034 #include "nel/misc/system_info.h"
00035 
00036 
00037 using namespace NLMISC;
00038 using namespace NL3D;
00039 
00040 namespace NL3D {
00041 
00042 CRGBA CTextureFar::_LightmapExpanded[NL_NUM_PIXELS_ON_FAR_TILE_EDGE*NL_MAX_TILES_BY_PATCH_EDGE*NL_NUM_PIXELS_ON_FAR_TILE_EDGE*NL_MAX_TILES_BY_PATCH_EDGE];
00043 uint8 CTextureFar::_LumelExpanded[(NL_MAX_TILES_BY_PATCH_EDGE*NL_LUMEL_BY_TILE+1)*(NL_MAX_TILES_BY_PATCH_EDGE*NL_LUMEL_BY_TILE+1)];
00044 CRGBA CTextureFar::_TileTLIColors[(NL_MAX_TILES_BY_PATCH_EDGE+1)*(NL_MAX_TILES_BY_PATCH_EDGE+1)];
00045 
00046 CTextureFar::CTextureFar()
00047 {
00048         // This texture is releasable. It doesn't stays in standard memory after been uploaded into video memory.
00049         setReleasable (true);
00050 
00051         _ULPrec= this;
00052         _ULNext= this;
00053 }
00054 
00055 CTextureFar::~CTextureFar()
00056 {
00057         // verify the textureFar is correctly unlinked from any ciruclar list.
00058         nlassert(_ULPrec==this && _ULNext==this);
00059 }
00060 
00061 
00062 void CTextureFar::linkBeforeUL(CTextureFar *textNext)
00063 {
00064         nlassert(textNext);
00065 
00066         // first, unlink others from me. NB: works even if _ULPrec==_ULNext==this.
00067         _ULNext->_ULPrec= _ULPrec;
00068         _ULPrec->_ULNext= _ULNext;
00069         // link to igNext.
00070         _ULNext= textNext;
00071         _ULPrec= textNext->_ULPrec;
00072         // link others to me.
00073         _ULNext->_ULPrec= this;
00074         _ULPrec->_ULNext= this;
00075 }
00076 
00077 void CTextureFar::unlinkUL()
00078 {
00079         // first, unlink others from me. NB: works even if _ULPrec==_ULNext==this.
00080         _ULNext->_ULPrec= _ULPrec;
00081         _ULPrec->_ULNext= _ULNext;
00082         // reset
00083         _ULPrec= this;
00084         _ULNext= this;
00085 }
00086 
00087 
00088 void CTextureFar::setSizeOfFarPatch (sint width, sint height)
00089 {
00090         // Resizing the bitmap
00091         _OriginalWidth=width*NL_NUM_FAR_PATCHES_BY_EDGE;
00092         _OriginalHeight=height*NL_NUM_FAR_PATCHES_BY_EDGE;
00093 
00094         // Resize patch array
00095         contReset (_Patches);
00096         _Patches.resize (NL_NUM_FAR_PATCHES_BY_TEXTURE);
00097 
00098         // Init count of patch
00099         _PatchCount=0;
00100 
00101         // Init upload format 16 bits
00102         setUploadFormat(RGB565);
00103 
00104         // Set filter mode. No mipmap!
00105         setFilterMode (Linear, LinearMipMapOff);
00106 
00107         // Wrap
00108         setWrapS (Clamp);
00109         setWrapT (Clamp);
00110 
00111         // Init patch array
00112         for (sint p=0; p<NL_NUM_FAR_PATCHES_BY_TEXTURE; p++)
00113         {
00114                 // Set patch pointer to NULL
00115                 _Patches[p].Patch=NULL;
00116         }
00117 }
00118 
00119 // Add a patch in the CTexture Patch. Must not be full! Return true if the texture is full after adding this patch else false.
00120 bool CTextureFar::addPatch (CPatch *pPatch, float& farUScale, float& farVScale, float& farUBias, float& farVBias, bool& bRot)
00121 {
00122         // Check that at least a cell is free
00123         nlassert (_PatchCount<NL_NUM_FAR_PATCHES_BY_TEXTURE);
00124 
00125         // Look for a free cell
00126         sint p;
00127         for (p=0; p<NL_NUM_FAR_PATCHES_BY_TEXTURE; p++)
00128         {
00129                 // Cell is NULL ?
00130                 if (_Patches[p].Patch==NULL)
00131                 {
00132                         // Put the patch here and go out.
00133                         _Patches[p].Patch=pPatch;
00134                         break;
00135                 }
00136         }
00137         // Check that at least a cell is free
00138         nlassert (p<NL_NUM_FAR_PATCHES_BY_TEXTURE);
00139 
00140         // Position of the invalide rectangle
00141         int x = ((p & NL_NUM_FAR_PATCHES_BY_EDGE_MASK) * _OriginalWidth) >> NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT;
00142         int y = ((p >> NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT) * _OriginalHeight) >> NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT;
00143 
00144         // Invalidate the rectangle
00145         CRect rect (x, y, _OriginalWidth>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT, _OriginalHeight>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT);
00146         ITexture::touchRect (rect);
00147 
00148         // ** Return some values
00149 
00150         // Rotation flag
00151         bRot = ( pPatch->getOrderS() < pPatch->getOrderT() );
00152 
00153         // Scale is the same for all
00154         farUScale=(float)((_OriginalWidth>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)-1)/(float)_OriginalWidth;
00155         farVScale=(float)((_OriginalHeight>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)-1)/(float)_OriginalHeight;
00156 
00157         // UBias is the same for all
00158         farUBias=((float)x+0.5f)/(float)_OriginalWidth;
00159 
00160         // UBias is the same for all
00161         farVBias=((float)y+0.5f)/(float)_OriginalHeight;
00162         
00163         // One more patch
00164         _PatchCount++;
00165 
00166         return (_PatchCount == NL_NUM_FAR_PATCHES_BY_TEXTURE);
00167 }
00168 
00169 // Remove a patch in the CTexture Patch
00170 bool CTextureFar::removePatch (CPatch *pPatch)
00171 {
00172         // Check that at least a cell is used
00173         nlassert (_PatchCount>0);
00174 
00175         // Look for the patch free cell
00176         sint p;
00177         for (p=0; p<NL_NUM_FAR_PATCHES_BY_TEXTURE; p++)
00178         {
00179                 // Is the good cell ?
00180                 if (_Patches[p].Patch==pPatch)
00181                 {
00182                         // ok, remove it
00183                         _Patches[p].Patch=NULL;
00184                         break;
00185                 }
00186         }
00187 
00188         // Check it has been found
00189         nlassert (p<NL_NUM_FAR_PATCHES_BY_TEXTURE);
00190 
00191         // One patch less
00192         _PatchCount--;
00193 
00194         // Return true if it is empty, else return false
00195         return (_PatchCount == 0);
00196 }
00197 
00198 uint CTextureFar::touchPatch(uint p)
00199 {
00200         // Check param
00201         nlassert (p<NL_NUM_FAR_PATCHES_BY_TEXTURE);
00202 
00203         // if there is still a patch here
00204         if( _Patches[p].Patch!=NULL )
00205         {
00206                 // Position of the invalide rectangle
00207                 int x = ((p & NL_NUM_FAR_PATCHES_BY_EDGE_MASK) * _OriginalWidth) >> NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT;
00208                 int y = ((p >> NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT) * _OriginalHeight) >> NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT;
00209 
00210                 // Invalidate the associated rectangle
00211                 CRect rect (x, y, _OriginalWidth>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT, _OriginalHeight>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT);
00212                 ITexture::touchRect (rect);
00213 
00214                 // return number of pixels touched
00215                 return (_OriginalWidth>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT) * (_OriginalHeight>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT);
00216         }
00217         else
00218         {
00219                 // no touch
00220                 return 0;
00221         }
00222 }
00223 
00224 // Generate the texture. See ITexture::doGenerate().
00225 void CTextureFar::doGenerate ()
00226 {
00227         // Resize
00228         CBitmap::resize (_OriginalWidth, _OriginalHeight, RGBA);
00229 
00230         // Rectangle invalidate ?
00231         if (_ListInvalidRect.begin()!=_ListInvalidRect.end())
00232         {
00233                 // Yes, rebuild only those rectangles.
00234 
00235                 // For each rectangle to compute
00236                 std::list<NLMISC::CRect>::iterator ite=_ListInvalidRect.begin();
00237                 while (ite!=_ListInvalidRect.end())
00238                 {
00239                         // Compute rectangle coordinates
00240                         sint x=(ite->left()<<NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)/_Width;
00241                         sint y=(ite->top()<<NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)/_Height;
00242 
00243                         // X and Y coord should be >0 and not be greater or equal to the number of patch stored on a texture edge.
00244                         nlassert (x>=0);
00245                         nlassert (x<NL_NUM_FAR_PATCHES_BY_EDGE);
00246                         nlassert (y>=0);
00247                         nlassert (y<NL_NUM_FAR_PATCHES_BY_EDGE);
00248 
00249                         // ReBuild the rectangle. verify first patch still exist.
00250                         if (_Patches[x+(y<<NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)].Patch)
00251                                 rebuildRectangle (x, y);
00252 
00253                         // Next rectangle
00254                         ite++;
00255                 }
00256         }
00257         else
00258         {
00259                 // no, rebuild all the rectangle
00260                 for (sint y=0; y<NL_NUM_FAR_PATCHES_BY_EDGE; y++)
00261                 for (sint x=0; x<NL_NUM_FAR_PATCHES_BY_EDGE; x++)
00262                 {
00263                         // Rebuild this rectangle
00264                         if (_Patches[x+(y<<NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)].Patch)
00265                                 rebuildRectangle (x, y);
00266                 }
00267         }
00268 }
00269 
00270 
00271 // Rebuild the rectangle passed with coordinate passed in parameter
00272 void CTextureFar::rebuildRectangle (uint x, uint y)
00273 {
00274         // Patch pointer
00275         CPatch* patch=_Patches[x+(y<<NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)].Patch;
00276 
00277         // Check it exists
00278         nlassert (patch);
00279 
00280         // get the order
00281         uint nS=patch->getOrderS();
00282         uint nT=patch->getOrderT();
00283 
00284         // Check it is a 16 bits texture
00285         nlassert (getPixelFormat()==RGBA);
00286 
00287         // Check pixels exist
00288         nlassert (getPixels().size()!=0);
00289 
00290         // Base offset of the first pixel of the patch's texture
00291         uint    nBaseOffset;
00292 
00293         // Delta to add to the destination offset when walk for a pixel to the right in the source tile
00294         sint dstDeltaX;
00295 
00296         // Delta to add to the destination offset when walk for a pixel to the bottom in the source tile
00297         sint dstDeltaY;
00298 
00299         // larger size
00300         uint larger;
00301 
00302         // larger than higher  (regular)
00303         if (nS>=nT)
00304         {
00305                 // Regular offset, top left
00306                 nBaseOffset=((x*_Width)>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)+((y*_Height)>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)*_Width;
00307 
00308                 // Regular deltaX, to the right
00309                 dstDeltaX=1;
00310 
00311                 // Regular deltaY, to the bottom
00312                 dstDeltaY=_Width;
00313 
00314                 // Larger size
00315                 larger=nS;
00316         }
00317         // higher than larger (goofy), the patch is stored with a rotation of 1 (to the left of course)
00318         else
00319         {
00320                 // Goofy offset, bottom left
00321                 nBaseOffset=((x*_Width)>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)+((y*_Height)>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)*_Width;
00322                 nBaseOffset+=((_Height>>NL_NUM_FAR_PATCHES_BY_EDGE_SHIFT)-1)*_Width;
00323 
00324                 // Goofy deltaX, to the top
00325                 dstDeltaX=-(sint)_Width;
00326 
00327                 // Goofy deltaY, to the right
00328                 dstDeltaY=1;
00329 
00330                 // Larger size
00331                 larger=nT;
00332         }
00333                 
00334         // Compute the order of the patch
00335         CTileFarBank::TFarOrder orderX=CTileFarBank::order0;
00336         uint tileSize=0;
00337         switch ((larger*NL_NUM_FAR_PATCHES_BY_EDGE*NL_NUM_PIXELS_ON_FAR_TILE_EDGE)/_Width)
00338         {
00339         case 4:
00340                 // Ratio 1:4
00341                 orderX=CTileFarBank::order2;
00342                 tileSize=NL_NUM_PIXELS_ON_FAR_TILE_EDGE>>2;
00343                 break;
00344         case 2:
00345                 // Ratio 1:2
00346                 orderX=CTileFarBank::order1;
00347                 tileSize=NL_NUM_PIXELS_ON_FAR_TILE_EDGE>>1;
00348                 break;
00349         case 1:
00350                 // Ratio 1:1
00351                 orderX=CTileFarBank::order0;
00352                 tileSize=NL_NUM_PIXELS_ON_FAR_TILE_EDGE;
00353                 break;
00354         default:
00355                 // no!: must be one of the previous values
00356                 nlassert (0);
00357         }
00358 
00359 #ifdef NL_DEBUG
00360         // Compute the Y order
00361         CTileFarBank::TFarOrder orderY;
00362         switch ((std::min(nS, nT)*NL_NUM_FAR_PATCHES_BY_EDGE*NL_NUM_PIXELS_ON_FAR_TILE_EDGE)/_Height)
00363         {
00364         case 4:
00365                 // Ratio 1:4
00366                 orderY=CTileFarBank::order2;
00367                 break;
00368         case 2:
00369                 // Ratio 1:2
00370                 orderY=CTileFarBank::order1;
00371                 break;
00372         case 1:
00373                 // Ratio 1:1
00374                 orderY=CTileFarBank::order0;
00375                 break;
00376         default:
00377                 // no!: must be one of the previous values
00378                 nlassert (0);
00379         }
00380 
00381         // Check the ratio on Y is the same than on X
00382         nlassert (orderX == orderY);
00383 #endif // NL_DEBUG
00384         // Must have a far tile bank pointer set in the CFarTexture
00385         nlassert (_Bank);
00386 
00387         // For all the tiles in the textures
00388         sint nTileInPatch=0;
00389 
00390         // ** Fill the struct for the tile fill method for each layers
00391         NL3D_CComputeTileFar TileFar;
00392         TileFar.AsmMMX= false;
00393 #ifdef NL_OS_WINDOWS
00394         TileFar.AsmMMX= NLMISC::CSystemInfo::hasMMX();
00395 #endif
00396 
00397         // Destination pointer
00398 
00399         // Destination delta
00400         TileFar.DstDeltaX=dstDeltaX;
00401         TileFar.DstDeltaY=dstDeltaY;
00402 
00403         // ** Build expand lightmap..
00404         NL3D_CExpandLightmap lightMap;
00405         
00406         // Fill the structure
00407         lightMap.MulFactor=tileSize;
00408         lightMap.ColorTile=&patch->TileColors[0];
00409         lightMap.Width=nS+1;
00410         lightMap.Height=nT+1;
00411         lightMap.StaticLightColor=patch->getZone()->getLandscape()->getStaticLight();
00412         lightMap.DstPixels=_LightmapExpanded;
00413         // Compute current TLI colors.
00414         patch->computeCurrentTLILightmap(_TileTLIColors);
00415         lightMap.TLIColor= _TileTLIColors;
00416 
00417         // Expand the shadowmap
00418         patch->unpackShadowMap (_LumelExpanded);
00419         lightMap.LumelTile=_LumelExpanded;
00420 
00421         // Expand the patch lightmap now
00422         NL3D_expandLightmap (&lightMap);
00423 
00424         // DeltaY for lightmap
00425         TileFar.SrcLightingDeltaY=nS*tileSize;
00426 
00427         // Base Dst pointer on the tile line
00428         uint nBaseDstTileLine=nBaseOffset;
00429         for (uint t=0; t<nT; t++)
00430         {
00431                 // Base Dst pointer on the tile
00432                 uint nBaseDstTilePixels=nBaseDstTileLine;
00433 
00434                 // For each tile of the line
00435                 for (uint s=0; s<nS; s++)
00436                 {
00437                         // Base pointer of the destination texture
00438                         TileFar.DstPixels=(CRGBA*)&(getPixels()[0])+nBaseDstTilePixels;
00439 
00440                         // Lightmap pointer
00441                         TileFar.SrcLightingPixels=_LightmapExpanded+(s*tileSize)+(t*nS*tileSize*tileSize);
00442 
00443                         // For each layer of the tile
00444                         for (sint l=0; l<3; l++)
00445                         {
00446                                 // Use of additive in this layer ?
00447                                 bool bAdditive=false;
00448 
00449                                 // Size of the edge far tile
00450                                 TileFar.Size=tileSize;
00451 
00452                                 // Get a tile element reference for this tile.
00453                                 const CTileElement &tileElm=patch->Tiles[nTileInPatch];
00454 
00455                                 // Check for 256 tiles...
00456                                 bool    is256x256;
00457                                 uint8   uvOff;
00458                                 tileElm.getTile256Info(is256x256, uvOff);
00459 
00460                                 // Get the tile number
00461                                 sint tile=tileElm.Tile[l];
00462 
00463                                 // Is the last layer ?
00464                                 bool lastLayer = ( (l == 2) || (tileElm.Tile[l+1] == NL_TILE_ELM_LAYER_EMPTY) );
00465 
00466                                 // Is an non-empty layer ?
00467                                 if (tile!=NL_TILE_ELM_LAYER_EMPTY)
00468                                 {
00469                                         // Get the read only pointer on the far tile
00470                                         const CTileFarBank::CTileFar*   pTile=_Bank->getTile (tile);
00471 
00472                                         // This pointer must not be null, else the farBank is not valid!
00473                                         if (pTile==NULL)
00474                                                 nlwarning ("FarBank is not valid!");
00475 
00476                                         // If the tile exist
00477                                         if (pTile)
00478                                         {
00479                                                 // Tile exist ?
00480                                                 if (pTile->isFill (CTileFarBank::diffuse))
00481                                                 {
00482                                                         // Get rotation of the tile in this layer
00483                                                         sint nRot=tileElm.getTileOrient(l);
00484 
00485                                                         // Source pointer
00486                                                         const CRGBA*    pSrcDiffusePixels=pTile->getPixels (CTileFarBank::diffuse, orderX);
00487                                                         const CRGBA*    pSrcAdditivePixels=NULL;
00488 
00489                                                         // Additive ?
00490                                                         if (pTile->isFill (CTileFarBank::additive))
00491                                                         {
00492                                                                 // Use it
00493                                                                 bAdditive=true;
00494 
00495                                                                 // Get additive pointer
00496                                                                 pSrcAdditivePixels=pTile->getPixels (CTileFarBank::additive, orderX);
00497                                                         }
00498 
00499                                                         // Source size
00500                                                         sint sourceSize;
00501 
00502                                                         // Source offset (for 256)
00503                                                         uint sourceOffset=0;
00504 
00505                                                         // 256 ?
00506                                                         if (is256x256)
00507                                                         {
00508                                                                 // On the left ?
00509                                                                 if (uvOff&0x02)
00510                                                                         sourceOffset+=tileSize;
00511 
00512                                                                 // On the bottom ?
00513                                                                 if ((uvOff==1)||(uvOff==2))
00514                                                                         sourceOffset+=2*tileSize*tileSize;
00515 
00516                                                                 // Yes, 256
00517                                                                 sourceSize=tileSize<<1;
00518                                                         }
00519                                                         else
00520                                                         {
00521                                                                 // No, 128
00522                                                                 sourceSize=tileSize;
00523                                                         }
00524 
00525                                                         // Compute offset and deltas
00526                                                         switch (nRot)
00527                                                         {
00528                                                         case 0:
00529                                                                 // Source pointers
00530                                                                 TileFar.SrcDiffusePixels=pSrcDiffusePixels+sourceOffset;
00531                                                                 TileFar.SrcAdditivePixels=pSrcAdditivePixels+sourceOffset;
00532 
00533                                                                 // Source delta
00534                                                                 TileFar.SrcDeltaX=1;
00535                                                                 TileFar.SrcDeltaY=sourceSize;
00536                                                                 break;
00537                                                         case 1:
00538                                                                 {
00539                                                                         // Source pointers
00540                                                                         uint newOffset=sourceOffset+(tileSize-1);
00541                                                                         TileFar.SrcDiffusePixels=pSrcDiffusePixels+newOffset;
00542                                                                         TileFar.SrcAdditivePixels=pSrcAdditivePixels+newOffset;
00543 
00544                                                                         // Source delta
00545                                                                         TileFar.SrcDeltaX=sourceSize;
00546                                                                         TileFar.SrcDeltaY=-1;
00547                                                                 }
00548                                                                 break;
00549                                                         case 2:
00550                                                                 {
00551                                                                         // Destination pointer
00552                                                                         uint newOffset=sourceOffset+(tileSize-1)*sourceSize+tileSize-1;
00553                                                                         TileFar.SrcDiffusePixels=pSrcDiffusePixels+newOffset;
00554                                                                         TileFar.SrcAdditivePixels=pSrcAdditivePixels+newOffset;
00555 
00556                                                                         // Source delta
00557                                                                         TileFar.SrcDeltaX=-1;
00558                                                                         TileFar.SrcDeltaY=-sourceSize;
00559                                                                 }
00560                                                                 break;
00561                                                         case 3:
00562                                                                 {
00563                                                                         // Destination pointer
00564                                                                         uint newOffset=sourceOffset+(tileSize-1)*sourceSize;
00565                                                                         TileFar.SrcDiffusePixels=pSrcDiffusePixels+newOffset;
00566                                                                         TileFar.SrcAdditivePixels=pSrcAdditivePixels+newOffset;
00567 
00568                                                                         // Source delta
00569                                                                         TileFar.SrcDeltaX=-sourceSize;
00570                                                                         TileFar.SrcDeltaY=1;
00571                                                                 }
00572                                                                 break;
00573                                                         }
00574 
00575                                                         // *** Draw the layer
00576 
00577                                                         // Alpha layer ?
00578                                                         if (l>0)
00579                                                         {
00580                                                                 // Additive layer ?
00581                                                                 if (bAdditive && lastLayer)
00582                                                                         NL3D_drawFarTileInFarTextureAdditiveAlpha (&TileFar);
00583                                                                 else    // No additive layer
00584                                                                         NL3D_drawFarTileInFarTextureAlpha (&TileFar);
00585                                                         }
00586                                                         else    // no alpha
00587                                                         {
00588                                                                 // Additive layer ?
00589                                                                 if (bAdditive && lastLayer)
00590                                                                         NL3D_drawFarTileInFarTextureAdditive (&TileFar);
00591                                                                 else    // No additive layer
00592                                                                         NL3D_drawFarTileInFarTexture (&TileFar);
00593                                                         }
00594                                                 }
00595                                         }
00596                                 }
00597                                 else
00598                                         // Stop, no more layer
00599                                         break;
00600                         }
00601                                                 
00602                         // Next tile
00603                         nTileInPatch++;
00604                         
00605                         // Next tile on the line
00606                         nBaseDstTilePixels+=dstDeltaX*tileSize;
00607                 }
00608 
00609                 // Next line of tiles
00610                 nBaseDstTileLine+=dstDeltaY*tileSize;
00611         }
00612 
00613 }
00614 
00615 } // NL3D
00616 
00617 
00618 // ***************************************************************************
00619 // ***************************************************************************
00620 // NL3D_ExpandLightmap. C and Asm Part
00621 // ***************************************************************************
00622 // ***************************************************************************
00623 
00624 #ifdef NL_OS_WINDOWS
00625 
00626 
00627 // EMMS called not in __asm block.
00628 #  pragma warning (disable : 4799)
00629 
00630 
00631 // ***************************************************************************
00632 inline  void    NL3D_asmEndMMX()
00633 {
00634         __asm
00635         {
00636                 // close MMX computation
00637                 emms
00638         }
00639 }
00640 
00641 
00642 // ***************************************************************************
00646 inline  void    NL3D_asmExpandLineColor565(const uint16 *src, CRGBA *dst, uint du, uint len)
00647 {
00648         static  uint64 blank = 0;
00649         static  uint64 cF800 = 0x0000F8000000F800;
00650         static  uint64 cE000 = 0x0000E0000000E000;
00651         static  uint64 c07E0 = 0x000007E0000007E0;
00652         static  uint64 c0600 = 0x0000060000000600;
00653         static  uint64 c001F = 0x0000001F0000001F;
00654         static  uint64 c001C = 0x0000001C0000001C;
00655         if(len==0)
00656                 return;
00657 
00658 
00659         // Loop for pix.
00660         __asm
00661         {
00662                 movq    mm7, blank
00663 
00664                 // start at pixel 1 => increment dst, and start u= du
00665                 mov             esi, src
00666                 mov             edi, dst
00667                 add             edi, 4
00668                 mov             ecx, len
00669                 mov             edx, du
00670 
00671                 // Loop
00672         myLoop:
00673 
00674 
00675                 // Read 565 colors
00676                 //----------
00677                 // index u.
00678                 mov             ebx, edx
00679                 shr             ebx, 8
00680 
00681                 // pack the 2 colors in eax: // Hedx= color0, Ledx= color1
00682                 xor             eax, eax                        // avoid partial stall.
00683                 mov             ax, [esi + ebx*2]
00684                 shl             eax, 16
00685                 mov             ax, [esi + ebx*2 +2]
00686                 
00687                 // store and unpack in mm2: Hmm2= color0, Lmm2= color1
00688                 movd    mm2, eax
00689                 punpcklwd       mm2, mm7
00690 
00691                 // reset accumulator mm3 to black
00692                 movq    mm3, mm7
00693 
00694                 // Expand 565 to 888: color0 and color1 in parrallel
00695                 // R
00696                 movq    mm0, mm2
00697                 movq    mm1, mm2
00698                 pand    mm0, cF800
00699                 pand    mm1, cE000
00700                 psrld   mm0, 8
00701                 psrld   mm1, 13
00702                 por             mm3, mm0
00703                 por             mm3, mm1
00704                 // G
00705                 movq    mm0, mm2
00706                 movq    mm1, mm2
00707                 pand    mm0, c07E0
00708                 pand    mm1, c0600
00709                 pslld   mm0, 5
00710                 psrld   mm1, 1
00711                 por             mm3, mm0
00712                 por             mm3, mm1
00713                 // B
00714                 movq    mm0, mm2
00715                 movq    mm1, mm2
00716                 pand    mm0, c001F
00717                 pand    mm1, c001C
00718                 pslld   mm0, 19
00719                 pslld   mm1, 14
00720                 por             mm3, mm0
00721                 por             mm3, mm1
00722 
00723                 // unpack mm3 quad to mm0=color0 and mm1=color1.
00724                 movq    mm0, mm3
00725                 movq    mm1, mm3
00726                 psrlq   mm0, 32
00727 
00728 
00729                 // Blend.
00730                 //----------
00731                 // blend factors
00732                 mov             ebx, edx
00733                 mov             eax, 256
00734 
00735                 and             ebx, 0xFF
00736                 sub             eax, ebx
00737 
00738                 movd    mm2, ebx                // mm2= factor
00739                 movd    mm3, eax                // mm3= 1-factor
00740                 // replicate to the     4 words.
00741                 punpckldq       mm2, mm2        // mm2= 0000 00AA 0000 00AA
00742                 punpckldq       mm3, mm3        // mm3= 0000 00AA 0000 00AA
00743                 packssdw        mm2, mm2        // mm2= 00AA 00AA 00AA 00AA
00744                 packssdw        mm3, mm3        // mm3= 00AA 00AA 00AA 00AA
00745 
00746                 // mul
00747                 punpcklbw       mm0, mm7
00748                 punpcklbw       mm1, mm7
00749                 pmullw          mm0, mm3        // color0*(1-factor)
00750                 pmullw          mm1, mm2        // color1*factor
00751                 // add, and unpack
00752                 paddusw         mm0, mm1
00753                 psrlw       mm0, 8
00754                 packuswb    mm0, mm0
00755 
00756                 // store
00757                 movd        [edi], mm0
00758 
00759 
00760                 // next pix
00761                 add     edx, du
00762                 add     edi, 4
00763                 dec ecx
00764                 jnz myLoop
00765         }
00766 }
00767 
00768 
00769 // ***************************************************************************
00773 inline  void    NL3D_asmExpandLineColor8888(const CRGBA *src, CRGBA *dst, uint du, uint len)
00774 {
00775         static  uint64 blank = 0;
00776         if(len==0)
00777                 return;
00778 
00779 
00780         // Loop for pix.
00781         __asm
00782         {
00783                 movq    mm7, blank
00784 
00785                 // start at pixel 1 => increment dst, and start u= du
00786                 mov             esi, src
00787                 mov             edi, dst
00788                 add             edi, 4
00789                 mov             ecx, len
00790                 mov             edx, du
00791 
00792                 // Loop
00793         myLoop:
00794 
00795 
00796                 // Read 8888 colors
00797                 //----------
00798                 // index u.
00799                 mov             ebx, edx
00800                 shr             ebx, 8
00801 
00802                 // read the 2 colors: mm0= color0, mm1= color1
00803                 movd    mm0 , [esi + ebx*4]
00804                 movd    mm1 , [esi + ebx*4 + 4]
00805 
00806 
00807                 // Blend.
00808                 //----------
00809                 // blend factors
00810                 mov             ebx, edx
00811                 mov             eax, 256
00812 
00813                 and             ebx, 0xFF
00814                 sub             eax, ebx
00815 
00816                 movd    mm2, ebx                // mm2= factor
00817                 movd    mm3, eax                // mm3= 1-factor
00818                 // replicate to the     4 words.
00819                 punpckldq       mm2, mm2        // mm2= 0000 00AA 0000 00AA
00820                 punpckldq       mm3, mm3        // mm3= 0000 00AA 0000 00AA
00821                 packssdw        mm2, mm2        // mm2= 00AA 00AA 00AA 00AA
00822                 packssdw        mm3, mm3        // mm3= 00AA 00AA 00AA 00AA
00823 
00824                 // mul
00825                 punpcklbw       mm0, mm7
00826                 punpcklbw       mm1, mm7
00827                 pmullw          mm0, mm3        // color0*(1-factor)
00828                 pmullw          mm1, mm2        // color1*factor
00829                 // add, and unpack
00830                 paddusw         mm0, mm1
00831                 psrlw       mm0, 8
00832                 packuswb    mm0, mm0
00833 
00834                 // store
00835                 movd        [edi], mm0
00836 
00837 
00838                 // next pix
00839                 add     edx, du
00840                 add     edi, 4
00841                 dec ecx
00842                 jnz myLoop
00843         }
00844 }
00845 
00846 
00847 // ***************************************************************************
00851 inline  void    NL3D_asmBlendLines(CRGBA *dst, const CRGBA *src0, const CRGBA *src1, uint index, uint len)
00852 {
00853         static  uint64 blank = 0;
00854         if(len==0)
00855                 return;
00856 
00857 
00858         // Loop for pix.
00859         __asm
00860         {
00861                 movq    mm7, blank
00862 
00863                 // read the factor and expand it to 4 words.
00864                 mov             ebx, index
00865                 mov             eax, 256
00866                 and             ebx, 0xFF
00867                 sub             eax, ebx
00868                 movd    mm2, ebx                // mm2= factor
00869                 movd    mm3, eax                // mm3= 1-factor
00870                 punpckldq       mm2, mm2        // mm2= 0000 00AA 0000 00AA
00871                 punpckldq       mm3, mm3        // mm3= 0000 00AA 0000 00AA
00872                 packssdw        mm2, mm2        // mm2= 00AA 00AA 00AA 00AA
00873                 packssdw        mm3, mm3        // mm3= 00AA 00AA 00AA 00AA
00874 
00875                 // setup ptrs
00876                 mov             esi, src0
00877                 mov             edx, src1
00878                 sub             edx, esi        // difference between 2 src
00879                 mov             edi, dst
00880                 mov             ecx, len
00881 
00882                 // Loop
00883         myLoop:
00884 
00885                 // Read
00886                 movd    mm0, [esi]
00887                 movd    mm1, [esi+edx]
00888 
00889                 // mul
00890                 punpcklbw       mm0, mm7
00891                 punpcklbw       mm1, mm7
00892                 pmullw          mm0, mm3        // color0*(1-factor)
00893                 pmullw          mm1, mm2        // color1*factor
00894                 // add, and unpack
00895                 paddusw         mm0, mm1
00896                 psrlw       mm0, 8
00897                 packuswb    mm0, mm0
00898 
00899                 // store
00900                 movd        [edi], mm0
00901 
00902 
00903                 // next pix
00904                 add     esi, 4
00905                 add     edi, 4
00906                 dec ecx
00907                 jnz myLoop
00908         }
00909 }
00910 
00911 
00912 // ***************************************************************************
00916 static void             NL3D_asmAssembleShading1x1(const uint8 *lumels, const CRGBA *colorMap, 
00917         const CRGBA *srcTLIs, const CRGBA *srcUSCs, CRGBA *dst, uint lineWidth, uint nbTexel)
00918 {
00919         static  uint64 blank = 0;
00920         if(nbTexel==0)
00921                 return;
00922 
00923         // local var
00924         uint    offsetTLIs= ((uint)srcTLIs-(uint)dst);
00925         uint    offsetUSCs= ((uint)srcUSCs-(uint)dst);
00926 
00927         // Loop for pix.
00928         __asm
00929         {
00930                 movq            mm7, blank
00931 
00932                 // setup ptrs
00933                 mov                     esi, lumels
00934                 mov                     edi, dst
00935                 mov                     ecx, nbTexel
00936 
00937                 // Loop
00938         myLoop:
00939 
00940                 // Average shade part
00941                 //------------
00942                 mov                     ebx, colorMap
00943                 mov                     edx, lineWidth
00944 
00945                 // read and accumulate shade 
00946                 xor                     eax,eax                 // avoid partial stall
00947                 // add with line 0
00948                 mov                     al, [esi + 0]
00949                 add                     al, [esi + 1]
00950                 adc                     ah, 0
00951                 add                     al, [esi + 2]
00952                 adc                     ah, 0
00953                 add                     al, [esi + 3]
00954                 adc                     ah, 0
00955                 // add with line 1
00956                 add                     al, [esi + edx + 0]
00957                 adc                     ah, 0
00958                 add                     al, [esi + edx + 1]
00959                 adc                     ah, 0
00960                 add                     al, [esi + edx + 2]
00961                 adc                     ah, 0
00962                 add                     al, [esi + edx + 3]
00963                 adc                     ah, 0
00964                 // add with line 2
00965                 add                     al, [esi + edx*2 + 0]
00966                 adc                     ah, 0
00967                 add                     al, [esi + edx*2 + 1]
00968                 adc                     ah, 0
00969                 add                     al, [esi + edx*2 + 2]
00970                 adc                     ah, 0
00971                 add                     al, [esi + edx*2 + 3]
00972                 adc                     ah, 0
00973                 // add with line 3
00974                 lea                     edx, [edx + edx*2]
00975                 add                     al, [esi + edx + 0]
00976                 adc                     ah, 0
00977                 add                     al, [esi + edx + 1]
00978                 adc                     ah, 0
00979                 add                     al, [esi + edx + 2]
00980                 adc                     ah, 0
00981                 add                     al, [esi + edx + 3]
00982                 adc                     ah, 0
00983                 // average
00984                 shr                     eax, 4
00985 
00986                 // convert to RGBA from the color Map
00987                 movd            mm0, [ebx + eax*4]
00988 
00989                 // Assemble part
00990                 //------------
00991                 mov                     edx, offsetTLIs
00992                 mov                     ebx, offsetUSCs
00993 
00994                 // Add with TLI, and clamp.
00995                 paddusb         mm0, [edi + edx]
00996 
00997                 // mul with USC
00998                 movd            mm1, [edi + ebx]
00999                 punpcklbw       mm0, mm7
01000                 punpcklbw       mm1, mm7
01001                 pmullw          mm0, mm1
01002                 // unpack
01003                 psrlw       mm0, 8
01004                 packuswb    mm0, mm0
01005 
01006                 // store
01007                 movd        [edi], mm0
01008 
01009 
01010                 // next pix
01011                 add                     esi, 4          // skip 4 lumels
01012                 add                     edi, 4          // next texel
01013                 dec                     ecx
01014                 jnz                     myLoop
01015         }
01016 }
01017 
01018 
01019 // ***************************************************************************
01023 static void             NL3D_asmAssembleShading2x2(const uint8 *lumels, const CRGBA *colorMap, 
01024         const CRGBA *srcTLIs, const CRGBA *srcUSCs, CRGBA *dst, uint lineWidth, uint nbTexel)
01025 {
01026         static  uint64 blank = 0;
01027         if(nbTexel==0)
01028                 return;
01029 
01030         // local var
01031         uint    offsetTLIs= ((uint)srcTLIs-(uint)dst);
01032         uint    offsetUSCs= ((uint)srcUSCs-(uint)dst);
01033 
01034         // Loop for pix.
01035         __asm
01036         {
01037                 movq            mm7, blank
01038 
01039                 // setup ptrs
01040                 mov                     esi, lumels
01041                 mov                     edi, dst
01042                 mov                     ecx, nbTexel
01043 
01044                 // Loop
01045         myLoop:
01046 
01047                 // Average shade part
01048                 //------------
01049                 mov                     ebx, colorMap
01050                 mov                     edx, lineWidth
01051 
01052                 // read and accumulate shade 
01053                 xor                     eax,eax                 // avoid partial stall
01054                 mov                     al, [esi]               // read lumel
01055                 // add with nbors
01056                 add                     al, [esi + 1]
01057                 adc                     ah, 0
01058                 add                     al, [esi + edx]
01059                 adc                     ah, 0
01060                 add                     al, [esi + edx + 1]
01061                 adc                     ah, 0
01062                 // average
01063                 shr                     eax, 2
01064 
01065                 // convert to RGBA from the color Map
01066                 movd            mm0, [ebx + eax*4]
01067 
01068                 // Assemble part
01069                 //------------
01070                 mov                     edx, offsetTLIs
01071                 mov                     ebx, offsetUSCs
01072 
01073                 // Add with TLI, and clamp.
01074                 paddusb         mm0, [edi + edx]
01075 
01076                 // mul with USC
01077                 movd            mm1, [edi + ebx]
01078                 punpcklbw       mm0, mm7
01079                 punpcklbw       mm1, mm7
01080                 pmullw          mm0, mm1
01081                 // unpack
01082                 psrlw       mm0, 8
01083                 packuswb    mm0, mm0
01084 
01085                 // store
01086                 movd        [edi], mm0
01087 
01088 
01089                 // next pix
01090                 add                     esi, 2          // skip 2 lumels
01091                 add                     edi, 4          // next texel
01092                 dec                     ecx
01093                 jnz                     myLoop
01094         }
01095 }
01096 
01097 
01098 // ***************************************************************************
01099 #  pragma warning (disable : 4731)                      // frame pointer register 'ebp' modified by inline assembly code
01100 
01103 static void             NL3D_asmAssembleShading4x4(const uint8 *lumels, const CRGBA *colorMap, 
01104         const CRGBA *srcTLIs, const CRGBA *srcUSCs, CRGBA *dst, uint nbTexel)
01105 {
01106         static  uint64 blank = 0;
01107         if(nbTexel==0)
01108                 return;
01109 
01110         // Loop for pix.
01111         __asm
01112         {
01113                 // Use ebp as a register for faster access...
01114                 push            ebp
01115 
01116                 movq            mm7, blank
01117 
01118                 // setup ptrs
01119                 mov                     esi, lumels
01120                 mov                     edi, dst
01121                 mov                     edx, srcTLIs
01122                 sub                     edx, edi        // difference src and dest
01123                 mov                     ebx, srcUSCs
01124                 sub                     ebx, edi        // difference src and dest
01125                 mov                     ecx, nbTexel
01126 
01127                 // set ebp after reading locals...
01128                 mov                     ebp, colorMap
01129 
01130                 // Loop
01131         myLoop:
01132 
01133                 // read shade RGBA into the color Map
01134                 xor                     eax,eax                 // avoid partial stall
01135                 mov                     al,[esi]                // read lumel
01136                 movd            mm0, [ebp + eax*4]
01137 
01138                 // Add with TLI, and clamp.
01139                 paddusb         mm0, [edi + edx]
01140 
01141                 // mul with USC
01142                 movd            mm1, [edi + ebx]
01143                 punpcklbw       mm0, mm7
01144                 punpcklbw       mm1, mm7
01145                 pmullw          mm0, mm1
01146                 // unpack
01147                 psrlw       mm0, 8
01148                 packuswb    mm0, mm0
01149 
01150                 // store
01151                 movd        [edi], mm0
01152 
01153 
01154                 // next pix
01155                 add                     esi, 1          // next lumel
01156                 add                     edi, 4          // next texel
01157                 dec                     ecx
01158                 jnz                     myLoop
01159 
01160                 // restore
01161                 pop                     ebp
01162         }
01163 
01164 }
01165 
01166 #  pragma warning (default : 4731)                      // frame pointer register 'ebp' modified by inline assembly code
01167 
01168 
01169 #else // NL_OS_WINDOWS
01170 
01171 // Dummy for non-windows platforms
01172 inline  void    NL3D_asmEndMMX() {}
01173 inline  void    NL3D_asmExpandLineColor565(const uint16 *src, CRGBA *dst, uint du, uint len) {}
01174 inline  void    NL3D_asmExpandLineColor8888(const CRGBA *src, CRGBA *dst, uint du, uint len) {}
01175 inline  void    NL3D_asmBlendLines(CRGBA *dst, const CRGBA *src0, const CRGBA *src1, uint index, uint len) {}
01176 static void             NL3D_asmAssembleShading1x1(const uint8 *lumels, const CRGBA *colorMap, 
01177         const CRGBA *srcTLIs, const CRGBA *srcUSCs, CRGBA *dst, uint lineWidth, uint nbTexel)
01178 {
01179 }
01180 static void             NL3D_asmAssembleShading2x2(const uint8 *lumels, const CRGBA *colorMap, 
01181         const CRGBA *srcTLIs, const CRGBA *srcUSCs, CRGBA *dst, uint lineWidth, uint nbTexel)
01182 {
01183 }
01184 static void             NL3D_asmAssembleShading4x4(const uint8 *lumels, const CRGBA *colorMap, 
01185         const CRGBA *srcTLIs, const CRGBA *srcUSCs, CRGBA *dst, uint nbTexel)
01186 {
01187 }
01188 
01189 #endif // NL_OS_WINDOWS
01190 
01191 
01192 // ***************************************************************************
01193 extern "C" void NL3D_expandLightmap (const NL3D_CExpandLightmap* pLightmap)
01194 {
01195         bool    asmMMX= false;
01196 #ifdef  NL_OS_WINDOWS
01197         asmMMX= CSystemInfo::hasMMX();
01198         // A CTileColor must be a 565 only.
01199         nlassert(sizeof(CTileColor)==2);
01200 #endif
01201 
01202         // Expanded width
01203         uint dstWidth=(pLightmap->Width-1)*pLightmap->MulFactor;
01204         uint dstHeight=(pLightmap->Height-1)*pLightmap->MulFactor;
01205 
01206         // *** First expand user color and TLI colors
01207         // First pass, expand on U
01208         static CRGBA expandedUserColorLine[ (NL_MAX_TILES_BY_PATCH_EDGE+1)*
01209                 (NL_MAX_TILES_BY_PATCH_EDGE+1)*NL_LUMEL_BY_TILE ];
01210         static CRGBA expandedTLIColorLine[ (NL_MAX_TILES_BY_PATCH_EDGE+1)*
01211                 (NL_MAX_TILES_BY_PATCH_EDGE+1)*NL_LUMEL_BY_TILE ];
01212         // Second pass, expand on V.
01213         static CRGBA expandedUserColor[ (NL_MAX_TILES_BY_PATCH_EDGE+1)*NL_LUMEL_BY_TILE * 
01214                 (NL_MAX_TILES_BY_PATCH_EDGE+1)*NL_LUMEL_BY_TILE ];
01215         static CRGBA expandedTLIColor[ (NL_MAX_TILES_BY_PATCH_EDGE+1)*NL_LUMEL_BY_TILE * 
01216                 (NL_MAX_TILES_BY_PATCH_EDGE+1)*NL_LUMEL_BY_TILE ];
01217 
01218 
01219         // ** Expand on U
01220         //=========
01221         uint u, v;
01222 
01223         // Expansion factor
01224         uint expandFactor=((pLightmap->Width-1)<<8)/(dstWidth-1);
01225 
01226         // Destination  pointer
01227         CRGBA *expandedUserColorLinePtr= expandedUserColorLine;
01228         CRGBA *expandedTLIColorLinePtr= expandedTLIColorLine;
01229 
01230         // Source pointer
01231         const NL3D::CTileColor  *colorTilePtr=pLightmap->ColorTile;
01232         const NLMISC::CRGBA             *colorTLIPtr= pLightmap->TLIColor;
01233 
01234         // Go for U
01235         for (v=0; v<pLightmap->Height; v++)
01236         {
01237                 // First pixel
01238                 expandedUserColorLinePtr[0].set565 (colorTilePtr[0].Color565);
01239                 expandedTLIColorLinePtr[0]= colorTLIPtr[0];
01240 
01241                 // MMX implementation.
01242                 //-------------
01243                 if(asmMMX)
01244                 {
01245                         NL3D_asmExpandLineColor565(&colorTilePtr->Color565, expandedUserColorLinePtr, expandFactor, dstWidth-2);
01246                         NL3D_asmExpandLineColor8888(colorTLIPtr, expandedTLIColorLinePtr, expandFactor, dstWidth-2);
01247                 }
01248                 // C implementation
01249                 //-------------
01250                 else
01251                 {
01252                         // Index next pixel
01253                         uint srcIndexPixel=expandFactor;
01254 
01255                         for (u=1; u<dstWidth-1; u++)
01256                         {
01257                                 // Check
01258                                 nlassert ( (u+v*dstWidth) < (sizeof(expandedUserColorLine)/sizeof(CRGBA)) );
01259 
01260                                 // Color index
01261                                 uint srcIndex=srcIndexPixel>>8;
01262                                 nlassert (srcIndex>=0);
01263                                 nlassert (srcIndex<pLightmap->Width-1);
01264 
01265                                 // Compute current color
01266                                 CRGBA color0;
01267                                 CRGBA color1;
01268                                 color0.set565 (colorTilePtr[srcIndex].Color565);
01269                                 color1.set565 (colorTilePtr[srcIndex+1].Color565);
01270                                 expandedUserColorLinePtr[u].blendFromui (color0, color1, srcIndexPixel&0xff);
01271                                 // Compute current TLI color
01272                                 color0= colorTLIPtr[srcIndex];
01273                                 color1= colorTLIPtr[srcIndex+1];
01274                                 expandedTLIColorLinePtr[u].blendFromui (color0, color1, srcIndexPixel&0xff);
01275 
01276                                 // Next index
01277                                 srcIndexPixel+=expandFactor;
01278                         }
01279                 }
01280 
01281                 // Last pixel
01282                 expandedUserColorLinePtr[dstWidth-1].set565 (colorTilePtr[pLightmap->Width-1].Color565);
01283                 expandedTLIColorLinePtr[dstWidth-1]= colorTLIPtr[pLightmap->Width-1];
01284 
01285                 // Next line
01286                 expandedUserColorLinePtr+= dstWidth;
01287                 expandedTLIColorLinePtr+= dstWidth;
01288                 colorTilePtr+=pLightmap->Width;
01289                 colorTLIPtr+=pLightmap->Width;
01290         }
01291 
01292         // stop MMX if used
01293         if(asmMMX)
01294                 NL3D_asmEndMMX();
01295 
01296         // ** Expand on V
01297         //=========
01298 
01299         // Expansion factor
01300         expandFactor=((pLightmap->Height-1)<<8)/(dstHeight-1);
01301 
01302         // Destination  pointer
01303         CRGBA *expandedUserColorPtr= expandedUserColor;
01304         CRGBA *expandedTLIColorPtr= expandedTLIColor;
01305 
01306         // Src pointer
01307         expandedUserColorLinePtr= expandedUserColorLine;
01308         expandedTLIColorLinePtr= expandedTLIColorLine;
01309 
01310         // Copy first row
01311         memcpy(expandedUserColorPtr, expandedUserColorLinePtr, dstWidth*sizeof(CRGBA));
01312         memcpy(expandedTLIColorPtr, expandedTLIColorLinePtr, dstWidth*sizeof(CRGBA));
01313 
01314         // Next line
01315         expandedUserColorPtr+=dstWidth;
01316         expandedTLIColorPtr+=dstWidth;
01317 
01318         // Index next pixel
01319         uint indexPixel=expandFactor;
01320 
01321         // Go for V
01322         for (v=1; v<dstHeight-1; v++)
01323         {
01324                 // Color index
01325                 uint index=indexPixel>>8;
01326 
01327                 // Source pointer
01328                 CRGBA *colorTilePtr0= expandedUserColorLine + index*dstWidth;
01329                 CRGBA *colorTilePtr1= expandedUserColorLine + (index+1)*dstWidth;
01330                 CRGBA *colorTLIPtr0= expandedTLIColorLine + index*dstWidth;
01331                 CRGBA *colorTLIPtr1= expandedTLIColorLine + (index+1)*dstWidth;
01332 
01333                 // MMX implementation.
01334                 //-------------
01335                 if(asmMMX)
01336                 {
01337                         NL3D_asmBlendLines(expandedUserColorPtr, colorTilePtr0, colorTilePtr1, indexPixel, dstWidth);
01338                         NL3D_asmBlendLines(expandedTLIColorPtr, colorTLIPtr0, colorTLIPtr1, indexPixel, dstWidth);
01339                 }
01340                 // C implementation
01341                 //-------------
01342                 else
01343                 {
01344                         // Copy the row
01345                         for (u=0; u<dstWidth; u++)
01346                         {
01347                                 expandedUserColorPtr[u].blendFromui (colorTilePtr0[u], colorTilePtr1[u], indexPixel&0xff);
01348                                 expandedTLIColorPtr[u].blendFromui (colorTLIPtr0[u], colorTLIPtr1[u],  indexPixel&0xff);
01349                         }
01350                 }
01351 
01352                 // Next index
01353                 indexPixel+=expandFactor;
01354 
01355                 // Next line
01356                 expandedUserColorPtr+=dstWidth;
01357                 expandedTLIColorPtr+=dstWidth;
01358         }
01359 
01360         // stop MMX if used
01361         if(asmMMX)
01362                 NL3D_asmEndMMX();
01363 
01364         // Last row
01365         // Destination  pointer
01366         expandedUserColorPtr= expandedUserColor + dstWidth*(dstHeight-1);
01367         expandedTLIColorPtr= expandedTLIColor + dstWidth*(dstHeight-1);
01368         // Src pointer
01369         expandedUserColorLinePtr= expandedUserColorLine + dstWidth*(pLightmap->Height-1);
01370         expandedTLIColorLinePtr= expandedTLIColorLine + dstWidth*(pLightmap->Height-1);
01371 
01372         // Copy last row
01373         memcpy(expandedUserColorPtr, expandedUserColorLinePtr, dstWidth*sizeof(CRGBA));
01374         memcpy(expandedTLIColorPtr, expandedTLIColorLinePtr, dstWidth*sizeof(CRGBA));
01375 
01376         // *** Now combine with shading
01377         //=========
01378 
01379         // Switch to the optimal method for each expansion value
01380         switch (pLightmap->MulFactor)
01381         {
01382         case 1:
01383                 {
01384                         // Make 4x4 -> 1x1 blend
01385                         CRGBA *lineUSCPtr= expandedUserColor;
01386                         CRGBA *lineTLIPtr= expandedTLIColor;
01387                         CRGBA *lineDestPtr=pLightmap->DstPixels;
01388                         const uint8 *lineLumelPtr=pLightmap->LumelTile;
01389                         uint lineWidth=dstWidth<<2;
01390                         uint lineWidthx2=lineWidth<<1;
01391                         uint lineWidthx3=lineWidthx2+lineWidth;
01392                         uint lineWidthx4=lineWidth<<2;
01393 
01394                         // For each line
01395                         for (v=0; v<dstHeight; v++)
01396                         {
01397                                 // MMX implementation.
01398                                 //-------------
01399                                 if(asmMMX)
01400                                 {
01401                                         NL3D_asmAssembleShading1x1(lineLumelPtr, pLightmap->StaticLightColor, lineTLIPtr, lineUSCPtr, lineDestPtr,
01402                                                 lineWidth, dstWidth);
01403                                 }
01404                                 // C implementation
01405                                 //-------------
01406                                 else
01407                                 {
01408                                         // For each lumel block
01409                                         for (u=0; u<dstWidth; u++)
01410                                         {
01411                                                 // index
01412                                                 uint lumelIndex=u<<2;
01413 
01414                                                 // Shading is filtred
01415                                                 uint shading=
01416                                                          ((uint)lineLumelPtr[lumelIndex]+(uint)lineLumelPtr[lumelIndex+1]+(uint)lineLumelPtr[lumelIndex+2]+(uint)lineLumelPtr[lumelIndex+3]
01417                                                         +(uint)lineLumelPtr[lumelIndex+lineWidth]+(uint)lineLumelPtr[lumelIndex+1+lineWidth]+(uint)lineLumelPtr[lumelIndex+2+lineWidth]+(uint)lineLumelPtr[lumelIndex+3+lineWidth]
01418                                                         +(uint)lineLumelPtr[lumelIndex+lineWidthx2]+(uint)lineLumelPtr[lumelIndex+1+lineWidthx2]+(uint)lineLumelPtr[lumelIndex+2+lineWidthx2]+(uint)lineLumelPtr[lumelIndex+3+lineWidthx2]
01419                                                         +(uint)lineLumelPtr[lumelIndex+lineWidthx3]+(uint)lineLumelPtr[lumelIndex+1+lineWidthx3]+(uint)lineLumelPtr[lumelIndex+2+lineWidthx3]+(uint)lineLumelPtr[lumelIndex+3+lineWidthx3]
01420                                                         )>>4;
01421 
01422                                                 // Add shading with TLI color.
01423                                                 CRGBA   col;
01424                                                 col.addRGBOnly(pLightmap->StaticLightColor[shading], lineTLIPtr[u]);
01425 
01426                                                 // Mul by the userColor
01427                                                 lineDestPtr[u].modulateFromColorRGBOnly(col, lineUSCPtr[u]);
01428                                         }
01429                                 }
01430 
01431                                 // Next line
01432                                 lineUSCPtr+=dstWidth;
01433                                 lineTLIPtr+=dstWidth;
01434                                 lineDestPtr+=dstWidth;
01435                                 lineLumelPtr+=lineWidthx4;
01436                         }
01437                         break;
01438                 }
01439         case 2:
01440                 {
01441                         // Make 2x2 -> 1x1 blend
01442                         CRGBA *lineUSCPtr= expandedUserColor;
01443                         CRGBA *lineTLIPtr= expandedTLIColor;
01444                         CRGBA *lineDestPtr=pLightmap->DstPixels;
01445                         const uint8 *lineLumelPtr=pLightmap->LumelTile;
01446                         uint lineWidth=dstWidth*2;
01447                         uint lineWidthx2=lineWidth<<1;
01448 
01449                         // For each line
01450                         for (v=0; v<dstHeight; v++)
01451                         {
01452                                 // MMX implementation.
01453                                 //-------------
01454                                 if(asmMMX)
01455                                 {
01456                                         NL3D_asmAssembleShading2x2(lineLumelPtr, pLightmap->StaticLightColor, lineTLIPtr, lineUSCPtr, lineDestPtr,
01457                                                 lineWidth, dstWidth);
01458                                 }
01459                                 // C implementation
01460                                 //-------------
01461                                 else
01462                                 {
01463                                         // For each lumel block
01464                                         for (u=0; u<dstWidth; u++)
01465                                         {
01466                                                 // index
01467                                                 uint lumelIndex=u<<1;
01468 
01469                                                 // Shading is filtred
01470                                                 uint shading=
01471                                                         ((uint)lineLumelPtr[lumelIndex]+(uint)lineLumelPtr[lumelIndex+1]+(uint)lineLumelPtr[lumelIndex+lineWidth]+(uint)lineLumelPtr[lumelIndex+1+lineWidth])>>2;
01472 
01473                                                 // Add shading with TLI color.
01474                                                 CRGBA   col;
01475                                                 col.addRGBOnly(pLightmap->StaticLightColor[shading], lineTLIPtr[u]);
01476 
01477                                                 // Mul by the userColor
01478                                                 lineDestPtr[u].modulateFromColorRGBOnly(col, lineUSCPtr[u]);
01479                                         }
01480                                 }
01481 
01482                                 // Next line
01483                                 lineUSCPtr+=dstWidth;
01484                                 lineTLIPtr+=dstWidth;
01485                                 lineDestPtr+=dstWidth;
01486                                 lineLumelPtr+=lineWidthx2;
01487                         }
01488                         break;
01489                 }
01490 
01491         case 4:
01492                         // Make copy
01493                         CRGBA *lineUSCPtr= expandedUserColor;
01494                         CRGBA *lineTLIPtr= expandedTLIColor;
01495                         CRGBA *lineDestPtr=pLightmap->DstPixels;
01496                         const uint8 *lineLumelPtr=pLightmap->LumelTile;
01497                         uint nbTexel=dstWidth*dstHeight;
01498 
01499                         // MMX implementation.
01500                         //-------------
01501                         if(asmMMX)
01502                         {
01503                                 NL3D_asmAssembleShading4x4(lineLumelPtr, pLightmap->StaticLightColor, lineTLIPtr, lineUSCPtr, lineDestPtr,
01504                                         nbTexel);
01505                         }
01506                         // C implementation
01507                         //-------------
01508                         else
01509                         {
01510                                 // For each pixel
01511                                 for (u=0; u<nbTexel; u++)
01512                                 {
01513                                         // Shading is filtred
01514                                         uint shading=lineLumelPtr[u];
01515 
01516                                         // Add shading with TLI color.
01517                                         CRGBA   col;
01518                                         col.addRGBOnly(pLightmap->StaticLightColor[shading], lineTLIPtr[u]);
01519 
01520                                         // Mul by the userColor
01521                                         lineDestPtr[u].modulateFromColorRGBOnly(col, lineUSCPtr[u]);
01522                                 }
01523                         }
01524                         break;
01525         }
01526 
01527         // stop MMX if used
01528         if(asmMMX)
01529                 NL3D_asmEndMMX();
01530 
01531 }
01532 
01533 
01534 // ***************************************************************************
01535 // ***************************************************************************
01536 // NL3D_drawFarTileInFar*. C and Asm Part
01537 // ***************************************************************************
01538 // ***************************************************************************
01539 
01540 
01541 #ifdef NL_OS_WINDOWS
01542 
01543 
01544 // ***************************************************************************
01545 inline  void    NL3D_asmModulateLineColors(CRGBA *dst, const CRGBA *src0, const CRGBA *src1, 
01546         uint len, uint  src0DeltaX, uint dstDeltaX)
01547 {
01548         static  uint64  blank= 0;
01549         if(len==0)
01550                 return;
01551 
01552         __asm
01553         {
01554                 movq            mm7, blank
01555 
01556                 mov                     esi, src0       // esi point to src Pixels
01557                 mov                     edx, src1       // edx point to src lighting pixels
01558                 mov                     edi, dst
01559                 mov                     ecx, len
01560                 // compute increments for esi and edi
01561                 mov                     eax, src0DeltaX
01562                 mov                     ebx, dstDeltaX
01563                 sal                     eax, 2
01564                 sal                     ebx, 2
01565 
01566         myLoop:
01567                 // read colors
01568                 movd            mm0, [esi]
01569                 movd            mm1, [edx]
01570 
01571                 // mul mm0 and mm1
01572                 punpcklbw       mm0, mm7
01573                 punpcklbw       mm1, mm7
01574                 pmullw          mm0, mm1
01575                 psrlw       mm0, 8
01576                 // pack
01577                 packuswb    mm0, mm0
01578 
01579                 // out
01580                 movd            [edi], mm0
01581 
01582                 // increment
01583                 add                     esi, eax
01584                 add                     edi, ebx
01585                 add                     edx, 4
01586                 dec                     ecx
01587                 jnz                     myLoop
01588         }
01589 }
01590 
01591 
01592 // ***************************************************************************
01593 inline  void    NL3D_asmModulateAndBlendLineColors(CRGBA *dst, const CRGBA *src0, const CRGBA *src1, 
01594         uint len, uint  src0DeltaX, uint dstDeltaX)
01595 {
01596         static  uint64  blank= 0;
01597         static  uint64  one= 0x0100010001000100;
01598         if(len==0)
01599                 return;
01600 
01601         __asm
01602         {
01603                 movq            mm7, blank
01604                 movq            mm6, one
01605 
01606                 mov                     esi, src0       // esi point to src Pixels
01607                 mov                     edx, src1       // edx point to src lighting pixels
01608                 mov                     edi, dst
01609                 mov                     ecx, len
01610                 // compute increments for esi and edi
01611                 mov                     eax, src0DeltaX
01612                 mov                     ebx, dstDeltaX
01613                 sal                     eax, 2
01614                 sal                     ebx, 2
01615 
01616         myLoop:
01617                 // read colors
01618                 movd            mm0, [esi]
01619                 movd            mm1, [edx]
01620 
01621                 // save and unpack Alpha. NB: ABGR
01622                 movq            mm2, mm0
01623                 psrld           mm2, 24         // mm2= 0000 0000 0000 00AA
01624                 punpckldq       mm2, mm2        // mm2= 0000 00AA 0000 00AA
01625                 packssdw        mm2, mm2        // mm2= 00AA 00AA 00AA 00AA
01626                 // negate with 256.
01627                 movq            mm3, mm6
01628                 psubusw         mm3, mm2
01629 
01630                 // mul mm0 and mm1
01631                 punpcklbw       mm0, mm7
01632                 punpcklbw       mm1, mm7
01633                 pmullw          mm0, mm1
01634                 psrlw       mm0, 8
01635 
01636                 // Alpha Blend with mm3 and mm2
01637                 movd            mm1, [edi]      // read dest
01638                 punpcklbw       mm1, mm7
01639                 pmullw          mm0, mm2        // mm0= srcColor*A
01640                 pmullw          mm1, mm3        // mm1= dstColor*(1-A)
01641 
01642                 // add and pack
01643                 paddusw         mm0, mm1
01644                 psrlw       mm0, 8
01645                 packuswb    mm0, mm0
01646 
01647                 // out
01648                 movd            [edi], mm0
01649 
01650                 // increment
01651                 add                     esi, eax
01652                 add                     edi, ebx
01653                 add                     edx, 4
01654                 dec                     ecx
01655                 jnz                     myLoop
01656         }
01657 }
01658 
01659 
01660 #else // NL_OS_WINDOWS
01661 
01662 // Dummy for non-windows platforms
01663 inline  void    NL3D_asmModulateLineColors(CRGBA *dst, const CRGBA *src0, const CRGBA *src1, 
01664         uint len, uint  src0DeltaX, uint dstDeltaX)
01665 {
01666 }
01667 inline  void    NL3D_asmModulateAndBlendLineColors(CRGBA *dst, const CRGBA *src0, const CRGBA *src1, 
01668         uint len, uint  src0DeltaX, uint dstDeltaX)
01669 {
01670 }
01671 
01672 #endif
01673 
01674 // ***************************************************************************
01675 void NL3D_drawFarTileInFarTexture (const NL3D_CComputeTileFar* pTileFar)
01676 {
01677         // Pointer of the Src diffuse pixels
01678         const CRGBA* pSrcPixels=pTileFar->SrcDiffusePixels;
01679 
01680         // Pointer of the Dst pixels
01681         const CRGBA* pSrcLightPixels=pTileFar->SrcLightingPixels;
01682 
01683         // Pointer of the Dst pixels
01684         CRGBA* pDstPixels=pTileFar->DstPixels;
01685 
01686         // For each pixels
01687         int x, y;
01688         for (y=0; y<pTileFar->Size; y++)
01689         {
01690                 // MMX implementation
01691                 //---------
01692                 if(pTileFar->AsmMMX)
01693                 {
01694                         NL3D_asmModulateLineColors(pDstPixels, pSrcPixels, pSrcLightPixels, 
01695                                 pTileFar->Size, pTileFar->SrcDeltaX, pTileFar->DstDeltaX);
01696                 }
01697                 // C Implementation.
01698                 //---------
01699                 else
01700                 {
01701                         // Pointer of the source line
01702                         const CRGBA* pSrcLine=pSrcPixels;
01703 
01704                         // Pointer of the source lighting line
01705                         const CRGBA* pSrcLightingLine=pSrcLightPixels;
01706                         
01707                         // Pointer of the destination line
01708                         CRGBA* pDstLine=pDstPixels;
01709 
01710                         // For each pixels on the line
01711                         for (x=0; x<pTileFar->Size; x++)
01712                         {
01713                                 // Read and write a pixel
01714                                 pDstLine->R=(uint8)(((uint)pSrcLine->R*(uint)pSrcLightingLine->R)>>8);
01715                                 pDstLine->G=(uint8)(((uint)pSrcLine->G*(uint)pSrcLightingLine->G)>>8);
01716                                 pDstLine->B=(uint8)(((uint)pSrcLine->B*(uint)pSrcLightingLine->B)>>8);
01717 
01718                                 // Next pixel
01719                                 pSrcLine+=pTileFar->SrcDeltaX;
01720                                 pSrcLightingLine++;
01721                                 pDstLine+=pTileFar->DstDeltaX;
01722                         }
01723                 }
01724 
01725                 // Next line
01726                 pSrcPixels+=pTileFar->SrcDeltaY;
01727                 pSrcLightPixels+=pTileFar->SrcLightingDeltaY;
01728                 pDstPixels+=pTileFar->DstDeltaY;
01729         }
01730 
01731         // stop MMX if used
01732         if(pTileFar->AsmMMX)
01733                 NL3D_asmEndMMX();
01734 }
01735 
01736 
01737 // ***************************************************************************
01738 void NL3D_drawFarTileInFarTextureAlpha (const NL3D_CComputeTileFar* pTileFar)
01739 {
01740         // Pointer of the Src pixels
01741         const CRGBA* pSrcPixels=pTileFar->SrcDiffusePixels;
01742 
01743         // Pointer of the Dst pixels
01744         const CRGBA* pSrcLightPixels=pTileFar->SrcLightingPixels;
01745 
01746         // Pointer of the Dst pixels
01747         CRGBA* pDstPixels=pTileFar->DstPixels;
01748 
01749         // Fill the buffer with layer 0
01750         int x, y;
01751         for (y=0; y<pTileFar->Size; y++)
01752         {
01753                 // MMX implementation
01754                 //---------
01755                 if(pTileFar->AsmMMX)
01756                 {
01757                         NL3D_asmModulateAndBlendLineColors(pDstPixels, pSrcPixels, pSrcLightPixels, 
01758                                 pTileFar->Size, pTileFar->SrcDeltaX, pTileFar->DstDeltaX);
01759                 }
01760                 // C Implementation.
01761                 //---------
01762                 else
01763                 {
01764                         // Pointer of the source line
01765                         const CRGBA* pSrcLine=pSrcPixels;
01766 
01767                         // Pointer of the source lighting line
01768                         const CRGBA* pSrcLightingLine=pSrcLightPixels;
01769 
01770                         // Pointer of the Dst pixels
01771                         CRGBA* pDstLine=pDstPixels;
01772 
01773                         // For each pixels on the line
01774                         for (x=0; x<pTileFar->Size; x++)
01775                         {
01776                                 // Read and write a pixel
01777                                 register uint alpha=pSrcLine->A;
01778                                 register uint oneLessAlpha=255-pSrcLine->A;
01779                                 pDstLine->R=(uint8)(((((uint)pSrcLine->R*(uint)pSrcLightingLine->R)>>8)*alpha+(uint)pDstLine->R*oneLessAlpha)>>8);
01780                                 pDstLine->G=(uint8)(((((uint)pSrcLine->G*(uint)pSrcLightingLine->G)>>8)*alpha+(uint)pDstLine->G*oneLessAlpha)>>8);
01781                                 pDstLine->B=(uint8)(((((uint)pSrcLine->B*(uint)pSrcLightingLine->B)>>8)*alpha+(uint)pDstLine->B*oneLessAlpha)>>8);
01782 
01783                                 // Next pixel
01784                                 pSrcLine+=pTileFar->SrcDeltaX;
01785                                 pSrcLightingLine++;
01786                                 pDstLine+=pTileFar->DstDeltaX;
01787                         }
01788                 }
01789 
01790                 // Next line
01791                 pSrcPixels+=pTileFar->SrcDeltaY;
01792                 pSrcLightPixels+=pTileFar->SrcLightingDeltaY;
01793                 pDstPixels+=pTileFar->DstDeltaY;
01794         }
01795 
01796         // stop MMX if used
01797         if(pTileFar->AsmMMX)
01798                 NL3D_asmEndMMX();
01799 }
01800 
01801 
01802 // ***************************************************************************
01803 // TODO: asm implementation of this function \\//
01804 //#ifdef NL_NO_ASM
01805 void NL3D_drawFarTileInFarTextureAdditive (const NL3D_CComputeTileFar* pTileFar)
01806 {
01807         // Pointer of the Src diffuse pixels
01808         const CRGBA* pSrcPixels=pTileFar->SrcDiffusePixels;
01809 
01810         // Pointer of the Src additive pixels
01811         const CRGBA* pSrcAddPixels=pTileFar->SrcAdditivePixels;
01812 
01813         // Pointer of the Dst pixels
01814         const CRGBA* pSrcLightPixels=pTileFar->SrcLightingPixels;
01815 
01816         // Pointer of the Dst pixels
01817         CRGBA* pDstPixels=pTileFar->DstPixels;
01818 
01819         // For each pixels
01820         int x, y;
01821         for (y=0; y<pTileFar->Size; y++)
01822         {
01823                 // Pointer of the source line
01824                 const CRGBA* pSrcLine=pSrcPixels;
01825 
01826                 // Pointer of the source line
01827                 const CRGBA* pSrcAddLine=pSrcAddPixels;
01828 
01829                 // Pointer of the source lighting line
01830                 const CRGBA* pSrcLightingLine=pSrcLightPixels;
01831 
01832                 // Pointer of the destination line
01833                 CRGBA* pDstLine=pDstPixels;
01834 
01835                 // For each pixels on the line
01836                 for (x=0; x<pTileFar->Size; x++)
01837                 {
01838                         // Read and write a pixel
01839                         uint nTmp=(((uint)pSrcLine->R*(uint)pSrcLightingLine->R)>>8)+(uint)pSrcAddLine->R;
01840                         if (nTmp>255)
01841                                 nTmp=255;
01842                         pDstLine->R=(uint8)nTmp;
01843                         nTmp=(((uint)pSrcLine->G*(uint)pSrcLightingLine->G)>>8)+(uint)pSrcAddLine->G;
01844                         if (nTmp>255)
01845                                 nTmp=255;
01846                         pDstLine->G=(uint8)nTmp;
01847                         nTmp=(((uint)pSrcLine->B*(uint)pSrcLightingLine->B)>>8)+(uint)pSrcAddLine->B;
01848                         if (nTmp>255)
01849                                 nTmp=255;
01850                         pDstLine->B=(uint8)nTmp;
01851 
01852                         // Next pixel
01853                         pSrcLine+=pTileFar->SrcDeltaX;
01854                         pSrcAddLine+=pTileFar->SrcDeltaX;
01855                         pSrcLightingLine++;
01856                         pDstLine+=pTileFar->DstDeltaX;
01857                 }
01858 
01859                 // Next line
01860                 pSrcPixels+=pTileFar->SrcDeltaY;
01861                 pSrcAddPixels+=pTileFar->SrcDeltaY;
01862                 pSrcLightPixels+=pTileFar->SrcLightingDeltaY;
01863                 pDstPixels+=pTileFar->DstDeltaY;
01864         }
01865 }
01866 //#endif // NL_NO_ASM
01867 
01868 
01869 // ***************************************************************************
01870 // TODO: asm implementation of this function \\//
01871 //#ifdef NL_NO_ASM
01872 void NL3D_drawFarTileInFarTextureAdditiveAlpha (const NL3D_CComputeTileFar* pTileFar)
01873 {
01874         // Pointer of the Src pixels
01875         const CRGBA* pSrcPixels=pTileFar->SrcDiffusePixels;
01876 
01877         // Pointer of the Src pixels
01878         const CRGBA* pSrcAddPixels=pTileFar->SrcAdditivePixels;
01879 
01880         // Pointer of the Dst pixels
01881         const CRGBA* pSrcLightPixels=pTileFar->SrcLightingPixels;
01882 
01883         // Pointer of the Dst pixels
01884         CRGBA* pDstPixels=pTileFar->DstPixels;
01885 
01886         // Fill the buffer with layer 0
01887         int x, y;
01888         for (y=0; y<pTileFar->Size; y++)
01889         {
01890                 // Pointer of the source line
01891                 const CRGBA* pSrcLine=pSrcPixels;
01892 
01893                 // Pointer of the source line
01894                 const CRGBA* pSrcAddLine=pSrcAddPixels;
01895 
01896                 // Pointer of the source lighting line
01897                 const CRGBA* pSrcLightingLine=pSrcLightPixels;
01898 
01899                 // Pointer of the Dst pixels
01900                 CRGBA* pDstLine=pDstPixels;
01901 
01902                 // For each pixels on the line
01903                 for (x=0; x<pTileFar->Size; x++)
01904                 {
01905                         // Read and write a pixel
01906                         register uint alpha=pSrcLine->A;
01907                         register uint oneLessAlpha=255-pSrcLine->A;
01908                         
01909                         // Read and write a pixel
01910                         uint nTmp=(((uint)pSrcLine->R*(uint)pSrcLightingLine->R)>>8)+(uint)pSrcAddLine->R;
01911                         if (nTmp>255)
01912                                 nTmp=255;
01913                         pDstLine->R=(uint8)((nTmp*alpha+pDstLine->R*oneLessAlpha)>>8);
01914                         nTmp=(((uint)pSrcLine->G*(uint)pSrcLightingLine->G)>>8)+(uint)pSrcAddLine->G;
01915                         if (nTmp>255)
01916                                 nTmp=255;
01917                         pDstLine->G=(uint8)((nTmp*alpha+pDstLine->G*oneLessAlpha)>>8);
01918                         nTmp=(((uint)pSrcLine->B*(uint)pSrcLightingLine->B)>>8)+(uint)pSrcAddLine->B;
01919                         if (nTmp>255)
01920                                 nTmp=255;
01921                         pDstLine->B=(uint8)((nTmp*alpha+pDstLine->B*oneLessAlpha)>>8);
01922 
01923                         // Next pixel
01924                         pSrcLine+=pTileFar->SrcDeltaX;
01925                         pSrcAddLine+=pTileFar->SrcDeltaX;
01926                         pSrcLightingLine++;
01927                         pDstLine+=pTileFar->DstDeltaX;
01928                 }
01929 
01930                 // Next line
01931                 pSrcPixels+=pTileFar->SrcDeltaY;
01932                 pSrcAddPixels+=pTileFar->SrcDeltaY;
01933                 pSrcLightPixels+=pTileFar->SrcLightingDeltaY;
01934                 pDstPixels+=pTileFar->DstDeltaY;
01935         }
01936 }
01937 //#endif // NL_NO_ASM