Search Unity

Off By One error generating a mesh

Discussion in 'Scripting' started by jzaun, Oct 12, 2010.

  1. jzaun

    jzaun

    Joined:
    Feb 20, 2010
    Posts:
    26
    I have what I think is an off-by-one error in my mesh generation code but can seem to find it after staring at it for hours. The function is below and I've attached the _HeightMapPreview texture and a screen-shot of the issue. The _mapSize is 512. The issue is there is a gap between each block of the terrain. I'm hoping another set of eyes (or a few sets) will help.

    Edit: The Heightmap has an alpha channel so it looks blank.

    Code (csharp):
    1.  
    2.    public void BuildMesh()
    3.     {
    4.         GameObject oTerrain = new GameObject();
    5.         oTerrain.name = "Terrain";
    6.        
    7.         float meshSize = 200f;
    8.         if (_mapSize == 256)
    9.             meshSize = 400;
    10.         if (_mapSize == 512)
    11.             meshSize = 800;
    12.        
    13.         int blocks = (int) Mathf.Ceil(_mapSize / 128f);
    14.         int partsPerBlock = (int)Mathf.Ceil(_mapSize / blocks);
    15.        
    16.         Debug.Log("Map Size: " + _mapSize.ToString());
    17.         Debug.Log("Blocks: " + blocks.ToString());
    18.         Debug.Log("Parts Per Block: " + partsPerBlock.ToString());
    19.        
    20.         for (int i = 0; i < blocks; i++)
    21.         {
    22.             for (int j = 0; j < blocks; j++)
    23.             {
    24.                 GameObject oBlock = new GameObject();
    25.                 oBlock.name = "Block " + (j*blocks + i).ToString();
    26.                 oBlock.transform.parent = oTerrain.transform;
    27.                 oBlock.AddComponent<MeshFilter>();
    28.                 oBlock.AddComponent<MeshRenderer>();
    29.                
    30.                 Mesh oMesh = oBlock.GetComponent<MeshFilter>().sharedMesh;
    31.                 if(oMesh == null)
    32.                     oMesh = new Mesh();
    33.            
    34.                 Vector3[] vertices = new Vector3[partsPerBlock * partsPerBlock];
    35.                 Vector2[] uv = new Vector2[partsPerBlock * partsPerBlock];
    36.                 Vector4[] tangents = new Vector4[partsPerBlock * partsPerBlock];
    37.                
    38.                 Vector2 uvScale = new Vector2 (1.0f / (_mapSize - 1), 1.0f / (_mapSize - 1));
    39.                 Vector3 sizeScale = new Vector3(meshSize / (_mapSize - 1), 50f, meshSize / (_mapSize - 1));
    40.                
    41.                 int startX = partsPerBlock * i;
    42.                 if (startX < 0)
    43.                     startX = 0;
    44.                 int endX = startX + partsPerBlock;
    45.                 if (endX > _mapSize)
    46.                     endX = _mapSize;
    47.                 int startY = partsPerBlock * j;
    48.                 if (startY < 0)
    49.                     startY = 0;
    50.                 int endY = startY + partsPerBlock;
    51.                 if (endY > _mapSize)
    52.                     endY = _mapSize;
    53.                
    54.                 for (int x = startX; x < endX; x++)
    55.                 {
    56.                     for (int y = startY; y < endY; y++)
    57.                     {
    58.                         int posX = x - startX;
    59.                         int posY = y - startY;
    60.                         //Debug.Log("["+posX.ToString()+", "+posY.ToString()+"] - "+(posY * partsPerBlock + posX).ToString() + " - "+vertices.Length.ToString());
    61.                        
    62.                         float h = _HeightMapPreview.GetPixel(x,y).r +_HeightMapPreview.GetPixel(x,y).g + _HeightMapPreview.GetPixel(x,y).b + _HeightMapPreview.GetPixel(x,y).a;
    63.                         Vector3 vertex = new Vector3(x, h, y);
    64.                         vertices[posY * partsPerBlock + posX] = Vector3.Scale(sizeScale, vertex);
    65.                         uv[posY * partsPerBlock + posX] = Vector2.Scale(new Vector2 (x, y), uvScale);
    66.        
    67.                         // Calculate tangent vector: a vector that goes from previous vertex
    68.                         // to next along X direction. We need tangents if we intend to
    69.                         // use bumpmap shaders on the mesh.
    70.                         h = _HeightMapPreview.GetPixel(x-1,y).r +_HeightMapPreview.GetPixel(x-1,y).g + _HeightMapPreview.GetPixel(x-1,y).b + _HeightMapPreview.GetPixel(x-1,y).a;
    71.                         Vector3 vertexL = new Vector3(x - 1, h, y);
    72.                         h = _HeightMapPreview.GetPixel(x+1,y).r +_HeightMapPreview.GetPixel(x+1,y).g + _HeightMapPreview.GetPixel(x+1,y).b + _HeightMapPreview.GetPixel(x+1,y).a;
    73.                         Vector3 vertexR = new Vector3(x + 1, h, y);
    74.                         Vector3 tan = Vector3.Scale(sizeScale, vertexR - vertexL).normalized;
    75.                         tangents[posY * partsPerBlock + posX] = new Vector4(tan.x, tan.y, tan.z, -1.0f);
    76.                     }
    77.                 }
    78.                
    79.                 // Assign them to the mesh
    80.                 oMesh.vertices = vertices;
    81.                 oMesh.uv = uv;
    82.            
    83.                 // Build triangle indices: 3 indices into vertex array for each triangle
    84.                 int[] triangles = new int[(partsPerBlock) * (partsPerBlock) * 6];
    85.                 int index = 0;
    86.                 for (int y = startY; y < endY - 1; y++)
    87.                 {
    88.                     for (int x = startX; x < endX - 1; x++)
    89.                     {
    90.                         int posX = x - startX;
    91.                         int posY = y - startY;
    92.  
    93.                         // For each grid cell output two triangles
    94.                         triangles[index++] = (posY * partsPerBlock) + posX;
    95.                         triangles[index++] = ((posY+1) * partsPerBlock) + posX;
    96.                         triangles[index++] = (posY * partsPerBlock) + posX + 1;
    97.                        
    98.                         triangles[index++] = ((posY+1) * partsPerBlock) + posX;
    99.                         triangles[index++] = ((posY+1) * partsPerBlock) + posX + 1;
    100.                         triangles[index++] = (posY * partsPerBlock) + posX + 1;
    101.                     }
    102.                 }
    103.                
    104.                 // And assign them to the mesh
    105.                 oMesh.triangles = triangles;
    106.                
    107.                 // Auto-calculate vertex normals from the mesh
    108.                 oMesh.RecalculateNormals();
    109.                
    110.                 // Assign tangents after recalculating normals
    111.                 oMesh.tangents = tangents;
    112.                
    113.                 oBlock.GetComponent<MeshFilter>().sharedMesh = oMesh;
    114.             }
    115.         }
    116.     }
    117.  
     

    Attached Files:

    Last edited: Oct 12, 2010