private Block CreateStreetBlock(StreetNode street)
    {
        GameObject blockGameObject = (GameObject)GameObject.Instantiate(blockPrefab, Vector3.zero, Quaternion.identity);

        int childCount = street.nodes.GetLength(0);

        float     leftMaxWidth  = 0;
        float     rightMaxWidth = 0;
        float     offsetLeft    = 0;
        float     offsetRight   = 0;
        Transform leftSide      = blockGameObject.transform.Find("LeftSide").transform;
        Transform rightSide     = blockGameObject.transform.Find("RightSide").transform;

        for (int i = 0; i < childCount; i++)
        {
            Node       node                 = street.nodes [i];
            Block      childBlock           = CreateBlock(node);
            GameObject childBlockGameObject = childBlock.gameObject;
            if (i % 2 == 1)
            {
                childBlockGameObject.transform.RotateAround(Vector3.zero, Vector3.up, -90);
                childBlockGameObject.transform.localPosition = new Vector3(0, 0, childBlock.width / 2 + offsetLeft);
                offsetLeft  += childBlock.width;
                leftMaxWidth = (leftMaxWidth > childBlock.length) ? leftMaxWidth : childBlock.length;
                childBlockGameObject.transform.SetParent(leftSide, false);
            }
            else
            {
                childBlockGameObject.transform.RotateAround(Vector3.zero, Vector3.up, 90);
                childBlockGameObject.transform.localPosition = new Vector3(0, 0, childBlock.width / 2 + offsetRight);
                offsetRight  += childBlock.width;
                rightMaxWidth = (rightMaxWidth > childBlock.length) ? rightMaxWidth : childBlock.length;
                childBlockGameObject.transform.SetParent(rightSide, false);
            }
        }

        float midpointOffset = (leftMaxWidth - rightMaxWidth) / 2;

        float length      = ((offsetLeft > offsetRight) ? offsetLeft : offsetRight) * 1f;
        float streetWidth = length / 50;

        leftSide.Translate(new Vector3(-streetWidth / 2 + midpointOffset, 0, 0));
        rightSide.Translate(new Vector3(streetWidth / 2 + midpointOffset, 0, 0));

        GameObject streetGameObject = (GameObject)GameObject.Instantiate(streetPrefab, new Vector3(midpointOffset, 0, 0), Quaternion.identity);

        streetGameObject.transform.localScale = new Vector3(streetWidth, 1, length);
        streetGameObject.transform.SetParent(blockGameObject.transform, true);

        Block result = new Block();

        result.gameObject = blockGameObject;
        result.width      = (leftMaxWidth + streetWidth + rightMaxWidth) * 1f;
        result.length     = length;
        return(result);
    }
    private Node CreateModel(int depth)
    {
        int         subTreeCount = (int)(depth / 2f + (Random.value * depth / 2f));
        int         leafCount    = (int)(Random.value * subTreeCount * 70 / depth);
        List <Node> nodes        = new List <Node> ();

        for (int i = 0; i < subTreeCount; i++)
        {
            nodes.Insert((int)(nodes.Count * Random.value), CreateModel(depth - 2));
        }

        for (int i = 0; i < leafCount; i++)
        {
            nodes.Insert((int)(nodes.Count * Random.value), new BuildingNode());
        }

        StreetNode street = new StreetNode(nodes.ToArray());

        return(street);
    }
Example #3
0
        // Function to stitch the street to the current list of nodes
        public bool Stitch(XmlBaseFactory xmlBaseFactory, WaysFactory street)
        {
            // Create list to append
            List <StreetNode> append = new List <StreetNode>();

            for (int i = 0; i < street.ndref.Count; i++)
            {
                StreetNode node = new StreetNode();
                node.id       = street.ndref[i];
                node.position = xmlBaseFactory.allNodes[node.id] - xmlBaseFactory.boundsFactory.center;
                node.waterway = street.isWaterway;
                append.Add(node);
            }

            // Atemmpt to stitch append list to current list of nodes

            // If street is empty
            if (nodes.Count == 0)
            {
                nodes = append;
            }
            // if the first node in the street is the same as the first node in the street we're trying to stich
            else if (nodes[0].id == append[0].id)
            {
                nodes.Reverse();
                nodes.AddRange(append);
            }
            // if the first node in the street is the same as the last node in the street we're trying to stitch
            else if (nodes[0].id == append[append.Count - 1].id)
            {
                append.AddRange(nodes);
                nodes = append;
            }
            // if the last node in the street is the same as the first node in the street we're trying to stitch
            else if (nodes[nodes.Count - 1].id == append[0].id)
            {
                nodes.AddRange(append);
            }
            // if the last node in the street is the same as the last node in the street we're trying to stitch
            else if (nodes[nodes.Count - 1].id == append[append.Count - 1].id)
            {
                append.Reverse();
                nodes.AddRange(append);
            }
            else
            {
                return(false);
            }

            // Cleanup data
            // Remove duplicate ids
            List <StreetNode> copy = new List <StreetNode>();

            for (int i = 0; i < nodes.Count; i++)
            {
                if (copy.Count == 0 || copy[copy.Count - 1].id != nodes[i].id)
                {
                    copy.Add(nodes[i]);
                }
            }
            nodes = copy;

            // Remove single waterways
            for (int i = 0; i < nodes.Count; i++)
            {
                bool fPrev = i - 1 >= 0 ? nodes[i - 1].waterway : !nodes[i].waterway;
                bool fNext = i + 1 < nodes.Count ? nodes[i + 1].waterway : !nodes[i].waterway;
                bool fCurr = nodes[i].waterway;
                if (fCurr != fPrev && fCurr != fNext)
                {
                    nodes[i].waterway = !(nodes[i].waterway);
                }
            }

            // Check if waterway is looped
            looped = nodes.Count > 2 && nodes[0].id == nodes[nodes.Count - 1].id;

            return(true);
        }
Example #4
0
    // Creates the waterways
    private void CreateWaterway(Street street, string name)
    {
        List <Vector3> vertices   = new List <Vector3>();
        List <Vector3> normals    = new List <Vector3>();
        List <Vector2> uvs        = new List <Vector2>();
        List <int>     triangles0 = new List <int>(); // road
        List <int>     triangles1 = new List <int>(); // waterway

        for (int i = 1; i < street.nodes.Count; i++)
        {
            StreetNode s0;
            StreetNode s1 = street.nodes[i - 1];
            StreetNode s2 = street.nodes[i];
            StreetNode s3;

            // Get point 0
            if (i > 1)
            {
                s0 = street.nodes[i - 2];
            }
            else if (street.looped)
            {
                s0 = street.nodes[street.nodes.Count - 1];
            }
            else
            {
                s0 = new StreetNode()
                {
                    position = 2 * s1.position - s2.position,
                    waterway = s1.waterway,
                };
            }

            // Get point 3
            if (i < street.nodes.Count - 1)
            {
                s3 = street.nodes[i + 1];
            }
            else if (street.looped)
            {
                s3 = street.nodes[1];
            }
            else
            {
                s3 = new StreetNode()
                {
                    position = 2 * s2.position - s1.position,
                    waterway = s2.waterway,
                };
            }

            // Width of the waterway at each point
            float waterWidth = s0.waterway || s1.waterway || s2.waterway || s3.waterway ? riverWid : streamWid;

            // Calculate section vertices
            Vector3 v1 = Intersection(
                Perpendicular(s0.position, s1.position, -waterWidth), Perpendicular(s1.position, s0.position, +waterWidth),
                Perpendicular(s2.position, s1.position, +waterWidth), Perpendicular(s1.position, s2.position, -waterWidth)
                );

            Vector3 v2 = Intersection(
                Perpendicular(s0.position, s1.position, +waterWidth), Perpendicular(s1.position, s0.position, -waterWidth),
                Perpendicular(s2.position, s1.position, -waterWidth), Perpendicular(s1.position, s2.position, +waterWidth)
                );

            Vector3 v3 = Intersection(
                Perpendicular(s1.position, s2.position, -waterWidth), Perpendicular(s2.position, s1.position, +waterWidth),
                Perpendicular(s3.position, s2.position, +waterWidth), Perpendicular(s2.position, s3.position, -waterWidth)
                );

            Vector3 v4 = Intersection(
                Perpendicular(s1.position, s2.position, +waterWidth), Perpendicular(s2.position, s1.position, -waterWidth),
                Perpendicular(s3.position, s2.position, -waterWidth), Perpendicular(s2.position, s3.position, +waterWidth)
                );

            // Add vertices
            vertices.Add(v1);
            vertices.Add(v2);
            vertices.Add(v3);
            vertices.Add(v4);

            // Add normals
            normals.Add(Vector3.up);
            normals.Add(Vector3.up);
            normals.Add(Vector3.up);
            normals.Add(Vector3.up);

            // Add uvs
            uvs.Add(new Vector2(0, 0));
            uvs.Add(new Vector2(1, 0));
            uvs.Add(new Vector2(0, 1));
            uvs.Add(new Vector2(1, 1));

            // Set indices
            int p1 = vertices.Count - 4;
            int p2 = vertices.Count - 3;
            int p3 = vertices.Count - 2;
            int p4 = vertices.Count - 1;

            // Add triangles
            triangles1.Add(p1);
            triangles1.Add(p2);
            triangles1.Add(p3);
            triangles1.Add(p2);
            triangles1.Add(p4);
            triangles1.Add(p3);
        }

        // Find mesh center and move vertices
        Vector3 center = Vector3.zero;

        foreach (Vector3 v in vertices)
        {
            center += v;
        }
        center /= vertices.Count;
        for (int i = 0; i < vertices.Count; i++)
        {
            vertices[i] -= center;
        }

        // Create object
        GameObject   go = new GameObject(name);
        MeshFilter   mf = go.AddComponent <MeshFilter>();
        MeshRenderer mr = go.AddComponent <MeshRenderer>();
        MeshCollider mc = go.AddComponent <MeshCollider>();

        go.transform.position = center;
        mf.mesh.vertices      = vertices.ToArray();
        mf.mesh.normals       = normals.ToArray();
        mf.mesh.uv            = uvs.ToArray();

        // Add triangles & materials
        if (triangles0.Count == 0)
        {
            mf.mesh.triangles = triangles1.ToArray();
            mr.material       = waterMat;
        }
        else if (triangles1.Count == 0)
        {
            mf.mesh.triangles = triangles0.ToArray();
            mr.material       = waterMat;
        }
        else
        {
            mf.mesh.subMeshCount = 2;
            mf.mesh.SetTriangles(triangles0.ToArray(), 0);
            mf.mesh.SetTriangles(triangles1.ToArray(), 1);

            mr.materials = new Material[] { waterMat };
        }

        // Move object ontop of the terrain
        RaycastHit hit;

        if (Physics.Raycast(go.transform.position, Vector3.down, out hit))
        {
            go.transform.position = hit.point + new Vector3(0, 0.035f, 0);
        }
    }
Example #5
0
    private void CreateStreet(Street street)
    {
        string name = street.nodes[0].name;

        List <Vector3> vertices   = new List <Vector3>();
        List <Vector3> normals    = new List <Vector3>();
        List <Vector2> uvs        = new List <Vector2>();
        List <int>     triangles0 = new List <int>();   // road
        List <int>     triangles1 = new List <int>();   // footway

        for (int i = 1; i < street.nodes.Count; i++)
        {
            StreetNode s0;
            StreetNode s1 = street.nodes[i - 1];
            StreetNode s2 = street.nodes[i];
            StreetNode s3;

            // Get point 0
            if (i > 1)
            {
                s0 = street.nodes[i - 2];
            }
            else if (street.looped)
            {
                s0 = street.nodes[street.nodes.Count - 1];
            }
            else
            {
                s0 = new StreetNode()
                {
                    position = 2 * s1.position - s2.position,
                    footway  = s1.footway,
                };
            }

            // Get point 3
            if (i < street.nodes.Count - 1)
            {
                s3 = street.nodes[i + 1];
            }
            else if (street.looped)
            {
                s3 = street.nodes[1];
            }
            else
            {
                s3 = new StreetNode()
                {
                    position = 2 * s2.position - s1.position,
                    footway  = s2.footway,
                };
            }

            // Width of the road at each point
            float w0 = s0.footway ? 1.6f : 3.7f;
            float w1 = s1.footway ? 1.6f : 3.7f;
            float w2 = s2.footway ? 1.6f : 3.7f;
            float w3 = s3.footway ? 1.6f : 3.7f;

            // Calculate section vertices
            Vector3 v1 = Intersection(
                Perpendicular(s0.position, s1.position, -w0), Perpendicular(s1.position, s0.position, +w1),
                Perpendicular(s2.position, s1.position, +w2), Perpendicular(s1.position, s2.position, -w1)
                );

            Vector3 v2 = Intersection(
                Perpendicular(s0.position, s1.position, +w0), Perpendicular(s1.position, s0.position, -w1),
                Perpendicular(s2.position, s1.position, -w2), Perpendicular(s1.position, s2.position, +w1)
                );

            Vector3 v3 = Intersection(
                Perpendicular(s1.position, s2.position, -w1), Perpendicular(s2.position, s1.position, +w2),
                Perpendicular(s3.position, s2.position, +w3), Perpendicular(s2.position, s3.position, -w2)
                );

            Vector3 v4 = Intersection(
                Perpendicular(s1.position, s2.position, +w1), Perpendicular(s2.position, s1.position, -w2),
                Perpendicular(s3.position, s2.position, -w3), Perpendicular(s2.position, s3.position, +w2)
                );

            // Add vertices, normals and uvs
            vertices.Add(v1);
            vertices.Add(v2);
            vertices.Add(v3);
            vertices.Add(v4);

            normals.Add(Vector3.up);
            normals.Add(Vector3.up);
            normals.Add(Vector3.up);
            normals.Add(Vector3.up);

            uvs.Add(new Vector2(0, 0));
            uvs.Add(new Vector2(1, 0));
            uvs.Add(new Vector2(0, 1));
            uvs.Add(new Vector2(1, 1));

            int p1 = vertices.Count - 4;
            int p2 = vertices.Count - 3;
            int p3 = vertices.Count - 2;
            int p4 = vertices.Count - 1;

            // Add triangles
            if (s2.footway)
            {
                triangles1.Add(p1);
                triangles1.Add(p2);
                triangles1.Add(p3);
                triangles1.Add(p2);
                triangles1.Add(p4);
                triangles1.Add(p3);
            }
            else
            {
                triangles0.Add(p1);
                triangles0.Add(p2);
                triangles0.Add(p3);
                triangles0.Add(p2);
                triangles0.Add(p4);
                triangles0.Add(p3);
            }

            if (street.nodes[i].name != name || i >= street.nodes.Count - 1)
            {
                // Find mesh center and move vertices
                Vector3 center = Vector3.zero;
                foreach (Vector3 v in vertices)
                {
                    center += v;
                }
                center /= vertices.Count;

                // Move vertices ontop of terrain
                for (int j = 0; j < vertices.Count; j++)
                {
                    RaycastHit hit;
                    if (Physics.Raycast(new Vector3(vertices[j].x, vertices[j].y + 200f, vertices[j].z), Vector3.down, out hit))
                    {
                        vertices[j] = new Vector3(vertices[j].x, hit.point.y + 0.05f, vertices[j].z);
                    }
                }

                // Move vertices based on center
                for (int j = 0; j < vertices.Count; j++)
                {
                    vertices[j] -= center;
                }

                // Create object
                GameObject   go = new GameObject(name);
                MeshFilter   mf = go.AddComponent <MeshFilter>();
                MeshRenderer mr = go.AddComponent <MeshRenderer>();
                MeshCollider mc = go.AddComponent <MeshCollider>();
                go.transform.position = center;
                mf.mesh.vertices      = vertices.ToArray();
                mf.mesh.normals       = normals.ToArray();
                mf.mesh.uv            = uvs.ToArray();

                /* Hide Road objects in the project hierarchy to make it more readable */
                // go.hideFlags = HideFlags.HideInHierarchy;

                go.transform.parent = parent.transform;

                // Add triangles & materials
                if (triangles0.Count == 0)
                {
                    mf.mesh.triangles = triangles1.ToArray();
                    mr.material       = footway;
                }
                else if (triangles1.Count == 0)
                {
                    mf.mesh.triangles = triangles0.ToArray();
                    mr.material       = road;
                }
                else
                {
                    mf.mesh.subMeshCount = 2;
                    mf.mesh.SetTriangles(triangles0.ToArray(), 0);
                    mf.mesh.SetTriangles(triangles1.ToArray(), 1);
                    mr.materials = new Material[] { road, footway };
                }

                // Clear data
                vertices.Clear();
                normals.Clear();
                uvs.Clear();
                triangles0.Clear();
                triangles1.Clear();

                name = street.nodes[i].name;
            }
        }
    }