public static int stbtt__solve_cubic(float a, float b, float c, float *r) { float s = -a / 3; float p = b - a * a / 3; float q = a * (2 * a * a - 9 * b) / 27 + c; float p3 = p * p * p; float d = q * q + 4 * p3 / 27; if ((d) >= (0)) { float z = (float)(CRuntime.Sqrt(d)); float u = (-q + z) / 2; float v = (-q - z) / 2; u = stbtt__cuberoot(u); v = stbtt__cuberoot(v); r[0] = s + u + v; return(1); } else { float u = (float)(CRuntime.Sqrt(-p / 3)); float v = (float)(CRuntime.Acos(-CRuntime.Sqrt(-27 / p3) * q / 2)) / 3; float m = (float)(CRuntime.Cos(v)); float n = (float)(CRuntime.Cos(v - 3.141592 / 2)) * 1.732050808f; r[0] = s + u * 2 * m; r[1] = s - u * (m + n); r[2] = s - u * (m - n); return(3); } }
public static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) { float dx0 = x1 - x0; float dy0 = y1 - y0; float dx1 = x2 - x1; float dy1 = y2 - y1; float dx2 = x3 - x2; float dy2 = y3 - y2; float dx = x3 - x0; float dy = y3 - y0; float longlen = (float)(CRuntime.Sqrt(dx0 * dx0 + dy0 * dy0) + CRuntime.Sqrt(dx1 * dx1 + dy1 * dy1) + CRuntime.Sqrt(dx2 * dx2 + dy2 * dy2)); float shortlen = (float)(CRuntime.Sqrt(dx * dx + dy * dy)); float flatness_squared = longlen * longlen - shortlen * shortlen; if ((n) > (16)) { return; } if ((flatness_squared) > (objspace_flatness_squared)) { float x01 = (x0 + x1) / 2; float y01 = (y0 + y1) / 2; float x12 = (x1 + x2) / 2; float y12 = (y1 + y2) / 2; float x23 = (x2 + x3) / 2; float y23 = (y2 + y3) / 2; float xa = (x01 + x12) / 2; float ya = (y01 + y12) / 2; float xb = (x12 + x23) / 2; float yb = (y12 + y23) / 2; float mx = (xa + xb) / 2; float my = (ya + yb) / 2; stbtt__tesselate_cubic(points, num_points, x0, y0, x01, y01, xa, ya, mx, my, objspace_flatness_squared, n + 1); stbtt__tesselate_cubic(points, num_points, mx, my, xb, yb, x23, y23, x3, y3, objspace_flatness_squared, n + 1); } else { stbtt__add_point(points, *num_points, x3, y3); *num_points = *num_points + 1; } }
public static int stbtt__ray_intersect_bezier(float *orig, float *ray, float *q0, float *q1, float *q2, float *hits) { float q0perp = q0[1] * ray[0] - q0[0] * ray[1]; float q1perp = q1[1] * ray[0] - q1[0] * ray[1]; float q2perp = q2[1] * ray[0] - q2[0] * ray[1]; float roperp = orig[1] * ray[0] - orig[0] * ray[1]; float a = q0perp - 2 * q1perp + q2perp; float b = q1perp - q0perp; float c = q0perp - roperp; float s0 = 0; float s1 = 0; int num_s = 0; if (a != 0.0) { float discr = b * b - a * c; if ((discr) > (0.0)) { float rcpna = -1 / a; float d = (float)(CRuntime.Sqrt(discr)); s0 = (b + d) * rcpna; s1 = (b - d) * rcpna; if (((s0) >= (0.0)) && (s0 <= 1.0)) { num_s = 1; } if ((((d) > (0.0)) && ((s1) >= (0.0))) && (s1 <= 1.0)) { if ((num_s) == (0)) { s0 = s1; } ++num_s; } } } else { s0 = c / (-2 * b); if (((s0) >= (0.0)) && (s0 <= 1.0)) { num_s = 1; } } if ((num_s) == (0)) { return(0); } else { float rcp_len2 = 1 / (ray[0] * ray[0] + ray[1] * ray[1]); float rayn_x = ray[0] * rcp_len2; float rayn_y = ray[1] * rcp_len2; float q0d = q0[0] * rayn_x + q0[1] * rayn_y; float q1d = q1[0] * rayn_x + q1[1] * rayn_y; float q2d = q2[0] * rayn_x + q2[1] * rayn_y; float rod = orig[0] * rayn_x + orig[1] * rayn_y; float q10d = q1d - q0d; float q20d = q2d - q0d; float q0rd = q0d - rod; hits[0] = q0rd + s0 * (2.0f - 2.0f * s0) * q10d + s0 * s0 * q20d; hits[1] = a * s0 + b; if ((num_s) > (1)) { hits[2] = q0rd + s1 * (2.0f - 2.0f * s1) * q10d + s1 * s1 * q20d; hits[3] = a * s1 + b; return(2); } else { return(1); } } }