Ejemplo n.º 1
0
 private IVisualElement CorridorWall(Quaternion rotation, Vector3 position)
 {
     return(ModelVisualElement.New()
            .SetModel(corridorWallModel)
            .SetMaterial(wallMaterial)
            .SetTransform(new Transform(1, -rotation, position + Vector3.UnitZ * centerHeight)));
 }
Ejemplo n.º 2
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
            });
        }
        public void OnQueryServiceUpdated()
        {
            visualElements.Clear();
            optionRects.Clear();

            currentQuery = queryService.Queries.LastOrDefault() as OptionsUserQuery;
            if (currentQuery == null || !currentQuery.Options.Any())
            {
                return;
            }
            const float OptionMargin     = 0.1f;
            const float OptionHalfHeight = 0.09f;
            const float OptionHalfWidth  = 0.9f;
            var         currentY         = 1f;

            for (var i = 0; i < currentQuery.Options.Count; i++)
            {
                currentY -= OptionMargin;
                currentY -= OptionHalfHeight;
                optionRects.Add(new AaRectangle2(new Vector2(0, currentY), OptionHalfWidth, OptionHalfHeight));
                currentY -= OptionHalfHeight;
                currentY -= OptionMargin;
            }
            var totalHeight = 1f - currentY;
            var centerY     = 1f - totalHeight / 2;

            for (int i = 0; i < currentQuery.Options.Count; i++)
            {
                var option = currentQuery.Options[i];

                var rect = optionRects[i];
                rect.Center.Y -= centerY;
                optionRects[i] = rect;

                var textBox = RichTextHelper.Label(option,
                                                   new IntSize2((int)(2 * 512 * OptionHalfWidth), (int)(2 * 512 * OptionHalfHeight)),
                                                   RtParagraphAlignment.Center,
                                                   Color4.Black,
                                                   RtTransparencyMode.Opaque,
                                                   "Arial",
                                                   32,
                                                   Color4.Orange,
                                                   FontDecoration.None);
                var textImageRgba = textImageBuilder.BuildImageRgba(textBox);
                var textImage     = new RawImage(ResourceVolatility.Immutable, textBox.Size, false, textImageRgba);
                visualElements.Add(ModelVisualElement.New()
                                   .SetModel(planeModel)
                                   .SetMaterial(StandardMaterial.New()
                                                .SetDiffuseMap(textImage)
                                                .SetIgnoreLighting(true)
                                                .FromGlobalCache())
                                   .SetTransform(Transform.Translation(new Vector3(rect.Center, 0)))
                                   .SetNonUniformScale(new Vector3(rect.HalfWidth, rect.HalfHeight, 1)));
            }
        }
Ejemplo n.º 4
0
 private ModelVisualElement <object> CreateLaneElem(Vector3 prevPoint, Vector3 currPoint, int disambiguator, int depth)
 {
     return(ModelVisualElement.New()
            .SetModel(lineModel)
            .SetMaterial(lineMaterial)
            .SetRenderState(StandardRenderState.New()
                            .SetLineWidth(3)
                            .SetZOffset(GraphicsHelper.MinZOffset * (depth + 1))
                            .FromGlobalCache())
            .SetTransform(CalcCorridorSegmentTransform(prevPoint, currPoint, disambiguator)));
 }
 protected ResizeRectangleGizmoComponent(IInputHandler inputHandler, IEmbeddedResources embeddedResources, IUndoRedoService undoRedo)
 {
     visualElement = ModelVisualElement.New()
                     .SetModel(embeddedResources.CubeModel())
                     .SetMaterial(StandardMaterial.New()
                                  .SetNoSpecular(true)
                                  .FromGlobalCache())
                     .SetTransform(Transform.Scaling(0.025f));
     interactionElement = new ResizeRectangleInteractionElement <ResizeRectangleGizmoComponent>(
         this, x => x.GetRectAspect(), x => x.GetChildSpace(), x => x.Place, inputHandler, undoRedo);
     hittable = new SphereHittable <ResizeRectangleGizmoComponent>(this, x =>
     {
         var globalTransform = Node.GlobalTransform;
         return(new Sphere(globalTransform.Offset, 0.025f * globalTransform.Scale));
     });
 }
Ejemplo n.º 6
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
            });
        }
Ejemplo n.º 7
0
        private void Rebuild()
        {
            if (SpherePackingResult == null)
            {
                return;
            }
            var material = StandardMaterial.New(this)
                           .SetDiffuseColor(x => x.Color);

            visualElems = SpherePackingResult.Points.Select(p =>
                                                            ModelVisualElement.New(this)
                                                            .SetModel(embeddedResources.SphereModel(64))
                                                            .SetTransform(x => new Transform(x.Radius, Quaternion.Identity, p))
                                                            .SetMaterial(material))
                          .Cast <IVisualElement>()
                          .ToArray();
            LocalBoundingSphere = Sphere.BoundingSphere(SpherePackingResult.Points);
        }
        public IEnumerable <IVisualElement> GetVisualElements()
        {
            yield return(borderVisualElement);

            yield return(backgroundVisualElement);

            for (int i = 0; i < solvingProcess.Packer.NumCircles; i++)
            {
                var iLoc = i;
                if (circleVisualElements.Count <= i)
                {
                    circleVisualElements.Add(ModelVisualElement.New(this)
                                             .SetModel(x => x.embeddedResources.CircleModel(64))
                                             .SetMaterial(StandardMaterial.New(this)
                                                          .SetIgnoreLighting(true)
                                                          .SetDiffuseColor(x => x.ColorForStatus(x.solvingProcess.Packer.FrontCircleStatuses[iLoc])))
                                             .SetTransform(x => new Transform(x.solvingProcess.Packer.CircleRadius, Quaternion.Identity, new Vector3(x.solvingProcess.Packer.FrontCircleCenters[iLoc], 0))));
                }
                yield return(circleVisualElements[i]);
            }
        }
        protected CirclePackingAutoComponent(IEmbeddedResources embeddedResources, IViewService viewService, ICoroutineService coroutineService)
        {
            this.embeddedResources = embeddedResources;
            this.coroutineService  = coroutineService;

            solver = new CirclePackingSolver();
            Reset();

            borderModel = new ExplicitModel(ResourceVolatility.Stable)
            {
                IndexSubranges = new ExplicitModelIndexSubrange[1],
                Topology       = ExplicitModelPrimitiveTopology.LineStrip
            };
            backgroundVisualElement = ModelVisualElement.New(this)
                                      .SetModel(embeddedResources.SimplePlaneXyModel())
                                      .SetMaterial(StandardMaterial.New()
                                                   .SetIgnoreLighting(true)
                                                   .SetDiffuseColor(Color4.Black)
                                                   .FromGlobalCache())
                                      .SetRenderState(StandardRenderState.New()
                                                      .SetZOffset(-GraphicsHelper.MinZOffset))
                                      .SetTransform(x => Transform.Translation(new Vector3(x.border.BoundingRect.Center, 0)))
                                      .SetNonUniformScale(x => new Vector3(
                                                              x.border.BoundingRect.HalfWidth,
                                                              x.border.BoundingRect.HalfHeight,
                                                              1));
            borderVisualElement = ModelVisualElement.New(this)
                                  .SetModel(x => x.GetRelevantBorderModel())
                                  .SetMaterial(StandardMaterial.New()
                                               .SetDiffuseColor(Color4.Yellow)
                                               .SetIgnoreLighting(true)
                                               .FromGlobalCache());
            circleVisualElements           = new List <IVisualElement>();
            selectOnClickInterationElement = new SelectOnClickInteractionElement(this, viewService);
            // todo: make precise
            hittable = new RectangleHittable <CirclePackingAutoComponent>(this, Transform.Identity,
                                                                          x => x.border.BoundingRect,
                                                                          x => 0);
        }
        private void Reset()
        {
            simulationRunning   = false;
            simulationTimestamp = 0;
            prevQueue           = new Queue <FluidSimulationFrame>();
            var size     = new IntSize3(Width, Height, 1);
            var cellSize = CellSize;

            fluidSimulation.Reset(CreateConfig());
            model             = CreateModel(size, cellSize, fluidSimulation.Particles.Length);
            levelSetImageData = new byte[fluidSimulation.LevelSet.Size.Width * fluidSimulation.LevelSet.Size.Height * 4];
            levelSetImage     = new RawImage(ResourceVolatility.Volatile, new IntSize2(fluidSimulation.LevelSet.Size.Width, fluidSimulation.LevelSet.Size.Height), true, levelSetImageData);
            squareModel       = embeddedResources.SimplePlaneXyModel();
            visualElements.Clear();
            visualElements.Add(ModelVisualElement.New()
                               .SetModel(model)
                               .SetMaterial(StandardMaterial.New()
                                            .SetDiffuseColor(Color4.Yellow)
                                            .SetIgnoreLighting(true)
                                            .FromGlobalCache()));
            visualElements.Add(ModelVisualElement.New()
                               .SetModel(model)
                               .SetModelPartIndex(1)
                               .SetMaterial(StandardMaterial.New()
                                            .SetDiffuseColor(Color4.White)
                                            .SetIgnoreLighting(true)
                                            .FromGlobalCache())
                               .SetRenderState(StandardRenderState.New()
                                               .SetPointSize(3)
                                               .FromGlobalCache()));
            visualElements.Add(ModelVisualElement.New()
                               .SetModel(squareModel)
                               .SetMaterial(StandardMaterial.New()
                                            .SetDiffuseMap(levelSetImage)
                                            .SetIgnoreLighting(true)
                                            .FromGlobalCache())
                               .SetTransform(new Transform(cellSize * size.Width / 2, Quaternion.Identity, new Vector3(cellSize * size.Width / 2, cellSize * size.Height / 2, -0.1f))));
        }
Ejemplo n.º 11
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
            });
        }
Ejemplo n.º 12
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)))
            });
        }
Ejemplo n.º 13
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
            });
        }
Ejemplo n.º 14
0
        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);
        }