Ejemplo n.º 1
0
 public static void FurnishRooms(LinkedList<RoomNode> roomList, RoomStyle rmstyle, GameObject doorConnector)
 {
     foreach (RoomNode room in roomList) {
             if(room.isCorridor == false)
             {
                 PlatformAssembler asm = room.roomObject.AddComponent<PlatformAssembler>();
                 asm.placeableObjects = rmstyle.placeablePlatforms;
                 LinkedList<PlatformingElement> doors = new LinkedList<PlatformingElement>();
                 foreach(RoomNode neighbor in room.neighbors)
                 {
                     Bounds overl = RoomNode.OverlapBounds(room.roomBounds, neighbor.roomBounds);
                     if(overl.extents.y > 0.01f)
                     {
                         GameObject newDoorPiece = (GameObject) Instantiate(doorConnector, overl.center - Vector3.Scale(Vector3.up, overl.extents), Quaternion.LookRotation(RoomNode.CheckRoomTouch(neighbor.roomBounds, room.roomBounds)));
                         doors.AddFirst(newDoorPiece.GetComponent<PlatformingElement>());
                     }
                     else
                     {
                         GameObject newDoorPiece = (GameObject) Instantiate(doorConnector, overl.center, Quaternion.LookRotation(RoomNode.CheckRoomTouch(neighbor.roomBounds, room.roomBounds)));
                         doors.AddFirst(newDoorPiece.GetComponent<PlatformingElement>());
                     }
                 }
                 if(doors.Count > 1) {
                     PlatformingElement[] starts = new PlatformingElement[doors.Count];
                     int doorind = 0;
                     foreach(PlatformingElement pe in doors)
                     {
                         starts[doorind++] = pe;
                     }
                     asm.ConnectDoorPieces(starts);
                 }
             }
         }
 }
Ejemplo n.º 2
0
    public void ConnectDoorPieces(PlatformingElement[] initialObjects)
    {
        if (placeableObjects.Length == 0)
        {
            return;
        }

        System.DateTime startTime = System.DateTime.UtcNow;
        allPieces = new LinkedList <PlatformingElement> ();
        LinkedList <PlatformingElement> newPieces;

        BuildPath(initialObjects [0], initialObjects [1], 0, 0, 20, 0, out newPieces);
        foreach (PlatformingElement p in newPieces)
        {
            allPieces.AddFirst(p);
        }
        for (int i = 2; i < initialObjects.Length; i++)
        {
            PlatformingElement closest = null;
            int     connNum            = 0;
            float   closestDist        = Mathf.Infinity;
            Vector3 initialObjCon      = initialObjects [i].getConnectorPos(0);
            foreach (PlatformingElement element in newPieces)
            {
                for (int con = 0; con < element.connectors.Length; con++)
                {
                    Vector3 diff = (element.getConnectorPos(con) - initialObjCon);
                    if (element.connectors [con].connectedNode == null)                     // && (Vector3.Dot (diff, element.getConnectorDir (con)) < 0 || diff.sqrMagnitude < 0.001f)) {
                    {
                        float dist = diff.sqrMagnitude;
                        if (dist < closestDist)
                        {
                            closest     = element;
                            connNum     = con;
                            closestDist = dist;
                        }
                    }
                }
            }

            if (closest == null && initialObjects[i - 1].connectors[0].connectedNode == null)
            {
                closest = initialObjects[i - 1];
                connNum = 0;
            }

            if (closest != null)
            {
                BuildPath(initialObjects [i], closest, 0, connNum, 20, 0, out newPieces);
                foreach (PlatformingElement p in newPieces)
                {
                    allPieces.AddFirst(p);
                }
            }
        }
        System.DateTime endTime = System.DateTime.UtcNow;
        Debug.Log((endTime - startTime).TotalMilliseconds + " milliseconds --- generated " + newPieces.Count);
    }
Ejemplo n.º 3
0
    // Use this for initialization
    void Start()
    {
        PlatformingElement pe = GetComponent <PlatformingElement> ();

        if (pe.connectors [0].connectedNode != null)
        {
            Vector3 rot = transform.localEulerAngles;
            rot.y = pe.connectors[0].connectedNode.transform.localEulerAngles.y;
            transform.localEulerAngles = rot;
            Destroy(this);
        }
    }
Ejemplo n.º 4
0
    void StretchPiece(PlatformingElement toStretch, Vector3 displacement, int stretchIndex, int connectorToMove, int connectorToNotMove)
    {
        Vector3 fixedConnectorPos  = toStretch.getConnectorPos(connectorToNotMove);
        Vector3 movingConnectorPos = toStretch.getConnectorPos(connectorToMove);
        float   currDist           = Mathf.Abs(movingConnectorPos [stretchIndex] - fixedConnectorPos [stretchIndex]);
        float   newDist            = currDist + Mathf.Abs(displacement [stretchIndex]);
        float   scaleFactor        = newDist / currDist;
        Vector3 localScale         = toStretch.transform.TransformDirection(toStretch.transform.localScale);

        localScale [stretchIndex] *= scaleFactor;

        toStretch.transform.localScale = toStretch.transform.InverseTransformDirection(localScale);
        toStretch.transform.position   = Vector3.zero;
        toStretch.transform.position  -= toStretch.getConnectorPos(connectorToNotMove);
        toStretch.transform.position  += fixedConnectorPos;
    }
Ejemplo n.º 5
0
    bool IsValidPlacement(PlatformingElement existingPiece, int connectorIndex, int newPieceIndex, int newPieceConnectorIndex, int angle)
    {
        if (angle != 0 && !placeableObjects [newPieceIndex].connectors [newPieceConnectorIndex].allowRotationOnConnector)
        {
            return(false);
        }
        Vector3 existingNormal = existingPiece.transform.TransformDirection(existingPiece.connectors [connectorIndex].normal);
        Vector3 newNormal      = placeableObjects [newPieceIndex].connectors [newPieceConnectorIndex].normal;
        Vector3 eulers         = Quaternion.FromToRotation(newNormal, existingNormal * -1).eulerAngles;

        if (eulers.x == 0 && eulers.z == 0)
        {
            return(true);
        }
        return(false);
    }
Ejemplo n.º 6
0
    public Vector2 CheckForConnection(PlatformingElement other, int myConnector, int allowDisplace, out Vector3 displaceVec)
    {
        for (int yourConnector = 0; yourConnector < other.connectors.Length; yourConnector++)
        {
            Vector3 myConnPoint    = connectors[myConnector].connectionPoint;
            Vector3 yourConnPoint  = other.connectors[yourConnector].connectionPoint;
            Vector3 myConnNormal   = connectors[myConnector].normal;
            Vector3 yourConnNormal = other.connectors[yourConnector].normal;
            myConnPoint    = transform.TransformPoint(myConnPoint);
            myConnNormal   = transform.TransformDirection(myConnNormal).normalized;
            yourConnPoint  = other.transform.TransformPoint(yourConnPoint);
            yourConnNormal = other.transform.TransformDirection(yourConnNormal).normalized;

            if (Vector3.Dot(myConnNormal, yourConnNormal) <= (-1 + Mathf.Min(connectors[myConnector].slackAngle, other.connectors[yourConnector].slackAngle)))
            {
                displaceVec = Vector3.zero;
                for (int i = 0; i < 3; i++)
                {
                    float diff = yourConnPoint[i] - myConnPoint[i];
                    int   mask;
                    if (diff > 0)
                    {
                        mask = (1 << i);
                    }
                    else
                    {
                        mask = (1 << (i + 3));
                    }
                    if ((allowDisplace & mask) != 0)
                    {
                        myConnPoint[i] = yourConnPoint[i];
                        displaceVec[i] = diff;
                    }
                }
                float normDist = Vector3.Dot(yourConnPoint - myConnPoint, myConnNormal);
                if (normDist >= 0 && normDist <= connectors[myConnector].slackNormal + other.connectors[yourConnector].slackNormal)
                {
                    if ((myConnPoint + myConnNormal * normDist - yourConnPoint).sqrMagnitude <= Mathf.Pow(connectors[myConnector].slackRadial + other.connectors[yourConnector].slackRadial, 2))
                    {
                        return(new Vector2(myConnector, yourConnector));
                    }
                }
            }
        }
        displaceVec = Vector3.zero;
        return(Vector2.one * -1);
    }
Ejemplo n.º 7
0
    //Rotate and attach new piece, return PlatformingElement component of new piece.
    public PlatformingElement PlacePiece(PlatformingElement existingPiece, int connectorIndex, int newPieceIndex, int newPieceConnectorIndex, float rotate)
    {
        GameObject newPiece = Instantiate (placeableObjects [newPieceIndex].gameObject) as GameObject;
                PlatformingElement newPlatform = newPiece.GetComponent<PlatformingElement> ();
                newPlatform.typeID = newPieceIndex;
                newPiece.transform.rotation = Quaternion.FromToRotation (newPlatform.connectors [newPieceConnectorIndex].normal,
            existingPiece.transform.TransformDirection (existingPiece.connectors [connectorIndex].normal) * -1);
                newPiece.transform.position = existingPiece.transform.TransformPoint (existingPiece.connectors [connectorIndex].connectionPoint)
                        - newPiece.transform.TransformDirection (newPlatform.connectors [newPieceConnectorIndex].connectionPoint);

                newPiece.transform.RotateAround (newPiece.transform.TransformPoint (newPlatform.connectors [newPieceConnectorIndex].connectionPoint),
            existingPiece.transform.TransformDirection (existingPiece.connectors [connectorIndex].normal), rotate);

                existingPiece.connectors [connectorIndex].connectedNode = newPlatform;
                newPlatform.connectors [newPieceConnectorIndex].connectedNode = existingPiece;
                return newPlatform;
    }
Ejemplo n.º 8
0
    public void ConnectDoorPieces(PlatformingElement[] initialObjects)
    {
        if (placeableObjects.Length == 0)
                        return;

        System.DateTime startTime = System.DateTime.UtcNow;
        allPieces = new LinkedList<PlatformingElement> ();
        LinkedList<PlatformingElement> newPieces;
        BuildPath (initialObjects [0], initialObjects [1], 0, 0, 20, 0, out newPieces);
        foreach (PlatformingElement p in newPieces)
            allPieces.AddFirst (p);
        for (int i = 2; i < initialObjects.Length; i++) {
            PlatformingElement closest = null;
            int connNum = 0;
            float closestDist = Mathf.Infinity;
            Vector3 initialObjCon = initialObjects [i].getConnectorPos (0);
            foreach (PlatformingElement element in newPieces) {
                for (int con = 0; con < element.connectors.Length; con++) {
                    Vector3 diff = (element.getConnectorPos (con) - initialObjCon);
                    if (element.connectors [con].connectedNode == null){// && (Vector3.Dot (diff, element.getConnectorDir (con)) < 0 || diff.sqrMagnitude < 0.001f)) {
                        float dist = diff.sqrMagnitude;
                        if (dist < closestDist) {
                            closest = element;
                            connNum = con;
                            closestDist = dist;
                        }
                    }
                }
            }

            if(closest == null && initialObjects[i-1].connectors[0].connectedNode == null)
            {
                closest = initialObjects[i-1];
                connNum = 0;
            }

            if (closest != null) {
                BuildPath (initialObjects [i], closest, 0, connNum, 20, 0, out newPieces);
                foreach (PlatformingElement p in newPieces)
                    allPieces.AddFirst (p);
            }
        }
        System.DateTime endTime = System.DateTime.UtcNow;
        Debug.Log ((endTime - startTime).TotalMilliseconds + " milliseconds --- generated " + newPieces.Count);
    }
Ejemplo n.º 9
0
    //Rotate and attach new piece, return PlatformingElement component of new piece.
    public PlatformingElement PlacePiece(PlatformingElement existingPiece, int connectorIndex, int newPieceIndex, int newPieceConnectorIndex, float rotate)
    {
        GameObject         newPiece    = Instantiate(placeableObjects [newPieceIndex].gameObject) as GameObject;
        PlatformingElement newPlatform = newPiece.GetComponent <PlatformingElement> ();

        newPlatform.typeID          = newPieceIndex;
        newPiece.transform.rotation = Quaternion.FromToRotation(newPlatform.connectors [newPieceConnectorIndex].normal,
                                                                existingPiece.transform.TransformDirection(existingPiece.connectors [connectorIndex].normal) * -1);
        newPiece.transform.position = existingPiece.transform.TransformPoint(existingPiece.connectors [connectorIndex].connectionPoint)
                                      - newPiece.transform.TransformDirection(newPlatform.connectors [newPieceConnectorIndex].connectionPoint);


        newPiece.transform.RotateAround(newPiece.transform.TransformPoint(newPlatform.connectors [newPieceConnectorIndex].connectionPoint),
                                        existingPiece.transform.TransformDirection(existingPiece.connectors [connectorIndex].normal), rotate);


        existingPiece.connectors [connectorIndex].connectedNode       = newPlatform;
        newPlatform.connectors [newPieceConnectorIndex].connectedNode = existingPiece;
        return(newPlatform);
    }
Ejemplo n.º 10
0
 public static void FurnishRooms(LinkedList <RoomNode> roomList, RoomStyle rmstyle, GameObject doorConnector)
 {
     foreach (RoomNode room in roomList)
     {
         if (room.isCorridor == false)
         {
             PlatformAssembler asm = room.roomObject.AddComponent <PlatformAssembler>();
             asm.placeableObjects = rmstyle.placeablePlatforms;
             LinkedList <PlatformingElement> doors = new LinkedList <PlatformingElement>();
             foreach (RoomNode neighbor in room.neighbors)
             {
                 Bounds overl = RoomNode.OverlapBounds(room.roomBounds, neighbor.roomBounds);
                 if (overl.extents.y > 0.01f)
                 {
                     GameObject newDoorPiece = (GameObject)Instantiate(doorConnector, overl.center - Vector3.Scale(Vector3.up, overl.extents), Quaternion.LookRotation(RoomNode.CheckRoomTouch(neighbor.roomBounds, room.roomBounds)));
                     doors.AddFirst(newDoorPiece.GetComponent <PlatformingElement>());
                 }
                 else
                 {
                     GameObject newDoorPiece = (GameObject)Instantiate(doorConnector, overl.center, Quaternion.LookRotation(RoomNode.CheckRoomTouch(neighbor.roomBounds, room.roomBounds)));
                     doors.AddFirst(newDoorPiece.GetComponent <PlatformingElement>());
                 }
             }
             if (doors.Count > 1)
             {
                 PlatformingElement[] starts = new PlatformingElement[doors.Count];
                 int doorind = 0;
                 foreach (PlatformingElement pe in doors)
                 {
                     starts[doorind++] = pe;
                 }
                 asm.ConnectDoorPieces(starts);
             }
         }
     }
 }
Ejemplo n.º 11
0
    Vector3 BuildPath(PlatformingElement start, PlatformingElement end, int startConn, int endConn, int depth, int directionMask, out LinkedList<PlatformingElement> newPieces)
    {
        foreach (PlatformingElement element in allPieces)
                {
                    if(element.getAdjustedExclusionZone().Intersects(start.getAdjustedExclusionZone()))
                    {
                        newPieces = new LinkedList<PlatformingElement>();
                        return Vector3.zero;
                    }
                }
                if (depth == 0) {
                        newPieces = new LinkedList<PlatformingElement> ();
                        return Vector3.one * float.NaN;
                }
                float tol = 0.95f;
                Vector3 diff = end.getConnectorPos (endConn) - start.getConnectorPos (startConn);
                Vector3[] targetDirs = Util.VecBreak (Util.VecSign (diff));

                int neededDirsCount = 0;
                foreach (Vector3 v in targetDirs) {
                        if (VecMaskCheck (directionMask, v)) {
                                neededDirsCount ++;
                        }
                }
                Vector3 startDir = start.getConnectorDir (startConn);
                Vector3 finalDir = end.getConnectorDir (endConn);
                if ((neededDirsCount == targetDirs.Length || (diff.sqrMagnitude < 0.001f)) && Vector3.Dot (startDir, finalDir) < -1 * tol) {
                        start.connectors[startConn].connectedNode = end;
                        end.connectors[endConn].connectedNode = start;
                        newPieces = new LinkedList<PlatformingElement>();
                        return end.getConnectorPos (endConn) - start.getConnectorPos (startConn);
                }

                for (int obj = 0; obj < placeableObjects.Length; obj++) {
                        for (int con = 0; con < placeableObjects[obj].connectors.Length; con++) {
                                for (int rot = 0; rot < 4; rot ++) {
                                        Quaternion attachRot = Quaternion.FromToRotation (placeableObjects [obj].connectors [con].normal, startDir * -1);
                                        Quaternion pieceRot = Quaternion.AngleAxis (rot * 90, startDir);
                                        Quaternion conRot = pieceRot * attachRot;
                                        if (placeableObjects [obj].allowTilt || ((conRot * Vector3.up).y > tol))
                                                for (int otherCon = 0; otherCon < placeableObjects[obj].connectors.Length; otherCon++) {
                                                        if (con != otherCon) {
                                                                Vector3 otherConTestDir = placeableObjects [obj].connectors [otherCon].normal;
                                                                Vector3 stretchDir = Vector3.Scale (otherConTestDir, placeableObjects [obj].allowedScaling);
                                                                if (stretchDir.sqrMagnitude > 0.001f) {
                                                                        if (!VecMaskCheck (directionMask, Util.VecSign (conRot * stretchDir))) {
                                                                                PlatformingElement newPiece = PlacePiece (start, startConn, obj, con, rot * 90);
                                                                                Vector3 displace = BuildPath (newPiece, end, otherCon, endConn, depth - 1, VecMaskAdd (directionMask, Util.VecSign (conRot * stretchDir)), out newPieces);

                                                                                if (Vector3.Dot (displace, conRot * stretchDir) > 0) {
                                                                                        Vector3 projDir = Vector3.Project (displace, (conRot * stretchDir).normalized);
                                                                                        displace = Vector3.Exclude (projDir, displace);
                                                                                        newPiece.transform.position += displace;
                                                                                        StretchPiece (newPiece, projDir, Util.VecSigIndex (projDir), otherCon, con);
                                                                                } else
                                                                                        newPiece.transform.position += displace;
                                    newPieces.AddFirst(newPiece);
                                                                                return displace;
                                                                        }
                                                                }

                                                                for (int i = 0; i < targetDirs.Length; i ++) {
                                                                        if ((Vector3.Dot (conRot * otherConTestDir, targetDirs [i]) > tol) && !VecMaskCheck (directionMask, targetDirs [i])) {
                                                                                PlatformingElement newPiece = PlacePiece (start, startConn, obj, con, rot * 90);
                                                                                Vector3 displace = BuildPath (newPiece, end, otherCon, endConn, depth - 1, directionMask, out newPieces);
                                                                                newPiece.transform.position += displace;
                                    newPieces.AddFirst(newPiece);
                                                                                return displace;
                                                                        }
                                                                }
                                                        }
                                                }
                                }
                        }
                }

                if (Vector3.Dot (startDir, finalDir) > -1 * tol)
                        for (int obj = 0; obj < placeableObjects.Length; obj++) {
                                for (int con = 0; con < placeableObjects[obj].connectors.Length; con++) {
                                        for (int rot = 0; rot < 4; rot ++) {
                                                Quaternion conRot = Quaternion.AngleAxis (rot * 90, startDir) * Quaternion.FromToRotation (placeableObjects [obj].connectors [con].normal, startDir * -1);
                                                if (placeableObjects [obj].allowTilt || ((conRot * Vector3.up).y > tol))
                                                        for (int otherCon = 0; otherCon < placeableObjects[obj].connectors.Length; otherCon++) {
                                                                if (con != otherCon) {
                                                                        Vector3 otherConTestDir = placeableObjects [obj].connectors [otherCon].normal;

                                                                        if ((Vector3.Dot (conRot * otherConTestDir, finalDir * -1) > tol)) {
                                                                                PlatformingElement newPiece = PlacePiece (start, startConn, obj, con, rot * 90);
                                                                                Vector3 displace = BuildPath (newPiece, end, otherCon, endConn, depth - 1, directionMask, out newPieces);
                                                                                newPiece.transform.position += displace;
                                newPieces.AddFirst(newPiece);
                                                                                return displace;
                                                                        }
                                                                }
                                                        }
                                        }
                                }
                        }
                newPieces = new LinkedList<PlatformingElement> ();
                return Vector3.one * float.NaN;
    }
Ejemplo n.º 12
0
    void StretchPiece(PlatformingElement toStretch, Vector3 displacement, int stretchIndex, int connectorToMove, int connectorToNotMove)
    {
        Vector3 fixedConnectorPos = toStretch.getConnectorPos (connectorToNotMove);
                Vector3 movingConnectorPos = toStretch.getConnectorPos (connectorToMove);
                float currDist = Mathf.Abs (movingConnectorPos [stretchIndex] - fixedConnectorPos [stretchIndex]);
                float newDist = currDist + Mathf.Abs (displacement [stretchIndex]);
                float scaleFactor = newDist / currDist;
                Vector3 localScale = toStretch.transform.TransformDirection (toStretch.transform.localScale);
                localScale [stretchIndex] *= scaleFactor;

                toStretch.transform.localScale = toStretch.transform.InverseTransformDirection (localScale);
                toStretch.transform.position = Vector3.zero;
                toStretch.transform.position -= toStretch.getConnectorPos (connectorToNotMove);
                toStretch.transform.position += fixedConnectorPos;
    }
Ejemplo n.º 13
0
 bool IsValidPlacement(PlatformingElement existingPiece, int connectorIndex, int newPieceIndex, int newPieceConnectorIndex, int angle)
 {
     if (angle != 0 && !placeableObjects [newPieceIndex].connectors [newPieceConnectorIndex].allowRotationOnConnector)
                     return false;
             Vector3 existingNormal = existingPiece.transform.TransformDirection (existingPiece.connectors [connectorIndex].normal);
             Vector3 newNormal = placeableObjects [newPieceIndex].connectors [newPieceConnectorIndex].normal;
             Vector3 eulers = Quaternion.FromToRotation (newNormal, existingNormal * -1).eulerAngles;
             if (eulers.x == 0 && eulers.z == 0)
                     return true;
             return false;
 }
Ejemplo n.º 14
0
    Vector3 BuildPath(PlatformingElement start, PlatformingElement end, int startConn, int endConn, int depth, int directionMask, out LinkedList <PlatformingElement> newPieces)
    {
        foreach (PlatformingElement element in allPieces)
        {
            if (element.getAdjustedExclusionZone().Intersects(start.getAdjustedExclusionZone()))
            {
                newPieces = new LinkedList <PlatformingElement>();
                return(Vector3.zero);
            }
        }
        if (depth == 0)
        {
            newPieces = new LinkedList <PlatformingElement> ();
            return(Vector3.one * float.NaN);
        }
        float   tol  = 0.95f;
        Vector3 diff = end.getConnectorPos(endConn) - start.getConnectorPos(startConn);

        Vector3[] targetDirs = Util.VecBreak(Util.VecSign(diff));

        int neededDirsCount = 0;

        foreach (Vector3 v in targetDirs)
        {
            if (VecMaskCheck(directionMask, v))
            {
                neededDirsCount++;
            }
        }
        Vector3 startDir = start.getConnectorDir(startConn);
        Vector3 finalDir = end.getConnectorDir(endConn);

        if ((neededDirsCount == targetDirs.Length || (diff.sqrMagnitude < 0.001f)) && Vector3.Dot(startDir, finalDir) < -1 * tol)
        {
            start.connectors[startConn].connectedNode = end;
            end.connectors[endConn].connectedNode     = start;
            newPieces = new LinkedList <PlatformingElement>();
            return(end.getConnectorPos(endConn) - start.getConnectorPos(startConn));
        }

        for (int obj = 0; obj < placeableObjects.Length; obj++)
        {
            for (int con = 0; con < placeableObjects[obj].connectors.Length; con++)
            {
                for (int rot = 0; rot < 4; rot++)
                {
                    Quaternion attachRot = Quaternion.FromToRotation(placeableObjects [obj].connectors [con].normal, startDir * -1);
                    Quaternion pieceRot  = Quaternion.AngleAxis(rot * 90, startDir);
                    Quaternion conRot    = pieceRot * attachRot;
                    if (placeableObjects [obj].allowTilt || ((conRot * Vector3.up).y > tol))
                    {
                        for (int otherCon = 0; otherCon < placeableObjects[obj].connectors.Length; otherCon++)
                        {
                            if (con != otherCon)
                            {
                                Vector3 otherConTestDir = placeableObjects [obj].connectors [otherCon].normal;
                                Vector3 stretchDir      = Vector3.Scale(otherConTestDir, placeableObjects [obj].allowedScaling);
                                if (stretchDir.sqrMagnitude > 0.001f)
                                {
                                    if (!VecMaskCheck(directionMask, Util.VecSign(conRot * stretchDir)))
                                    {
                                        PlatformingElement newPiece = PlacePiece(start, startConn, obj, con, rot * 90);
                                        Vector3            displace = BuildPath(newPiece, end, otherCon, endConn, depth - 1, VecMaskAdd(directionMask, Util.VecSign(conRot * stretchDir)), out newPieces);

                                        if (Vector3.Dot(displace, conRot * stretchDir) > 0)
                                        {
                                            Vector3 projDir = Vector3.Project(displace, (conRot * stretchDir).normalized);
                                            displace = Vector3.Exclude(projDir, displace);
                                            newPiece.transform.position += displace;
                                            StretchPiece(newPiece, projDir, Util.VecSigIndex(projDir), otherCon, con);
                                        }
                                        else
                                        {
                                            newPiece.transform.position += displace;
                                        }
                                        newPieces.AddFirst(newPiece);
                                        return(displace);
                                    }
                                }

                                for (int i = 0; i < targetDirs.Length; i++)
                                {
                                    if ((Vector3.Dot(conRot * otherConTestDir, targetDirs [i]) > tol) && !VecMaskCheck(directionMask, targetDirs [i]))
                                    {
                                        PlatformingElement newPiece = PlacePiece(start, startConn, obj, con, rot * 90);
                                        Vector3            displace = BuildPath(newPiece, end, otherCon, endConn, depth - 1, directionMask, out newPieces);
                                        newPiece.transform.position += displace;
                                        newPieces.AddFirst(newPiece);
                                        return(displace);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        if (Vector3.Dot(startDir, finalDir) > -1 * tol)
        {
            for (int obj = 0; obj < placeableObjects.Length; obj++)
            {
                for (int con = 0; con < placeableObjects[obj].connectors.Length; con++)
                {
                    for (int rot = 0; rot < 4; rot++)
                    {
                        Quaternion conRot = Quaternion.AngleAxis(rot * 90, startDir) * Quaternion.FromToRotation(placeableObjects [obj].connectors [con].normal, startDir * -1);
                        if (placeableObjects [obj].allowTilt || ((conRot * Vector3.up).y > tol))
                        {
                            for (int otherCon = 0; otherCon < placeableObjects[obj].connectors.Length; otherCon++)
                            {
                                if (con != otherCon)
                                {
                                    Vector3 otherConTestDir = placeableObjects [obj].connectors [otherCon].normal;

                                    if ((Vector3.Dot(conRot * otherConTestDir, finalDir * -1) > tol))
                                    {
                                        PlatformingElement newPiece = PlacePiece(start, startConn, obj, con, rot * 90);
                                        Vector3            displace = BuildPath(newPiece, end, otherCon, endConn, depth - 1, directionMask, out newPieces);
                                        newPiece.transform.position += displace;
                                        newPieces.AddFirst(newPiece);
                                        return(displace);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        newPieces = new LinkedList <PlatformingElement> ();
        return(Vector3.one * float.NaN);
    }