void Events_InitialCollisionDetected(EntityCollidable sender, Collidable other, CollidablePairHandler pair) { if ("Environment".Equals(other.Tag)) { // do something on collision } }
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<BEPUutilities.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 = MathConverter.Convert(BEPUutilities.Vector3.Normalize(BEPUutilities.Vector3.Cross(hullTriangleVertices[i + 2] - hullTriangleVertices[i], hullTriangleVertices[i + 1] - hullTriangleVertices[i]))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i]), normal, new Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i + 1]), normal, new Vector2(1, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i + 2]), normal, new Vector2(0, 1))); indices.Add(i); indices.Add((ushort)(i + 1)); indices.Add((ushort)(i + 2)); } }
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 BEPUutilities.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<BEPUutilities.Vector3>(); foreach (int i in hullIndices) { hullTriangleVertices.Add(vertexPositions[i]); } for (ushort i = 0; i < hullTriangleVertices.Count; i += 3) { Vector3 normal = MathConverter.Convert(BEPUutilities.Vector3.Normalize(BEPUutilities.Vector3.Cross(hullTriangleVertices[i + 2] - hullTriangleVertices[i], hullTriangleVertices[i + 1] - hullTriangleVertices[i]))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i]), normal, new Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i + 1]), normal, new Vector2(1, 0))); vertices.Add(new VertexPositionNormalTexture(MathConverter.Convert(hullTriangleVertices[i + 2]), normal, new Vector2(0, 1))); indices.Add(i); indices.Add((ushort)(i + 1)); indices.Add((ushort)(i + 2)); } }
internal CompoundChild(CompoundShape shape, EntityCollidable collisionInformation, Material material, int index) { this.shape = shape; this.collisionInformation = collisionInformation; Material = material; this.shapeIndex = index; }
private void CollisionDetectedHandler(EntityCollidable sender, Collidable other, CollidablePairHandler pair) { EntityCollidable otherEntityCollidable = other as EntityCollidable; Terrain otherTerrain = other as Terrain; if (otherEntityCollidable != null && otherEntityCollidable.Entity != null && otherEntityCollidable.Entity.Tag != null) { int actorId = (int)(otherEntityCollidable.Entity.Tag); if (actorId == mOwnerActorId) return; Actor actorHit = GameResources.ActorManager.GetActorById(actorId); IDamagable damage = actorHit.GetBehaviorThatImplementsType<IDamagable>(); if (damage != null) { damage.TakeDamage(mDamage); } Impact(); } else if (otherTerrain != null) { Impact(); } }
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)); } RigidTransform localTransform = child.Entry.LocalTransform; Vector3 localPosition = child.CollisionInformation.LocalPosition; for (int j = 0; j < tempVertices.Count; j++) { VertexPositionNormalTexture vertex = tempVertices[j]; Vector3.Add(ref vertex.Position, ref localPosition, out vertex.Position); RigidTransform.Transform(ref vertex.Position, ref localTransform, out vertex.Position); Vector3.Transform(ref vertex.Normal, ref localTransform.Orientation, out vertex.Normal); vertices.Add(vertex); } tempVertices.Clear(); tempIndices.Clear(); } } }
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)); } }
public void InitialCollisionDetected(EntityCollidable sender, Collidable other, CollidablePairHandler collisionPair) { if (other == acceptedTrigger) { //If the detector collided with the accepted trigger, move the box. movedBox.Position = new Vector3(4, 5, 0); movedBox.Orientation = Quaternion.Identity; movedBox.LinearVelocity = Vector3.Zero; movedBox.AngularVelocity = Vector3.Zero; } }
private void Events_InitialCollisionDetected(BEPUphysics.BroadPhaseEntries.MobileCollidables.EntityCollidable sender, BEPUphysics.BroadPhaseEntries.Collidable other, BEPUphysics.NarrowPhaseSystems.Pairs.CollidablePairHandler pair) { Console.WriteLine(duckID + " Duck Collision"); var otherEntityInformation = other as EntityCollidable; string tag = (string)otherEntityInformation.Entity.Tag; // don't remove if it hits any of the packs if (!tag.Contains("fuelPack") && !tag.Contains("torpedoPack")) { RemoveFromGame(); } }
private void InitialCollisionDetectedHandler(EntityCollidable sender, Collidable other, CollidablePairHandler pair) { EntityCollidable otherEntityCollidable = other as EntityCollidable; if (otherEntityCollidable != null && otherEntityCollidable.Entity != null && otherEntityCollidable.Entity.Tag != null && mTriggerSet && GameResources.ActorManager.IsPlayer((int)(otherEntityCollidable.Entity.Tag))) { mTriggerSet = false; GameResources.LoadNewLevelDelegate(mLevelName); } }
private void Events_InitialCollisionDetected(BEPUphysics.BroadPhaseEntries.MobileCollidables.EntityCollidable sender, BEPUphysics.BroadPhaseEntries.Collidable other, BEPUphysics.NarrowPhaseSystems.Pairs.CollidablePairHandler pair) { // issues with motion upon impact with other objects Console.WriteLine("Ship Collision"); var otherEntityInformation = other as EntityCollidable; string tag = (string)otherEntityInformation.Entity.Tag; if (tag.Contains("duck")) { Console.WriteLine("Hit DUCK"); if (!shieldActive) { health -= duckDamage; generalInfoMessage = "DAMAGE TAKEN"; } } if (tag.Equals("turtle")) { Console.WriteLine("Hit Turtle"); if (Vector3.Distance(linearVelocity, maxVelocityToWin) <= 2f) { conclusionMessage = "You successfully claimed the sacred Turtle!"; } else { conclusionMessage = "Your ship was going too fast! Failed to safely aquire the Turtle."; } } if (tag.Contains("fuelPack")) { float newValue = fuelLevel + fuelPackValue; // can't go over 100 fuel if (newValue > 100) { fuelLevel = 100; } else { fuelLevel = newValue; } generalInfoMessage = "FUEL PACK AQUIRED "; } if (tag.Contains("torpedoPack")) { // TODO - broken // AddTorpedo(); generalInfoMessage = "TORPEDO PACK AQUIRED"; } }
public static void GetShapeMeshData(EntityCollidable collidable, List<VertexPositionNormalTexture> vertices, List<ushort> indices) { ConeShape coneShape = collidable.Shape as ConeShape; if (coneShape == null) throw new ArgumentException("Wrong shape type."); float verticalOffset = -coneShape.Height / 4; float angleBetweenFacets = MathHelper.TwoPi / NumSides; float radius = coneShape.Radius; //Create the vertex list var topVertexPosition = new Vector3(0, coneShape.Height + verticalOffset, 0); for (int i = 0; i < NumSides; i++) { float theta = i * angleBetweenFacets; var position = new Vector3((float)Math.Cos(theta) * radius, verticalOffset, (float)Math.Sin(theta) * radius); Vector3 offset = topVertexPosition - position; Vector3 normal = Vector3.Normalize(Vector3.Cross(Vector3.Cross(offset, Vector3.Up), offset)); //Top vertex vertices.Add(new VertexPositionNormalTexture(topVertexPosition, normal, Vector2.Zero)); //Sloped vertices vertices.Add(new VertexPositionNormalTexture(position, normal, Vector2.Zero)); //Bottom vertices vertices.Add(new VertexPositionNormalTexture(position, Vector3.Down, Vector2.Zero)); } //Create the index list for (ushort i = 0; i < vertices.Count; i += 3) { //Each iteration, the loop advances to the next vertex 'column.' //Four triangles per column (except for the four degenerate cap triangles). //Sloped Triangles indices.Add(i); indices.Add((ushort)(i + 1)); indices.Add((ushort)((i + 4) % vertices.Count)); //Bottom cap triangles. var nextIndex = (ushort)((i + 5) % vertices.Count); if (nextIndex != 2) //Don't add cap indices if it's going to be a degenerate triangle. { indices.Add((ushort)(i + 2)); indices.Add(2); indices.Add(nextIndex); } } }
private void InitialCollisionDetectedHandler(EntityCollidable sender, Collidable other, CollidablePairHandler pair) { EntityCollidable otherEntityCollidable = other as EntityCollidable; if (otherEntityCollidable != null && otherEntityCollidable.Entity != null && otherEntityCollidable.Entity.Tag != null && mTriggerSet && GameResources.ActorManager.IsPlayer((int)(otherEntityCollidable.Entity.Tag))) { PlayerView finder = GameResources.ActorManager.GetPlayerViewOfAvatar((int)(otherEntityCollidable.Entity.Tag)); finder.AvatarDesc.ObtainItem(Item); mTriggerSet = false; Owner.Despawn(); } }
private void Events_InitialCollisionDetected(BEPUphysics.BroadPhaseEntries.MobileCollidables.EntityCollidable sender, BEPUphysics.BroadPhaseEntries.Collidable other, BEPUphysics.NarrowPhaseSystems.Pairs.CollidablePairHandler pair) { Console.WriteLine(fuelPackID + " FuellPack Collision"); var otherEntityInformation = other as EntityCollidable; string tag = (string)otherEntityInformation.Entity.Tag; // only remove object if comes in contact with the ship if (tag.Equals("ship")) { if (Game.Components.Contains(this)) { RemoveFromGame(); } } }
private void Events_InitialCollisionDetected(BEPUphysics.BroadPhaseEntries.MobileCollidables.EntityCollidable sender, BEPUphysics.BroadPhaseEntries.Collidable other, BEPUphysics.NarrowPhaseSystems.Pairs.CollidablePairHandler pair) { Console.WriteLine(torpedoID + " Collision"); var otherEntityInformation = other as EntityCollidable; string tag = (string)otherEntityInformation.Entity.Tag; // hitting the ship doesn't remove the torpedo (would interfer with firing logic if (!tag.Equals("ship")) { if (Game.Components.Contains(this)) { RemoveFromGame(); } } }
protected void TryToAdd(EntityCollidable collidable) { CollisionRule rule; if ((rule = CollisionRules.collisionRuleCalculator(DetectorVolume, collidable)) < CollisionRule.NoNarrowPhasePair) { //Clamp the rule to the parent's rule. Always use the more restrictive option. //Don't have to test for NoNarrowPhasePair rule on the parent's rule because then the parent wouldn't exist! if (rule < CollisionRule) rule = CollisionRule; if (!subPairs.ContainsKey(collidable)) { var newPair = NarrowPhaseHelper.GetPairHandler(DetectorVolume, collidable, rule) as DetectorVolumePairHandler; if (newPair != null) { newPair.Parent = this; subPairs.Add(collidable, newPair); } } containedPairs.Add(collidable); } }
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."); Vector3 normal = triangleShape.GetLocalNormal(); vertices.Add(new VertexPositionNormalTexture(triangleShape.VertexA, -normal, new Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(triangleShape.VertexB, -normal, new Vector2(0, 1))); vertices.Add(new VertexPositionNormalTexture(triangleShape.VertexC, -normal, new Vector2(1, 0))); vertices.Add(new VertexPositionNormalTexture(triangleShape.VertexA, normal, new Vector2(0, 0))); vertices.Add(new VertexPositionNormalTexture(triangleShape.VertexB, normal, new Vector2(0, 1))); vertices.Add(new VertexPositionNormalTexture(triangleShape.VertexC, normal, new Vector2(1, 0))); indices.Add(0); indices.Add(1); indices.Add(2); indices.Add(3); indices.Add(5); indices.Add(4); }
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++) { BEPUutilities.Vector3 position; shape.TriangleMesh.Data.GetVertexPosition(i, out position); tempVertices[i] = new VertexPositionNormalTexture( MathConverter.Convert(position), Vector3.Zero, 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]; Vector3 normal = Vector3.Normalize(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> /// Finds contacts between the query object and any intersected objects within the character's bounding box. /// </summary> /// <param name="queryObject">Collidable to query for contacts with.</param> /// <param name="tractionContacts">Output contacts that would provide traction.</param> /// <param name="supportContacts">Output contacts that would provide support.</param> /// <param name="sideContacts">Output contacts on the sides of the query object.</param> /// <param name="headContacts">Output contacts on the head of the query object.</param> public void QueryContacts(EntityCollidable queryObject, ref QuickList<CharacterContact> tractionContacts, ref QuickList<CharacterContact> supportContacts, ref QuickList<CharacterContact> sideContacts, ref QuickList<CharacterContact> headContacts) { var downDirection = characterBody.orientationMatrix.Down; tractionContacts.Clear(); supportContacts.Clear(); sideContacts.Clear(); headContacts.Clear(); foreach (var collidable in characterBody.CollisionInformation.OverlappedCollidables) { //The query object is assumed to have a valid bounding box. if (collidable.BoundingBox.Intersects(queryObject.BoundingBox)) { var pair = new CollidablePair(collidable, queryObject); var pairHandler = NarrowPhaseHelper.GetPairHandler(ref pair); if (pairHandler.CollisionRule == CollisionRule.Normal) { pairHandler.SuppressEvents = true; pairHandler.UpdateCollision(0); pairHandler.SuppressEvents = false; contactCategorizer.CategorizeContacts(pairHandler, characterBody.CollisionInformation, ref downDirection, ref tractionContacts, ref supportContacts, ref sideContacts, ref headContacts); } //TODO: It would be nice if this was a bit easier. //Having to remember to clean up AND give it back is a bit weird, especially with the property-diving. //No one would ever just guess this correctly. //At least hide it behind a NarrowPhaseHelper function. pairHandler.CleanUp(); pairHandler.Factory.GiveBack(pairHandler); } } }
void QueryContacts(Vector3 position, EntityCollidable queryObject) { ClearContacts(); //Update the position and orientation of the query object. RigidTransform transform; transform.Position = position; transform.Orientation = character.Body.Orientation; queryObject.UpdateBoundingBoxForTransform(ref transform, 0); foreach (var collidable in character.Body.CollisionInformation.OverlappedCollidables) { if (collidable.BoundingBox.Intersects(queryObject.BoundingBox)) { var pair = new CollidablePair(collidable, queryObject); var pairHandler = NarrowPhaseHelper.GetPairHandler(ref pair); if (pairHandler.CollisionRule == CollisionRule.Normal) { pairHandler.SuppressEvents = true; pairHandler.UpdateCollision(0); pairHandler.SuppressEvents = false; foreach (var contact in pairHandler.Contacts) { //Must check per-contact collision rules, just in case //the pair was actually a 'parent pair.' if (contact.Pair.CollisionRule == CollisionRule.Normal) { ContactData contactData; contactData.Position = contact.Contact.Position; contactData.Normal = contact.Contact.Normal; contactData.Id = contact.Contact.Id; contactData.PenetrationDepth = contact.Contact.PenetrationDepth; contacts.Add(contactData); } } } //TODO: It would be nice if this was a bit easier. //Having to remember to clean up AND give it back is a bit weird, especially with the property-diving. //No one would ever just guess this correctly. //At least hide it behind a NarrowPhaseHelper function. pairHandler.CleanUp(); pairHandler.Factory.GiveBack(pairHandler); } } CategorizeContacts(ref position); }
private void PrepareQueryObject(EntityCollidable queryObject, ref Vector3 position) { RigidTransform transform; transform.Position = position; transform.Orientation = characterBody.Orientation; queryObject.UpdateBoundingBoxForTransform(ref transform, 0); }
public void CollisionEnded(EntityCollidable sender, Collidable other, CollidablePairHandler collisionPair) { if (other == acceptedTrigger) { //If the detector ceases to collide, get rid of the spawned box. movedBox.Position = new Vector3(-4, 5, 0); movedBox.Orientation = Quaternion.Identity; movedBox.LinearVelocity = Vector3.Zero; movedBox.AngularVelocity = Vector3.Zero; } }
float GetSubmergedHeight(EntityCollidable collidable, float maxLength, float boundingBoxHeight, ref System.Numerics.Vector3 rayOrigin, ref System.Numerics.Vector3 xSpacing, ref System.Numerics.Vector3 zSpacing, int i, int j, out System.Numerics.Vector3 volumeCenter) { Ray ray; Vector3Ex.Multiply(ref xSpacing, i, out ray.Position); Vector3Ex.Multiply(ref zSpacing, j, out ray.Direction); Vector3Ex.Add(ref ray.Position, ref ray.Direction, out ray.Position); Vector3Ex.Add(ref ray.Position, ref rayOrigin, out ray.Position); ray.Direction = upVector; //do a bottom-up raycast. RayHit rayHit; //Only go up to maxLength. If it's further away than maxLength, then it's above the water and it doesn't contribute anything. if (collidable.RayCast(ray, maxLength, out rayHit)) { //Position the ray to point from the other side. Vector3Ex.Multiply(ref ray.Direction, boundingBoxHeight, out ray.Direction); Vector3Ex.Add(ref ray.Position, ref ray.Direction, out ray.Position); Vector3Ex.Negate(ref upVector, out ray.Direction); //Transform the hit into local space. RigidTransform.TransformByInverse(ref rayHit.Location, ref surfaceTransform, out rayHit.Location); float bottomY = rayHit.Location.Y; float bottom = rayHit.T; System.Numerics.Vector3 bottomPosition = rayHit.Location; if (collidable.RayCast(ray, boundingBoxHeight - rayHit.T, out rayHit)) { //Transform the hit into local space. RigidTransform.TransformByInverse(ref rayHit.Location, ref surfaceTransform, out rayHit.Location); Vector3Ex.Add(ref rayHit.Location, ref bottomPosition, out volumeCenter); Vector3Ex.Multiply(ref volumeCenter, .5f, out volumeCenter); return Math.Min(-bottomY, boundingBoxHeight - rayHit.T - bottom); } //This inner raycast should always hit, but just in case it doesn't due to some numerical problem, give it a graceful way out. volumeCenter = System.Numerics.Vector3.Zero; return 0; } volumeCenter = System.Numerics.Vector3.Zero; return 0; }
void GetBuoyancyInformation(EntityCollidable collidable, out float submergedVolume, out System.Numerics.Vector3 submergedCenter) { BoundingBox entityBoundingBox; RigidTransform localTransform; RigidTransform.MultiplyByInverse(ref collidable.worldTransform, ref surfaceTransform, out localTransform); collidable.Shape.GetBoundingBox(ref localTransform, out entityBoundingBox); if (entityBoundingBox.Min.Y > 0) { //Fish out of the water. Don't need to do raycast tests on objects not at the boundary. submergedVolume = 0; submergedCenter = collidable.worldTransform.Position; return; } if (entityBoundingBox.Max.Y < 0) { submergedVolume = collidable.entity.CollisionInformation.Shape.Volume; submergedCenter = collidable.worldTransform.Position; return; } System.Numerics.Vector3 origin, xSpacing, zSpacing; float perColumnArea; GetSamplingOrigin(ref entityBoundingBox, out xSpacing, out zSpacing, out perColumnArea, out origin); float boundingBoxHeight = entityBoundingBox.Max.Y - entityBoundingBox.Min.Y; float maxLength = -entityBoundingBox.Min.Y; submergedCenter = new System.Numerics.Vector3(); submergedVolume = 0; for (int i = 0; i < samplePointsPerDimension; i++) { for (int j = 0; j < samplePointsPerDimension; j++) { System.Numerics.Vector3 columnVolumeCenter; float submergedHeight; if ((submergedHeight = GetSubmergedHeight(collidable, maxLength, boundingBoxHeight, ref origin, ref xSpacing, ref zSpacing, i, j, out columnVolumeCenter)) > 0) { float columnVolume = submergedHeight * perColumnArea; Vector3Ex.Multiply(ref columnVolumeCenter, columnVolume, out columnVolumeCenter); Vector3Ex.Add(ref columnVolumeCenter, ref submergedCenter, out submergedCenter); submergedVolume += columnVolume; } } } Vector3Ex.Divide(ref submergedCenter, submergedVolume, out submergedCenter); //Pull the submerged center into world space before applying the force. RigidTransform.Transform(ref submergedCenter, ref surfaceTransform, out submergedCenter); }
///<summary> /// Constructs a new kinematic entity. ///</summary> ///<param name="collisionInformation">Collidable to use with the entity.</param> public Entity(EntityCollidable collisionInformation) : this() { Initialize(collisionInformation); }
protected internal void Initialize(EntityCollidable collisionInformation, float mass) { CollisionInformation = collisionInformation; if (mass > 0) { ShapeDistributionInformation shapeInfo; collisionInformation.Shape.ComputeDistributionInformation(out shapeInfo); Matrix3x3.Multiply(ref shapeInfo.VolumeDistribution, mass * InertiaHelper.InertiaTensorScale, out shapeInfo.VolumeDistribution); volume = shapeInfo.Volume; BecomeDynamic(mass, shapeInfo.VolumeDistribution); } else { volume = collisionInformation.Shape.ComputeVolume(); BecomeKinematic(); } collisionInformation.Entity = this; }
protected internal void Initialize(EntityCollidable collisionInformation, float mass, Matrix3x3 inertiaTensor) { CollisionInformation = collisionInformation; if (mass > 0) BecomeDynamic(mass, inertiaTensor); else BecomeKinematic(); collisionInformation.Entity = this; }
protected internal void Initialize(EntityCollidable collisionInformation, float mass) { CollisionInformation = collisionInformation; if (mass > 0) { BecomeDynamic(mass, collisionInformation.Shape.VolumeDistribution * (mass * InertiaHelper.InertiaTensorScale)); } else { BecomeKinematic(); } collisionInformation.Entity = this; }
//These initialize methods make it easier to construct some Entity prefab types. protected internal void Initialize(EntityCollidable collisionInformation) { CollisionInformation = collisionInformation; BecomeKinematic(); collisionInformation.Entity = this; }
///<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); }
///<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); }
protected internal void Initialize(EntityCollidable collisionInformation, float mass, Matrix3x3 inertiaTensor, float volume) { CollisionInformation = collisionInformation; this.volume = volume; BecomeDynamic(mass, inertiaTensor); collisionInformation.Entity = this; }
void RemoveFriction(EntityCollidable sender, BroadPhaseEntry other, NarrowPhasePair pair) { var collidablePair = pair as CollidablePairHandler; if (collidablePair != null) { //The default values for InteractionProperties is all zeroes- zero friction, zero bounciness. //That's exactly how we want the character to behave when hitting objects. collidablePair.UpdateMaterialProperties(new InteractionProperties()); } }
void GetBuoyancyInformation(EntityCollidable info, out float submergedVolume, out Vector3 submergedCenter) { BoundingBox entityBoundingBox; entityBoundingBox = info.BoundingBox;// new BoundingBox(); //info.ComputeBoundingBox(ref surfaceOrientationTranspose, out entityBoundingBox); if (entityBoundingBox.Min.Y > surfacePlaneHeight) { //Fish out of the water. Don't need to do raycast tests on objects not at the boundary. submergedVolume = 0; submergedCenter = info.WorldTransform.Position; return; } if (entityBoundingBox.Max.Y < surfacePlaneHeight) { submergedVolume = info.Entity.Volume; submergedCenter = info.WorldTransform.Position; return; } Vector3 origin, xSpacing, zSpacing; float perColumnArea; GetSamplingOrigin(ref entityBoundingBox, out xSpacing, out zSpacing, out perColumnArea, out origin); float boundingBoxHeight = entityBoundingBox.Max.Y - entityBoundingBox.Min.Y; float maxLength = surfacePlaneHeight - entityBoundingBox.Min.Y; submergedCenter = new Vector3(); submergedVolume = 0; for (int i = 0; i < samplePointsPerDimension; i++) { for (int j = 0; j < samplePointsPerDimension; j++) { Vector3 columnVolumeCenter; float submergedHeight; if ((submergedHeight = GetSubmergedHeight(info, maxLength, boundingBoxHeight, ref origin, ref xSpacing, ref zSpacing, i, j, out columnVolumeCenter)) > 0) { float columnVolume = submergedHeight * perColumnArea; Vector3.Multiply(ref columnVolumeCenter, columnVolume, out columnVolumeCenter); Vector3.Add(ref columnVolumeCenter, ref submergedCenter, out submergedCenter); submergedVolume += columnVolume; } } } Vector3.Divide(ref submergedCenter, submergedVolume, out submergedCenter); }