public void UpdatePiece(JunctionPiece Piece, VoxelHandle Location) { DetachFromNeighbors(); this.Piece = Piece; this.Location = Location; LocalTransform = Matrix.CreateTranslation(Location.WorldPosition + new Vector3(Piece.Offset.X, 0, Piece.Offset.Y) + new Vector3(0.5f, 0.2f, 0.5f)); var piece = RailLibrary.GetRailPiece(Piece.RailPiece); Frame = piece.Tile; ResetPrimitive(); // Hack to make the listener update it's damn bounding box var deathTrigger = EnumerateChildren().OfType <GenericVoxelListener>().FirstOrDefault(); if (deathTrigger != null) { deathTrigger.LocalTransform = Matrix.Identity; } AttachToNeighbors(); PropogateTransforms(); }
public List <Tuple <Vector3, Vector3> > GetTransformedConnections() { var piece = RailLibrary.GetRailPiece(Piece.RailPiece); var transform = Matrix.CreateRotationY((float)Math.PI * 0.5f * (float)Piece.Orientation) * GlobalTransform; return(piece.EnumerateConnections().Select(l => Tuple.Create(Vector3.Transform(l.Item1, transform), Vector3.Transform(l.Item2, transform))).ToList()); }
public override void CreateCosmeticChildren(ComponentManager manager) { base.CreateCosmeticChildren(manager); var piece = RailLibrary.GetRailPiece(Piece.RailPiece); Sheet = new SpriteSheet(ContentPaths.rail_tiles, 32, 32); AddChild(new GenericVoxelListener(manager, Matrix.Identity, new Vector3(0.8f, 1.5f, 0.8f), Vector3.Zero, (_event) => { if (!Active) { return; } if (_event.Type == VoxelChangeEventType.VoxelTypeChanged && _event.NewVoxelType == 0) { Die(); var designation = World.PlayerFaction.Designations.EnumerateEntityDesignations(DesignationType.Craft).FirstOrDefault(d => Object.ReferenceEquals(d.Body, this)); if (designation != null) { World.PlayerFaction.Designations.RemoveEntityDesignation(this, DesignationType.Craft); var craftDesignation = designation.Tag as CraftDesignation; if (craftDesignation.WorkPile != null) { craftDesignation.WorkPile.Die(); } } } })).SetFlag(Flag.ShouldSerialize, false); UpdatePiece(Piece, Location); }
public static IEnumerable <uint> EnumerateForwardNetworkConnections(RailEntity Leaving, RailEntity Entering) { if (Leaving == null) { foreach (var neighbor in Entering.NeighborRails) { yield return(neighbor.NeighborID); } yield break; } var connectionPoint = FindConnectionPoint(Leaving, Entering); if (connectionPoint != null) { var transformToEntitySpace = Matrix.CreateRotationY((float)Math.PI * 0.5f * (float)Entering.GetPiece().Orientation) * Entering.GlobalTransform; var backConnection = FindConnectionPoint(Entering, Leaving); var connection = FindConnectionFromTransformedEntrancePoint(RailLibrary.GetRailPiece(Entering.GetPiece().RailPiece), transformToEntitySpace, backConnection.Raised ? (connectionPoint.Position - Vector3.UnitY) : connectionPoint.Position); if (connection != null) { foreach (var exit in connection.Exits) { var transformedExit = Vector3.Transform(exit, transformToEntitySpace); foreach (var neighbor in Entering.NeighborRails) { if (neighbor.Raised) { transformedExit += Vector3.UnitY; } if ((neighbor.Position - transformedExit).LengthSquared() < 0.01f) { yield return(neighbor.NeighborID); } } } } } }
private void AddScaffoldGeometry(Matrix transform, Vector4 sideBounds, Vector2[] sideUvs, float HeightOffset, bool FlipTexture) { var uvDelta = sideUvs[1].X - sideUvs[0].X; foreach (var railSpline in RailLibrary.GetRailPiece(Piece.RailPiece).RailSplines) { var uvStep = 1.0f / (railSpline.Count - 1); for (var i = 1; i < railSpline.Count; ++i) { var baseIndex = Primitive.VertexCount; Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(railSpline[i - 1].X, HeightOffset + 1.0f, railSpline[i - 1].Y), transform), Color.White, Color.White, FlipTexture ? new Vector2(sideUvs[0].X + uvDelta - uvDelta * (uvStep * (i - 1)), sideUvs[0].Y) : new Vector2(sideUvs[0].X + uvDelta * (uvStep * (i - 1)), sideUvs[0].Y), sideBounds)); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(railSpline[i].X, HeightOffset + 1.0f, railSpline[i].Y), transform), Color.White, Color.White, FlipTexture ? new Vector2(sideUvs[0].X + uvDelta - uvDelta * (uvStep * i), sideUvs[0].Y) : new Vector2(sideUvs[0].X + uvDelta * (uvStep * i), sideUvs[0].Y), sideBounds)); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(railSpline[i].X, HeightOffset, railSpline[i].Y), transform), Color.White, Color.White, FlipTexture ? new Vector2(sideUvs[0].X + uvDelta - uvDelta * (uvStep * i), sideUvs[2].Y) : new Vector2(sideUvs[0].X + uvDelta * (uvStep * i), sideUvs[2].Y), sideBounds)); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(railSpline[i - 1].X, HeightOffset, railSpline[i - 1].Y), transform), Color.White, Color.White, FlipTexture ? new Vector2(sideUvs[0].X + uvDelta - uvDelta * (uvStep * (i - 1)), sideUvs[2].Y) : new Vector2(sideUvs[0].X + uvDelta * (uvStep * (i - 1)), sideUvs[2].Y), sideBounds)); Primitive.AddOffsetIndicies(new short[] { 0, 1, 3, 1, 2, 3 }, baseIndex); } } }
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 Texture2D RenderPatternIcons(GraphicsDevice device, Microsoft.Xna.Framework.Content.ContentManager Content, Gui.JsonTileSheet Sheet) { Initialize(); var shader = new Shader(Content.Load <Effect>(ContentPaths.Shaders.TexturedShaders), true); var sqrt = (int)(Math.Ceiling(Math.Sqrt(Patterns.Count))); var width = MathFunctions.NearestPowerOf2(sqrt * Sheet.TileWidth); var fitHorizontal = width / Sheet.TileWidth; var rowCount = (int)Math.Ceiling((float)Patterns.Count / (float)fitHorizontal); var height = MathFunctions.NearestPowerOf2(rowCount * Sheet.TileHeight); RenderTarget2D toReturn = new RenderTarget2D(device, width, height, false, SurfaceFormat.Color, DepthFormat.Depth16, 16, RenderTargetUsage.PreserveContents); var tileSheet = new SpriteSheet(ContentPaths.rail_tiles, 32); device.SetRenderTarget(toReturn); device.Clear(Color.Transparent); shader.SetTexturedTechnique(); shader.MainTexture = AssetManager.GetContentTexture(ContentPaths.rail_tiles); shader.SelfIlluminationEnabled = true; shader.SelfIlluminationTexture = AssetManager.GetContentTexture(ContentPaths.Terrain.terrain_illumination); shader.EnableShadows = false; shader.EnableLighting = false; shader.ClippingEnabled = false; shader.CameraPosition = new Vector3(-0.5f, 0.5f, 0.5f); shader.VertexColorTint = Color.White; shader.LightRamp = Color.White; shader.SunlightGradient = AssetManager.GetContentTexture(ContentPaths.Gradients.sungradient); shader.AmbientOcclusionGradient = AssetManager.GetContentTexture(ContentPaths.Gradients.ambientgradient); shader.TorchlightGradient = AssetManager.GetContentTexture(ContentPaths.Gradients.torchgradient); Viewport oldview = device.Viewport; int rows = height / Sheet.TileWidth; int cols = width / Sheet.TileWidth; device.ScissorRectangle = new Rectangle(0, 0, Sheet.TileWidth, Sheet.TileHeight); device.RasterizerState = RasterizerState.CullNone; device.DepthStencilState = DepthStencilState.Default; Vector3 half = Vector3.One * 0.5f; half = new Vector3(half.X, half.Y, half.Z); foreach (EffectPass pass in shader.CurrentTechnique.Passes) { int ID = 0; foreach (var type in Patterns) { int row = ID / cols; int col = ID % cols; var xboundsMin = 0; var xboundsMax = 0; var yboundsMin = 0; var yboundsMax = 0; var primitive = new RawPrimitive(); foreach (var piece in type.Pieces) { var rawPiece = RailLibrary.GetRailPiece(piece.RailPiece); var bounds = Vector4.Zero; var uvs = tileSheet.GenerateTileUVs(rawPiece.Tile, out bounds); primitive.AddQuad( Matrix.CreateRotationY((float)Math.PI * 0.5f * (float)piece.Orientation) * Matrix.CreateTranslation(new Vector3(piece.Offset.X, 0.0f, piece.Offset.Y)), Color.White, Color.White, uvs, bounds); xboundsMin = Math.Min(xboundsMin, piece.Offset.X); xboundsMax = Math.Max(xboundsMax, piece.Offset.X); yboundsMin = Math.Min(yboundsMin, piece.Offset.Y); yboundsMax = Math.Max(yboundsMax, piece.Offset.Y); } float xSize = xboundsMax - xboundsMin + 1; float ySize = yboundsMax - yboundsMin + 1; var cameraPos = new Vector3(xboundsMin + (xSize / 2), 2.0f, yboundsMax + 1.0f); device.Viewport = new Viewport(col * Sheet.TileWidth, row * Sheet.TileHeight, Sheet.TileWidth, Sheet.TileHeight); shader.View = Matrix.CreateLookAt(cameraPos, new Vector3((xboundsMin + (xSize / 2)), 0.0f, yboundsMin), Vector3.UnitY); shader.Projection = Matrix.CreatePerspectiveFieldOfView(1.0f, 1.0f, 0.1f, 10); shader.World = Matrix.Identity; shader.CameraPosition = cameraPos; pass.Apply(); primitive.Render(device); ++ID; } } device.Viewport = oldview; device.SetRenderTarget(null); return((Texture2D)toReturn); }
private void AttachToNeighbors() { System.Diagnostics.Debug.Assert(NeighborRails.Count == 0); var myPiece = RailLibrary.GetRailPiece(Piece.RailPiece); var myEndPoints = GetTransformedConnections().SelectMany(l => new Vector3[] { l.Item1, l.Item2 }); foreach (var entity in Manager.World.EnumerateIntersectingObjects(this.BoundingBox.Expand(0.5f), CollisionType.Static)) { if (Object.ReferenceEquals(entity, this)) { continue; } var neighborRail = entity as RailEntity; if (neighborRail == null) { continue; } var neighborEndPoints = neighborRail.GetTransformedConnections().SelectMany(l => new Vector3[] { l.Item1, l.Item2 }); foreach (var point in myEndPoints) { foreach (var nPoint in neighborEndPoints) { if ((nPoint - point).LengthSquared() < 0.01f) { AttachNeighbor(neighborRail.GlobalID, point, false); neighborRail.AttachNeighbor(this.GlobalID, point, false); goto __CONTINUE; } } if (myPiece.AutoSlope) { var raisedPoint = point + new Vector3(0.0f, 1.0f, 0.0f); foreach (var nPoint in neighborEndPoints) { if ((nPoint - raisedPoint).LengthSquared() < 0.01f) { AttachNeighbor(neighborRail.GlobalID, raisedPoint, true); neighborRail.AttachNeighbor(this.GlobalID, raisedPoint, false); goto __CONTINUE; } } } var neighborPiece = RailLibrary.GetRailPiece(neighborRail.Piece.RailPiece); if (neighborPiece.AutoSlope) { var loweredPoint = point - new Vector3(0.0f, 1.0f, 0.0f); foreach (var nPoint in neighborEndPoints) { if ((nPoint - loweredPoint).LengthSquared() < 0.01f) { AttachNeighbor(neighborRail.GlobalID, point, false); neighborRail.AttachNeighbor(this.GlobalID, point, true); goto __CONTINUE; } } } } __CONTINUE :; } }
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; var piece = Rail.RailLibrary.GetRailPiece(Piece.RailPiece); 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); } } foreach (var compassConnection in piece.CompassConnections) { var localConnection = compassConnection.RotateToPiece(Piece.Orientation); Drawer3D.DrawLine(Position + new Vector3(0.0f, 0.7f, 0.0f), Position + Vector3.Transform(new Vector3(0.0f, 0.7f, 0.5f), Matrix.CreateRotationY(((float)Math.PI / 4) * (float)localConnection.A)), Color.DarkBlue, 0.1f); Drawer3D.DrawLine(Position + new Vector3(0.0f, 0.7f, 0.0f), Position + Vector3.Transform(new Vector3(0.0f, 0.7f, 0.5f), Matrix.CreateRotationY(((float)Math.PI / 4) * (float)localConnection.B)), Color.DarkBlue, 0.1f); } } if (!IsVisible) { return; } if (Primitive == null) { var bounds = Vector4.Zero; var uvs = Sheet.GenerateTileUVs(Frame, out bounds); var rawPiece = RailLibrary.GetRailPiece(Piece.RailPiece); 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); 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.ChunkData, 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); } }