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 Model3d GenerateModel(GenerationParameters parameters) { var buildingParams = parameters as BuildingsGenerationParameters; var assetsMeshes = new Dictionary <Asset, DMesh3>(); LoadAssetsAsMeshes(buildingParams.DoorsAssets, buildingParams.DoorAssetTrianglesLimit, 1.0 / buildingParams.AssetsScaleModifier, assetsMeshes); LoadAssetsAsMeshes(buildingParams.WindowsAssets, buildingParams.WindowAssetTrianglesLimit, 1.0 / buildingParams.AssetsScaleModifier, assetsMeshes); // make grammar var grammarController = new BuildingsGrammarController(buildingParams.RandomGenerator, assetsMeshes); var buildingWord = grammarController.TransformWordRepeatedly(parameters, 10); // build model var buildingMeshes = MakeMeshFromGrammar(buildingWord); if (!buildingMeshes[0].CheckValidity()) { throw new Exception("Generated mesh is invalid"); } foreach (var doorAsset in buildingParams.DoorsAssets) { doorAsset.CloseAssetFile(); } foreach (var windowAsset in buildingParams.WindowsAssets) { windowAsset.CloseAssetFile(); } assetsMeshes.Clear(); //Reducer r = new Reducer(mesh); //r.ReduceToTriangleCount(1000); return(new Model3d { Mesh = buildingMeshes }); }
public GrammarNode TransformWordRepeatedly(GenerationParameters buildingParameters, int epochs, int depthLimit = 50) { Rules = new HashSet <GrammarRule> { new RootSplitRule(), new TopFloorToRoofRule(), new FloorToWallStripRule(), new WallStripToSegmentRule(), new SegmentToDoorsRule(), new SegmentsToWindowsRule(), }; while (epochs > 0 || epochs < 0 && Rules.Any(r => !r.IsTerminated)) { foreach (var rule in Rules) { CurrentWord = rule.Apply(CurrentWord, buildingParameters, m_assetsMeshes, depthLimit); } --epochs; } return(CurrentWord); }
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 GrammarNode Apply(GrammarNode node, GenerationParameters parameters, Dictionary <Asset, DMesh3> assetsMeshes, int depthLimit) { if (IsTerminated || depthLimit == 0) { return(node); } node = TransformGrammarTree(node, parameters, assetsMeshes); if (IsTerminated) { return(node); } if (ContinueRecursion) { for (int c = 0; c < node.Subnodes.Count; ++c) { node.Subnodes[c] = Apply(node.Subnodes[c], parameters, assetsMeshes, depthLimit - 1); } } else { ContinueRecursion = 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 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); }
public abstract GrammarNode TransformGrammarTree(GrammarNode node, GenerationParameters parameters, Dictionary <Asset, DMesh3> assetsMeshes);