/// <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);
        }
        private int GetVertexCount(List <Vector2d> points, float maxWidth)
        {
            int count = 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);
                var distance = Vector3.Distance(start, end);
                count += (int)Math.Ceiling(distance / maxWidth) * 12;
            }
            return(count);
        }
Exemplo n.º 3
0
        /// <summary> Process unity specific data. </summary>
        private void BuildObject(Tile tile, IGameObject gameObjectWrapper, Rule rule,
                                 Rectangle2d rect, Vector2d point, float minHeight)
        {
            var gameObject = gameObjectWrapper.AddComponent(GameObject.CreatePrimitive(PrimitiveType.Cube));
            var transform  = gameObject.transform;
            var elevation  = ElevationProvider.GetElevation(point);

            transform.position = new Vector3((float)point.X, elevation + minHeight, (float)point.Y);
            // TODO define size
            transform.localScale = new Vector3(2, 2, 2);

            var p0 = new Vector2((float)rect.Left, (float)rect.Bottom);
            var p1 = new Vector2((float)rect.Right, (float)rect.Bottom);
            var p2 = new Vector2((float)rect.Left, (float)rect.Top);
            var p3 = new Vector2((float)rect.Right, (float)rect.Top);

            var mesh = gameObject.GetComponent <MeshFilter>().mesh;

            // Imagine looking at the front of the cube, the first 4 vertices are arranged like so
            //   2 --- 3
            //   |     |
            //   |     |
            //   0 --- 1
            // then the UV's are mapped as follows
            //    2    3    0    1   Front
            //    6    7   10   11   Back
            //   19   17   16   18   Left
            //   23   21   20   22   Right
            //    4    5    8    9   Top
            //   15   13   12   14   Bottom
            mesh.uv = new[]
            {
                p0, p1, p2, p3,
                p2, p3, p2, p3,
                p0, p1, p0, p1,
                p0, p3, p1, p2,
                p0, p3, p1, p2,
                p0, p3, p1, p2
            };

            gameObject.GetComponent <MeshRenderer>().sharedMaterial = rule.GetMaterial(CustomizationService);

            gameObjectWrapper.Parent = tile.GameObject;
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
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);
        }
        private IGameObject BuildBuilding(Tile tile, Rule rule, Model model, List <GeoCoordinate> footPrint)
        {
            if (tile.Registry.Contains(model.Id))
            {
                return(null);
            }

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

            PointUtils.GetClockwisePolygonPoints(tile.RelativeNullPoint, footPrint, points);

            var minHeight = BuildingRuleExtensions.GetMinHeight(rule);

            // TODO invent better algorithm
            var elevation = ElevationProvider.GetElevation(points[0]);

            var gameObject = BuildGameObject(tile, rule, model, points, elevation, minHeight);

            ObjectPool.StoreList(points);

            return(gameObject);
        }
        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);
            }
        }
Exemplo n.º 8
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);
        }
        private void BuildBarrierSegment(SegmentBuilderContext context, Vector3 start, Vector3 end,
                                         ref int startIndex)
        {
            var distance  = Vector3.Distance(start, end);
            var direction = (end - start).normalized;

            var stepCount = (int)Math.Ceiling(distance / context.MaxWidth);
            var width     = distance / stepCount;

            var startEle = ElevationProvider.GetElevation(start.x, start.z);

            // read context properties
            var gradient       = context.Gradient;
            var colorNoiseFreq = context.ColorNoiseFreq;
            var vertCount      = context.MeshData.Vertices.Length / 2;
            var vertices       = context.MeshData.Vertices;
            var triangles      = context.MeshData.Triangles;
            var colors         = context.MeshData.Colors;

            for (int z = 0; z < stepCount; z++)
            {
                // get next points
                end = start + direction * width;
                var   middle = start + direction * (0.5f * width);
                float endEle = ElevationProvider.GetElevation(end.x, end.z);

                var p0 = new Vector3(start.x, startEle, start.z);
                var p1 = new Vector3(end.x, endEle, end.z);
                var p2 = new Vector3(end.x, endEle + context.Height, end.z);
                var p3 = new Vector3(start.x, startEle + context.Height, start.z);
                var pc = new Vector3(middle.x, startEle + context.Height / 2, middle.z);

                var count = startIndex;

                #region Vertices
                vertices[count]             = p3;
                vertices[count + vertCount] = p3;
                vertices[++count]           = p0;
                vertices[count + vertCount] = p0;
                vertices[++count]           = pc;
                vertices[count + vertCount] = pc;

                vertices[++count]           = p0;
                vertices[count + vertCount] = p0;
                vertices[++count]           = p1;
                vertices[count + vertCount] = p1;
                vertices[++count]           = pc;
                vertices[count + vertCount] = pc;

                vertices[++count]           = p1;
                vertices[count + vertCount] = p1;
                vertices[++count]           = p2;
                vertices[count + vertCount] = p2;
                vertices[++count]           = pc;
                vertices[count + vertCount] = pc;

                vertices[++count]           = p2;
                vertices[count + vertCount] = p2;
                vertices[++count]           = p3;
                vertices[count + vertCount] = p3;
                vertices[++count]           = pc;
                vertices[count + vertCount] = pc;
                #endregion

                #region Triangles
                // triangles for outer part
                for (int i = startIndex; i < startIndex + 12; i++)
                {
                    triangles[i] = i;
                }

                var lastIndex = startIndex + vertCount + 12;
                for (int i = startIndex + vertCount; i < lastIndex; i++)
                {
                    var rest = i % 3;
                    triangles[i] = rest == 0 ? i : (rest == 1 ? i + 1 : i - 1);
                }
                #endregion

                #region Colors
                count = startIndex;
                var color = GetColor(gradient, colorNoiseFreq, p3);
                colors[count]             = color;
                colors[count + vertCount] = color;
                colors[++count]           = color;
                colors[count + vertCount] = color;
                colors[++count]           = color;
                colors[count + vertCount] = color;

                color                     = GetColor(gradient, colorNoiseFreq, p0);
                colors[++count]           = color;
                colors[count + vertCount] = color;
                colors[++count]           = color;
                colors[count + vertCount] = color;
                colors[++count]           = color;
                colors[count + vertCount] = color;

                color                     = GetColor(gradient, colorNoiseFreq, p1);
                colors[++count]           = color;
                colors[count + vertCount] = color;
                colors[++count]           = color;
                colors[count + vertCount] = color;
                colors[++count]           = color;
                colors[count + vertCount] = color;

                color                     = GetColor(gradient, colorNoiseFreq, p2);
                colors[++count]           = color;
                colors[count + vertCount] = color;
                colors[++count]           = color;
                colors[count + vertCount] = color;
                colors[++count]           = color;
                colors[count + vertCount] = color;
                #endregion

                // reuse last
                start       = end;
                startEle    = endEle;
                startIndex += 12;
            }
        }