/// <summary> /// Handles contact /// </summary> /// <param name="sender"></param> /// <param name="other"></param> /// <param name="pair"></param> /// <param name="contact"></param> private void handleContactCreated(EntityCollidable sender, Collidable other, CollidablePairHandler pair, ContactData contact) { var compoundBody = sender as CompoundCollidable; var ballEntity = other as EntityCollidable; // Find exact block being hit by ball float minDistance = 0; CompoundChild closestChild = null; foreach (CompoundChild child in compoundBody.Children) { if (child.CollisionInformation.CollisionRules.Group != gameLevel.RemovedBlocksGroup) { Vector3 p = Vector3.Transform(child.Entry.LocalTransform.Position, compoundBody.WorldTransform.Matrix); float distance = 0.0f; Vector3.DistanceSquared(ref contact.Position, ref p, out distance); if (closestChild != null) { if (minDistance > distance) { closestChild = child; minDistance = distance; } } else { closestChild = child; minDistance = distance; } } } // Obtain block instance Block hittedBlock = null; foreach (Block block in gameLevel.Blocks) { if (block.Entity == closestChild) { hittedBlock = block; break; } } // Obtain ball instance Ball hittingBall = null; foreach (Platform platform in platforms) { foreach (Ball ball in platform.Balls) { if (ball.Active == true && ball.Entity.CollisionInformation == ballEntity) { hittingBall = ball; break; } } } // We have obtained block and ball which are collided, now we can run game logic if (hittedBlock != null && hittingBall != null) { // Get hit points from the ball int ballHitPoints = hittingBall.HitPoints; int gainedHitPoints = Math.Min(hittedBlock.HitPoints, hittingBall.HitPoints); gainedHitPoints *= hittedBlock.BlockType.ScoresPerHitPoint; hittedBlock.HitPoints -= hittingBall.HitPoints; // Run block logic BlockType blockType = hittedBlock.BlockType; gameLevel.AnimateHit(hittedBlock, contact.Position, hittingBall.Platform); foreach (BlockEvent blockAction in blockType.Events) { blockAction.HandleEvent(hittedBlock); } if (hittedBlock.HitPoints <= 0) { blockType.Owner.RemoveBlock(hittedBlock); } } }
///<summary> /// Constructs a new enumerator. ///</summary> ///<param name="collection">Owning collection.</param> public Enumerator(EntityCollidableCollection collection) { this.collection = collection; index = -1; current = null; }
/// <summary> /// Raises the appropriate ParentObject collision events depending on its CollisionType value /// </summary> /// <param name="sender">The current ISpaceObject instance</param> /// <param name="other">The ISpaceObject instance which collided</param> /// <param name="pair"/> private void OnEntityCollisionDetected(EntityCollidable sender, Collidable other, CollidablePairHandler pair) { OnCollisionDetected(sender, other, pair); }
void Events_ContactCreated(EntityCollidable sender, Collidable other, BEPUphysics.NarrowPhaseSystems.Pairs.CollidablePairHandler pair, ContactData contact) { this.Collided.Execute(other, pair.Contacts); }
private void Events_DetectingInitialCollision(EntityCollidable sender, Collidable other, CollidablePairHandler pair) { _sound.Impact(sender.Entity); }
public static void GetShapeMeshData(EntityCollidable collidable, List <VertexPositionNormalTexture> vertices, List <ushort> indices) { var minkowskiShape = collidable.Shape as MinkowskiSumShape; if (minkowskiShape == null) { throw new ArgumentException("Wrong shape type."); } var points = new List <Vector3>(); Vector3 max; var direction = new Vector3(); float angleChange = MathHelper.TwoPi / NumSamples; for (int i = 1; i < NumSamples / 2 - 1; i++) { float phi = MathHelper.PiOver2 - i * angleChange; var sinPhi = (float)Math.Sin(phi); var cosPhi = (float)Math.Cos(phi); for (int j = 0; j < NumSamples; j++) { float theta = j * angleChange; direction.X = (float)Math.Cos(theta) * cosPhi; direction.Y = sinPhi; direction.Z = (float)Math.Sin(theta) * cosPhi; minkowskiShape.GetLocalExtremePoint(direction, out max); points.Add(max); } } minkowskiShape.GetLocalExtremePoint(Toolbox.UpVector, out max); points.Add(max); minkowskiShape.GetLocalExtremePoint(Toolbox.DownVector, out max); points.Add(max); var hullTriangleVertices = new List <Vector3>(); var hullTriangleIndices = new List <int>(); ConvexHullHelper.GetConvexHull(points, 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(points[i]); } 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(hullTriangleVertices[i], normal, new Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(hullTriangleVertices[i + 1], normal, new Vector2(1, 0))); vertices.Add(new VertexPositionNormalTexture(hullTriangleVertices[i + 2], normal, new Vector2(0, 1))); indices.Add(i); indices.Add((ushort)(i + 1)); indices.Add((ushort)(i + 2)); } }
///<summary> /// Constructs a new entity. ///</summary> ///<param name="collisionInformation">Collidable to use with the entity.</param> ///<param name="mass">Mass of the entity. If positive, the entity will be dynamic. Otherwise, it will be kinematic.</param> public Entity(EntityCollidable collisionInformation, float mass) : this() { Initialize(collisionInformation, mass); }
public static void GetShapeMeshData(EntityCollidable collidable, List <VertexPositionNormalTexture> vertices, List <ushort> indices) { var sphereShape = collidable.Shape as SphereShape; if (sphereShape == null) { throw new ArgumentException("Wrong shape type"); } var n = new Vector3(); float angleBetweenFacets = MathHelper.TwoPi / NumSides; float radius = (float)sphereShape.Radius; //Create the vertex list vertices.Add(new VertexPositionNormalTexture(new Vector3(0, radius, 0), Vector3.Up, Vector2.Zero)); for (int i = 1; i < NumSides / 2; i++) { float phi = MathHelper.PiOver2 - i * angleBetweenFacets; var sinPhi = (float)Math.Sin(phi); var cosPhi = (float)Math.Cos(phi); for (int j = 0; j < NumSides; j++) { float theta = j * angleBetweenFacets; n.X = (float)Math.Cos(theta) * cosPhi; n.Y = sinPhi; n.Z = (float)Math.Sin(theta) * cosPhi; vertices.Add(new VertexPositionNormalTexture(n * radius, n, Vector2.Zero)); } } vertices.Add(new VertexPositionNormalTexture(new Vector3(0, -radius, 0), Vector3.Down, Vector2.Zero)); //Create the index list for (int i = 0; i < NumSides; i++) { indices.Add((ushort)(vertices.Count - 1)); indices.Add((ushort)(vertices.Count - 2 - i)); indices.Add((ushort)(vertices.Count - 2 - (i + 1) % NumSides)); } for (int i = 0; i < NumSides / 2 - 2; i++) { for (int j = 0; j < NumSides; j++) { int nextColumn = (j + 1) % NumSides; indices.Add((ushort)(i * NumSides + nextColumn + 1)); indices.Add((ushort)(i * NumSides + j + 1)); indices.Add((ushort)((i + 1) * NumSides + j + 1)); indices.Add((ushort)((i + 1) * NumSides + nextColumn + 1)); indices.Add((ushort)(i * NumSides + nextColumn + 1)); indices.Add((ushort)((i + 1) * NumSides + j + 1)); } } for (int i = 0; i < NumSides; i++) { indices.Add(0); indices.Add((ushort)(i + 1)); indices.Add((ushort)((i + 1) % NumSides + 1)); } }
///<summary> /// Constructs a new morphable entity. ///</summary> ///<param name="collisionInformation">Collidable to use with the entity.</param> ///<param name="mass">Mass of the entity.</param> /// <param name="inertiaTensor">Inertia tensor of the entity.</param> public MorphableEntity(EntityCollidable collisionInformation, Fix64 mass, Matrix3x3 inertiaTensor) : base(collisionInformation, mass, inertiaTensor) { }
///<summary> /// Constructs a new kinematic entity. ///</summary> ///<param name="collisionInformation">Collidable to use with the entity.</param> public Entity(EntityCollidable collisionInformation) : this() { Initialize(collisionInformation); }
///<summary> /// Constructs a new morphable entity. ///</summary> ///<param name="collisionInformation">Collidable to use with the entity.</param> ///<param name="mass">Mass of the entity.</param> public MorphableEntity(EntityCollidable collisionInformation, Fix64 mass) : base(collisionInformation, mass) { }
///<summary> /// Constructs a new morphable entity. ///</summary> ///<param name="collisionInformation">Collidable to use with the entity.</param> public MorphableEntity(EntityCollidable collisionInformation) : base(collisionInformation) { }
public static void GetShapeMeshData(EntityCollidable collidable, List <VertexPositionNormalTexture> vertices, List <ushort> indices) { var cylinderShape = collidable.Shape as CylinderShape; if (cylinderShape == null) { throw new ArgumentException("Wrong shape type."); } float verticalOffset = cylinderShape.Height / 2; float angleBetweenFacets = MathHelper.TwoPi / NumSides; float radius = cylinderShape.Radius; //Create the vertex list for (int i = 0; i < NumSides; i++) { float theta = i * angleBetweenFacets; float x = (float)Math.Cos(theta) * radius; float z = (float)Math.Sin(theta) * radius; //Top cap vertices.Add(new VertexPositionNormalTexture(new Vector3(x, verticalOffset, z), Vector3.Up, Vector2.Zero)); //Top part of body vertices.Add(new VertexPositionNormalTexture(new Vector3(x, verticalOffset, z), new Vector3(x, 0, z), Vector2.Zero)); //Bottom part of body vertices.Add(new VertexPositionNormalTexture(new Vector3(x, -verticalOffset, z), new Vector3(x, 0, z), Vector2.Zero)); //Bottom cap vertices.Add(new VertexPositionNormalTexture(new Vector3(x, -verticalOffset, z), Vector3.Down, Vector2.Zero)); } //Create the index list //The vertices are arranged a little nonintuitively. //0 is part of the top cap, 1 is the upper body, 2 is lower body, and 3 is bottom cap. for (ushort i = 0; i < vertices.Count; i += 4) { //Each iteration, the loop advances to the next vertex 'column.' //Four triangles per column (except for the four degenerate cap triangles). //Top cap triangles var nextIndex = (ushort)((i + 4) % vertices.Count); if (nextIndex != 0) //Don't add cap indices if it's going to be a degenerate triangle. { indices.Add(i); indices.Add(nextIndex); indices.Add(0); } //Body triangles nextIndex = (ushort)((i + 5) % vertices.Count); indices.Add((ushort)(i + 1)); indices.Add((ushort)(i + 2)); indices.Add(nextIndex); indices.Add(nextIndex); indices.Add((ushort)(i + 2)); indices.Add((ushort)((i + 6) % vertices.Count)); //Bottom cap triangles. nextIndex = (ushort)((i + 7) % vertices.Count); if (nextIndex != 3) //Don't add cap indices if it's going to be a degenerate triangle. { indices.Add((ushort)(i + 3)); indices.Add(3); indices.Add(nextIndex); } } }
///<summary> /// Constructs a new EntityCollidableCollection. ///</summary> ///<param name="owner">Owner of the collection.</param> public EntityCollidableCollection(EntityCollidable owner) { this.owner = owner; }
///<summary> /// Constructs a new entity. ///</summary> ///<param name="collisionInformation">Collidable to use with the entity.</param> ///<param name="mass">Mass of the entity. If positive, the entity will be dynamic. Otherwise, it will be kinematic.</param> /// <param name="inertiaTensor">Inertia tensor of the entity. Only used for a dynamic entity.</param> public Entity(EntityCollidable collisionInformation, float mass, Matrix3x3 inertiaTensor) : this() { Initialize(collisionInformation, mass, inertiaTensor); }
public bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweepnorm, double slen, MaterialSolidity solidness, out RayHit hit) { RigidTransform rot = new RigidTransform(Vector3.Zero, startingTransform.Orientation); castShape.GetBoundingBox(ref rot, out BoundingBox bb); double adv = 0.1f; double max = slen + adv; bool gotOne = false; RayHit BestRH = default(RayHit); Vector3 sweep = sweepnorm * slen; for (double f = 0; f < max; f += adv) { Vector3 c = startingTransform.Position + sweepnorm * f; int mx = (int)Math.Ceiling(c.X + bb.Max.X); for (int x = (int)Math.Floor(c.X + bb.Min.X); x <= mx; x++) { if (x < 0 || x >= ChunkSize.X) { continue; } int my = (int)Math.Ceiling(c.Y + bb.Max.Y); for (int y = (int)Math.Floor(c.Y + bb.Min.Y); y <= my; y++) { if (y < 0 || y >= ChunkSize.Y) { continue; } int mz = (int)Math.Ceiling(c.Z + bb.Max.Z); for (int z = (int)Math.Floor(c.Z + bb.Min.Z); z <= mz; z++) { if (z < 0 || z >= ChunkSize.Z) { continue; } BlockInternal bi = Blocks[BlockIndex(x, y, z)]; if (solidness.HasFlag(((Material)bi.BlockMaterial).GetSolidity())) { EntityShape es = BlockShapeRegistry.BSD[bi.BlockData].GetShape(bi.Damage, out Location offs, false); if (es == null) { continue; } Vector3 adj = new Vector3(x + (double)offs.X, y + (double)offs.Y, z + (double)offs.Z); EntityCollidable coll = es.GetCollidableInstance(); //coll.LocalPosition = adj; RigidTransform rt = new RigidTransform(Vector3.Zero, BEPUutilities.Quaternion.Identity); coll.LocalPosition = Vector3.Zero; coll.WorldTransform = rt; coll.UpdateBoundingBoxForTransform(ref rt); RigidTransform adjusted = new RigidTransform(startingTransform.Position - adj, startingTransform.Orientation); bool b = coll.ConvexCast(castShape, ref adjusted, ref sweep, out RayHit rhit); if (b && (!gotOne || rhit.T * slen < BestRH.T) && rhit.T >= 0) { gotOne = true; BestRH = rhit; BestRH.Location += adj; BestRH.T *= slen; // TODO: ??? BestRH.Normal = -BestRH.Normal; // TODO: WHY?! } } } } } if (gotOne) { hit = BestRH; return(true); } } hit = new RayHit() { Location = startingTransform.Position + sweep, Normal = new Vector3(0, 0, 0), T = slen }; return(false); }
//These initialize methods make it easier to construct some Entity prefab types. protected internal void Initialize(EntityCollidable collisionInformation) { CollisionInformation = collisionInformation; BecomeKinematic(); collisionInformation.Entity = this; }
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)); Vector3[] corners = boundingBox.GetCorners(); var textureCoords = new Vector2[4]; textureCoords[0] = new Vector2(0, 0); textureCoords[1] = new Vector2(1, 0); textureCoords[2] = new Vector2(1, 1); textureCoords[3] = new Vector2(0, 1); vertices.Add(new VertexPositionNormalTexture(corners[0], Vector3.Backward, textureCoords[0])); vertices.Add(new VertexPositionNormalTexture(corners[1], Vector3.Backward, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[2], Vector3.Backward, textureCoords[2])); vertices.Add(new VertexPositionNormalTexture(corners[3], 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], Vector3.Right, textureCoords[0])); vertices.Add(new VertexPositionNormalTexture(corners[2], Vector3.Right, textureCoords[3])); vertices.Add(new VertexPositionNormalTexture(corners[5], Vector3.Right, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[6], 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], Vector3.Forward, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[5], Vector3.Forward, textureCoords[0])); vertices.Add(new VertexPositionNormalTexture(corners[6], Vector3.Forward, textureCoords[3])); vertices.Add(new VertexPositionNormalTexture(corners[7], 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], Vector3.Left, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[3], Vector3.Left, textureCoords[2])); vertices.Add(new VertexPositionNormalTexture(corners[4], Vector3.Left, textureCoords[0])); vertices.Add(new VertexPositionNormalTexture(corners[7], 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], Vector3.Up, textureCoords[2])); vertices.Add(new VertexPositionNormalTexture(corners[1], Vector3.Up, textureCoords[3])); vertices.Add(new VertexPositionNormalTexture(corners[4], Vector3.Up, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[5], 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], Vector3.Down, textureCoords[1])); vertices.Add(new VertexPositionNormalTexture(corners[3], Vector3.Down, textureCoords[0])); vertices.Add(new VertexPositionNormalTexture(corners[6], Vector3.Down, textureCoords[2])); vertices.Add(new VertexPositionNormalTexture(corners[7], Vector3.Down, textureCoords[3])); indices.Add(21); indices.Add(20); indices.Add(22); indices.Add(21); indices.Add(22); indices.Add(23); }
private void Events_CollisionEnded(EntityCollidable sender, Collidable other, CollidablePairHandler pair) { _sound.RollStop(); }