/// <summary> /// Moves the constraint lines to the proper location relative to the entities involved. /// </summary> public override void Update() { //Move lines around axis.PositionA = MathConverter.Convert(LineObject.ConnectionB.Position); axis.PositionB = MathConverter.Convert(LineObject.ConnectionB.Position + LineObject.TwistAxisB * 1.5f); float angleIncrement = 4 * MathHelper.Pi / limitLines.Length; //Each loop iteration moves this many radians forward. for (int i = 0; i < limitLines.Length / 2; i++) { Line pointToPreviousPoint = limitLines[2 * i]; Line centerToPoint = limitLines[2 * i + 1]; float currentAngle = i * angleIncrement; //Using the parametric equation for an ellipse, compute the axis of rotation and angle. Microsoft.Xna.Framework.Vector3 rotationAxis = MathConverter.Convert(LineObject.Basis.xAxis * LineObject.MaximumAngleX * (float)Math.Cos(currentAngle) + LineObject.Basis.yAxis * LineObject.MaximumAngleY * (float)Math.Sin(currentAngle)); float angle = rotationAxis.Length(); rotationAxis /= angle; pointToPreviousPoint.PositionA = MathConverter.Convert(LineObject.ConnectionB.Position) + //Rotate the primary axis to the ellipse boundary... Microsoft.Xna.Framework.Vector3.TransformNormal(MathConverter.Convert(LineObject.Basis.PrimaryAxis), Microsoft.Xna.Framework.Matrix.CreateFromAxisAngle(rotationAxis, angle)); centerToPoint.PositionA = pointToPreviousPoint.PositionA; centerToPoint.PositionB = MathConverter.Convert(LineObject.ConnectionB.Position); } for (int i = 0; i < limitLines.Length / 2; i++) { //Connect all the pointToPreviousPoint lines to the previous points. limitLines[2 * i].PositionB = limitLines[2 * ((i + 1) % (limitLines.Length / 2))].PositionA; } }
public static void GetMeshData(TriangleMesh mesh, List <VertexPositionNormalTexture> vertices, List <ushort> indices) { var tempVertices = new VertexPositionNormalTexture[mesh.Data.Vertices.Length]; for (int i = 0; i < mesh.Data.Vertices.Length; i++) { Vector3 v; mesh.Data.GetVertexPosition(i, out v); tempVertices[i] = new VertexPositionNormalTexture(MathConverter.Convert(v), Microsoft.Xna.Framework.Vector3.Zero, Microsoft.Xna.Framework.Vector2.Zero); } for (int i = 0; i < mesh.Data.Indices.Length; i++) { indices.Add((ushort)mesh.Data.Indices[i]); } for (int i = 0; i < indices.Count; i += 3) { int a = indices[i]; int b = indices[i + 1]; int c = indices[i + 2]; Microsoft.Xna.Framework.Vector3 normal = Microsoft.Xna.Framework.Vector3.Normalize(Microsoft.Xna.Framework.Vector3.Cross( tempVertices[c].Position - tempVertices[a].Position, tempVertices[b].Position - tempVertices[a].Position)); tempVertices[a].Normal += normal; tempVertices[b].Normal += normal; tempVertices[c].Normal += normal; } for (int i = 0; i < tempVertices.Length; i++) { tempVertices[i].Normal.Normalize(); vertices.Add(tempVertices[i]); } }
public static void GetShapeMeshData(EntityCollidable collidable, List <VertexPositionNormalTexture> vertices, List <ushort> indices) { var convexHullShape = collidable.Shape as ConvexHullShape; if (convexHullShape == null) { throw new ArgumentException("Wrong shape type."); } var hullTriangleVertices = new List <Vector3>(); var hullTriangleIndices = new List <int>(); ConvexHullHelper.GetConvexHull(convexHullShape.Vertices, hullTriangleIndices, hullTriangleVertices); //The hull triangle vertices are used as a dummy to get the unnecessary hull vertices, which are cleared afterwards. hullTriangleVertices.Clear(); foreach (int i in hullTriangleIndices) { hullTriangleVertices.Add(convexHullShape.Vertices[i]); } var toReturn = new VertexPositionNormalTexture[hullTriangleVertices.Count]; Vector3 normal; for (ushort i = 0; i < hullTriangleVertices.Count; i += 3) { normal = Vector3.Normalize(Vector3.Cross(hullTriangleVertices[i + 2] - hullTriangleVertices[i], hullTriangleVertices[i + 1] - hullTriangleVertices[i])); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i]), MathConverter.Convert(normal), new Microsoft.Xna.Framework.Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i + 1]), MathConverter.Convert(normal), new Microsoft.Xna.Framework.Vector2(1, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i + 2]), MathConverter.Convert(normal), new Microsoft.Xna.Framework.Vector2(0, 1))); indices.Add(i); indices.Add((ushort)(i + 1)); indices.Add((ushort)(i + 2)); } }
/// <summary> /// Moves the constraint lines to the proper location relative to the entities involved. /// </summary> public override void Update() { //Move lines around if (LineObject.IsActive) { toPoint.PositionA = MathConverter.Convert(LineObject.Entity.Position); toPoint.PositionB = MathConverter.Convert(LineObject.Point); if (LineObject.Settings.Mode == MotorMode.Servomechanism) { error.PositionA = toPoint.PositionB; error.PositionB = MathConverter.Convert(LineObject.Settings.Servo.Goal); } else { error.PositionA = toPoint.PositionB; error.PositionB = toPoint.PositionB; } } else { error.PositionA = toPoint.PositionB; error.PositionB = toPoint.PositionB; } }
public static void GetShapeMeshData(EntityCollidable collidable, List <VertexPositionNormalTexture> vertices, List <ushort> indices) { var triangleShape = collidable.Shape as TriangleShape; if (triangleShape == null) { throw new ArgumentException("Wrong shape type."); } Microsoft.Xna.Framework.Vector3 normal = MathConverter.Convert(triangleShape.GetLocalNormal()); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(triangleShape.VertexA), -normal, new Microsoft.Xna.Framework.Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(triangleShape.VertexB), -normal, new Microsoft.Xna.Framework.Vector2(0, 1))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(triangleShape.VertexC), -normal, new Microsoft.Xna.Framework.Vector2(1, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(triangleShape.VertexA), normal, new Microsoft.Xna.Framework.Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(triangleShape.VertexB), normal, new Microsoft.Xna.Framework.Vector2(0, 1))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(triangleShape.VertexC), normal, new Microsoft.Xna.Framework.Vector2(1, 0))); indices.Add(0); indices.Add(1); indices.Add(2); indices.Add(3); indices.Add(5); indices.Add(4); }
public override void GetMeshData(List <VertexPositionNormalTexture> vertices, List <ushort> indices) { var tempVertices = new VertexPositionNormalTexture[DisplayedObject.Shape.TriangleMesh.Data.Vertices.Length]; for (int i = 0; i < DisplayedObject.Shape.TriangleMesh.Data.Vertices.Length; i++) { tempVertices[i] = new VertexPositionNormalTexture( MathConverter.Convert(AffineTransform.Transform(DisplayedObject.Shape.TriangleMesh.Data.Vertices[i], DisplayedObject.WorldTransform)), Microsoft.Xna.Framework.Vector3.Zero, Microsoft.Xna.Framework.Vector2.Zero); } for (int i = 0; i < DisplayedObject.Shape.TriangleMesh.Data.Indices.Length; i++) { indices.Add((ushort)DisplayedObject.Shape.TriangleMesh.Data.Indices[i]); } for (int i = 0; i < indices.Count; i += 3) { int a = indices[i]; int b = indices[i + 1]; int c = indices[i + 2]; Microsoft.Xna.Framework.Vector3 normal = Microsoft.Xna.Framework.Vector3.Normalize(Microsoft.Xna.Framework.Vector3.Cross( tempVertices[c].Position - tempVertices[a].Position, tempVertices[b].Position - tempVertices[a].Position)); tempVertices[a].Normal += normal; tempVertices[b].Normal += normal; tempVertices[c].Normal += normal; } for (int i = 0; i < tempVertices.Length; i++) { tempVertices[i].Normal.Normalize(); vertices.Add(tempVertices[i]); } }
/// <summary> /// Draws the component. /// </summary> /// <param name="viewMatrix">View matrix to use when rendering the lines.</param> /// <param name="projectionMatrix">Projection matrix to use when rendering the lines.</param> public void Draw(Matrix viewMatrix, Matrix projectionMatrix) { int numElements = firstOpenIndex / 2; if (numElements > 0) { //Set state game.GraphicsDevice.BlendState = blendState; lineDrawer.LightingEnabled = false; lineDrawer.VertexColorEnabled = true; lineDrawer.World = Microsoft.Xna.Framework.Matrix.Identity; lineDrawer.View = MathConverter.Convert(viewMatrix); lineDrawer.Projection = MathConverter.Convert(projectionMatrix); //Draw for (int i = 0; i < lineDrawer.CurrentTechnique.Passes.Count; i++) { lineDrawer.CurrentTechnique.Passes[i].Apply(); game.GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, numElements); } } }
/// <summary> /// Draws the display object. /// </summary> /// <param name="viewMatrix">Current view matrix.</param> /// <param name="projectionMatrix">Current projection matrix.</param> public override void Draw(Matrix viewMatrix, Matrix projectionMatrix) { //This is not a particularly fast method of drawing. //It's used very rarely in the demos. model.CopyAbsoluteBoneTransformsTo(transforms); for (int i = 0; i < Model.Meshes.Count; i++) { for (int j = 0; j < Model.Meshes[i].Effects.Count; j++) { var effect = Model.Meshes[i].Effects[j] as BasicEffect; if (effect != null) { effect.World = transforms[Model.Meshes[i].ParentBone.Index] * MathConverter.Convert(WorldTransform); effect.View = MathConverter.Convert(viewMatrix); effect.Projection = MathConverter.Convert(projectionMatrix); effect.AmbientLightColor = Color; if (Texture != null) { effect.TextureEnabled = true; effect.Texture = Texture; } else { effect.TextureEnabled = false; } } } Model.Meshes[i].Draw(); } }
/// <summary> /// Moves the constraint lines to the proper location relative to the entities involved. /// </summary> public override void Update() { //Move lines around error.PositionA = MathConverter.Convert(LineObject.GoalPosition); error.PositionB = MathConverter.Convert(LineObject.GrabbedPosition); }
/// <summary> /// Moves the constraint lines to the proper location relative to the entities involved. /// </summary> public override void Update() { //Move lines around axisA.PositionA = MathConverter.Convert(LineObject.ConnectionA.Position); axisA.PositionB = MathConverter.Convert(LineObject.ConnectionA.Position + LineObject.WorldAxisA); axisB.PositionA = MathConverter.Convert(LineObject.ConnectionB.Position); axisB.PositionB = MathConverter.Convert(LineObject.ConnectionB.Position + LineObject.WorldAxisB); }
/// <summary> /// Moves the constraint lines to the proper location relative to the entities involved. /// </summary> public override void Update() { //Move lines around aToConnection.PositionA = MathConverter.Convert(LineObject.ConnectionA.Position); aToConnection.PositionB = MathConverter.Convert(LineObject.WorldAnchorA); bToConnection.PositionA = MathConverter.Convert(LineObject.ConnectionB.Position); bToConnection.PositionB = MathConverter.Convert(LineObject.WorldAnchorB); error.PositionA = aToConnection.PositionB; error.PositionB = bToConnection.PositionB; }
public void Draw(Effect effect, Space space) { if (space.Entities.Count > 0) { foreach (var e in space.Entities) { Microsoft.Xna.Framework.Vector3[] boundingBoxCorners = MathConverter.Convert(e.CollisionInformation.BoundingBox.GetCorners()); var color = e.ActivityInformation.IsActive ? Color.DarkRed : new Color(150, 100, 100); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[0], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[1], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[0], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[3], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[0], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[4], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[1], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[2], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[1], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[5], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[2], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[3], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[2], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[6], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[3], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[7], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[4], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[5], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[4], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[7], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[5], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[6], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[6], color)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[7], color)); } foreach (var pass in effect.CurrentTechnique.Passes) { pass.Apply(); game.GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, boundingBoxLines.Elements, 0, space.Entities.Count * 12); } boundingBoxLines.Clear(); } }
/// <summary> /// Draws the models managed by the drawer. /// </summary> /// <param name="viewMatrix">View matrix to use to draw the objects.</param> /// <param name="projectionMatrix">Projection matrix to use to draw the objects.</param> protected override void DrawManagedModels(Matrix viewMatrix, Matrix projectionMatrix) { viewParameter.SetValue(MathConverter.Convert(viewMatrix)); projectionParameter.SetValue(MathConverter.Convert(projectionMatrix)); for (int i = 0; i < instancingEffect.CurrentTechnique.Passes.Count; i++) { foreach (ModelDisplayObjectBatch batch in batches) { batch.Draw(instancingEffect, worldTransformsParameter, textureIndicesParameter, instancingEffect.CurrentTechnique.Passes[i]); } } }
/// <summary> /// Moves the constraint lines to the proper location relative to the entities involved. /// </summary> public override void Update() { //Move lines around aToConnection.PositionA = MathConverter.Convert(LineObject.ConnectionA.Position); aToConnection.PositionB = MathConverter.Convert(LineObject.AnchorA); bToConnection.PositionA = MathConverter.Convert(LineObject.ConnectionB.Position); bToConnection.PositionB = MathConverter.Convert(LineObject.AnchorB); error.PositionA = aToConnection.PositionB; error.PositionB = bToConnection.PositionB; axis.PositionA = MathConverter.Convert(LineObject.AnchorA + LineObject.Axis * LineObject.Minimum); axis.PositionB = MathConverter.Convert(LineObject.AnchorA + LineObject.Axis * LineObject.Maximum); }
/// <summary> /// Moves the constraint lines to the proper location relative to the entities involved. /// </summary> public override void Update() { //Move lines around PointOnPlaneJoint constraint = LineObject; Microsoft.Xna.Framework.Vector3 planeAnchor = MathConverter.Convert(constraint.PlaneAnchor); Microsoft.Xna.Framework.Vector3 y = MathConverter.Convert(Vector3.Cross(constraint.ConnectionA.OrientationMatrix.Up, constraint.PlaneNormal)); if (y.LengthSquared() < .001f) { y = MathConverter.Convert(Vector3.Cross(constraint.ConnectionA.OrientationMatrix.Right, constraint.PlaneNormal)); } Microsoft.Xna.Framework.Vector3 x = Microsoft.Xna.Framework.Vector3.Cross(MathConverter.Convert(constraint.PlaneNormal), y); //Grid gridRow1.PositionA = planeAnchor - 1.5f * x + y; gridRow1.PositionB = planeAnchor + 1.5f * x + y; gridRow2.PositionA = planeAnchor - 1.5f * x; gridRow2.PositionB = planeAnchor + 1.5f * x; gridRow3.PositionA = planeAnchor - 1.5f * x - y; gridRow3.PositionB = planeAnchor + 1.5f * x - y; gridColumn1.PositionA = planeAnchor + x - 1.5f * y; gridColumn1.PositionB = planeAnchor + x + 1.5f * y; gridColumn2.PositionA = planeAnchor - 1.5f * y; gridColumn2.PositionB = planeAnchor + 1.5f * y; gridColumn3.PositionA = planeAnchor - x - 1.5f * y; gridColumn3.PositionB = planeAnchor - x + 1.5f * y; //Connection and error aToConnection.PositionA = MathConverter.Convert(constraint.ConnectionA.Position); aToConnection.PositionB = MathConverter.Convert(constraint.PlaneAnchor); bToConnection.PositionA = MathConverter.Convert(constraint.ConnectionB.Position); bToConnection.PositionB = MathConverter.Convert(constraint.PointAnchor); error.PositionA = aToConnection.PositionB; error.PositionB = bToConnection.PositionB; }
public static void GetShapeMeshData(EntityCollidable collidable, List <VertexPositionNormalTexture> vertices, List <ushort> indices) { var compoundCollidable = collidable as CompoundCollidable; if (compoundCollidable == null) { throw new ArgumentException("Wrong shape type."); } var tempIndices = new List <ushort>(); var tempVertices = new List <VertexPositionNormalTexture>(); for (int i = 0; i < compoundCollidable.Children.Count; i++) { var child = compoundCollidable.Children[i]; ModelDrawer.ShapeMeshGetter shapeMeshGetter; if (ModelDrawer.ShapeMeshGetters.TryGetValue(child.CollisionInformation.GetType(), out shapeMeshGetter)) { shapeMeshGetter(child.CollisionInformation, tempVertices, tempIndices); for (int j = 0; j < tempIndices.Count; j++) { indices.Add((ushort)(tempIndices[j] + vertices.Count)); } var localTransform = child.Entry.LocalTransform; var localPosition = MathConverter.Convert(child.CollisionInformation.LocalPosition); var orientation = MathConverter.Convert(localTransform.Orientation); var position = MathConverter.Convert(localTransform.Position); for (int j = 0; j < tempVertices.Count; j++) { VertexPositionNormalTexture vertex = tempVertices[j]; Microsoft.Xna.Framework.Vector3.Add(ref vertex.Position, ref localPosition, out vertex.Position); Microsoft.Xna.Framework.Vector3.Transform(ref vertex.Position, ref orientation, out vertex.Position); Microsoft.Xna.Framework.Vector3.Add(ref vertex.Position, ref position, out vertex.Position); Microsoft.Xna.Framework.Vector3.Transform(ref vertex.Normal, ref orientation, out vertex.Normal); vertices.Add(vertex); } tempVertices.Clear(); tempIndices.Clear(); } } }
public override void Update() { if (DisplayedObject.Entity != null) { //The reason for this complexity is that we're drawing the shape's location directly and interpolated buffers might be active. //That means we can't rely solely on the collidable's world transform or the entity's world transform alone; //we must rebuild it from the entity's world transform and the collidable's local position. //TODO: This is awfully annoying. Could use some built-in convenience methods to ease the usage. Vector3 translation = Matrix3x3.Transform(DisplayedObject.LocalPosition, DisplayedObject.Entity.BufferedStates.InterpolatedStates.OrientationMatrix); translation += DisplayedObject.Entity.BufferedStates.InterpolatedStates.Position; Matrix worldTransform = Matrix3x3.ToMatrix4X4(DisplayedObject.Entity.BufferedStates.InterpolatedStates.OrientationMatrix); worldTransform.Translation = translation; WorldTransform = MathConverter.Convert(worldTransform); } else { //Entityless EntityCollidables just go by what their current transform is. WorldTransform = MathConverter.Convert(DisplayedObject.WorldTransform.Matrix); } }
public void Draw(Effect effect, Space space) { contactLines.Clear(); int contactCount = 0; foreach (var pair in space.NarrowPhase.Pairs) { var pairHandler = pair as CollidablePairHandler; if (pairHandler != null) { foreach (ContactInformation information in pairHandler.Contacts) { contactCount++; if (information.Contact.PenetrationDepth < 0) { contactLines.Add(new VertexPositionColor(MathConverter.Convert(information.Contact.Position), Color.Blue)); contactLines.Add(new VertexPositionColor(MathConverter.Convert(information.Contact.Position + information.Contact.Normal * information.Contact.PenetrationDepth), Color.White)); contactLines.Add(new VertexPositionColor(MathConverter.Convert(information.Contact.Position), Color.White)); contactLines.Add(new VertexPositionColor(MathConverter.Convert(information.Contact.Position + information.Contact.Normal * .3f), Color.White)); } else { contactLines.Add(new VertexPositionColor(MathConverter.Convert(information.Contact.Position), Color.White)); contactLines.Add(new VertexPositionColor(MathConverter.Convert(information.Contact.Position + information.Contact.Normal * information.Contact.PenetrationDepth), Color.Red)); contactLines.Add(new VertexPositionColor(MathConverter.Convert(information.Contact.Position + information.Contact.Normal * information.Contact.PenetrationDepth), Color.White)); contactLines.Add(new VertexPositionColor(MathConverter.Convert(information.Contact.Position + information.Contact.Normal * (information.Contact.PenetrationDepth + .3f)), Color.White)); } } } } if (contactCount > 0) { foreach (var pass in effect.CurrentTechnique.Passes) { pass.Apply(); game.GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, contactLines.Elements, 0, contactLines.Count / 2); } } }
public override void GetMeshData(List <VertexPositionNormalTexture> vertices, List <ushort> indices) { for (int i = 0; i < DisplayedObject.SurfaceTriangles.Count; i++) { Microsoft.Xna.Framework.Vector3 upVector = MathConverter.Convert(DisplayedObject.UpVector); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(DisplayedObject.SurfaceTriangles[i][0]), upVector, new Microsoft.Xna.Framework.Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(DisplayedObject.SurfaceTriangles[i][1]), upVector, new Microsoft.Xna.Framework.Vector2(0, 1))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(DisplayedObject.SurfaceTriangles[i][2]), upVector, new Microsoft.Xna.Framework.Vector2(1, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(DisplayedObject.SurfaceTriangles[i][0]), -upVector, new Microsoft.Xna.Framework.Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(DisplayedObject.SurfaceTriangles[i][1]), -upVector, new Microsoft.Xna.Framework.Vector2(0, 1))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(DisplayedObject.SurfaceTriangles[i][2]), -upVector, new Microsoft.Xna.Framework.Vector2(1, 0))); indices.Add((ushort)(i * 6)); indices.Add((ushort)(i * 6 + 1)); indices.Add((ushort)(i * 6 + 2)); indices.Add((ushort)(i * 6 + 3)); indices.Add((ushort)(i * 6 + 5)); indices.Add((ushort)(i * 6 + 4)); } }
public static void GetShapeMeshData(EntityCollidable collidable, List <VertexPositionNormalTexture> vertices, List <ushort> indices) { var shape = collidable.Shape as ConvexShape; if (shape == null) { throw new ArgumentException("Wrong shape type for this helper."); } var vertexPositions = new Vector3[SampleDirections.Length]; for (int i = 0; i < SampleDirections.Length; ++i) { shape.GetLocalExtremePoint(SampleDirections[i], out vertexPositions[i]); } var hullIndices = new RawList <int>(); ConvexHullHelper.GetConvexHull(vertexPositions, hullIndices); var hullTriangleVertices = new RawList <Vector3>(); foreach (int i in hullIndices) { hullTriangleVertices.Add(vertexPositions[i]); } for (ushort i = 0; i < hullTriangleVertices.Count; i += 3) { Vector3 normal = Vector3.Normalize(Vector3.Cross(hullTriangleVertices[i + 2] - hullTriangleVertices[i], hullTriangleVertices[i + 1] - hullTriangleVertices[i])); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i]), MathConverter.Convert(normal), new Microsoft.Xna.Framework.Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i + 1]), MathConverter.Convert(normal), new Microsoft.Xna.Framework.Vector2(1, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i + 2]), MathConverter.Convert(normal), new Microsoft.Xna.Framework.Vector2(0, 1))); indices.Add(i); indices.Add((ushort)(i + 1)); indices.Add((ushort)(i + 2)); } }
/// <summary> /// Moves the constraint lines to the proper location relative to the entities involved. /// </summary> public override void Update() { //Move lines around Microsoft.Xna.Framework.Vector3 left = MathConverter.Convert(LineObject.ConnectionB.Position - LineObject.Basis.PrimaryAxis); Microsoft.Xna.Framework.Vector3 right = MathConverter.Convert(LineObject.ConnectionB.Position + LineObject.Basis.PrimaryAxis); Microsoft.Xna.Framework.Vector3 upwardsOffset = Microsoft.Xna.Framework.Vector3.TransformNormal(MathConverter.Convert(LineObject.Basis.xAxis), Microsoft.Xna.Framework.Matrix.CreateFromAxisAngle(MathConverter.Convert(LineObject.Basis.PrimaryAxis), LineObject.MaximumAngle)); Microsoft.Xna.Framework.Vector3 topRightPosition = right + upwardsOffset; Microsoft.Xna.Framework.Vector3 topLeftPosition = left + upwardsOffset; Microsoft.Xna.Framework.Vector3 downwardsOffset = Microsoft.Xna.Framework.Vector3.TransformNormal(MathConverter.Convert(LineObject.Basis.xAxis), Microsoft.Xna.Framework.Matrix.CreateFromAxisAngle(MathConverter.Convert(LineObject.Basis.PrimaryAxis), LineObject.MinimumAngle)); Microsoft.Xna.Framework.Vector3 bottomRightPosition = right + downwardsOffset; Microsoft.Xna.Framework.Vector3 bottomLeftPosition = left + downwardsOffset; middle.PositionA = left; middle.PositionB = right; topLeft.PositionA = left; topLeft.PositionB = topLeftPosition; topRight.PositionA = right; topRight.PositionB = topRightPosition; top.PositionA = topLeftPosition; top.PositionB = topRightPosition; bottomLeft.PositionA = left; bottomLeft.PositionB = bottomLeftPosition; bottomRight.PositionA = right; bottomRight.PositionB = bottomRightPosition; bottom.PositionA = bottomLeftPosition; bottom.PositionB = bottomRightPosition; testAxis.PositionA = MathConverter.Convert(LineObject.ConnectionB.Position); testAxis.PositionB = MathConverter.Convert(LineObject.ConnectionB.Position + LineObject.TestAxis); }
public static void GetShapeMeshData(EntityCollidable collidable, List <VertexPositionNormalTexture> vertices, List <ushort> indices) { MobileMeshShape shape = collidable.Shape as MobileMeshShape; var tempVertices = new VertexPositionNormalTexture[shape.TriangleMesh.Data.Vertices.Length]; for (int i = 0; i < shape.TriangleMesh.Data.Vertices.Length; i++) { Vector3 position; shape.TriangleMesh.Data.GetVertexPosition(i, out position); tempVertices[i] = new VertexPositionNormalTexture( MathConverter.Convert(position), Microsoft.Xna.Framework.Vector3.Zero, Microsoft.Xna.Framework.Vector2.Zero); } for (int i = 0; i < shape.TriangleMesh.Data.Indices.Length; i++) { indices.Add((ushort)shape.TriangleMesh.Data.Indices[i]); } for (int i = 0; i < indices.Count; i += 3) { int a = indices[i]; int b = indices[i + 1]; int c = indices[i + 2]; Microsoft.Xna.Framework.Vector3 normal = Microsoft.Xna.Framework.Vector3.Normalize(Microsoft.Xna.Framework.Vector3.Cross( tempVertices[c].Position - tempVertices[a].Position, tempVertices[b].Position - tempVertices[a].Position)); tempVertices[a].Normal += normal; tempVertices[b].Normal += normal; tempVertices[c].Normal += normal; } for (int i = 0; i < tempVertices.Length; i++) { tempVertices[i].Normal.Normalize(); vertices.Add(tempVertices[i]); } }
/// <summary> /// Gets an array of vertices and indices from the provided model. /// </summary> /// <param name="collisionModel">Model to use for the collision shape.</param> /// <param name="vertices">Compiled set of vertices from the model.</param> /// <param name="indices">Compiled set of indices from the model.</param> public static void GetVerticesAndIndicesFromModel(Model collisionModel, out Vector3[] vertices, out int[] indices) { Microsoft.Xna.Framework.Vector3[] tempVertices; GetVerticesAndIndicesFromModel(collisionModel, out tempVertices, out indices); vertices = MathConverter.Convert(tempVertices); }
/// <summary> /// This is called when the game should draw itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(new Color(.41f, .41f, .45f, 1)); var viewMatrix = Camera.ViewMatrix; var projectionMatrix = Camera.ProjectionMatrix; if (displayEntities) { ModelDrawer.Draw(viewMatrix, projectionMatrix); } if (displayConstraints) { ConstraintDrawer.Draw(viewMatrix, projectionMatrix); } LineDrawer.LightingEnabled = false; LineDrawer.VertexColorEnabled = true; LineDrawer.World = Microsoft.Xna.Framework.Matrix.Identity; LineDrawer.View = MathConverter.Convert(viewMatrix); LineDrawer.Projection = MathConverter.Convert(projectionMatrix); if (displayContacts) { ContactDrawer.Draw(LineDrawer, currentSimulation.Space); } if (displayBoundingBoxes) { BoundingBoxDrawer.Draw(LineDrawer, currentSimulation.Space); } if (displaySimulationIslands) { SimulationIslandDrawer.Draw(LineDrawer, currentSimulation.Space); } //This doesn't actually draw the elements in the demo (that's the modeldrawer's job), //but some demos can specify their own extra stuff to draw. currentSimulation.Draw(); base.Draw(gameTime); #region UI Drawing UIDrawer.Begin(); int bottom = GraphicsDevice.Viewport.Bounds.Height; int right = GraphicsDevice.Viewport.Bounds.Width; if (displayUI) { FPStotalSinceLast += gameTime.ElapsedGameTime.TotalSeconds; FPStotalFramesSinceLast++; if (gameTime.TotalGameTime.TotalSeconds - FPSlastTime > .25 && gameTime.ElapsedGameTime.TotalSeconds > 0) { double avg = FPStotalSinceLast / FPStotalFramesSinceLast; FPSlastTime = gameTime.TotalGameTime.TotalSeconds; FPStoDisplay = Math.Round(1 / avg, 1); averagePhysicsTime = Math.Round(1000 * currentSimulation.PhysicsTime, 1); FPStotalSinceLast = 0; FPStotalFramesSinceLast = 0; } DataTextDrawer.Draw("FPS: ", (int)FPStoDisplay, new Microsoft.Xna.Framework.Vector2(50, bottom - 150)); DataTextDrawer.Draw("Physics Time (ms): ", (int)averagePhysicsTime, new Microsoft.Xna.Framework.Vector2(50, bottom - 133)); DataTextDrawer.Draw("Collision Pairs: ", currentSimulation.Space.NarrowPhase.Pairs.Count, new Microsoft.Xna.Framework.Vector2(50, bottom - 116)); if (displayActiveEntityCount) { int countActive = 0; for (int i = 0; i < currentSimulation.Space.Entities.Count; i++) { if (currentSimulation.Space.Entities[i].ActivityInformation.IsActive) { countActive++; } } DataTextDrawer.Draw("Active Objects: ", countActive, new Microsoft.Xna.Framework.Vector2(50, bottom - 99)); } #if !WINDOWS DataTextDrawer.Draw("Press Start for Controls", new Vector2(50, bottom - 82)); #else DataTextDrawer.Draw("Press F1 for Controls", new Microsoft.Xna.Framework.Vector2(50, bottom - 82)); #endif TinyTextDrawer.Draw("Current Simulation: ", currentSimulationIndex, new Microsoft.Xna.Framework.Vector2(right - 200, bottom - 100)); TinyTextDrawer.Draw(currentSimulation.Name, new Microsoft.Xna.Framework.Vector2(right - 180, bottom - 86)); currentSimulation.DrawUI(); } if (displayMenu) { UIDrawer.Draw(controlsMenu, new Rectangle(right / 2 - 400, bottom / 2 - 300, 800, 600), Color.White); } UIDrawer.End(); #endregion }
public static void GetShapeMeshData(EntityCollidable collidable, List <VertexPositionNormalTexture> vertices, List <ushort> indices) { var boxShape = collidable.Shape as BoxShape; if (boxShape == null) { throw new ArgumentException("Wrong shape type."); } var boundingBox = new BoundingBox( new Vector3(-boxShape.HalfWidth, -boxShape.HalfHeight, -boxShape.HalfLength), new Vector3(boxShape.HalfWidth, boxShape.HalfHeight, boxShape.HalfLength)); Microsoft.Xna.Framework.Vector3[] corners = MathConverter.Convert(boundingBox.GetCorners()); var textureCoords = new Microsoft.Xna.Framework.Vector2[4]; textureCoords[0] = new Microsoft.Xna.Framework.Vector2(0, 0); textureCoords[1] = new Microsoft.Xna.Framework.Vector2(1, 0); textureCoords[2] = new Microsoft.Xna.Framework.Vector2(1, 1); textureCoords[3] = new Microsoft.Xna.Framework.Vector2(0, 1); vertices.Add(new VertexPositionNormalTexture(corners[0], Microsoft.Xna.Framework.Vector3.Backward, textureCoords[0])); vertices.Add(new VertexPositionNormalTexture(corners[1], Microsoft.Xna.Framework.Vector3.Backward, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[2], Microsoft.Xna.Framework.Vector3.Backward, textureCoords[2])); vertices.Add(new VertexPositionNormalTexture(corners[3], Microsoft.Xna.Framework.Vector3.Backward, textureCoords[3])); indices.Add(0); indices.Add(1); indices.Add(2); indices.Add(0); indices.Add(2); indices.Add(3); vertices.Add(new VertexPositionNormalTexture(corners[1], Microsoft.Xna.Framework.Vector3.Right, textureCoords[0])); vertices.Add(new VertexPositionNormalTexture(corners[2], Microsoft.Xna.Framework.Vector3.Right, textureCoords[3])); vertices.Add(new VertexPositionNormalTexture(corners[5], Microsoft.Xna.Framework.Vector3.Right, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[6], Microsoft.Xna.Framework.Vector3.Right, textureCoords[2])); indices.Add(4); indices.Add(6); indices.Add(7); indices.Add(4); indices.Add(7); indices.Add(5); vertices.Add(new VertexPositionNormalTexture(corners[4], Microsoft.Xna.Framework.Vector3.Forward, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[5], Microsoft.Xna.Framework.Vector3.Forward, textureCoords[0])); vertices.Add(new VertexPositionNormalTexture(corners[6], Microsoft.Xna.Framework.Vector3.Forward, textureCoords[3])); vertices.Add(new VertexPositionNormalTexture(corners[7], Microsoft.Xna.Framework.Vector3.Forward, textureCoords[2])); indices.Add(9); indices.Add(8); indices.Add(11); indices.Add(9); indices.Add(11); indices.Add(10); vertices.Add(new VertexPositionNormalTexture(corners[0], Microsoft.Xna.Framework.Vector3.Left, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[3], Microsoft.Xna.Framework.Vector3.Left, textureCoords[2])); vertices.Add(new VertexPositionNormalTexture(corners[4], Microsoft.Xna.Framework.Vector3.Left, textureCoords[0])); vertices.Add(new VertexPositionNormalTexture(corners[7], Microsoft.Xna.Framework.Vector3.Left, textureCoords[3])); indices.Add(14); indices.Add(12); indices.Add(13); indices.Add(14); indices.Add(13); indices.Add(15); vertices.Add(new VertexPositionNormalTexture(corners[0], Microsoft.Xna.Framework.Vector3.Up, textureCoords[2])); vertices.Add(new VertexPositionNormalTexture(corners[1], Microsoft.Xna.Framework.Vector3.Up, textureCoords[3])); vertices.Add(new VertexPositionNormalTexture(corners[4], Microsoft.Xna.Framework.Vector3.Up, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[5], Microsoft.Xna.Framework.Vector3.Up, textureCoords[0])); indices.Add(16); indices.Add(19); indices.Add(17); indices.Add(16); indices.Add(18); indices.Add(19); vertices.Add(new VertexPositionNormalTexture(corners[2], Microsoft.Xna.Framework.Vector3.Down, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[3], Microsoft.Xna.Framework.Vector3.Down, textureCoords[0])); vertices.Add(new VertexPositionNormalTexture(corners[6], Microsoft.Xna.Framework.Vector3.Down, textureCoords[2])); vertices.Add(new VertexPositionNormalTexture(corners[7], Microsoft.Xna.Framework.Vector3.Down, textureCoords[3])); indices.Add(21); indices.Add(20); indices.Add(22); indices.Add(21); indices.Add(22); indices.Add(23); }
public void Draw(Effect effect, Space space) { if (space.Entities.Count > 0) { Microsoft.Xna.Framework.BoundingBox box; foreach (var entity in space.Entities) { var island = entity.ActivityInformation.SimulationIsland; if (island != null) { if (islandBoundingBoxes.TryGetValue(island, out box)) { box = Microsoft.Xna.Framework.BoundingBox.CreateMerged(MathConverter.Convert(entity.CollisionInformation.BoundingBox), box); islandBoundingBoxes[island] = box; } else { islandBoundingBoxes.Add(island, MathConverter.Convert(entity.CollisionInformation.BoundingBox)); } } } foreach (var islandBoundingBox in islandBoundingBoxes) { Color colorToUse = islandBoundingBox.Key.IsActive ? Color.DarkGoldenrod : Color.DarkGray; Microsoft.Xna.Framework.Vector3[] boundingBoxCorners = islandBoundingBox.Value.GetCorners(); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[0], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[1], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[0], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[3], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[0], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[4], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[1], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[2], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[1], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[5], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[2], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[3], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[2], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[6], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[3], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[7], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[4], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[5], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[4], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[7], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[5], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[6], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[6], colorToUse)); boundingBoxLines.Add(new VertexPositionColor(boundingBoxCorners[7], colorToUse)); } if (space.DeactivationManager.SimulationIslands.Count > 0) { foreach (var pass in effect.CurrentTechnique.Passes) { pass.Apply(); game.GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, boundingBoxLines.Elements, 0, islandBoundingBoxes.Count * 12); } } islandBoundingBoxes.Clear(); boundingBoxLines.Clear(); } }
public override void GetMeshData(List <VertexPositionNormalTexture> vertices, List <ushort> indices) { int numColumns = DisplayedObject.Shape.Heights.GetLength(0); int numRows = DisplayedObject.Shape.Heights.GetLength(1); TerrainShape shape = DisplayedObject.Shape; //The terrain can be transformed arbitrarily. However, the collision against the triangles is always oriented such that the transformed local //up vector points in the same direction as the collidable surfaces. //To make sure the graphics match the terrain collision, try transforming the local space up direction into world space. Treat it as a normal- it requires an adjugate transpose, not a regular transformation. var normalTransform = Matrix3x3.AdjugateTranspose(DisplayedObject.WorldTransform.LinearTransform); var reverseWinding = Vector3.Dot(normalTransform.Up, DisplayedObject.WorldTransform.LinearTransform.Up) < 0; for (int j = 0; j < numRows; j++) { for (int i = 0; i < numColumns; i++) { VertexPositionNormalTexture v; Vector3 position, n; DisplayedObject.GetPosition(i, j, out position); shape.GetLocalNormal(i, j, out n); Matrix3x3.Transform(ref n, ref normalTransform, out n); n.Normalize(); MathConverter.Convert(ref position, out v.Position); MathConverter.Convert(ref n, out v.Normal); if (reverseWinding) { Microsoft.Xna.Framework.Vector3.Negate(ref v.Normal, out v.Normal); } v.TextureCoordinate = new Microsoft.Xna.Framework.Vector2(i, j); vertices.Add(v); if (i < numColumns - 1 && j < numRows - 1) { if (shape.QuadTriangleOrganization == QuadTriangleOrganization.BottomLeftUpperRight) { //v3 v4 //v1 v2 //v1 v2 v3 indices.Add((ushort)(numColumns * j + i)); if (reverseWinding) { indices.Add((ushort)(numColumns * (j + 1) + i)); indices.Add((ushort)(numColumns * j + i + 1)); } else { indices.Add((ushort)(numColumns * j + i + 1)); indices.Add((ushort)(numColumns * (j + 1) + i)); } //v2 v4 v3 indices.Add((ushort)(numColumns * j + i + 1)); if (reverseWinding) { indices.Add((ushort)(numColumns * (j + 1) + i)); indices.Add((ushort)(numColumns * (j + 1) + i + 1)); } else { indices.Add((ushort)(numColumns * (j + 1) + i + 1)); indices.Add((ushort)(numColumns * (j + 1) + i)); } } else if (shape.QuadTriangleOrganization == QuadTriangleOrganization.BottomRightUpperLeft) { //v1 v2 v4 indices.Add((ushort)(numColumns * j + i)); if (reverseWinding) { indices.Add((ushort)(numColumns * (j + 1) + i + 1)); indices.Add((ushort)(numColumns * j + i + 1)); } else { indices.Add((ushort)(numColumns * j + i + 1)); indices.Add((ushort)(numColumns * (j + 1) + i + 1)); } //v1 v4 v3 indices.Add((ushort)(numColumns * j + i)); if (reverseWinding) { indices.Add((ushort)(numColumns * (j + 1) + i)); indices.Add((ushort)(numColumns * (j + 1) + i + 1)); } else { indices.Add((ushort)(numColumns * (j + 1) + i + 1)); indices.Add((ushort)(numColumns * (j + 1) + i)); } } } } } }
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(new Color(.41f, .41f, .45f, 1)); var viewMatrix = Camera.ViewMatrix; var projectionMatrix = Camera.ProjectionMatrix; if (displayEntities) { ModelDrawer.Draw(viewMatrix, projectionMatrix); } if (displayConstraints) { ConstraintDrawer.Draw(viewMatrix, projectionMatrix); } LineDrawer.LightingEnabled = false; LineDrawer.VertexColorEnabled = true; LineDrawer.World = Microsoft.Xna.Framework.Matrix.Identity; LineDrawer.View = MathConverter.Convert(viewMatrix); LineDrawer.Projection = MathConverter.Convert(projectionMatrix); if (displayContacts) { ContactDrawer.Draw(LineDrawer, Globals.space); } if (displayBoundingBoxes) { BoundingBoxDrawer.Draw(LineDrawer, Globals.space); } if (displaySimulationIslands) { SimulationIslandDrawer.Draw(LineDrawer, Globals.space); } base.Draw(gameTime); UIDrawer.Begin(); int bottom = GraphicsDevice.Viewport.Bounds.Height; int right = GraphicsDevice.Viewport.Bounds.Width; if (displayUI) { FPStotalSinceLast += gameTime.ElapsedGameTime.TotalSeconds; FPStotalFramesSinceLast++; if (gameTime.TotalGameTime.TotalSeconds - FPSlastTime > .25 && gameTime.ElapsedGameTime.TotalSeconds > 0) { double avg = FPStotalSinceLast / FPStotalFramesSinceLast; FPSlastTime = gameTime.TotalGameTime.TotalSeconds; FPStoDisplay = Math.Round(1 / avg, 1); averagePhysicsTime = Math.Round(1000 * ServerSimulation.PhysicsTime, 1); FPStotalSinceLast = 0; FPStotalFramesSinceLast = 0; } //Display console control terminal DrawControlConsole((int)averagePhysicsTime); DataTextDrawer.Draw("FPS: ", (int)FPStoDisplay, new Microsoft.Xna.Framework.Vector2(50, bottom - 150)); DataTextDrawer.Draw("Physics Time (ms): ", (int)averagePhysicsTime, new Microsoft.Xna.Framework.Vector2(50, bottom - 133)); DataTextDrawer.Draw("Collision Pairs: ", Globals.space.NarrowPhase.Pairs.Count, new Microsoft.Xna.Framework.Vector2(50, bottom - 116)); if (displayActiveEntityCount) { int countActive = 0; for (int i = 0; i < Globals.space.Entities.Count; i++) { if (Globals.space.Entities[i].ActivityInformation.IsActive) { countActive++; } } DataTextDrawer.Draw("Active Objects: ", countActive, new Microsoft.Xna.Framework.Vector2(50, bottom - 99)); } DataTextDrawer.Draw("Press F1 to output camera postion", new Microsoft.Xna.Framework.Vector2(50, bottom - 82)); ServerSimulation.DrawUI(); } if (displayMenu) { UIDrawer.Draw(controlsMenu, new Rectangle(right / 2 - 400, bottom / 2 - 300, 800, 600), Color.White); } UIDrawer.End(); }