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))) }); }
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] }); } }
public WallDefaultViewpointMechanism(ISceneNode node, TargetedControlledCameraY.Props props) { this.node = node; this.props = props; FixedCamera = CreateControlledViewpoint(); }