예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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
            });
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
 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);
 }
예제 #9
0
        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);
        }
예제 #10
0
 public abstract GrammarNode TransformGrammarTree(GrammarNode node, GenerationParameters parameters, Dictionary <Asset, DMesh3> assetsMeshes);