changeset 1338:9749edd941c6

shading terrain
author Ritor1
date Fri, 05 Jul 2013 17:37:12 +0600
parents c6695ebd8fe6
children 8bfdc44cebfd
files Outdoor.cpp Outdoor_stuff.h Render.cpp mm7_3.cpp
diffstat 4 files changed, 148 insertions(+), 184 deletions(-) [+]
line wrap: on
line diff
--- a/Outdoor.cpp	Thu Jul 04 09:21:57 2013 +0600
+++ b/Outdoor.cpp	Fri Jul 05 17:37:12 2013 +0600
@@ -1147,7 +1147,7 @@
   pTilemap = (unsigned __int8 *)pAllocator->AllocNamedChunk(pTilemap, 0x4000u, "TMAP");//tile map
   pAttributemap = (unsigned __int8 *)pAllocator->AllocNamedChunk(pAttributemap, 0x4000u, "AMAP");//карта атрибутов
   pDmap=(struct DMap *)pAllocator->AllocNamedChunk(pDmap, 0x8000u, "DMAP");
-  if (pHeightmap&&pTilemap&&pAttributemap&&pDmap)
+  if ( pHeightmap && pTilemap && pAttributemap && pDmap )
     return true;
   else
     return false;
--- a/Outdoor_stuff.h	Thu Jul 04 09:21:57 2013 +0600
+++ b/Outdoor_stuff.h	Fri Jul 05 17:37:12 2013 +0600
@@ -15,7 +15,7 @@
   }
 
   int _479295();
-  void _4811A3();
+  void DrawBorderTiles();
   void _48276F_sr();
   void _486089_normalize_v_18();
   void _48607B(struct stru149 *a2);
--- a/Render.cpp	Thu Jul 04 09:21:57 2013 +0600
+++ b/Render.cpp	Fri Jul 05 17:37:12 2013 +0600
@@ -1670,24 +1670,13 @@
 // 4D864C: using guessed type char byte_4D864C;
 
 
-void Render::RenderTerrainD3D() // New function. It's temporary
+void Render::RenderTerrainD3D() // New function
 {
   char result; // al@3
-  //int v1; // eax@3
-  //int v2; // ebx@4
-  //struct ODMFace *v4; // esi@6
   int v6; // ecx@8
-  //int v7; // ecx@8
- struct stru148 *v8; // ebx@8
-// RenderVertexSoft *v8a; // edi@3
-  //char v11; // zf@8
+ struct stru148 *pTile; // ebx@8
  struct stru148 *v16;
   unsigned int v18; // edi@22
-  //int v20; // edi@34
-  //int v28; // eax@50
-  //int v29; // ecx@55
-  //int v30; // eax@57
-  int v31; // eax@57
   int v35; // edi@63
   int v37; // eax@73
   int v39; // eax@80
@@ -1697,156 +1686,145 @@
   int v43; // [sp-Ch] [bp-64h]@2
   const char *v44; // [sp-8h] [bp-60h]@2
   int v45; // [sp-4h] [bp-5Ch]@2
-  //float v48; // [sp+14h] [bp-44h]@8
-  //void *v52; // [sp+24h] [bp-34h]@3
-  bool v54; // [sp+2Ch] [bp-2Ch]@10
-  int v55; // [sp+30h] [bp-28h]@34
   int v56;
   int v57; // [sp+38h] [bp-20h]@36
-  int v58; // [sp+3Ch] [bp-1Ch]@8
-  int v63; // [sp+50h] [bp-8h]@3
   int v64; // [sp+57h] [bp-1h]@2
   int v62;
-  //struct IndoorCameraD3D *pIndoorCameraD3D;
-  //RenderVertexSoft *pVertices; // [sp+C4h] [bp-Ch]@6
-
 
   //warning: the game uses CW culling by default, ccw is incosistent
   pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW);
 
-
-  v63 = 0;
-  // basic optimizations
-  unsigned int uStartX, uEndX, uStartZ, uEndZ;
-  if (pIndoorCamera->sRotationY >= 0 && pIndoorCamera->sRotationY <= 1024)
-  {
-    uStartX = 0, uEndX = 128;
-    uStartZ = 0, uEndZ = 64 + 16;
-  }
-  else if (pIndoorCamera->sRotationY >= 512 && pIndoorCamera->sRotationY <= 1536)
-  {
-    uStartX = 0, uEndX = 64 + 16;
-    uStartZ = 0, uEndZ = 128;
-  }
-  else if (pIndoorCamera->sRotationY >= 1536 || pIndoorCamera->sRotationY <= 512)
-  {
-    uStartX = 64 - 16, uEndX = 128;
-    uStartZ = 0, uEndZ = 128;
-  }
-  else
-  {
-    uStartX = 0, uEndX = 128;
-    uStartZ = 64 - 16, uEndZ = 128;
-  }
-  uStartX = 0, uEndX = 128;
-  uStartZ = 0, uEndZ = 128;
-  static RenderVertexSoft pTerrainVertices[128 * 128];
-  for (unsigned int z = uStartZ; z < uEndZ; ++z)
-  {
-    for (unsigned int x = uStartX; x < uEndX; ++x)
-    {
-      pTerrainVertices[z * 128 + x].vWorldPosition.x = (-64 + (signed)x) * 512;
-      pTerrainVertices[z * 128 + x].vWorldPosition.y = (64 - (signed)z) * 512;
-      pTerrainVertices[z * 128 + x].vWorldPosition.z = 32 * pOutdoor->pTerrain.pHeightmap[z * 128 + x];
-      //pIndoorCameraD3D = pGame->pIndoorCameraD3D;
+  static RenderVertexSoft pTerrainVertices[128 * 128];//vertexCountX and vertexCountZ
+
+  //Генерация местоположения вершин-------------------------------------------------------------------------
+  //решётка вершин делится на две части от -64 до 0 и от 0 до 64
+  //
+  // -64  X  0     64
+  //  --------------- 64
+  //  |      |      |
+  //  |      |      |
+  //  |      |      |
+  // 0|------+------| Z
+  //  |      |      |
+  //  |      |      |
+  //  |      |      |
+  //  ---------------
+  //                -64
+
+  int blockScale = 512;
+  int heightScale = 32;
+  for (unsigned int z = 0; z < 128; ++z)
+  {
+    for (unsigned int x = 0; x < 128; ++x)
+    {
+      pTerrainVertices[z * 128 + x].vWorldPosition.x = (-64 + (signed)x) * blockScale;
+      pTerrainVertices[z * 128 + x].vWorldPosition.y = (64 - (signed)z) * blockScale;
+      pTerrainVertices[z * 128 + x].vWorldPosition.z = heightScale * pOutdoor->pTerrain.pHeightmap[z * 128 + x];
       pGame->pIndoorCameraD3D->ViewTransform(&pTerrainVertices[z * 128 + x], 1);
       pGame->pIndoorCameraD3D->Project(&pTerrainVertices[z * 128 + x], 1, 0);
     }
   }
-
-  for (unsigned int z = uStartZ; z < uEndZ - 1; ++z)
-  {
-    for (unsigned int x = uStartX; x < uEndX - 1; ++x)
-    {
-      v8 = &array_77EC08[pOutdoorCamera->numStru148s];
-      v8->flags = 0;
-      v8->field_32 = 0;
-      //unsigned int uTileID = pOutdoor->pTerrain.pTilemap[z * 128 + x];
-      //struct TileDesc *pTile = pTileTable->GetTileById(uTileID);
-      v8->uTileBitmapID = pOutdoor->DoGetTileTexture(x, z);
-      //v6 = v8->uTileBitmapID;
-      v8->pTexture = (Texture *)&pBitmaps_LOD->pHardwareTextures[v8->uTileBitmapID];
-      if (v8->uTileBitmapID == 0xFFFF)
+//--------------------------------------------------------------------------------------------------------------------
+
+  //
+  for (unsigned int z = 0; z < 128; ++z)
+  {
+    for (unsigned int x = 0; x < 128; ++x)
+    {
+      pTile = &array_77EC08[pOutdoorCamera->numStru148s];
+      pTile->flags = 0;
+      pTile->field_32 = 0;
+      pTile->uTileBitmapID = pOutdoor->DoGetTileTexture(x, z);
+      pTile->pTexture = (Texture *)&pBitmaps_LOD->pHardwareTextures[pTile->uTileBitmapID];
+      if (pTile->uTileBitmapID == 0xFFFF)
         continue;
 
-      v8->flags = 0x8010 |pOutdoor->GetSomeOtherTileInfo(x, z);
-      v8->field_32 = 0;
-      v8->field_59 = 1;
-      //v8->field_5D = (char)WorldPosToGridCellZ(floorf((pVertices->vWorldPosition.z + v8a->vWorldPosition.z) / 2 + 0.5f));
-      //v8->field_5C = WorldPosToGridCellX(floorf((v101->vWorldPosition.x + v8->vWorldPosition.x) / 2 + 0.5f));;
-      v8->sTextureDeltaU = 0;
-      v8->sTextureDeltaV = 0;
-      memcpy(array_73D150 + 0, &pTerrainVertices[z * 128 + x], sizeof(RenderVertexSoft));
+      //pTile->flags = 0x8010 |pOutdoor->GetSomeOtherTileInfo(x, z);
+      pTile->flags = pOutdoor->GetSomeOtherTileInfo(x, z);
+      pTile->field_32 = 0;
+      pTile->field_59 = 1;
+      pTile->sTextureDeltaU = 0;
+      pTile->sTextureDeltaV = 0;
+//  x,z         x+1,z
+//  .____________.
+//  |            |
+//  |            |
+//  |            |
+//  |            |
+//  |            |
+//  .____________.
+//  x,z+1       x+1,z+1
+      memcpy(&array_73D150[0], &pTerrainVertices[z * 128 + x], sizeof(RenderVertexSoft));//x, z
       array_73D150[0].u = 0;
       array_73D150[0].v = 0;
-      memcpy(array_73D150 + 1, &pTerrainVertices[z * 128 + x + 1], sizeof(RenderVertexSoft));
+      memcpy(&array_73D150[1], &pTerrainVertices[z * 128 + x + 1], sizeof(RenderVertexSoft));//x + 1, z
       array_73D150[1].u = 1;
       array_73D150[1].v = 0;
-      memcpy(array_73D150 + 2, &pTerrainVertices[(z + 1) * 128 + x + 1], sizeof(RenderVertexSoft));
+      memcpy(&array_73D150[2], &pTerrainVertices[(z + 1) * 128 + x + 1], sizeof(RenderVertexSoft));//x + 1, z + 1
       array_73D150[2].u = 1;
       array_73D150[2].v = 1;
-      memcpy(array_73D150 + 3, &pTerrainVertices[(z + 1) * 128 + x], sizeof(RenderVertexSoft));
+      memcpy(&array_73D150[3], &pTerrainVertices[(z + 1) * 128 + x], sizeof(RenderVertexSoft));//x, z + 1
       array_73D150[3].u = 0;
       array_73D150[3].v = 1;
-      v55 = 0;
-      v54 = false;
-      v58 = 0;
-      if (v58 == 4) // if all y == first y;  primitive in xz plane 
-        v8->field_32 |= 0x0001;
-      v8->pODMFace = nullptr;
-      v8->uNumVertices = 4;
-      v8->field_59 = 5;
-
-
-      uint norm_idx = pTerrainNormalIndices[2 * (x + 128 * z) + 1];
+      //v58 = 0;
+      //if (v58 == 4) // if all y == first y;  primitive in xz plane 
+        //pTile->field_32 |= 0x0001;
+      pTile->pODMFace = nullptr;
+      pTile->uNumVertices = 4;
+      pTile->field_59 = 5;
+
+//shading (затенение)----------------------------------------------------------------------------
+      //uint norm_idx = pTerrainNormalIndices[2 * (z * 128 + x) + 1];
+      uint norm_idx = pTerrainNormalIndices[2 * (x * 128 + z) + 1];//есть несовпадение в 1 кубик, тень надо поднять на 1
       assert(norm_idx < uNumTerrainNormals);
 
       auto norm = pTerrainNormals + norm_idx;
-      float _f = (norm->x * (float)pOutdoor->vSunlight.x / 65536.0 -
-                  norm->y * (float)pOutdoor->vSunlight.y / 65536.0 -
-                  norm->z * (float)pOutdoor->vSunlight.z / 65536.0);
-      v8->dimming_level = 20.0 - floorf(20.0 * _f + 0.5f);
+      float _f = ((norm->x * (float)pOutdoor->vSunlight.x / 65536.0) -
+                  (norm->y * (float)pOutdoor->vSunlight.y / 65536.0) -
+                  (norm->z * (float)pOutdoor->vSunlight.z / 65536.0));
+      pTile->dimming_level = 20.0 - floorf(20.0 * _f + 0.5f);
+//-----------------------------------------------------------------------------------------------
 
       ++pOutdoorCamera->numStru148s;
       ++pOutdoorCamera->field_44;
       assert(pOutdoorCamera->numStru148s < 20000);
 
-      v8->uBModelID = 0;
-      v8->uBModelFaceID = 0;
-      v31 = (8 * (0 | (0 << 6)));
-      v8->field_50 = v31 | 6;
-      for (unsigned int k = 0; k < v8->uNumVertices; ++k)
+      pTile->uBModelID = 0;
+      pTile->uBModelFaceID = 0;
+      pTile->field_50 = (8 * (0 | (0 << 6))) | 6;
+      for (unsigned int k = 0; k < pTile->uNumVertices; ++k)
       {
         memcpy(&array_50AC10[k], &array_73D150[k], sizeof(struct RenderVertexSoft));
         array_50AC10[k]._rhw = 1.0 / (array_73D150[k].vWorldViewPosition.x + 0.0000001000000011686097);
       }
 
+// check the transparency and texture (tiles) mapping (проверка прозрачности и наложение текстур (тайлов))----------------------
       bool transparent = false;
-            if ( v8->flags & 2 && v8->uTileBitmapID == pRenderer->hd_water_tile_id)
-            {
-              //v80 = false;
-              v6 = pRenderer->pHDWaterBitmapIDs[pRenderer->hd_water_current_frame];
-            }
-            else
-            {
-              v6 = v8->uTileBitmapID;
-              if ( !_strnicmp(pBitmaps_LOD->pTextures[v8->uTileBitmapID].pName, "wtrdr", 5) )
-                transparent = true;
-            }
+      if ( !( pTile->flags & 1 ) ) // не поддерживается TextureFrameTable
+      {
+        if ( pTile->flags & 2 && pTile->uTileBitmapID == pRenderer->hd_water_tile_id)
+        {
+          //transparent = false;
+          v6 = pRenderer->pHDWaterBitmapIDs[pRenderer->hd_water_current_frame];
+        }
+        else
+        {
+          v6 = pTile->uTileBitmapID;
+          if ( !_strnicmp(pBitmaps_LOD->pTextures[pTile->uTileBitmapID].pName, "wtrdr", 5) )
+            transparent = true;
+        }
 
       assert(v6 < 1000); // many random crashes here
 
       // for all shore tiles - draw a tile water under them since they're half-empty
-      if (!_strnicmp(pBitmaps_LOD->pTextures[v8->uTileBitmapID].pName, "wtrdr", 5))  // all shore tile filenames are wtrdrXXX
-      {
-        pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE);  // no Z writing: the shore tile will be draw in the same place, so taking care about z-fighting
-        pRenderer->DrawTerrainPolygon(v8->uNumVertices, v8, pBitmaps_LOD->pHardwareTextures[pRenderer->pHDWaterBitmapIDs[pRenderer->hd_water_current_frame]], false, true);
-        pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE);
-        
-      }
-
-      pRenderer->DrawTerrainPolygon(v8->uNumVertices, v8, pBitmaps_LOD->pHardwareTextures[v6], transparent, true);
-
+      if (!_strnicmp(pBitmaps_LOD->pTextures[pTile->uTileBitmapID].pName, "wtrdr", 5))  // all shore tile filenames are wtrdrXXX
+        pTile->DrawBorderTiles();
+
+      pRenderer->DrawTerrainPolygon(pTile->uNumVertices, pTile, pBitmaps_LOD->pHardwareTextures[v6], transparent, true);
+      }
+      //else //здесь уже пограничные тайлы воды
+        //pTile->DrawBorderTiles();
+//--------------------------------------------------------------------------------------------------------------------------------
 
       --pOutdoorCamera->numStru148s;
       --pOutdoorCamera->field_44;
@@ -1870,15 +1848,12 @@
   double v13; // ST2C_8@6
   int v14; // eax@6
   double v15; // st7@6
-  stru148 *v16; // ebx@12
+  stru148 *pTile; // ebx@12
   unsigned __int16 v17; // ax@12
   int v18; // eax@13
-  int v19; // ecx@13
-  int v20; // eax@13
-  int v21; // eax@13
   signed int v22; // eax@13
-  Vec3_float_ *v23; // eax@15
-  double v24; // st6@17
+  Vec3_float_ *norm; // eax@15
+  //double v24; // st6@17
   double v25; // ST54_8@17
   unsigned __int8 v26; // sf@17
   unsigned __int8 v27; // of@17
@@ -1893,7 +1868,7 @@
   char v35; // zf@47
   unsigned int v36; // eax@50
   int v37; // eax@54
-  stru148 *v38; // ecx@55
+  //stru148 *v38; // ecx@55
   unsigned int v39; // eax@59
   stru148 *v40; // ebx@62
   unsigned __int16 pTileBitmapsID; // ax@62
@@ -1945,9 +1920,6 @@
   float v87; // [sp+78h] [bp-58h]@122
   int v88; // [sp+7Ch] [bp-54h]@1
   int v89; // [sp+80h] [bp-50h]@6
-  float v90; // [sp+84h] [bp-4Ch]@1
-  float v91; // [sp+88h] [bp-48h]@1
-  float v92; // [sp+8Ch] [bp-44h]@1
   int v93; // [sp+90h] [bp-40h]@2
   int X; // [sp+94h] [bp-3Ch]@1
   float v95; // [sp+98h] [bp-38h]@21
@@ -1985,9 +1957,6 @@
   v4 = 0;
   v88 = 0;
   v84 = a1 - 1;
-  v90 = (float)pOutdoor->vSunlight.x / 65536.0;
-  v91 = (float)pOutdoor->vSunlight.y / 65536.0;
-  v92 = (float)pOutdoor->vSunlight.z / 65536.0;
 /*  if ( a1 - 1 > 0 )
   {
     while ( 1 )
@@ -2043,31 +2012,28 @@
         if ( v8->vWorldPosition.y != pVertices->vWorldPosition.y || pVertices->vWorldPosition.y != pVertices2->vWorldPosition.y 
              || pVertices2->vWorldPosition.y != v101->vWorldPosition.y )
           break;*/
-        v16 = &array_77EC08[pOutdoorCamera->numStru148s];
-        v16->uTileBitmapID = pOutdoor->GetTileTexture(sX, sY);
-        if ( v16->uTileBitmapID != -1 )
-        {
-          v19 = v97;
-          v16->flags = 0x8010 |pOutdoor->GetSomeOtherTileInfo(sX, sY);
-          v16->field_32 = 0;
-          v20 = v93;
-          v16->field_59 = 1;
-          v16->terrain_grid_x = (char)v19;
-          v16->field_34 = *(_WORD *)(v20 + 2);
-          v21 = v89;
-          v16->terrain_grid_z = v89;
-          v22 = pTerrainNormalIndices[2 * (v19 + 128 * v21) + 1];
+        pTile = &array_77EC08[pOutdoorCamera->numStru148s];
+        pTile->uTileBitmapID = pOutdoor->GetTileTexture(sX, sY);
+        if ( pTile->uTileBitmapID != -1 )
+        {
+          pTile->flags = 0x8010 |pOutdoor->GetSomeOtherTileInfo(sX, sY);
+          pTile->field_32 = 0;
+          pTile->field_59 = 1;
+          pTile->terrain_grid_x = (char)v97;
+          pTile->field_34 = *(_WORD *)(v93 + 2);
+          pTile->terrain_grid_z = v89;
+          v22 = pTerrainNormalIndices[2 * (v97 + 128 * v89) + 1];
           if ( v22 < 0 || v22 > uNumTerrainNormals - 1 )
-            v23 = 0;
+            norm = 0;
           else
-            v23 = &pTerrainNormals[v22];
-          v24 = v92 * v23->z;
-          //v99 = v23;
-          thisf = 20.0 - (-v24 - v91 * v23->y - v90 * v23->x) * 20.0;
+            norm = &pTerrainNormals[v22];
+          thisf = 20.0 - ( -(((float)pOutdoor->vSunlight.x / 65536.0) * norm->x) -
+                            (((float)pOutdoor->vSunlight.y / 65536.0) * norm->y) -
+                            (((float)pOutdoor->vSunlight.z / 65536.0) * norm->z)) * 20.0;
           //v25 = thisf + 6.7553994e15;
           //v27 = pOutdoorCamera->numStru148s > 1999;
           //v26 = pOutdoorCamera->numStru148s - 1999 < 0;
-          v16->dimming_level = floorf(thisf + 0.5f);
+          pTile->dimming_level = floorf(thisf + 0.5f);
           if ( pOutdoorCamera->numStru148s >= 1999 )
             return;
           ++pOutdoorCamera->numStru148s;
@@ -2101,8 +2067,8 @@
           }*/
           v32 = (struct8 *)array_50AC10;
           v97 = (int)pGame->pLightmapBuilder;
-          pGame->pLightmapBuilder->StackLights_TerrainFace(v23, &v95, array_50AC10, 4, 1);
-          pDecalBuilder->_49BE8A(v16, v23, &v95, array_50AC10, 4, 1);
+          pGame->pLightmapBuilder->StackLights_TerrainFace(norm, &v95, array_50AC10, 4, 1);
+          pDecalBuilder->_49BE8A(pTile, norm, &v95, array_50AC10, 4, 1);
           a5 = 4;
           if ( byte_4D864C && pGame->uFlags & 0x80 )
           {
@@ -2125,55 +2091,54 @@
               v33 = 3;
             else
               v33 = v108 != 0 ? 5 : 0;
-            static_sub_0048034E_stru_154.ClassifyPolygon(v23, v95);
+            static_sub_0048034E_stru_154.ClassifyPolygon(norm, v95);
             if ( pDecalBuilder->uNumDecals > 0 )
-              pDecalBuilder->ApplyDecals(31 - v16->dimming_level, 4, &static_sub_0048034E_stru_154, a5, array_50AC10, 0, *(float *)&v33, -1);
+              pDecalBuilder->ApplyDecals(31 - pTile->dimming_level, 4, &static_sub_0048034E_stru_154, a5, array_50AC10, 0, *(float *)&v33, -1);
           }
           if ( stru_F8AD28.uNumLightsApplied > 0 )
             pGame->pLightmapBuilder->ApplyLights(&stru_F8AD28, &static_sub_0048034E_stru_154, a5, array_50AC10, 0, v33);
           v34 = a5;
           //v35 = byte_4D864C == 0;
-          v16->uNumVertices = a5;
+          pTile->uNumVertices = a5;
           if ( !byte_4D864C || ~pGame->uFlags & 0x80 )
           {
             if ( this_3 )
             {
               v36 = sr_424CD7(v34);
-              v16->uNumVertices = v36;
+              pTile->uNumVertices = v36;
               OutdoorCamera::Project(v36);
             }
             if ( v108 )
             {
               v36 = sr_424EE0_MakeFanFromTriangle(v34);
-              v16->uNumVertices = v36;
+              pTile->uNumVertices = v36;
               OutdoorCamera::Project(v36);
             }
           }
           //v37 = *(int *)&v16->flags;
-          if ( ~v16->flags & 1 )
+          if ( ~pTile->flags & 1 )
           {
-            if ( v16->flags & 2 && v16->uTileBitmapID == pRenderer->hd_water_tile_id )
+            if ( pTile->flags & 2 && pTile->uTileBitmapID == pRenderer->hd_water_tile_id )
             {
               v80 = false;
               v39 = pRenderer->pHDWaterBitmapIDs[pRenderer->hd_water_current_frame];
             }
             else
             {
-              v39 = v16->uTileBitmapID;
+              v39 = pTile->uTileBitmapID;
               v80 = true;
             }
             //v79 = 0;
             //v78 = pBitmaps_LOD->pHardwareTextures[v39];
-            v16->pTexture = (Texture *)&pBitmaps_LOD->pHardwareTextures[v39];// Ritor1: It's temporary
-            v77 = (int)v16;
+            pTile->pTexture = (Texture *)&pBitmaps_LOD->pHardwareTextures[v39];// Ritor1: It's temporary
+            v77 = (int)pTile;
             //v76 = v16->uNumVertices;
 //LABEL_161:
-            pRenderer->DrawTerrainPolygon(v16->uNumVertices, v16, pBitmaps_LOD->pHardwareTextures[v39], false, v80);
+            pRenderer->DrawTerrainPolygon(pTile->uNumVertices, pTile, pBitmaps_LOD->pHardwareTextures[v39], false, v80);
             goto LABEL_162;
           }
-          v38 = v16;
 LABEL_56:
-          v38->_4811A3();
+          pTile->DrawBorderTiles();
         }
 LABEL_162:
         v4 = v88 + 1;
@@ -2298,7 +2263,7 @@
       v57 = *(int *)&v40->flags;
       if ( BYTE1(v57) & 1 )
       {
-        v40->_4811A3();
+        v40->DrawBorderTiles();
       }
       else
       {
--- a/mm7_3.cpp	Thu Jul 04 09:21:57 2013 +0600
+++ b/mm7_3.cpp	Fri Jul 05 17:37:12 2013 +0600
@@ -7452,17 +7452,16 @@
 }
 
 //----- (004811A3) --------------------------------------------------------
-void stru148::_4811A3()
-{
-  __debugbreak();
-
-  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0));
+void stru148::DrawBorderTiles()
+{
+  //__debugbreak();
+
+  pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
   pRenderer->DrawTerrainPolygon(uNumVertices, this,
-    pBitmaps_LOD->pHardwareTextures[pRenderer->pHDWaterBitmapIDs[pRenderer->hd_water_tile_id]],
-    0, 0);
-
-  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1));
-  pRenderer->DrawTerrainPolygon(uNumVertices, this, pBitmaps_LOD->pHardwareTextures[uTileBitmapID], 1, 1);
+    pBitmaps_LOD->pHardwareTextures[pRenderer->pHDWaterBitmapIDs[pRenderer->hd_water_current_frame]], false, true);
+
+  pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+  //pRenderer->DrawTerrainPolygon(uNumVertices, this, pBitmaps_LOD->pHardwareTextures[uTileBitmapID], true, true);
 }
 
 //----- (00481DB2) --------------------------------------------------------