public TestTerrainBuilder(CustomizationService customizationService,
                           IElevationProvider elevationProvider,
                           IGameObjectFactory gameObjectFactory,
                           IObjectPool objectPool) :
     base(customizationService, elevationProvider, gameObjectFactory, objectPool)
 {
 }
예제 #2
0
        /// <summary> Builds game object from meshData </summary>
        protected virtual void BuildObject(IGameObject parent, MeshData meshData, Rule rule, Model model)
        {
            Observable.Start(() =>
            {
                var gameObject = meshData.GameObject.AddComponent(new GameObject());
                var mesh       = new Mesh();
                mesh.vertices  = meshData.Vertices;
                mesh.triangles = meshData.Triangles;
                mesh.colors    = meshData.Colors;
                mesh.RecalculateNormals();

                gameObject.AddComponent <MeshFilter>().mesh = mesh;
                gameObject.AddComponent <MeshCollider>();
                gameObject.AddComponent <MeshRenderer>().sharedMaterial = CustomizationService
                                                                          .GetMaterial(meshData.MaterialKey);

                // attach behaviours
                gameObject.AddComponent <MeshIndexBehaviour>().Index = meshData.Index;
                var behaviourTypes = rule.GetModelBehaviours(CustomizationService);
                foreach (var behaviourType in behaviourTypes)
                {
                    var behaviour = gameObject.AddComponent(behaviourType) as IModelBehaviour;
                    if (behaviour != null)
                    {
                        behaviour.Apply(meshData.GameObject, model);
                    }
                }

                gameObject.isStatic         = true;
                gameObject.transform.parent = parent.GetComponent <GameObject>().transform;
            }, Scheduler.MainThread);
        }
예제 #3
0
        public void CanGetMultiplyModelBuilders()
        {
            // ARRANGE
            var stylesheet = MapCssHelper.GetStylesheetFromContent("way[highway] { builders:test1,test2;}\n");
            var way        = MapCssHelper.GetWay(new Dictionary <string, string>()
            {
                { "highway", "yes" }
            }.ToTags());
            var testBulder1 = new Mock <IModelBuilder>();

            testBulder1.SetupGet(b => b.Name).Returns("test1");
            var testBulder2 = new Mock <IModelBuilder>();

            testBulder2.SetupGet(b => b.Name).Returns("test2");
            var testBulder3 = new Mock <IModelBuilder>();

            testBulder3.SetupGet(b => b.Name).Returns("test2");
            var provider = new CustomizationService(new Container())
                           .RegisterBuilder(testBulder1.Object)
                           .RegisterBuilder(testBulder2.Object);
            var rule = stylesheet.GetModelRule(way, ZoomHelper.GetZoomLevel(RenderMode.Scene));

            // ACT
            var builders = rule.GetModelBuilders(provider).ToArray();

            // ASSERT
            Assert.AreEqual(2, builders.Length);
            Assert.AreEqual("test1", builders[0].Name);
            Assert.AreEqual("test2", builders[1].Name);
        }
        /// <inheritdoc />
        public override IGameObject BuildWay(Tile tile, Rule rule, Way way)
        {
            if (way.Points.Count < 2)
            {
                Trace.Warn("model.barrier", Strings.InvalidPolyline);
                return(null);
            }

            if (tile.Registry.Contains(way.Id))
            {
                return(null);
            }

            tile.Registry.RegisterGlobal(way.Id);

            var gameObjectWrapper = GameObjectFactory.CreateNew(GetName(way));
            var maxWidth          = 4f;

            var points = ObjectPool.NewList <Vector2d>(way.Points.Count);

            PointUtils.SetPolygonPoints(tile.RelativeNullPoint, way.Points, points);

            var vertexCount = GetVertexCount(points, maxWidth);
            var meshIndex   = new MultiPlaneMeshIndex(points.Count - 1, vertexCount);
            var meshData    = new MeshData(meshIndex, vertexCount)
            {
                MaterialKey = rule.GetMaterialKey(),
                GameObject  = gameObjectWrapper,
            };

            meshData.Index = meshIndex;
            var context = new SegmentBuilderContext()
            {
                MeshData       = meshData,
                Gradient       = CustomizationService.GetGradient(rule.GetFillColor()),
                ColorNoiseFreq = rule.GetColorNoiseFreq(),
                Height         = rule.GetHeight(),
                MaxWidth       = maxWidth,
            };

            var index = 0;

            for (int i = 0; i < points.Count - 1; i++)
            {
                var p1 = points[i];
                var p2 = points[i + 1];

                var start = new Vector3((float)p1.X, ElevationProvider.GetElevation(p1), (float)p1.Y);
                var end   = new Vector3((float)p2.X, ElevationProvider.GetElevation(p2), (float)p2.Y);

                meshIndex.AddPlane(new Vector3((float)p1.X, 0, (float)p1.Y), start, end, meshData.NextIndex);

                BuildBarrierSegment(context, start, end, ref index);
            }
            ObjectPool.StoreList(points);
            BuildObject(tile.GameObject, meshData, rule, way);

            return(gameObjectWrapper);
        }
예제 #5
0
        /// <summary> Builds flat floors. </summary>
        protected List <MeshData> BuildFloors(Building building, int floorCount,
                                              bool lastFloorIsRoof, int extraMeshCount = 0)
        {
            var mesh = CreateMesh(building.Footprint);

            var floorHeight  = building.Height / building.Levels;
            var bottomOffset = building.Elevation + building.MinHeight;

            var vertexPerFloor = mesh.Triangles.Count * 3 * 2;
            int vertexCount    = vertexPerFloor * floorCount;

            int meshCount          = 1;
            int floorsPerIteration = floorCount;
            var twoSizedMeshCount  = vertexCount * 2;

            if (twoSizedMeshCount > Consts.MaxMeshSize)
            {
                Trace.Warn(LogCategory, Strings.MeshHasMaxVertexLimit, building.Id.ToString(),
                           twoSizedMeshCount.ToString());
                meshCount          = (int)Math.Ceiling((double)twoSizedMeshCount / Consts.MaxMeshSize);
                floorsPerIteration = floorCount / meshCount;
            }

            var meshDataList = new List <MeshData>(meshCount + extraMeshCount);

            for (int i = 0; i < meshCount; i++)
            {
                var stepFloorCount = (i != meshCount - 1 || meshCount == 1)
                    ? floorsPerIteration
                    : floorsPerIteration + floorCount % meshCount;

                var stepVertexCount  = vertexPerFloor * stepFloorCount;
                var stepBottomOffset = bottomOffset + i * (floorsPerIteration * floorHeight);

                var meshIndex = new MultiPlaneMeshIndex(stepFloorCount, stepVertexCount);
                var meshData  = new MeshData(meshIndex, stepVertexCount);

                AttachFloors(new RoofContext()
                {
                    Mesh      = mesh,
                    MeshData  = meshData,
                    MeshIndex = meshIndex,

                    Bottom             = stepBottomOffset,
                    FloorCount         = stepFloorCount,
                    FloorHeight        = floorHeight,
                    FloorFrontGradient = CustomizationService.GetGradient(building.FloorFrontColor),
                    FloorBackGradient  = CustomizationService.GetGradient(building.FloorBackColor),

                    IsLastRoof        = i == meshCount - 1 && lastFloorIsRoof,
                    RoofFrontGradient = CustomizationService.GetGradient(building.RoofColor),
                    RoofBackGradient  = CustomizationService.GetGradient(building.RoofColor),
                });

                meshDataList.Add(meshData);
            }

            return(meshDataList);
        }
예제 #6
0
 public void SetUp()
 {
     _fixture = new Fixture();
     _mockCommentRepository = new RepositoryMock <Comment>();
     _mockEventRepository   = new RepositoryMock <Event>();
     _mockTrackerRepository = new RepositoryMock <Tracker>();
     _customizationService  = new CustomizationService(_mockTrackerRepository, _mockEventRepository,
                                                       _mockCommentRepository, new RepositoryMock <Rating>(), new RepositoryMock <Scale>(),
                                                       new RepositoryMock <Geotag>(), new RepositoryMock <Photo>());
 }
예제 #7
0
 public TerrainBuilder(CustomizationService customizationService,
                       IElevationProvider elevationProvider,
                       IGameObjectFactory gameObjectFactory,
                       IObjectPool objectPool)
 {
     _customizationService = customizationService;
     _elevationProvider    = elevationProvider;
     _gameObjectFactory    = gameObjectFactory;
     _objectPool           = objectPool;
     _meshCellBuilder      = new MeshCellBuilder(_objectPool);
 }
예제 #8
0
        public override bool Run()
        {
            new MapGenTileListener(m_manager);

            CustomizationService
            .RegisterAtlas("main", TextureAtlasHelper.GetTextureAtlas());

            Container.Register(
                Component.For <ITileController>().Use <MapGenTileController>().Singleton());

            return(true);
        }
예제 #9
0
        public TileModelLoader(IGameObjectFactory gameObjectFactory,
                               ITerrainBuilder terrainBuilder, IStylesheetProvider stylesheetProvider,
                               CustomizationService customizationService, IObjectPool objectPool)
        {
            _terrainBuilder       = terrainBuilder;
            _customizationService = customizationService;

            _objectPool = objectPool;

            _gameObjectFactory = gameObjectFactory;
            _stylesheet        = stylesheetProvider.Get();
        }
예제 #10
0
        public override bool Run()
        {
            // this class will listen messages about tile processing from ASM engine
            _messageListener = new DemoTileListener(_messageBus, _trace);

            // extensions
            CustomizationService
            .RegisterBehaviour("terrain_draw", typeof(TerrainDrawBehaviour))
            .RegisterAtlas("main", TextureAtlasHelper.GeTextureAtlas());

            return(true);
        }
예제 #11
0
        public override bool Run()
        {
            // Replace default elevation provider with custom one
            Container.Register(Component.For <IElevationProvider>().Use <FlatElevationProvider>().Singleton());

            // Register model extensions. Name should match with mapCSS
            // rule builders/behaviours declaration.
            CustomizationService
            .RegisterAtlas("main", TextureAtlasHelper.GeTextureAtlas())
            .RegisterBuilder("waypoint", typeof(WaypointModelBuilder))
            .RegisterBehaviour("hide", typeof(HideModelBehaviour));

            return(true);
        }
예제 #12
0
        /// <inheritdoc />
        public override IGameObject BuildArea(Tile tile, Rule rule, Area area)
        {
            base.BuildArea(tile, rule, area);

            if (tile.Registry.Contains(area.Id))
            {
                return(null);
            }

            double   radius;
            Vector2d center;

            CircleUtils.GetCircle(tile.RelativeNullPoint, area.Points, out radius, out center);

            var elevation = ElevationProvider.GetElevation(center);

            var height       = rule.GetHeight();
            var minHeight    = rule.GetMinHeight();
            var actualHeight = (height - minHeight);
            var color        = rule.GetFillColor();
            var gradient     = CustomizationService.GetGradient(color);

            tile.Registry.RegisterGlobal(area.Id);

            var cylinderGen = new CylinderGenerator()
                              .SetCenter(new Vector3((float)center.X, elevation + minHeight, (float)center.Y))
                              .SetHeight(actualHeight)
                              .SetMaxSegmentHeight(5f)
                              .SetRadialSegments(7)
                              .SetRadius((float)radius)
                              .SetGradient(gradient);

            var meshData = new MeshData(MeshDestroyIndex.Default, cylinderGen.CalculateVertexCount())
            {
                GameObject  = GameObjectFactory.CreateNew(GetName(area)),
                MaterialKey = rule.GetMaterialKey()
            };

            cylinderGen.Build(meshData);

            BuildObject(tile.GameObject, meshData, rule, area);
            return(meshData.GameObject);
        }
예제 #13
0
        /// <inheritdoc />
        public override IGameObject BuildArea(Tile tile, Rule rule, Area area)
        {
            base.BuildArea(tile, rule, area);

            if (tile.Registry.Contains(area.Id))
            {
                return(null);
            }
            tile.Registry.RegisterGlobal(area.Id);

            double   radius;
            Vector2d center;

            CircleUtils.GetCircle(tile.RelativeNullPoint, area.Points, out radius, out center);

            var elevation = ElevationProvider.GetElevation(center);
            var minHeight = rule.GetMinHeight();
            var color     = rule.GetFillColor();
            var gradient  = CustomizationService.GetGradient(color);

            int recursionLevel = rule.EvaluateDefault("recursion_level", 2);

            var center3d = new Vector3((float)center.X, elevation + minHeight, (float)center.Y);

            var sphereGen = new IcoSphereGenerator()
                            .SetCenter(center3d)
                            .SetRadius((float)radius)
                            .SetRecursionLevel(recursionLevel)
                            .SetGradient(gradient);

            var meshData = new MeshData(new SphereMeshIndex((float)radius, center3d),
                                        sphereGen.CalculateVertexCount());

            meshData.GameObject  = GameObjectFactory.CreateNew(GetName(area));
            meshData.MaterialKey = rule.GetMaterialKey();

            sphereGen.Build(meshData);

            BuildObject(tile.GameObject, meshData, rule, area);

            return(meshData.GameObject);
        }
예제 #14
0
        private void CreateForest(IGameObject parent, Rule rule, Mesh mesh)
        {
            var trunkGradientKey   = rule.Evaluate <string>("trunk-color");
            var foliageGradientKey = rule.Evaluate <string>("foliage-color");
            int treeFreq           = (int)(1 / rule.EvaluateDefault <float>("tree-freq", 0.1f));
            // TODO reuse tree builder?
            // TODO behaviour should be set somehow
            var node = new Node();

            foreach (var triangle in mesh.Triangles)
            {
                // TODO reuse mesh and/or generator?
                if (triangle.Id % treeFreq != 0)
                {
                    continue;
                }

                var v0 = triangle.GetVertex(0);
                var v1 = triangle.GetVertex(1);
                var v2 = triangle.GetVertex(2);

                var center    = new Vector2d((v0.X + v1.X + v2.X) / 3, (v0.Y + v1.Y + v2.Y) / 3);
                var elevation = ElevationProvider.GetElevation(center);

                var treeGen = new TreeGenerator()
                              .SetTrunkGradient(CustomizationService.GetGradient(trunkGradientKey))
                              .SetFoliageGradient(CustomizationService.GetGradient(foliageGradientKey))
                              .SetPosition(new Vector3((float)center.X, elevation, (float)center.Y));

                var meshData = new MeshData(MeshDestroyIndex.Default, treeGen.CalculateVertexCount());
                meshData.GameObject  = GameObjectFactory.CreateNew("tree");
                meshData.MaterialKey = rule.GetMaterialKey();

                treeGen.Build(meshData);

                BuildObject(parent, meshData, rule, node);
            }
        }
예제 #15
0
        /// <inheritdoc />
        public override IGameObject BuildNode(Tile tile, Rule rule, Node node)
        {
            var mapPoint  = GeoProjection.ToMapCoordinate(tile.RelativeNullPoint, node.Point);
            var elevation = ElevationProvider.GetElevation(mapPoint);

            var trunkGradientKey   = rule.Evaluate <string>("trunk-color");
            var foliageGradientKey = rule.Evaluate <string>("foliage-color");

            var treeGen = new TreeGenerator()
                          .SetTrunkGradient(CustomizationService.GetGradient(trunkGradientKey))
                          .SetFoliageGradient(CustomizationService.GetGradient(foliageGradientKey))
                          .SetPosition(new Vector3((float)mapPoint.X, elevation, (float)mapPoint.Y));

            var meshData = new MeshData(MeshDestroyIndex.Default, treeGen.CalculateVertexCount());

            meshData.GameObject  = GameObjectFactory.CreateNew("tree " + node.Id);
            meshData.MaterialKey = rule.GetMaterialKey();

            treeGen.Build(meshData);

            BuildObject(tile.GameObject, meshData, rule, node);

            return(meshData.GameObject);
        }
예제 #16
0
 public FacadeBuilder(CustomizationService customizationService)
 {
     _customizationService = customizationService;
 }
예제 #17
0
        /// <inheritdoc />
        public override List <MeshData> Build(Building building)
        {
            Vector2d center;
            double   radius;

            CircleUtils.GetCircle(building.Footprint, out radius, out center);

            var center3d = new Vector3((float)center.X,
                                       building.Elevation + building.MinHeight + building.Height,
                                       (float)center.Y);

            var sphereGen = new IcoSphereGenerator()
                            .SetCenter(center3d)
                            .SetRadius((float)radius)
                            .SetRecursionLevel(2)
                            .IsSemiphere(true)
                            .SetGradient(CustomizationService.GetGradient(building.RoofColor));

            var mesh = CreateMesh(building.Footprint);

            var        floorCount       = building.Levels;
            var        floorVertexCount = mesh.Triangles.Count * 3 * 2 * floorCount;
            IMeshIndex floorMeshIndex   = new MultiPlaneMeshIndex(building.Levels, floorVertexCount);

            var roofVertexCount = sphereGen.CalculateVertexCount();

            var vertexCount = roofVertexCount + floorVertexCount;

            bool limitIsReached = false;

            if (vertexCount * 2 > Consts.MaxMeshSize)
            {
                vertexCount    = roofVertexCount;
                limitIsReached = true;
                floorMeshIndex = DummyMeshIndex.Default;
            }

            var meshIndex = new CompositeMeshIndex(2)
                            .AddMeshIndex(new SphereMeshIndex((float)radius, center3d))
                            .AddMeshIndex(floorMeshIndex);
            var meshData = new MeshData(meshIndex, vertexCount);

            // attach roof
            sphereGen.Build(meshData);

            if (!limitIsReached)
            {
                // attach floors
                AttachFloors(new RoofContext()
                {
                    Mesh      = mesh,
                    MeshData  = meshData,
                    MeshIndex = (MultiPlaneMeshIndex)floorMeshIndex,

                    Bottom             = building.Elevation + building.MinHeight,
                    FloorCount         = floorCount,
                    FloorHeight        = building.Height / floorCount,
                    FloorFrontGradient = CustomizationService.GetGradient(building.FloorFrontColor),
                    FloorBackGradient  = CustomizationService.GetGradient(building.FloorBackColor),

                    IsLastRoof = false
                });

                return(new List <MeshData>(1)
                {
                    meshData
                });
            }

            var meshDataList = BuildFloors(building, building.Levels, false);

            meshDataList.Add(meshData);
            return(meshDataList);
        }
예제 #18
0
        public override List <MeshData> Build(Building building)
        {
            var roofOffset = building.Elevation + building.MinHeight + building.Height;
            var roofHeight = roofOffset + building.RoofHeight;

            // 1. detect the longest segment
            float    length;
            Vector2d longestStart;
            Vector2d longestEnd;

            GetLongestSegment(building.Footprint, out length, out longestStart, out longestEnd);

            // 2. get direction vector
            var ridgeDirection = (new Vector3((float)longestEnd.X, roofOffset, (float)longestEnd.Y) -
                                  new Vector3((float)longestStart.X, roofOffset, (float)longestStart.Y)).normalized;

            // 3. get centroid
            var centroidPoint  = PolygonUtils.GetCentroid(building.Footprint);
            var centroidVector = new Vector3((float)centroidPoint.X, roofHeight, (float)centroidPoint.Y);

            // 4. get something like center line
            Vector3 p1 = centroidVector + length * length * ridgeDirection;
            Vector3 p2 = centroidVector - length * length * ridgeDirection;

            // 5. detect segments which have intesection with center line
            Vector2d first, second;
            int      firstIndex, secondIndex;

            DetectIntersectSegments(building.Footprint, new Vector2d(p1.x, p1.z), new Vector2d(p2.x, p2.z),
                                    out first, out firstIndex, out second, out secondIndex);
            if (firstIndex == -1 || secondIndex == -1)
            {
                Trace.Warn(LogCategory, Strings.RoofGenFailed, Name, building.Id.ToString());
                return(base.Build(building));
            }

            // prepare mesh and its index
            var mesh             = CreateMesh(building.Footprint);
            var floorCount       = building.Levels;
            var floorVertexCount = mesh.Triangles.Count * 3 * 2 * floorCount;
            var roofVertexCount  = (building.Footprint.Count - 1) * 2 * 12;

            var vertexCount = roofVertexCount + floorVertexCount;
            var planeCount  = building.Footprint.Count + floorCount;

            bool limitIsReached = false;

            if (vertexCount * 2 > Consts.MaxMeshSize)
            {
                vertexCount    = roofVertexCount;
                planeCount     = building.Footprint.Count;
                limitIsReached = true;
            }

            var meshIndex = new MultiPlaneMeshIndex(planeCount, vertexCount);
            var meshData  = new MeshData(meshIndex, vertexCount);

            // 6. process all segments and create vertices
            FillMeshData(meshData, CustomizationService.GetGradient(building.RoofColor), roofOffset,
                         roofHeight, building.Footprint, first, firstIndex, second, secondIndex);

            if (!limitIsReached)
            {
                AttachFloors(new RoofContext()
                {
                    Mesh      = mesh,
                    MeshData  = meshData,
                    MeshIndex = meshIndex,

                    Bottom             = building.Elevation + building.MinHeight,
                    FloorCount         = floorCount,
                    FloorHeight        = building.Height / floorCount,
                    FloorFrontGradient = CustomizationService.GetGradient(building.FloorFrontColor),
                    FloorBackGradient  = CustomizationService.GetGradient(building.FloorBackColor),

                    IsLastRoof = false
                });

                return(new List <MeshData>(1)
                {
                    meshData
                });
            }

            var meshDataList = BuildFloors(building, building.Levels, false);

            meshDataList.Add(meshData);
            return(meshDataList);
        }
예제 #19
0
        /// <inheritdoc />
        public override List <MeshData> Build(Building building)
        {
            var center     = PolygonUtils.GetCentroid(building.Footprint);
            var roofOffset = building.Elevation + building.MinHeight + building.Height;
            var footprint  = building.Footprint;
            var roofHeight = building.RoofHeight;
            var floorCount = building.Levels;

            var length           = footprint.Count;
            var mesh             = CreateMesh(footprint);
            var roofVertexCount  = 12 * length;
            var floorVertexCount = mesh.Triangles.Count * 3 * 2 * floorCount;

            var vertexCount = roofVertexCount + floorVertexCount;
            var planeCount  = building.Footprint.Count + floorCount;

            bool limitIsReached = false;

            if (vertexCount * 2 > Consts.MaxMeshSize)
            {
                vertexCount    = roofVertexCount;
                planeCount     = building.Footprint.Count;
                limitIsReached = true;
            }

            var meshIndex = new MultiPlaneMeshIndex(planeCount, vertexCount);
            var meshData  = new MeshData(meshIndex, vertexCount);

            var roofGradient = CustomizationService.GetGradient(building.RoofColor);

            for (int i = 0; i < length; i++)
            {
                var nextIndex = i == (length - 1) ? 0 : i + 1;

                var v0 = new Vector3((float)footprint[i].X, roofOffset, (float)footprint[i].Y);
                var v1 = new Vector3((float)center.X, roofOffset + roofHeight, (float)center.Y);
                var v2 = new Vector3((float)footprint[nextIndex].X, roofOffset, (float)footprint[nextIndex].Y);

                var v01 = Vector3Utils.GetIntermediatePoint(v0, v1);
                var v12 = Vector3Utils.GetIntermediatePoint(v1, v2);
                var v02 = Vector3Utils.GetIntermediatePoint(v0, v2);

                meshIndex.AddPlane(v0, v1, v2, meshData.NextIndex);

                var color = GetColor(roofGradient, v0);
                meshData.AddTriangle(v0, v01, v02, color, color);

                color = GetColor(roofGradient, v01);
                meshData.AddTriangle(v02, v01, v12, color, color);

                color = GetColor(roofGradient, v02);
                meshData.AddTriangle(v2, v02, v12, color, color);

                color = GetColor(roofGradient, v01);
                meshData.AddTriangle(v01, v1, v12, color, color);
            }

            if (!limitIsReached)
            {
                AttachFloors(new RoofContext()
                {
                    Mesh      = mesh,
                    MeshData  = meshData,
                    MeshIndex = meshIndex,

                    Bottom             = building.Elevation + building.MinHeight,
                    FloorCount         = floorCount,
                    FloorHeight        = building.Height / floorCount,
                    FloorFrontGradient = CustomizationService.GetGradient(building.FloorFrontColor),
                    FloorBackGradient  = CustomizationService.GetGradient(building.FloorBackColor),

                    IsLastRoof = false,
                });

                return(new List <MeshData>(1)
                {
                    meshData
                });
            }

            var meshDataList = BuildFloors(building, building.Levels, false);

            meshDataList.Add(meshData);
            return(meshDataList);
        }
예제 #20
0
 public PlaceElementBuilder(CustomizationService customizationService)
 {
     _customizationService = customizationService;
 }
예제 #21
0
        /// <inheritdoc />
        public override List <MeshData> Build(Building building)
        {
            var random     = new System.Random((int)building.Id);
            var footprint  = building.Footprint;
            var roofOffset = building.Elevation + building.MinHeight + building.Height;
            var roofHeight = roofOffset + building.RoofHeight;

            var offset = new ClipperOffset();

            offset.AddPath(footprint.Select(p => new IntPoint(p.X * Scale, p.Y * Scale)).ToList(),
                           JoinType.jtMiter, EndType.etClosedPolygon);

            var result = new List <List <IntPoint> >();

            offset.Execute(ref result, random.NextFloat(1, 3) * -Scale);

            if (result.Count != 1 || result[0].Count != footprint.Count)
            {
                Trace.Warn(LogCategory, Strings.RoofGenFailed, Name, building.Id.ToString());
                return(base.Build(building));
            }

            var    topVertices = ObjectPool.NewList <Vector2d>(footprint.Count);
            double scale       = Scale;

            foreach (var intPoint in result[0])
            {
                topVertices.Add(new Vector2d(intPoint.X / scale, intPoint.Y / scale));
            }
            // NOTE need reverse vertices
            topVertices.Reverse();

            var floorCount = building.Levels;
            var topMesh    = CreateMesh(topVertices);
            var floorMesh  = CreateMesh(footprint);

            var roofVertexCount  = topMesh.Triangles.Count * 3 * 2 + footprint.Count * 2 * 12;
            var floorVertexCount = floorMesh.Triangles.Count * 3 * 2 * floorCount;

            var vertexCount = roofVertexCount + floorVertexCount;

            var planeCount = footprint.Count + floorCount + 1;

            bool limitIsReached = false;

            if (vertexCount * 2 > Consts.MaxMeshSize)
            {
                vertexCount    = roofVertexCount;
                planeCount     = building.Footprint.Count + 1;
                limitIsReached = true;
            }

            var meshIndex = new MultiPlaneMeshIndex(planeCount, vertexCount);
            var meshData  = new MeshData(meshIndex, vertexCount);

            var roofGradient = CustomizationService.GetGradient(building.RoofColor);
            int index        = FindStartIndex(topVertices[0], footprint);

            for (int i = 0; i < topVertices.Count; i++)
            {
                var top        = topVertices[i];
                var bottom     = footprint[(index + i) % footprint.Count];
                var nextTop    = topVertices[(i + 1) % topVertices.Count];
                var nextBottom = footprint[(index + i + 1) % footprint.Count];

                var v0 = new Vector3((float)bottom.X, roofOffset, (float)bottom.Y);
                var v1 = new Vector3((float)nextBottom.X, roofOffset, (float)nextBottom.Y);
                var v2 = new Vector3((float)nextTop.X, roofHeight, (float)nextTop.Y);
                var v3 = new Vector3((float)top.X, roofHeight, (float)top.Y);

                meshIndex.AddPlane(v0, v1, v2, meshData.NextIndex);
                AddTriangle(meshData, roofGradient, v0, v2, v3);
                AddTriangle(meshData, roofGradient, v2, v0, v1);
            }
            ObjectPool.StoreList(topVertices);

            // Attach top reusing roof context object
            var context = new RoofContext()
            {
                Mesh      = topMesh,
                MeshData  = meshData,
                MeshIndex = meshIndex,

                Bottom             = roofHeight,
                FloorCount         = 1,
                FloorHeight        = building.Height / floorCount,
                FloorFrontGradient = CustomizationService.GetGradient(building.FloorFrontColor),
                FloorBackGradient  = CustomizationService.GetGradient(building.FloorBackColor),

                IsLastRoof        = true,
                RoofFrontGradient = roofGradient,
                RoofBackGradient  = roofGradient
            };

            AttachFloors(context);

            if (!limitIsReached)
            {
                context.Mesh       = floorMesh;
                context.MeshData   = meshData;
                context.Bottom     = building.Elevation + building.MinHeight;
                context.FloorCount = floorCount;
                context.IsLastRoof = false;
                AttachFloors(context);
                return(new List <MeshData>(1)
                {
                    meshData
                });
            }

            var meshDataList = BuildFloors(building, building.Levels, false);

            meshDataList.Add(meshData);
            return(meshDataList);
        }
예제 #22
0
        /// <inheritdoc />
        public override List <MeshData> Build(Building building)
        {
            var roofHeight = building.RoofHeight;
            var roofOffset = building.Elevation + building.MinHeight + building.Height;

            var skeleton        = SkeletonBuilder.Build(building.Footprint);
            var roofVertexCount = 0;

            foreach (var edgeResult in skeleton.Edges)
            {
                roofVertexCount += (edgeResult.Polygon.Count - 2) * 12;
            }

            var mesh             = CreateMesh(building.Footprint);
            var floorCount       = building.Levels;
            var floorVertexCount = mesh.Triangles.Count * 3 * 2 * floorCount;

            var vertexCount = roofVertexCount + floorVertexCount;
            var planeCount  = skeleton.Edges.Count + floorCount;

            bool limitIsReached = false;

            if (vertexCount * 2 > Consts.MaxMeshSize)
            {
                vertexCount    = roofVertexCount;
                planeCount     = building.Footprint.Count;
                limitIsReached = true;
            }

            var      meshIndex = new MultiPlaneMeshIndex(planeCount + floorCount, vertexCount);
            MeshData meshData  = new MeshData(meshIndex, vertexCount);

            try
            {
                var roofGradient = CustomizationService.GetGradient(building.RoofColor);
                foreach (var edge in skeleton.Edges)
                {
                    if (edge.Polygon.Count < 5)
                    {
                        HandleSimpleCase(meshData, meshIndex, roofGradient, skeleton, edge, roofOffset, roofHeight);
                    }
                    else
                    {
                        HandleComplexCase(meshData, meshIndex, roofGradient, skeleton, edge, roofOffset, roofHeight);
                    }
                }

                if (!limitIsReached)
                {
                    // attach floors
                    AttachFloors(new RoofContext()
                    {
                        Mesh      = mesh,
                        MeshData  = meshData,
                        MeshIndex = meshIndex,

                        Bottom             = building.Elevation + building.MinHeight,
                        FloorCount         = floorCount,
                        FloorHeight        = building.Height / floorCount,
                        FloorFrontGradient = CustomizationService.GetGradient(building.FloorFrontColor),
                        FloorBackGradient  = CustomizationService.GetGradient(building.FloorBackColor),

                        IsLastRoof = false
                    });
                    return(new List <MeshData>(1)
                    {
                        meshData
                    });
                }
                var meshDataList = BuildFloors(building, building.Levels, false);
                meshDataList.Add(meshData);
                return(meshDataList);
            }
            catch
            {
                // NOTE straight skeleton may fail on some footprints.
                Trace.Warn("building.roof", Strings.RoofGenFailed, Name, building.Id.ToString());
                return(base.Build(building));
            }
        }
예제 #23
0
 public DemoModelBuilder(CustomizationService customizationService)
 {
     _customizationService = customizationService;
     _placeElementBuilder  = new PlaceElementBuilder(customizationService);
 }
예제 #24
0
 void Start()
 {
     Srv = GetComponentInParent <CustomizationService>();
     SetModel();
     // Debug.Log(Model);
 }