public IStoryLayoutInstance ArrangeAndDecorate(IStoryGraph sg)
        {
            var springModel = new NestedCirclesStorySpringModel(coroutineService, x => ArrangeAndDecorateInternal(sg.Root, 0, x, sg), sg);

            springModel.Apply();
            return(new BasicStoryLayoutInstance(sg));
        }
Esempio n. 2
0
        private static Dictionary <int, List <int> > BuildNodeExternalConnections(IStoryGraph sg)
        {
            var result = new Dictionary <int, List <int> >();

            result.GetOrAdd(sg.Leaves.First(), x => new List <int>());
            result.GetOrAdd(sg.Leaves.Last(), x => new List <int>());
            foreach (var edge in sg.Edges)
            {
                var commonParent = sg.GetCommonParent(edge.First, edge.Second);

                var first = edge.First;
                while (sg.Parents[first] != commonParent)
                {
                    var list = result.GetOrAdd(first, x => new List <int>());
                    list.Add(edge.Second);
                    first = sg.Parents[first];
                }

                var second = edge.Second;
                while (sg.Parents[second] != commonParent)
                {
                    var list = result.GetOrAdd(second, x => new List <int>());
                    list.Add(edge.First);
                    second = sg.Parents[second];
                }
            }
            return(result);
        }
Esempio n. 3
0
        private void ArrangeAndDecorateLeaf(int nodeIndex, IStoryGraph sg)
        {
            var aStory = sg.Aspects[nodeIndex];
            var node   = sg.NodeObjects[nodeIndex];

            var wallVisuals    = CorridorWall(Quaternion.Identity, Vector3.UnitY * FrustumDistance);
            var frustumVisuals = ModelVisualElement.New()
                                 .SetModel(frustumModel)
                                 .SetMaterial(frustumMaterial)
                                 .SetRenderState(StandardRenderState.New()
                                                 .SetCullFace(CullFace.Back)
                                                 .FromGlobalCache())
                                 .SetTransform(new Transform(1, Quaternion.RotationX(-MathHelper.PiOver2), Vector3.Zero));
            var visuals = new [] { frustumVisuals, wallVisuals };

            var viewpointProps = new TargetedControlledCamera.Props
            {
                Target      = Vector3.Zero,
                Distance    = FrustumDistance,
                FieldOfView = MathHelper.PiOver4,
                ZNear       = 0.1f * FrustumDistance,
                ZFar        = 100.0f * FrustumDistance
            };

            var transform2D = new Transform(2, Quaternion.RotationX(-MathHelper.PiOver2), FrustumDistance * Vector3.UnitY);

            aStory.SetDynamicParts(new StoryNodeDynamicParts
            {
                DefaultViewpointMechanism = new WallDefaultViewpointMechanismZ(node, viewpointProps),
                Hittable       = GetHittableComponent(node, transform2D),
                VisualElements = visuals
            });
        }
Esempio n. 4
0
 private void OnStoryGraphChanged()
 {
     sg = storyService.GlobalGraph;
     Reset(sg.NodeIds.Contains(current)
         ? current
         : sg.Root);
 }
Esempio n. 5
0
 public FlowchartTunnelDigger(IStoryGraph graph)
 {
     sg        = graph;
     grids     = graph.NonLeaves.ToDictionary(x => x, x => new FlowchartGrid());
     sizes     = new Size2[graph.EnoughIntegers.Count];
     positions = new Vector2[graph.EnoughIntegers.Count];
     nodeCols  = sg.EnoughIntegers.Select(x => - 1).ToArray();
 }
Esempio n. 6
0
 public void OnWorldRootChanged(ISceneNode newRoot, IStoryGraph newSg)
 {
     gizmosByNodes.Clear();
     edgeGizmos.Clear();
     Node.ChildNodes.Clear();
     CreateGizmosForSubtree(newRoot, 0);
     OnGraphUpdated(newSg);
 }
Esempio n. 7
0
 public BuildingStoryLayoutInstance(IInputService inputService, BuildingStoryLayoutPlacementAlgorithm placementAlgorithm,
                                    ICollisionMesh collisionMesh, IStoryLayoutZoning zoning)
 {
     this.placementAlgorithm = placementAlgorithm;
     this.collisionMesh      = collisionMesh;
     this.zoning             = zoning;
     this.inputService       = inputService;
     sg = placementAlgorithm.StoryGraph;
 }
 public BuildingLaneBuilder(IStoryGraph sg, Func <int, Transform> getLocalTransform)
 {
     this.sg = sg;
     this.getLocalTransform = getLocalTransform;
     lanes       = new Dictionary <Pair <int>, BuildingLane>();
     rawPoints   = new List <Vector3>();
     rawSegments = new List <BuildingRawLaneSegment>();
     rawSegmentsByParentNodes = new Dictionary <int, List <BuildingRawLaneSegment> >();
 }
Esempio n. 9
0
        private void OnGraphUpdated(IStoryGraph newSg)
        {
            UpdateRouteEdges(newSg);
            Rearrange(newSg);

            // digger only
            flowchartTunnelDigger = new FlowchartTunnelDigger(newSg);
            ApplyDigger();
            AdjustEdgeGizmos();
            FixNames();
        }
Esempio n. 10
0
        private static IEnumerable <int> EnumerateParentChain(IStoryGraph sg, int node)
        {
            var parent = sg.Parents[node];

            while (parent != sg.Parents[sg.Root])
            {
                yield return(parent);

                parent = sg.Parents[parent];
            }
        }
 public NestedCirclesStorySpringModel(ICoroutineService coroutineService, Action <NestedCirclesStorySpringModel> visualize, IStoryGraph sg)
 {
     Debug.Assert(SpringConstant * IterationDeltaT < 1, "SpringConstant * IterationDeltaT < 1");
     this.coroutineService = coroutineService;
     this.visualize        = visualize;
     this.sg = sg;
     nodeExternalConnections = BuildNodeExternalConnections(sg);
     positions    = new Vector2[sg.EnoughIntegers.Count];
     oldPositions = new Vector2[sg.EnoughIntegers.Count];
     radii        = new float[sg.EnoughIntegers.Count];
     placed       = new bool[sg.EnoughIntegers.Count];
 }
Esempio n. 12
0
 public BuildingStoryLayoutPlacementAlgorithm(ICoroutineService coroutineService, Action <BuildingStoryLayoutPlacementAlgorithm> visualize, IStoryGraph sg)
 {
     this.coroutineService = coroutineService;
     this.visualize        = visualize;
     this.sg            = sg;
     laneBuilder        = new BuildingLaneBuilder(sg, x => relativeTransforms[x]);
     nodeRows           = sg.EnoughIntegers.Select(x => - 1).ToArray();
     grids              = sg.EnoughIntegers.ToDictionary(x => x, x => new BuildingStoryLayoutAbstractGrid());
     relPositions       = new Vector3[sg.EnoughIntegers.Count];
     halfSizes          = new Size3[sg.EnoughIntegers.Count];
     isReversed         = new bool[sg.EnoughIntegers.Count];
     relativeTransforms = new Dictionary <int, Transform>();
 }
Esempio n. 13
0
        private void UpdateRouteEdges(IStoryGraph storyGraph)
        {
            var allRouteEdges = new HashSet <UnorderedPair <ISceneNode> >(storyGraph.Edges
                                                                          .Select(x => new UnorderedPair <ISceneNode>(storyGraph.NodeObjects[x.First], storyGraph.NodeObjects[x.Second])));
            var deathNote = edgeGizmos.Keys.Where(x => x.Second.ParentNode != x.First && !allRouteEdges.Contains(x)).ToList();

            foreach (var key in deathNote)
            {
                DeleteEdge(key);
            }
            foreach (var key in allRouteEdges.Where(x => !edgeGizmos.ContainsKey(x)))
            {
                AddNewEdge(key, routeMaterial, routeRenderState);
            }
        }
Esempio n. 14
0
        private void ArrangeAndDecorateInternal(IStoryGraph sg, int nodeIndex, int scaleLevel)
        {
            var aStory           = sg.Aspects[nodeIndex];
            var node             = sg.NodeObjects[nodeIndex];
            var abstractChildren = sg.Children[nodeIndex];
            var numChildren      = abstractChildren.Count;

            var scale = MathHelper.Pow(4, scaleLevel);

            var visuals = new []
            {
                ModelVisualElement.New()
                .SetModel(planeModel)
                .SetMaterial(planeMaterials[scaleLevel % planeMaterials.Length])
                .SetTransform(Transform.Scaling(10 * scale))
            };

            var viewpointProps = new FreeControlledCamera.Props
            {
                Eye         = Vector3.UnitZ * 10f * scale,
                Yaw         = MathHelper.PiOver4,
                Pitch       = MathHelper.PiOver4,
                FieldOfView = MathHelper.PiOver4,
                ZNear       = 0.1f * scale,
                ZFar        = 100.0f * scale
            };

            for (var i = 0; i < numChildren; i++)
            {
                var adaptiveChild = abstractChildren[i];
                var angle         = MathHelper.TwoPi * i / numChildren - MathHelper.PiOver4;
                var rotation      = Quaternion.RotationZ(angle);
                var radius        = scale * GetBestRadius(numChildren);

                var offset = new Vector3(radius * MathHelper.Sin(angle), radius * MathHelper.Cos(angle), 0.1f * scale);
                sg.NodeObjects[adaptiveChild].Transform = new Transform(1, rotation, offset);
                ArrangeAndDecorateInternal(sg, adaptiveChild, scaleLevel - 1);
            }

            aStory.SetDynamicParts(new StoryNodeDynamicParts
            {
                DefaultViewpointMechanism = new FreeLandDefaultViewpointMechanism(node, viewpointProps, keyboardInputProvider),
                Hittable       = GetHittableComponent(node),
                VisualElements = visuals
            });
        }
Esempio n. 15
0
        private void ArrangeIntermediateNode(int node, int depthHeight, IStoryGraph storyGraph)
        {
            var aNode      = storyGraph.Aspects[node];
            var gizmo      = gizmosByNodes[aNode.Node];
            var firstLeafX = gizmosByNodes[storyGraph.Leaves.Select(x => storyGraph.NodeObjects[x]).First(x => x.IsDescendantOf(aNode.Node))].Transform.Offset.X;
            var lastLeafX  = gizmosByNodes[storyGraph.Leaves.Select(x => storyGraph.NodeObjects[x]).Last(x => x.Node.IsDescendantOf(aNode.Node)).Node].Transform.Offset.X;

            gizmo.Transform = Transform.Translation((firstLeafX + lastLeafX) / 2, OffsetY * depthHeight, 0);
            if (depthHeight <= 1)
            {
                return;
            }
            foreach (var child in storyGraph.Children[node].Except(storyGraph.Leaves))
            {
                ArrangeIntermediateNode(child, depthHeight - 1, storyGraph);
            }
        }
Esempio n. 16
0
        //
        public IStoryLayoutInstance ArrangeAndDecorate(IStoryGraph sg)
        {
            var placementAlgorithm = new BuildingStoryLayoutPlacementAlgorithm(coroutineService, x => ArrangeAndDecorateInternal(sg.Root, x, new List <BuildingWallSegment>()), sg);

            placementAlgorithm.Run();
            var collisionSegments = new List <BuildingWallSegment>();

            ArrangeAndDecorateInternal(sg.Root, placementAlgorithm, collisionSegments);
            var floors = sg.Children[sg.Root]
                         .Select(x => new AaBox(placementAlgorithm.RelativeTransforms[x].Offset, placementAlgorithm.HalfSizes[x]))
                         .ToArray();
            var zonesWithProperties   = floors.Select(x => Tuples.Pair(x, new StoryLayoutZoneProperties(-15f))).ToArray();
            var defaultZoneProperties = new StoryLayoutZoneProperties(0);
            var zoning = new AaBoxStoryLayoutZoning(zonesWithProperties, defaultZoneProperties);
            var buildingCollisionMesh = new CollisionMesh(collisionSegments, floors, zoning);

            return(new BuildingStoryLayoutInstance(inputService, placementAlgorithm, buildingCollisionMesh, zoning));
        }
Esempio n. 17
0
        private void Rearrange(IStoryGraph storyGraph)
        {
            var leafGizmos = storyGraph.Leaves.Select(x => gizmosByNodes[storyGraph.NodeObjects[x]]).ToList();

            {
                var width = 0f;
                foreach (var leafGizmo in leafGizmos)
                {
                    //leafGizmo.Transform.Own = Transform.Translation(width + OffsetX / 2, 0, 0);
                    var cGizmo = leafGizmo.GetComponent <StoryFlowchartNodeGizmoComponent>();
                    cGizmo.Depth = storyGraph.Depths[cGizmo.ReferencedNode.Id];
                    width       += OffsetX;
                }
            }
            if (storyGraph.Depth > 1)
            {
                ArrangeIntermediateNode(storyGraph.Root, storyGraph.Depth - 1, storyGraph);
            }
        }
        private void ArrangeAndDecorateInternal(int nodeIndex, int level, NestedCirclesStorySpringModel springModel, IStoryGraph sg)
        {
            var node   = sg.NodeObjects[nodeIndex];
            var aspect = sg.Aspects[nodeIndex];
            var index  = node.Id;

            var dynamicParts = new StoryNodeDynamicParts();
            var scale        = springModel.GetVisualRadius(index);
            var visualElems  = new List <IVisualElement>
            {
                new ModelVisualElement <object>(null)
                .SetModel(circleModel)
                .SetMaterial(circleMaterials[level % circleMaterials.Length])
                .SetRenderState(circleRenderState)
                .SetTransform(Transform.Scaling(scale))
                .SetTransformSpace(TransformSpace.ScreenAlighned)
            };

            var transform = Transform.Translation(new Vector3(springModel.GetPosition(index), 0));

            node.Transform = transform;

            if (level == 0)
            {
                var edgeVisuals = sg.Edges.Select(edge => CreateEdgeVisualElement(node, sg.NodeObjects[edge.First], sg.NodeObjects[edge.Second]));
                visualElems.AddRange(edgeVisuals);
            }

            if (sg.Children[index].Any())
            {
                foreach (var childIndex in sg.Children[index])
                {
                    ArrangeAndDecorateInternal(childIndex, level + 1, springModel, sg);
                }
            }

            dynamicParts.VisualElements            = visualElems;
            dynamicParts.Hittable                  = new CircleHittable <ISceneNode>(node, Transform.Identity, x => new Circle2(Vector2.Zero, scale), x => - 0.01f * level);
            dynamicParts.DefaultViewpointMechanism = new OrthoDefaultViewpointMechanism(node, new PlaneOrthoBoundControlledCamera.Props
            {
                Target   = Vector2.Zero,
                Distance = 1.5f * scale,
                ZNear    = 0.1f,
                ZFar     = 1000f
            });
            aspect.SetDynamicParts(dynamicParts);
        }
Esempio n. 19
0
 public IStoryLayoutInstance ArrangeAndDecorate(IStoryGraph sg)
 {
     ArrangeAndDecorateInternal(sg, sg.Root, sg.Depth);
     return(new BasicStoryLayoutInstance(sg));
 }
Esempio n. 20
0
        private void ArrangeAndDecorateRoot(IStoryGraph sg)
        {
            var nodeIndex        = sg.Root;
            var aStory           = sg.Aspects[nodeIndex];
            var node             = sg.NodeObjects[nodeIndex];
            var adaptiveChildren = sg.Children[nodeIndex];
            var numChildren      = adaptiveChildren.Count;

            var visuals = new List <IVisualElement>();

            // todo: refactor to CenterLayout struct
            var wallRadius = 1f;

            var alpha = MathHelper.PiOver2;

            if (numChildren > 2)
            {
                alpha      = MathHelper.TwoPi / (2 * numChildren);
                wallRadius = corridorHalfWidth / MathHelper.Tan(alpha / 2f);
            }

            for (int i = 0; i < numChildren; i++)
            {
                var centerAngle = alpha * (1 + 2 * i);
                var pos         = new Vector3(
                    wallRadius * MathHelper.Cos(centerAngle),
                    wallRadius * MathHelper.Sin(centerAngle),
                    0);
                var rotation = Quaternion.RotationZ(-centerAngle + MathHelper.PiOver2);
                visuals.Add(CorridorWall(rotation, pos));
            }

            for (int i = 0; i < numChildren; i++)
            {
                var child = adaptiveChildren[i];

                var centerAngle = alpha * (2 * i);
                var doorPos     = new Vector3(
                    wallRadius * MathHelper.Cos(centerAngle),
                    wallRadius * MathHelper.Sin(centerAngle),
                    0);

                var forward  = doorPos.Normalize();
                var rotation = Quaternion.RotationZ(-centerAngle + MathHelper.PiOver2);
                if (sg.Children[child].Any())
                {
                    sg.NodeObjects[child].Transform = new Transform(1, rotation, doorPos);
                    ArrangeAndDecorateIntermediate(child, sg);
                }
                else
                {
                    sg.NodeObjects[child].Transform = new Transform(1, rotation, doorPos - forward * FrustumDistance);
                    ArrangeAndDecorateLeaf(child, sg);
                }
            }

            // floor
            visuals.Add(ModelVisualElement.New()
                        .SetModel(floorModel)
                        .SetMaterial(floorMaterial)
                        .SetRenderState(StandardRenderState.New()
                                        .SetCullFace(CullFace.Back)
                                        .FromGlobalCache())
                        .SetTransform(new Transform(1, Quaternion.Identity, new Vector3(0, 0, centerHeight - ceilingHalfHeight))));

            // ceiling
            visuals.Add(ModelVisualElement.New()
                        .SetModel(ceilingModel)
                        .SetMaterial(ceilingMaterial)
                        .SetRenderState(StandardRenderState.New()
                                        .SetCullFace(CullFace.Back)
                                        .FromGlobalCache())
                        .SetTransform(new Transform(1, Quaternion.Identity, new Vector3(0, 0, centerHeight + ceilingHalfHeight))));

            var viewpointProps = new LookAroundCamera.Props
            {
                Distance    = 24,
                FieldOfView = MathHelper.PiOver2,
                ZNear       = 0.1f,
                ZFar        = 100.0f,
                Pitch       = 0
            };

            aStory.SetDynamicParts(new StoryNodeDynamicParts
            {
                DefaultViewpointMechanism = new SphereDefaultViewpointMechanism(node, viewpointProps),
                Hittable       = new DummyHittable(),
                VisualElements = visuals
            });
        }
Esempio n. 21
0
        private void ArrangeAndDecorateInternal(IStoryGraph sg, int nodeId, AaRectangle2 yawPitchBounds, float radius)
        {
            var cStory      = sg.Aspects[nodeId];
            var node        = sg.NodeObjects[nodeId];
            var children    = sg.Children[nodeId];
            var numChildren = children.Count;

            var yaw      = yawPitchBounds.Center.X;
            var pitch    = yawPitchBounds.Center.Y;
            var pos      = ToCartesian(yaw, pitch, radius);
            var zAxis    = (-pos).Normalize();
            var xAxis    = Vector3.Cross(Vector3.UnitY, zAxis).Normalize();
            var yAxis    = Vector3.Cross(zAxis, xAxis);
            var rotation = Quaternion.RotationToFrame(xAxis, yAxis);

            node.Transform = new Transform(1, rotation, pos);

            var numRows             = (int)Math.Ceiling(MathHelper.Sqrt(numChildren));
            var numCols             = (int)Math.Ceiling((float)numChildren / numRows);
            var totalHeightRequired = MinVerticalDistance * numRows;
            var totalWidthRequired  = MinHorizontalDistance * numRows;
            var minChildrenRadius   = Math.Max(totalWidthRequired / yawPitchBounds.Width, totalHeightRequired / yawPitchBounds.Height);
            var childRadius         = Math.Max(radius + MinRadiusDistance, minChildrenRadius);

            for (var i = 0; i < numChildren; i++)
            {
                var child               = children[i];
                var row                 = i / numCols;
                var col                 = i % numCols;
                var childYawWidth       = yawPitchBounds.Width / numCols;
                var childYawHeight      = yawPitchBounds.Height / numRows;
                var childYaw            = yawPitchBounds.MinX + childYawWidth * (row + 0.5f);
                var childPitch          = yawPitchBounds.MinY + childYawHeight * (col * 0.5f);
                var childYawPitchBounds = AaRectangle2.FromCenter(new Vector2(childYaw, childPitch), HalfWidth / childRadius, HalfHeight / childRadius);
                ArrangeAndDecorateInternal(sg, child, childYawPitchBounds, childRadius);
            }

            var visuals = new []
            {
                ModelVisualElement.New(sg.Aspects[sg.Root])
                .SetModel(frustumModel)
                .SetMaterial(frustumMaterial)
                .SetTransform(new Transform(0.5f, Quaternion.Identity, new Vector3(0, 0, 0.5f * MathHelper.FrustumDistance)))
                .SetHide(x => !x.ShowAux1)
            };

            var viewpointProps = new TargetedControlledCameraY.Props
            {
                Target      = Vector3.Zero,
                Distance    = MathHelper.FrustumDistance,
                FieldOfView = MathHelper.PiOver4,
                ZNear       = 0.1f,
                ZFar        = 100.0f
            };

            var transform2D = new Transform(2, Quaternion.Identity, -MathHelper.FrustumDistance * Vector3.UnitZ);

            cStory.SetDynamicParts(new StoryNodeDynamicParts
            {
                DefaultViewpointMechanism = new WallDefaultViewpointMechanism(node, viewpointProps),
                Hittable           = GetHittableComponent(node, transform2D),
                VisualElements     = visuals,
                PlacementSurface2D = new PlanarPlacementSurface(node, Transform.Identity),
                PlacementSurface3D = new PlanarPlacementSurface(node, new Transform(0.05f, Quaternion.Identity, new Vector3(0, 0, 0.5f * MathHelper.FrustumDistance)))
            });
        }
Esempio n. 22
0
 public IStoryLayoutInstance ArrangeAndDecorate(IStoryGraph sg)
 {
     ArrangeAndDecorateRoot(sg);
     return(new BasicStoryLayoutInstance(sg));
 }
Esempio n. 23
0
 private static bool IsIndirectParent(IStoryGraph sg, int child, int parent) =>
 EnumerateParentChain(sg, child).Any(x => x == parent);
Esempio n. 24
0
 public void OnEdgeRemoved(Pair <int> edge, IStoryGraph newSg)
 {
     OnGraphUpdated(newSg);
 }
Esempio n. 25
0
 public void OnStoryNodeAdded(ISceneNode parent, ISceneNode newNode, IStoryGraph newSg)
 {
     CreateGizmosForSubtree(newNode, newSg.Depths[newNode.Id]);
     OnGraphUpdated(newSg);
 }
Esempio n. 26
0
 public IStoryLayoutInstance ArrangeAndDecorate(IStoryGraph sg)
 {
     ArrangeAndDecorateLevel(sg, sg.Root, sg.Depth, true);
     return(new BasicStoryLayoutInstance(sg));
 }
Esempio n. 27
0
 public void OnStoryNodeRemoved(ISceneNode parent, ISceneNode removedNode, IStoryGraph newSg)
 {
     DeleteGizmoSubtree(removedNode);
     OnGraphUpdated(newSg);
 }
Esempio n. 28
0
        private void ArrangeAndDecorateIntermediate(int nodeIndex, IStoryGraph sg)
        {
            var aStory           = sg.Aspects[nodeIndex];
            var node             = sg.NodeObjects[nodeIndex];
            var abstractChildren = sg.Children[nodeIndex];
            var numChildren      = abstractChildren.Count;

            var forward      = Vector3.UnitY;
            var right        = Vector3.UnitX;
            var rightWallPos = forward * exitHalfLength + right * corridorHalfWidth;
            var rightWallRot = Quaternion.RotationZ(MathHelper.PiOver2);
            var leftWallPos  = forward * exitHalfLength - right * corridorHalfWidth;
            var leftWallRot  = Quaternion.RotationZ(-MathHelper.PiOver2);

            var visuals = new List <IVisualElement>();

            // right exit wall
            visuals.Add(ExitWall(rightWallRot, rightWallPos));

            // left exit wall
            visuals.Add(ExitWall(leftWallRot, leftWallPos));

            var viewpointProps = new TargetedControlledCamera.Props
            {
                Target      = Vector3.Zero,
                Distance    = FrustumDistance,
                FieldOfView = MathHelper.PiOver4,
                ZNear       = 0.1f * FrustumDistance,
                ZFar        = 100.0f * FrustumDistance
            };

            var i = 0;
            //var numSegments = adaptiveLayout.AdaptiveChildren.Count * 2 - 1;
            var numSegments = numChildren % 2 == 0
                ? numChildren + 1
                : numChildren;

            while (i < numSegments)
            {
                //var childIndex = i / 2;
                var childIndex = i;

                var     exitOffset     = 2 * exitHalfLength;
                var     neighborOffset = 2 * corridorHalfWidth;
                Vector3 childForward;

                Vector3    position;
                Quaternion rotation;

                if (i < numSegments / 2)
                {
                    childForward = right;
                    position     =
                        forward * (exitOffset + neighborOffset * i + corridorHalfWidth) +
                        childForward * corridorHalfWidth;
                    rotation = rightWallRot;
                }
                else if (i > numSegments / 2)
                {
                    childForward = -right;
                    var numNeighborsAfter = numSegments - i - 1;
                    position =
                        forward * (exitOffset + neighborOffset * numNeighborsAfter + corridorHalfWidth) +
                        childForward * corridorHalfWidth;
                    rotation = leftWallRot;
                }
                else
                {
                    childForward = forward;
                    position     = forward * (exitOffset + neighborOffset * i);
                    rotation     = Quaternion.Identity;
                }

                if (i < numChildren)
                {
                    var adaptiveChild = abstractChildren[childIndex];
                    if (abstractChildren.Any())
                    {
                        sg.NodeObjects[adaptiveChild].Transform = new Transform(1, rotation, position);
                        ArrangeAndDecorateIntermediate(adaptiveChild, sg);
                    }
                    else
                    {
                        sg.NodeObjects[adaptiveChild].Transform = new Transform(1, rotation, position - childForward * FrustumDistance);
                        ArrangeAndDecorateLeaf(adaptiveChild, sg);
                    }
                }
                else
                {
                    visuals.Add(CorridorWall(rotation, position));
                }

                i++;
            }

            aStory.SetDynamicParts(new StoryNodeDynamicParts
            {
                DefaultViewpointMechanism = new WallDefaultViewpointMechanismZ(node, viewpointProps),
                Hittable       = new DummyHittable(),
                VisualElements = visuals
            });
        }
Esempio n. 29
0
        private void ArrangeAndDecorateRoot(IStoryGraph sg, int nodeIndex)
        {
            var cStory      = sg.Aspects[nodeIndex];
            var node        = sg.NodeObjects[nodeIndex];
            var children    = sg.Children[nodeIndex];
            var numChildren = children.Count;

            if (numChildren < 2)
            {
                var viewpointProps = new TargetedControlledCameraY.Props
                {
                    Target      = Vector3.Zero,
                    Distance    = MathHelper.FrustumDistance,
                    FieldOfView = MathHelper.PiOver4,
                    ZNear       = 0.1f,
                    ZFar        = 100.0f
                };

                cStory.SetDynamicParts(new StoryNodeDynamicParts
                {
                    DefaultViewpointMechanism = new WallDefaultViewpointMechanism(node, viewpointProps),
                    Hittable       = new DummyHittable(),
                    VisualElements = new IVisualElement[0]
                });

                foreach (var child in children)
                {
                    ArrangeAndDecorateRoot(sg, child);
                }
            }
            else
            {
                var distr  = CalculateDistribution(numChildren);
                var radius = distr.RelativeRadius;

                var oneMore = children.SelectMany(x => sg.Children[x]).Any();

                for (int i = 0; i < numChildren; i++)
                {
                    var pitch = distr.Angles[i].Pitch;
                    var yaw   = distr.Angles[i].Yaw;

                    if (oneMore)
                    {
                        //var internalRadius = radius / 2;
                        ArrangeAndDecorateRoot(sg, children[i]);

                        //var yaw = yawPitchBounds.Center.X;
                        //var pitch = yawPitchBounds.Center.Y;
                        var pos      = ToCartesian(yaw, pitch, radius * 20);
                        var zAxis    = (-pos).Normalize();
                        var xAxis    = Vector3.Cross(Vector3.UnitY, zAxis).Normalize();
                        var yAxis    = Vector3.Cross(zAxis, xAxis);
                        var rotation = Quaternion.RotationToFrame(xAxis, yAxis);
                        sg.NodeObjects[children[i]].Transform = new Transform(1, rotation, pos);

                        //ArrangeAndDecorateInternal(sg, children[i],
                        //    AaRectangle2.FromCenter(new Vector2(yaw, pitch), HalfWidth / radius, HalfHeight / radius),
                        //    radius);
                    }
                    else
                    {
                        ArrangeAndDecorateInternal(sg, children[i],
                                                   AaRectangle2.FromCenter(new Vector2(yaw, pitch), HalfWidth / radius, HalfHeight / radius),
                                                   radius);
                    }
                }

                var viewpointProps = new LookAroundCamera.Props
                {
                    Distance    = distr.RelativeRadius,
                    FieldOfView = 0.75f * MathHelper.Pi,
                    ZNear       = 0.1f,
                    ZFar        = 100.0f,
                    Pitch       = 0//MathHelper.PiOver2 + 0.1f
                };

                cStory.SetDynamicParts(new StoryNodeDynamicParts
                {
                    DefaultViewpointMechanism = new SphereDefaultViewpointMechanism(node, viewpointProps),
                    Hittable       = new DummyHittable(),
                    VisualElements = new IVisualElement[0]
                });
            }
        }
Esempio n. 30
0
        private void ArrangeAndDecorateLevel(IStoryGraph sg, int nodeIndex, int scaleLevel, bool isRoot)
        {
            var aStory           = sg.Aspects[nodeIndex];
            var node             = sg.NodeObjects[nodeIndex];
            var abstractChildren = sg.Children[nodeIndex];

            var scale = MathHelper.Pow(2, scaleLevel / 4f);

            var halfSize = 1f;
            var fov      = MathHelper.PiOver4;
            var distance = halfSize / MathHelper.Tan(fov / 2);

            var visuals = new List <IVisualElement>();

            visuals.Add(ModelVisualElement.New()
                        .SetModel(frustumModel)
                        .SetMaterial(frustumMaterial));

            var viewpointProps = isRoot
                ?   new TargetedControlledCameraY.Props
            {
                Target      = Vector3.Zero,
                Distance    = distance * 10,
                Pitch       = MathHelper.Pi * 0.1f,
                FieldOfView = fov,
                ZNear       = 0.1f * distance * scale,
                ZFar        = 100.0f * distance * scale
            }
                :   new TargetedControlledCameraY.Props
            {
                Target      = Vector3.Zero,
                Distance    = distance,
                FieldOfView = fov,
                ZNear       = 0.1f * distance * scale,
                ZFar        = 100.0f * distance * scale
            };

            if (isRoot)
            {
                // todo: change into additional local transform, or move to a 3D child space
                node.Transform = new Transform(1, Quaternion.RotationToFrame(Vector3.UnitX, Vector3.UnitZ), Vector3.Zero);
            }

            for (int i = 0; i < abstractChildren.Count; i++)
            {
                var adaptiveChild       = abstractChildren[i];
                var childBoundingRadius = 5 * scale;
                var angle    = MathHelper.Pi * 0.33f + 3 * MathHelper.TwoPi / 5 * i;
                var rotation = Quaternion.RotationY(-angle + MathHelper.Pi);
                var childScalingCompoensation = 10f;
                var radius = isRoot
                    ? (childBoundingRadius / 3) * (2 + i) * childScalingCompoensation
                    : (childBoundingRadius / 3) * (2 + i * 0.5f) * childScalingCompoensation * 0.5f;

                var offset = new Vector3(radius * MathHelper.Sin(angle), 0, radius * MathHelper.Cos(angle));
                sg.NodeObjects[adaptiveChild].Transform = new Transform(5, rotation, offset);
                ArrangeAndDecorateLevel(sg, adaptiveChild, scaleLevel - 1, false);

                visuals.Add(ModelVisualElement.New()
                            .SetModel(circleModel)
                            .SetMaterial(circleMaterial)
                            .SetTransform(new Transform(radius / childScalingCompoensation, Quaternion.RotationToFrame(Vector3.UnitX, Vector3.UnitZ), Vector3.Zero)));
            }

            aStory.SetDynamicParts(new StoryNodeDynamicParts
            {
                DefaultViewpointMechanism = new WallDefaultViewpointMechanism(node, viewpointProps),
                Hittable       = GetHittableComponent(node),
                VisualElements = visuals
            });
        }