void bezier_interpolate( float t, vec3 a0, vec3 a1, vec3 a2, vec3 a3, out vec3 point, #ifdef USE_CURVE_ROTATION out vec3 acceleration, #endif out vec3 tangent ) { float t2 = t * t; float m_t = 1. - t; float m_t2 = m_t * m_t; vec4 kt = vec4(m_t2 * m_t, 3. * t * m_t2, 3. * t2 * m_t, t2 * t); vec3 dt = vec3(3. * m_t2, 6. * t * m_t, 3. * t2); #ifdef USE_CURVE_ROTATION vec4 ddt = vec4(6. * m_t, 18. * t - 12., 6. - 18. * t, 6. * t); acceleration = ddt.x * a0 + ddt.y * a1 + ddt.z * a2 + ddt.w * a3; #endif point = kt.x * a0 + kt.y * a1 + kt.z * a2 + kt.w * a3; tangent = dt.x * (a1 - a0) + dt.y * (a2 - a1) + dt.z * (a3 - a2); } void transform(inout vec3 vertex, inout vec3 normal, vec3 a0, vec3 a1, vec3 a2, vec3 a3, float mn, float mx) { vec3 offset = vec3(0., mn, 0.); float t = (vertex.y - mn) / (mx - mn); vec3 point, #ifdef USE_CURVE_ROTATION acceleration, #endif tangent; bezier_interpolate( #ifdef USE_CURVE_ROTATION 0., #else t, #endif a0, a1, a2, a3, point, #ifdef USE_CURVE_ROTATION acceleration, #endif tangent); vec3 a = normalize(tangent); #ifdef USE_CURVE_ROTATION vec3 b = normalize(a + acceleration); vec3 r = normalize(cross(b, a)); if (length(r) < 0.00001) { r = vec3(0., 0., 1.); } #else vec3 r = vec3(0., 0., 1.); #endif vec3 n = normalize(cross(a, r)); #ifndef USE_CURVE_ROTATION r = normalize(cross(n, a)); #else if(t > 0.) { vec3 n_p, n_t, n_a; bezier_interpolate(t, a0, a1, a2, a3, n_p, n_a, n_t); vec3 v1 = n_p - a0; float c1 = dot(v1, v1); float inv_c1 = 2. / c1; vec3 cv1 = v1 * inv_c1; vec3 riL = r - cv1 * dot(v1, r); vec3 tiL = tangent - cv1 * dot(v1, tangent); vec3 v2 = n_t - tiL; float c2 = dot(v2, v2); r = normalize(riL - v2 * (2. / c2) * dot(v2, riL)); n = normalize(cross(n_t, r)); a = normalize(n_t); point = n_p; } #endif vertex = point + n * vertex.x + r * vertex.z; normal = a * normal.y + n * normal.x + r * normal.z; }
or share this direct link: