예제 #1
0
    /// <summary>
    /// Adds this loaded chunk to the generation que
    /// </summary>
    /// <param name="chunk"></param>
    public void AddToGenerationQue(LoadedChunk2 chunk)
    {
        Debug.Log("Added to gen que");
        float priority = chunk.LOD;

        //If we already contain this chunk, then we don't need to add again


        //Stay thread safe - add object
        lock (ChunkToLoadLock)
        {
            if (ChunksToLoad2.Contains(chunk))
            {
                return;
            }
            ChunksToLoad2.Enqueue(chunk, priority);
        }
        if (MainThread == null || !MainThread.IsAlive)
        {
            //We start/restart the internal load loop
            MainThread = new Thread(() => InternalThreadLoop());
            Debug.Log("[ChunkLoader] Chunk Loader thread starting", Debug.CHUNK_LOADING);
            MainThread.Start();
        }
    }
예제 #2
0
    /// <summary>
    /// Takes a 'preloadedchunk' and forms a loaded chunk
    /// This must be called from the main thread.
    /// </summary>
    /// <param name="pChunk"></param>
    /// <returns></returns>
    private LoadedChunk2 CreateChunk(PreLoadedChunk pChunk, ChunkData cd)
    {
        GameObject cObj = Instantiate(ChunkPrefab);

        cObj.transform.parent   = ChunkHolder.transform;
        cObj.transform.position = pChunk.Position.AsVector3() * World.ChunkSize;

        cObj.name = "chunk_" + pChunk.Position;
        LoadedChunk2 loaded = cObj.GetComponent <LoadedChunk2>();

        MeshFilter mf = loaded.GetComponent <MeshFilter>();

        //Create the terrain mesh
        mf.mesh = PreLoadedChunk.CreateMesh(pChunk.TerrainMesh);
        mf.mesh.RecalculateNormals();
        MeshCollider mc = loaded.GetComponent <MeshCollider>();

        mc.sharedMesh = mf.mesh;
        //Iterate all voxels
        foreach (Voxel v in MiscUtils.GetValues <Voxel>())
        {
            if (v == Voxel.none)
            {
                continue;
            }
            if (pChunk.VoxelMesh.TryGetValue(v, out PreMesh pmesh))
            {
                GameObject voxelObj = Instantiate(ChunkVoxelPrefab);
                MeshFilter voxelMf  = voxelObj.GetComponent <MeshFilter>();
                voxelMf.mesh = PreLoadedChunk.CreateMesh(pmesh);
                Material voxMat = ResourceManager.GetVoxelMaterial(v);
                //Debug.Log(voxMat + " vox mat");
                voxelObj.GetComponent <MeshRenderer>().material = voxMat;
                MeshCollider voxelMc = voxelObj.GetComponent <MeshCollider>();
                voxelMc.sharedMesh               = voxelMf.mesh;
                voxelObj.transform.parent        = cObj.transform;
                voxelObj.transform.localPosition = Vector3.zero;

                voxelMf.mesh.RecalculateNormals();
            }
        }
        if (cd.WorldObjects != null)
        {
            foreach (WorldObjectData objDat in cd.WorldObjects)
            {
                WorldObject obj = WorldObject.CreateWorldObject(objDat, cObj.transform, 0.7f);
                //if(objDat.AutoHeight)
                //    obj.AdjustHeight();
                //obj.transform.position = objDat.Position;
                //obj.transform.localPosition = objDat.Position.Mod(World.ChunkSize);
            }
        }

        loaded.SetChunk(pChunk.ChunkData);
        return(loaded);
    }
예제 #3
0
    public override bool Equals(object other)
    {
        if (other == null || (other as LoadedChunk2) == null)
        {
            return(false);
        }
        LoadedChunk2 lc = other as LoadedChunk2;

        return(lc.Position == Position);
    }
    private LoadedChunk2 CreateChunk(PreLoadedChunk pChunk)
    {
        GameObject cObj = Instantiate(ChunkPrefab);
        cObj.transform.parent = transform;

        cObj.name = "chunk_" + pChunk.Position;
        LoadedChunk2 loaded = cObj.GetComponent<LoadedChunk2>();

        MeshFilter mf = loaded.GetComponent<MeshFilter>();
        //Create the terrain mesh
        mf.mesh = PreLoadedChunk.CreateMesh(pChunk.TerrainMesh);
        mf.mesh.RecalculateNormals();
        MeshCollider mc = loaded.GetComponent<MeshCollider>();
        mc.sharedMesh = mf.mesh;
        //Iterate all voxels
        foreach (Voxel v in MiscUtils.GetValues<Voxel>())
        {
            if (v == Voxel.none)
                continue;
            if (pChunk.VoxelMesh.TryGetValue(v, out PreMesh pmesh))
            {
                GameObject voxelObj = Instantiate(ChunkVoxelPrefab);
                MeshFilter voxelMf = voxelObj.GetComponent<MeshFilter>();
                MeshRenderer voxelMr = voxelObj.GetComponent<MeshRenderer>();
                voxelMr.material = ResourceManager.GetVoxelMaterial(v);
                voxelMf.mesh = PreLoadedChunk.CreateMesh(pmesh);
                MeshCollider voxelMc = voxelObj.GetComponent<MeshCollider>();
                voxelMc.sharedMesh = voxelMf.mesh;
                voxelObj.transform.parent = cObj.transform;
                voxelObj.transform.localPosition = Vector3.up * (pChunk.ChunkData.BaseHeight + 0.7f);

                voxelMf.mesh.RecalculateNormals();
            }
        }

        cObj.transform.position = pChunk.Position.AsVector3() * World.ChunkSize;
        loaded.SetChunk(pChunk.ChunkData);

        if (pChunk.ChunkData.WorldObjects != null)
        {
            foreach (WorldObjectData objData in pChunk.ChunkData.WorldObjects)
            {
                Vec2i localPos = Vec2i.FromVector3(objData.Position.Mod(World.ChunkSize));
                float off = loaded.Chunk.GetHeight(localPos);
                WorldObject obj = WorldObject.CreateWorldObject(objData, loaded.transform, off + 0.7f);
                obj.AdjustHeight();
            }


        }

        return loaded;
    }
예제 #5
0
    /// <summary>
    /// Adds the loaded chunk to the chunk buffer.
    /// This should be used when a chunk position is no longer required
    /// </summary>
    /// <param name="chunk"></param>
    public void AddToChunkBuffer(LoadedChunk2 chunk)
    {
        chunk.gameObject.name = "Unloaded";
        if (chunk.HasLoadedWorldObjects || chunk.HasGeneratedVoxels)
        {
            foreach (Transform t in chunk.transform)
            {
                Destroy(t.gameObject);
            }
        }

        ChunkBuffer.Add(chunk);
    }
    public void UnloadChunk(Vec2i chunk)
    {
        if (LoadedChunks.ContainsKey(chunk))
        {
            LoadedChunk2 loaded = LoadedChunks[chunk];
            lock (LoadedChunksLock)
            {
                LoadedChunks.Remove(chunk);
            }


            //We set inactive, and add it the chunk Loaders ChunkBuffer
            loaded.gameObject.SetActive(false);
            ChunkLoader.AddToChunkBuffer(loaded);
            //GameManager.EntityManager.UnloadChunk(chunk);
            //Destroy(loaded.gameObject);
        }
    }
예제 #7
0
    private void LoadSingleObject(int count = 0)
    {
        if (count > 10)
        {
            return;
        }

        WorldObjectData objData = null;


        lock (ObjectsToLoadLock) {
            objData = ObjectsToLoad[0];
            ObjectsToLoad.RemoveAt(0);
        }
        //Find the chunk for the first object to generate
        Vec2i chunk = World.GetChunkPosition(objData.Position);



        LoadedChunk2 lc2 = ChunkRegionManager.GetLoadedChunk(chunk);

        if (lc2 == null)
        {
            //Debug.Log(chunk);
            Debug.Log("[ChunkLoader] Chunk ( " + chunk + " ) for object ( " + objData + " ) is not loaded, attempting another object");
            //if the chunk is null, we throw this object to the end of the que and try again.
            lock (ObjectsToLoadLock)
            {
                ObjectsToLoad.Add(objData);
            }
            LoadSingleObject(count + 1);
            return;
        }
        Vec2i       localPos = Vec2i.FromVector3(objData.Position.Mod(World.ChunkSize));
        float       off      = lc2.Chunk.GetHeight(localPos);
        WorldObject obj      = WorldObject.CreateWorldObject(objData, lc2.transform, off + 0.7f);
        //Debug.Log("Created object " + obj);
        //obj.AdjustHeight();
    }
    /// <summary>
    /// Loads all chunks within a square of size 2*radius centred on the player
    /// </summary>
    /// <param name="middle"></param>
    /// <param name="radius"></param>
    public void LoadChunks(Vec2i middle, int radius, bool forceLoad)
    {
        Debug.BeginDeepProfile("load_chunks");



        //We define a list of chunks to unload
        List <Vec2i> toUnload = new List <Vec2i>();

        HashSet <int> currentlyLoadedH = new HashSet <int>();

        lock (LoadedChunksLock)
        {
            //A list containing all the chunks currently loaded
            foreach (KeyValuePair <Vec2i, LoadedChunk2> kvp in LoadedChunks)
            {
                int distSqr = middle.QuickDistance(kvp.Key);
                if (distSqr > radius * radius)
                {
                    toUnload.Add(kvp.Key);
                }

                currentlyLoadedH.Add(kvp.Key.GetHashCode());
            }
        }

        lock (ToGetLoadedChunksLOCK)
        {
            foreach (KeyValuePair <ChunkData, int> kvp in ToGetLoadedChunks)
            {
                currentlyLoadedH.Add(kvp.Key.Position.GetHashCode());
            }
        }
        foreach (Vec2i v in ChunkLoader.GetCurrentlyLoadingChunks())
        {
            currentlyLoadedH.Add(v.GetHashCode());
        }
        //We iterate each chunk too far from the player, and unload it
        foreach (Vec2i v in toUnload)
        {
            UnloadChunkSafe(v);
            //UnloadChunk(v);
        }

        LoadedChunksCentre = middle;

        Debug.EndDeepProfile("load_chunks");
        Debug.BeginDeepProfile("load_chunks1");

        //We now iterate the position of each chunk we require
        for (int x = -radius; x <= radius; x++)
        {
            for (int z = -radius; z <= radius; z++)
            {
                //Check if the requested position is inside world bounds
                if (x + middle.x < 0 || x + middle.x >= World.WorldSize - 1 || z + middle.z < 0 || z + middle.z >= World.WorldSize - 1)
                {
                    continue;
                }
                Vec2i pos     = new Vec2i(x + middle.x, z + middle.z);
                int   distSqr = middle.QuickDistance(pos);
                if (distSqr > radius * radius)
                {
                    continue;
                }
                int lod     = CalculateLOD(distSqr);
                int posHash = pos.GetHashCode();
                //if our currently loaded does not contain the position, we must generate it
                if (!currentlyLoadedH.Contains(posHash))
                {
                    //Attempt to get the chunk data
                    ChunkData cd = GetChunk(pos);
                    if (cd == null)
                    {
                        // Debug.Log("Chunk at " + pos + " was null");
                        continue;
                    }
                    lock (ToGetLoadedChunksLOCK)
                    {
                        ToGetLoadedChunks.Add(cd, lod);
                    }


                    //Load the entities for this chunk
                    //TODO - check this doesn't cause issues with entities loading before chunks?

                    //ChunkLoader.LoadChunk(cd);
                }
                else if (toUnload.Contains(pos))
                {
                    //We check if 'toUnload' contains this position (this should always happen if the chunk
                    //isn't already loaded.
                    //We then remove it from this list, as this list will define which chunks need to be unloaded.
                    toUnload.Remove(pos);
                }
                else
                {
                    //If the chunk is loaded, we get it and set its LOD - this ensures it will update if required
                    LoadedChunk2 lc = GetLoadedChunk(pos);
                    lc.SetLOD(lod);
                }
            }
        }
        Debug.BeginDeepProfile("load_chunks1");
    }
예제 #9
0
    /// <summary>
    /// Takes a 'preloadedchunk' and forms a loaded chunk
    /// This must be called from the main thread.
    /// </summary>
    /// <param name="pChunk"></param>
    /// <returns></returns>
    private LoadedChunk2 CreateChunk(PreLoadedChunk pChunk)
    {
        GameObject cObj = pChunk.LoadedChunk.gameObject;

        cObj.transform.parent = transform;

        cObj.name = "chunk_" + pChunk.Position;
        LoadedChunk2 loaded = pChunk.LoadedChunk;

        loaded.SetPreLoadedChunk(pChunk);
        loaded.gameObject.SetActive(true);
        MeshFilter mf = loaded.GetComponent <MeshFilter>();

        //Create the terrain mesh
        mf.mesh = PreLoadedChunk.CreateMesh(pChunk.TerrainMesh);

        /*try
         * {
         *  mf.mesh.RecalculateNormals();
         * }catch(System.Exception e)
         * {
         *  Debug.Log(e);
         * }*/

        if (pChunk.LoadedChunk.LOD == 1)
        {
            MeshCollider mc = loaded.GetComponent <MeshCollider>();
            mc.sharedMesh = mf.mesh;
            mc.enabled    = true;
        }
        else
        {
            MeshCollider mc = loaded.GetComponent <MeshCollider>();
            mc.sharedMesh = null;
            mc.enabled    = false;
        }


        if (loaded.PreLoaded.VoxelMesh != null)
        {
            loaded.SetHasGeneratedVoxels(true);
        }

        if (loaded.LOD < 4 && loaded.HasGeneratedVoxels)
        {
            //loaded.SetHasGeneratedVoxels(true);
            //Iterate all voxels
            foreach (Voxel v in MiscUtils.GetValues <Voxel>())
            {
                if (v == Voxel.none)
                {
                    continue;
                }
                if (pChunk.VoxelMesh.TryGetValue(v, out PreMesh pmesh))
                {
                    GameObject   voxelObj = Instantiate(ChunkVoxelPrefab);
                    MeshFilter   voxelMf  = voxelObj.GetComponent <MeshFilter>();
                    MeshRenderer voxelMr  = voxelObj.GetComponent <MeshRenderer>();
                    voxelMr.material = ResourceManager.GetVoxelMaterial(v);
                    voxelMf.mesh     = PreLoadedChunk.CreateMesh(pmesh);
                    MeshCollider voxelMc = voxelObj.GetComponent <MeshCollider>();
                    voxelMc.sharedMesh               = voxelMf.mesh;
                    voxelObj.transform.parent        = cObj.transform;
                    voxelObj.transform.localPosition = Vector3.zero;

                    // voxelMf.mesh.RecalculateNormals();
                }
            }
        }
        cObj.transform.position = pChunk.Position.AsVector3() * World.ChunkSize;

        if (loaded.LOD < 3 && !loaded.HasLoadedWorldObjects)
        {
            loaded.SetHasLoadedWorldObjects(true);
            //loaded.SetChunk(pChunk.ChunkData);
            lock (ObjectsToLoadLock)
            {
                if (pChunk.ChunkData.WorldObjects != null)
                {
                    ObjectsToLoad.AddRange(pChunk.ChunkData.WorldObjects);
                }
            }
        }



        return(loaded);
    }
예제 #10
0
 public void SetLoadedChunk(LoadedChunk2 lc)
 {
     LoadedChunk = lc;
 }