void OnTriggerEnter(Collider other) { if(other.gameObject.layer == LayerMask.NameToLayer("Enemy")) { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = false; this.collision_results.Add(result); } else if(other.gameObject.layer == LayerMask.NameToLayer("EnemyLair")) { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = false; this.collision_results.Add(result); } else if(other.gameObject.layer == LayerMask.NameToLayer("Wall")) { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = false; this.collision_results.Add(result); } }
public static bool circleToCircle( Circle first, Circle second, out CollisionResult result ) { result = new CollisionResult(); // avoid the square root until we actually need it var distanceSquared = Vector2.DistanceSquared( first.position, second.position ); var sumOfRadii = first.radius + second.radius; var collided = distanceSquared < sumOfRadii * sumOfRadii; if( collided ) { result.normal = Vector2.Normalize( first.position - second.position ); var depth = sumOfRadii - Mathf.sqrt( distanceSquared ); result.minimumTranslationVector = -depth * result.normal; result.point = second.position + result.normal * second.radius; // this gets the actual point of collision which may or may not be useful so we'll leave it here for now //var collisionPointX = ( ( first.position.X * second.radius ) + ( second.position.X * first.radius ) ) / sumOfRadii; //var collisionPointY = ( ( first.position.Y * second.radius ) + ( second.position.Y * first.radius ) ) / sumOfRadii; //result.point = new Vector2( collisionPointX, collisionPointY ); return true; } return false; }
/// <summary> /// Determines if two objects have collided using Axis-Aligned Bounding Box /// </summary> /// <param name="first">The first object to check.</param> /// <param name="second">The second object to check.</param> /// <returns>True if a collision was detected, false otherwise.</returns> /// <remarks> /// https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection /// /// Ax,Ay Bx,By /// --------------- --------------- /// - - - - /// - - - - /// - - - - /// - - - - /// --------------- --------------- /// AX,AY BX,BY /// /// They are seperate if any of these statements are true: /// /// AX is less than Bx /// BX is less than Ax /// AY is less than By /// BY is less than Ay /// /// </remarks> public static CollisionResult CheckForCollision(ICollidable first, ICollidable second, Vector2 velocity) { if (first == null) { throw new ArgumentNullException("first"); } if (second == null) { throw new ArgumentNullException("second"); } Rectangle a = first.BoundingBox; Rectangle b = second.BoundingBox; //bool haveCollided = !(a.Right < b.X // || b.Right < a.X // || a.Bottom < b.Y // || b.Bottom < a.Y); bool haveCollided = (a.Right > b.X && b.Right > a.X && a.Bottom > b.Y && b.Bottom > a.Y); a.Offset(Convert.ToInt32(velocity.X), Convert.ToInt32(velocity.Y)); bool willCollided = (a.Right > b.X && b.Right > a.X && a.Bottom > b.Y && b.Bottom > a.Y); CollisionResult collisionResult = new CollisionResult(); collisionResult.HaveCollided = haveCollided; collisionResult.WillCollide = willCollided; collisionResult.CorrectionVector = null; return collisionResult; }
public override bool collidesWithShape( Shape other, out CollisionResult result ) { // special, high-performance cases. otherwise we fall back to Polygon. if( other is Box ) return ShapeCollisions.boxToBox( this, other as Box, out result ); // TODO: get Minkowski working for circle to box //if( other is Circle ) // fallthrough to standard cases return base.collidesWithShape( other, out result ); }
public override bool collidesWithShape( Shape other, out CollisionResult result ) { if( other is Box ) return ShapeCollisions.circleToBox( this, other as Box, out result ); if( other is Circle ) return ShapeCollisions.circleToCircle( this, other as Circle, out result ); if( other is Polygon ) return ShapeCollisions.circleToPolygon( this, other as Polygon, out result ); throw new NotImplementedException( string.Format( "Collisions of Circle to {0} are not supported", other ) ); }
public static bool pointToBox( Vector2 point, Box box, out CollisionResult result ) { result = new CollisionResult(); if( box.containsPoint( point ) ) { // get the point in the space of the Box result.point = box.bounds.getClosestPointOnRectangleBorderToPoint( point, out result.normal ); result.minimumTranslationVector = point - result.point; return true; } return false; }
/// <summary> /// Crear inicializado /// </summary> public ElipsoidCollisionManager() { gravityEnabled = true; gravityForce = new Vector3(0, -10, 0); slideFactor = 1.3f; movementSphere = new TgcBoundingSphere(); eSphere = new TgcBoundingSphere(); objetosCandidatos = new List<Collider>(); onGroundMinDotValue = 0.72f; result = new CollisionResult(); result.collisionFound = false; result.collisionNormal = Vector3.Empty; result.collisionPoint = Vector3.Empty; result.realMovmentVector = Vector3.Empty; }
public override bool collidesWithShape( Shape other, out CollisionResult result ) { if( other is Polygon ) return ShapeCollisions.polygonToPolygon( this, other as Polygon, out result ); if( other is Circle ) { if( ShapeCollisions.circleToPolygon( other as Circle, this, out result ) ) { result.invertResult(); return true; } return false; } throw new NotImplementedException( string.Format( "overlaps of Polygon to {0} are not supported", other ) ); }
public static bool pointToPoly( Vector2 point, Polygon poly, out CollisionResult result ) { result = new CollisionResult(); if( poly.containsPoint( point ) ) { float distanceSquared; var closestPoint = Polygon.getClosestPointOnPolygonToPoint( poly.points, point - poly.position, out distanceSquared, out result.normal ); result.minimumTranslationVector = result.normal * Mathf.sqrt( distanceSquared ); result.point = closestPoint + poly.position; return true; } return false; }
// 컬리전에 히트하는 동안 호출되는 메소드. void OnCollisionStay(Collision other) { switch(other.gameObject.tag) { case "Item": case "Enemy": case "Boss": { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = false; CollisionManager.getInstance().results.Add(result); } break; } }
public static bool pointToCircle( Vector2 point, Circle circle, out CollisionResult result ) { result = new CollisionResult(); // avoid the square root until we actually need it var distanceSquared = Vector2.DistanceSquared( point, circle.position ); var sumOfRadii = 1 + circle.radius; var collided = distanceSquared < sumOfRadii * sumOfRadii; if( collided ) { result.normal = Vector2.Normalize( point - circle.position ); var depth = sumOfRadii - Mathf.sqrt( distanceSquared ); result.minimumTranslationVector = -depth * result.normal; result.point = circle.position + result.normal * circle.radius; return true; } return false; }
public static bool pointToPoly(Vector2 point, Polygon poly, out CollisionResult result) { result = new CollisionResult(); if (poly.containsPoint(point)) { float distanceSquared; var closestPoint = Polygon.getClosestPointOnPolygonToPoint( poly.points, point - poly.position, out distanceSquared, out result.normal); result.minimumTranslationVector = result.normal * Mathf.sqrt(distanceSquared); result.point = closestPoint + poly.position; return(true); } return(false); }
public static bool PointToCircle(Vector2 point, Circle circle, out CollisionResult result) { result = new CollisionResult(); // avoid the square root until we actually need it var distanceSquared = Vector2.DistanceSquared(point, circle.position); var sumOfRadii = 1 + circle.Radius; var collided = distanceSquared < sumOfRadii * sumOfRadii; if (collided) { result.Normal = Vector2.Normalize(point - circle.position); var depth = sumOfRadii - Mathf.Sqrt(distanceSquared); result.MinimumTranslationVector = -depth * result.Normal; result.Point = circle.position + result.Normal * circle.Radius; return(true); } return(false); }
public static bool boxToBox( Box first, Box second, out CollisionResult result ) { result = new CollisionResult(); var minkowskiDiff = minkowskiDifference( first, second ); if( minkowskiDiff.contains( 0f, 0f ) ) { // calculate the MTV. if it is zero then we can just call this a non-collision result.minimumTranslationVector = minkowskiDiff.getClosestPointOnBoundsToOrigin(); if( result.minimumTranslationVector == Vector2.Zero ) return false; result.normal = -result.minimumTranslationVector; result.normal.Normalize(); return true; } return false; }
/// <summary> /// tank's A.I. function. /// moves to the position and stops when collides with others. /// </summary> /// <param name="aiBase">current A.I.</param> /// <param name="gameTime"></param> public override void OnAIMoveEvent(AIBase aiBase, GameTime gameTime) { if (aiBase.IsActive) { Vector3 vMoveVelocity = new Vector3(0.0f, 0.0f, SpecData.MoveSpeed); CollisionResult result = MoveHitTest(gameTime, vMoveVelocity); if (result != null) { if (GameSound.IsPlaying(soundMove)) { GameSound.Stop(soundMove); } MoveStop(); // Cannot move } else { Move(vMoveVelocity); if (!GameSound.IsPlaying(soundMove)) { soundMove = GameSound.Play3D(SoundTrack.TankMove, this); } } } else { if (GameSound.IsPlaying(soundMove)) { GameSound.Stop(soundMove); } MoveStop(); turretAngleSpeed = 0.0f; SetNextAI(AIType.Search, HelperMath.RandomNormal()); } }
public static bool SphereOverlapSingle(EntityManager entityManager, Entity entity, int tick, sphere sphere, ref CollisionResult result) { var collData = entityManager.GetComponentData <HitCollisionData>(entity); var histIndex = collData.GetHistoryIndex(tick); var transformBuffer = entityManager.GetBuffer <TransformHistory>(entity); var sphereArray = entityManager.GetBuffer <Sphere>(entity); var capsuleArray = entityManager.GetBuffer <Capsule>(entity); var boxArray = entityManager.GetBuffer <Box>(entity); var resultArray = new NativeArray <CollisionResult>(1, Allocator.TempJob); var job = new SphereOverlapJob { transformBuffer = new NativeSlice <TransformHistory>(transformBuffer.ToNativeArray(Allocator.TempJob), histIndex * k_maxColliderCount), sphereArray = sphereArray.ToNativeArray(Allocator.TempJob), capsuleArray = capsuleArray.ToNativeArray(Allocator.TempJob), boxArray = boxArray.ToNativeArray(Allocator.TempJob), sphere = sphere, result = resultArray, }; var handle = job.Schedule(); handle.Complete(); result = resultArray[0]; //if(math.length(result.box.size) > 0) // DebugDraw.Prim(result.box, Color.red, 1); //if(result.capsule.radius > 0) // DebugDraw.Prim(result.capsule, Color.red, 1); //if(result.sphere.radius > 0) // DebugDraw.Prim(result.sphere, Color.red, 1); resultArray.Dispose(); return(result.hit == 1); }
/// <summary> /// works for circles whos center is in the box as well as just overlapping with the center out of the box. /// </summary> /// <returns><c>true</c>, if to box was circled, <c>false</c> otherwise.</returns> /// <param name="circle">First.</param> /// <param name="box">Second.</param> /// <param name="result">Result.</param> public static bool CircleToBox(Circle circle, Box box, out CollisionResult result) { result = new CollisionResult(); var closestPointOnBounds = box.bounds.GetClosestPointOnRectangleBorderToPoint(circle.position, out result.Normal); // deal with circles whos center is in the box first since its cheaper to see if we are contained if (box.ContainsPoint(circle.position)) { result.Point = closestPointOnBounds; // calculate mtv. Find the safe, non-collided position and get the mtv from that. var safePlace = closestPointOnBounds + result.Normal * circle.Radius; result.MinimumTranslationVector = circle.position - safePlace; return(true); } float sqrDistance = System.Numerics.Vector2.DistanceSquared(closestPointOnBounds, circle.position); // see if the point on the box is less than radius from the circle if (sqrDistance == 0) { result.MinimumTranslationVector = result.Normal * circle.Radius; } else if (sqrDistance <= circle.Radius * circle.Radius) { result.Normal = circle.position - closestPointOnBounds; var depth = result.Normal.Length() - circle.Radius; result.Point = closestPointOnBounds; Vector2Ext.Normalize(ref result.Normal); result.MinimumTranslationVector = depth * result.Normal; return(true); } return(false); }
/// <summary> /// works for circles whos center is in the box as well as just overlapping with the center out of the box. /// </summary> /// <returns><c>true</c>, if to box was circled, <c>false</c> otherwise.</returns> /// <param name="circle">First.</param> /// <param name="box">Second.</param> /// <param name="result">Result.</param> public static bool circleToBox( Circle circle, Box box, out CollisionResult result ) { result = new CollisionResult(); var closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint( circle.position, out result.normal ); // deal with circles whos center is in the box first since its cheaper to see if we are contained if( box.containsPoint( circle.position ) ) { result.point = closestPointOnBounds; // calculate mtv. Find the safe, non-collided position and get the mtv from that. var safePlace = closestPointOnBounds + result.normal * circle.radius; result.minimumTranslationVector = circle.position - safePlace; return true; } float sqrDistance; Vector2.DistanceSquared( ref closestPointOnBounds, ref circle.position, out sqrDistance ); // see if the point on the box is less than radius from the circle if( sqrDistance == 0 ) { result.minimumTranslationVector = result.normal * circle.radius; } else if( sqrDistance <= circle.radius * circle.radius ) { result.normal = circle.position - closestPointOnBounds; var depth = result.normal.Length() - circle.radius; result.point = closestPointOnBounds; Vector2Ext.normalize( ref result.normal ); result.minimumTranslationVector = depth * result.normal; return true; } return false; }
private SceneIntersectResult SceneIntersect(RayEntity rayEntity, float?distanceMax = null) { CollisionResult collisionRef = null; float? distanceMin = null; IEssence essenceRef = null; foreach (var essence in essences) { var collision = essence.CheckCollision(rayEntity); if (collision == null) { continue; } var distance = (rayEntity.Origin - collision.Point).Length(); if (distanceMax != null && distanceMax < distance) { continue; } if (distanceMin == null ^ distanceMin > distance) { distanceMin = distance; essenceRef = essence; collisionRef = collision; } } if (essenceRef == null) { return(null); } return(new SceneIntersectResult() { Essence = essenceRef, Collision = collisionRef }); }
/// <summary> /// Checks wheter the cannon collides with an object horizontally and bounces it when it does. /// </summary> /// <param name="other"></param> public void CheckBounce(SpriteGameObject other) { if (!carriage.CollidesWith(other)) { return; } CollisionResult side = carriage.CollisionSide(other); switch (side) { case CollisionResult.LEFT: position.X = other.Position.X + other.Width + carriage.Center.X; break; case CollisionResult.RIGHT: position.X = other.Position.X - carriage.Center.X; break; } // flip and decrease velocity by 70% velocity.X = velocity.X * -0.30f; }
public void Collide(float s, PhysicsGroupType groupType, ICollide other) { if (groupType == PhysicsGroupType.Physical) { for (int i = bullets.Count - 1; i >= 0; i--) { Circle bullet = bullets[i]; CollisionResult bulletCollision = other.Collide(s, groupType, bullet, bulletIdentity); if (bulletCollision) { bullets.RemoveAt(i); //bullet.Position = bulletCollision.PositionB; //bullet.Velocity = bulletCollision.VelocityB; } } CollisionResult result = other.Collide(s, groupType, collision, null); if (result) { takeDamage(result.Identity); } } }
void OnCollisionStay(Collision other) { switch (other.gameObject.tag) { case "Player": { chrBehaviorPlayer player = other.gameObject.GetComponent <chrBehaviorPlayer>(); if (player != null) { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = false; this.collision_results.Add(result); } } break; } }
public static bool circleToPolygon(Circle circle, Polygon polygon, out CollisionResult result) { result = new CollisionResult(); // circle position in the polygons coordinates var poly2Circle = circle.position - polygon.position; // first, we need to find the closest distance from the circle to the polygon float distanceSquared; var closestPoint = polygon.getClosestPointOnPolygonToPoint(poly2Circle, out distanceSquared, out result.normal); // make sure the squared distance is less than our radius squared else we are not colliding. Note that if the Circle is fully // contained in the Polygon the distance could be larger than the radius. Because of that we also make sure the circle position // is not inside the poly. var circleCenterInsidePoly = polygon.containsPoint(circle.position); if (distanceSquared > circle.radius * circle.radius && !circleCenterInsidePoly) { return(false); } // figure out the mtv. We have to be careful to deal with circles fully contained in the polygon or with their center contained. Vector2 mtv; if (circleCenterInsidePoly) { mtv = result.normal * (Mathf.sqrt(distanceSquared) + circle.radius); } else { var distance = Mathf.sqrt(distanceSquared); mtv = (poly2Circle - closestPoint) * ((circle.radius - distance) / distance); } result.minimumTranslationVector = -mtv; result.point = closestPoint + polygon.position; return(true); }
/// <summary> /// 检测与精灵对象是否冲突 /// </summary> /// <param name="spriteChecker"></param> /// <returns></returns> public CollisionResult CheckCollisionWithSprites(SpriteColMethod spriteChecker) { foreach (Sprite sprite in spriteChecker.ColSprites) { CollisionResult result = sprite.CheckOutBorder(borderRect); if (result.IsCollided) { float originX = result.NormalVector.X; float originY = result.NormalVector.Y; float x, y; if (Math.Abs(originX) > 0.5) { x = 1; } else { x = 0; } if (Math.Abs(originY) > 0.5) { y = 1; } else { y = 0; } x *= Math.Sign(originX); y *= Math.Sign(originY); return(new CollisionResult(result.InterPos, new Vector2(x, y))); } } return(new CollisionResult(false)); }
/// <summary> /// works for circles whos center is in the box as well as just overlapping with the center out of the box. /// </summary> /// <returns><c>true</c>, if to box was circled, <c>false</c> otherwise.</returns> /// <param name="circle">First.</param> /// <param name="box">Second.</param> /// <param name="result">Result.</param> public static bool circleToBox(Circle circle, Box box, out CollisionResult result) { result = new CollisionResult(); var closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position); // deal with circles whos center is in the box first since its cheaper to see if we are contained if (box.containsPoint(circle.position)) { result.point = closestPointOnBounds; result.normal = Vector2.Normalize(closestPointOnBounds - circle.position); // calculate mtv. Find the safe, non-collided position and get the mtv from that. var safePlace = closestPointOnBounds + result.normal * circle.radius; result.minimumTranslationVector = circle.position - safePlace; return(true); } float sqrDistance; Vector2.DistanceSquared(ref closestPointOnBounds, ref circle.position, out sqrDistance); // see if the point on the box is less than radius from the circle making sure the circle center is not in the box if (sqrDistance <= circle.radius * circle.radius) { var directionToCircle = circle.position - closestPointOnBounds; var depth = directionToCircle.Length() - circle.radius; result.point = closestPointOnBounds; result.normal = Vector2.Normalize(directionToCircle); result.minimumTranslationVector = depth * result.normal; return(true); } return(false); }
public async Task <CollisionResult> DetectCollision(IPlayerActor player, ICollection <IPlayerActor> opponents) { var collissionChecks = await Task.WhenAll(opponents .Select(opponent => IsCollidedWith(player, opponent))); var collided = collissionChecks .Where(x => x.IsCollided) .Select(x => x.Target); var sortedDictionary = new SortedDictionary <int, List <IPlayerActor> >(); foreach (var grain in collided.Append(player)) { var info = await grain.GetState(); if (!sortedDictionary.ContainsKey(info.SpriteSize)) { sortedDictionary.Add(info.SpriteSize, new List <IPlayerActor>()); } sortedDictionary[info.SpriteSize].Add(grain); } var loosers = sortedDictionary .Take(sortedDictionary.Count - 1) .SelectMany(k => k.Value) .ToList(); var winner = sortedDictionary.Count > 1 ? sortedDictionary.LastOrDefault().Value?.LastOrDefault() : null; var result = new CollisionResult { Loosers = loosers, Winner = winner, }; return(result); }
public void CheckBounce(SpriteGameObject other) { if (!this.CollidesWith(other)) { return; } CollisionResult side = this.CollisionSide(other); switch (side) { case CollisionResult.LEFT: position.X = other.Position.X + other.Width + this.Center.X; // decrease velocity by 70% velocity.X = velocity.X * Bounciness; break; case CollisionResult.RIGHT: position.X = other.Position.X - this.Center.X; // decrease velocity by 70% velocity.X = velocity.X * Bounciness; break; case CollisionResult.TOP: position.Y = other.Position.Y - this.Center.Y; // decrease velocity by 70% velocity.Y = velocity.Y * Bounciness; break; case CollisionResult.BOTTOM: position.Y = other.Position.Y - this.Center.Y + 1; // decrease velocity by 70% velocity.Y = velocity.Y * Bounciness; // add friction velocity = velocity * friction; break; } }
public void Collide(float s, PhysicsGroupType groupType, ICollide other) { if (groupType == PhysicsGroupType.Physical) { Weapon.Collide(s, groupType, other); CollisionResult playerCollision = other.Collide(s, groupType, this.collision, null); if (playerCollision) { if (collisionResult) { //Not sure if necessary, but if we have multiple collisions in a single frame, stop all movement. collisionResult.PositionA = collision.Position; collisionResult.VelocityA = Vector2.Zero; } else { collisionResult = playerCollision; } TakeDamage(playerCollision.Identity); } } }
void OnCollisionEnter(Collision other) { switch (other.gameObject.tag) { case "Player": case "Wall": { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = false; if (other.contacts.Length > 0) { result.option0 = (object)other.contacts[0]; } this.control.collision_results.Add(result); } break; } }
public override void Click(Entity entity, ItemStack item) { if (!(entity is PlayerEntity)) { // TODO: non-player support return; } PlayerEntity player = (PlayerEntity)entity; if (player.LastClick + 0.2 > player.TheRegion.GlobalTickTime) { return; } Location eye = player.ItemSource(); Location adj = player.ItemDir * 20f; CollisionResult cr = player.TheRegion.Collision.CuboidLineTrace(new Location(0.1f), eye, eye + adj, player.IgnoreThis); if (!cr.Hit) { return; } ApplyHook(player, item, cr.Position, cr.HitEnt); }
protected void on_trigger_common(Collider other) { switch (other.gameObject.tag) { case "Item": { if (GameRoot.get().isNowCakeBiking()) { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = true; this.control.collision_results.Add(result); } else { // 케이크 무한제공 이외(보통 게임 중)일 때는 리모트는. // 아이템을 주울 수 없다. } } break; case "Door": { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = true; CollisionManager.getInstance().results.Add(result); } break; } }
protected void on_trigger_common(Collider other) { switch (other.gameObject.tag) { case "Item": { if (GameRoot.get().isNowCakeBiking()) { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = true; this.control.collision_results.Add(result); } else { // 耳?댄겕 臾댄븳?쒓났 ?댁쇅(蹂댄넻 寃뚯엫 以????뚮뒗 由щえ?몃뒗. // ?꾩씠?쒖쓣 二쇱슱 ???녿떎. } } break; case "Door": { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = true; CollisionManager.getInstance().results.Add(result); } break; } }
public CollisionResult Collide(float s, PhysicsGroupType groupType, PhysicsObject physicsObject, CollisionIdentity identity) { CollisionResult response = CollisionResult.None; if (groupType == PhysicsGroupType.Physical) { for (int i = bullets.Count - 1; i >= 0; i--) { Circle bullet = bullets[i]; CollisionResult bulletCollision = physicsObject.Collide(s, bullet); if (bulletCollision) { bullets.RemoveAt(i); //bullet.Position = bulletCollision.PositionB; //bullet.Velocity = bulletCollision.VelocityB; bulletCollision.Identity = bulletIdentity; response = bulletCollision; } } CollisionResult result = physicsObject.Collide(s, collision); if (result) { if (collisionResult) { collisionResult.PositionA = collision.Position; collisionResult.VelocityA = Vector2.Zero; } else { collisionResult = result.Switch(); } takeDamage(identity); response = result; } } return(response); }
public CollisionResult CollidePoint(Vector3 position, Vector3 impulse, QueryOptions options, float elasticity, Viewpoint viewpoint) { CollisionResult collisionResult = new CollisionResult(); Vector3 vector3 = position + impulse; TrileInstance instance = (TrileInstance)null; if ((options & QueryOptions.Background) != QueryOptions.None) { instance = this.LevelManager.ActualInstanceAt(vector3); } if (instance == null) { NearestTriles nearestTriles = this.LevelManager.NearestTrile(vector3, options, new Viewpoint?(viewpoint)); instance = nearestTriles.Deep ?? nearestTriles.Surface; } bool invertedGravity = (double)this.GravityFactor < 0.0; if (instance != null) { collisionResult = CollisionManager.CollideWithInstance(position, vector3, impulse, instance, options, elasticity, viewpoint, invertedGravity); } if (collisionResult.Collided && (invertedGravity ? ((double)impulse.Y > 0.0 ? 1 : 0) : ((double)impulse.Y < 0.0 ? 1 : 0)) != 0) { if ((double)vector3.X % 0.25 == 0.0) { vector3.X += 1.0 / 1000.0; } if ((double)vector3.Z % 0.25 == 0.0) { vector3.Z += 1.0 / 1000.0; } TrileInstance trileInstance = this.LevelManager.ActualInstanceAt(vector3); CollisionType rotatedFace; collisionResult.ShouldBeClamped = trileInstance == null || !trileInstance.Enabled || (rotatedFace = trileInstance.GetRotatedFace(this.CameraManager.VisibleOrientation)) == CollisionType.None || rotatedFace == CollisionType.Immaterial; } return(collisionResult); }
private static CollisionResult CollideWithInstance(Vector3 origin, Vector3 destination, Vector3 impulse, TrileInstance instance, QueryOptions options, float elasticity, Viewpoint viewpoint, bool invertedGravity) { CollisionResult collisionResult = new CollisionResult(); Vector3 normal = -FezMath.Sign(impulse); FaceOrientation faceOrientation = FezMath.VisibleOrientation(viewpoint); if ((options & QueryOptions.Background) == QueryOptions.Background) { faceOrientation = FezMath.GetOpposite(faceOrientation); } CollisionType rotatedFace = instance.GetRotatedFace(faceOrientation); if (rotatedFace != CollisionType.None) { collisionResult.Destination = instance; collisionResult.NearestDistance = instance.Center; collisionResult.Response = CollisionManager.SolidCollision(normal, instance, origin, destination, impulse, elasticity); if (collisionResult.Response != Vector3.Zero) { collisionResult.Collided = rotatedFace == CollisionType.AllSides || (rotatedFace == CollisionType.TopNoStraightLedge || rotatedFace == CollisionType.TopOnly) && (invertedGravity ? (double)normal.Y <0.0 : (double)normal.Y> 0.0); } } return(collisionResult); }
void OnCollisionEnter(Collision other) { switch(other.gameObject.tag) { case "Player": case "Wall": { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = false; if(other.contacts.Length > 0) { result.option0 = (object)other.contacts[0]; } this.control.collision_results.Add(result); } break; } }
public static bool boxToBox(Box first, Box second, out CollisionResult result) { result = new CollisionResult(); var minkowskiDiff = minkowskiDifference(first, second); if (minkowskiDiff.contains(0f, 0f)) { // calculate the MTV. if it is zero then we can just call this a non-collision result.minimumTranslationVector = minkowskiDiff.getClosestPointOnBoundsToOrigin(); if (result.minimumTranslationVector == Vector2.Zero) { return(false); } result.normal = -result.minimumTranslationVector; result.normal.Normalize(); return(true); } return(false); }
// something isnt right here with this one static bool circleToPolygon2(Circle circle, Polygon polygon, out CollisionResult result) { result = new CollisionResult(); var closestPointIndex = -1; var poly2Circle = circle.position - polygon.position; var poly2CircleNormalized = Vector2.Normalize(poly2Circle); var max = float.MinValue; for (var i = 0; i < polygon.points.Length; i++) { var projection = Vector2.Dot(polygon.points[i], poly2CircleNormalized); if (max < projection) { closestPointIndex = i; max = projection; } } var poly2CircleLength = poly2Circle.Length(); if (poly2CircleLength - max - circle.radius > 0 && poly2CircleLength > 0) { return(false); } // we have a collision // find the closest point on the polygon. we know the closest index so we only have 2 edges to test var prePointIndex = closestPointIndex - 1; var postPointIndex = closestPointIndex + 1; // handle wrapping the points if (prePointIndex < 0) { prePointIndex = polygon.points.Length - 1; } if (postPointIndex == polygon.points.Length) { postPointIndex = 0; } var circleCenter = circle.position - polygon.position; var closest1 = closestPointOnLine(polygon.points[prePointIndex], polygon.points[closestPointIndex], circleCenter); var closest2 = closestPointOnLine(polygon.points[closestPointIndex], polygon.points[postPointIndex], circleCenter); float distance1, distance2; Vector2.DistanceSquared(ref circleCenter, ref closest1, out distance1); Vector2.DistanceSquared(ref circleCenter, ref closest2, out distance2); var radiusSquared = circle.radius * circle.radius; float seperationDistance; if (distance1 < distance2) { // make sure the squared distance is less than our radius squared else we are not colliding if (distance1 > radiusSquared) { return(false); } seperationDistance = circle.radius - Mathf.sqrt(distance1); var edge = polygon.points[closestPointIndex] - polygon.points[prePointIndex]; result.normal = new Vector2(edge.Y, -edge.X); result.point = polygon.position + closest1; } else { // make sure the squared distance is less than our radius squared else we are not colliding if (distance2 > radiusSquared) { return(false); } seperationDistance = circle.radius - Mathf.sqrt(distance2); var edge = polygon.points[postPointIndex] - polygon.points[closestPointIndex]; result.normal = new Vector2(edge.Y, -edge.X); result.point = polygon.position + closest2; } result.normal.Normalize(); result.minimumTranslationVector = result.normal * -seperationDistance; return(true); }
public void removeResult(CollisionResult result) { this.results.Remove(result); }
public void UpdateBrushHighLight(Vector3 Origin, Vector3 Direction, Vector4 Color, int ToolGroup, int Shape, float BrushRadius, float Radius) { if (FileManager.CurrentWorldFile == null || FileManager.MasteryFile == null) { return; } CollisionResults Results = new CollisionResults(); switch (ToolGroup) { case 0: Results.AddRange(RayCastTerrain(Origin, Direction, Radius)); break; case 1: Results.AddRange(RayCastWater(Origin, Direction, Radius)); break; case 2: Results.AddRange(RayCastWater(Origin, Direction, Radius)); Results.AddRange(RayCastTerrain(Origin, Direction, Radius)); break; } if (Results.Count == 0) { return; } CollisionResult Result = Results.GetClosest(); int SelectedLOD = FileManager.CurrentWorldFile.LODID; //Editing Bounds Vector2 A1 = new Vector2(Result.CollisionPoint.X - Radius, Result.CollisionPoint.Y - BrushRadius); Vector2 A2 = new Vector2(Result.CollisionPoint.X + Radius, Result.CollisionPoint.Y + BrushRadius); for (int i = 0; i < TerrainGeometries.Count; i++) { if (TerrainGeometries[i].WorldFile.LODID != SelectedLOD) { continue; } Vector2 B1 = TerrainGeometries[i].WorldFile.GetA(); Vector2 B2 = TerrainGeometries[i].WorldFile.GetB(); if (A1.X < B2.X && A2.X > B1.X && A1.Y < B2.Y && A2.Y > B1.Y) { if (Result.GeometryName.Contains("Water")) { WaterGeometries[i].SetHighLight(Result.CollisionPoint, Color, Shape, BrushRadius); } else if (Result.GeometryName.Contains("Terrain")) { TerrainGeometries[i].SetHighLight(Result.CollisionPoint, Color, Shape, BrushRadius); } } else { TerrainGeometries[i].SetHighLight(Result.CollisionPoint, new Vector4(), Shape, 0); WaterGeometries[i].SetHighLight(Result.CollisionPoint, new Vector4(), Shape, 0); } } }
public CollisionResults RayCastWater(Vector3 Origin, Vector3 Direction, float Range, bool HasCurrentChunkLock) { if (FileManager.MasteryFile == null) { return(new CollisionResults()); } int LOD = FileManager.CurrentWorldFile.LODID; SettingsContainer Settings = FileManager.MasteryFile.Settings; List <WorldFile> ActiveWorldFiles = FileManager.MasteryFile.ActiveWorldFiles; CollisionResults Results = new CollisionResults(); List <Vector2> QuadCheck = new List <Vector2>(); if (HasCurrentChunkLock) { if (FileManager.CurrentWorldFile != null) { float TerrainScale = FileManager.CurrentWorldFile.TerrainScale; float HeightScale = FileManager.CurrentWorldFile.HeightScale; int[,] HeightMap = FileManager.CurrentWorldFile.HeightMap; int[,] WaterHeightMap = FileManager.CurrentWorldFile.WaterHeightMap; float Precision = TerrainScale * 0.5f; for (float j = 0; j < Range; j += Precision) { Vector3 CurrentPosition = Origin + (Direction * j); Vector3 CurrentVertexPosition = (CurrentPosition - FileManager.CurrentWorldFile.GetPosition()) / TerrainScale; int VX = (int)Math.Floor(CurrentVertexPosition.X); int VY = (int)Math.Floor(CurrentVertexPosition.Y); if (VX < 0 || VY < 0 || VX >= HeightMap.GetLength(0) - 1 || VY >= HeightMap.GetLength(1) - 1) { continue; } float MidPoint = (HeightMap[VX, VY] + HeightMap[VX + 1, VY] + HeightMap[VX, VY + 1] + HeightMap[VX + 1, VY + 1] + WaterHeightMap[VX, VY] + WaterHeightMap[VX + 1, VY] + WaterHeightMap[VX, VY + 1] + WaterHeightMap[VX + 1, VY + 1]) / 4; Vector3[] QuadVertices = { new Vector3(0, 0, (WaterHeightMap[VX, VY] + HeightMap[VX, VY]) * HeightScale), new Vector3(TerrainScale, 0, (WaterHeightMap[VX + 1, VY] + HeightMap[VX + 1, VY]) * HeightScale), new Vector3(0, TerrainScale, (WaterHeightMap[VX, VY + 1] + HeightMap[VX, VY + 1]) * HeightScale), new Vector3(TerrainScale, TerrainScale, (WaterHeightMap[VX + 1, VY + 1] + HeightMap[VX + 1, VY + 1]) * HeightScale) }; if (!QuadCheck.Contains(new Vector2(VX, VY))) { QuadCheck.Add(new Vector2(VX, VY)); Vector3 VertexWorldPosition = FileManager.CurrentWorldFile.GetPosition() + new Vector3(VX * TerrainScale, VY * TerrainScale, 0); for (int k = 0; k < Indices.Length; k += 3) { Vector3 V0 = VertexWorldPosition + QuadVertices[Indices[k]]; Vector3 V1 = VertexWorldPosition + QuadVertices[Indices[k + 1]]; Vector3 V2 = VertexWorldPosition + QuadVertices[Indices[k + 2]]; if (CollisionUtil.Intersect(V0, V1, V2, Origin, Direction)) { TerrainWaterContainer WaterGeom = WaterGeometries.Where(x => x.WorldFile.FileName == FileManager.CurrentWorldFile.FileName).First(); Vector3 CollisionPoint = CollisionUtil.GetCollisionPoint(V0, V1, V2, Origin, Direction); CollisionResult Result = new CollisionResult( V0, V1, V2, Origin, CollisionPoint, WaterGeom.Geom); Results.Add(Result); } } } } } } else { int PX = (int)Math.Floor(Origin.X / Settings.ChunkSize); int PY = (int)Math.Floor(Origin.Y / Settings.ChunkSize); for (int i = 0; i < ActiveWorldFiles.Count; i++) { int ValidLOD = LOD == -1 ? ActiveWorldFiles[i].LODID : LOD; if (Math.Abs(ActiveWorldFiles[i].IDX - PX) <= Settings.ChunkSelectionRadius && Math.Abs(ActiveWorldFiles[i].IDY - PY) < Settings.ChunkSelectionRadius && ActiveWorldFiles[i].LODID == ValidLOD) { float TerrainScale = ActiveWorldFiles[i].TerrainScale; float HeightScale = ActiveWorldFiles[i].HeightScale; int[,] HeightMap = ActiveWorldFiles[i].HeightMap; int[,] WaterHeightMap = FileManager.CurrentWorldFile.WaterHeightMap; float Precision = TerrainScale * 0.5f; for (float j = 0; j < Range; j += Precision) { Vector3 CurrentPosition = Origin + (Direction * j); Vector3 CurrentVertexPosition = (CurrentPosition - ActiveWorldFiles[i].GetPosition()) / TerrainScale; int VX = (int)Math.Floor(CurrentVertexPosition.X); int VY = (int)Math.Floor(CurrentVertexPosition.Y); if (VX < 0 || VY < 0 || VX >= HeightMap.GetLength(0) - 1 || VY >= HeightMap.GetLength(1) - 1) { continue; } float MidPoint = (HeightMap[VX, VY] + HeightMap[VX + 1, VY] + HeightMap[VX, VY + 1] + HeightMap[VX + 1, VY + 1] + WaterHeightMap[VX, VY] + WaterHeightMap[VX + 1, VY] + WaterHeightMap[VX, VY + 1] + WaterHeightMap[VX + 1, VY + 1]) / 4; Vector3[] QuadVertices = { new Vector3(0, 0, (WaterHeightMap[VX, VY] + HeightMap[VX, VY]) * HeightScale), new Vector3(TerrainScale, 0, (WaterHeightMap[VX + 1, VY] + HeightMap[VX + 1, VY]) * HeightScale), new Vector3(0, TerrainScale, (WaterHeightMap[VX, VY + 1] + HeightMap[VX, VY + 1]) * HeightScale), new Vector3(TerrainScale, TerrainScale, (WaterHeightMap[VX + 1, VY + 1] + HeightMap[VX + 1, VY + 1]) * HeightScale) }; if (!QuadCheck.Contains(new Vector2(VX, VY))) { QuadCheck.Add(new Vector2(VX, VY)); Vector3 VertexWorldPosition = ActiveWorldFiles[i].GetPosition() + new Vector3(VX * TerrainScale, VY * TerrainScale, 0); for (int k = 0; k < Indices.Length; k += 3) { Vector3 V0 = VertexWorldPosition + QuadVertices[Indices[k]]; Vector3 V1 = VertexWorldPosition + QuadVertices[Indices[k + 1]]; Vector3 V2 = VertexWorldPosition + QuadVertices[Indices[k + 2]]; if (CollisionUtil.Intersect(V0, V1, V2, Origin, Direction)) { Vector3 CollisionPoint = CollisionUtil.GetCollisionPoint(V0, V1, V2, Origin, Direction); TerrainWaterContainer WaterGeom = WaterGeometries.Where(x => x.WorldFile.FileName == FileManager.CurrentWorldFile.FileName).First(); CollisionResult Result = new CollisionResult( V0, V1, V2, Origin, CollisionPoint, WaterGeom.Geom); Results.Add(Result); } } } } } } } return(Results); }
/// <summary> /// checks for a collision between two Polygons /// </summary> /// <returns>The collision.</returns> /// <param name="first">Polygon a.</param> /// <param name="second">Polygon b.</param> public static bool polygonToPolygon( Polygon first, Polygon second, out CollisionResult result ) { result = new CollisionResult(); var isIntersecting = true; var firstEdges = first.edgeNormals; var secondEdges = second.edgeNormals; var minIntervalDistance = float.PositiveInfinity; var translationAxis = new Vector2(); var polygonOffset = first.position - second.position; Vector2 axis; // Loop through all the edges of both polygons for( var edgeIndex = 0; edgeIndex < firstEdges.Length + secondEdges.Length; edgeIndex++ ) { // 1. Find if the polygons are currently intersecting // Polygons have the normalized axis perpendicular to the current edge cached for us if( edgeIndex < firstEdges.Length ) axis = firstEdges[edgeIndex]; else axis = secondEdges[edgeIndex - firstEdges.Length]; // Find the projection of the polygon on the current axis float minA = 0; float minB = 0; float maxA = 0; float maxB = 0; var intervalDist = 0f; getInterval( axis, first, ref minA, ref maxA ); getInterval( axis, second, ref minB, ref maxB ); // get our interval to be space of the second Polygon. Offset by the difference in position projected on the axis. float relativeIntervalOffset; Vector2.Dot( ref polygonOffset, ref axis, out relativeIntervalOffset ); minA += relativeIntervalOffset; maxA += relativeIntervalOffset; // check if the polygon projections are currentlty intersecting intervalDist = intervalDistance( minA, maxA, minB, maxB ); if( intervalDist > 0 ) isIntersecting = false; // for Poly-to-Poly casts add a Vector2? parameter called deltaMovement. In the interest of speed we do not use it here // 2. Now find if the polygons *will* intersect. only bother checking if we have some velocity //if( deltaMovement.HasValue ) //{ // // Project the velocity on the current axis // var velocityProjection = Vector2.Dot( axis, deltaMovement.Value ); // // Get the projection of polygon A during the movement // if( velocityProjection < 0 ) // minA += velocityProjection; // else // maxA += velocityProjection; // // Do the same test as above for the new projection // intervalDist = intervalDistance( minA, maxA, minB, maxB ); // if( intervalDist > 0 ) // willIntersect = false; //} // If the polygons are not intersecting and won't intersect, exit the loop if( !isIntersecting ) return false; // Check if the current interval distance is the minimum one. If so store the interval distance and the current distance. // This will be used to calculate the minimum translation vector intervalDist = Math.Abs( intervalDist ); if( intervalDist < minIntervalDistance ) { minIntervalDistance = intervalDist; translationAxis = axis; if( Vector2.Dot( translationAxis, polygonOffset ) < 0 ) translationAxis = -translationAxis; } } // The minimum translation vector can be used to push the polygons appart. result.normal = translationAxis; result.minimumTranslationVector = -translationAxis * minIntervalDistance; return true; }
/// <summary> /// 处理碰撞,空函数 /// </summary> /// <param name="result"></param> /// <param name="objB"></param> public void HandleCollision(CollisionResult result, ICollideObj objA, ICollideObj objB) { }
/// <summary> /// Mover Elipsoide con detección de colisiones, sliding y gravedad. /// Se actualiza la posición del centro del Elipsoide /// </summary> /// <param name="characterElipsoid">Elipsoide del cuerpo a mover</param> /// <param name="movementVector">Movimiento a realizar</param> /// <param name="colliders">Obstáculos contra los cuales se puede colisionar</param> /// <returns>Desplazamiento relativo final efecutado al Elipsoide</returns> public Vector3 moveCharacter(TgcElipsoid characterElipsoid, Vector3 movementVector, List<Collider> colliders) { //Guardar posicion original del Elipsoide Vector3 originalElipsoidCenter = characterElipsoid.Center; //Pasar elipsoid space Vector3 eCenter = TgcVectorUtils.div(characterElipsoid.Center, characterElipsoid.Radius); Vector3 eMovementVector = TgcVectorUtils.div(movementVector, characterElipsoid.Radius); eSphere.setValues(eCenter, 1); Vector3 eOrigCenter = eSphere.Center; //Ver si la distancia a recorrer es para tener en cuenta float distanceToTravelSq = movementVector.LengthSq(); if (distanceToTravelSq >= EPSILON) { //Mover la distancia pedida selectPotentialColliders(characterElipsoid, movementVector, colliders); this.result = doCollideWithWorld(eSphere, eMovementVector, characterElipsoid.Radius, objetosCandidatos, 0, movementSphere, 1); } //Aplicar gravedad if (gravityEnabled) { //Mover con gravedad Vector3 eGravity = TgcVectorUtils.div(gravityForce, characterElipsoid.Radius); selectPotentialColliders(characterElipsoid, eGravity, colliders); this.result = doCollideWithWorld(eSphere, eGravity, characterElipsoid.Radius, objetosCandidatos, 0, movementSphere, onGroundMinDotValue); } //Mover Elipsoid pasando valores de colision a R3 Vector3 movement = TgcVectorUtils.mul(eSphere.Center - eOrigCenter, characterElipsoid.Radius); characterElipsoid.moveCenter(movement); //Ajustar resultados result.realMovmentVector = TgcVectorUtils.mul(result.realMovmentVector, characterElipsoid.Radius); result.collisionPoint = TgcVectorUtils.mul(result.collisionPoint, characterElipsoid.Radius); return movement; }
/// <summary> /// Verifica si este poligono esta colisionando o va a colisionar /// con otro poligono dado. /// Esta verificación se realiza utilizando SAT (Separating Axis Theorem) la cual explica /// que, si existe una linea en el plano que pueda separar dos distintas figuras en diferentes /// lados por completo, entonces estas figuras no están colisionando. /// Nota: Este teorema solo debería aplicarse ante poligonos concavos, de otra forma el algoritmo /// no daria una respuesta correcta ante poligonos convexos. /// </summary> /// <param name="polygon2">Segundo poligono con el cual se hará la verificacion</param> /// <param name="distance">Distancia por la cual se movera el poligono principal (this)</param> /// <param name="result">Referencia del objeto que contendrá la información necesaria sobre /// si se esta intersectando, si se intersectará y la distancia necesaria /// para evitar una intersección</param> protected override CollisionResult IntersectWithPolygon(Polygon polygon2, ref Vector2 distance) { CollisionResult result = new CollisionResult(); result.triggeringBody = this; result.affectedBody = polygon2; // Se asume que ambos poligonos intersectan hasta que // se pueda demostrar lo contrario result.intersect = true; result.willIntersect = true; // Se obtiene la cantidad de lados del poligono principal // y del segundo poligono int sideCountA = this.sides.Count; int sideCountB = polygon2.Sides.Count; float minIntervalDistance = float.PositiveInfinity; Vector2 translationAxis = new Vector2(); // Lado actual a analizar Line currentSide; // Se realiza una verificacion por cada uno de los lados de ambos poligonos // hasta que pueda encontrarse alguna separación entre ambos o hasta que se hayan // verificado todos los lados for (int sideIndex = 0; sideIndex < sideCountA + sideCountB; sideIndex++) { if (sideIndex < sideCountA) { currentSide = this.sides[sideIndex]; } else { currentSide = polygon2.Sides[sideIndex - sideCountA]; } // Se obtiene un Vector perpendicular al lado actual con valores unitarios, // esto servira para obtener el eje sobre el cual deben hacerse las proyecciones Vector2 axis = new Vector2(-currentSide.Edge.Y, currentSide.Edge.X); axis.Normalize(); // Se proyectan ambos poligonos sobre el mismo eje float minA = 0; float minB = 0; float maxA = 0; float maxB = 0; this.Project(ref axis, out minA, out maxA); polygon2.Project(ref axis, out minB, out maxB); // Se obtiene el intervalo entre ambos poligonos sobre el eje, // si el intervalo (separación) es mayor a 0 entonces los poligonos // no están intersectando float intervalDistance = IntervalDistance(minA, maxA, minB, maxB); if (intervalDistance > 0) result.intersect = false; // Luego se realizan los mismos calculos pero sumando el vector // de velocidad al poligono en (posible) movimiento float velocityProjection = Vector2.Dot(axis, distance); //if (velocityProjection < 0) //{ minA += velocityProjection; //} //else //{ maxA += velocityProjection; //} // Si el intervalo de distancia es menor a 0 con el poligono en movimiento, // entonces los poligonos tambien intersectaran al moverse intervalDistance = IntervalDistance(minA, maxA, minB, maxB); if (intervalDistance > 0) result.willIntersect = false; // Si ya sabemos que los poligonos estan intersectando y van a intersectar, // no hay mucho mas que hacer aquí asi que terminamos las verificaciones if (result.intersect == false && result.willIntersect == false) { break; } // Si el intervalo de distancia es el minimo, se guarda // junto con el eje donde fue encontrado para asi poder separar // a los poligonos en esa dirección intervalDistance = Math.Abs(intervalDistance); if (intervalDistance < minIntervalDistance) { minIntervalDistance = intervalDistance; translationAxis = axis; Vector2 d = this.Center - polygon2.Center; if (Vector2.Dot(d, translationAxis) < 0) { translationAxis = -translationAxis; } } } // El vector minimo de transición // servira para separar ambos poligonos en caso de que colisionen. if (result.willIntersect) { result.minimumTranslationVector = translationAxis * minIntervalDistance; } result.translationAxis = translationAxis; return result; }
protected void on_trigger_common(Collider other) { switch(other.gameObject.tag) { case "Door": { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = false; CollisionManager.getInstance().results.Add(result); } break; } }
/// <summary> /// Verifica si este poligono esta colisionando o va a colisionar /// con una esféra dada. /// Para esto se ubica el punto centro de la esfera en la región de voronoi /// que le corresponde según el poligono, de forma que obtenemos el punto /// mas cercano de la esfera al poligono junto al respectivo eje. /// </summary> /// <param name="sphere">Esféra con la cual se hará la verificacion</param> /// <param name="distance">Distancia por la cual se movera este poligono</param> /// <param name="result">Referencia del objeto que contendrá la información necesaria sobre /// si se esta intersectando, si se intersectará y la distancia necesaria /// para evitar una intersección</param> protected override CollisionResult IntersectWithSphere(Sphere sphere, ref Vector2 distance) { CollisionResult result = new CollisionResult(); result.triggeringBody = this; result.affectedBody = sphere; // Empezamos asumiendo que las dos figuras no // se encuentran intersectando result.intersect = false; result.willIntersect = false; // Se toman tanto la cantidad de puntos // como la cantidad de lados del poligono int sideCountPolygon = this.sides.Count; int pointCountPolygon = this.vertices.Count; // Dos valores distintos para guardar float minIntervalDistanceAfterMove = float.PositiveInfinity; float minIntervalDistance = float.PositiveInfinity; Vector2 translationAxis = new Vector2(); // Ahora se estudia cada lado del poligono para verificar si el centro // de la esfera se encuentra perpendicular a algun punto de ese lado for (int sideIndex = 0; sideIndex < sideCountPolygon; sideIndex++) { Line currentSide = this.sides[sideIndex]; // Se crea un vector paralelo al lado donde puedan proyectase // ambos puntos del lado actual mas el centro de la esfera Vector2 axis = new Vector2(currentSide.Edge.X, currentSide.Edge.Y); axis.Normalize(); float minA = Vector2.Dot(axis, currentSide.StartPoint); float maxA = Vector2.Dot(axis, currentSide.EndPoint); float centerB = Vector2.Dot(axis, sphere.Center); float velocityProjection = Vector2.Dot(axis, distance); // Se realiza un chequeo preliminar antes de sumar el vector // de distancia #region Verificaciones de intersección actual // Si el punto centro se encuentra perpendicular a algun // punto del lado actual, entonces la esfera puede encontrarse en esa region if (minA <= centerB && maxA >= centerB) { // Creamos un eje perpendicular a la linea para obtener la distancia // entre un punto de la linea y el centro de la esfera axis = new Vector2(-currentSide.Edge.Y, currentSide.Edge.X); axis.Normalize(); // Ya que el eje es perpendicular, tanto el punto inicial de la linea // como el final terminan en la misma posicion al ser proyectados float pointA = Vector2.Dot(axis, currentSide.EndPoint); float pointB = Vector2.Dot(axis, sphere.Center); // Se obtiene el intervalo y se guarda en caso de que sea menor // al intervalo anterior (La esfera se encontrara en la region de voronoi // que tenga el punto mas cercano desde la esfera hacia el poligono) float intervalDistance = Math.Abs(pointA - pointB); if (intervalDistance < minIntervalDistance) { minIntervalDistance = intervalDistance; } } #endregion // Aplicamos la proyeccion de velocidad a el lado actual if (velocityProjection < 0) { minA += velocityProjection; } else { maxA += velocityProjection; } // Si el punto centro se encuentra perpendicular a algun // punto del lado actual, entonces la esfera puede encontrarse en esa region if (minA <= centerB && maxA >= centerB) { // Creamos un eje perpendicular a la linea para obtener la distancia // entre un punto de la linea y el centro de la esfera axis = new Vector2(-currentSide.Edge.Y, currentSide.Edge.X); axis.Normalize(); // Volvemos a aplicar la proyeccion de velocidad puesto que // esta vez estamos proyectando en un diferente eje velocityProjection = Vector2.Dot(axis, distance); // Ya que el eje es perpendicular, tanto el punto inicial de la linea // como el final terminan en la misma posicion al ser proyectados float pointA = Vector2.Dot(axis, currentSide.EndPoint) + velocityProjection; float pointB = Vector2.Dot(axis, sphere.Center); // Se obtiene el intervalo y se guarda en caso de que sea menor // al intervalo anterior (La esfera se encontrara en la region de voronoi // que tenga el punto mas cercano desde la esfera hacia el poligono) float intervalDistance = Math.Abs(pointA - pointB); if (intervalDistance < minIntervalDistanceAfterMove) { minIntervalDistanceAfterMove = intervalDistance; translationAxis = axis; Vector2 d = this.Center - sphere.Center; if (Vector2.Dot(d, translationAxis) < 0) { translationAxis = -translationAxis; } } } } // Luego se estudia la distancia entre cada vertice del poligono // contra el centro de la esfera, si se encuentra alguna distancia // menor que las ya guardadas entonces se guarda for (int pointIndex = 0; pointIndex < pointCountPolygon; pointIndex++) { Vector2 currentPoint = this.vertices[pointIndex]; // Creamos una linea que vaya desde el vertice hasta el centro // de la esfera, sumandole el vector de distancia al vertice Line line = new Line(currentPoint + distance, sphere.Center); Vector2 axis = new Vector2(line.Edge.X, line.Edge.Y); axis.Normalize(); if (line.Lenght < minIntervalDistanceAfterMove) { minIntervalDistanceAfterMove = line.Lenght; translationAxis = axis; Vector2 d = this.Center - sphere.Center; if (Vector2.Dot(d, translationAxis) < 0) { translationAxis = -translationAxis; } } // Misma verificacion sin sumar el vector de distancia #region Verificaciones de intersección actual line = new Line(currentPoint, sphere.Center); axis = new Vector2(line.Edge.X, line.Edge.Y); axis.Normalize(); if (line.Lenght < minIntervalDistance) { minIntervalDistance = line.Lenght; } #endregion } // Se verifica si el poligono intersecta bool isInside = this.PointInBody(sphere.Center); if (isInside || minIntervalDistance < sphere.Radius) { result.intersect = true; } // Se verifica si intersectaran y aplica un vector de transicion // diferente dependiendo de si el centro de la esfera se encuentra // dentro o fuera del poligono isInside = this.PointInBody(sphere.Center - distance); if (isInside) { result.minimumTranslationVector = translationAxis * (sphere.Radius + minIntervalDistanceAfterMove); result.willIntersect = true; } else if (minIntervalDistanceAfterMove < sphere.Radius) { result.minimumTranslationVector = translationAxis * Math.Abs(sphere.Radius - minIntervalDistanceAfterMove); result.willIntersect = true; } result.translationAxis = translationAxis; return result; }
public override bool pointCollidesWithShape( Vector2 point, out CollisionResult result ) { if( isUnrotated ) return ShapeCollisions.pointToBox( point, this, out result ); return base.pointCollidesWithShape( point, out result ); }
/// <summary> /// note: if circle center lies in the box the collision result will be incorrect! /// </summary> /// <returns><c>true</c>, if to box was circled, <c>false</c> otherwise.</returns> /// <param name="first">First.</param> /// <param name="second">Second.</param> /// <param name="result">Result.</param> public static bool circleToBox( Circle first, Box second, out CollisionResult result ) { result = new CollisionResult(); var closestPointOnBounds = second.bounds.getClosestPointOnRectangleBorderToPoint( first.position ); float sqrDistance; Vector2.DistanceSquared( ref closestPointOnBounds, ref first.position, out sqrDistance ); // see if the point on the box is less than radius from the circle if( sqrDistance <= first.radius * first.radius ) { var distanceToCircle = first.position - closestPointOnBounds; var depth = distanceToCircle.Length() - first.radius; result.point = closestPointOnBounds; result.normal = Vector2.Normalize( distanceToCircle ); result.minimumTranslationVector = depth * result.normal; return true; } return false; }
// something isnt right here with this one static bool circleToPolygon2( Circle circle, Polygon polygon, out CollisionResult result ) { result = new CollisionResult(); var closestPointIndex = -1; var poly2Circle = circle.position - polygon.position; var poly2CircleNormalized = Vector2.Normalize( poly2Circle ); var max = float.MinValue; for( var i = 0; i < polygon.points.Length; i++ ) { var projection = Vector2.Dot( polygon.points[i], poly2CircleNormalized ); if( max < projection ) { closestPointIndex = i; max = projection; } } var poly2CircleLength = poly2Circle.Length(); if( poly2CircleLength - max - circle.radius > 0 && poly2CircleLength > 0 ) return false; // we have a collision // find the closest point on the polygon. we know the closest index so we only have 2 edges to test var prePointIndex = closestPointIndex - 1; var postPointIndex = closestPointIndex + 1; // handle wrapping the points if( prePointIndex < 0 ) prePointIndex = polygon.points.Length - 1; if( postPointIndex == polygon.points.Length ) postPointIndex = 0; var circleCenter = circle.position - polygon.position; var closest1 = closestPointOnLine( polygon.points[prePointIndex], polygon.points[closestPointIndex], circleCenter ); var closest2 = closestPointOnLine( polygon.points[closestPointIndex], polygon.points[postPointIndex], circleCenter ); float distance1, distance2; Vector2.DistanceSquared( ref circleCenter, ref closest1, out distance1 ); Vector2.DistanceSquared( ref circleCenter, ref closest2, out distance2 ); var radiusSquared = circle.radius * circle.radius; float seperationDistance; if( distance1 < distance2 ) { // make sure the squared distance is less than our radius squared else we are not colliding if( distance1 > radiusSquared ) return false; seperationDistance = circle.radius - Mathf.sqrt( distance1 ); var edge = polygon.points[closestPointIndex] - polygon.points[prePointIndex]; result.normal = new Vector2( edge.Y, -edge.X ); result.point = polygon.position + closest1; } else { // make sure the squared distance is less than our radius squared else we are not colliding if( distance2 > radiusSquared ) return false; seperationDistance = circle.radius - Mathf.sqrt( distance2 ); var edge = polygon.points[postPointIndex] - polygon.points[closestPointIndex]; result.normal = new Vector2( edge.Y, -edge.X ); result.point = polygon.position + closest2; } result.normal.Normalize(); result.minimumTranslationVector = result.normal * -seperationDistance; return true; }
/// <summary> /// does an overlap check of first vs second. ShapeCollisionResult retuns the data for moving first so it isn't colliding with second. /// </summary> /// <returns><c>true</c>, if to polygon was polygoned, <c>false</c> otherwise.</returns> /// <param name="first">First.</param> /// <param name="second">Second.</param> /// <param name="result">Result.</param> public static bool polygonToPolygon( Polygon first, Polygon second, out CollisionResult result ) { result = new CollisionResult(); float timeOfCollision; if( polygonToPolygon( first, second, null, out result.normal, out timeOfCollision ) ) { result.minimumTranslationVector = result.normal * ( timeOfCollision ); return true; } return false; }
void OnTriggerEnter(Collider other) { // 여분의 것과 맞지 않는 설정이므로 일단 쌓아 버린다. CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = false; this.collision_results.Add(result); }
public void SetResult(CollisionResult result) => this.result = result;
public static bool circleToPolygon( Circle circle, Polygon polygon, out CollisionResult result ) { result = new CollisionResult(); // circle position in the polygons coordinates var poly2Circle = circle.position - polygon.position; // first, we need to find the closest distance from the circle to the polygon float distanceSquared; var closestPoint = Polygon.getClosestPointOnPolygonToPoint( polygon.points, poly2Circle, out distanceSquared, out result.normal ); // make sure the squared distance is less than our radius squared else we are not colliding. Note that if the Circle is fully // contained in the Polygon the distance could be larger than the radius. Because of that we also make sure the circle position // is not inside the poly. var circleCenterInsidePoly = polygon.containsPoint( circle.position ); if( distanceSquared > circle.radius * circle.radius && !circleCenterInsidePoly ) return false; // figure out the mtv. We have to be careful to deal with circles fully contained in the polygon or with their center contained. Vector2 mtv; if( circleCenterInsidePoly ) { mtv = result.normal * ( Mathf.sqrt( distanceSquared ) - circle.radius ); } else { // if we have no distance that means the circle center is on the polygon edge. Move it only by its radius if( distanceSquared == 0 ) { mtv = result.normal * circle.radius; } else { var distance = Mathf.sqrt( distanceSquared ); mtv = -( poly2Circle - closestPoint ) * ( ( circle.radius - distance ) / distance ); } } result.minimumTranslationVector = mtv; result.point = closestPoint + polygon.position; return true; }
/// <summary> /// Detección de colisiones recursiva /// </summary> /// <param name="eSphere">Sphere de radio 1 pasada a Elipsoid space</param> /// <param name="eMovementVector">Movimiento pasado a Elipsoid space</param> /// <param name="eRadius">Radio de la elipsoide</param> /// <param name="colliders">Objetos contra los cuales colisionar</param> /// <param name="recursionDepth">Nivel de recursividad</param> /// <param name="movementSphere">Esfera real que representa el movimiento abarcado</param> /// <param name="slidingMinY">Minimo valor de normal Y de colision para hacer sliding</param> /// <returns>Resultado de colision</returns> public CollisionResult doCollideWithWorld(TgcBoundingSphere eSphere, Vector3 eMovementVector, Vector3 eRadius, List<Collider> colliders, int recursionDepth, TgcBoundingSphere movementSphere, float slidingMinY) { CollisionResult result = new CollisionResult(); result.collisionFound = false; //Limitar recursividad if (recursionDepth > 5) { return result; } //Posicion deseada Vector3 nextSphereCenter = eSphere.Center + eMovementVector; //Buscar el punto de colision mas cercano de todos los objetos candidatos Vector3 q; float t; Vector3 n; float minT = float.MaxValue; foreach (Collider collider in colliders) { //Colisionar Sphere en movimiento contra Collider (cada Collider resuelve la colision) if (collider.intersectMovingElipsoid(eSphere, eMovementVector, eRadius, movementSphere, out t, out q, out n)) { //Quedarse con el menor instante de colision if(t < minT) { minT = t; result.collisionFound = true; result.collisionPoint = q; result.collisionNormal = n; result.collider = collider; } } } //Si nunca hubo colisión, avanzar todo lo requerido if (!result.collisionFound) { //Avanzar todo lo pedido eSphere.moveCenter(eMovementVector); result.realMovmentVector = eMovementVector; result.collisionNormal = Vector3.Empty; result.collisionPoint = Vector3.Empty; result.collider = null; return result; } //Solo movernos si ya no estamos muy cerca if (minT >= EPSILON) { //Restar un poco al instante de colision, para movernos hasta casi esa distancia minT -= EPSILON; result.realMovmentVector = eMovementVector * minT; eSphere.moveCenter(result.realMovmentVector); //Quitarle al punto de colision el EPSILON restado al movimiento, para no afectar al plano de sliding Vector3 v = Vector3.Normalize(result.realMovmentVector); result.collisionPoint -= v * EPSILON; } //Calcular plano de Sliding, como un plano tangete al punto de colision con la esfera, apuntando hacia el centro de la esfera Vector3 slidePlaneOrigin = result.collisionPoint; Vector3 slidePlaneNormal = eSphere.Center - result.collisionPoint; slidePlaneNormal.Normalize(); Plane slidePlane = Plane.FromPointNormal(slidePlaneOrigin, slidePlaneNormal); //Calcular vector de movimiento para sliding, proyectando el punto de destino original sobre el plano de sliding float distance = TgcCollisionUtils.distPointPlane(nextSphereCenter, slidePlane); Vector3 newDestinationPoint = nextSphereCenter - distance * slidePlaneNormal; Vector3 slideMovementVector = newDestinationPoint - result.collisionPoint; //No hacer recursividad si es muy pequeño slideMovementVector.Scale(slideFactor); if (slideMovementVector.Length() < EPSILON) { return result; } //Ver si posee la suficiente pendiente en Y para hacer sliding if (result.collisionNormal.Y <= slidingMinY) { //Recursividad para aplicar sliding doCollideWithWorld(eSphere, slideMovementVector, eRadius, colliders, recursionDepth + 1, movementSphere, slidingMinY); } return result; }
public CollisionResults RayCastTerrain(Vector3 Origin, Vector3 Direction, float Range, WorldFile File) { if (FileManager.MasteryFile == null) { return(new CollisionResults()); } SettingsContainer Settings = FileManager.MasteryFile.Settings; List <WorldFile> ActiveWorldFiles = FileManager.MasteryFile.ActiveWorldFiles; List <Vector2> QuadCheck = new List <Vector2>(); CollisionResults Results = new CollisionResults(); float TerrainScale = File.TerrainScale; float HeighScale = File.HeightScale; int[,] HeightMap = File.HeightMap; float Precision = TerrainScale * 0.5f; for (float j = 0; j < Range; j += Precision) { Vector3 CurrentPosition = Origin + (Direction * j); Vector3 CurrentVertexPosition = (CurrentPosition - File.GetPosition()) / TerrainScale; int VX = (int)Math.Floor(CurrentVertexPosition.X); int VY = (int)Math.Floor(CurrentVertexPosition.Y); if (VX < 0 || VY < 0 || VX >= HeightMap.GetLength(0) - 1 || VY >= HeightMap.GetLength(1) - 1) { continue; } Vector3[] QuadVertices = { new Vector3(0, 0, HeightMap[VX, VY] * HeighScale), new Vector3(TerrainScale, 0, HeightMap[VX + 1, VY] * HeighScale), new Vector3(0, TerrainScale, HeightMap[VX, VY + 1] * HeighScale), new Vector3(TerrainScale, TerrainScale, HeightMap[VX + 1, VY + 1] * HeighScale) }; if (!QuadCheck.Contains(new Vector2(VX, VY))) { QuadCheck.Add(new Vector2(VX, VY)); Vector3 VertexWorldPosition = File.GetPosition() + new Vector3(VX * TerrainScale, VY * TerrainScale, 0); for (int k = 0; k < Indices.Length; k += 3) { Vector3 V0 = VertexWorldPosition + QuadVertices[Indices[k]]; Vector3 V1 = VertexWorldPosition + QuadVertices[Indices[k + 1]]; Vector3 V2 = VertexWorldPosition + QuadVertices[Indices[k + 2]]; if (CollisionUtil.Intersect(V0, V1, V2, Origin, Direction)) { TerrainGeometryContainer TerrainGeom = TerrainGeometries.Where(x => x.WorldFile.FileName == FileManager.CurrentWorldFile.FileName).First(); Vector3 CollisionPoint = CollisionUtil.GetCollisionPoint(V0, V1, V2, Origin, Direction); CollisionResult Result = new CollisionResult( V0, V1, V2, Origin, CollisionPoint, TerrainGeom.TerrainGeometry); Results.Add(Result); } } } } return(Results); }
/// <summary> /// 处理重叠,空函数 /// </summary> /// <param name="result"></param> /// <param name="objB"></param> public void HandleOverlap(CollisionResult result, ICollideObj objA, ICollideObj objB) { }
void Update() { this.resolve_collision(); float explode_time = 0.5f; // ---------------------------------------------------------------- // // 다음 상태로 전환할지 체크한다. switch(this.step.do_transition()) { case STEP.FLYING: { if(this.trigger_damage) { this.step.set_next(STEP.EXPLODE); } } break; case STEP.EXPLODE: { //if(this.explode_effect == null) { if(this.step.get_time() > explode_time) { this.step.set_next(STEP.END); } } break; } // ---------------------------------------------------------------- // // 상태 전환 시 초기화. while(this.step.get_next() != STEP.NONE) { switch(this.step.do_initialize()) { case STEP.FLYING: { } break; case STEP.EXPLODE: { this.model_node.GetComponent<Renderer>().enabled = false; this.explode_effect = EffectRoot.get().createYuzuExplode(this.gameObject.getPosition().Y(0.5f)); this.coli_node.setLocalScale(Vector3.one*this.max_radius*0.0f); } break; case STEP.END: { this.gameObject.destroy(); } break; } } // ---------------------------------------------------------------- // // 각 상태에서의 실행 처리. switch(this.step.do_execution(Time.deltaTime)) { case STEP.FLYING: { // 이동. this.velocity += Physics.gravity*Time.deltaTime; this.transform.position += this.velocity*Time.deltaTime; } break; case STEP.EXPLODE: { float rate = this.step.get_time()/explode_time; float scale = rate*this.max_radius; this.coli_node.setLocalScale(Vector3.one*scale); // 폭풍과의 충돌. // 콜라이더가 바닥에 충돌하면 그 다음 폭풍이 충돌해도 OnTriggerEnter가. // 호출되지 않으므로 직접 조사한다. RaycastHit hit; if(Physics.SphereCast(this.transform.position, scale*this.coli_sphere_radius, Vector3.up, out hit, float.MinValue, LayerMask.GetMask("Enemy", "EnemyLair"))) { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = hit.collider.gameObject; result.is_trigger = true; this.collision_results.Add(result); } } break; } }
void OnCollisionStay(Collision other) { switch(other.gameObject.tag) { case "Player": { chrBehaviorPlayer player = other.gameObject.GetComponent<chrBehaviorPlayer>(); if(player != null) { CollisionResult result = new CollisionResult(); result.object0 = this.gameObject; result.object1 = other.gameObject; result.is_trigger = false; this.collision_results.Add(result); } } break; } }
public static bool circleToPolygon( Circle circle, Polygon polygon, out CollisionResult result ) { result = new CollisionResult(); // circle position in the polygons coordinates var poly2Circle = circle.position - polygon.position; // first, we need to find the closest distance from the circle to the polygon float distanceSquared; var closestPoint = polygon.getClosestPointOnPolygonToPoint( poly2Circle, out distanceSquared, out result.normal ); // make sure the squared distance is less than our radius squared else we are not colliding if( distanceSquared > circle.radius * circle.radius ) return false; // figure out the mtd var distance = Mathf.sqrt( distanceSquared ); var mtv = ( poly2Circle - closestPoint ) * ( ( circle.radius - distance ) / distance ); result.minimumTranslationVector = -mtv; result.normal.Normalize(); return true; }