public void RegenerateVertexBuffer() { if (!ChunkPosition.HasValue) { return; } // Chunk nachladen if (chunk == null) { chunk = _manager.GetChunk(ChunkPosition.Value); if (chunk == null) { return; } } List <VertexPositionNormalTexture> vertices = new List <VertexPositionNormalTexture>(); List <int> index = new List <int>(); int textureColumns = textures.Width / SceneControl.TEXTURESIZE; float textureWidth = 1f / textureColumns; // BlockTypes sammlen Dictionary <IBlockDefinition, int> textureOffsets = new Dictionary <IBlockDefinition, int>(); // Dictionary<Type, BlockDefinition> definitionMapping = new Dictionary<Type, BlockDefinition>(); int definitionIndex = 0; foreach (var definition in DefinitionManager.GetBlockDefinitions()) { int textureCount = definition.Textures.Count(); textureOffsets.Add(definition, definitionIndex); // definitionMapping.Add(definition.GetBlockType(), definition); definitionIndex += textureCount; } for (int z = 0; z < Chunk.CHUNKSIZE_Z; z++) { for (int y = 0; y < Chunk.CHUNKSIZE_Y; y++) { for (int x = 0; x < Chunk.CHUNKSIZE_X; x++) { ushort block = chunk.GetBlock(x, y, z); if (block == 0) { continue; } IBlockDefinition blockDefinition = DefinitionManager.GetBlockDefinitionByIndex(block); if (blockDefinition == null) { continue; } int textureIndex; if (!textureOffsets.TryGetValue(blockDefinition, out textureIndex)) { continue; } // Textur-Koordinate "berechnen" Vector2 textureOffset = new Vector2(); Vector2 textureSize = new Vector2(textureWidth - 0.005f, textureWidth - 0.005f); ushort topBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x, y, z + 1)); IBlockDefinition topBlockDefintion = DefinitionManager.GetBlockDefinitionByIndex(topBlock); // Top if (topBlock == 0 || (!topBlockDefintion.IsBottomSolidWall(_manager, x, y, z + 1) && topBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetTopTextureIndex(_manager, x, y, z)) % textureColumns) * textureWidth) + 0.002f, (((textureIndex + blockDefinition.GetTopTextureIndex(_manager, x, y, z)) / textureColumns) * textureWidth) + 0.002f); Vector2[] points = new[] { textureOffset, new Vector2(textureOffset.X + textureSize.X, textureOffset.Y), textureOffset + textureSize, new Vector2(textureOffset.X, textureOffset.Y + textureSize.X) }; int rotation = -blockDefinition.GetTopTextureRotation(_manager, x, y, z); int localOffset = vertices.Count; vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 1, z + 1), new Vector3(0, 0, 1), points[(4 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 1, z + 1), new Vector3(0, 0, 1), points[(5 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 0, z + 1), new Vector3(0, 0, 1), points[(7 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 0, z + 1), new Vector3(0, 0, 1), points[(6 + rotation) % 4])); index.Add(localOffset + 0); index.Add(localOffset + 1); index.Add(localOffset + 3); index.Add(localOffset + 0); index.Add(localOffset + 3); index.Add(localOffset + 2); } ushort bottomBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x, y, z - 1)); IBlockDefinition bottomBlockDefintion = DefinitionManager.GetBlockDefinitionByIndex(bottomBlock); // Unten if (bottomBlock == 0 || (!bottomBlockDefintion.IsTopSolidWall(_manager, x, y, z - 1) && bottomBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetBottomTextureIndex(_manager, x, y, z)) % textureColumns) * textureWidth) + 0.002f, (((textureIndex + blockDefinition.GetBottomTextureIndex(_manager, x, y, z)) / textureColumns) * textureWidth) + 0.002f); Vector2[] points = new[] { textureOffset, new Vector2(textureOffset.X + textureSize.X, textureOffset.Y), textureOffset + textureSize, new Vector2(textureOffset.X, textureOffset.Y + textureSize.X) }; int rotation = -blockDefinition.GetBottomTextureRotation(_manager, x, y, z); int localOffset = vertices.Count; vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 1, z + 0), new Vector3(0, 0, -1), points[(6 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 1, z + 0), new Vector3(0, 0, -1), points[(7 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 0, z + 0), new Vector3(0, 0, -1), points[(5 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 0, z + 0), new Vector3(0, 0, -1), points[(4 + rotation) % 4])); index.Add(localOffset + 0); index.Add(localOffset + 1); index.Add(localOffset + 3); index.Add(localOffset + 0); index.Add(localOffset + 3); index.Add(localOffset + 2); } ushort southBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x, y + 1, z)); IBlockDefinition southBlockDefintion = DefinitionManager.GetBlockDefinitionByIndex(southBlock); // South if (southBlock == 0 || (!southBlockDefintion.IsNorthSolidWall(_manager, x, y + 1, z) && southBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetSouthTextureIndex(_manager, x, y, z)) % textureColumns) * textureWidth) + 0.002f, (((textureIndex + blockDefinition.GetSouthTextureIndex(_manager, x, y, z)) / textureColumns) * textureWidth) + 0.002f); Vector2[] points = new[] { textureOffset, new Vector2(textureOffset.X + textureSize.X, textureOffset.Y), textureOffset + textureSize, new Vector2(textureOffset.X, textureOffset.Y + textureSize.X) }; int rotation = -blockDefinition.GetSouthTextureRotation(_manager, x, y, z); int localOffset = vertices.Count; vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 1, z + 0), new Vector3(0, 1, 0), points[(6 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 1, z + 0), new Vector3(0, 1, 0), points[(7 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 1, z + 1), new Vector3(0, 1, 0), points[(5 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 1, z + 1), new Vector3(0, 1, 0), points[(4 + rotation) % 4])); index.Add(localOffset + 0); index.Add(localOffset + 1); index.Add(localOffset + 3); index.Add(localOffset + 0); index.Add(localOffset + 3); index.Add(localOffset + 2); } ushort northBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x, y - 1, z)); IBlockDefinition northBlockDefintion = DefinitionManager.GetBlockDefinitionByIndex(northBlock); // North if (northBlock == 0 || (!northBlockDefintion.IsSouthSolidWall(_manager, x, y - 1, z) && northBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetNorthTextureIndex(_manager, x, y, z)) % textureColumns) * textureWidth) + 0.002f, (((textureIndex + blockDefinition.GetNorthTextureIndex(_manager, x, y, z)) / textureColumns) * textureWidth) + 0.002f); Vector2[] points = new[] { textureOffset, new Vector2(textureOffset.X + textureSize.X, textureOffset.Y), textureOffset + textureSize, new Vector2(textureOffset.X, textureOffset.Y + textureSize.X) }; int rotation = -blockDefinition.GetNorthTextureRotation(_manager, x, y, z); int localOffset = vertices.Count; vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 0, z + 1), new Vector3(0, -1, 0), points[(4 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 0, z + 1), new Vector3(0, -1, 0), points[(5 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 0, z + 0), new Vector3(0, -1, 0), points[(7 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 0, z + 0), new Vector3(0, -1, 0), points[(6 + rotation) % 4])); index.Add(localOffset + 0); index.Add(localOffset + 1); index.Add(localOffset + 3); index.Add(localOffset + 0); index.Add(localOffset + 3); index.Add(localOffset + 2); } ushort westBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x - 1, y, z)); IBlockDefinition westBlockDefintion = DefinitionManager.GetBlockDefinitionByIndex(westBlock); // West if (westBlock == 0 || (!westBlockDefintion.IsEastSolidWall(_manager, x - 1, y, z) && westBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetWestTextureIndex(_manager, x, y, z)) % textureColumns) * textureWidth) + 0.002f, (((textureIndex + blockDefinition.GetWestTextureIndex(_manager, x, y, z)) / textureColumns) * textureWidth) + 0.002f); Vector2[] points = new[] { textureOffset, new Vector2(textureOffset.X + textureSize.X, textureOffset.Y), textureOffset + textureSize, new Vector2(textureOffset.X, textureOffset.Y + textureSize.X) }; int rotation = -blockDefinition.GetWestTextureRotation(_manager, x, y, z); int localOffset = vertices.Count; vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 1, z + 0), new Vector3(-1, 0, 0), points[(7 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 1, z + 1), new Vector3(-1, 0, 0), points[(4 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 0, z + 0), new Vector3(-1, 0, 0), points[(6 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 0, y + 0, z + 1), new Vector3(-1, 0, 0), points[(5 + rotation) % 4])); index.Add(localOffset + 0); index.Add(localOffset + 1); index.Add(localOffset + 3); index.Add(localOffset + 0); index.Add(localOffset + 3); index.Add(localOffset + 2); } ushort eastBlock = _manager.GetBlock((ChunkPosition.Value * Chunk.CHUNKSIZE) + new Index3(x + 1, y, z)); IBlockDefinition eastBlockDefintion = DefinitionManager.GetBlockDefinitionByIndex(eastBlock); // Ost if (eastBlock == 0 || (!eastBlockDefintion.IsWestSolidWall(_manager, x + 1, y, z) && eastBlock != block)) { textureOffset = new Vector2( (((textureIndex + blockDefinition.GetEastTextureIndex(_manager, x, y, z)) % textureColumns) * textureWidth) + 0.002f, (((textureIndex + blockDefinition.GetEastTextureIndex(_manager, x, y, z)) / textureColumns) * textureWidth) + 0.002f); Vector2[] points = new[] { textureOffset, new Vector2(textureOffset.X + textureSize.X, textureOffset.Y), textureOffset + textureSize, new Vector2(textureOffset.X, textureOffset.Y + textureSize.X) }; int rotation = -blockDefinition.GetEastTextureRotation(_manager, x, y, z); int localOffset = vertices.Count; vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 1, z + 1), new Vector3(1, 0, 0), points[(5 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 1, z + 0), new Vector3(1, 0, 0), points[(6 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 0, z + 1), new Vector3(1, 0, 0), points[(4 + rotation) % 4])); vertices.Add(new VertexPositionNormalTexture(new Vector3(x + 1, y + 0, z + 0), new Vector3(1, 0, 0), points[(7 + rotation) % 4])); index.Add(localOffset + 0); index.Add(localOffset + 1); index.Add(localOffset + 3); index.Add(localOffset + 0); index.Add(localOffset + 3); index.Add(localOffset + 2); } } } } vertexCount = vertices.Count; indexCount = index.Count; VertexBuffer vb2 = null; IndexBuffer ib2 = null; if (vertexCount > 0) { try { vb2 = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, vertexCount, BufferUsage.WriteOnly); vb2.SetData <VertexPositionNormalTexture>(vertices.ToArray()); ib2 = new IndexBuffer(graphicsDevice, IndexElementSize.ThirtyTwoBits, indexCount, BufferUsage.WriteOnly); ib2.SetData <int>(index.ToArray()); } catch (Exception) { } } VertexBuffer vbOld = vb; IndexBuffer ibOld = ib; lock (this) { vb = vb2; ib = ib2; loaded = true; } if (vbOld != null) { vbOld.Dispose(); } if (ibOld != null) { ibOld.Dispose(); } lastReset = chunk.ChangeCounter; }
protected override void OnUpdate(GameTime gameTime) { sunPosition += (float)gameTime.ElapsedGameTime.TotalMinutes * MathHelper.TwoPi; Index3 centerblock = player.ActorHost.Position.GlobalBlockIndex; Index3 renderOffset = player.ActorHost.Position.ChunkIndex * Chunk.CHUNKSIZE; Index3? selected = null; Axis? selectedAxis = null; Vector3?selectionPoint = null; float bestDistance = 9999; for (int z = -Player.SELECTIONRANGE; z < Player.SELECTIONRANGE; z++) { for (int y = -Player.SELECTIONRANGE; y < Player.SELECTIONRANGE; y++) { for (int x = -Player.SELECTIONRANGE; x < Player.SELECTIONRANGE; x++) { Index3 range = new Index3(x, y, z); Index3 pos = range + centerblock; ushort block = _manager.GetBlock(pos); if (block == 0) { continue; } IBlockDefinition blockDefinition = DefinitionManager.GetBlockDefinitionByIndex(block); Axis? collisionAxis; float?distance = Block.Intersect(blockDefinition.GetCollisionBoxes(_manager, pos.X, pos.Y, pos.Z), pos - renderOffset, camera.PickRay, out collisionAxis); if (distance.HasValue && distance.Value < bestDistance) { pos.NormalizeXY(planet.Size * Chunk.CHUNKSIZE); selected = pos; selectedAxis = collisionAxis; bestDistance = distance.Value; selectionPoint = (camera.PickRay.Position + (camera.PickRay.Direction * distance)) - (selected - renderOffset); } } } } if (selected.HasValue) { player.SelectedBox = selected; switch (selectedAxis) { case Axis.X: player.SelectedSide = (camera.PickRay.Direction.X > 0 ? OrientationFlags.SideWest : OrientationFlags.SideEast); break; case Axis.Y: player.SelectedSide = (camera.PickRay.Direction.Y > 0 ? OrientationFlags.SideSouth : OrientationFlags.SideNorth); break; case Axis.Z: player.SelectedSide = (camera.PickRay.Direction.Z > 0 ? OrientationFlags.SideBottom : OrientationFlags.SideTop); break; } player.SelectedPoint = new Vector2(); switch (player.SelectedSide) { case OrientationFlags.SideWest: player.SelectedPoint = new Vector2(1f - selectionPoint.Value.Y, 1f - selectionPoint.Value.Z); player.SelectedCorner = FindCorner(player.SelectedPoint.Value, OrientationFlags.Corner011, OrientationFlags.Corner001, OrientationFlags.Corner010, OrientationFlags.Corner000); player.SelectedEdge = FindEdge(player.SelectedPoint.Value, OrientationFlags.EdgeWestTop, OrientationFlags.EdgeWestBottom, OrientationFlags.EdgeNorthWest, OrientationFlags.EdgeSouthWest); break; case OrientationFlags.SideEast: player.SelectedPoint = new Vector2(selectionPoint.Value.Y, 1f - selectionPoint.Value.Z); player.SelectedCorner = FindCorner(player.SelectedPoint.Value, OrientationFlags.Corner101, OrientationFlags.Corner111, OrientationFlags.Corner100, OrientationFlags.Corner110); player.SelectedEdge = FindEdge(player.SelectedPoint.Value, OrientationFlags.EdgeEastTop, OrientationFlags.EdgeEastBottom, OrientationFlags.EdgeSouthEast, OrientationFlags.EdgeNorthEast); break; case OrientationFlags.SideTop: player.SelectedPoint = new Vector2(selectionPoint.Value.X, 1f - selectionPoint.Value.Y); player.SelectedCorner = FindCorner(player.SelectedPoint.Value, OrientationFlags.Corner011, OrientationFlags.Corner111, OrientationFlags.Corner001, OrientationFlags.Corner101); player.SelectedEdge = FindEdge(player.SelectedPoint.Value, OrientationFlags.EdgeNorthTop, OrientationFlags.EdgeSouthTop, OrientationFlags.EdgeWestTop, OrientationFlags.EdgeEastTop); break; case OrientationFlags.SideBottom: player.SelectedPoint = new Vector2(selectionPoint.Value.X, selectionPoint.Value.Y); player.SelectedCorner = FindCorner(player.SelectedPoint.Value, OrientationFlags.Corner000, OrientationFlags.Corner100, OrientationFlags.Corner010, OrientationFlags.Corner110); player.SelectedEdge = FindEdge(player.SelectedPoint.Value, OrientationFlags.EdgeSouthBottom, OrientationFlags.EdgeNorthBottom, OrientationFlags.EdgeWestBottom, OrientationFlags.EdgeEastBottom); break; case OrientationFlags.SideNorth: player.SelectedPoint = new Vector2(1f - selectionPoint.Value.X, 1f - selectionPoint.Value.Z); player.SelectedCorner = FindCorner(player.SelectedPoint.Value, OrientationFlags.Corner111, OrientationFlags.Corner011, OrientationFlags.Corner110, OrientationFlags.Corner010); player.SelectedEdge = FindEdge(player.SelectedPoint.Value, OrientationFlags.EdgeNorthTop, OrientationFlags.EdgeNorthBottom, OrientationFlags.EdgeNorthEast, OrientationFlags.EdgeNorthWest); break; case OrientationFlags.SideSouth: player.SelectedPoint = new Vector2(selectionPoint.Value.X, 1f - selectionPoint.Value.Z); player.SelectedCorner = FindCorner(player.SelectedPoint.Value, OrientationFlags.Corner001, OrientationFlags.Corner101, OrientationFlags.Corner000, OrientationFlags.Corner100); player.SelectedEdge = FindEdge(player.SelectedPoint.Value, OrientationFlags.EdgeSouthTop, OrientationFlags.EdgeSouthBottom, OrientationFlags.EdgeSouthWest, OrientationFlags.EdgeSouthEast); break; } player.SelectedPoint = new Vector2( Math.Min(1f, Math.Max(0f, player.SelectedPoint.Value.X)), Math.Min(1f, Math.Max(0f, player.SelectedPoint.Value.Y))); } else { player.SelectedBox = null; player.SelectedPoint = null; player.SelectedSide = OrientationFlags.None; player.SelectedEdge = OrientationFlags.None; player.SelectedCorner = OrientationFlags.None; } base.OnUpdate(gameTime); }