示例#1
0
    public void FillInsideWithFootprints()
    {
        ClearUnmodifiedFootprints(false);

        //List<Footprint> instantiatedFootprints = new List<Footprint>();

        Vector3    bPos;
        Quaternion bRot;
        Vector3    closestPoint;
        //GameObject footprintObj;
        Footprint footprint;
        Primitive primitive = graph.mainPrimitives[0];

        List <Node> nodes = primitive.nodes;
        List <Edge> edges = primitive.edges;

        int failedPosCount = 0;
        int failedPosMax   = 1000;
        int safeCount      = 0;

        Vector3 point;
        Vector3 pointWorld;

        while (failedPosCount < failedPosMax && safeCount < 1000)
        {
            safeCount++;

            //Get random point inside the boundaries
            float randX = UnityEngine.Random.Range(primitive.minX, primitive.maxX);
            float randZ = UnityEngine.Random.Range(primitive.minZ, primitive.maxZ);

            point = new Vector3(randX, 0f, randZ);

            //If point is inside the polygon, proceed
            if (EdgeGraphUtility.PointIsInside(point, nodes, edges))
            {
                pointWorld = transform.TransformPoint(point);
                int footprintIdx = GetRandomInsideFootPrintIdx();
                GetFootprintPosAndRotAtTarget(pointWorld, out bPos, out bRot, out closestPoint, footprintIdx, false);
                footprint = UtilityTools.Helper.GetComponentInPrefabChildren <Footprint>(footprintPrefabsOnEdge[footprintIdx]);
                Matrix4x4 footprintTRSMatrix = Matrix4x4.TRS(bPos, bRot, Vector3.one);
                if (!FootprintOverlapsOthers(footprint, footprintTRSMatrix) && FootprintIsInsideGraph(footprint, footprintTRSMatrix))
                {
                    PlaceFootprint(bPos, bRot, footprintIdx, false);
                }
                else
                {
                    failedPosCount++;
                }
            }

            if (failedPosCount >= failedPosMax || safeCount >= 1000)
            {
                break;
            }
        }
    }
示例#2
0
    /// <summary>
    /// Gets position and rotation in given target position according to closest edge
    /// </summary>
    /// <param name="target"></param>
    /// <param name="pos"></param>
    /// <param name="rot"></param>
    /// <param name="index"></param>
    /// <param name="placeInside">Is footprint placed inside or outside the edge?</param>
    /// <param name="placeOnEdge">Is footprint placed on the edge or on target?</param>
    public void GetFootprintPosAndRotAtTarget(Vector3 target, out Vector3 pos, out Quaternion rot, out Vector3 closestPoint, int index, bool placeOnEdge = true, bool placeInside = true)
    {
        pos          = Vector3.zero;
        rot          = Quaternion.identity;
        closestPoint = Vector3.zero;

        if (placeOnEdge)
        {
            // Line the footprint with closest edge
            Edge edge = null;
            closestPoint = EdgeGraphUtility.GetClosestPointOnEdge(target, graph.mainPrimitives[0].nodes, graph.mainPrimitives[0].edges, transform, out edge);

            Node    n1     = EdgeGraphUtility.GetNode(edge.Node1, ref graph.mainPrimitives[0].nodes);
            Vector3 eN1Pos = n1.Position;
            Vector3 eN2Pos = EdgeGraphUtility.GetNode(edge.Node2, ref graph.mainPrimitives[0].nodes).Position;

            eN2Pos.y = eN1Pos.y;
            Footprint fp = UtilityTools.Helper.GetComponentInPrefabChildren <Footprint>(footprintPrefabsOnEdge[index]);
            if (fp != null)
            {
                Vector3 fpN1Pos     = fp.nodes[0].Position;
                Vector3 fpN2Pos     = fp.nodes[1].Position;
                Vector3 fpEdgePoint = Edge.GetClosestPointOnEdge(Vector3.zero, fpN1Pos, fpN2Pos);

                //Vector3 nodeDir = (fpN2Pos - fpN1Pos).normalized;
                Vector3 edgeDir = (eN2Pos - eN1Pos).normalized;

                Vector3 edgeNormal = UtilityTools.MathHelper.LeftSideNormal(edgeDir);
                // Check that edge normal points outside (building will be placed inside the edge)
                if (Vector3.Dot(n1.dirToInside, edgeNormal) > 0)
                {
                    edgeNormal = -edgeNormal;
                }

                // Place the building outside
                if (!placeInside)
                {
                    edgeNormal = -edgeNormal;
                }

                pos = closestPoint - edgeNormal * (fpEdgePoint.magnitude + .05f);

                rot = Quaternion.LookRotation((pos - closestPoint), Vector3.up);
            }
            else
            {
                Debug.Log("FootprintPlacer::GetFootprintPosAndRotAtTarget() - No footprint found in prefab.");
            }
        }
        else
        {
            pos = target;
            rot = Quaternion.AngleAxis(Random.Range(0f, 360f), Vector3.up);
        }
    }
示例#3
0
    bool FootprintIsInsideGraph(Footprint footprint, Matrix4x4 footprintTRSMatrix)
    {
        for (int i = 0; i < footprint.edges.Count; i++)
        {
            Vector3 n1PosWorld = footprintTRSMatrix.MultiplyPoint3x4(EdgeGraphUtility.GetNode(footprint.edges[i].Node1, ref footprint.nodes).Position);
            Vector3 n2PosWorld = footprintTRSMatrix.MultiplyPoint3x4(EdgeGraphUtility.GetNode(footprint.edges[i].Node2, ref footprint.nodes).Position);

            Vector3 n1PosGraph = graph.transform.InverseTransformPoint(n1PosWorld);
            Vector3 n2PosGraph = graph.transform.InverseTransformPoint(n2PosWorld);

            if (!EdgeGraphUtility.PointIsInside(n1PosGraph, graph.mainPrimitives[0].nodes, graph.mainPrimitives[0].edges) ||
                !EdgeGraphUtility.PointIsInside(n2PosGraph, graph.mainPrimitives[0].nodes, graph.mainPrimitives[0].edges))
            {
                return(false);
            }
        }

        return(true);
    }
示例#4
0
    void OnSceneGUI()
    {
        if (placer.handPlacementEnabled && placer.footprintPrefabsOnEdge.Count > 0)
        {
            controls.Update();

            Vector3    newFootprintPos = Vector3.zero;
            Quaternion newFootprintRot = Quaternion.identity;

            bool placeInside = EdgeGraphUtility.PointIsInside(controls.cursorLocalPosition, placer.graph.mainPrimitives[0].nodes, placer.graph.mainPrimitives[0].edges);

            if (controls.controlIsPressed)
            {
                if (placer.handPlacementOnEdge)
                {
                    if (handPlacedIndex >= placer.footprintPrefabsOnEdge.Count)
                    {
                        handPlacedIndex = placer.footprintPrefabsOnEdge.Count - 1;
                    }
                }
                else
                {
                    if (handPlacedIndex >= placer.footprintPrefabsInside.Count)
                    {
                        handPlacedIndex = placer.footprintPrefabsInside.Count - 1;
                    }
                }

                if (Event.current.isKey && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.W)
                {
                    if (placer.handPlacementOnEdge)
                    {
                        handPlacedIndex = UtilityTools.Helper.GetNextIndex <GameObject>(placer.footprintPrefabsOnEdge, handPlacedIndex);
                    }
                    else
                    {
                        handPlacedIndex = UtilityTools.Helper.GetNextIndex <GameObject>(placer.footprintPrefabsInside, handPlacedIndex);
                    }
                }
                else if (Event.current.isKey && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Q)
                {
                    if (placer.handPlacementOnEdge)
                    {
                        handPlacedIndex = UtilityTools.Helper.GetPrevIndex <GameObject>(placer.footprintPrefabsOnEdge, handPlacedIndex);
                    }
                    else
                    {
                        handPlacedIndex = UtilityTools.Helper.GetPrevIndex <GameObject>(placer.footprintPrefabsInside, handPlacedIndex);
                    }
                }
                else if (Event.current.isKey && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.E)
                {
                    placer.handPlacementOnEdge = !placer.handPlacementOnEdge;
                }

                Quaternion rot;
                Vector3    closestPoint;
                placer.GetFootprintPosAndRotAtTarget(controls.cursorWorldPosition, out newFootprintPos, out rot, out closestPoint, handPlacedIndex, placer.handPlacementOnEdge, placeInside);

                if (placer.handPlacementOnEdge)
                {
                    newFootprintRot = rot;
                }

                Footprint fp;
                if (placer.handPlacementOnEdge)
                {
                    fp = UtilityTools.Helper.GetComponentInPrefabChildren <Footprint>(placer.footprintPrefabsOnEdge[handPlacedIndex]);
                }
                else
                {
                    fp = UtilityTools.Helper.GetComponentInPrefabChildren <Footprint>(placer.footprintPrefabsInside[handPlacedIndex]);
                }

                if (fp != null)
                {
                    Handles.color = Color.yellow;
                    Matrix4x4 newPosMatrix = Matrix4x4.TRS(newFootprintPos, newFootprintRot, Vector3.one);
                    for (int i = 0; i < fp.nodes.Count; i++)
                    {
                        Node cur = fp.nodes[i];
                        Node next;
                        if (i == fp.nodes.Count - 1)
                        {
                            next = fp.nodes[0];
                        }
                        else
                        {
                            next = fp.nodes[i + 1];
                        }

                        Handles.DrawLine(newPosMatrix.MultiplyPoint3x4(cur.Position), newPosMatrix.MultiplyPoint3x4(next.Position));
                        Handles.CubeCap(0, newPosMatrix.MultiplyPoint3x4(cur.Position), Quaternion.LookRotation(newPosMatrix.GetColumn(2), newPosMatrix.GetColumn(1)), .2f);
                        if (placer.handPlacementOnEdge)
                        {
                            Handles.Label(controls.cursorWorldPosition, placer.footprintPrefabsOnEdge[handPlacedIndex].name, "box");
                        }
                        else
                        {
                            Handles.Label(controls.cursorWorldPosition, placer.footprintPrefabsInside[handPlacedIndex].name, "box");
                        }

                        Handles.SphereCap(0, newFootprintPos, Quaternion.identity, .2f);
                        Handles.SphereCap(0, closestPoint, Quaternion.identity, .2f);
                    }
                }
            }

            if (controls.MouseClickedDown())
            {
                if (controls.controlIsPressed)
                {
                    placer.PlaceFootprint(newFootprintPos, newFootprintRot, handPlacedIndex, placer.handPlacementOnEdge, true);
                    if (!placer.handPlacementOnEdge)
                    {
                        newFootprintRot = Quaternion.AngleAxis(UnityEngine.Random.Range(0f, 360f), Vector3.up);
                    }
                }
            }
        }

        Handles.BeginGUI();
        GUILayout.Window(1, new Rect(16f, 232f, 150f, 50f), DrawSceneWindow, "Placement by hand");
        Handles.EndGUI();
    }
示例#5
0
    bool FootprintOverlapsOthers(Footprint footprint, Matrix4x4 footprintTRSMatrix)
    {
        // Check if any footprint edges cross each other
        for (int i = 0; i < footprint.edges.Count; i++)
        {
            Vector3 n1Pos = footprintTRSMatrix.MultiplyPoint3x4(EdgeGraphUtility.GetNode(footprint.edges[i].Node1, ref footprint.nodes).Position);
            Vector3 n2Pos = footprintTRSMatrix.MultiplyPoint3x4(EdgeGraphUtility.GetNode(footprint.edges[i].Node2, ref footprint.nodes).Position);

            for (int j = 0; j < instantiatedFootprints.Count; j++)
            {
                List <Node> placedFootprintWorldNodes = new List <Node>();
                instantiatedFootprints[j].nodes.ForEach((node) =>
                {
                    Node newNode     = new Node(node);
                    newNode.Position = instantiatedFootprints[j].transform.TransformPoint(node.Position);
                    placedFootprintWorldNodes.Add(newNode);
                });

                for (int k = 0; k < instantiatedFootprints[j].edges.Count; k++)
                {
                    Vector3 n3Pos = instantiatedFootprints[j].transform.TransformPoint(EdgeGraphUtility.GetNode(instantiatedFootprints[j].edges[k].Node1, ref instantiatedFootprints[j].nodes).Position);
                    Vector3 n4Pos = instantiatedFootprints[j].transform.TransformPoint(EdgeGraphUtility.GetNode(instantiatedFootprints[j].edges[k].Node2, ref instantiatedFootprints[j].nodes).Position);

                    Vector3 intersect;
                    if (UtilityTools.MathHelper.AreIntersecting(out intersect, n1Pos, n2Pos, n3Pos, n4Pos) == 1)
                    {
                        return(true);
                    }
                }
            }
        }

        // Check if footprint is inside placed footprint
        Vector3 nodePosWorld;

        for (int i = 0; i < footprint.nodes.Count; i++)
        {
            nodePosWorld = footprintTRSMatrix.MultiplyPoint3x4(footprint.nodes[i].Position);
            for (int j = 0; j < instantiatedFootprints.Count; j++)
            {
                List <Node> placedFootprintWorldNodes = new List <Node>();
                instantiatedFootprints[j].nodes.ForEach((node) =>
                {
                    Node newNode     = new Node(node);
                    newNode.Position = instantiatedFootprints[j].transform.TransformPoint(node.Position);
                    placedFootprintWorldNodes.Add(newNode);
                });

                if (EdgeGraphUtility.PointIsInside(nodePosWorld, placedFootprintWorldNodes, instantiatedFootprints[j].edges))
                {
                    return(true);
                }
            }
        }

        // Check if any placed footprint is inside the footprint
        List <Node> footprintWorldNodes = new List <Node>();

        footprint.nodes.ForEach((node) =>
        {
            Node newNode     = new Node(node);
            newNode.Position = footprintTRSMatrix.MultiplyPoint3x4(node.Position);
            footprintWorldNodes.Add(newNode);
        });

        for (int i = 0; i < instantiatedFootprints.Count; i++)
        {
            List <Node> placedFootprintWorldNodes = new List <Node>();
            instantiatedFootprints[i].nodes.ForEach((node) =>
            {
                Node newNode     = new Node(node);
                newNode.Position = instantiatedFootprints[i].transform.TransformPoint(node.Position);
                placedFootprintWorldNodes.Add(newNode);
            });

            for (int j = 0; j < placedFootprintWorldNodes.Count; j++)
            {
                if (EdgeGraphUtility.PointIsInside(placedFootprintWorldNodes[j].Position, footprintWorldNodes, footprint.edges))
                {
                    return(true);
                }
            }
        }

        return(false);
    }
示例#6
0
    public void FillWithEdgesWithFootprints()
    {
        ClearUnmodifiedFootprints(true);

        //List<Footprint> instantiatedFootprints = new List<Footprint>();

        Vector3    target;
        Vector3    bPos;
        Vector3    closestPoint;
        Quaternion bRot;
        Matrix4x4  footprintTRSMatrix;
        Footprint  footprint;
        Primitive  primitive = graph.mainPrimitives[0];

        List <Node> nodes = primitive.nodes;
        List <Edge> edges = primitive.edges;

        // Two passes are made, first one places random footprints, the second tries every footprint on every position so smaller gaps left are filled
        for (int pass = 1; pass <= 2; pass++)
        {
            for (int i = 0; i < edges.Count; i++)
            {
                Node n1 = EdgeGraphUtility.GetNode(edges[i].Node1, ref nodes);
                Node n2 = EdgeGraphUtility.GetNode(edges[i].Node2, ref nodes);

                Vector3 n1Pos = transform.TransformPoint(n1.Position);
                Vector3 n2Pos = transform.TransformPoint(n2.Position);
                //Vector3 n1n2 = (n2Pos - n1Pos);

                int footprintIdx = GetRandomEdgeFootPrintIdx();
                for (float t = 0f; t < 1f; t += .005f)
                {
                    target = Vector3.Lerp(n1Pos, n2Pos, t);
                    GetFootprintPosAndRotAtTarget(target, out bPos, out bRot, out closestPoint, footprintIdx);

                    if (pass == 1)
                    {
                        footprint          = UtilityTools.Helper.GetComponentInPrefabChildren <Footprint>(footprintPrefabsOnEdge[footprintIdx]);
                        footprintTRSMatrix = Matrix4x4.TRS(bPos, bRot, Vector3.one);
                        if (!FootprintOverlapsOthers(footprint, footprintTRSMatrix) && FootprintIsInsideGraph(footprint, footprintTRSMatrix))
                        {
                            PlaceFootprint(bPos, bRot, footprintIdx, true);
                            footprintIdx = GetRandomEdgeFootPrintIdx();
                        }
                    }
                    else
                    {
                        for (int j = 0; j < footprintPrefabsOnEdge.Count; j++)
                        {
                            footprint          = UtilityTools.Helper.GetComponentInPrefabChildren <Footprint>(footprintPrefabsOnEdge[j]);
                            footprintTRSMatrix = Matrix4x4.TRS(bPos, bRot, Vector3.one);
                            if (!FootprintOverlapsOthers(footprint, footprintTRSMatrix) && FootprintIsInsideGraph(footprint, footprintTRSMatrix))
                            {
                                PlaceFootprint(bPos, bRot, j, true);
                            }
                        }
                    }
                }
            }
        }
    }