public VoxelHandle GetContainingVoxel() { return(new VoxelHandle(Manager.World.ChunkManager, GlobalVoxelCoordinate.FromVector3(Position))); }
override public void Render(DwarfTime gameTime, ChunkManager chunks, Camera camera, SpriteBatch spriteBatch, GraphicsDevice graphicsDevice, Shader effect, bool renderingForWater) { base.Render(gameTime, chunks, camera, spriteBatch, graphicsDevice, effect, renderingForWater); if (Debugger.Switches.DrawRailNetwork) { DrawNeighborConnection(TrackAbove); DrawNeighborConnection(TrackBelow); } if (Primitive == null) { Primitive = new RawPrimitive(); var voxel = GetContainingVoxel(); AddSideQuad(voxel, new GlobalVoxelOffset(1, 0, 0), (float)Math.PI * 0.5f, new Vector3(0.45f, 0.0f, 0.0f)); AddSideQuad(voxel, new GlobalVoxelOffset(0, 0, 1), 0.0f, new Vector3(0.0f, 0.0f, 0.45f)); AddSideQuad(voxel, new GlobalVoxelOffset(-1, 0, 0), (float)Math.PI * 0.5f, new Vector3(-0.45f, 0.0f, 0.0f)); AddSideQuad(voxel, new GlobalVoxelOffset(0, 0, -1), 0.0f, new Vector3(0.0f, 0.0f, -0.45f)); } if (Primitive.VertexCount == 0) { return; } var under = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(Position)); if (under.IsValid) { Color color = new Color(under.Sunlight ? 255 : 0, 255, 0); LightRamp = color; } else { LightRamp = new Color(200, 255, 0); } Color origTint = effect.VertexColorTint; if (!Active) { DoStipple(effect); } effect.VertexColorTint = VertexColor; effect.LightRamp = LightRamp; effect.World = GlobalTransform; effect.MainTexture = Sheet.GetTexture(); effect.EnableWind = false; foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); Primitive.Render(graphicsDevice); } effect.VertexColorTint = origTint; if (!Active && !String.IsNullOrEmpty(previousEffect)) { effect.CurrentTechnique = effect.Techniques[previousEffect]; } }
public IEnumerable <VoxelHandle> EnumerateExits() { foreach (var neighborVoxel in VoxelHelpers.EnumerateManhattanNeighbors2D_Y(GlobalVoxelCoordinate.FromVector3(Position))) { var below = neighborVoxel + new GlobalVoxelOffset(0, -1, 0); var neighborHandle = new VoxelHandle(Manager.World.ChunkManager, neighborVoxel); if (neighborHandle.IsValid && neighborHandle.IsEmpty) { var belowHandle = new VoxelHandle(Manager.World.ChunkManager, below); if (belowHandle.IsValid && !belowHandle.IsEmpty) { yield return(neighborHandle); } } } }
public static VoxelChunk GenerateChunk(GlobalChunkCoordinate ID, ChunkGeneratorSettings Settings) { var origin = new GlobalVoxelCoordinate(ID, new LocalVoxelCoordinate(0, 0, 0)); var worldDepth = Settings.WorldSizeInChunks.Y * VoxelConstants.ChunkSizeY; var waterHeight = NormalizeHeight(Settings.Overworld.GenerationSettings.SeaLevel + 1.0f / worldDepth); var c = new VoxelChunk(Settings.World.ChunkManager, ID); for (int x = 0; x < VoxelConstants.ChunkSizeX; x++) { for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++) { var overworldPosition = OverworldMap.WorldToOverworld(new Vector2(x + origin.X, z + origin.Z), Settings.Overworld.InstanceSettings.Origin); var biomeData = Settings.Overworld.Map.GetBiomeAt(new Vector3(x + origin.X, 0, z + origin.Z), Settings.Overworld.InstanceSettings.Origin); var normalizedHeight = NormalizeHeight(Settings.Overworld.Map.LinearInterpolate(overworldPosition, OverworldField.Height)); var height = MathFunctions.Clamp(normalizedHeight * worldDepth, 0.0f, worldDepth - 2); var stoneHeight = (int)MathFunctions.Clamp((int)(height - (biomeData.SoilLayer.Depth + (Math.Sin(overworldPosition.X) + Math.Cos(overworldPosition.Y)))), 1, height); for (int y = 0; y < VoxelConstants.ChunkSizeY; y++) { var globalY = origin.Y + y; var voxel = VoxelHandle.UnsafeCreateLocalHandle(c, new LocalVoxelCoordinate(x, y, z)); if (globalY == 0) { voxel.RawSetType(Library.GetVoxelType("Bedrock")); continue; } // Below the stone line, use subsurface layers. if (globalY <= stoneHeight && stoneHeight > 1) { var depth = stoneHeight - globalY; var subsurfaceLayer = 0; while (depth > 0 && subsurfaceLayer < biomeData.SubsurfaceLayers.Count - 1) { depth -= biomeData.SubsurfaceLayers[subsurfaceLayer].Depth; subsurfaceLayer += 1; } voxel.RawSetType(Library.GetVoxelType(biomeData.SubsurfaceLayers[subsurfaceLayer].VoxelType)); } // Otherwise, on the surface. else if ((globalY == (int)height || globalY == stoneHeight) && normalizedHeight > waterHeight) { voxel.RawSetType(Library.GetVoxelType(biomeData.SoilLayer.VoxelType)); if (!String.IsNullOrEmpty(biomeData.GrassDecal)) { if (!biomeData.ClumpGrass || (biomeData.ClumpGrass && Settings.NoiseGenerator.Noise(overworldPosition.X / biomeData.ClumpSize, 0, overworldPosition.Y / biomeData.ClumpSize) > biomeData.ClumpTreshold)) { voxel.RawSetGrass(Library.GetGrassType(biomeData.GrassDecal).ID); } } } else if (globalY > height && globalY > 0) { voxel.RawSetType(Library.EmptyVoxelType); } else if (normalizedHeight <= waterHeight) { voxel.RawSetType(Library.GetVoxelType(biomeData.ShoreVoxel)); } else { voxel.RawSetType(Library.GetVoxelType(biomeData.SoilLayer.VoxelType)); } } } } return(c); }
public override void Update(DwarfGame game, DwarfTime time) { if (Player.IsCameraRotationModeActive()) { Player.VoxSelector.Enabled = false; Player.World.SetMouse(null); Player.BodySelector.Enabled = false; return; } Player.VoxSelector.Enabled = true; Player.BodySelector.Enabled = false; Player.VoxSelector.DrawBox = false; Player.VoxSelector.DrawVoxel = true; Player.VoxSelector.SelectionType = VoxelSelectionType.SelectEmpty; if (Player.World.IsMouseOverGui) { Player.World.SetMouse(Player.World.MousePointer); } else { Player.World.SetMouse(new Gui.MousePointer("mouse", 1, 4)); } // Don't attempt any camera control if the user is trying to type intoa focus item. if (Player.World.Gui.FocusItem != null && !Player.World.Gui.FocusItem.IsAnyParentTransparent() && !Player.World.Gui.FocusItem.IsAnyParentHidden()) { return; } KeyboardState state = Keyboard.GetState(); bool leftKey = state.IsKeyDown(ControlSettings.Mappings.RotateObjectLeft); bool rightKey = state.IsKeyDown(ControlSettings.Mappings.RotateObjectRight); if (LeftPressed && !leftKey) { if (PathVoxels.Count > 1) { var matched = false; var firstDelta = CompassOrientationHelper.GetVoxelDelta(PathVoxels[0], PathVoxels[1]); var firstConnection = new CompassConnection(OverrideStartingOrientation ? StartingOppositeOrientation : CompassOrientationHelper.Opposite(firstDelta), firstDelta); var orientationDelta = 1; for (; orientationDelta < 8 && !matched; ++orientationDelta) { firstConnection.A = CompassOrientationHelper.Rotate(firstConnection.A, 1); foreach (var piece in RailLibrary.EnumeratePieces().Where(p => p.CompassConnections.Count != 0)) { for (int j = 0; j < 4 && !matched; ++j) { foreach (var compassConnection in piece.CompassConnections) { if (compassConnection.RotateToPiece((PieceOrientation)j) == firstConnection) { matched = true; } } } if (matched) { break; } } } if (matched) { StartingOppositeOrientation = firstConnection.A; } OverrideStartingOrientation = true; } } if (RightPressed && !rightKey) { if (PathVoxels.Count > 1) { var matched = false; var lastDelta = CompassOrientationHelper.GetVoxelDelta(PathVoxels[PathVoxels.Count - 1], PathVoxels[PathVoxels.Count - 2]); var lastConnection = new CompassConnection(lastDelta, OverrideEndingOrientation ? EndingOppositeOrientation : CompassOrientationHelper.Opposite(lastDelta)); var orientationDelta = 1; for (; orientationDelta < 8 && !matched; ++orientationDelta) { lastConnection.B = CompassOrientationHelper.Rotate(lastConnection.B, 1); foreach (var piece in RailLibrary.EnumeratePieces().Where(p => p.CompassConnections.Count != 0)) { for (int j = 0; j < 4 && !matched; ++j) { foreach (var compassConnection in piece.CompassConnections) { if (compassConnection.RotateToPiece((PieceOrientation)j) == lastConnection) { matched = true; } } } if (matched) { break; } } } if (matched) { EndingOppositeOrientation = lastConnection.B; } OverrideEndingOrientation = true; } } LeftPressed = leftKey; RightPressed = rightKey; var tint = Color.White; if (!Dragging) { } else { var voxelUnderMouse = Player.VoxSelector.VoxelUnderMouse; if (voxelUnderMouse == DragStartVoxel) { // Create single straight preview piece } else { var destinationPoint = voxelUnderMouse.Coordinate; // Prevent path finding from attempting slopes - not supported yet. destinationPoint = new GlobalVoxelCoordinate(destinationPoint.X, DragStartVoxel.Coordinate.Y, destinationPoint.Z); var currentVoxel = DragStartVoxel.Coordinate; PathVoxels.Clear(); PathVoxels.Add(currentVoxel); while (true) { var closestDirection = 0; float closestDistance = float.PositiveInfinity; for (var i = 0; i < 8; ++i) { var offsetPos = currentVoxel + CompassOrientationHelper.GetOffset((CompassOrientation)i); var distance = (destinationPoint.ToVector3() - offsetPos.ToVector3()).LengthSquared(); if (distance < closestDistance) { closestDistance = distance; closestDirection = i; } } var nextCoordinate = currentVoxel + CompassOrientationHelper.GetOffset((CompassOrientation)closestDirection); PathVoxels.Add(nextCoordinate); if (PathVoxels.Count >= 100) { break; } if (nextCoordinate == destinationPoint) { break; } currentVoxel = nextCoordinate; } // Iterate PathVoxels, determining deltas and using them to decide which piece to create. var pathCompassConnections = new List <CompassConnection>(); if (PathVoxels.Count > 1) { var firstDelta = CompassOrientationHelper.GetVoxelDelta(PathVoxels[0], PathVoxels[1]); pathCompassConnections.Add(new CompassConnection(OverrideStartingOrientation ? StartingOppositeOrientation : CompassOrientationHelper.Opposite(firstDelta), firstDelta)); for (var i = 1; i < PathVoxels.Count - 1; ++i) { pathCompassConnections.Add(new CompassConnection( CompassOrientationHelper.GetVoxelDelta(PathVoxels[i], PathVoxels[i - 1]), CompassOrientationHelper.GetVoxelDelta(PathVoxels[i], PathVoxels[i + 1]))); } var lastDelta = CompassOrientationHelper.GetVoxelDelta(PathVoxels[PathVoxels.Count - 1], PathVoxels[PathVoxels.Count - 2]); pathCompassConnections.Add(new CompassConnection(lastDelta, OverrideEndingOrientation ? EndingOppositeOrientation : CompassOrientationHelper.Opposite(lastDelta))); } var bodyCounter = 0; var previousPieceAddedTrailingDiagonals = false; for (var i = 0; i < pathCompassConnections.Count; ++i) { var pieceAdded = false; foreach (var piece in RailLibrary.EnumeratePieces().Where(p => p.CompassConnections.Count != 0)) { var matchedOrientation = PieceOrientation.North; CompassConnection matchedConnection = new CompassConnection(); bool matched = false; for (int j = 0; j < 4 && !matched; ++j) { foreach (var compassConnection in piece.CompassConnections) { var rotated = compassConnection.RotateToPiece((PieceOrientation)j); if (rotated == pathCompassConnections[i]) { matched = true; matchedOrientation = (PieceOrientation)j; matchedConnection = pathCompassConnections[i]; break; } } } if (matched) { var newPiece = new JunctionPiece { Offset = new Point(PathVoxels[i].X - DragStartVoxel.Coordinate.X, PathVoxels[i].Z - DragStartVoxel.Coordinate.Z), RailPiece = piece.Name, Orientation = matchedOrientation }; if (PreviewBodies.Count <= bodyCounter) { PreviewBodies.Add(RailHelper.CreatePreviewBody(Player.World.ComponentManager, DragStartVoxel, newPiece)); } else { PreviewBodies[bodyCounter].UpdatePiece(newPiece, DragStartVoxel); } bodyCounter += 1; pieceAdded = true; if (!previousPieceAddedTrailingDiagonals && (matchedConnection.A == CompassOrientation.Northeast || matchedConnection.A == CompassOrientation.Southeast || matchedConnection.A == CompassOrientation.Southwest || matchedConnection.A == CompassOrientation.Northwest)) { bodyCounter = AddDiagonal(bodyCounter, matchedConnection.A, newPiece, 7, 5); bodyCounter = AddDiagonal(bodyCounter, matchedConnection.A, newPiece, 1, 1); } if (matchedConnection.B == CompassOrientation.Northeast || matchedConnection.B == CompassOrientation.Southeast || matchedConnection.B == CompassOrientation.Southwest || matchedConnection.B == CompassOrientation.Northwest) { previousPieceAddedTrailingDiagonals = true; bodyCounter = AddDiagonal(bodyCounter, matchedConnection.B, newPiece, 7, 5); bodyCounter = AddDiagonal(bodyCounter, matchedConnection.B, newPiece, 1, 1); } else { previousPieceAddedTrailingDiagonals = false; } break; } } if (!pieceAdded) { break; } } // Clean up any excess preview entities. var lineSize = bodyCounter; while (bodyCounter < PreviewBodies.Count) { PreviewBodies[bodyCounter].GetRoot().Delete(); bodyCounter += 1; } PreviewBodies = PreviewBodies.Take(lineSize).ToList(); } } CanPlace = RailHelper.CanPlace(Player, PreviewBodies); if (CanPlace) { tint = GameSettings.Default.Colors.GetColor("Positive", Color.Green); } else { tint = GameSettings.Default.Colors.GetColor("Negative", Color.Red); } foreach (var body in PreviewBodies) { body.SetVertexColorRecursive(tint); } }
public static float GetAverageHeight(int X, int Z, int Width, int Height, ChunkGeneratorSettings Settings) { var avgHeight = 0; var numHeight = 0; for (var dx = 0; dx < Width; dx++) { for (var dz = 0; dz < Height; dz++) { var worldPos = new Vector3(X + dx, (Settings.WorldSizeInChunks.Y * VoxelConstants.ChunkSizeY) - 1, Z + dz); var baseVoxel = VoxelHelpers.FindFirstVoxelBelowIncludingWater(Settings.World.ChunkManager.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(worldPos))); if (!baseVoxel.IsValid) { continue; } avgHeight += baseVoxel.Coordinate.Y + 1; numHeight += 1; } } if (numHeight == 0) { return(0); } return(avgHeight / numHeight); }
public static BalloonPortVoxelSets GenerateBalloonPort(ChunkManager chunkManager, float x, float z, int size, ChunkGeneratorSettings Settings) { var centerCoordinate = GlobalVoxelCoordinate.FromVector3(new Vector3(x, (Settings.WorldSizeInChunks.Y * VoxelConstants.ChunkSizeY) - 1, z)); var averageHeight = (int)GetAverageHeight(centerCoordinate.X - size, centerCoordinate.Y - size, size * 2 + 1, size * 2 + 1, Settings); // Next, create the balloon port by deciding which voxels to fill. var balloonPortDesignations = new List <VoxelHandle>(); for (int dx = -size; dx <= size; dx++) { for (int dz = -size; dz <= size; dz++) { var worldPos = new Vector3(centerCoordinate.X + dx, centerCoordinate.Y, centerCoordinate.Z + dz); var baseVoxel = VoxelHelpers.FindFirstVoxelBelow(chunkManager.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(worldPos))); if (!baseVoxel.IsValid) { continue; } var h = baseVoxel.Coordinate.Y + 1; for (int y = averageHeight; y < h && y < chunkManager.World.WorldSizeInVoxels.Y; y++) { var v = chunkManager.CreateVoxelHandle(new GlobalVoxelCoordinate(baseVoxel.Coordinate.X, y, baseVoxel.Coordinate.Z)); v.RawSetType(Library.GetVoxelType(0)); v.RawSetIsExplored(); v.QuickSetLiquid(LiquidType.None, 0); } if (averageHeight < h) { h = averageHeight; } bool isPosX = (dx == size && dz == 0); bool isPosZ = (dz == size & dx == 0); bool isNegX = (dx == -size && dz == 0); bool isNegZ = (dz == -size && dz == 0); bool isSide = (isPosX || isNegX || isPosZ || isNegZ); Vector3 offset = Vector3.Zero; if (isSide) { if (isPosX) { offset = Vector3.UnitX; } else if (isPosZ) { offset = Vector3.UnitZ; } else if (isNegX) { offset = -Vector3.UnitX; } else if (isNegZ) { offset = -Vector3.UnitZ; } } // Fill from the top height down to the bottom. for (int y = Math.Max(0, h - 1); y < averageHeight && y < chunkManager.World.WorldSizeInVoxels.Y; y++) { var v = chunkManager.CreateVoxelHandle(new GlobalVoxelCoordinate(baseVoxel.Coordinate.X, y, baseVoxel.Coordinate.Z)); if (!v.IsValid) { throw new InvalidProgramException("Voxel was invalid while creating a new game's initial zones. This should not happen."); } v.RawSetType(Library.GetVoxelType("Scaffold")); v.IsPlayerBuilt = true; v.QuickSetLiquid(LiquidType.None, 0); v.Sunlight = false; if (y == averageHeight - 1) { v.RawSetIsExplored(); balloonPortDesignations.Add(v); } if (isSide) { var ladderPos = new Vector3(worldPos.X, y, worldPos.Z) + offset + Vector3.One * 0.5f; var ladderVox = chunkManager.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(ladderPos)); if (ladderVox.IsValid && ladderVox.IsEmpty) { var ladder = EntityFactory.CreateEntity <Ladder>("Ladder", ladderPos); Settings.World.PlayerFaction.OwnedObjects.Add(ladder); ladder.Tags.Add("Moveable"); ladder.Tags.Add("Deconstructable"); } } } CastSunlightColumn(baseVoxel.Coordinate.X, baseVoxel.Coordinate.Z, Settings); } } return(new BalloonPortVoxelSets { StockpileVoxels = balloonPortDesignations, }); }
public static void GenerateCaves(VoxelChunk Chunk, ChunkGeneratorSettings Settings) { if (Library.GetBiome("Cave").HasValue(out BiomeData caveBiome) && Library.GetBiome("Hell").HasValue(out BiomeData hellBiome)) { for (int x = 0; x < VoxelConstants.ChunkSizeX; x++) { for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++) { for (int i = 0; i < Settings.CaveLevels.Count; i++) { // Does layer intersect this voxel? int y = Settings.CaveLevels[i]; if (y + Settings.MaxCaveHeight < Chunk.Origin.Y) { continue; } if (y >= Chunk.Origin.Y + VoxelConstants.ChunkSizeY) { continue; } var coordinate = new GlobalVoxelCoordinate(Chunk.Origin.X + x, y, Chunk.Origin.Z + z); var data = GetCaveGenerationData(coordinate, i, Settings); var biome = (y <= Settings.HellLevel) ? hellBiome : caveBiome; if (!data.CaveHere) { continue; } for (int dy = 0; dy < data.Height; dy++) { var globalY = y + dy; // Prevent caves punching holes in bedrock. if (globalY <= 0) { continue; } // Check if voxel is inside chunk. if (globalY <= 0 || globalY < Chunk.Origin.Y || globalY >= Chunk.Origin.Y + VoxelConstants.ChunkSizeY) { continue; } var voxel = VoxelHandle.UnsafeCreateLocalHandle(Chunk, new LocalVoxelCoordinate(x, globalY - Chunk.Origin.Y, z)); // Prevent caves from breaking surface. bool caveBreaksSurface = false; foreach (var neighborCoordinate in VoxelHelpers.EnumerateAllNeighbors(voxel.Coordinate)) { var v = Chunk.Manager.CreateVoxelHandle(neighborCoordinate); if (!v.IsValid || (v.Sunlight)) { caveBreaksSurface = true; break; } } if (caveBreaksSurface) { break; } voxel.RawSetType(Library.EmptyVoxelType); if (dy == 0) { // Place soil voxel and grass below cave. var below = VoxelHelpers.GetVoxelBelow(voxel); if (below.IsValid) { below.RawSetType(Library.GetVoxelType(biome.SoilLayer.VoxelType)); var grassType = Library.GetGrassType(biome.GrassDecal); if (grassType != null) { below.RawSetGrass(grassType.ID); } } // Spawn flora and fauna. if (data.Noise > Settings.CaveSize * 1.8f && globalY > Settings.LavaLevel) { GenerateCaveFlora(below, biome, Settings); GenerateCaveFauna(below, biome, Settings); } } } } } } } }
override public void Render(DwarfTime gameTime, ChunkManager chunks, Camera camera, SpriteBatch spriteBatch, GraphicsDevice graphicsDevice, Shader effect, bool renderingForWater) { base.Render(gameTime, chunks, camera, spriteBatch, graphicsDevice, effect, renderingForWater); if (Debugger.Switches.DrawRailNetwork) { //Drawer3D.DrawBox(GetContainingVoxel().GetBoundingBox(), Color.White, 0.01f, true); //Drawer3D.DrawLine(GetContainingVoxel().GetBoundingBox().Center(), GlobalTransform.Translation, Color.White, 0.01f); var transform = Matrix.CreateRotationY((float)Math.PI * 0.5f * (float)Piece.Orientation) * GlobalTransform; if (Library.GetRailPiece(Piece.RailPiece).HasValue(out var piece)) { foreach (var spline in piece.SplinePoints) { for (var i = 1; i < spline.Count; ++i) { Drawer3D.DrawLine(Vector3.Transform(spline[i - 1], transform), Vector3.Transform(spline[i], transform), Color.Purple, 0.1f); } } foreach (var connection in piece.EnumerateConnections()) { Drawer3D.DrawLine(Vector3.Transform(connection.Item1, transform) + new Vector3(0.0f, 0.2f, 0.0f), Vector3.Transform(connection.Item2, transform) + new Vector3(0.0f, 0.2f, 0.0f), Color.Brown, 0.1f); } //foreach (var neighborConnection in NeighborRails) //{ // var neighbor = Manager.FindComponent(neighborConnection.NeighborID); // if (neighbor == null) // Drawer3D.DrawLine(Position, Position + Vector3.UnitY, Color.CornflowerBlue, 0.1f); // else // Drawer3D.DrawLine(Position + new Vector3(0.0f, 0.5f, 0.0f), (neighbor as Body).Position + new Vector3(0.0f, 0.5f, 0.0f), Color.Teal, 0.1f); //} } } if (!IsVisible) { return; } if (Primitive == null) { var bounds = Vector4.Zero; var uvs = Sheet.GenerateTileUVs(Frame, out bounds); if (Library.GetRailPiece(Piece.RailPiece).HasValue(out var rawPiece)) { var transform = Matrix.CreateRotationY((float)Math.PI * 0.5f * (float)Piece.Orientation); var realShape = 0; if (rawPiece.AutoSlope) { var transformedConnections = GetTransformedConnections(); var matchingNeighbor1 = NeighborRails.FirstOrDefault(n => (n.Position - transformedConnections[0].Item1 - new Vector3(0.0f, 1.0f, 0.0f)).LengthSquared() < 0.001f); var matchingNeighbor2 = NeighborRails.FirstOrDefault(n => (n.Position - transformedConnections[1].Item1 - new Vector3(0.0f, 1.0f, 0.0f)).LengthSquared() < 0.001f); if (matchingNeighbor1 != null && matchingNeighbor2 != null) { realShape = 3; } else if (matchingNeighbor1 != null) { realShape = 1; } else if (matchingNeighbor2 != null) { realShape = 2; } } Primitive = new RawPrimitive(); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(-0.5f, VertexHeightOffsets[realShape, 0], 0.5f), transform), Color.White, Color.White, uvs[0], bounds)); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(0.5f, VertexHeightOffsets[realShape, 1], 0.5f), transform), Color.White, Color.White, uvs[1], bounds)); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(0.5f, VertexHeightOffsets[realShape, 2], -0.5f), transform), Color.White, Color.White, uvs[2], bounds)); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(-0.5f, VertexHeightOffsets[realShape, 3], -0.5f), transform), Color.White, Color.White, uvs[3], bounds)); Primitive.AddIndicies(new short[] { 0, 1, 3, 1, 2, 3 }); var sideBounds = Vector4.Zero; Vector2[] sideUvs = null; sideUvs = Sheet.GenerateTileUVs(new Point(3, 4), out sideBounds); AddScaffoldGeometry(transform, sideBounds, sideUvs, -1.0f, false); if (realShape == 3) { AddScaffoldGeometry(transform, sideBounds, sideUvs, 0.0f, false); } else if (realShape == 1) { sideUvs = Sheet.GenerateTileUVs(new Point(0, 4), out sideBounds); AddScaffoldGeometry(transform, sideBounds, sideUvs, 0.0f, true); } else if (realShape == 2) { sideUvs = Sheet.GenerateTileUVs(new Point(0, 4), out sideBounds); AddScaffoldGeometry(transform, sideBounds, sideUvs, 0.0f, false); } // Todo: Make these static and avoid recalculating them constantly. var bumperBackBounds = Vector4.Zero; var bumperBackUvs = Sheet.GenerateTileUVs(new Point(0, 5), out bumperBackBounds); var bumperFrontBounds = Vector4.Zero; var bumperFrontUvs = Sheet.GenerateTileUVs(new Point(1, 5), out bumperFrontBounds); var bumperSideBounds = Vector4.Zero; var bumperSideUvs = Sheet.GenerateTileUVs(new Point(2, 5), out bumperSideBounds); foreach (var connection in GetTransformedConnections()) { var matchingNeighbor = NeighborRails.FirstOrDefault(n => (n.Position - connection.Item1).LengthSquared() < 0.001f); if (matchingNeighbor == null && rawPiece.AutoSlope) { matchingNeighbor = NeighborRails.FirstOrDefault(n => (n.Position - connection.Item1 - new Vector3(0.0f, 1.0f, 0.0f)).LengthSquared() < 0.001f); } if (matchingNeighbor == null) { var bumperOffset = connection.Item1 - GlobalTransform.Translation; var bumperGap = Vector3.Normalize(bumperOffset) * 0.1f; var bumperAngle = AngleBetweenVectors(new Vector2(bumperOffset.X, bumperOffset.Z), new Vector2(0, 0.5f)); var xDiag = bumperOffset.X <-0.001f || bumperOffset.X> 0.001f; var zDiag = bumperOffset.Z <-0.001f || bumperOffset.Z> 0.001f; if (xDiag && zDiag) { var y = bumperOffset.Y; bumperOffset *= sqrt2; bumperOffset.Y = y; var endBounds = Vector4.Zero; var endUvs = Sheet.GenerateTileUVs(new Point(6, 2), out endBounds); Primitive.AddQuad( Matrix.CreateRotationY((float)Math.PI * 1.25f) * Matrix.CreateRotationY(bumperAngle) // This offset would not be correct if diagonals could slope. * Matrix.CreateTranslation(new Vector3(Sign(bumperOffset.X), 0.0f, Sign(bumperOffset.Z))), Color.White, Color.White, endUvs, endBounds); } Primitive.AddQuad( Matrix.CreateRotationX(-(float)Math.PI * 0.5f) * Matrix.CreateTranslation(0.0f, 0.3f, -0.2f) * Matrix.CreateRotationY(bumperAngle) * Matrix.CreateTranslation(bumperOffset + bumperGap), Color.White, Color.White, bumperBackUvs, bumperBackBounds); Primitive.AddQuad( Matrix.CreateRotationX(-(float)Math.PI * 0.5f) * Matrix.CreateTranslation(0.0f, 0.3f, -0.2f) * Matrix.CreateRotationY(bumperAngle) * Matrix.CreateTranslation(bumperOffset), Color.White, Color.White, bumperFrontUvs, bumperFrontBounds); var firstVoxelBelow = VoxelHelpers.FindFirstVoxelBelow(GetContainingVoxel()); if (firstVoxelBelow.IsValid && firstVoxelBelow.RampType == RampType.None) // if (VoxelHelpers.FindFirstVoxelBelow(GetContainingVoxel()).RampType == RampType.None) { Primitive.AddQuad( Matrix.CreateRotationX(-(float)Math.PI * 0.5f) * Matrix.CreateRotationY(-(float)Math.PI * 0.5f) * Matrix.CreateTranslation(0.3f, 0.3f, 0.18f) * Matrix.CreateRotationY(bumperAngle) * Matrix.CreateTranslation(bumperOffset), Color.White, Color.White, bumperSideUvs, bumperSideBounds); Primitive.AddQuad( Matrix.CreateRotationX(-(float)Math.PI * 0.5f) * Matrix.CreateRotationY(-(float)Math.PI * 0.5f) * Matrix.CreateTranslation(-0.3f, 0.3f, 0.18f) * Matrix.CreateRotationY(bumperAngle) * Matrix.CreateTranslation(bumperOffset), Color.White, Color.White, bumperSideUvs, bumperSideBounds); } } } } } // Everything that draws should set it's tint, making this pointless. var under = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(Position)); if (under.IsValid) { Color color = new Color(under.Sunlight ? 255 : 0, 255, 0); LightRamp = color; } else { LightRamp = new Color(200, 255, 0); } Color origTint = effect.VertexColorTint; if (!Active) { DoStipple(effect); } effect.VertexColorTint = VertexColor; effect.LightRamp = LightRamp; effect.World = GlobalTransform; effect.MainTexture = Sheet.GetTexture(); effect.EnableWind = false; foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); Primitive.Render(graphicsDevice); } effect.VertexColorTint = origTint; if (!Active) { EndDraw(effect); } }
public Microsoft.Xna.Framework.Vector3 GetSpawnLocation(WorldManager world, EntitySpawnLocation SpawnLocation) { Microsoft.Xna.Framework.Vector3 location = location = VoxelHelpers.FindFirstVoxelBelowIncludingWater(new VoxelHandle(world.ChunkManager, GlobalVoxelCoordinate.FromVector3(MonsterSpawner.GetRandomWorldEdge(world)))).WorldPosition + Microsoft.Xna.Framework.Vector3.Up * 1.5f; switch (SpawnLocation) { case EntitySpawnLocation.BalloonPort: { var balloonport = world.EnumerateZones().OfType <BalloonPort>(); if (balloonport.Any()) { location = Datastructures.SelectRandom(balloonport).GetBoundingBox().Center() + Microsoft.Xna.Framework.Vector3.Up * 1.5f; } break; } case EntitySpawnLocation.RandomZone: { var zones = world.EnumerateZones(); if (zones.Any()) { location = Datastructures.SelectRandom(zones).GetBoundingBox().Center() + Microsoft.Xna.Framework.Vector3.Up * 1.5f; } break; } case EntitySpawnLocation.WorldEdge: { // already computed break; } } return(location); }
public static void GenerateRuin(VoxelChunk Chunk, ChunkGeneratorSettings Settings) { var noiseVector = Chunk.Origin.ToVector3() * Settings.CaveNoiseScale; var ruinsNoise = Settings.CaveNoise.GetValue(noiseVector.X, noiseVector.Y, noiseVector.Z); if (Math.Abs(ruinsNoise) > GameSettings.Default.GenerationRuinsRate) { return; } int structureWidth = MathFunctions.RandInt(4, 16); int structureDepth = MathFunctions.RandInt(4, 16); int xOffset = MathFunctions.RandInt(0, VoxelConstants.ChunkSizeX - structureWidth); int zOffset = MathFunctions.RandInt(0, VoxelConstants.ChunkSizeZ - structureDepth); int wallHeight = MathFunctions.RandInt(2, 6); int heightOffset = MathFunctions.RandInt(-4, 2); var biome = Settings.Overworld.Map.GetBiomeAt(Chunk.Origin.ToVector3(), Settings.Overworld.InstanceSettings.Origin); var avgHeight = GetAverageHeight(Chunk.Origin.X, Chunk.Origin.Z, structureWidth, structureDepth, Settings); bool[] doors = new bool[4]; for (int k = 0; k < 4; k++) { doors[k] = MathFunctions.RandEvent(0.5f); } for (int dx = 0; dx < structureWidth; dx++) { for (int dz = 0; dz < structureDepth; dz++) { var worldPos = new Vector3(Chunk.Origin.X + dx + xOffset, avgHeight + heightOffset, Chunk.Origin.Z + dz + zOffset); var baseVoxel = Settings.World.ChunkManager.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(worldPos)); var underVoxel = VoxelHelpers.FindFirstVoxelBelow(Settings.World.ChunkManager.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(worldPos))); var decay = Settings.NoiseGenerator.Generate(worldPos.X * 0.05f, worldPos.Y * 0.05f, worldPos.Z * 0.05f); if (decay > 0.7f) { continue; } if (!baseVoxel.IsValid) { continue; } if (baseVoxel.Coordinate.Y == (Settings.WorldSizeInChunks.Y * VoxelConstants.ChunkSizeY) - 1) { continue; } if (!underVoxel.IsValid) { continue; } var edge = (dx == 0 || dx == structureWidth - 1) || (dz == 0 || dz == structureDepth - 1); if (!edge && !baseVoxel.IsEmpty) { continue; } if (edge) { baseVoxel.RawSetType(Library.GetVoxelType(biome.RuinWallType)); } else { baseVoxel.RawSetType(Library.GetVoxelType(biome.RuinFloorType)); } bool[] wallState = new bool[4]; wallState[0] = dx == 0; wallState[1] = dx == structureWidth - 1; wallState[2] = dz == 0; wallState[3] = dz == structureDepth - 1; bool[] doorState = new bool[4]; doorState[0] = Math.Abs(dz - structureDepth / 2) < 1; doorState[1] = doorState[0]; doorState[2] = Math.Abs(dx - structureWidth / 2) < 1; doorState[3] = doorState[2]; for (int dy = 1; dy < (baseVoxel.Coordinate.Y - underVoxel.Coordinate.Y); dy++) { var currVoxel = Settings.World.ChunkManager.CreateVoxelHandle(underVoxel.Coordinate + new GlobalVoxelOffset(0, dy, 0)); if (!currVoxel.IsValid) { continue; } currVoxel.RawSetType(underVoxel.Type); } underVoxel.RawSetGrass(0); if (edge) { for (int dy = 1; dy < wallHeight * (1.0f - decay) && dy < (Settings.WorldSizeInChunks.Y * VoxelConstants.ChunkSizeY) - 2; dy++) { var currVoxel = Settings.World.ChunkManager.CreateVoxelHandle(baseVoxel.Coordinate + new GlobalVoxelOffset(0, dy, 0)); if (!currVoxel.IsValid) { continue; } if (currVoxel.Coordinate.Y == VoxelConstants.ChunkSizeY - 1) { continue; } bool door = false; for (int k = 0; k < 4; k++) { if (wallState[k] && doors[k] && doorState[k]) { door = true; break; } } if (door && dy < 3) { continue; } currVoxel.RawSetType(Library.GetVoxelType(biome.RuinWallType)); } } } } }
public void OnClicked(int X, int Y) { Viewport viewPort = new Viewport(RenderTarget.Bounds); Vector3 forward = (World.Camera.Target - World.Camera.Position); forward.Normalize(); Vector3 pos = viewPort.Unproject(new Vector3(X, Y, 0), Camera.ProjectionMatrix, Camera.ViewMatrix, Matrix.Identity); Vector3 target = new Vector3(pos.X, World.Camera.Position.Y, pos.Z); var height = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle( World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(target))) .Coordinate.Y + 1; target.Y = Math.Max(height + 15, target.Y); target = MathFunctions.Clamp(target, World.ChunkManager.Bounds); World.Camera.ZoomTargets.Clear(); World.Camera.ZoomTargets.Add(target); }