Ejemplo n.º 1
0
    public void UpdateMeshFrom3dBoundedByHeightMap(
        float[,] heightMap, Defines.MapParams mapSize,
        Vector3 samplingRate, float spaceCreationThreshold)
    {
        var spaceMap = HeightMapAssembler.AssembleSpaceMap(mapSize);
        var vertices = new List <Vector3>();
        var colors   = new List <Color>();

        for (int x = 0; x < mapSize.width; x += (int)samplingRate.x)
        {
            for (int y = 0; y < mapSize.height; y += (int)samplingRate.y)
            {
                for (int z = 0; z < mapSize.depth; z += (int)samplingRate.z)
                {
                    //Debug.Log("Vertex " + x + ", " + y + ", " + z + " = " + spaceMap[x, y, z]);
                    if (heightMap[x, y] * mapSize.depth > z && spaceMap[x, y, z] > spaceCreationThreshold)
                    {
                        vertices.Add(new Vector3(x / (int)samplingRate.x, y / (int)samplingRate.y, z));
                        colors.Add(ColorPicker.GetColor(colorParams, heightMap[x, y]));
                    }
                }
            }
        }
        var mesh = VoxelHandler.CreateMulticubeMesh(vertices, colors);

        filter.mesh = mesh;
    }
Ejemplo n.º 2
0
    public static Mesh CreateMulticubeMeshOptimized(
        float[,] heightMap, System.Func <float, float, float, bool> spaceProbeFunc,
        Vector3 samplingRate, Defines.MapParams mapSize, Defines.ColorThreshold[] colorParams)
    {
        var meshVertices = new List <Vector3>();
        var triangles    = new List <int>();
        var vertColors   = new List <Color>();

        foreach (var face in MarchingCubeFaces.GetFacesToDraw(spaceProbeFunc, heightMap, samplingRate, mapSize))
        {
            if (face.x >= heightMap.GetLength(0) || face.y >= heightMap.GetLength(1))
            {
                continue;
            }
            //Debug.Log("FACE: " + face.x + " " + face.y + " " + face.z);
            var color = ColorPicker.GetColor(colorParams, heightMap[Mathf.Abs(Mathf.FloorToInt(face.x)), Mathf.Abs(Mathf.FloorToInt(face.y))]);

            vertColors.Add(color); vertColors.Add(color); vertColors.Add(color); vertColors.Add(color);

            var l = meshVertices.Count;

            // ToDo: I suppose this logic could be entirely moved to GetFaceVerts(face, cubeOfOrigin)
            var squareVerts = MarchingCubeFaces.GetFaceVerts(face);
            if (Mathf.Floor(face.y) != face.y && spaceProbeFunc(Mathf.Floor(face.x), Mathf.Floor(face.y), Mathf.Floor(face.z)) ||
                Mathf.Floor(face.x) != face.x && !spaceProbeFunc(Mathf.Floor(face.x), Mathf.Floor(face.y), Mathf.Floor(face.z)) ||
                Mathf.Floor(face.z) != face.z && !spaceProbeFunc(Mathf.Floor(face.x), Mathf.Floor(face.y), Mathf.Floor(face.z)))
            {
                meshVertices.Add(squareVerts[0]);
                meshVertices.Add(squareVerts[2]);
                meshVertices.Add(squareVerts[1]);
                meshVertices.Add(squareVerts[3]);
            }
            else
            {
                foreach (var v in squareVerts)
                {
                    meshVertices.Add(v);
                }
            }

            foreach (var t in MarchingCubeFaces.trisList)
            {
                triangles.Add(t + l);
            }
        }
        var mesh = new Mesh
        {
            vertices  = meshVertices.ToArray(),
            triangles = triangles.ToArray(),
            colors    = vertColors.ToArray()
        };

        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

        return(mesh);
    }
Ejemplo n.º 3
0
    public void UpdateMeshFrom3dBoundedByHeightMapOptimized(
        float[,] heightMap, Defines.MapParams mapSize,
        Vector3 samplingRate, System.Func <float, float, float, bool> spaceProbingFunction)
    {
        cleanupChunks();

        // ToDo: Could pass height generating function instead of height map to
        // free ourselves from array.Length() sanity checks and solve potential rounding problems
        System.Func <float, float, float, bool> spaceProbingFunc =
            (x, y, z) => z == 0 ||
            (spaceProbingFunction(x, y, z) &&
             x >= 0 &&
             y >= 0 &&
             z >= 0 &&
             x < heightMap.GetLength(0) &&
             y < heightMap.GetLength(1) &&
             z < heightMap[(int)x, (int)y] * mapSize.depth);

        int xBot = 0;

        while (xBot < mapSize.width)
        {
            int xTop = Mathf.Min(mapSize.width, xBot + chunkSize);
            int yBot = 0;
            while (yBot < mapSize.height)
            {
                int yTop         = Mathf.Min(mapSize.height, yBot + chunkSize);
                var chunkMapSize = new Defines.MapParams(
                    new Vector3(xTop - xBot, yTop - yBot, mapSize.depth),
                    new Vector3(xBot, yBot, mapSize.offset.z));

                GameObject newChunk = prepareNewChunk();

                var chunkMesh = VoxelHandler.CreateMulticubeMeshOptimized(heightMap, spaceProbingFunc, samplingRate, chunkMapSize, colorParams);
                chunkMesh.Optimize();
                newChunk.GetComponent <MeshFilter>().mesh = chunkMesh;
                yBot += chunkSize;
            }
            xBot += chunkSize;
        }
    }
Ejemplo n.º 4
0
    public static List <V3> GetFacesToDraw(System.Func <float, float, float, bool> spaceProbeFunc, float[,] heightMap, V3 samplingRate, Defines.MapParams mapSize)
    {
        // Todo: Consider refactoring samplingRate into mapSize
        Queue <V3>   pointsToHandle = new Queue <V3>();
        HashSet <V3> pointsHandled  = new HashSet <V3>();
        List <V3>    result         = new List <V3>();

        V3 startingPoint = FindStartingPoint(spaceProbeFunc, heightMap, samplingRate, mapSize);

        pointsToHandle.Enqueue(startingPoint);

        while (pointsToHandle.Count > 0)
        {
            var currentPoint = pointsToHandle.Dequeue();

            pointsHandled.Add(currentPoint);

            foreach (var neighbor in NeumannNeighborhood3D(currentPoint))
            {
                var inSpace = spaceProbeFunc(
                    neighbor.x * samplingRate.x,
                    neighbor.y * samplingRate.y,
                    neighbor.z * samplingRate.z);
                var isThisInBounds = InBounds(neighbor, mapSize, samplingRate);

                // we know at this point that currentPoint is solid, so we only create faces
                // between it and its non-solid neighbors
                if (!inSpace && isThisInBounds)
                {
                    var face = GetFaceMidpoint(currentPoint, neighbor);
                    result.Add(face);
                    foreach (var n in GetPositionsNeighboringFace(face))
                    {
                        var isInBounds  = InBounds(n, mapSize, samplingRate);
                        var belowGround = isInBounds && (
                            heightMap[
                                (int)(n.x * samplingRate.x),
                                (int)(n.y * samplingRate.y)] * mapSize.depth > n.z);
                        var wasAlreadyHandled     = pointsHandled.Contains(n);
                        var spaceCreationAllowsIt = spaceProbeFunc(
                            (n.x) * samplingRate.x,
                            (n.y) * samplingRate.y,
                            (n.z) * samplingRate.z);

                        // ToDo: this could be optimized, I think, by looking at the output of all faces
                        // and removing ones that cannot have neighboring face with the cube
                        if (belowGround && !wasAlreadyHandled && spaceCreationAllowsIt)
                        {
                            pointsToHandle.Enqueue(n);
                            pointsHandled.Add(n);
                        }
                    }
                }
            }
        }

        return(result);
    }
Ejemplo n.º 5
0
    public static V3 FindStartingPoint(System.Func <float, float, float, bool> spaceProbeFunc, float[,] heightMap, V3 samplingRate, Defines.MapParams mapSize)
    {
        // Todo: find a sensible null check for C#
        // Todo: this looks from the middle of the chunk and iterates over 1/4 of its area
        //   This will cause issues when there are holes in the map.
        //   Might need to look for a more sophisticated way.
        int x = (int)(mapSize.width) / (int)samplingRate.x / 2 + (int)mapSize.offset.x;

        while (x < mapSize.width + mapSize.offset.x)
        {
            int y = (int)(mapSize.height) / (int)samplingRate.y / 2 + (int)mapSize.offset.y;
            while (y < mapSize.height + mapSize.offset.y)
            {
                int z = (int)(heightMap[x, y] * mapSize.depth) + 1;
                while (z > 0)
                {
                    var isInSpace = spaceProbeFunc(
                        x * samplingRate.x,
                        y * samplingRate.y,
                        z * samplingRate.z);
                    var isBelowGround = heightMap[
                        (int)(x * samplingRate.x),
                        (int)(y * samplingRate.y)] * mapSize.depth > z * samplingRate.z;
                    if (isInSpace && isBelowGround)
                    {
                        return(new V3(x, y, z));
                    }
                    z -= (int)samplingRate.z;
                }
                y += (int)samplingRate.y;
            }
            x += (int)samplingRate.x;
        }
        Debug.LogWarning("Not a single vertex is of use. Too bad.");
        return(new V3(0, 0, 0));
    }
Ejemplo n.º 6
0
 public static bool InBounds(V3 point, Defines.MapParams bounds, V3 sampling)
 {
     return(point.x >= bounds.offset.x && point.y >= bounds.offset.y &&
            point.x < (bounds.width + bounds.offset.x) / sampling.x &&
            point.y < (bounds.height + bounds.offset.y) / sampling.y);
 }
Ejemplo n.º 7
0
    public static float[,] Generate(IEnumerable <Defines.GeneratorLayer> layerParams, Defines.MapParams mapSize, Vector3 globalScale)
    {
        float[,] result = new float[mapSize.width, mapSize.height];
        foreach (Defines.GeneratorLayer layer in layerParams)
        {
            System.Func <float, float, float> generatorMethod = GeneratorMethods2d.ChooseFunc(layer);
            float[,] map = HeightMapAssembler.AssembleHeightMap(mapSize, generatorMethod, globalScale);

            // prone to change when I find an elegant way of doing this (Zip?)
            for (int i = 0; i < mapSize.width; i++)
            {
                for (int j = 0; j < mapSize.height; j++)
                {
                    result[i, j] += map[i, j] * layer.significance;
                }
            }
        }

        Normalize(result);
        return(result);
    }