/*! SLCurveBezier::subdivideRender adds points along the curve to the point vector renderPoints by recursively subdividing the curve with the Casteljau scheme. */ void SLCurveBezier::subdivideRender(SLVVec3f &renderPoints, const SLMat4f &wm, SLfloat epsilon, const SLVec3f& P0, const SLVec3f& P1, const SLVec3f& P2, const SLVec3f& P3) { // add first point transformed by wm if not already in the list if (renderPoints.size()==0) renderPoints.push_back(wm.multVec(P0)); else if (P0 != renderPoints[renderPoints.size()-1]) renderPoints.push_back(wm.multVec(P0)); // check to see if basically straight SLfloat Lmin = P0.distance(P3); SLfloat Lmax = P0.distance(P1) + P1.distance(P2) + P2.distance(P3); SLfloat diff = Lmin - Lmax; if (diff*diff < epsilon) return; // otherwise get control points for subdivision SLVec3f L1 = (P0 + P1) * 0.5f; SLVec3f H = (P1 + P2) * 0.5f; SLVec3f L2 = (L1 + H) * 0.5f; SLVec3f R2 = (P2 + P3) * 0.5f; SLVec3f R1 = (H + R2) * 0.5f; SLVec3f mid = (L2 + R1) * 0.5f; // subdivide subdivideRender(renderPoints, wm, epsilon, P0, L1, L2, mid); subdivideRender(renderPoints, wm, epsilon, mid, R1, R2, P3); }
/*! SLCurveBezier::subdivideLength calculates length of Bezier curve by recursive midpoint subdivision. */ SLfloat SLCurveBezier::subdivideLength(const SLVec3f& P0, const SLVec3f& P1, const SLVec3f& P2, const SLVec3f& P3) { // check to see if basically straight SLfloat Lmin = P0.distance(P3); SLfloat Lmax = P0.distance(P1) + P1.distance(P2) + P2.distance(P3); SLfloat diff = Lmin - Lmax; if (diff*diff < 1.0e-3f) return 0.5f*(Lmin + Lmax); // otherwise get control points for subdivision SLVec3f L1 = (P0 + P1) * 0.5f; SLVec3f H = (P1 + P2) * 0.5f; SLVec3f L2 = (L1 + H ) * 0.5f; SLVec3f R2 = (P2 + P3) * 0.5f; SLVec3f R1 = (H + R2) * 0.5f; SLVec3f mid = (L2 + R1) * 0.5f; // subdivide return subdivideLength(P0, L1, L2, mid) + subdivideLength(mid, R1, R2, P3); }