示例#1
0
    // an array of MeshFilters, with opaque mesh stored in 0; alpha test mesh stored in 1
    public void UpdateChunk(Vector2Int pos, Mesh opaque, Mesh alphaTest)
    {
        ChunkInstance chunk;

        if (instances.ContainsKey(pos))
        {
            chunk = instances[pos];
        }
        else
        {
            chunk          = new ChunkInstance();
            instances[pos] = chunk;

            var obj = Instantiate(chunkPrefab, new Vector3(pos.x << Chunk.CHUNK_X_SHIFT, 0, pos.y << Chunk.CHUNK_Z_SHIFT), Quaternion.identity, transform);
            chunk.opaqueMeshFilter   = obj.GetComponent <MeshFilter>();
            chunk.opaqueMeshCollider = obj.GetComponent <MeshCollider>();
            obj.GetComponent <MeshRenderer>().sharedMaterial = opaqueMaterial;

            var obj2 = Instantiate(chunkPrefab, new Vector3(pos.x << Chunk.CHUNK_X_SHIFT, 0, pos.y << Chunk.CHUNK_Z_SHIFT), Quaternion.identity, transform);
            chunk.alphaTestMeshFilter   = obj2.GetComponent <MeshFilter>();
            chunk.alphaTestMeshCollider = obj2.GetComponent <MeshCollider>();
            obj2.GetComponent <MeshRenderer>().sharedMaterial = alphaMaterial;
        }

        chunk.opaqueMeshFilter.mesh            = opaque;
        chunk.alphaTestMeshFilter.mesh         = alphaTest;
        chunk.opaqueMeshCollider.sharedMesh    = opaque;
        chunk.alphaTestMeshCollider.sharedMesh = alphaTest;
        if (enableStaticBatching)
        {
            StaticBatchingUtility.Combine(gameObject);
        }
    }
    //create a new chunk GameObject. needs to be passed certain values and also be made a child of this object (for neatness)
    ChunkInstance CreateNewChunk(Vector3 worldPos, int lodProfile)
    {
        GameObject newChunk = new GameObject(GetName(worldPos));

        newChunk.transform.parent   = transform;
        newChunk.transform.position = worldPos + transform.position;
        ChunkInstance c = newChunk.AddComponent <ChunkInstance>();

        c.Setup(worldPos, lodProfile, useCollisions);
        return(c);
    }
示例#3
0
    public void InstantiateChunk(BlockTerrain.Chunk c)
    {
        int           index    = Terrain.GetChunkIndex(c.chunkx, c.chunky);
        ChunkInstance instance = Terrain.chunkInstances[index];

        instance.UpdateAll(c);
        instance.UpdateMesh(0);
        instance.UpdateMesh(1);
        chunkRenderer.AddChunk(index);
        //chunkInstanceManager.LoadChunkInstance(instance);
    }
示例#4
0
    public BlockTerrain()
    {
        chunks = new Chunk[terrainSize * terrainSize];

        chunkStats     = new ChunkStatus(terrainSize);
        chunkInstances = new ChunkInstance[terrainSize * terrainSize];

        for (int i = 0; i < chunkInstances.Length; i++)
        {
            chunkInstances[i] = new ChunkInstance();
        }
    }
 //if infinite world is disabled, generate the simple grid of chunks
 void GenerateFixedChunks()
 {
     for (int x = 0; x < fixedChunkDimensions.x; x++)
     {
         for (int y = 0; y < fixedChunkDimensions.y; y++)
         {
             for (int z = 0; z < fixedChunkDimensions.z; z++)
             {
                 Vector3 worldPos = new Vector3(x, y, z) * actualDimension;
                 db.Generate(threadsPerAxis + 1, worldPos);
                 ChunkInstance c = CreateNewChunk(worldPos, 0);
                 GenerateChunkMesh(c);
             }
         }
     }
 }
    //method which calls the marching cubes algorithm and recieves its data to create the mesh for a given chunk
    void GenerateChunkMesh(ChunkInstance c)
    {
        //basic stuff: get the lod, set the material to be right one for its lod level
        int lodModifier = lodProfiles[c.lodIndex].lodModifier;

        c.SetMat(lodProfiles[c.lodIndex].mat);
        marchCompute.SetInt("lodModifier", lodModifier);

        //init buffers so data can be properly collected later
        triangleBuffer.SetCounterValue(0);
        int threads = Mathf.Max(threadsPerAxis / lodModifier, 1);

        marchCompute.Dispatch(0, threads, threads, threads);

        //get length of triangles to be made
        ComputeBuffer.CopyCount(triangleBuffer, triCountBuffer, 0);
        int[] triCountArray = { 0 };
        triCountBuffer.GetData(triCountArray);
        int numTris = triCountArray[0];

        //retrieve triangle data
        Triangle[] triangles = new Triangle[numTris];
        triangleBuffer.GetData(triangles, 0, 0, numTris);

        //get the vertices and triangles for the mesh
        Vector3[] vertices      = new Vector3[numTris * 3];
        int[]     meshTriangles = new int[numTris * 3];
        for (int i = 0; i < numTris; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                meshTriangles[i * 3 + j] = i * 3 + j;
                vertices[i * 3 + j]      = triangles[i][j];
            }
        }

        c.mesh.Clear();
        c.mesh.vertices  = vertices;
        c.mesh.triangles = meshTriangles;
        c.mesh.RecalculateNormals();

        if (useCollisions)
        {
            c.collider.enabled = false;
            c.collider.enabled = true;
        }
    }
示例#7
0
    void Export(string exportPath)
    {
        BlockTerrain terrain = FindObjectOfType <TerrainManager>().Terrain;

        int[] chunks = FindObjectOfType <ChunkRenderer>().RenderingChunks;

        List <Mesh>      ms = new List <Mesh>();
        List <Matrix4x4> ts = new List <Matrix4x4>();

        for (int i = 0; i < chunks.Length; i++)
        {
            ChunkInstance instance = terrain.chunkInstances[chunks[i]];

            ms.Add(instance.Meshes[0]);
            ts.Add(instance.transform);
            ms.Add(instance.Meshes[1]);
            ts.Add(instance.transform);
        }

        Export(exportPath, ms.ToArray(), ts.ToArray());
    }
示例#8
0
    public override void _Ready()
    {
        GD.Print("Ready to create world!");

        if (densityGeneratorPath == null)
        {
            GD.PushError("VoxelTerrain must have a Density Generator.");
            return;
        }

        densityGenerator = GetNode <DensityGenerator>(densityGeneratorPath);
        if (densityGenerator == null)
        {
            GD.PushError("VoxelTerrain could not locate the supplied Density Generator.");
            return;
        }

        if (observerPath == null)
        {
            GD.PushError("VoxelTerrain must have an observer.");
            return;
        }

        observer = GetNode <Spatial>(observerPath);
        if (observer == null)
        {
            GD.PushError("VoxelTerrain could not locate the supplied observer.");
            return;
        }

        if (!(observer is Camera))
        {
            observer = (Camera)observer.FindNode("Camera");
        }

        if (debugLabelPath != null)
        {
            debugLabel = GetNode <Label>(debugLabelPath);
        }

        for (int y = -5; y < 5; y++)
        {
            for (int z = -5; z <= 5; z++)
            {
                for (int x = -5; x <= 5; x++)
                {
                    var at    = new ChunkPosition(x, y, z);
                    var chunk = new Chunk(at);
                    AddChunk(chunk);

                    var instance = new ChunkInstance(chunk)
                    {
                        MaterialOverride = material
                    };

                    chunk.InitDensity(densityGenerator.GetDensity);
                    AddChild(instance);
                }
            }
        }

        var origoChunk = chunks[new ChunkPosition(0, 0, 0)];

        origoChunk.GetLuminance().Init();
        origoChunk.ForEachChunk(chunk => chunk.TriangulateChunk());

        SetPhysicsProcess(true);
    }
    //handles which chunks should be created, updated, or destroyed if infiniteWorld is enabled
    void GenerateVisibleChunks()
    {
        Vector3 p      = camera.transform.position;
        Vector3 pCoord = WorldPos2Coord(p);

        //iterates through the currently active chunks to find which ones need to be recycled (if in the wrong LOD for it's position or too far away to be seen)
        //if does need to be recycled, add them to the queue to be used later
        foreach (ChunkInstance c in chunks)
        {
            float sqrDis = Vector3.SqrMagnitude(ChunkPos2Centre(c.coord) - p);
            if (sqrDis > sqrViewDis || GetLODProfile(sqrDis) != c.lodIndex)
            {
                chunksToRecycle.Enqueue(c);
                chunkCoords.Remove(c.coord);
            }
        }

        //runs through the possible chunk positions. if there is a chunk at said position, move to the next. if there isn't, add one.
        int maxChunksInView = Mathf.CeilToInt(viewDistance / (float)actualDimension);

        for (int x = -maxChunksInView; x <= maxChunksInView; x++)
        {
            for (int y = -maxChunksInView; y <= maxChunksInView; y++)
            {
                for (int z = -maxChunksInView; z <= maxChunksInView; z++)
                {
                    Vector3 worldPos = pCoord + new Vector3(x, y, z) * actualDimension;

                    if (chunkCoords.Contains(worldPos))
                    {
                        continue;
                    }

                    //make sure that chunk is close enough and also in the direction the player is facing. otherwise it doesn't need to be generated
                    Vector3 centre = ChunkPos2Centre(worldPos);
                    float   sqrDis = Vector3.SqrMagnitude(centre - p);
                    if (sqrDis <= sqrViewDis)
                    {
                        Bounds bounds = new Bounds(centre, Vector3.one * actualDimension);
                        if (IsVisible(bounds))
                        {
                            //now run the RNG to generate random terrain for our point
                            db.Generate(threadsPerAxis + 1, worldPos);
                            int lodProfile = GetLODProfile(sqrDis);

                            //if we still have chunk GameObjects that were created previously and needed to be recycled, use one. if we don't, create a new GameObject.
                            if (chunksToRecycle.Count > 0)
                            {
                                ChunkInstance c = chunksToRecycle.Dequeue();
                                c.name = GetName(worldPos);
                                c.transform.position = transform.position + worldPos;
                                c.coord    = worldPos;
                                c.lodIndex = lodProfile;
                                GenerateChunkMesh(c);
                                chunkCoords.Add(worldPos);
                            }
                            else
                            {
                                ChunkInstance c = CreateNewChunk(worldPos, lodProfile);
                                GenerateChunkMesh(c);
                                chunks.Add(c);
                                chunkCoords.Add(worldPos);
                            }
                        }
                    }
                }
            }
        }

        //if any chunks that were recycled and didn't end up being used, they can be destroyed
        while (chunksToRecycle.Count > 0)
        {
            ChunkInstance c = chunksToRecycle.Dequeue();
            chunks.Remove(c);
            Destroy(c.gameObject);
        }
    }
示例#10
0
 public ExecutionQueueEntity(CompiledChunk chunk, ChunkInstance instance)
 {
     Chunk    = chunk;
     Instance = instance;
 }
示例#11
0
 void RenderChunk(ChunkInstance instance)
 {
     Graphics.DrawMesh(instance.Meshes[0], instance.transform, terrain, chunkLayer, Camera.main);
     Graphics.DrawMesh(instance.Meshes[1], instance.transform, alaphaTest, chunkLayer, Camera.main);
 }