예제 #1
0
        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));
        }
예제 #2
0
        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;
        }