Пример #1
0
    public void ThreadFindPathObject(object o)
    {
        if (o.GetType() != typeof(NavPathRequest))
        {
            ThreadRunner.ExportData(null);
            ThreadRunner.MarkComplete();
            return;
        }
        NavPathRequest r = (NavPathRequest)o;

        ThreadFindPath(r.entry, r.exit, r.tolerance);
    }
Пример #2
0
    void ThreadedSphere(object d)
    {
        int DetailLevel = SphereDetail;

        if (DetailLevel < 1)
        {
            DetailLevel = 1;
        }

        List <Vector3> verts = new List <Vector3>();
        List <Vector2> uvs   = new List <Vector2>();
        List <int>     tris  = new List <int>();
        int            index = 0;


        List <Vector3> PointTriplets = new List <Vector3>();

        // phi = (1 + root(5)) / 2 = 1.6180339887498948482045868343656
        float high = (1f + Mathf.Sqrt(5)) / 2f;
        float low  = 1.0f;
        float zero = 0.0f;

        float[] settings = new float[3] {
            zero, low, high
        };
        // generate the main points
        // z is forward. So...I don't know.

        // 0, +-1, +- phi



        // using detail level, produce loops for faces.

        /*
         * POINTS ON UNIQUE RECTANGLES
         * We take any point.
         * eg. P1(h,z,l)
         * We fork, raising z to high in both positive and negative.
         * Low axis goes to zero.
         * High axis goes to low.
         * eg. P2a(l,+h,z)  P2b(1,-h, z)
         * Low goes to zero.
         * eg. P3a(z,+l,h)   P3b(z,-l,h)
         */
        // we should take the y = 0 rectangle, and generate the 8 faces from it's 4 points
        Vector3[] set = new Vector3[4] {
            new Vector3(1, 0, 2),
            new Vector3(1, 0, -2),
            new Vector3(-1, 0, -2),
            new Vector3(-1, 0, 2)
        };


        Vector3 upperorigin = Vector3.zero, upperleft = Vector3.zero, upperright = Vector3.zero, lowerorigin = Vector3.zero, lowerleft = Vector3.zero, lowerright = Vector3.zero;

        for (int i = 0; i < 4; i++)
        {
            // do lower y triangle first.
            // this triangle points up.
            lowerorigin = new Vector3(set[i].x, set[i].y, set[i].z);

            // high to low, low to zero, zero to high [lower fork]
            lowerleft.x = Mathf.Sign(lowerorigin.x) * ((Mathf.Abs(lowerorigin.x) - 1 < 0) ? (Mathf.Sign(lowerorigin.x) * 2) : (Mathf.Abs(lowerorigin.x) - 1));
            lowerleft.y = Mathf.Sign(lowerorigin.y) * ((Mathf.Abs(lowerorigin.y) - 1 < 0) ? (-2) : (Mathf.Abs(lowerorigin.y) - 1));
            lowerleft.z = Mathf.Sign(lowerorigin.z) * ((Mathf.Abs(lowerorigin.z) - 1 < 0) ? (Mathf.Sign(lowerorigin.z) * 2) : (Mathf.Abs(lowerorigin.z) - 1));
            // eg. P1(h,z,l)

            lowerright.x = Mathf.Sign(lowerorigin.x) * ((Mathf.Abs(lowerleft.x) - 1 < 0) ? (2) : (Mathf.Abs(lowerleft.x) - 1));
            lowerright.y = Mathf.Sign(lowerleft.y) * ((Mathf.Abs(lowerleft.y) - 1 < 0) ? (-2) : (Mathf.Abs(lowerleft.y) - 1));
            lowerright.z = Mathf.Sign(lowerorigin.z) * ((Mathf.Abs(lowerleft.z) - 1 < 0) ? (Mathf.Sign(lowerorigin.z) * 2) : (Mathf.Abs(lowerleft.z) - 1));

            Convert2ToPhi(ref lowerorigin); Convert2ToPhi(ref lowerleft); Convert2ToPhi(ref lowerright);

            PointTriplets.Add(lowerorigin);
            PointTriplets.Add(lowerleft);
            PointTriplets.Add(lowerright);

            // begin upper triangles
            // this triangle points up.
            upperorigin = new Vector3(set[i].x, set[i].y, set[i].z);

            // these calculations are chained, and thus don't do well in their own functions.
            // high to low, low to zero, zero to high [upper fork]
            upperleft.x = Mathf.Sign(upperorigin.x) * ((Mathf.Abs(upperorigin.x) - 1 < 0) ? (Mathf.Sign(upperorigin.x) * 2) : (Mathf.Abs(upperorigin.x) - 1));
            upperleft.y = Mathf.Sign(upperorigin.y) * ((Mathf.Abs(upperorigin.y) - 1 < 0) ? (2) : (Mathf.Abs(upperorigin.y) - 1));
            upperleft.z = Mathf.Sign(upperorigin.z) * ((Mathf.Abs(upperorigin.z) - 1 < 0) ? (Mathf.Sign(upperorigin.z) * 2) : (Mathf.Abs(upperorigin.z) - 1));
            // eg. P1(h,z,l)

            upperright.x = Mathf.Sign(upperorigin.x) * ((Mathf.Abs(upperleft.x) - 1 < 0) ? (2) : (Mathf.Abs(upperleft.x) - 1));
            upperright.y = Mathf.Sign(upperleft.y) * ((Mathf.Abs(upperleft.y) - 1 < 0) ? (2) : (Mathf.Abs(upperleft.y) - 1));
            upperright.z = Mathf.Sign(upperorigin.z) * ((Mathf.Abs(upperleft.z) - 1 < 0) ? (Mathf.Sign(upperorigin.z) * 2) : (Mathf.Abs(upperleft.z) - 1));

            Convert2ToPhi(ref upperorigin); Convert2ToPhi(ref upperleft); Convert2ToPhi(ref upperright);

            PointTriplets.Add(upperorigin);
            PointTriplets.Add(upperright);
            PointTriplets.Add(upperleft);
        }

        /*
         * END OF POINTS ON UNIQUE RECTANGLES ALGORITHM
         */

        /*
         * BEGIN PAIRED POINTS ALGORITHM
         */
        set = new Vector3[12] {
            new Vector3(1, 0, 2), new Vector3(1, 0, -2), new Vector3(-1, 0, -2), new Vector3(-1, 0, 2),
            new Vector3(2, 1, 0), new Vector3(-2, 1, 0), new Vector3(-2, -1, 0), new Vector3(2, -1, 0),
            new Vector3(0, 2, 1), new Vector3(0, -2, 1), new Vector3(0, -2, -1), new Vector3(0, 2, -1)
        };

        Vector3 origin = Vector3.zero, leftpoint = Vector3.zero, rightpoint = Vector3.zero;

        for (int i = 0; i < set.Length; i++)
        {
            origin     = new Vector3(set[i].x, set[i].y, set[i].z);
            leftpoint  = PairedPoint(origin, true);
            rightpoint = PairedPoint(origin, false);

            Convert2ToPhi(ref origin); Convert2ToPhi(ref leftpoint); Convert2ToPhi(ref rightpoint);

            PointTriplets.Add(origin);
            PointTriplets.Add(leftpoint);
            PointTriplets.Add(rightpoint);
        }


        // prepare tesselation verts for each point triplets.
        for (int i = 0; i < PointTriplets.Count / 3; i++)
        {
            origin     = PointTriplets[i * 3];
            leftpoint  = PointTriplets[i * 3 + 1];
            rightpoint = PointTriplets[i * 3 + 2];

            Vector3 leftstep  = (leftpoint - origin) / DetailLevel;
            Vector3 rightstep = (rightpoint - origin) / DetailLevel;


            bool    oddTriangle = false; // odd triangles are upside down.
            Vector3 myOrigin, leftfoot, rightfoot, temp;
            bool    faceValue;
            for (int row = 0; row < DetailLevel; row++)
            {
                myOrigin  = origin + row * leftstep;
                leftfoot  = myOrigin + leftstep;
                rightfoot = myOrigin + rightstep;

                // determine clockwise order for tri.
                // honestly, no idea how I came to this.
                faceValue = (Mathf.Sign(origin.x) * Mathf.Sign(origin.z) == ((origin.y != 0) ? (Mathf.Sign(origin.y)) : (1)));

                for (int n = 0; n < 1 + 2 * row; n++)
                {
                    // Debug.Log("triangle #" + (n + 1) + " m: " + myOrigin + " l: " + leftfoot + " r:" + rightfoot);
                    index = verts.Count;
                    verts.Add(myOrigin);
                    verts.Add(leftfoot);
                    verts.Add(rightfoot);

                    // Wizard shit. Seriously. No idea. It just works.
                    if (!faceValue)
                    {
                        tris.Add(index); tris.Add(index + 2); tris.Add(index + 1);
                    }
                    else
                    {
                        tris.Add(index); tris.Add(index + 1); tris.Add(index + 2);
                    }

                    if (oddTriangle)
                    {
                        temp      = myOrigin;
                        myOrigin  = leftfoot;
                        leftfoot  = temp;
                        rightfoot = myOrigin + rightstep;
                    }
                    else
                    {
                        temp      = myOrigin;
                        myOrigin  = rightfoot;
                        leftfoot  = myOrigin - leftstep;
                        rightfoot = temp;
                    }

                    oddTriangle = !oddTriangle;
                }

                oddTriangle = false;
            }
        }



        // apply proper scaling.
        for (int i = 0; i < verts.Count; i++)
        {
            Vector3 temp = verts[i];
            // temp = (PhiDistanceConstant / temp.magnitude) * temp; // sets all points to the phyDistanceConstant.
            temp *= (SphereRadius / temp.magnitude); // sets all points to sphere radius.

            verts[i] = temp;
        }

        // export final verts, tris and uvs to mesh and wrap it up.

        ThreadedSimpleMesh newMesh = new ThreadedSimpleMesh();

        // prepare uvs based on position
        for (int n = 0; n < verts.Count; n++)
        {
            Vector3 vert = verts[n].normalized;
            Vector2 uv   = Vector2.zero;

            uv.x = ((Mathf.Atan2(vert.x, vert.z) / (Mathf.PI)));
            uv.x = (uv.x + 1f) / 2f;

            uv.y = Mathf.Acos(vert.y) / Mathf.PI;


            uvs.Add(uv);
        }

        // solve the atan seam problem.
        // crossing over the x axis, seems to produce one negative, one positive.
        // this results in an ugly band where the texture repeats.
        for (int n = 0; n < uvs.Count / 3; n++)
        {
            // if two of the uv.x disagree...
            if (Mathf.Abs(uvs[3 * n].x - uvs[3 * n + 1].x) > 0.5f ||
                Mathf.Abs(uvs[3 * n].x - uvs[3 * n + 2].x) > 0.5f ||
                Mathf.Abs(uvs[3 * n + 1].x - uvs[3 * n + 2].x) > 0.5f)
            {
                // we crossed streams.

                // how many are far?
                int far = 0;
                if (uvs[3 * n].x > 0.5f)
                {
                    far++;
                }
                if (uvs[3 * n + 1].x > 0.5f)
                {
                    far++;
                }
                if (uvs[3 * n + 2].x > 0.5f)
                {
                    far++;
                }

                // then fix the one that is wrong.
                if (far == 2)
                {
                    for (int m = 0; m < 3; m++)
                    {
                        if (uvs[3 * n + m].x < 0.5f)
                        {
                            Vector2 uv = uvs[3 * n + m];
                            uv.x          += 1f;
                            uvs[3 * n + m] = uv;
                            break;
                        }
                    }
                }
                else
                {
                    for (int m = 0; m < 3; m++)
                    {
                        if (uvs[3 * n + m].x > 0.5f)
                        {
                            Vector2 uv = uvs[3 * n + m];
                            uv.x          -= 1f;
                            uvs[3 * n + m] = uv;
                            break;
                        }
                    }
                }
            }
        }

        newMesh.SetVertices(verts);
        newMesh.SetTriangles(tris, 0);
        newMesh.SetUVs(0, uvs);

        // newMesh.RecalculateBounds();
        // newMesh.RecalculateNormals();

        ThreadRunner.ExportData(newMesh);
        ThreadRunner.MarkComplete();
    }
Пример #3
0
    // returns null, if no path found.
    // returns a list of Vector3s
    public IEnumerator FindPath(Vector3 entry, Vector3 exit, float tolerance = 5f)
    {
        float          realtime  = Time.realtimeSinceStartup;
        float          totaltime = 0f;
        List <Vector3> retList   = new List <Vector3>();

        // find nearest node
        ThreadedNavNode start = FindClosestNode(entry);
        ThreadedNavNode end   = FindClosestNode(exit);

        if (((start.getOrigin() - entry).magnitude > tolerance) || (end.getOrigin() - exit).magnitude > tolerance)
        {
            //Debug.Log("Could not find nodes for entry or exit.");
            yield break;  // return null;
        }

        // if (start == end) { return new List<Vector3>(); }
        if (start == end)
        {
            yield break;
        }

        PriorityQueue <ThreadedNavNode>     queue = new PriorityQueue <ThreadedNavNode>();
        Dictionary <ThreadedNavNode, float> costs = new Dictionary <ThreadedNavNode, float>();
        List <ThreadedNavNode> visited            = new List <ThreadedNavNode>();

        ThreadedNavNode prev    = start;
        ThreadedNavNode current = start;

        bool  solved   = false;
        float priority = 0f;

        queue.Add(start, 0f); // begin with the origin node
        costs.Add(start, 0f); //

        while (queue.Count > 0)
        {
            current  = queue.Get(0);
            priority = queue.GetPriority(0);
            queue.RemoveAt(0);

            if (visited.Contains(current))
            {
                continue;
            }
            visited.Add(current);


            List <WeightedThreadedNavNodeExit> exits = current.accessExits();
            int count = exits.Count;

            if (count < 4)
            {
                //Debug.Log("short exits");
                Debug.DrawRay(current.getOrigin(), 10f * Vector3.up, Color.red, 0.5f);
            }

            for (int i = 0; i < count; i++)
            {
                // calculate heuristic for each node and add to the queue
                // heuristic is cost + expected

                float h = (exits[i].exit.getOrigin() - end.getOrigin()).magnitude;


                if (!costs.ContainsKey(exits[i].exit))
                {
                    // we have never been here before.
                    costs.Add(exits[i].exit, costs[current] + exits[i].weight);
                    // now add it to the queue

                    queue.Add(exits[i].exit, h + costs[exits[i].exit]);
                    Debug.DrawLine(exits[i].exit.getOrigin(), current.getOrigin(), Color.green, 0.5f);
                }
                else if (costs[current] + exits[i].weight < costs[exits[i].exit])
                {
                    // we have found a shorter path to this location
                    costs[exits[i].exit] = costs[current] + exits[i].weight;
                    // so add it to the queue again
                    queue.Add(exits[i].exit, h + costs[exits[i].exit]);
                    Debug.DrawLine(exits[i].exit.getOrigin(), current.getOrigin(), Color.green, 0.5f);
                }
                else
                {
                    Debug.DrawLine(exits[i].exit.getOrigin(), current.getOrigin(), Color.red, 0.5f);
                }
            }

            if (current == end)
            {
                solved = true;
                break; // solved.
            }

            if (Time.realtimeSinceStartup - realtime > m_ScanDeltaMax)
            {
                realtime = Time.realtimeSinceStartup;
                yield return(null);
            }
        }

        if (!solved)
        {
            Debug.Log("[PATHER] Path finding failed.");
            yield break; // return null;
        }

        // then we reconstruct the path
        current  = end;
        priority = Mathf.Infinity;
        prev     = null; // temp


        while (current != start)
        {
            if (current == null)
            {
                break;
            }
            priority = Mathf.Infinity;
            retList.Add(current.getOrigin());
            prev = null;

            for (int i = 0; i < current.accessExits().Count; i++)
            {
                //Debug.Log("checking: " + current.accessExits()[i].exit.getOrigin());
                if (!costs.ContainsKey(current.accessExits()[i].exit))
                {
                }
                else if (costs[current.accessExits()[i].exit] < priority)
                {
                    priority = costs[current.accessExits()[i].exit];
                    prev     = current.accessExits()[i].exit;
                }
            }

            //Debug.Log(current.getOrigin() + " - " + priority);

            current = prev;
            if (Time.realtimeSinceStartup - realtime > m_ScanDeltaMax)
            {
                realtime = Time.realtimeSinceStartup; yield return(null);
            }
        }
        retList.Add(start.getOrigin());

        for (int i = 0; i < retList.Count - 1; i++)
        {
            Debug.DrawLine(retList[i], retList[i + 1], Color.magenta, 5f);
        }

        ThreadRunner.ExportData(retList);

        yield return(null); // return retList;
    }
Пример #4
0
    void ThreadedSphere(object d)
    {
        int DetailLevel = SphereDetail;

        if (DetailLevel < 1)
        {
            DetailLevel = 1;
        }

        List <Vector3> verts = new List <Vector3>();
        List <Vector2> uvs   = new List <Vector2>();
        List <int>     tris  = new List <int>();
        int            index = 0;

        Vector2 uvstep = new Vector2(1.0f / UVTileDimensions.x, 1.0f / UVTileDimensions.y);


        List <Vector3> PointTriplets = new List <Vector3>();

        // phi = (1 + root(5)) / 2 = 1.6180339887498948482045868343656
        float high = (1f + Mathf.Sqrt(5)) / 2f;
        float low  = 1.0f;
        float zero = 0.0f;

        float[] settings = new float[3] {
            zero, low, high
        };
        // generate the main points
        // z is forward. So...I don't know.

        // 0, +-1, +- phi



        // using detail level, produce loops for faces.

        /*
         * POINTS ON UNIQUE RECTANGLES
         * We take any point.
         * eg. P1(h,z,l)
         * We fork, raising z to high in both positive and negative.
         * Low axis goes to zero.
         * High axis goes to low.
         * eg. P2a(l,+h,z)  P2b(1,-h, z)
         * Low goes to zero.
         * eg. P3a(z,+l,h)   P3b(z,-l,h)
         */
        // we should take the y = 0 rectangle, and generate the 8 faces from it's 4 points
        Vector3[] set = new Vector3[4] {
            new Vector3(1, 0, 2),
            new Vector3(1, 0, -2),
            new Vector3(-1, 0, -2),
            new Vector3(-1, 0, 2)
        };


        Vector3 upperorigin = Vector3.zero, upperleft = Vector3.zero, upperright = Vector3.zero, lowerorigin = Vector3.zero, lowerleft = Vector3.zero, lowerright = Vector3.zero;


        int     tileIndex = 0;
        Vector2 uv_origin = Vector2.zero;

        for (int i = 0; i < 4; i++)
        {
            // do lower y triangle first.
            // this triangle points up.
            lowerorigin = new Vector3(set[i].x, set[i].y, set[i].z);
            // high to low, low to zero, zero to high [lower fork]
            lowerleft.x = Mathf.Sign(lowerorigin.x) * ((Mathf.Abs(lowerorigin.x) - 1 < 0) ? (Mathf.Sign(lowerorigin.x) * 2) : (Mathf.Abs(lowerorigin.x) - 1));
            lowerleft.y = Mathf.Sign(lowerorigin.y) * ((Mathf.Abs(lowerorigin.y) - 1 < 0) ? (-2) : (Mathf.Abs(lowerorigin.y) - 1));
            lowerleft.z = Mathf.Sign(lowerorigin.z) * ((Mathf.Abs(lowerorigin.z) - 1 < 0) ? (Mathf.Sign(lowerorigin.z) * 2) : (Mathf.Abs(lowerorigin.z) - 1));
            // eg. P1(h,z,l)

            lowerright.x = Mathf.Sign(lowerorigin.x) * ((Mathf.Abs(lowerleft.x) - 1 < 0) ? (2) : (Mathf.Abs(lowerleft.x) - 1));
            lowerright.y = Mathf.Sign(lowerleft.y) * ((Mathf.Abs(lowerleft.y) - 1 < 0) ? (-2) : (Mathf.Abs(lowerleft.y) - 1));
            lowerright.z = Mathf.Sign(lowerorigin.z) * ((Mathf.Abs(lowerleft.z) - 1 < 0) ? (Mathf.Sign(lowerorigin.z) * 2) : (Mathf.Abs(lowerleft.z) - 1));

            Convert2ToPhi(ref lowerorigin); Convert2ToPhi(ref lowerleft); Convert2ToPhi(ref lowerright);

            PointTriplets.Add(lowerorigin);
            PointTriplets.Add(lowerleft);
            PointTriplets.Add(lowerright);

            // begin upper triangles
            // this triangle points up.
            upperorigin = new Vector3(set[i].x, set[i].y, set[i].z);

            // these calculations are chained, and thus don't do well in their own functions.
            // high to low, low to zero, zero to high [upper fork]
            upperleft.x = Mathf.Sign(upperorigin.x) * ((Mathf.Abs(upperorigin.x) - 1 < 0) ? (Mathf.Sign(upperorigin.x) * 2) : (Mathf.Abs(upperorigin.x) - 1));
            upperleft.y = Mathf.Sign(upperorigin.y) * ((Mathf.Abs(upperorigin.y) - 1 < 0) ? (2) : (Mathf.Abs(upperorigin.y) - 1));
            upperleft.z = Mathf.Sign(upperorigin.z) * ((Mathf.Abs(upperorigin.z) - 1 < 0) ? (Mathf.Sign(upperorigin.z) * 2) : (Mathf.Abs(upperorigin.z) - 1));
            // eg. P1(h,z,l)

            upperright.x = Mathf.Sign(upperorigin.x) * ((Mathf.Abs(upperleft.x) - 1 < 0) ? (2) : (Mathf.Abs(upperleft.x) - 1));
            upperright.y = Mathf.Sign(upperleft.y) * ((Mathf.Abs(upperleft.y) - 1 < 0) ? (2) : (Mathf.Abs(upperleft.y) - 1));
            upperright.z = Mathf.Sign(upperorigin.z) * ((Mathf.Abs(upperleft.z) - 1 < 0) ? (Mathf.Sign(upperorigin.z) * 2) : (Mathf.Abs(upperleft.z) - 1));

            Convert2ToPhi(ref upperorigin); Convert2ToPhi(ref upperleft); Convert2ToPhi(ref upperright);

            PointTriplets.Add(upperorigin);
            PointTriplets.Add(upperright);
            PointTriplets.Add(upperleft);
        }

        /*
         * END OF POINTS ON UNIQUE RECTANGLES ALGORITHM
         */

        /*
         * BEGIN PAIRED POINTS ALGORITHM
         */
        set = new Vector3[12] {
            new Vector3(1, 0, 2), new Vector3(1, 0, -2), new Vector3(-1, 0, -2), new Vector3(-1, 0, 2),             // this is right
            new Vector3(2, 1, 0), new Vector3(-2, 1, 0), new Vector3(-2, -1, 0), new Vector3(2, -1, 0),
            new Vector3(0, 2, 1), new Vector3(0, -2, 1), new Vector3(0, -2, -1), new Vector3(0, 2, -1)
        };

        Vector3 origin = Vector3.zero, leftpoint = Vector3.zero, rightpoint = Vector3.zero;

        for (int i = 0; i < set.Length; i++)
        {
            origin     = new Vector3(set[i].x, set[i].y, set[i].z);
            leftpoint  = PairedPoint(origin, true);
            rightpoint = PairedPoint(origin, false);

            Convert2ToPhi(ref origin); Convert2ToPhi(ref leftpoint); Convert2ToPhi(ref rightpoint);

            PointTriplets.Add(origin);
            PointTriplets.Add(leftpoint);
            PointTriplets.Add(rightpoint);
        }

        for (int i = 0; i < PointTriplets.Count / 3; i++)
        {
            //  TEXTURE CONTROL
            tileIndex = i;
            uv_origin = new Vector2(uvstep.x * (tileIndex % UVTileDimensions.x), 1.0f - uvstep.y * (1 + Mathf.Floor(tileIndex / UVTileDimensions.x)));

            origin     = PointTriplets[i * 3];
            leftpoint  = PointTriplets[i * 3 + 1];
            rightpoint = PointTriplets[i * 3 + 2];

            Vector3 leftstep  = (leftpoint - origin) / DetailLevel;
            Vector3 rightstep = (rightpoint - origin) / DetailLevel;

            //  END TEXTURE CONTROL

            bool    oddTriangle = false; // odd triangles are upside down.
            Vector3 myOrigin, leftfoot, rightfoot, temp;
            bool    faceValue;
            for (int row = 0; row < DetailLevel; row++)
            {
                myOrigin  = origin + row * leftstep;
                leftfoot  = myOrigin + leftstep;
                rightfoot = myOrigin + rightstep;

                // wizard shit. No idea.
                faceValue = (Mathf.Sign(origin.x) * Mathf.Sign(origin.z) == ((origin.y != 0) ? (Mathf.Sign(origin.y)) : (1)));

                for (int n = 0; n < 1 + 2 * row; n++)
                {
                    // Debug.Log("triangle #" + (n + 1) + " m: " + myOrigin + " l: " + leftfoot + " r:" + rightfoot);
                    index = verts.Count;
                    verts.Add(myOrigin);
                    verts.Add(leftfoot);
                    verts.Add(rightfoot);

                    // Wizard shit. Seriously. No idea. It just works.
                    if (!faceValue)
                    {
                        tris.Add(index); tris.Add(index + 2); tris.Add(index + 1);
                    }
                    else
                    {
                        tris.Add(index); tris.Add(index + 1); tris.Add(index + 2);
                    }

                    if (oddTriangle)
                    {
                        temp      = myOrigin;
                        myOrigin  = leftfoot;
                        leftfoot  = temp;
                        rightfoot = myOrigin + rightstep;
                    }
                    else
                    {
                        temp      = myOrigin;
                        myOrigin  = rightfoot;
                        leftfoot  = myOrigin - leftstep;
                        rightfoot = temp;
                    }

                    uvs.Add(new Vector2(uv_origin.x + 0.5f * uvstep.x, uv_origin.y + uvstep.y));
                    if (tileIndex % 2 != 0)
                    {
                        uvs.Add(new Vector2(uv_origin.x + 0f, uv_origin.y + 0f));
                        uvs.Add(new Vector2(uv_origin.x + uvstep.x, uv_origin.y + 0f));
                    }
                    else
                    {
                        uvs.Add(new Vector2(uv_origin.x + uvstep.x, uv_origin.y + 0f));
                        uvs.Add(new Vector2(uv_origin.x + 0f, uv_origin.y + 0f));
                    }

                    oddTriangle = !oddTriangle;
                }

                oddTriangle = false;
            }
        }



        // apply proper scaling.
        for (int i = 0; i < verts.Count; i++)
        {
            Vector3 temp = verts[i];
            temp     = (PhiDistanceConstant / temp.magnitude) * temp; // sets all points to the phyDistanceConstant.
            temp     = (SphereRadius / PhiDistanceConstant) * temp;   // sets all points to sphere radius.
            verts[i] = temp;
        }

        // export final verts, tris and uvs to mesh and wrap it up.

        ThreadedSimpleMesh newMesh = new ThreadedSimpleMesh();

        newMesh.SetVertices(verts);
        newMesh.SetTriangles(tris, 0);
        newMesh.SetUVs(0, uvs);

        // newMesh.RecalculateBounds();
        // newMesh.RecalculateNormals();

        ThreadRunner.ExportData(newMesh);
        ThreadRunner.MarkComplete();
    }