private static void CheckForAndManageCollision( ref Entity entity, ref Building building ) { if ( entity.AABB.Min.X > building.AABB.Max.X || entity.AABB.Max.X < building.AABB.Min.X || entity.AABB.Min.X > building.AABB.Max.X || entity.AABB.Max.X < building.AABB.Min.X ) { entity.Collision = 0; return; } // SAT part 2 here: tempAABBVerts[0] = entity.AABB.Min; tempAABBVerts[1] = new Vector2( entity.AABB.Min.X, entity.AABB.Max.Y ); tempAABBVerts[2] = entity.AABB.Max; tempAABBVerts[3] = new Vector2( entity.AABB.Max.X, entity.AABB.Min.Y ); int vertCount = building.Boundary.Length; for ( int i = 0; i < vertCount; ++i ) { float lower = float.MaxValue; float upper = float.MinValue; for ( int j = 0; j < 4; ++j ) { float proj = ( building.Boundary[i].X - tempAABBVerts[j].X ) * building.Normals[i].X + ( building.Boundary[i].Y - tempAABBVerts[j].Y ) * building.Normals[i].Y; if ( proj < lower ) lower = proj; if ( proj > upper ) upper = proj; } if ( upper < 0 || lower > building.SATProjections[i] ) { entity.Collision = 0; return; } } // resolve collision here: Vector2 bToA = Vector2.Zero; bToA.X = entity.NextPosition.X - building.Center.X; bToA.Y = entity.NextPosition.Z - building.Center.Y; // use difference to seperate entities Vector2 direction; Vector2.Normalize( ref bToA, out direction ); float resolveMoveSpeed = 2f; if ( entity.Collision == 0 || building.Index < entity.Collision ) { entity.Direction.X = resolveMoveSpeed * direction.X; entity.Direction.Z = resolveMoveSpeed * direction.Y; entity.Collision = 5; } }
private bool TestBuildingVsAABB( Building building, AABB aabb ) { Vector2 min = Vector2.Clamp( building.AABB.Min, Min, Max ); Vector2 max = Vector2.Clamp( building.AABB.Max, Min, Max ); float cellWidth = ( Max.X - Min.X ) / Cols; int colMin = (int)( ( min.X - Min.X ) / cellWidth ); int colMax = (int)( ( max.X - Min.X ) / cellWidth ); float cellHeight = ( Max.Y - Min.Y ) / Rows; int rowMin = (int)( ( min.Y - Min.Y ) / cellHeight ); int rowMax = (int)( ( max.Y - Min.Y ) / cellHeight ); // make sure the maxs don't go out of bounds if ( colMax == Cols ) colMax = colMin; if ( rowMax == Rows ) rowMax = rowMin; // test polygon's aabb against aabb (effectively aabb version of SAT) if ( aabb.Max.X < min.X || aabb.Min.X > max.X ) return false; if ( aabb.Max.Y < min.Y || aabb.Min.Y > max.Y ) return false; tempAABBVerts[0] = aabb.Min; tempAABBVerts[1] = new Vector2( aabb.Min.X, aabb.Max.Y ); tempAABBVerts[2] = aabb.Max; tempAABBVerts[3] = new Vector2( aabb.Max.X, aabb.Min.Y ); // SAT using building's axes for ( int i = 0; i < building.Boundary.Length; ++i ) { float lower = float.MaxValue; float upper = float.MinValue; for ( int j = 0; j < tempAABBVerts.Length; ++j ) { Vector2 disp = building.Boundary[i] - tempAABBVerts[j]; float proj = Vector2.Dot( disp, building.Normals[i] ); if ( proj < lower ) lower = proj; if ( proj > upper ) upper = proj; } if ( upper < 0 || lower > building.SATProjections[i] ) return false; } return true; }
private bool DetermineIfPathCellIsWalkable( AABB aabb, Building[] buildings ) { for ( int i = 0; i < buildings.Length; ++i ) { if ( TestBuildingVsAABB( buildings[i], aabb ) ) return false; } return true; }
public void RemoveBuilding( ref Building building ) { }
public void AddBuilding( ref Building building ) { Vector2 min = Vector2.Clamp( building.AABB.Min, Min, Max ); Vector2 max = Vector2.Clamp( building.AABB.Max, Min, Max ); float cellWidth = ( Max.X - Min.X ) / Cols; int colMin = (int)( ( min.X - Min.X ) / cellWidth ); int colMax = (int)( ( max.X - Min.X ) / cellWidth ); float cellHeight = ( Max.Y - Min.Y ) / Rows; int rowMin = (int)( ( min.Y - Min.Y ) / cellHeight ); int rowMax = (int)( ( max.Y - Min.Y ) / cellHeight ); // make sure the maxs don't go out of bounds if ( colMax == Cols ) colMax = colMin; if ( rowMax == Rows ) rowMax = rowMin; for ( int r = rowMin; r <= rowMax; ++r ) { for ( int c = colMin; c <= colMax; ++c ) { int index = Cols * r + c; if ( TestBuildingVsAABB( building, new AABB( cells[index].Min, cells[index].Max ) ) ) cells[index].Buildings.Add( building.Index ); } } }
public static void PopulateGrid( Entity[] entities, Building[] buildings ) { for ( int i = 0; i < entities.Length; ++i ) grid.AddEntity( ref entities[i] ); for ( int i = 0; i < buildings.Length; ++i ) grid.AddBuilding( ref buildings[i] ); grid.InitializePathGrid( 6 ); }