public int GetClosestNodeId(CameraProps cameraProps) { return(sg.Leaves.Minimal(x => (placementAlgorithm.GetGlobalTransform(x).Offset - cameraProps.Target).LengthSquared())); }
private void ArrangeAndDecorateInternal(int subtreeRoot, BuildingStoryLayoutPlacementAlgorithm placementAlgorithm, List <BuildingWallSegment> globalWallSegments) { var sg = placementAlgorithm.StoryGraph; var node = sg.NodeObjects[subtreeRoot]; var aspect = sg.Aspects[subtreeRoot]; var index = node.Id; var children = sg.Children[index]; foreach (var child in children) { ArrangeAndDecorateInternal(child, placementAlgorithm, globalWallSegments); } var depth = sg.Depths[subtreeRoot]; var hasChildren = children.Any(); var halfSize = placementAlgorithm.HalfSizes[index]; node.Transform = hasChildren ? placementAlgorithm.RelativeTransforms[index] : placementAlgorithm.RelativeTransforms[index] * Transform.Translation(0, BuildingConstants.EyeHeight, 0); var dynamicParts = new StoryNodeDynamicParts(); var visualElems = new List <IVisualElement>(); var corridorDigger = new BuildingCorridorDigger(); var digResult = corridorDigger.Dig(placementAlgorithm, index); var globalTransform = placementAlgorithm.GetGlobalTransform(index); var rootStoryComponent = sg.Aspects[sg.Root]; if (digResult.WallSegments.Any()) { var wallModel = BuildWallModel(digResult.WallSegments); visualElems.Add(new ModelVisualElement <IStoryComponent>(rootStoryComponent) .SetModel(wallModel) .SetMaterial(wallMaterial) .SetRenderState(StandardRenderState.New() .SetCullFace(CullFace.Back) .FromGlobalCache()) .SetHide(x => x.HideMain)); foreach (var wallSegment in digResult.WallSegments) { globalWallSegments.Add(new BuildingWallSegment { Basement = new LineSegment3( wallSegment.Basement.Point1 * globalTransform, wallSegment.Basement.Point2 * globalTransform), Height = wallSegment.Height }); } var wallPrimitivesModel = BuildWallModel4(digResult.RawWallSegments); visualElems.Add(new ModelVisualElement <IStoryComponent>(rootStoryComponent) .SetModel(wallPrimitivesModel) .SetMaterial(rawWallMaterial) .SetHide(x => !x.ShowAux3)); var filteredWallPrimitivesModel = BuildWallModel4(digResult.WallSegments); visualElems.Add(new ModelVisualElement <IStoryComponent>(rootStoryComponent) .SetModel(filteredWallPrimitivesModel) .SetMaterial(rawWallMaterial) .SetHide(x => !x.ShowAux4)); } foreach (var flooring in digResult.Floorings) { visualElems.Add(new ModelVisualElement <IStoryComponent>(rootStoryComponent) .SetModel(BuildFloorOrCeiling(new Size3(flooring.HalfWidth, 0, flooring.HalfHeight), PlaneModelSourceNormalDirection.Positive)) .SetMaterial(floorMaterial) .SetRenderState(StandardRenderState.New() .SetCullFace(CullFace.Back) .FromGlobalCache()) .SetTransform(Transform.Translation(flooring.Center.X, 0, flooring.Center.Y)) .SetHide(x => x.HideMain)); } if (index == sg.Root) { foreach (var lane in placementAlgorithm.Lanes.Values) { var laneLoc = lane; var navigationService = navigationServiceLazy.Value; var model = BuildLaneModel(lane); visualElems.Add(ModelVisualElement.New() .SetModel(model) .SetMaterial(x => new UnorderedPair <int>(navigationService.Previous.Id, navigationService.Current.Id) == new UnorderedPair <int>(laneLoc.Edge.First, laneLoc.Edge.Second) ? currentLineMaterial : lineMaterial) .SetRenderState(StandardRenderState.New() // todo: remove *5 .SetZOffset(GraphicsHelper.MinZOffset * 5) .SetLineWidth(3) .FromGlobalCache())); } } dynamicParts.Hittable = hasChildren ? new RectangleHittable <ISceneNode>(node, Transform.Rotate(Quaternion.RotationToFrame(Vector3.UnitX, Vector3.UnitZ)), x => new AaRectangle2(Vector2.Zero, halfSize.Width, halfSize.Height), x => - 0.01f * depth) : new RectangleHittable <ISceneNode>(node, new Transform(1, Quaternion.RotationToFrame(Vector3.UnitX, Vector3.UnitZ), new Vector3(0, -BuildingConstants.EyeHeight, 0)), x => new AaRectangle2(Vector2.Zero, halfSize.Width, halfSize.Height), x => - 0.01f * depth); if (depth == 1) { visualElems.Add(new ModelVisualElement <IStoryComponent>(rootStoryComponent) .SetModel(BuildFloorOrCeiling(halfSize, PlaneModelSourceNormalDirection.Negative)) .SetMaterial(ceilingMaterial) .SetRenderState(StandardRenderState.New() .SetCullFace(CullFace.Back) .FromGlobalCache()) .SetTransform(Transform.Translation(0, BuildingConstants.CeilingHeight, 0)) .SetHide(x => x.HideMain)); } if (hasChildren) { var size = halfSize.ToVector().Length(); dynamicParts.DefaultViewpointMechanism = new WallDefaultViewpointMechanism(node, new TargetedControlledCameraY.Props { Target = Vector3.Zero, Distance = size, FieldOfView = MathHelper.PiOver4, Pitch = MathHelper.PiOver4, Yaw = -MathHelper.PiOver4, ZNear = 0.01f, ZFar = 1000f }); } else { dynamicParts.DefaultViewpointMechanism = new WallDefaultViewpointMechanism(node, new TargetedControlledCameraY.Props { Distance = FrustumDistance, FieldOfView = MathHelper.PiOver4, Pitch = 0, Yaw = 0, ZNear = 0.01f, ZFar = 1000f }); visualElems.Add(new ModelVisualElement <IStoryComponent>(rootStoryComponent) .SetModel(frustumModel) .SetMaterial(frustumMaterial) .SetRenderState(StandardRenderState.New() .SetZOffset(GraphicsHelper.MinZOffset * (depth + 1)) .FromGlobalCache()) .SetHide(x => !x.ShowAux1)); dynamicParts.PlacementSurface2D = new PlanarPlacementSurface(node, new Transform(2f, Quaternion.Identity, new Vector3(0, 0, -MathHelper.FrustumDistance))); dynamicParts.PlacementSurface3D = new PlanarPlacementSurface(node, Transform.Scaling(0.1f)); } dynamicParts.VisualElements = visualElems; aspect.SetDynamicParts(dynamicParts); }