public override void MarkIntersectWithSurface(ObstacleSurface otherSurface, MovementMechanism forMechanism) { Hitbox hitbox = forMechanism.Hitbox; switch (hitbox.Type) { case Hitbox.HitboxType.Square: { //SquareHitbox square = hitbox as SquareHitbox; } break; default: throw new NotImplementedException("Unknown hitbox type"); } SimpleVolume vol = MyVolume; Orientation offset = forMechanism.HitboxOffset(otherSurface); //Reverse changes to find how this object intersects with original surface instead of the other way around. vol.MinX = vol.MinX - offset.x - hitbox.MaxXIncrease((Rotation)offset); vol.MaxX = vol.MaxX - offset.x + hitbox.MaxXDecrease((Rotation)offset); vol.MinY = vol.MinY - offset.y - hitbox.MaxYIncrease((Rotation)offset); vol.MaxY = vol.MaxY - offset.y + hitbox.MaxYDecrease((Rotation)offset); vol.MinZ = vol.MinZ - offset.z - hitbox.MaxZIncrease((Rotation)offset); vol.MaxZ = vol.MaxZ - offset.z + hitbox.MaxZDecrease((Rotation)offset); Vector normal = otherSurface.GetNormal(); int height = otherSurface.GetHeight(); //Important: These indices match the obstacle point indices. int[] differences = new int[8]; differences[0] = (int)normal.DotProduct(vol.MinX, vol.MinY, vol.MinZ) - height; differences[1] = (int)normal.DotProduct(vol.MaxX, vol.MinY, vol.MinZ) - height; differences[2] = (int)normal.DotProduct(vol.MaxX, vol.MaxY, vol.MinZ) - height; differences[3] = (int)normal.DotProduct(vol.MinX, vol.MaxY, vol.MinZ) - height; differences[4] = (int)normal.DotProduct(vol.MinX, vol.MinY, vol.MaxZ) - height; differences[5] = (int)normal.DotProduct(vol.MaxX, vol.MinY, vol.MaxZ) - height; differences[6] = (int)normal.DotProduct(vol.MaxX, vol.MaxY, vol.MaxZ) - height; differences[7] = (int)normal.DotProduct(vol.MinX, vol.MaxY, vol.MaxZ) - height; List <int> negativeHeights = new List <int>(8); List <int> positiveHeights = new List <int>(8); if (differences[0] > 0) { positiveHeights.Add(0); } else { negativeHeights.Add(0); } if (differences[1] > 0) { positiveHeights.Add(1); } else { negativeHeights.Add(1); } if (differences[2] > 0) { positiveHeights.Add(2); } else { negativeHeights.Add(2); } if (differences[3] > 0) { positiveHeights.Add(3); } else { negativeHeights.Add(3); } if (differences[4] > 0) { positiveHeights.Add(4); } else { negativeHeights.Add(4); } if (differences[5] > 0) { positiveHeights.Add(5); } else { negativeHeights.Add(5); } if (differences[6] > 0) { positiveHeights.Add(6); } else { negativeHeights.Add(6); } if (differences[7] > 0) { positiveHeights.Add(7); } else { negativeHeights.Add(7); } if (positiveHeights.Count == 0 || negativeHeights.Count == 0) { return; } for (int i = 0; i < negativeHeights.Count; i++) { int pointId = negativeHeights[i]; for (int j = 0; j < 3; j++) { SurfaceLine line = PointLine(pointId, j); ObstaclePoint otherPoint = line.Start; if (otherPoint.id == pointId) { otherPoint = line.End; } if (differences[otherPoint.id] > 0) { double ratio = differences[pointId] / (differences[pointId] - differences[otherPoint.id]); Point start = PointPosition(pointId); Point end = otherPoint.Position; Point intersectPoint; intersectPoint.x = start.x + (int)((end.x - start.x) * ratio); intersectPoint.y = start.y + (int)((end.y - start.y) * ratio); intersectPoint.z = start.z + (int)((end.z - start.z) * ratio); List <Point> IntersectingPoints = new List <Point>(); IntersectingPoints.Add(intersectPoint); SurfaceLine previousLine = line; SurfaceLine nextLine = new SurfaceLine(); //compiler has failed me for once, this shouldn't need initialization here. int previousSurfaceId = -1; do { ObstacleSurface nextSurface = previousLine.Left; if (previousSurfaceId == nextSurface.surfaceIndex) { nextSurface = previousLine.Right; } for (int k = 0; k < 4; k++) { nextLine = nextSurface.GetLine(k); if (nextLine.id == previousLine.id) { continue; } ObstaclePoint nextStart = nextLine.Start; ObstaclePoint nextEnd = nextLine.End; if ((differences[nextStart.id] > 0 && differences[nextEnd.id] <= 0) || (differences[nextStart.id] <= 0 && differences[nextEnd.id] > 0)) { start = nextStart.Position; end = nextEnd.Position; ratio = differences[nextStart.id] / (differences[nextStart.id] - differences[nextEnd.id]); intersectPoint.x = start.x + (int)((end.x - start.x) * ratio); intersectPoint.y = start.y + (int)((end.y - start.y) * ratio); intersectPoint.z = start.z + (int)((end.z - start.z) * ratio); IntersectingPoints.Add(intersectPoint); break; } } previousSurfaceId = nextSurface.surfaceIndex; previousLine = nextLine; }while (nextLine.id != line.id); otherSurface.AddIntersectLines(IntersectingPoints, this, forMechanism); return; } } } }
public void AddIntersectLines(List <Point> points, int surfaceIndex, Obstacle forObstacle, MovementMechanism forMechanism) { VolumeTree <ObstacleHitLine> collection = SurfaceObstacleLines[surfaceIndex]; if (collection == null) { SimpleVolume surfaceVolume = MyVolume; switch (surfaceIndex) { case 0: surfaceVolume.MaxZ = surfaceVolume.MinZ; break; case 1: surfaceVolume.MinZ = surfaceVolume.MaxZ; break; case 2: surfaceVolume.MaxY = surfaceVolume.MinY; break; case 3: surfaceVolume.MinX = surfaceVolume.MaxX; break; case 4: surfaceVolume.MinY = surfaceVolume.MaxY; break; case 5: surfaceVolume.MaxX = surfaceVolume.MinX; break; } collection = new VolumeTree <ObstacleHitLine>(surfaceVolume); SurfaceObstacleLines[surfaceIndex] = collection; } ObstacleHitLineGroup lineGroup = new ObstacleHitLineGroup(); lineGroup.CausingObstacle = forObstacle; lineGroup.Mechanism = forMechanism; lineGroup.SetupPoints(points, collection, SurfaceNormal(surfaceIndex)); }