public override GrammarNode TransformGrammarTree(GrammarNode node, GenerationParameters parameters, Dictionary <Asset, DMesh3> assetsMeshes) { if (!(node is RootNode) || ChangedNodes.Contains(node)) { return(node); } var bp = parameters as BuildingsGenerationParameters; (node as RootNode).Parameters = bp; var basementPolygon = MakePolygon3d(bp.BasementPoints); var doorWallLength = bp.BasementPoints[bp.DoorWall.PointIdx1] .Distance(bp.BasementPoints[bp.DoorWall.PointIdx2]); var segmentLength = doorWallLength / bp.SelectedWallSegments; var segmentsPerWall = new List <int>(); var windowsPerWall = new List <int>(); for (int p = 0; p < bp.BasementPoints.Count - 1; ++p) { var p1 = bp.BasementPoints[p]; var p2 = bp.BasementPoints[p + 1]; var d = p1.Distance(p2); segmentsPerWall.Add((int)(d / segmentLength)); windowsPerWall.Add((int)(segmentsPerWall.Last() * bp.WindowsToSegmentsFraction)); } var dlast = bp.BasementPoints.Last().Distance(bp.BasementPoints[0]); segmentsPerWall.Add((int)(dlast / segmentLength)); windowsPerWall.Add((int)(segmentsPerWall.Last() * bp.WindowsToSegmentsFraction)); var regularFloorHeight = bp.BasementExtrudeHeight / bp.FloorsNumber; for (int f = 0; f < bp.FloorsNumber + 1; ++f) { var type = f == 0 ? FloorMark.Ground : (f == bp.FloorsNumber ? FloorMark.Top : FloorMark.None); var height = type == FloorMark.Top ? bp.RoofHeight : regularFloorHeight; node.Subnodes.Add(new FloorNode { FloorType = type, Height = height, BaseShape = basementPolygon, SegmentWidth = segmentLength, SegmentsPerWall = segmentsPerWall, WindowsPerWall = windowsPerWall, FloorIdx = f, }); basementPolygon = Geometry.OffsetPolygon(basementPolygon, height); } ChangedNodes.Add(node); //this.IsTerminated = true; return(node); }
public override GrammarNode TransformGrammarTree(GrammarNode node, GenerationParameters parameters, Dictionary <Asset, DMesh3> assetsMeshes) { if (!(node is WallStripNode) || ChangedNodes.Contains(node)) { return(node); } var wallStrip = node as WallStripNode; var isGroundParadeStrip = wallStrip.WallType == WallMark.Parade && wallStrip.FloorType == FloorMark.Ground; var isGroundParadeCandidate = isGroundParadeStrip && !m_isGroundDoorPlaced; if (!isGroundParadeCandidate) { return(node); // !segment.IsDoorRequired } if (isGroundParadeStrip) { m_isGroundDoorPlaced = true; } //if (!(node is SegmentNode) || ChangedNodes.Contains(node)) return node; //var segment = node as SegmentNode; //var isGroundParadeSegment = segment.WallType == WallMark.Parade && segment.FloorType == FloorMark.Ground; //if (isGroundParadeStrip) //{ // m_isGroundDoorPlaced = true; //} var segmentIdx = parameters.RandomGenerator.Next(wallStrip.SegmentsNumber); var segment = wallStrip.Subnodes .Where(n => n is SegmentNode) .ToArray()[segmentIdx] as SegmentNode; var bparams = parameters as BuildingsGenerationParameters; var randomDoorAssetIdx = bparams.RandomGenerator.Next(bparams.DoorsAssets.Count); var segmentBottomCenter = segment.Origin + segment.AlongWidthDirection * segment.Width / 2.0; segment.RemoveSubnodes(n => n is WindowNode); segment.Subnodes.Add(new DoorNode { Mesh = assetsMeshes?[bparams.DoorsAssets[randomDoorAssetIdx]], FrontNormal = segment.FrontNormal, Origin = segmentBottomCenter, HeightLimit = segment.Height * 0.8, // todo: why hardcoded WidthLimit = segment.Width * 0.8, // todo: why hardcoded }); ChangedNodes.Add(node); ChangedNodes.Add(segment); return(node); }
public override GrammarNode TransformGrammarTree(GrammarNode node, GenerationParameters parameters, Dictionary <Asset, DMesh3> assetsMeshes) { if (!(node is WallStripNode) || ChangedNodes.Contains(node)) { return(node); } var bparams = parameters as BuildingsGenerationParameters; var wall = node as WallStripNode; // add wall in registry if (!m_verticalSymmetryRegistry.ContainsKey(wall.WallIdx)) { m_verticalSymmetryRegistry[wall.WallIdx] = new HashSet <int>(); } IEnumerable <int> slotsIndices; if (bparams.IsVerticalWindowSymmetryPreserved) { // if no columns selected, select them randomly if (m_verticalSymmetryRegistry[wall.WallIdx].Count == 0) { m_verticalSymmetryRegistry[wall.WallIdx] = new HashSet <int>( SelectRandomSegments(wall.SegmentsNumber, wall.WindowsNumber, bparams.RandomGenerator) ); } // take columns which have to be filled slotsIndices = m_verticalSymmetryRegistry[wall.WallIdx]; } else { // take columns randomly for this strip slotsIndices = SelectRandomSegments(wall.SegmentsNumber, wall.WindowsNumber, bparams.RandomGenerator); } var segmentsInWall = wall.Subnodes.Where(n => n is SegmentNode).ToArray(); foreach (var slotIdx in slotsIndices) { if (slotIdx < segmentsInWall.Length) { AddWindow(segmentsInWall[slotIdx] as SegmentNode, bparams, assetsMeshes); } } ChangedNodes.Add(node); ContinueRecursion = false; return(node); }
public override GrammarNode TransformGrammarTree(GrammarNode node, GenerationParameters parameters, Dictionary <Asset, DMesh3> assetsMeshes) { if (!(node is FloorNode) || ChangedNodes.Contains(node)) { return(node); } var floor = (node as FloorNode); var buildingsParams = parameters as BuildingsGenerationParameters; if (floor.FloorType != FloorMark.Top) { return(node); } ChangedNodes.Add(node); var baseShape = floor.BaseShape.Reverse().ToList(); var roofNormal = Vector3d.AxisY; switch (buildingsParams.RoofStyle) { case RoofStyle.Flat: var edgeOffset = 0.1f; return(new FlatRoofNode { RoofHeight = buildingsParams.RoofHeight, RoofEdgeOffset = edgeOffset, BaseShape = baseShape, Normal = roofNormal }); case RoofStyle.Slope: return(new SlopeRoofNode { RoofHeight = buildingsParams.RoofHeight, RoofEdgeOffset = 0.5f, BaseShape = baseShape, Normal = roofNormal }); case RoofStyle.SlopeFlat: return(new FlatSlopeRoofNode { RoofHeight = buildingsParams.RoofHeight, RoofEdgeOffset = 0.5f, BaseShape = baseShape, Normal = roofNormal }); default: return(node); } }
public Node Prepend(T value) { if (Tail == null && Head == null) { var newNode = new Node(NextId++, this) { Value = value }; ChangedNodes.Add(newNode); return(Head = Tail = newNode); } return(Head = Head.AddBefore(value)); }
public Node Append(T value) { if (Tail == null && Head == null) { var newNode = new Node(NextId++, this) { Value = value }; ChangedNodes.Add(newNode); return(Head = Tail = newNode); } return(Tail = Tail.AddAfter(value)); }
public void AddWindow(SegmentNode segment, BuildingsGenerationParameters parameters, Dictionary <Asset, DMesh3> assetsMeshes) { if (segment.Subnodes.Any(n => n is DoorNode)) { return; } var randomWindowAssetIdx = parameters.RandomGenerator.Next(parameters.WindowsAssets.Count); var segmentBottomCenter = segment.Origin + segment.AlongWidthDirection * segment.Width / 2.0; var windowBottomCenter = segmentBottomCenter + Vector3d.AxisY * segment.Height * 0.3; // todo: hardcode //var windowBottomCenter = segmentBottomCenter; segment.Subnodes.Add(new WindowNode { Mesh = assetsMeshes?[parameters.WindowsAssets[randomWindowAssetIdx]], FrontNormal = segment.FrontNormal, Origin = windowBottomCenter, // todo: hardcode HeightLimit = segment.Height * 0.65, // todo: hardcode //HeightLimit = segment.Height, // todo: hardcode WidthLimit = segment.Width * 0.85, }); ChangedNodes.Add(segment); }
public override GrammarNode TransformGrammarTree(GrammarNode node, GenerationParameters parameters, Dictionary <Asset, DMesh3> assetsMeshes) { if (!(node is FloorNode) || ChangedNodes.Contains(node)) { return(node); } var floor = (node as FloorNode); var buildingsParams = parameters as BuildingsGenerationParameters; var firstAddedIdx = floor.Subnodes.Count; for (int w = 0; w < floor.SegmentsPerWall.Count; ++w) { var nextWallPoint = floor.BaseShape[(w + 1) % floor.BaseShape.Count]; var wallHorizontalSide = nextWallPoint - floor.BaseShape[w]; var wallWidth = wallHorizontalSide.Length; var alongWallDirection = wallHorizontalSide.Normalized; node.Subnodes.Add(new WallStripNode { WallType = WallMark.None, FloorType = floor.FloorType, SegmentsNumber = floor.SegmentsPerWall[w], SegmentWidth = floor.SegmentWidth, WindowsNumber = floor.WindowsPerWall[w], Height = floor.Height, Width = wallWidth, Origin = floor.BaseShape[w], FrontNormal = Vector3d.AxisY.UnitCross(alongWallDirection), AlongWidthDirection = alongWallDirection, FloorIdx = floor.FloorIdx, WallIdx = w, }); } var doorWallIdx = firstAddedIdx + buildingsParams.DoorWall.PointIdx1; var doorWallNode = node.Subnodes[doorWallIdx] as WallStripNode; doorWallNode.WallType = WallMark.Parade; ChangedNodes.Add(node); return(node); }
public override GrammarNode TransformGrammarTree(GrammarNode node, GenerationParameters parameters, Dictionary <Asset, DMesh3> assetsMeshes) { if (!(node is WallStripNode) || ChangedNodes.Contains(node)) { return(node); } var wallStrip = node as WallStripNode; var bparams = parameters as BuildingsGenerationParameters; //var segmentWidth = wallStrip.Width / wallStrip.SegmentsNumber; var unusedWidth = wallStrip.Width - wallStrip.SegmentWidth * wallStrip.SegmentsNumber; var paddingStep = unusedWidth / (wallStrip.SegmentsNumber + 1); var segmentOrigin = wallStrip.Origin + wallStrip.AlongWidthDirection * paddingStep; for (int s = 0; s < wallStrip.SegmentsNumber; ++s) { wallStrip.Subnodes.Add(new SegmentNode { Width = wallStrip.SegmentWidth, Height = wallStrip.Height, Origin = segmentOrigin, FrontNormal = wallStrip.FrontNormal, FloorType = wallStrip.FloorType, WallType = wallStrip.WallType, AlongWidthDirection = wallStrip.AlongWidthDirection, WallIdx = wallStrip.WallIdx, SegmentIdx = s, }); segmentOrigin += wallStrip.AlongWidthDirection * (wallStrip.SegmentWidth + paddingStep); } ChangedNodes.Add(node); return(node); }