private static BezierQuadratic3 ApplyDisambiguator(BezierQuadratic3 bezier, int disambiguator) { var offset = bezier.P2.X >= bezier.P0.X ? BuildingConstants.CorridorDisambiguationOffset * disambiguator * Vector3.UnitZ : -BuildingConstants.CorridorDisambiguationOffset * disambiguator * Vector3.UnitZ; if (disambiguator % 2 == 1) { offset = -offset; } return(new BezierQuadratic3(bezier.P0 + offset, bezier.P1 + offset, bezier.P2 + offset)); }
public BuildingStoryPath(BuildingStoryLayoutPlacementAlgorithm pa, IStoryGraph sg, CameraProps initialCameraProps, int endNodeId, NavigationState navigationState, bool interLevel) { this.pa = pa; this.sg = sg; beziers = new List <BezierQuadratic3>(); var closestNode = sg.Leaves.Minimal(x => (BuildingConstants.LeafHalfSize.Depth * Vector3.UnitZ * GetGlobalTransform(x) - initialCameraProps.Frame.Eye).LengthSquared()); //var closestNodeGlobalTransform = GetGlobalTransform(endNodeId); //var closestNodeCenter = Vector3.Zero * closestNodeGlobalTransform; //var closestNodeConnector = BuildingConstants.LeafHalfSize.Depth * Vector3.UnitZ * closestNodeGlobalTransform; if (closestNode != endNodeId || interLevel) { if (!interLevel && sg.TryFindShortestPath(closestNode, endNodeId, out var nodePath)) { foreach (var edge in nodePath.SequentialPairs()) { IEnumerable <BezierQuadratic3> pathToAdd; if (pa.Lanes.TryGetValue(edge, out var lane)) { pathToAdd = lane.GlobalPath; } else if (pa.Lanes.TryGetValue(edge.Reverse(), out lane)) { pathToAdd = lane.GlobalPath.Reverse().Select(x => x.Reverse()); } else { throw new Exception("Path search returned an unexisting path."); } beziers.AddRange(pathToAdd.Skip(1).ExceptLast()); } } else { var endNode = sg.NodeObjects[endNodeId]; var aEndFocus = endNode.GetComponent <IFocusNodeComponent>(); var endCameraInfo = aEndFocus.DefaultViewpointMechanism.FixedCamera.GetProps(); directPath = new DirectStoryPath(initialCameraProps, endCameraInfo, 1f); } } switch (navigationState) { case NavigationState.AtNode: break; case NavigationState.AtForwardFork: { var nextEdge = new Pair <int>(endNodeId, sg.Next[endNodeId].First()); var nextLane = pa.Lanes[nextEdge]; var lastBezier = nextLane.GlobalPath.First(); var point = lastBezier.At(1); var tangent = lastBezier.TangentAt(1); beziers.Add(BezierQuadratic3.Straight(point - tangent, point)); break; } case NavigationState.AtBackwardFork: { var nextEdge = new Pair <int>(sg.Previous[endNodeId].First(), endNodeId); var nextLane = pa.Lanes[nextEdge]; var lastBezier = nextLane.GlobalPath.Last().Reverse(); var point = lastBezier.At(1); var tangent = lastBezier.TangentAt(1); beziers.Add(BezierQuadratic3.Straight(point - tangent, point)); break; } default: throw new ArgumentOutOfRangeException(nameof(navigationState), navigationState, null); } foreach (var indexPair in Enumerable.Range(0, beziers.Count).SequentialPairs()) { if (beziers[indexPair.First].P2 != beziers[indexPair.Second].P0) { var avg = (beziers[indexPair.First].P2 + beziers[indexPair.Second].P0) / 2; beziers[indexPair.First] = beziers[indexPair.First].With((ref BezierQuadratic3 b) => b.P2 = avg); beziers[indexPair.Second] = beziers[indexPair.Second].With((ref BezierQuadratic3 b) => b.P0 = avg); } } if (!beziers.Any()) { beziers.Add(BezierQuadratic3.Straight(initialCameraProps.Frame.Eye, initialCameraProps.Frame.Eye + initialCameraProps.Frame.Forward)); } path = beziers .SelectMany(x => x.ToEnumPolyline(BezierTolerance)) .SequentialPairs() .Select(x => new PathSegment(x.First, x.Second)) .Where(x => x.Length > 0) .ToArray(); currentCameraProps = initialCameraProps; }