/// <summary> /// Finds overlaps with another obstacle's lines. /// </summary> /// <param name="other"></param> public void FindOverlaps(ObstacleHitLineGroup other) { //TODO: Toggleable obstacles (like doors or bridges) should each have a independant overlap group instead //of using a universal overlap group here. //For each outside-line in this and the other group, check for overlaps. If none, also check if one is entirely //in the other. }
private StructListStruct <int> FindOverlapsInner(int startIndex, int stopIndex, StructListStruct <int> linesToSkip, Vector surfaceNormal, Point start, Point end, Vector firstVector, Vector lineNormal, Vector nextFirstVector, Vector nextLineNormal, int i, ObstacleHitLineGroup otherGroup, StructListStruct <HitLineSetupOverlapData>[] setupOverlaps) { StructListStruct <int> nextLinesToSkip = default(StructListStruct <int>); Point secondEnd = StartPointOf(startIndex); //Initialize for j loop for (int j = startIndex; j < stopIndex; j++) { Point secondStart = secondEnd; secondEnd = otherGroup.EndPointOf(j); if (linesToSkip.Contains(j)) { continue; } bool collide; Point intersect = KejUtils.Geometry.Geometry.LineOverlapInPlane(start, end, secondStart, secondEnd, out collide); if (!collide) { continue; //Note: Parallel lines that overlap also 'don't collide'. This is okay as long as they are handled on the lines before/after them. } Vector secondVector = secondStart.VectorTo(secondEnd); Vector thirdVector = secondVector; double prevPrevDot = lineNormal.DotProduct(secondVector); double prevNextDot = prevPrevDot, nextPrevDot = prevPrevDot, nextNextDot = prevPrevDot; bool tiltLeft = false, nextI = false; if (intersect.Equals(start)) { Vector prevFirstVector; if (i == 0) { //Check for edge case of first line, with last line not parallel to j. prevFirstVector = StartPointOf(hitLines.Count - 1).VectorTo(StartPointOf(0)); Vector cross = prevFirstVector.CrossProduct(secondVector); if (cross.x != 0 || cross.y != 0 || cross.z != 0) { continue; //This will be handled later. Right now we don't want to do this. } } else { Point previousStart = StartPointOf(i - 1); prevFirstVector = previousStart.VectorTo(start); } //Previous line was parallel. Get the info for it. prevPrevDot = 0; prevNextDot = 0; Vector prevNormal = surfaceNormal.CrossProduct(prevFirstVector); tiltLeft = prevNormal.DotProduct(firstVector) > 0; if (intersect.Equals(secondStart)) { //TODO: Wait how does this case happen? I'm tempted to throw in a log statement to see if it ever happens. //Backtrack second vector one index. Point previousStart = otherGroup.StartPointOf(j - 1); secondVector = previousStart.VectorTo(secondStart); prevPrevDot = prevNormal.DotProduct(secondVector); nextPrevDot = lineNormal.DotProduct(secondVector); } else if (intersect.Equals(secondEnd)) { j++; //Skip the next line, it's known to start with this intersection and we're handling everything about it now. Point nextEnd = otherGroup.EndPointOf(j); thirdVector = secondEnd.VectorTo(nextEnd); prevNextDot = prevNormal.DotProduct(thirdVector); nextNextDot = lineNormal.DotProduct(thirdVector); } else { //Defaults are fine. } } else if (intersect.Equals(end)) { //The end of line i is on line j, so the start of line i+1 will also be on line j. //The intersection is being handled here in all cases, so always skip i+1 with j. StructListStruct <int> .Add(ref nextLinesToSkip, j); nextI = true; if (intersect.Equals(secondStart)) { //Seems safe to assume the previous lines were parallel. //Backtrack second vector one index. Point previousStart = otherGroup.StartPointOf(j - 1); secondVector = previousStart.VectorTo(secondStart); prevPrevDot = 0; nextPrevDot = nextLineNormal.DotProduct(secondVector); nextNextDot = nextLineNormal.DotProduct(thirdVector); tiltLeft = lineNormal.DotProduct(nextFirstVector) > 0; } else if (intersect.Equals(secondEnd)) { j++; //Skip the next line, it's known to start with this intersection and we're handling everything about it now. StructListStruct <int> .Add(ref linesToSkip, j); //Also skip i+1 with j+1 Point nextEnd = otherGroup.EndPointOf(j); thirdVector = secondEnd.VectorTo(nextEnd); prevNextDot = lineNormal.DotProduct(thirdVector); nextPrevDot = nextLineNormal.DotProduct(secondVector); nextNextDot = nextLineNormal.DotProduct(thirdVector); tiltLeft = lineNormal.DotProduct(nextFirstVector) > 0; } else { nextPrevDot = nextLineNormal.DotProduct(secondVector); nextNextDot = nextPrevDot; tiltLeft = lineNormal.DotProduct(nextFirstVector) > 0; } } else { if (intersect.Equals(secondStart)) { //Seems safe to assume the previous lines were parallel. //Backtrack second vector one index. Point previousStart = otherGroup.StartPointOf(j - 1); secondVector = previousStart.VectorTo(secondStart); prevPrevDot = 0; nextPrevDot = 0; } else if (intersect.Equals(secondEnd)) { j++; //Skip the next line, it's known to start with this intersection and we're handling everything about it now. Point nextEnd = otherGroup.EndPointOf(j); thirdVector = secondEnd.VectorTo(nextEnd); prevNextDot = lineNormal.DotProduct(thirdVector); } else { //Defaults are correct for this, do nothing } } int jTiltLeft = -1; int wasI = (prevPrevDot < 0) ? 1 : 0; wasI += (prevNextDot < 0) ? 1 : 0; if (wasI == 1 && !thirdVector.Equals(secondVector)) { jTiltLeft = surfaceNormal.CrossProduct(secondVector).DotProduct(thirdVector) > 0 ? 1 : 0; wasI += jTiltLeft; } int isI = (nextPrevDot > 0) ? 1 : 0; isI += (nextNextDot > 0) ? 1 : 0; if (wasI == 1 && !thirdVector.Equals(secondVector)) { if (jTiltLeft == -1) { jTiltLeft = surfaceNormal.CrossProduct(secondVector).DotProduct(thirdVector) > 0 ? 1 : 0; } isI += jTiltLeft; } int wasJ = (prevPrevDot > 0) ? 1 : 0; wasJ += (nextPrevDot > 0) ? 1 : 0; wasJ += tiltLeft ? 1 : 0; int isJ = (prevNextDot < 0) ? 1 : 0; isJ += (nextNextDot < 0) ? 1 : 0; isJ += tiltLeft ? 1 : 0; if (wasI >= 2 != isI >= 2) { HitLineSetupOverlapData newOverlap = new HitLineSetupOverlapData() { inside = (isI >= 2), intersect = intersect }; StructListStruct <HitLineSetupOverlapData> .Add(ref setupOverlaps[i + (nextI ? 1 : 0)], newOverlap); } if (wasJ >= 2 != isJ >= 2) { HitLineSetupOverlapData newOverlap = new HitLineSetupOverlapData() { inside = (isJ >= 2), intersect = intersect }; StructListStruct <HitLineSetupOverlapData> .Add(ref setupOverlaps[j], newOverlap); } } return(nextLinesToSkip); }