public void RequestMesh(HeightMap heightMap, MeshSettings meshSettings)
 {
     hasRequestedMesh = true;
     ThreadedDataRequester.RequestData(
         () => MeshGenerator.GenerateTerrainMesh(heightMap.values, meshSettings, lod),
         OnMeshDataReceived);
 }
        public TerrainChunk(Vector2 coords, HeightMapSettings heightMapSettings, MeshSettings meshSettings,
                            LODInfo[] detailLevels, int colliderLODIndex, Transform parent, Transform viewer, Material material)
        {
            this.coord             = coords;
            this.heightMapSettings = heightMapSettings;
            this.meshSettings      = meshSettings;
            this.detailLevels      = detailLevels;
            this.colliderLODIndex  = colliderLODIndex;
            this.viewer            = viewer;
            maxViewDist            = detailLevels[detailLevels.Length - 1].visibleDistThreshold;

            sampleCenter = coords * meshSettings.meshWorldSize / meshSettings.meshScale;
            Vector2 position = coord * meshSettings.meshWorldSize;

            bounds = new Bounds(sampleCenter, Vector2.one * meshSettings.meshWorldSize);

            meshObject            = new GameObject("Terrain Chunk");
            meshRenderer          = meshObject.AddComponent <MeshRenderer>();
            meshCollider          = meshObject.AddComponent <MeshCollider>();
            meshFilter            = meshObject.AddComponent <MeshFilter>();
            meshRenderer.material = material;

            meshObject.transform.position = new Vector3(position.x, 0, position.y);
            meshObject.transform.SetParent(parent, false);
            SetVisible(false);

            lodMeshes = new LODMesh[detailLevels.Length];
            for (int i = 0; i < lodMeshes.Length; ++i)
            {
                lodMeshes[i] = new LODMesh(detailLevels[i].lod);
                lodMeshes[i].updateCallback += UpdateTerrainChunk;
                if (i == colliderLODIndex)
                {
                    lodMeshes[i].updateCallback += UpdateCollisionMesh;
                }
            }
        }
Exemplo n.º 3
0
        public static MeshData GenerateTerrainMesh(float[,] heightMap, MeshSettings meshSettings, int levelOfDetail)
        {
            // can support LODs of (NumSupportedLODs - 1)
            int skipIncrement   = (levelOfDetail == 0) ? 1 : levelOfDetail * 2;
            int numVertsPerLine = meshSettings.NumVertsPerLine;

            Vector2 topLeft = new Vector2(-1, 1) * meshSettings.meshWorldSize * .5f;

            MeshData meshData = new MeshData(numVertsPerLine, skipIncrement, meshSettings.useFlatShading);

            int[,] vertexIndicesMap = new int[numVertsPerLine, numVertsPerLine];
            int meshVertexIndex      = 0;
            int outOfMeshVertexIndex = -1;

            for (int y = 0; y < numVertsPerLine; ++y)
            {
                for (int x = 0; x < numVertsPerLine; ++x)
                {
                    bool isOutOfMeshVertex = y == 0 || y == numVertsPerLine - 1 || x == 0 || x == numVertsPerLine - 1;
                    bool isSkippedVertex   =
                        x > 2 && x < numVertsPerLine - 3 &&
                        y > 2 && y < numVertsPerLine - 3 &&
                        ((x - 2) % skipIncrement != 0 || (y - 2) % skipIncrement != 0);
                    if (isOutOfMeshVertex)
                    {
                        vertexIndicesMap[x, y] = outOfMeshVertexIndex;
                        --outOfMeshVertexIndex;
                    }
                    else if (!isSkippedVertex)
                    {
                        vertexIndicesMap[x, y] = meshVertexIndex;
                        ++meshVertexIndex;
                    }
                }
            }

            for (int y = 0; y < numVertsPerLine; ++y)
            {
                for (int x = 0; x < numVertsPerLine; ++x)
                {
                    bool isSkippedVertex =
                        x > 2 && x < numVertsPerLine - 3 &&
                        y > 2 && y < numVertsPerLine - 3 &&
                        ((x - 2) % skipIncrement != 0 || (y - 2) % skipIncrement != 0);
                    if (isSkippedVertex)
                    {
                        continue;
                    }

                    bool isOutOfMeshVertex = y == 0 || y == numVertsPerLine - 1 || x == 0 || x == numVertsPerLine - 1;
                    bool isMeshEdgeVertex  = y == 1 || y == numVertsPerLine - 2 || x == 1 || x == numVertsPerLine - 2 &&
                                             !isOutOfMeshVertex;
                    bool isMainVertex = (x - 2) % skipIncrement == 0 && (y - 2) % skipIncrement == 0 &&
                                        !isOutOfMeshVertex && !isMeshEdgeVertex;
                    bool isEdgeConnectionVertex = (y == 2 || y == numVertsPerLine - 3 || x == 2 || x == numVertsPerLine - 3) &&
                                                  !isOutOfMeshVertex && !isMeshEdgeVertex && !isMainVertex;

                    int     vertexIndex      = vertexIndicesMap[x, y];
                    Vector2 percent          = new Vector2(x - 1, y - 1) / (numVertsPerLine - 3);
                    Vector2 vertexPosition2D = topLeft + new Vector2(percent.x, -percent.y) * meshSettings.meshWorldSize;
                    float   height           = heightMap[x, y];

                    if (isEdgeConnectionVertex)
                    {
                        bool  isVertical          = x == 2 || x == numVertsPerLine - 3;
                        int   distToMainVertexA   = (isVertical ? y - 2 : x - 2) % skipIncrement;
                        int   distToMainVertexB   = skipIncrement - distToMainVertexA;
                        float distPercentFromAToB = distToMainVertexA / (float)skipIncrement;

                        float heightMainVertexA = heightMap[isVertical ? x : x - distToMainVertexA, isVertical ? y - distToMainVertexA : y];
                        float heightMainVertexB = heightMap[isVertical ? x : x + distToMainVertexB, isVertical ? y + distToMainVertexB : y];

                        height = heightMainVertexA * (1 - distPercentFromAToB) + heightMainVertexB * distPercentFromAToB;
                    }


                    meshData.AddVertex(new Vector3(vertexPosition2D.x, height, vertexPosition2D.y), percent, vertexIndex);

                    bool createTriangle = x < numVertsPerLine - 1 && y < numVertsPerLine - 1 &&
                                          (!isEdgeConnectionVertex || (x != 2 && y != 2));

                    if (createTriangle)
                    {
                        int currentIncrement = (isMainVertex && x != numVertsPerLine - 3 && y != numVertsPerLine - 3) ? skipIncrement : 1;
                        int a = vertexIndicesMap[x, y];
                        int b = vertexIndicesMap[x + currentIncrement, y];
                        int c = vertexIndicesMap[x, y + currentIncrement];
                        int d = vertexIndicesMap[x + currentIncrement, y + currentIncrement];
                        meshData.AddTriangle(a, d, c);
                        meshData.AddTriangle(d, a, b);
                    }
                }
            }

            meshData.FinalizeNormals();
            return(meshData);
        }