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); }
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(); }
// 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; }
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(); }