public static int StringPull(Vector3[] portals, int nportalPts, Vector3[] pts, int maxPts) { // Find straight path. int npts = 0; // Init scan state Vector3 portalApex = portals[0]; Vector3 portalLeft = portals[2]; Vector3 portalRight = portals[3]; int apexIndex = 0, leftIndex = 0, rightIndex = 0; // Add start point. pts[0] = portalApex; npts++; for (int i = 1; ((i < (nportalPts / 2)) && (npts < maxPts)); ++i) { Vector3 left = portals[i * 2 + 0]; Vector3 right = portals[i * 2 + 1]; // Update right vertex. if (TriArea2(portalApex, portalRight, right) <= 0.0f) { if (PathUtils.AreVertsTheSame(portalApex, portalRight) || TriArea2(portalApex, portalLeft, right) > 0.0f) { // Tighten the funnel. portalRight = right; rightIndex = i; } else { // Right over left, insert left to path and restart scan from portal left point. pts[npts] = portalLeft; npts++; // Make current left the new apex. portalApex = portalLeft; apexIndex = leftIndex; // Reset portal portalLeft = portalApex; portalRight = portalApex; leftIndex = apexIndex; rightIndex = apexIndex; // Restart scan i = apexIndex; continue; } } // Update left vertex. if (TriArea2(portalApex, portalLeft, left) >= 0.0f) { if (PathUtils.AreVertsTheSame(portalApex, portalLeft) || TriArea2(portalApex, portalRight, left) < 0.0f) { // Tighten the funnel. portalLeft = left; leftIndex = i; } else { // Left over right, insert right to path and restart scan from portal right point. pts[npts] = portalRight; npts++; // Make current right the new apex. portalApex = portalRight; apexIndex = rightIndex; // Reset portal portalLeft = portalApex; portalRight = portalApex; leftIndex = apexIndex; rightIndex = apexIndex; // Restart scan i = apexIndex; continue; } } } // Append last point to path. if (npts < maxPts) { pts[npts] = portals[nportalPts - 1]; npts++; } return(npts); }