private void SetVertices() { var b = _blockStates[_index]; var vertices = b.Model .GetVertices(World , Vector3.Zero, _blockStates[_index].Block); if (vertices.vertices.Length > 0 && vertices.indexes.Length > 0) { var oldBuffer = _buffer; var oldIndexBuffer = _indexBuffer; var newBuffer = GpuResourceManager.GetBuffer(this, Alex.GraphicsDevice, VertexPositionNormalTextureColor.VertexDeclaration, vertices.vertices.Length, BufferUsage.None); var newIndexBuffer = GpuResourceManager.GetIndexBuffer(this, Alex.GraphicsDevice, IndexElementSize.ThirtyTwoBits, vertices.indexes.Length, BufferUsage.None); newBuffer.SetData(vertices.vertices); newIndexBuffer.SetData(vertices.indexes); _buffer = newBuffer; _indexBuffer = newIndexBuffer; oldIndexBuffer?.MarkForDisposal(); oldBuffer?.MarkForDisposal(); GraphicsDevice.Indices = _indexBuffer; GraphicsDevice.SetVertexBuffer(_buffer); _canRender = true; } // _vertices = vertices.vertices; // _indices = vertices.indexes; }
internal bool UpdateChunk(ChunkCoordinates coordinates, IChunkColumn c) { var chunk = c as ChunkColumn; if (!Monitor.TryEnter(chunk.UpdateLock)) { Interlocked.Decrement(ref _chunkUpdates); return(false); //Another thread is already updating this chunk, return. } var scheduleType = chunk.Scheduled; var profiler = MiniProfiler.StartNew("chunk.update"); ChunkData data = null; bool force = !_chunkData.TryGetValue(coordinates, out data); try { //chunk.UpdateChunk(Graphics, World); var currentChunkY = Math.Min(((int)Math.Round(_cameraPosition.Y)) >> 4, (chunk.GetHeighest() >> 4) - 2); if (currentChunkY < 0) { currentChunkY = 0; } List <ChunkMesh> meshes = new List <ChunkMesh>(); using (profiler.Step("chunk.sections")) { for (var i = chunk.Sections.Length - 1; i >= 0; i--) { if (i < 0) { break; } var section = chunk.Sections[i] as ChunkSection; if (section == null || section.IsEmpty()) { continue; } if (i != currentChunkY && i != 0) { using (profiler.Step("chunk.neighboring")) { if (i > 0 && i < chunk.Sections.Length - 1) { var neighbors = chunk.CheckNeighbors(section, i, World).ToArray(); if (!section.HasAirPockets && neighbors.Length == 6) //All surrounded by solid. { // Log.Info($"Found section with solid neigbors, skipping."); continue; } if (i < currentChunkY && neighbors.Length >= 6) { continue; } } else if (i < currentChunkY) { continue; } } } //if (i == 0) force = true; if (force || !section.ScheduledUpdates.IsZero || section.IsDirty) { using (profiler.Step("chunk.meshing")) { var sectionMesh = GenerateSectionMesh(World, scheduleType, new Vector3(chunk.X * 16f, 0, chunk.Z * 16f), ref section, i); meshes.Add(sectionMesh); } } } } List <VertexPositionNormalTextureColor> vertices = new List <VertexPositionNormalTextureColor>(); List <int> transparentIndexes = new List <int>(); List <int> solidIndexes = new List <int>(); List <int> animatedIndexes = new List <int>(); foreach (var mesh in meshes) { var startVerticeIndex = vertices.Count; vertices.AddRange(mesh.Vertices); solidIndexes.AddRange(mesh.SolidIndexes.Select(a => startVerticeIndex + a)); transparentIndexes.AddRange(mesh.TransparentIndexes.Select(a => startVerticeIndex + a)); animatedIndexes.AddRange(mesh.AnimatedIndexes.Select(a => startVerticeIndex + a)); } if (vertices.Count > 0) { ProfilerService.ReportCount("chunk.vertexCount", vertices.Count); using (profiler.Step("chunk.buffer")) { var vertexArray = vertices.ToArray(); var solidArray = solidIndexes.ToArray(); var transparentArray = transparentIndexes.ToArray(); var animatedArray = animatedIndexes.ToArray(); if (data == null) { data = new ChunkData() { Buffer = GpuResourceManager.GetBuffer(this, Graphics, VertexPositionNormalTextureColor.VertexDeclaration, vertexArray.Length, BufferUsage.WriteOnly), SolidIndexBuffer = GpuResourceManager.GetIndexBuffer(this, Graphics, IndexElementSize.ThirtyTwoBits, solidArray.Length, BufferUsage.WriteOnly), TransparentIndexBuffer = GpuResourceManager.GetIndexBuffer(this, Graphics, IndexElementSize.ThirtyTwoBits, transparentArray.Length, BufferUsage.WriteOnly), AnimatedIndexBuffer = GpuResourceManager.GetIndexBuffer(this, Graphics, IndexElementSize.ThirtyTwoBits, animatedArray.Length, BufferUsage.WriteOnly) }; } PooledVertexBuffer oldBuffer = data.Buffer; PooledVertexBuffer newVertexBuffer = null; PooledIndexBuffer newsolidIndexBuffer = null; PooledIndexBuffer newTransparentIndexBuffer = null; PooledIndexBuffer newAnimatedIndexBuffer = null; PooledIndexBuffer oldAnimatedIndexBuffer = data.AnimatedIndexBuffer; PooledIndexBuffer oldSolidIndexBuffer = data.SolidIndexBuffer; PooledIndexBuffer oldTransparentIndexBuffer = data.TransparentIndexBuffer; using (profiler.Step("chunk.buffer.check")) if (vertexArray.Length >= data.Buffer.VertexCount) { // var oldBuffer = data.Buffer; PooledVertexBuffer newBuffer = GpuResourceManager.GetBuffer(this, Graphics, VertexPositionNormalTextureColor.VertexDeclaration, vertexArray.Length, BufferUsage.WriteOnly); newBuffer.SetData(vertexArray); newVertexBuffer = newBuffer; // data.Buffer = newBuffer; // oldBuffer?.Dispose(); ProfilerService.ReportCount("chunk.bufferSize", data.Buffer.MemoryUsage); ProfilerService.TriggerCounter("chunk.bufferResize"); } else { data.Buffer.SetData(vertexArray); ProfilerService.ReportCount("chunk.bufferSize", data.Buffer.MemoryUsage); } using (profiler.Step("Chunk Solid indexbuffer check")) if (solidArray.Length > data.SolidIndexBuffer.IndexCount) { // var old = data.SolidIndexBuffer; var newSolidBuffer = GpuResourceManager.GetIndexBuffer(this, Graphics, IndexElementSize.ThirtyTwoBits, solidArray.Length, BufferUsage.WriteOnly); newSolidBuffer.SetData(solidArray); newsolidIndexBuffer = newSolidBuffer; // data.SolidIndexBuffer = newSolidBuffer; // old?.Dispose(); } else { data.SolidIndexBuffer.SetData(solidArray); } using (profiler.Step("Chunk Transparent indexbuffer check")) if (transparentArray.Length > data.TransparentIndexBuffer.IndexCount) { // var old = data.TransparentIndexBuffer; var newTransparentBuffer = GpuResourceManager.GetIndexBuffer(this, Graphics, IndexElementSize.ThirtyTwoBits, transparentArray.Length, BufferUsage.WriteOnly); newTransparentBuffer.SetData(transparentArray); newTransparentIndexBuffer = newTransparentBuffer; } else { data.TransparentIndexBuffer.SetData(transparentArray); } using (profiler.Step("Chunk Animated indexbuffer check")) if (animatedArray.Length > data.AnimatedIndexBuffer.IndexCount) { // var old = data.TransparentIndexBuffer; var newTransparentBuffer = GpuResourceManager.GetIndexBuffer(this, Graphics, IndexElementSize.ThirtyTwoBits, animatedArray.Length, BufferUsage.WriteOnly); newTransparentBuffer.SetData(animatedArray); newAnimatedIndexBuffer = newTransparentBuffer; } else { data.AnimatedIndexBuffer.SetData(animatedArray); } using (profiler.Step("chunk.buffer.dispose")) { if (newVertexBuffer != null) { data.Buffer = newVertexBuffer; oldBuffer?.MarkForDisposal(); } if (newTransparentIndexBuffer != null) { data.TransparentIndexBuffer = newTransparentIndexBuffer; oldTransparentIndexBuffer?.MarkForDisposal(); } if (newAnimatedIndexBuffer != null) { data.AnimatedIndexBuffer = newAnimatedIndexBuffer; oldAnimatedIndexBuffer?.MarkForDisposal(); } if (newsolidIndexBuffer != null) { data.SolidIndexBuffer = newsolidIndexBuffer; oldSolidIndexBuffer?.MarkForDisposal(); } } } } else { if (data != null) { data.Dispose(); data = null; } } chunk.IsDirty = chunk.HasDirtySubChunks; //false; chunk.Scheduled = ScheduleType.Unscheduled; if (data != null) { data.Coordinates = coordinates; } _chunkData.AddOrUpdate(coordinates, data, (chunkCoordinates, chunkData) => data); return(true); } catch (Exception ex) { Log.Error(ex, $"Exception while updating chunk: {ex.ToString()}"); } finally { //Enqueued.Remove(new ChunkCoordinates(chunk.X, chunk.Z)); Interlocked.Decrement(ref _chunkUpdates); Monitor.Exit(chunk.UpdateLock); profiler.Stop(); // Log.Info(MiniProfiler.Current.RenderPlainText()); } return(false); }
public void Apply(GraphicsDevice device = null, bool keepInMemory = true) { lock (_writeLock) { if (!HasChanges && _previousKeepInMemory) { return; } _previousKeepInMemory = keepInMemory; var realVertices = BuildVertices(); if (realVertices.Length == 0) { _renderableVerticeCount = 0; return; } var verticeCount = realVertices.Length; while (verticeCount % 3 != 0) //Make sure we have a valid triangle list. { verticeCount--; } _renderableVerticeCount = verticeCount; bool callSetData = HasResized; PooledVertexBuffer oldBuffer = null; PooledVertexBuffer buffer = Buffer; if (buffer != null && buffer.VertexCount - realVertices.Length >= 256) { if (GpuResourceManager.TryGetRecycledBuffer( this, device, MinifiedBlockShaderVertex.VertexDeclaration, realVertices.Length, BufferUsage.WriteOnly, out var b)) { oldBuffer = buffer; buffer = b; callSetData = true; } } if (buffer == null || buffer.VertexCount < realVertices.Length) { oldBuffer = buffer; buffer = GpuResourceManager.GetBuffer( this, device, MinifiedBlockShaderVertex.VertexDeclaration, realVertices.Length, BufferUsage.WriteOnly); callSetData = true; } // if (callSetData) buffer.SetData(realVertices, 0, realVertices.Length); Buffer = buffer; oldBuffer?.MarkForDisposal(); HasResized = false; HasChanges = false; } }