예제 #1
0
 void ReleaseNode(TerrainChunk chunk)
 {
     if (chunk != null)
     {
         chunk.DestroyChunk();
     }
 }
예제 #2
0
        //	Load terrain chunk data from file, this function is called from loading thread
        void StreamInNodeData_t(TerrainChunk chunk)
        {
            try
            {
                if (chunk.cancelLoading)
                {
                    return;
                }

                int index  = chunk.row * chunkInRow + chunk.col;
                int offset = dataOffset + nodeDataSize * index;

                file.Seek(offset, SeekOrigin.Begin);
                using (BinaryReader br = new BinaryReader(file, Encoding.UTF8, true))
                {
                    br.Read(dataBuffer, 0, nodeDataSize);
                    Buffer.BlockCopy(dataBuffer, 0, vertBuffer, 0, nodeDataSize);
                }

                int vertNum = (chunkGrid + 1) * (chunkGrid + 1);
                chunk.FillData(vertBuffer, vertNum, chunkGrid);
            }
            catch
            {
                Debug.Log("TestTerrain.CreateNode failed!");
            }
        }
예제 #3
0
        //	add a loading request for specified chunk
        void AddLoadingRequest(TerrainChunk chunk)
        {
            chunk.inLoadingList = true;

            lock (loadingRequestList)
            {
#if DEBUG
                if (loadingRequestList.FindIndex(n => n == chunk) >= 0)
                {
                    Debug.Log("TestTerrain.AddLoadingRequest, loading request already exist.");
                }
#endif
                loadingRequestList.Add(chunk);
                autoLoadingEvents[(int)eLoadingEventsID.TO_LOAD].Set();
            }
        }
예제 #4
0
        //	update terrain chunks
        void UpdateTerrainNodes(Vector3 centerPos)
        {
            if (file == null)
            {
                return;
            }

            //	two cache take turns storing terrain chunks
            List <TerrainChunk> cache     = nodeCaches[curCache];
            List <TerrainChunk> tempCache = nodeCaches[curCache ^ 1];

            float sx           = -(widthInGrids / 2) * gridSize;
            float sz           = -sx;
            float nodeSize     = chunkGrid * gridSize;
            float halfNodeSize = nodeSize * 0.5f;

            int nodeInView = (int)(viewDistance / nodeSize) + 1;
            int loadFlag   = 0;             //	0: remain; 1: load; 2: unload

            //	Lambda function used to move chunk between two caches
            Action <int, int> MoveNodeInCache = (int r, int c) =>
            {
                int index    = nodeCacheIndices[r, c];
                int newIndex = tempCache.Count;
                tempCache.Add(cache[index]);
                nodeCacheIndices[r, c] = newIndex;
            };

            //	traverse all nodes to see which should be streamed in and which should be streamed out.
            for (int r = 0; r < chunkInRow; r++)
            {
                float nz = sz - nodeSize * r;
                float nx = sx;

                for (int c = 0; c < chunkInRow; c++)
                {
                    loadFlag = 0;

                    float deltaX = Mathf.Abs(centerPos.x - (nx + halfNodeSize));
                    float deltaZ = Mathf.Abs(centerPos.z - (nz - halfNodeSize));

                    //	check if chunk is in view distance. we give a larger checking distance for unloading
                    //	terrain chunks than for loading them, this can prevent chunks from being loaded/unloaded
                    //	frequently when camera hovering around a point.
                    if (deltaX - halfNodeSize < viewDistance && deltaZ - halfNodeSize < viewDistance)
                    {
                        //	chunk is in view distance
                        loadFlag = 1;
                    }
                    else if (deltaX > viewDistance + halfNodeSize || deltaZ > viewDistance + halfNodeSize)
                    {
                        //	chunk is out of view distance
                        loadFlag = 2;
                    }

                    if (loadFlag == 0)
                    {
                        //	remain current state.
                        //	if chunk has been created, just move it into the other cache
                        if (nodeCacheIndices[r, c] >= 0)
                        {
                            MoveNodeInCache(r, c);
                        }
                    }
                    else if (loadFlag == 1)
                    {
                        //	the chunk needs to be loaded
                        if (nodeCacheIndices[r, c] >= 0)
                        {
                            //	chunk has been loaded, just move it into the other cache
                            MoveNodeInCache(r, c);
                        }
                        else
                        {
                            //	create an empty chunk to hold a place in cache
                            TerrainChunk chunk    = new TerrainChunk(r, c);
                            int          newIndex = tempCache.Count;
                            tempCache.Add(chunk);
                            nodeCacheIndices[r, c] = newIndex;

                            //	send out a loading request for the chunk
                            AddLoadingRequest(chunk);
                        }
                    }
                    else if (loadFlag == 2)
                    {
                        //	the chunk needs to be unloaded
                        if (nodeCacheIndices[r, c] >= 0)
                        {
                            int          index = nodeCacheIndices[r, c];
                            TerrainChunk chunk = cache[index];

                            if (chunk.inLoadingList)
                            {
                                //	the chunk has been put into loading list, so we just set its cancelLoading flag
                                //	instead of destroying it by calling ReleaseNode() immediately, for loading thread
                                //	may be loading data for it right now. In this way, the chunk's destruction is postponed
                                //	to GenerateNodeObjects() after its data has been loaded.
                                chunk.cancelLoading = true;
                            }
                            else
                            {
                                //	this chunk has finished loading, so it can be released safely.
                                ReleaseNode(chunk);
                            }

                            nodeCacheIndices[r, c] = -1;
                        }
                    }

                    nx += nodeSize;
                }
            }

            //	Clear current cache
            cache.Clear();
            //	exchange cache
            curCache ^= 1;
        }