Ejemplo n.º 1
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);
        }
    }
Ejemplo n.º 2
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);
    }
Ejemplo n.º 3
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);
    }
Ejemplo n.º 4
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);
                            }
                        }
                    }
                }
            }
        }
    }