public void CullMeshes(ref ChunkCoordinate current, ref BoundingFrustum frustum) { BoundingBox box; if (!current.Equals(ref _previous)) { _solidMeshes.Sort((x, y) => x.Position.LengthSquared().CompareTo(y.Position.LengthSquared())); _transparentMeshes.Sort((x, y) => -x.Position.LengthSquared().CompareTo(y.Position.LengthSquared())); } for (int i = 0; i < _solidMeshes.Count; i++) { _solidMeshes[i].GetBoundingBox(out box); if (frustum.Contains(box) != ContainmentType.Disjoint) { _solidMeshRenderQueue.Enqueue(_solidMeshes[i]); } } for (int i = 0; i < _transparentMeshes.Count; i++) { _transparentMeshes[i].GetBoundingBox(out box); if (frustum.Contains(box) != ContainmentType.Disjoint) { _transparentMeshRenderQueue.Enqueue(_transparentMeshes[i]); } } }
public int CompareDistance(ref ChunkCoordinate other, ref ChunkCoordinate origin) { int dist = DistanceSquared(ref origin); int otherdist = other.DistanceSquared(ref origin); return dist.CompareTo(otherdist); }
public bool Contains(ref ChunkCoordinate coords, out Chunk chunk) { int x = coords.X & _dimMask; int z = coords.Z & _dimMask; chunk = Chunks[x, z]; return (chunk != null) ? chunk.Coords.Equals(ref coords) : false; }
public void Add(int x, int z, out ChunkCoordinate coords) { x = X + x; z = Z + z; if (Math.Abs(x) > WrapDistance) x = -x; if (Math.Abs(z) > WrapDistance) z = -z; coords.X = x; coords.Z = z; coords.WrapDistance = WrapDistance; }
public Chunk(ChunkManager manager, ref ChunkCoordinate coords, ref Vector3 initialPosition) { ObjectCount += 1; ObjectNumber = ObjectCount; Position = initialPosition; Coords = coords; _heightMap = new int[WIDTH, WIDTH]; Meshes = new List<ChunkMesh>(); Xstart = coords.X * Chunk.WIDTH; Zstart = coords.Z * Chunk.WIDTH; manager.CubeStorage.WrapCoords(ref Xstart, ref Zstart); ChangedSinceLoad = false; Empty = true; }
public void GetShiftedX(int x, out ChunkCoordinate coords) { int temp = X + x; if (Math.Abs(temp) > WrapDistance) temp = -temp; coords.X = temp; coords.Z = Z; coords.WrapDistance = WrapDistance; }
public bool Equals(ref ChunkCoordinate coords) { return (coords.X == X) && (coords.Z == Z) && (coords.WrapDistance == WrapDistance); }
public int DistanceSquared(ref ChunkCoordinate other) { int x = other.X - X; int z = other.Z - Z; return x * x + z * z; }
public int Distance(ref ChunkCoordinate other) { int x = other.X - X; int z = other.Z - Z; return (int)Math.Sqrt(x * x + z * z); }
public byte Neighbors(ref ChunkCoordinate coord2) { int diffX = coord2.X - X; int diffZ = coord2.Z - Z; if (diffZ == 0 && diffX == 1) return 1; else if (diffZ == 0 && diffX == -1) return 2; else if (diffX == 0 && diffZ == 1) return 4; else if (diffX == 0 && diffZ == -1) return 8; else if (diffX == 1 && diffZ == 1) return 16; else if (diffX == -1 && diffZ == 1) return 32; else if (diffX == 1 && diffZ == -1) return 64; else if (diffX == -1 && diffZ == -1) return 128; else return 0; }
public void GetShiftedZ(int z, out ChunkCoordinate coords) { int temp = Z + z; if (Math.Abs(temp) > WrapDistance) temp = -temp; coords.X = X; coords.Z = temp; coords.WrapDistance = WrapDistance; }
public void Update(float dt, ChunkCoordinate playerPosition, Vector3 deltaPosition) { watch1.Start(); _numToLoad = PER_TICK_CHUNKS_LOAD; _numToLight = PER_TICK_CHUNKS_LIGHT; _numToBuild = PER_TICK_CHUNKS_BUILD; PlayerPosition = playerPosition; //Queue chunks for processing _timeSinceQueue += dt; if (_timeSinceQueue > TIME_BETWEEN_QUEUES) { _timeSinceQueue -= TIME_BETWEEN_QUEUES; watch2.Start(); ManageChunks(); watch2.Stop(); QueueTime = (float)watch2.Elapsed.TotalMilliseconds; } //Rebuild chunk vertices, always done sequentially to ensure that changes are immediately noticed by player. watch2.Reset(); watch2.Start(); RebuildChunkVertices(); watch2.Stop(); RebuildTime = (float)watch2.Elapsed.TotalMilliseconds; //Unload chunks by transferring them back to hard drive with changes and then release to object pool (eventually) if (UnloadQueue.Count > 0 && _running) { _running = false; ThreadPool.UnsafeQueueUserWorkItem(UnloadChunks,false); } //Update all chunks watch2.Reset(); watch2.Start(); ChunkStorage.UpdateChunks(dt, deltaPosition); watch2.Stop(); UpdateTime = (float)watch2.Elapsed.TotalMilliseconds; //Store previous player position PreviousPlayerPosition = PlayerPosition; watch1.Stop(); TotalUpdateTime = (float)watch1.Elapsed.TotalMilliseconds; watch1.Reset(); watch2.Reset(); }
public void Reload() { ChunkStorage.UnloadAll(this); Vector3 positionInChunk = -Vector3.Up * Chunk.HEIGHT * 0.9f; ChunkCoordinate chunkPlayerIsIn = new ChunkCoordinate(0, 0, 8000); Chunk seed = new Chunk(this, ref chunkPlayerIsIn, ref positionInChunk); ChunkStorage.Store(seed, this); _loadQueue.TryAdd(seed); Monitor.Pulse(_loadQueue); }
public ChunkManager(Game game, ChunkCoordinate chunkPlayerIsIn, Vector3 positionInChunk, bool useThreading) { _graphics = game.GraphicsDevice; ChunkRenderer = new ChunkMeshRenderer(game); UseThreading = useThreading; int width = 1; while (width < 2*CHUNK_LOAD_DIST) width *= 2; ChunkStorage = new ChunkStorage(width); //WARN: When load dist is a power of 2 queue chunks infinitely adds delegates to the ChunkStateChange event resulting in an eventual //out of memory exception. CHUNK_LOAD_DIST = width / 2-1; CHUNK_LIGHT_DIST = CHUNK_LOAD_DIST;// -1; CHUNK_BUILD_DIST = CHUNK_LIGHT_DIST;// -1; width *= Chunk.WIDTH; CubeStorage = new CubeStorage(width, Chunk.HEIGHT, width); _loadQueue = new ConcurrentSerialQueue<Chunk>(); _vertexBuffer = new CubeVertex[1000]; LightQueue = new ConcurrentSerialQueue<Chunk>(); BuildQueue = new ConcurrentSerialQueue<Chunk>(); RebuildQueue = new Queue<Chunk>(); UnloadQueue = new ConcurrentSerialQueue<Chunk>(); DrawList = new List<Chunk>(); _timeSinceQueue = TIME_BETWEEN_QUEUES; _timeSinceLoad = TIME_BETWEEN_LOADS; _timeSinceLight = TIME_BETWEEN_LIGHTS * 0.5f; _timeSinceBuild = 0.0f; _running = true; _running = true; _running = true; _running = true; watch1 = new Stopwatch(); watch2 = new Stopwatch(); Thread thread = new Thread(LoadChunks); thread.IsBackground = true; thread.SetApartmentState(ApartmentState.MTA); thread.Name = "LoadThread1"; thread.Priority = ThreadPriority.Lowest; thread.Start(); //thread = new Thread(LoadChunks); //thread.IsBackground = true; //thread.SetApartmentState(ApartmentState.MTA); //thread.Name = "LoadThread2"; //thread.Priority = ThreadPriority.Lowest; //thread.Start(); thread = new Thread(LightChunks); thread.IsBackground = true; thread.SetApartmentState(ApartmentState.MTA); thread.Name = "LightThread"; thread.Priority = ThreadPriority.Lowest; thread.Start(); thread = new Thread(BuildChunkVertices); thread.IsBackground = true; thread.SetApartmentState(ApartmentState.MTA); thread.Name = "BuildThread"; thread.Priority = ThreadPriority.Lowest; thread.Start(); //Initialize chunk loading. positionInChunk = -positionInChunk; Chunk seed = new Chunk(this, ref chunkPlayerIsIn, ref positionInChunk); _loadQueue.TryAdd(seed); ChunkStorage.Store(seed, this); }