简体   繁体   中英

Trying to smooth generated mesh in unity

I am having problems with creating the smooth, and i am getting some undesirable details Like this The way its working now i can control how i generate mesh, but i am kind of forced to create a function which try to smooth the mesh. But i get some weird error connected to a array sorting which i executed after all the threads are done, and the debug.log don't even output anything.

NullReferenceException: Object reference not set to an instance of an object.

Generation of the vertices is done with multi threaded manner, so i am not sure if that affect my array.

    {


        for (int i = 0, z = 0; z <= tileMeshSize; z++)
        {
            for (int x = 0; x <= tileMeshSize; x++)
            {
                float y = TerrainBasicGeology.CreatingY(x + tileData.xStartPos, z + tileData.zStartPos, perlinNoiseScale, perlinNoiseHeigh, tileData);
                tileData.vertices[i] = new Vector3((x * tileSizeScaleModifier), (y * tileSizeScaleModifier), (z * tileSizeScaleModifier));
                i++;
            }
        }
        Vector3[] tempVector = TerrainBasicGeology.SmoothingTile(tileData, tileThreadContainer, tileMeshSize, tileSizeScaleModifier, perlinNoiseScale, perlinNoiseHeigh);
        Array.Clear(tileData.vertices,0, tileData.vertices.Length);

        tileData.vertices = tempVector;

If i just remove function TerrainBasicGeology.SmoothingTile then its fine.

    public static Vector3[] SmoothingTile(TileData tileData, TileThreadContainer tileThreadContainer, int tileMeshSize, int tileSizeScaleModifier, int perlinNoiseScale, int perlinNoiseHeigh)
    {
        tileThreadContainer.tempVectorArray = new Vector3[(tileMeshSize + 1) * (tileMeshSize + 1)];
        for (int i = 0, z = 0; z <= tileMeshSize; z++)
        {
            for (int x = 0; x <= tileMeshSize; x++)
            {
                



                for (int j = 0, k = 0, zCheck = 0; zCheck <= tileMeshSize; zCheck++)
                {
                    for (int xCheck = 0; xCheck <= tileMeshSize; xCheck++)
                    {
                        float checkSmoothDistance = Vector3.Distance(tileData.vertices[i], tileData.vertices[j]);
                        if (checkSmoothDistance < 10)
                        {
                            tileThreadContainer.tempContainerCQ.Enqueue(tileData.vertices[j]);
                            k++;
                        }

                        j++;
                    }
                }

                float averageVector = 0;
                for (int c = 0; c < tileThreadContainer.tempContainerCQ.Count; c++)
                {
                    tileThreadContainer.tempContainerCQ.TryDequeue(out Vector3 tempVector);
                    averageVector = averageVector + tempVector.y;
                }
                Vector3 newVectorY = new Vector3(tileData.vertices[i].x, averageVector, tileData.vertices[i].z);

                //Check
                if ((x != 0) || (x != tileMeshSize) || (z != 0) || (z != tileMeshSize))
                {
                    tileThreadContainer.tempVectorArray[i] = newVectorY;
                }
                else
                {
                    tileThreadContainer.tempVectorArray[i] = tileData.vertices[i];
                }
                i++;
            }
        }
        Debug.Log(tileThreadContainer.tempVectorArray);
        Debug.Log(tileData.vertices);
        return tileThreadContainer.tempVectorArray;
    }

}

edit1: This starts the thread

 tasks[x] = Task.Run(() => TerrainGenerator.CreatingTile(tileCQ, tileThreadContainer[x], tileArrayData[x], tileMeshSize, tileSizeScaleModifier, perlinNoiseScale, perlinNoiseHeigh));

I think my problem when the TerrainBasicGeology.SmoothingTile is used but i am not sure were it is because i get an error that is not directly connected to the function, and Debug.log don't say anything. What do i get wrong? Any pointers would be nice.

Solved my problem by just adding another for loop after the first creation of vertices. Then just gather the average of different points from the perlin function around a vertex i want to smooth.

    for (int i = 0, z = 0; z <= tileMeshSize; z++)
    {
        for (int x = 0; x <= tileMeshSize; x++)
        {
            //Smoothing
            float y = TerrainBasicGeology.SmoothingY(x + tileData.xStartPos, z + tileData.zStartPos, perlinNoiseScale, perlinNoiseHeigh, tileData);
            tileData.vertices[i] = new Vector3((tileData.tileContainer.baseVertices[i].x), (y), (tileData.tileContainer.baseVertices[i].z));
            Vector3 continentAreaVector = new Vector3((tileData.tileContainer.baseVertices[i].x), (y), (tileData.tileContainer.baseVertices[i].z));

            i++;
        }
    }

Smooth function

public static float SmoothingY(int xPos, int zPos, int perlinNoiseScale, int perlinNoiseheigh, TileData tileData)
{
    float averageY = .0f;
    int smoothValue = 10;
    int i = 0;
    for (int z = -2; z <= 2; z++)
    {
        for (int x = -2; x <= 2; x++)
        {
            averageY = averageY + CreatingY((x + xPos) * smoothValue, (z + zPos) * smoothValue, perlinNoiseScale, perlinNoiseheigh, tileData);
            i++;
        }
    }

    float newY = averageY / (i + 1);
    return newY;
}

This solved my problem for me, and it works on multiple threads

I think the problem might be caused by 2 reasons(might be not 100% correct though, so interpret these just as hints):

  1. Some piece of data(eg vertices array) used by several threads and isn't being locked. This might be caused because several threads simultaneously are trying to get/modify the same piece of data and Unity will not like that.
  2. Unity has some internal optimizations because of which such incorrect behavior can be caused even if you use lock() on shared data. I had this problem with AnimationCurve object when I generated random terrain mesh. In this case you can create local temp copy of the used object, and use only that copy inside the function which is used in separate thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM