public static void ReadInList(List <IntersectInfo> listToPopulate, StreamReader reader) { int count; int.TryParse(reader.ReadLine(), NumberStyles.Number, null, out count); for (int i = 0; i < count; i++) { IntersectInfo info = new IntersectInfo(); string line = reader.ReadLine(); string[] strings = line.Split(','); if (strings[0] == IntersectionType.FrontFace.ToString()) { info.hitType = IntersectionType.FrontFace; } else { if (strings[0] != IntersectionType.BackFace.ToString()) { throw new Exception("Has to be back or front."); } info.hitType = IntersectionType.BackFace; } double.TryParse(strings[1], NumberStyles.Number, null, out info.distanceToHit); listToPopulate.Add(info); } }
public IntersectInfo(IntersectInfo copyInfo) { this.hitType = copyInfo.hitType; this.closestHitObject = copyInfo.closestHitObject; this.hitPosition = copyInfo.hitPosition; this.normalAtHit = copyInfo.normalAtHit; this.distanceToHit = copyInfo.distanceToHit; }
public IntersectInfo GetClosestIntersection(Ray ray) { if (ray.Intersection(Aabb)) { IPrimitive checkFirst = nodeA; IPrimitive checkSecond = nodeB; if (ray.directionNormal[splitingPlane] < 0) { checkFirst = nodeB; checkSecond = nodeA; } IntersectInfo infoFirst = checkFirst.GetClosestIntersection(ray); if (infoFirst != null && infoFirst.hitType != IntersectionType.None) { if (ray.isShadowRay) { return(infoFirst); } else { ray.maxDistanceToConsider = infoFirst.distanceToHit; } } if (checkSecond != null) { IntersectInfo infoSecond = checkSecond.GetClosestIntersection(ray); if (infoSecond != null && infoSecond.hitType != IntersectionType.None) { if (ray.isShadowRay) { return(infoSecond); } else { ray.maxDistanceToConsider = infoSecond.distanceToHit; } } if (infoFirst != null && infoFirst.hitType != IntersectionType.None && infoFirst.distanceToHit >= 0) { if (infoSecond != null && infoSecond.hitType != IntersectionType.None && infoSecond.distanceToHit < infoFirst.distanceToHit && infoSecond.distanceToHit >= 0) { return(infoSecond); } else { return(infoFirst); } } return(infoSecond); // we don't have to test it because it didn't hit. } return(infoFirst); } return(null); }
private static bool GetRemoveRegion(List <IntersectInfo> subtractList, int startIndex, out int regionStartIndex, out int regionEndIndex) { regionStartIndex = startIndex; regionEndIndex = startIndex; double insideCount = 0; int subtractCount = subtractList.Count; for (int subtractIndex = startIndex; subtractIndex < subtractCount; subtractIndex++) { IntersectInfo subtractInfo = subtractList[subtractIndex]; if (subtractInfo.hitType == IntersectionType.FrontFace) { if (insideCount == 0) { regionStartIndex = subtractIndex; } insideCount++; } else if (subtractInfo.hitType == IntersectionType.BackFace) { if (insideCount == 0) { throw new Exception("You should not have a back face without a matching front face."); } insideCount--; if (insideCount == 0) { // let's check that there is not another entry aligned exactly with this exit int nextIndex = subtractIndex + 1; if (nextIndex >= subtractCount || subtractList[subtractIndex].distanceToHit + Ray.sameSurfaceOffset < subtractList[nextIndex].distanceToHit) { // we have our subtract region regionEndIndex = subtractIndex; return(true); } } } else { throw new Exception("There should be no 'none's in the hit types."); } } return(false); }
public IntersectInfo GetClosestIntersection(Ray ray) { IntersectInfo bestInfo = null; foreach (IPrimitive item in items) { IntersectInfo info = item.GetClosestIntersection(ray); if (info != null && info.hitType != IntersectionType.None && info.distanceToHit >= 0) { if (bestInfo == null || info.distanceToHit < bestInfo.distanceToHit) { bestInfo = info; } } } return(bestInfo); }
private static bool IsInside(List <IntersectInfo> listToCheck, double distance) { int insideCount = 0; int conut = listToCheck.Count; for (int index = 0; index < conut; index++) { IntersectInfo info = listToCheck[index]; if (info.hitType == HitType.FrontFace) { if (insideCount == 0) { startSubtract = info.distanceToHit; // add all the elements from the last end to the new start } insideCount++; } else if (info.hitType == HitType.BackFace) { insideCount--; if (insideCount == 0) { if (IsInside(allPrimary, info.distanceToHit)) { result.Add(info); } lastSubtractEnd = info.distanceToHit; // add all the front face points between lastSubtractEnd and startSubtract } } else { throw new Exception("There should be no 'none's in the hit types."); } } return(false); }
private static void SubtractRemoveRegion(List <IntersectInfo> removeFrom, IntersectInfo startRemoveInfo, IntersectInfo endRemoveInfo) { if (startRemoveInfo.hitType != IntersectionType.FrontFace || endRemoveInfo.hitType != IntersectionType.BackFace) { throw new Exception("These should always be set right."); } double insideCount = 0; for (int primaryIndex = 0; primaryIndex < removeFrom.Count; primaryIndex++) { IntersectInfo primaryInfo = removeFrom[primaryIndex]; if (primaryInfo.hitType == IntersectionType.FrontFace) { insideCount++; if (primaryInfo.distanceToHit < (startRemoveInfo.distanceToHit - Ray.sameSurfaceOffset)) { // We are in front of the remove start. If the next backface is behind the remove start, add a back face at the remove start. // there should always be a back face so it should be safe to + 1 this index. I will let the bounds checker get it because it will throw an assert. If not I would throw one instead. if (removeFrom[primaryIndex + 1].distanceToHit > (startRemoveInfo.distanceToHit - Ray.sameSurfaceOffset)) { IntersectInfo newBackFace = new IntersectInfo(startRemoveInfo); newBackFace.hitType = IntersectionType.BackFace; removeFrom.Insert(primaryIndex + 1, newBackFace); // it goes after the current index primaryIndex++; } } else if (primaryInfo.distanceToHit >= (startRemoveInfo.distanceToHit - Ray.sameSurfaceOffset) && primaryInfo.distanceToHit < (endRemoveInfo.distanceToHit + Ray.sameSurfaceOffset)) { // the front face is within the remove so remove it. removeFrom.Remove(primaryInfo); // need to check the same index again. primaryIndex--; } else if (primaryInfo.distanceToHit >= (endRemoveInfo.distanceToHit + Ray.sameSurfaceOffset)) { // we have gone past the remove region just return. return; } } else if (primaryInfo.hitType == IntersectionType.BackFace) { if (insideCount == 0) { throw new Exception("You should not have a back face without a matching front face."); } insideCount--; if (insideCount == 0) { if (primaryInfo.distanceToHit > (startRemoveInfo.distanceToHit - Ray.sameSurfaceOffset) && primaryInfo.distanceToHit < (endRemoveInfo.distanceToHit + Ray.sameSurfaceOffset)) { // the back face is within the remove so remove it. removeFrom.Remove(primaryInfo); // need to check the same index again. primaryIndex--; } else if (primaryInfo.distanceToHit >= (endRemoveInfo.distanceToHit + Ray.sameSurfaceOffset)) { // the back face is past the remove distance. // Add the remove back face as a front face to the primary // We should be guaranteed that the front face is within the remove distance because if it was we should have returned above. IntersectInfo newFrontFace = new IntersectInfo(endRemoveInfo); newFrontFace.hitType = IntersectionType.FrontFace; removeFrom.Insert(primaryIndex, newFrontFace); primaryIndex++; } } else { if (primaryInfo.distanceToHit > (startRemoveInfo.distanceToHit - Ray.sameSurfaceOffset) && primaryInfo.distanceToHit < (endRemoveInfo.distanceToHit + Ray.sameSurfaceOffset)) { // the back face is within the remove so remove it. removeFrom.Remove(primaryInfo); // need to check the same index again. primaryIndex--; } } } else { throw new Exception("There should be no 'none's in the hit types."); } } }