예제 #1
0
    // Create a single chunk's matrix of nodes
    // arguements are the chunks index, not their true positions
    void CreateChunkMatrix(int x, int y, int z)
    {
        // For heirarchy cleaning purposes I create multiple game objects to be nested within eachother
        ChunkMatrix currChunkMatrix = new ChunkMatrix(xChunkCubeLength, yChunkCubeLength, zChunkCubeLength);
        GameObject  chunkObj        = Instantiate(chunk_parent, Vector3.zero, Quaternion.identity);

        chunkObj.transform.parent = mapHolder.transform;
        chunkObj.tag             = "Chunk";
        currChunkMatrix.chunkObj = chunkObj;

        Mesh mesh = new Mesh();

        mesh.SetVertices(currChunkMatrix.vertices);
        mesh.SetTriangles(currChunkMatrix.indices, 0);
        currChunkMatrix.chunkMesh = new GameObject("Mesh");
        currChunkMatrix.chunkMesh.transform.parent = currChunkMatrix.chunkObj.transform;
        currChunkMatrix.chunkMesh.AddComponent <MeshCollider>();
        currChunkMatrix.chunkMesh.AddComponent <MeshFilter>();
        currChunkMatrix.chunkMesh.AddComponent <MeshRenderer>();
        currChunkMatrix.chunkMesh.GetComponent <Renderer>().material       = mesh_material;
        currChunkMatrix.chunkMesh.GetComponent <MeshFilter>().mesh         = mesh;
        currChunkMatrix.chunkMesh.GetComponent <MeshCollider>().sharedMesh = mesh;
        currChunkMatrix.chunkMesh.tag = "Mesh";
        currChunkMatrix.chunkMesh.transform.localPosition = Vector3.zero;

        // this is like the local positions of the chunk with respect to other chunks
        currChunkMatrix.chunksIndex = new int [] { x, y, z };

        // this is the true position of the start of the chunk in unity units... or whatever
        currChunkMatrix.position = new Vector3(x * xChunkLength / (float)cubeResolution, y * yChunkLength / (float)cubeResolution, z * zChunkLength / (float)cubeResolution);

        AddNodesToChunk(currChunkMatrix);

        AddNoiseToChunk(currChunkMatrix);
    }
예제 #2
0
    // Function to change values in the noise map
    //      x,y,z are the nodes position inside the chunk
    void SetNoiseValues(ChunkMatrix currChunk, int x, int y, int z, float isovalue, int width)
    {
        float fWidth = width; // / (float)cubeResolution;

        // get the indices in the noise map for the supplied position
        int[] hitIndices = emptyHitIndices;
        hitIndices[0] = currChunk.nodes[x, y, z].noiseIndices[0];
        hitIndices[1] = currChunk.nodes[x, y, z].noiseIndices[1];
        hitIndices[2] = currChunk.nodes[x, y, z].noiseIndices[2];

        int[] chunkIndices = emptyChunkIndices;
        chunkIndices[0] = currChunk.chunksIndex[0];
        chunkIndices[1] = currChunk.chunksIndex[1];
        chunkIndices[2] = currChunk.chunksIndex[2];


        // if its in the middle of the chunks
        if (chunkIndices[0] > 0 && chunkIndices[0] < xChunks - 1 &&
            chunkIndices[1] > 0 && chunkIndices[1] < yChunks - 1 &&
            chunkIndices[2] > 0 && chunkIndices[2] < zChunks - 1)
        {
            for (int y_ = hitIndices[1] - width; y_ < hitIndices[1] + width; y_++)
            {
                for (int z_ = hitIndices[2] - width; z_ < hitIndices[2] + width; z_++)
                {
                    for (int x_ = hitIndices[0] - width; x_ < hitIndices[0] + width; x_++)
                    {
                        // Create vectors to check the distances between the nodes within the range of the hit point
                        distanceP1.x = x_;
                        distanceP1.y = y_;
                        distanceP1.z = z_;
                        distanceP2.x = hitIndices[0];
                        distanceP2.y = hitIndices[1];
                        distanceP2.z = hitIndices[2];

                        float checkDst = Vector3.Distance(distanceP1, distanceP2);

                        if (checkDst <= fWidth)
                        {
                            mapNoise[x_, y_, z_] += isovalue;
                            if (mapNoise[x_, y_, z_] > 1)
                            {
                                mapNoise[x_, y_, z_] = 1;
                            }
                            else if (mapNoise[x_, y_, z_] < 0)
                            {
                                mapNoise[x_, y_, z_] = 0;
                            }
                        }
                    }
                }
            }
        }
        else
        {
            Debug.Log(chunkIndices[0] + ", " + chunkIndices[1] + ", " + chunkIndices[2]);       // tells the console that it clicked on an edge rather than somewhere in the middle
        }
    }
예제 #3
0
    // Function to reset the chunk's mesh data
    ChunkMatrix ResetChunkMeshData(ChunkMatrix hitChunk)
    {
        hitChunk.vertices.Clear();
        hitChunk.indices.Clear();
        hitChunk.vertexCount = 0;

        // reset the noise in the chunk
        AddNoiseToChunk(hitChunk);

        return(hitChunk);
    }
예제 #4
0
 // This function sets up the cube-by-cube marching within the polygonize function for a specific chunk
 void MarchThroughChunk(ChunkMatrix currChunk)
 {
     for (int y = 1; y < currChunk.nodes.GetLength(1) - 1; y++)
     {
         for (int x = 1; x < currChunk.nodes.GetLength(0) - 1; x++)
         {
             for (int z = 1; z < currChunk.nodes.GetLength(2) - 1; z++)
             {
                 currChunk = PolygonizeCube(currChunk, x, y, z);
             }
         }
     }
 }
예제 #5
0
    // Add all of the necessary nodes to the chunk matrix
    void AddNodesToChunk(ChunkMatrix currChunk)
    {
        for (int y = 0; y < yChunkCubeLength; y++)
        {
            for (int z = 0; z < zChunkCubeLength; z++)
            {
                for (int x = 0; x < xChunkCubeLength; x++)
                {
                    currChunk.nodes[x, y, z] = new Node(Vector3.zero, 0f);
                }
            }
        }

        // place the current chunk into the chunk array
        chunks[currChunk.chunksIndex[0], currChunk.chunksIndex[1], currChunk.chunksIndex[2]] = currChunk;
    }
예제 #6
0
    // Check which vertices around the cube are active (above surfaceLevel
    public static int CheckVertices(ChunkMatrix currChunk, ChunkMatrix[,,] chunks, float surfaceLevel, int x, int y, int z)
    {
        // Initialize the cube index
        int cubeIndex = 0;

        // get nodes of the current chunk
        Node[,,] nodes = currChunk.nodes;

        // check which vertices around the cube are active
        // the order assigned in this mannor is essential for how the LUT(look up tables) are set up
        // the order corresponds to the vertices in Paul Burke's graphic on his 1994 site about Polygonizing a scalar field
        if (nodes[x, y, z + 1].isovalue <= surfaceLevel)           // vertex 0
        {
            cubeIndex |= 1;
        }
        if (nodes[x + 1, y, z + 1].isovalue <= surfaceLevel)       // vertex 1
        {
            cubeIndex |= 2;
        }
        if (nodes[x + 1, y, z].isovalue <= surfaceLevel)           // vertex 2
        {
            cubeIndex |= 4;
        }
        if (nodes[x, y, z].isovalue <= surfaceLevel)               // vertex 3
        {
            cubeIndex |= 8;
        }
        if (nodes[x, y + 1, z + 1].isovalue <= surfaceLevel)       // vertex 4
        {
            cubeIndex |= 16;
        }
        if (nodes[x + 1, y + 1, z + 1].isovalue <= surfaceLevel)   // vertex 5
        {
            cubeIndex |= 32;
        }
        if (nodes[x + 1, y + 1, z].isovalue <= surfaceLevel)       // vertex 6
        {
            cubeIndex |= 64;
        }
        if (nodes[x, y + 1, z].isovalue <= surfaceLevel)           // vertex 7
        {
            cubeIndex |= 128;
        }


        return(cubeIndex);
    }
예제 #7
0
    // Function to draw the mesh of a given chunk
    //      x y z are the indicies in the chunk matrix for which chunk youre referencing not the chunks position
    void DrawSingleMesh(ChunkMatrix currChunk)
    {
        MeshFilter filter = currChunk.chunkMesh.GetComponent <MeshFilter>();
        Mesh       mesh   = filter.mesh;

        filter.mesh = null;
        mesh.Clear();
        mesh.SetVertices(currChunk.vertices);
        mesh.SetTriangles(currChunk.indices, 0);
        mesh.RecalculateNormals();

        filter.mesh = mesh;
        MeshCollider collider = currChunk.chunkMesh.GetComponent <MeshCollider>();

        collider.sharedMesh = null;
        collider.sharedMesh = mesh;
    }
예제 #8
0
    // I want to change this so that it just works on the current voxel rather than have the material fly at the user

    // Update is called once per frame
    void Update()
    {
        CameraMovement();

        if (Input.GetMouseButton(0) || Input.GetMouseButton(1))
        {
            // dir variable is used to dictate whether the cubes are being deleted or added to
            int dir = 0;
            if (Input.GetMouseButton(0))
            {
                dir = 1;
            }
            else if (Input.GetMouseButton(1))
            {
                dir = -1;
            }
            RaycastHit hit;
            Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit, 20f) && hit.transform.tag == "Mesh")
            {
                Vector3 hitPos = hit.point;
                int[]   currentChunkIndices = GetCurrentChunkFromPos(hitPos);
                int[]   currentVoxelIndices = GetCurrentCubeInChunkFromPos(hitPos);


                // get the chunk that the ray hit
                ChunkMatrix hitChunk = chunks[currentChunkIndices[0], currentChunkIndices[1], currentChunkIndices[2]];

                // change the noise values around the affected point
                SetNoiseValues(hitChunk, currentVoxelIndices[0], currentVoxelIndices[1], currentVoxelIndices[2], dir * editValue, radius);



                // update the chunks around the affected mesh
                UpdateSurroundingChunks(currentChunkIndices[0], currentChunkIndices[1], currentChunkIndices[2]);
            }
        }
    }
예제 #9
0
    // Function to fill the chunk matrix with the noise values
    //      x,y,z are chunk's indices
    void AddNoiseToChunk(ChunkMatrix currChunk)
    {
        int x = currChunk.chunksIndex[0];
        int y = currChunk.chunksIndex[1];
        int z = currChunk.chunksIndex[2];

        float currNoise = 0;

        // iterate through the noiseMap and add the noise to the current node in the chunk matrix
        for (int _y = 0, k = y * (yChunkCubeLength - 2); k < y * (yChunkCubeLength - 2) + yChunkCubeLength; k++, _y++)
        {
            for (int _z = 0, j = z * (zChunkCubeLength - 2); j < z * (zChunkCubeLength - 2) + zChunkCubeLength; j++, _z++)
            {
                for (int _x = 0, i = x * (xChunkCubeLength - 2); i < x * (xChunkCubeLength - 2) + xChunkCubeLength; i++, _x++)
                {
                    // get the noise from the large noise map
                    currNoise = mapNoise[i, k, j];

                    // define the node's position in unity space'
                    //Debug.Log(currChunk.nodes[_x, _y, _z].position.x);
                    currChunk.nodes[_x, _y, _z].position.x = _x / (float)cubeResolution + x * xChunkLength;
                    currChunk.nodes[_x, _y, _z].position.y = _y / (float)cubeResolution + y * yChunkLength;
                    currChunk.nodes[_x, _y, _z].position.z = _z / (float)cubeResolution + z * zChunkLength;

                    // define the node's isovalue
                    currChunk.nodes[_x, _y, _z].isovalue = currNoise;

                    // define the node's location on the noise map
                    currChunk.nodes[_x, _y, _z].noiseIndices[0] = i;
                    currChunk.nodes[_x, _y, _z].noiseIndices[1] = k;
                    currChunk.nodes[_x, _y, _z].noiseIndices[2] = j;

                    // add the working matrix to the array of chunks
                    chunks[x, y, z] = currChunk;
                }
            }
        }
    }
예제 #10
0
    // Function to set a specific chunk's specific node's isovalue
    //      also set the chunks around it
    ChunkMatrix SetIsovalues(ChunkMatrix currChunk, int x, int y, int z, float isovalue, int width)
    {
        float fWidth = width / (float)cubeResolution;



        for (int k = 0; k < yChunkCubeLength; k++)
        {
            for (int j = 0; j < zChunkCubeLength; j++)
            {
                for (int i = 0; i < xChunkCubeLength; i++)
                {
                    float checkDst = Vector3.Distance(currChunk.nodes[i, k, j].position, currChunk.nodes[x, y, z].position);
                    // any nodes within the width of the "brush"
                    if (checkDst <= fWidth)
                    {
                        currChunk.nodes[i, k, j].isovalue += isovalue;
                    }
                }
            }
        }

        return(currChunk);
    }
예제 #11
0
 void DestroyChunk(ChunkMatrix currChunk)
 {
     // destroy the mesh object from the current chunk
     Destroy(currChunk.chunkMesh);
 }
예제 #12
0
    // Function to check each corner of a given cube - this is the "March" of Marching Cubes
    //      The x,y,z arguments are the positions of nodes in a chunk's node matrix
    //      The currChunk argument is the nodes within the current chunk's matrix data
    ChunkMatrix PolygonizeCube(ChunkMatrix currChunk, int x, int y, int z)
    {
        Node[,,] nodes = currChunk.nodes;

        // get the type of cube dependant on the active vertices within it
        int cubeIndex = MarchingCubes.CheckVertices(currChunk, chunks, surfaceLevel, x, y, z);

        // if there were no active nodes in this cube, break the function
        if (cubeIndex == 0)
        {
            return(currChunk);
        }

        // use the edge table to obtain which edges are active for this cube configuration
        int edges = MarchingCubes.edgeTable[cubeIndex];

        // array holding the positions of each edge vertex
        Vector3[] edgeVertices = emptyVertices;

        // value of which vertex is being worked on at the moment for the mesh creation
        int vert;

        // Find the vertices for the triangles in the cube - TODO: do the interpolation here   *****************************************
        for (int i = 0; i < edgeVertices.Length; i++)      // edge vertices length is the numver of edges in the cube
        {
            if ((edges & (1 << i)) != 0)                   // checks the boolean values from the edges table to see which edges are active
            {
                // start by assuming a hard edge - turn softEdge to false to create a more flat terrain
                float edgeOffset = 1 / (float)cubeResolution / 2f;

                // turning on softEdge will use the linear interpolation to smooth out the edges
                if (softEdge)
                {
                    float[] cube = MarchingCubes.GetIsovaluesOfCube(nodes, x, y, z);
                    edgeOffset = MarchingCubes.CalculateEdgeOffset(cube[MarchingCubes.edgeConnection[i, 0]], cube[MarchingCubes.edgeConnection[i, 1]], surfaceLevel) / (float)cubeResolution;
                }

                // The edgeVertices array holds the position for where the vertex will be drawn along the edge
                //      To figure this out, we need the position of the current node added to the
                //          VertexOffset defined by the LUT that shows where the next edge is in comparison to this current one
                //          The vertex offset needs to be divided by the cube resolution because the distance between edges will change if there are more cubes in the same amount of space
                //          The edgeOffset is the linear interpolated value we found and it is basically a percentage of how far between the current and next node that the vertex should be placed
                //          The edgeOffset needs to be multiplied by the edgeDirection value in order to know which direction that the offset is in

                edgeVertices[i].x = nodes[x, y, z].position.x + MarchingCubes.vertexOffset[MarchingCubes.edgeConnection[i, 0], 0] / (float)cubeResolution + edgeOffset * MarchingCubes.edgeDirection[i, 0];
                edgeVertices[i].y = nodes[x, y, z].position.y + MarchingCubes.vertexOffset[MarchingCubes.edgeConnection[i, 0], 1] / (float)cubeResolution + edgeOffset * MarchingCubes.edgeDirection[i, 1];
                edgeVertices[i].z = nodes[x, y, z].position.z + MarchingCubes.vertexOffset[MarchingCubes.edgeConnection[i, 0], 2] / (float)cubeResolution + edgeOffset * MarchingCubes.edgeDirection[i, 2];
            }
        }

        // Create the triangles from these verts - there will be at most 5 triangles to be made per cube
        for (int i = 0; i < 5; i++)
        {
            if (MarchingCubes.triTable[cubeIndex, 3 * i] < 0)       // no triangles to be made
            {
                break;
            }

            // get the current number of verts in the mesh
            int vertexCount = currChunk.vertices.Count;


            for (int j = 0; j < 3; j++)                             // iterate through the triangle verts
            {
                vert = MarchingCubes.triTable[cubeIndex, 3 * i + j];
                currChunk.indices.Add(vertexCount + windingOrder[j]);
                currChunk.vertices.Add(edgeVertices[vert]);
            }
        }


        return(currChunk);
    }
예제 #13
0
    // Use this for initialization
    void Start()
    {
        Global.Instance.InitClient();

        Global.Instance.CurrentScene = SceneManager.GetActiveScene().name;
        Global.Instance.MoveMessages.Clear();

        entitiesNode = GameObject.FindGameObjectWithTag("Entities");

        entityMatrix = new ChunkMatrix<MapEntity>(chunksize);
        mapMatrix = new ChunkMatrix<GameObject>(chunksize);
        mapObjMatrix = new ChunkMatrix<GameObject>(chunksize);
        groundMatrix = new ChunkMatrix<Int32>(chunksize);
        mapOverlayMatrix = new ChunkMatrix<List<GameObject>>(chunksize);
        populationMatrix = new ChunkMatrix<List<PopulationEntity>>(chunksize);
        mapEntities = new Dictionary<Int32, MapEntity>();
    }