Esempio n. 1
0
        public static ObjectPoint[] CreateObjectPoints(int uniformSize, MeshSettings meshSettings, ResourceMapSettings resourceMapSettings, BiomeMap biomeMap, HeightMap heightMap, TerrainChunk terrainChunk)
        {
            string fileName = $"chunkInfo{terrainChunk.Coord.x}{terrainChunk.Coord.y}.dat";

            // Try to load a save file
            if (File.Exists(SaveDataManager.WorldDataPath + fileName))
            {
                return(ObjectMapLoader.LoadObjectMap(terrainChunk, SaveDataManager.WorldDataPath).ObjectPoints);
            }
            else
            {
                //ResourceMap resourceMap = ResourceMapGenerator.GenerateResourceMap(uniformSize, resourceMapSettings, terrainChunk.SampleCenter);

                ResourceMap resourceMap = ResourceMapGenerator.GenerateResourceMap(uniformSize, resourceMapSettings, terrainChunk.SampleCenter, biomeMap, heightMap);

                List <ObjectPoint> tempObjectPoints = new List <ObjectPoint>();

                // Resource points to object points
                foreach (var resourcePoint in resourceMap.resourcePoints)
                {
                    int x = resourcePoint.x;
                    int z = resourcePoint.z;

                    HeightMapLayer layer = heightMap.GetLayer(x + 1, z + 1);

                    // Don't spawn objects on water.
                    if (layer.IsWater)
                    {
                        continue;
                    }

                    float   height   = heightMap.Values[x + 1, z + 1];
                    Vector3 position = new Vector3(terrainChunk.Bounds.center.x, 0f, terrainChunk.Bounds.center.y) + new Vector3((x - (uniformSize - 1) / 2f) * meshSettings.MeshScale, height, (z - (uniformSize - 1) / 2f) * -meshSettings.MeshScale);

                    // Create a seeded System.Random for the rotation based on the position
                    float         a    = position.x + position.y;
                    float         b    = position.z + position.y;
                    System.Random rand = new System.Random((int)(0.5 * (a + b) * (a + b + 1) + b));

                    Quaternion rotation = Quaternion.Euler(new Vector3(0f, rand.Next(0, 360), 0f));

                    int chunkPartSize = uniformSize / meshSettings.ChunkPartSizeRoot + 1;
                    int coordX        = Mathf.FloorToInt(x / chunkPartSize) - 1;
                    int coordZ        = Mathf.FloorToInt(z / chunkPartSize) - 1;

                    Vector2 chunkPartCoords = terrainChunk.Coord * meshSettings.ChunkPartSizeRoot + new Vector2(coordX, -coordZ);

                    tempObjectPoints.Add(new ObjectPoint(position, rotation, resourcePoint.biomeId, resourcePoint.worldResourcePrefabId, chunkPartCoords.x, chunkPartCoords.y));
                }

                return(tempObjectPoints.ToArray());
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Generates a <see cref="DataMap"/> that consists of a heightmap, biomeMap and resourceMap based on a single size. Divides the resourceMap in <see cref="DataMap.ChunkParts"/> based on <see cref="MeshSettings.ChunkPartSizeRoot"/>
        /// </summary>
        /// <param name="terrainChunk">The terrain chunk that requested the DataMap.</param>
        /// <returns></returns>
        public static DataMap GenerateDataMap(MeshSettings meshSettings, HeightMapSettings heightMapSettings, BiomeMapSettings biomeMapSettings, ResourceMapSettings resourceMapSettings, TerrainChunk terrainChunk)
        {
            int size        = meshSettings.NumVertsPerLine;
            int uniformSize = size - 2;

            // Generate data maps
            HeightMap heightMap = HeightMapGenerator.GenerateHeightMap(size, heightMapSettings, terrainChunk.SampleCenter);
            BiomeMap  biomeMap  = BiomeMapGenerator.GenerateBiomeMap(uniformSize, biomeMapSettings, terrainChunk.SampleCenter);

            // Create chunk parts
            Dictionary <Vector2, TerrainChunkPart> chunkParts = CreateChunkParts(uniformSize, meshSettings, terrainChunk);

            FillChunkParts(uniformSize, ref chunkParts, meshSettings, resourceMapSettings, biomeMap, heightMap, terrainChunk);

            return(new DataMap(uniformSize, heightMap, biomeMap, chunkParts));
        }
Esempio n. 3
0
        public TerrainChunk(Vector2 coord, HeightMapSettings heightMapSettings, BiomeMapSettings biomeMapSettings, ResourceMapSettings resourceMapSettings, MeshSettings meshSettings, LODInfo[] detailLevels, int colliderLODIndex, Transform parent, TerrainViewer viewer, Material terrainMeshMaterial)
        {
            this.Coord               = coord;
            this.HeightMapSettings   = heightMapSettings;
            this.BiomeMapSettings    = biomeMapSettings;
            this.ResourceMapSettings = resourceMapSettings;
            this.MeshSettings        = meshSettings;
            this.detailLevels        = detailLevels;
            this.colliderLODIndex    = colliderLODIndex;
            this.Viewer              = viewer;

            SampleCenter = coord * meshSettings.MeshWorldSize / meshSettings.MeshScale;
            Vector2 position = coord * meshSettings.MeshWorldSize;

            Bounds = new Bounds(position, Vector2.one * meshSettings.MeshWorldSize);

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

            MeshObject.AddComponent <TerrainChunkInteraction>().TerrainChunk = this;

            MeshObject.transform.position = new Vector3(position.x, 0, position.y);
            MeshObject.transform.parent   = parent;
            MeshObject.layer = parent.gameObject.layer;

            SetVisible(false);

            lodMeshes = new LODMesh[detailLevels.Length];
            for (int i = 0; i < detailLevels.Length; i++)
            {
                lodMeshes[i] = new LODMesh(detailLevels[i].Lod);
                lodMeshes[i].UpdateCallback += UpdateTerrainChunk;
                if (i == colliderLODIndex)
                {
                    lodMeshes[i].UpdateCallback += UpdateCollisionMesh;
                }
            }

            MaxViewDistance = detailLevels[detailLevels.Length - 1].VisibleDistanceThreshold;
        }
Esempio n. 4
0
        private static void FillChunkParts(int uniformSize, ref Dictionary <Vector2, TerrainChunkPart> chunkParts, MeshSettings meshSettings, ResourceMapSettings resourceMapSettings, BiomeMap biomeMap, HeightMap heightMap, TerrainChunk terrainChunk)
        {
            ObjectPoint[] objectPoints = CreateObjectPoints(uniformSize, meshSettings, resourceMapSettings, biomeMap, heightMap, terrainChunk);

            // Fill chunk parts
            for (int i = 0; i < objectPoints.Length; i++)
            {
                Vector2          chunkPartCoords  = new Vector2(objectPoints[i].chunkPartCoordX, objectPoints[i].chunkPartCoordZ);
                TerrainChunkPart terrainChunkPart = chunkParts[chunkPartCoords];

                terrainChunkPart.AddObjectPoint(objectPoints[i]);
            }
        }
Esempio n. 5
0
        private static Dictionary <Vector2, TerrainChunkPart> CreateChunkParts(int uniformSize, MeshSettings meshSettings, TerrainChunk terrainChunk)
        {
            Dictionary <Vector2, TerrainChunkPart> chunkParts = new Dictionary <Vector2, TerrainChunkPart>();

            int chunkRangeHalf = Mathf.FloorToInt(meshSettings.ChunkPartSizeRoot / 2f); // ONLY WORKS FOR UNEVEN NUMBERS AT THE MOMENT

            for (int x = -chunkRangeHalf; x <= chunkRangeHalf; x++)
            {
                for (int z = -chunkRangeHalf; z <= chunkRangeHalf; z++)
                {
                    Vector2 chunkPartCoord    = terrainChunk.Coord * meshSettings.ChunkPartSizeRoot + new Vector2(x, z);
                    Vector3 partWorldPosition = new Vector3(terrainChunk.Bounds.size.x / meshSettings.ChunkPartSizeRoot * chunkPartCoord.x, 0f, terrainChunk.Bounds.size.y / meshSettings.ChunkPartSizeRoot * chunkPartCoord.y);

                    chunkParts.Add(chunkPartCoord, new TerrainChunkPart(chunkPartCoord, partWorldPosition, terrainChunk));
                }
            }

            return(chunkParts);
        }
Esempio n. 6
0
 public void RequestMesh(HeightMap heightMap, MeshSettings meshSettings)
 {
     HasRequestedMesh = true;
     ThreadedDataRequester.RequestData(() => MeshGenerator.GenerateTerrainMesh(heightMap.Values, meshSettings, lod), OnMeshDataReceived);
 }
Esempio n. 7
0
        /// <summary>
        /// Generates a MeshData object that can be used to construct a mesh.
        /// </summary>
        /// <param name="map">The map values.</param>
        /// <param name="meshSettings">The settings for the mesh.</param>
        /// <param name="levelOfDetail">0 for highest detail.</param>
        public static MeshData GenerateTerrainMesh(float[,] map, MeshSettings meshSettings, int levelOfDetail)
        {
            int skipIncrement   = (levelOfDetail == 0) ? 1 : levelOfDetail * 2;
            int numVertsPerLine = meshSettings.NumVertsPerLine;

            Vector2 topLeft = new Vector2(-1, 1) * meshSettings.MeshWorldSize / 2f;

            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)
                    {
                        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           = map[x, y];

                        if (isEdgeConnectionVertex)
                        {
                            bool  isVertical         = x == 2 || x == numVertsPerLine - 3;
                            int   dstToMainVertexA   = ((isVertical) ? y - 2 : x - 2) % skipIncrement;
                            int   dstToMainVertexB   = skipIncrement - dstToMainVertexA;
                            float dstPercentFromAToB = dstToMainVertexA / (float)skipIncrement;

                            Coord coordA = new Coord((isVertical) ? x : x - dstToMainVertexA, (isVertical) ? y - dstToMainVertexA : y);
                            Coord coordB = new Coord((isVertical) ? x : x + dstToMainVertexB, (isVertical) ? y + dstToMainVertexB : y);

                            float heightMainVertexA = map[coordA.x, coordA.y];
                            float heightMainVertexB = map[coordB.x, coordB.y];

                            height = heightMainVertexA * (1 - dstPercentFromAToB) + heightMainVertexB * dstPercentFromAToB;

                            EdgeConnectionVertexData edgeConnectionVertexData = new EdgeConnectionVertexData(vertexIndex, vertexIndicesMap[coordA.x, coordA.y], vertexIndicesMap[coordB.x, coordB.y], dstPercentFromAToB);
                            meshData.DeclareEdgeConnectionVertex(edgeConnectionVertexData);
                        }

                        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.ProcessMesh();

            return(meshData);
        }