void CollideWithReachableBlocks(int count, ref AABB entityBB, ref AABB extentBB) { // Reset collision detection states bool wasOn = entity.onGround; entity.onGround = false; hitXMin = false; hitYMin = false; hitZMin = false; hitXMax = false; hitYMax = false; hitZMax = false; AABB blockBB; Vector3 bPos, size = entity.Size; for (int i = 0; i < count; i++) { // Unpack the block and coordinate data State state = Searcher.stateCache[i]; bPos.X = state.X >> 3; bPos.Y = state.Y >> 4; bPos.Z = state.Z >> 3; int block = (state.X & 0x7) | (state.Y & 0xF) << 3 | (state.Z & 0x7) << 7; blockBB.Min = BlockInfo.MinBB[block]; blockBB.Min.X += bPos.X; blockBB.Min.Y += bPos.Y; blockBB.Min.Z += bPos.Z; blockBB.Max = BlockInfo.MaxBB[block]; blockBB.Max.X += bPos.X; blockBB.Max.Y += bPos.Y; blockBB.Max.Z += bPos.Z; if (!extentBB.Intersects(blockBB)) { continue; } // Recheck time to collide with block (as colliding with blocks modifies this) float tx, ty, tz; Searcher.CalcTime(ref entity.Velocity, ref entityBB, ref blockBB, out tx, out ty, out tz); if (tx > 1 || ty > 1 || tz > 1) { Utils.LogDebug("t > 1 in physics calculation.. this shouldn't have happened."); } // Calculate the location of the entity when it collides with this block Vector3 v = entity.Velocity; v.X *= tx; v.Y *= ty; v.Z *= tz; AABB finalBB = entityBB; finalBB.Min += v; finalBB.Max += v; // Inlined ABBB.Offset // if we have hit the bottom of a block, we need to change the axis we test first. if (!hitYMin) { if (finalBB.Min.Y + Adjustment >= blockBB.Max.Y) { ClipYMax(ref blockBB, ref entityBB, ref extentBB, ref size); } else if (finalBB.Max.Y - Adjustment <= blockBB.Min.Y) { ClipYMin(ref blockBB, ref entityBB, ref extentBB, ref size); } else if (finalBB.Min.X + Adjustment >= blockBB.Max.X) { ClipXMax(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size); } else if (finalBB.Max.X - Adjustment <= blockBB.Min.X) { ClipXMin(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size); } else if (finalBB.Min.Z + Adjustment >= blockBB.Max.Z) { ClipZMax(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size); } else if (finalBB.Max.Z - Adjustment <= blockBB.Min.Z) { ClipZMin(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size); } continue; } // if flying or falling, test the horizontal axes first. if (finalBB.Min.X + Adjustment >= blockBB.Max.X) { ClipXMax(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size); } else if (finalBB.Max.X - Adjustment <= blockBB.Min.X) { ClipXMin(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size); } else if (finalBB.Min.Z + Adjustment >= blockBB.Max.Z) { ClipZMax(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size); } else if (finalBB.Max.Z - Adjustment <= blockBB.Min.Z) { ClipZMin(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size); } else if (finalBB.Min.Y + Adjustment >= blockBB.Max.Y) { ClipYMax(ref blockBB, ref entityBB, ref extentBB, ref size); } else if (finalBB.Max.Y - Adjustment <= blockBB.Min.Y) { ClipYMin(ref blockBB, ref entityBB, ref extentBB, ref size); } } }
void CollideWithReachableBlocks(int count, ref Vector3 size, ref AABB entityBB, ref AABB entityExtentBB) { bool wasOn = entity.onGround; entity.onGround = false; hitXMin = false; hitYMin = false; hitZMin = false; hitXMax = false; hitYMax = false; hitZMax = false; AABB blockBB = default(AABB); for (int i = 0; i < count; i++) { State state = Searcher.stateCache[i]; Vector3 blockPos = new Vector3(state.X >> 3, state.Y >> 3, state.Z >> 3); int block = (state.X & 0x7) | (state.Y & 0x7) << 3 | (state.Z & 0x7) << 6; blockBB.Min = blockPos + info.MinBB[block]; blockBB.Max = blockPos + info.MaxBB[block]; if (!entityExtentBB.Intersects(blockBB)) { continue; } float tx = 0, ty = 0, tz = 0; Searcher.CalcTime(ref entity.Velocity, ref entityBB, ref blockBB, out tx, out ty, out tz); if (tx > 1 || ty > 1 || tz > 1) { Utils.LogDebug("t > 1 in physics calculation.. this shouldn't have happened."); } Vector3 v = entity.Velocity; v.X *= tx; v.Y *= ty; v.Z *= tz; AABB finalBB = entityBB.Offset(v); // if we have hit the bottom of a block, we need to change the axis we test first. if (!hitYMin) { if (finalBB.Min.Y + Adjustment >= blockBB.Max.Y) { ClipYMax(ref blockBB, ref entityBB, ref entityExtentBB, ref size); } else if (finalBB.Max.Y - Adjustment <= blockBB.Min.Y) { ClipYMin(ref blockBB, ref entityBB, ref entityExtentBB, ref size); } else if (finalBB.Min.X + Adjustment >= blockBB.Max.X) { ClipXMax(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size); } else if (finalBB.Max.X - Adjustment <= blockBB.Min.X) { ClipXMin(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size); } else if (finalBB.Min.Z + Adjustment >= blockBB.Max.Z) { ClipZMax(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size); } else if (finalBB.Max.Z - Adjustment <= blockBB.Min.Z) { ClipZMin(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size); } continue; } // if flying or falling, test the horizontal axes first. if (finalBB.Min.X + Adjustment >= blockBB.Max.X) { ClipXMax(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size); } else if (finalBB.Max.X - Adjustment <= blockBB.Min.X) { ClipXMin(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size); } else if (finalBB.Min.Z + Adjustment >= blockBB.Max.Z) { ClipZMax(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size); } else if (finalBB.Max.Z - Adjustment <= blockBB.Min.Z) { ClipZMin(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size); } else if (finalBB.Min.Y + Adjustment >= blockBB.Max.Y) { ClipYMax(ref blockBB, ref entityBB, ref entityExtentBB, ref size); } else if (finalBB.Max.Y - Adjustment <= blockBB.Min.Y) { ClipYMin(ref blockBB, ref entityBB, ref entityExtentBB, ref size); } } }